##// END OF EJS Templates
commands: use a context manager for file I/O in debugdiscovery
Bryan O'Sullivan -
r27771:338c9d22 default
parent child Browse files
Show More
@@ -1,7051 +1,7047
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullhex, nullid, nullrev, short
8 from node import hex, bin, nullhex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb
16 import sshserver, hgweb
17 import extensions
17 import extensions
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod, copies
20 import dagparser, context, simplemerge, graphmod, copies
21 import random, operator
21 import random, operator
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 import ui as uimod
24 import ui as uimod
25 import streamclone
25 import streamclone
26 import commandserver
26 import commandserver
27
27
28 table = {}
28 table = {}
29
29
30 command = cmdutil.command(table)
30 command = cmdutil.command(table)
31
31
32 # Space delimited list of commands that don't require local repositories.
32 # Space delimited list of commands that don't require local repositories.
33 # This should be populated by passing norepo=True into the @command decorator.
33 # This should be populated by passing norepo=True into the @command decorator.
34 norepo = ''
34 norepo = ''
35 # Space delimited list of commands that optionally require local repositories.
35 # Space delimited list of commands that optionally require local repositories.
36 # This should be populated by passing optionalrepo=True into the @command
36 # This should be populated by passing optionalrepo=True into the @command
37 # decorator.
37 # decorator.
38 optionalrepo = ''
38 optionalrepo = ''
39 # Space delimited list of commands that will examine arguments looking for
39 # Space delimited list of commands that will examine arguments looking for
40 # a repository. This should be populated by passing inferrepo=True into the
40 # a repository. This should be populated by passing inferrepo=True into the
41 # @command decorator.
41 # @command decorator.
42 inferrepo = ''
42 inferrepo = ''
43
43
44 # label constants
44 # label constants
45 # until 3.5, bookmarks.current was the advertised name, not
45 # until 3.5, bookmarks.current was the advertised name, not
46 # bookmarks.active, so we must use both to avoid breaking old
46 # bookmarks.active, so we must use both to avoid breaking old
47 # custom styles
47 # custom styles
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
49
49
50 # common command options
50 # common command options
51
51
52 globalopts = [
52 globalopts = [
53 ('R', 'repository', '',
53 ('R', 'repository', '',
54 _('repository root directory or name of overlay bundle file'),
54 _('repository root directory or name of overlay bundle file'),
55 _('REPO')),
55 _('REPO')),
56 ('', 'cwd', '',
56 ('', 'cwd', '',
57 _('change working directory'), _('DIR')),
57 _('change working directory'), _('DIR')),
58 ('y', 'noninteractive', None,
58 ('y', 'noninteractive', None,
59 _('do not prompt, automatically pick the first choice for all prompts')),
59 _('do not prompt, automatically pick the first choice for all prompts')),
60 ('q', 'quiet', None, _('suppress output')),
60 ('q', 'quiet', None, _('suppress output')),
61 ('v', 'verbose', None, _('enable additional output')),
61 ('v', 'verbose', None, _('enable additional output')),
62 ('', 'config', [],
62 ('', 'config', [],
63 _('set/override config option (use \'section.name=value\')'),
63 _('set/override config option (use \'section.name=value\')'),
64 _('CONFIG')),
64 _('CONFIG')),
65 ('', 'debug', None, _('enable debugging output')),
65 ('', 'debug', None, _('enable debugging output')),
66 ('', 'debugger', None, _('start debugger')),
66 ('', 'debugger', None, _('start debugger')),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
68 _('ENCODE')),
68 _('ENCODE')),
69 ('', 'encodingmode', encoding.encodingmode,
69 ('', 'encodingmode', encoding.encodingmode,
70 _('set the charset encoding mode'), _('MODE')),
70 _('set the charset encoding mode'), _('MODE')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
72 ('', 'time', None, _('time how long the command takes')),
72 ('', 'time', None, _('time how long the command takes')),
73 ('', 'profile', None, _('print command execution profile')),
73 ('', 'profile', None, _('print command execution profile')),
74 ('', 'version', None, _('output version information and exit')),
74 ('', 'version', None, _('output version information and exit')),
75 ('h', 'help', None, _('display help and exit')),
75 ('h', 'help', None, _('display help and exit')),
76 ('', 'hidden', False, _('consider hidden changesets')),
76 ('', 'hidden', False, _('consider hidden changesets')),
77 ]
77 ]
78
78
79 dryrunopts = [('n', 'dry-run', None,
79 dryrunopts = [('n', 'dry-run', None,
80 _('do not perform actions, just print output'))]
80 _('do not perform actions, just print output'))]
81
81
82 remoteopts = [
82 remoteopts = [
83 ('e', 'ssh', '',
83 ('e', 'ssh', '',
84 _('specify ssh command to use'), _('CMD')),
84 _('specify ssh command to use'), _('CMD')),
85 ('', 'remotecmd', '',
85 ('', 'remotecmd', '',
86 _('specify hg command to run on the remote side'), _('CMD')),
86 _('specify hg command to run on the remote side'), _('CMD')),
87 ('', 'insecure', None,
87 ('', 'insecure', None,
88 _('do not verify server certificate (ignoring web.cacerts config)')),
88 _('do not verify server certificate (ignoring web.cacerts config)')),
89 ]
89 ]
90
90
91 walkopts = [
91 walkopts = [
92 ('I', 'include', [],
92 ('I', 'include', [],
93 _('include names matching the given patterns'), _('PATTERN')),
93 _('include names matching the given patterns'), _('PATTERN')),
94 ('X', 'exclude', [],
94 ('X', 'exclude', [],
95 _('exclude names matching the given patterns'), _('PATTERN')),
95 _('exclude names matching the given patterns'), _('PATTERN')),
96 ]
96 ]
97
97
98 commitopts = [
98 commitopts = [
99 ('m', 'message', '',
99 ('m', 'message', '',
100 _('use text as commit message'), _('TEXT')),
100 _('use text as commit message'), _('TEXT')),
101 ('l', 'logfile', '',
101 ('l', 'logfile', '',
102 _('read commit message from file'), _('FILE')),
102 _('read commit message from file'), _('FILE')),
103 ]
103 ]
104
104
105 commitopts2 = [
105 commitopts2 = [
106 ('d', 'date', '',
106 ('d', 'date', '',
107 _('record the specified date as commit date'), _('DATE')),
107 _('record the specified date as commit date'), _('DATE')),
108 ('u', 'user', '',
108 ('u', 'user', '',
109 _('record the specified user as committer'), _('USER')),
109 _('record the specified user as committer'), _('USER')),
110 ]
110 ]
111
111
112 # hidden for now
112 # hidden for now
113 formatteropts = [
113 formatteropts = [
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 templateopts = [
118 templateopts = [
119 ('', 'style', '',
119 ('', 'style', '',
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
121 ('T', 'template', '',
121 ('T', 'template', '',
122 _('display with template'), _('TEMPLATE')),
122 _('display with template'), _('TEMPLATE')),
123 ]
123 ]
124
124
125 logopts = [
125 logopts = [
126 ('p', 'patch', None, _('show patch')),
126 ('p', 'patch', None, _('show patch')),
127 ('g', 'git', None, _('use git extended diff format')),
127 ('g', 'git', None, _('use git extended diff format')),
128 ('l', 'limit', '',
128 ('l', 'limit', '',
129 _('limit number of changes displayed'), _('NUM')),
129 _('limit number of changes displayed'), _('NUM')),
130 ('M', 'no-merges', None, _('do not show merges')),
130 ('M', 'no-merges', None, _('do not show merges')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
132 ('G', 'graph', None, _("show the revision DAG")),
132 ('G', 'graph', None, _("show the revision DAG")),
133 ] + templateopts
133 ] + templateopts
134
134
135 diffopts = [
135 diffopts = [
136 ('a', 'text', None, _('treat all files as text')),
136 ('a', 'text', None, _('treat all files as text')),
137 ('g', 'git', None, _('use git extended diff format')),
137 ('g', 'git', None, _('use git extended diff format')),
138 ('', 'nodates', None, _('omit dates from diff headers'))
138 ('', 'nodates', None, _('omit dates from diff headers'))
139 ]
139 ]
140
140
141 diffwsopts = [
141 diffwsopts = [
142 ('w', 'ignore-all-space', None,
142 ('w', 'ignore-all-space', None,
143 _('ignore white space when comparing lines')),
143 _('ignore white space when comparing lines')),
144 ('b', 'ignore-space-change', None,
144 ('b', 'ignore-space-change', None,
145 _('ignore changes in the amount of white space')),
145 _('ignore changes in the amount of white space')),
146 ('B', 'ignore-blank-lines', None,
146 ('B', 'ignore-blank-lines', None,
147 _('ignore changes whose lines are all blank')),
147 _('ignore changes whose lines are all blank')),
148 ]
148 ]
149
149
150 diffopts2 = [
150 diffopts2 = [
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
152 ('p', 'show-function', None, _('show which function each change is in')),
152 ('p', 'show-function', None, _('show which function each change is in')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
154 ] + diffwsopts + [
154 ] + diffwsopts + [
155 ('U', 'unified', '',
155 ('U', 'unified', '',
156 _('number of lines of context to show'), _('NUM')),
156 _('number of lines of context to show'), _('NUM')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
159 ]
159 ]
160
160
161 mergetoolopts = [
161 mergetoolopts = [
162 ('t', 'tool', '', _('specify merge tool')),
162 ('t', 'tool', '', _('specify merge tool')),
163 ]
163 ]
164
164
165 similarityopts = [
165 similarityopts = [
166 ('s', 'similarity', '',
166 ('s', 'similarity', '',
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
168 ]
168 ]
169
169
170 subrepoopts = [
170 subrepoopts = [
171 ('S', 'subrepos', None,
171 ('S', 'subrepos', None,
172 _('recurse into subrepositories'))
172 _('recurse into subrepositories'))
173 ]
173 ]
174
174
175 debugrevlogopts = [
175 debugrevlogopts = [
176 ('c', 'changelog', False, _('open changelog')),
176 ('c', 'changelog', False, _('open changelog')),
177 ('m', 'manifest', False, _('open manifest')),
177 ('m', 'manifest', False, _('open manifest')),
178 ('', 'dir', False, _('open directory manifest')),
178 ('', 'dir', False, _('open directory manifest')),
179 ]
179 ]
180
180
181 # Commands start here, listed alphabetically
181 # Commands start here, listed alphabetically
182
182
183 @command('^add',
183 @command('^add',
184 walkopts + subrepoopts + dryrunopts,
184 walkopts + subrepoopts + dryrunopts,
185 _('[OPTION]... [FILE]...'),
185 _('[OPTION]... [FILE]...'),
186 inferrepo=True)
186 inferrepo=True)
187 def add(ui, repo, *pats, **opts):
187 def add(ui, repo, *pats, **opts):
188 """add the specified files on the next commit
188 """add the specified files on the next commit
189
189
190 Schedule files to be version controlled and added to the
190 Schedule files to be version controlled and added to the
191 repository.
191 repository.
192
192
193 The files will be added to the repository at the next commit. To
193 The files will be added to the repository at the next commit. To
194 undo an add before that, see :hg:`forget`.
194 undo an add before that, see :hg:`forget`.
195
195
196 If no names are given, add all files to the repository (except
196 If no names are given, add all files to the repository (except
197 files matching ``.hgignore``).
197 files matching ``.hgignore``).
198
198
199 .. container:: verbose
199 .. container:: verbose
200
200
201 Examples:
201 Examples:
202
202
203 - New (unknown) files are added
203 - New (unknown) files are added
204 automatically by :hg:`add`::
204 automatically by :hg:`add`::
205
205
206 $ ls
206 $ ls
207 foo.c
207 foo.c
208 $ hg status
208 $ hg status
209 ? foo.c
209 ? foo.c
210 $ hg add
210 $ hg add
211 adding foo.c
211 adding foo.c
212 $ hg status
212 $ hg status
213 A foo.c
213 A foo.c
214
214
215 - Specific files to be added can be specified::
215 - Specific files to be added can be specified::
216
216
217 $ ls
217 $ ls
218 bar.c foo.c
218 bar.c foo.c
219 $ hg status
219 $ hg status
220 ? bar.c
220 ? bar.c
221 ? foo.c
221 ? foo.c
222 $ hg add bar.c
222 $ hg add bar.c
223 $ hg status
223 $ hg status
224 A bar.c
224 A bar.c
225 ? foo.c
225 ? foo.c
226
226
227 Returns 0 if all files are successfully added.
227 Returns 0 if all files are successfully added.
228 """
228 """
229
229
230 m = scmutil.match(repo[None], pats, opts)
230 m = scmutil.match(repo[None], pats, opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
232 return rejected and 1 or 0
232 return rejected and 1 or 0
233
233
234 @command('addremove',
234 @command('addremove',
235 similarityopts + subrepoopts + walkopts + dryrunopts,
235 similarityopts + subrepoopts + walkopts + dryrunopts,
236 _('[OPTION]... [FILE]...'),
236 _('[OPTION]... [FILE]...'),
237 inferrepo=True)
237 inferrepo=True)
238 def addremove(ui, repo, *pats, **opts):
238 def addremove(ui, repo, *pats, **opts):
239 """add all new files, delete all missing files
239 """add all new files, delete all missing files
240
240
241 Add all new files and remove all missing files from the
241 Add all new files and remove all missing files from the
242 repository.
242 repository.
243
243
244 Unless names are given, new files are ignored if they match any of
244 Unless names are given, new files are ignored if they match any of
245 the patterns in ``.hgignore``. As with add, these changes take
245 the patterns in ``.hgignore``. As with add, these changes take
246 effect at the next commit.
246 effect at the next commit.
247
247
248 Use the -s/--similarity option to detect renamed files. This
248 Use the -s/--similarity option to detect renamed files. This
249 option takes a percentage between 0 (disabled) and 100 (files must
249 option takes a percentage between 0 (disabled) and 100 (files must
250 be identical) as its parameter. With a parameter greater than 0,
250 be identical) as its parameter. With a parameter greater than 0,
251 this compares every removed file with every added file and records
251 this compares every removed file with every added file and records
252 those similar enough as renames. Detecting renamed files this way
252 those similar enough as renames. Detecting renamed files this way
253 can be expensive. After using this option, :hg:`status -C` can be
253 can be expensive. After using this option, :hg:`status -C` can be
254 used to check which files were identified as moved or renamed. If
254 used to check which files were identified as moved or renamed. If
255 not specified, -s/--similarity defaults to 100 and only renames of
255 not specified, -s/--similarity defaults to 100 and only renames of
256 identical files are detected.
256 identical files are detected.
257
257
258 .. container:: verbose
258 .. container:: verbose
259
259
260 Examples:
260 Examples:
261
261
262 - A number of files (bar.c and foo.c) are new,
262 - A number of files (bar.c and foo.c) are new,
263 while foobar.c has been removed (without using :hg:`remove`)
263 while foobar.c has been removed (without using :hg:`remove`)
264 from the repository::
264 from the repository::
265
265
266 $ ls
266 $ ls
267 bar.c foo.c
267 bar.c foo.c
268 $ hg status
268 $ hg status
269 ! foobar.c
269 ! foobar.c
270 ? bar.c
270 ? bar.c
271 ? foo.c
271 ? foo.c
272 $ hg addremove
272 $ hg addremove
273 adding bar.c
273 adding bar.c
274 adding foo.c
274 adding foo.c
275 removing foobar.c
275 removing foobar.c
276 $ hg status
276 $ hg status
277 A bar.c
277 A bar.c
278 A foo.c
278 A foo.c
279 R foobar.c
279 R foobar.c
280
280
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
282 Afterwards, it was edited slightly::
282 Afterwards, it was edited slightly::
283
283
284 $ ls
284 $ ls
285 foo.c
285 foo.c
286 $ hg status
286 $ hg status
287 ! foobar.c
287 ! foobar.c
288 ? foo.c
288 ? foo.c
289 $ hg addremove --similarity 90
289 $ hg addremove --similarity 90
290 removing foobar.c
290 removing foobar.c
291 adding foo.c
291 adding foo.c
292 recording removal of foobar.c as rename to foo.c (94% similar)
292 recording removal of foobar.c as rename to foo.c (94% similar)
293 $ hg status -C
293 $ hg status -C
294 A foo.c
294 A foo.c
295 foobar.c
295 foobar.c
296 R foobar.c
296 R foobar.c
297
297
298 Returns 0 if all files are successfully added.
298 Returns 0 if all files are successfully added.
299 """
299 """
300 try:
300 try:
301 sim = float(opts.get('similarity') or 100)
301 sim = float(opts.get('similarity') or 100)
302 except ValueError:
302 except ValueError:
303 raise error.Abort(_('similarity must be a number'))
303 raise error.Abort(_('similarity must be a number'))
304 if sim < 0 or sim > 100:
304 if sim < 0 or sim > 100:
305 raise error.Abort(_('similarity must be between 0 and 100'))
305 raise error.Abort(_('similarity must be between 0 and 100'))
306 matcher = scmutil.match(repo[None], pats, opts)
306 matcher = scmutil.match(repo[None], pats, opts)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
308
308
309 @command('^annotate|blame',
309 @command('^annotate|blame',
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
311 ('', 'follow', None,
311 ('', 'follow', None,
312 _('follow copies/renames and list the filename (DEPRECATED)')),
312 _('follow copies/renames and list the filename (DEPRECATED)')),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
314 ('a', 'text', None, _('treat all files as text')),
314 ('a', 'text', None, _('treat all files as text')),
315 ('u', 'user', None, _('list the author (long with -v)')),
315 ('u', 'user', None, _('list the author (long with -v)')),
316 ('f', 'file', None, _('list the filename')),
316 ('f', 'file', None, _('list the filename')),
317 ('d', 'date', None, _('list the date (short with -q)')),
317 ('d', 'date', None, _('list the date (short with -q)')),
318 ('n', 'number', None, _('list the revision number (default)')),
318 ('n', 'number', None, _('list the revision number (default)')),
319 ('c', 'changeset', None, _('list the changeset')),
319 ('c', 'changeset', None, _('list the changeset')),
320 ('l', 'line-number', None, _('show line number at the first appearance'))
320 ('l', 'line-number', None, _('show line number at the first appearance'))
321 ] + diffwsopts + walkopts + formatteropts,
321 ] + diffwsopts + walkopts + formatteropts,
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
323 inferrepo=True)
323 inferrepo=True)
324 def annotate(ui, repo, *pats, **opts):
324 def annotate(ui, repo, *pats, **opts):
325 """show changeset information by line for each file
325 """show changeset information by line for each file
326
326
327 List changes in files, showing the revision id responsible for
327 List changes in files, showing the revision id responsible for
328 each line.
328 each line.
329
329
330 This command is useful for discovering when a change was made and
330 This command is useful for discovering when a change was made and
331 by whom.
331 by whom.
332
332
333 If you include --file, --user, or --date, the revision number is
333 If you include --file, --user, or --date, the revision number is
334 suppressed unless you also include --number.
334 suppressed unless you also include --number.
335
335
336 Without the -a/--text option, annotate will avoid processing files
336 Without the -a/--text option, annotate will avoid processing files
337 it detects as binary. With -a, annotate will annotate the file
337 it detects as binary. With -a, annotate will annotate the file
338 anyway, although the results will probably be neither useful
338 anyway, although the results will probably be neither useful
339 nor desirable.
339 nor desirable.
340
340
341 Returns 0 on success.
341 Returns 0 on success.
342 """
342 """
343 if not pats:
343 if not pats:
344 raise error.Abort(_('at least one filename or pattern is required'))
344 raise error.Abort(_('at least one filename or pattern is required'))
345
345
346 if opts.get('follow'):
346 if opts.get('follow'):
347 # --follow is deprecated and now just an alias for -f/--file
347 # --follow is deprecated and now just an alias for -f/--file
348 # to mimic the behavior of Mercurial before version 1.5
348 # to mimic the behavior of Mercurial before version 1.5
349 opts['file'] = True
349 opts['file'] = True
350
350
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
352
352
353 fm = ui.formatter('annotate', opts)
353 fm = ui.formatter('annotate', opts)
354 if ui.quiet:
354 if ui.quiet:
355 datefunc = util.shortdate
355 datefunc = util.shortdate
356 else:
356 else:
357 datefunc = util.datestr
357 datefunc = util.datestr
358 if ctx.rev() is None:
358 if ctx.rev() is None:
359 def hexfn(node):
359 def hexfn(node):
360 if node is None:
360 if node is None:
361 return None
361 return None
362 else:
362 else:
363 return fm.hexfunc(node)
363 return fm.hexfunc(node)
364 if opts.get('changeset'):
364 if opts.get('changeset'):
365 # omit "+" suffix which is appended to node hex
365 # omit "+" suffix which is appended to node hex
366 def formatrev(rev):
366 def formatrev(rev):
367 if rev is None:
367 if rev is None:
368 return '%d' % ctx.p1().rev()
368 return '%d' % ctx.p1().rev()
369 else:
369 else:
370 return '%d' % rev
370 return '%d' % rev
371 else:
371 else:
372 def formatrev(rev):
372 def formatrev(rev):
373 if rev is None:
373 if rev is None:
374 return '%d+' % ctx.p1().rev()
374 return '%d+' % ctx.p1().rev()
375 else:
375 else:
376 return '%d ' % rev
376 return '%d ' % rev
377 def formathex(hex):
377 def formathex(hex):
378 if hex is None:
378 if hex is None:
379 return '%s+' % fm.hexfunc(ctx.p1().node())
379 return '%s+' % fm.hexfunc(ctx.p1().node())
380 else:
380 else:
381 return '%s ' % hex
381 return '%s ' % hex
382 else:
382 else:
383 hexfn = fm.hexfunc
383 hexfn = fm.hexfunc
384 formatrev = formathex = str
384 formatrev = formathex = str
385
385
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
390 ('file', ' ', lambda x: x[0].path(), str),
390 ('file', ' ', lambda x: x[0].path(), str),
391 ('line_number', ':', lambda x: x[1], str),
391 ('line_number', ':', lambda x: x[1], str),
392 ]
392 ]
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
394
394
395 if (not opts.get('user') and not opts.get('changeset')
395 if (not opts.get('user') and not opts.get('changeset')
396 and not opts.get('date') and not opts.get('file')):
396 and not opts.get('date') and not opts.get('file')):
397 opts['number'] = True
397 opts['number'] = True
398
398
399 linenumber = opts.get('line_number') is not None
399 linenumber = opts.get('line_number') is not None
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
402
402
403 if fm:
403 if fm:
404 def makefunc(get, fmt):
404 def makefunc(get, fmt):
405 return get
405 return get
406 else:
406 else:
407 def makefunc(get, fmt):
407 def makefunc(get, fmt):
408 return lambda x: fmt(get(x))
408 return lambda x: fmt(get(x))
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
410 if opts.get(op)]
410 if opts.get(op)]
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
413 if opts.get(op))
413 if opts.get(op))
414
414
415 def bad(x, y):
415 def bad(x, y):
416 raise error.Abort("%s: %s" % (x, y))
416 raise error.Abort("%s: %s" % (x, y))
417
417
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
419
419
420 follow = not opts.get('no_follow')
420 follow = not opts.get('no_follow')
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
422 whitespace=True)
422 whitespace=True)
423 for abs in ctx.walk(m):
423 for abs in ctx.walk(m):
424 fctx = ctx[abs]
424 fctx = ctx[abs]
425 if not opts.get('text') and util.binary(fctx.data()):
425 if not opts.get('text') and util.binary(fctx.data()):
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
427 continue
427 continue
428
428
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
430 diffopts=diffopts)
430 diffopts=diffopts)
431 formats = []
431 formats = []
432 pieces = []
432 pieces = []
433
433
434 for f, sep in funcmap:
434 for f, sep in funcmap:
435 l = [f(n) for n, dummy in lines]
435 l = [f(n) for n, dummy in lines]
436 if l:
436 if l:
437 if fm:
437 if fm:
438 formats.append(['%s' for x in l])
438 formats.append(['%s' for x in l])
439 else:
439 else:
440 sizes = [encoding.colwidth(x) for x in l]
440 sizes = [encoding.colwidth(x) for x in l]
441 ml = max(sizes)
441 ml = max(sizes)
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
443 pieces.append(l)
443 pieces.append(l)
444
444
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
446 fm.startitem()
446 fm.startitem()
447 fm.write(fields, "".join(f), *p)
447 fm.write(fields, "".join(f), *p)
448 fm.write('line', ": %s", l[1])
448 fm.write('line', ": %s", l[1])
449
449
450 if lines and not lines[-1][1].endswith('\n'):
450 if lines and not lines[-1][1].endswith('\n'):
451 fm.plain('\n')
451 fm.plain('\n')
452
452
453 fm.end()
453 fm.end()
454
454
455 @command('archive',
455 @command('archive',
456 [('', 'no-decode', None, _('do not pass files through decoders')),
456 [('', 'no-decode', None, _('do not pass files through decoders')),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
458 _('PREFIX')),
458 _('PREFIX')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
461 ] + subrepoopts + walkopts,
461 ] + subrepoopts + walkopts,
462 _('[OPTION]... DEST'))
462 _('[OPTION]... DEST'))
463 def archive(ui, repo, dest, **opts):
463 def archive(ui, repo, dest, **opts):
464 '''create an unversioned archive of a repository revision
464 '''create an unversioned archive of a repository revision
465
465
466 By default, the revision used is the parent of the working
466 By default, the revision used is the parent of the working
467 directory; use -r/--rev to specify a different revision.
467 directory; use -r/--rev to specify a different revision.
468
468
469 The archive type is automatically detected based on file
469 The archive type is automatically detected based on file
470 extension (to override, use -t/--type).
470 extension (to override, use -t/--type).
471
471
472 .. container:: verbose
472 .. container:: verbose
473
473
474 Examples:
474 Examples:
475
475
476 - create a zip file containing the 1.0 release::
476 - create a zip file containing the 1.0 release::
477
477
478 hg archive -r 1.0 project-1.0.zip
478 hg archive -r 1.0 project-1.0.zip
479
479
480 - create a tarball excluding .hg files::
480 - create a tarball excluding .hg files::
481
481
482 hg archive project.tar.gz -X ".hg*"
482 hg archive project.tar.gz -X ".hg*"
483
483
484 Valid types are:
484 Valid types are:
485
485
486 :``files``: a directory full of files (default)
486 :``files``: a directory full of files (default)
487 :``tar``: tar archive, uncompressed
487 :``tar``: tar archive, uncompressed
488 :``tbz2``: tar archive, compressed using bzip2
488 :``tbz2``: tar archive, compressed using bzip2
489 :``tgz``: tar archive, compressed using gzip
489 :``tgz``: tar archive, compressed using gzip
490 :``uzip``: zip archive, uncompressed
490 :``uzip``: zip archive, uncompressed
491 :``zip``: zip archive, compressed using deflate
491 :``zip``: zip archive, compressed using deflate
492
492
493 The exact name of the destination archive or directory is given
493 The exact name of the destination archive or directory is given
494 using a format string; see :hg:`help export` for details.
494 using a format string; see :hg:`help export` for details.
495
495
496 Each member added to an archive file has a directory prefix
496 Each member added to an archive file has a directory prefix
497 prepended. Use -p/--prefix to specify a format string for the
497 prepended. Use -p/--prefix to specify a format string for the
498 prefix. The default is the basename of the archive, with suffixes
498 prefix. The default is the basename of the archive, with suffixes
499 removed.
499 removed.
500
500
501 Returns 0 on success.
501 Returns 0 on success.
502 '''
502 '''
503
503
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
505 if not ctx:
505 if not ctx:
506 raise error.Abort(_('no working directory: please specify a revision'))
506 raise error.Abort(_('no working directory: please specify a revision'))
507 node = ctx.node()
507 node = ctx.node()
508 dest = cmdutil.makefilename(repo, dest, node)
508 dest = cmdutil.makefilename(repo, dest, node)
509 if os.path.realpath(dest) == repo.root:
509 if os.path.realpath(dest) == repo.root:
510 raise error.Abort(_('repository root cannot be destination'))
510 raise error.Abort(_('repository root cannot be destination'))
511
511
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
513 prefix = opts.get('prefix')
513 prefix = opts.get('prefix')
514
514
515 if dest == '-':
515 if dest == '-':
516 if kind == 'files':
516 if kind == 'files':
517 raise error.Abort(_('cannot archive plain files to stdout'))
517 raise error.Abort(_('cannot archive plain files to stdout'))
518 dest = cmdutil.makefileobj(repo, dest)
518 dest = cmdutil.makefileobj(repo, dest)
519 if not prefix:
519 if not prefix:
520 prefix = os.path.basename(repo.root) + '-%h'
520 prefix = os.path.basename(repo.root) + '-%h'
521
521
522 prefix = cmdutil.makefilename(repo, prefix, node)
522 prefix = cmdutil.makefilename(repo, prefix, node)
523 matchfn = scmutil.match(ctx, [], opts)
523 matchfn = scmutil.match(ctx, [], opts)
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
525 matchfn, prefix, subrepos=opts.get('subrepos'))
525 matchfn, prefix, subrepos=opts.get('subrepos'))
526
526
527 @command('backout',
527 @command('backout',
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
529 ('', 'commit', None, _('commit if no conflicts were encountered')),
529 ('', 'commit', None, _('commit if no conflicts were encountered')),
530 ('', 'parent', '',
530 ('', 'parent', '',
531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
532 ('r', 'rev', '', _('revision to backout'), _('REV')),
532 ('r', 'rev', '', _('revision to backout'), _('REV')),
533 ('e', 'edit', False, _('invoke editor on commit messages')),
533 ('e', 'edit', False, _('invoke editor on commit messages')),
534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
535 _('[OPTION]... [-r] REV'))
535 _('[OPTION]... [-r] REV'))
536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
537 '''reverse effect of earlier changeset
537 '''reverse effect of earlier changeset
538
538
539 Prepare a new changeset with the effect of REV undone in the
539 Prepare a new changeset with the effect of REV undone in the
540 current working directory.
540 current working directory.
541
541
542 If REV is the parent of the working directory, then this new changeset
542 If REV is the parent of the working directory, then this new changeset
543 is committed automatically. Otherwise, hg needs to merge the
543 is committed automatically. Otherwise, hg needs to merge the
544 changes and the merged result is left uncommitted.
544 changes and the merged result is left uncommitted.
545
545
546 .. note::
546 .. note::
547
547
548 :hg:`backout` cannot be used to fix either an unwanted or
548 :hg:`backout` cannot be used to fix either an unwanted or
549 incorrect merge.
549 incorrect merge.
550
550
551 .. container:: verbose
551 .. container:: verbose
552
552
553 Examples:
553 Examples:
554
554
555 - Reverse the effect of the parent of the working directory.
555 - Reverse the effect of the parent of the working directory.
556 This backout will be committed immediately::
556 This backout will be committed immediately::
557
557
558 hg backout -r .
558 hg backout -r .
559
559
560 - Reverse the effect of previous bad revision 23::
560 - Reverse the effect of previous bad revision 23::
561
561
562 hg backout -r 23
562 hg backout -r 23
563 hg commit -m "Backout revision 23"
563 hg commit -m "Backout revision 23"
564
564
565 - Reverse the effect of previous bad revision 23 and
565 - Reverse the effect of previous bad revision 23 and
566 commit the backout immediately::
566 commit the backout immediately::
567
567
568 hg backout -r 23 --commit
568 hg backout -r 23 --commit
569
569
570 By default, the pending changeset will have one parent,
570 By default, the pending changeset will have one parent,
571 maintaining a linear history. With --merge, the pending
571 maintaining a linear history. With --merge, the pending
572 changeset will instead have two parents: the old parent of the
572 changeset will instead have two parents: the old parent of the
573 working directory and a new child of REV that simply undoes REV.
573 working directory and a new child of REV that simply undoes REV.
574
574
575 Before version 1.7, the behavior without --merge was equivalent
575 Before version 1.7, the behavior without --merge was equivalent
576 to specifying --merge followed by :hg:`update --clean .` to
576 to specifying --merge followed by :hg:`update --clean .` to
577 cancel the merge and leave the child of REV as a head to be
577 cancel the merge and leave the child of REV as a head to be
578 merged separately.
578 merged separately.
579
579
580 See :hg:`help dates` for a list of formats valid for -d/--date.
580 See :hg:`help dates` for a list of formats valid for -d/--date.
581
581
582 See :hg:`help revert` for a way to restore files to the state
582 See :hg:`help revert` for a way to restore files to the state
583 of another revision.
583 of another revision.
584
584
585 Returns 0 on success, 1 if nothing to backout or there are unresolved
585 Returns 0 on success, 1 if nothing to backout or there are unresolved
586 files.
586 files.
587 '''
587 '''
588 wlock = lock = None
588 wlock = lock = None
589 try:
589 try:
590 wlock = repo.wlock()
590 wlock = repo.wlock()
591 lock = repo.lock()
591 lock = repo.lock()
592 return _dobackout(ui, repo, node, rev, commit, **opts)
592 return _dobackout(ui, repo, node, rev, commit, **opts)
593 finally:
593 finally:
594 release(lock, wlock)
594 release(lock, wlock)
595
595
596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
597 if rev and node:
597 if rev and node:
598 raise error.Abort(_("please specify just one revision"))
598 raise error.Abort(_("please specify just one revision"))
599
599
600 if not rev:
600 if not rev:
601 rev = node
601 rev = node
602
602
603 if not rev:
603 if not rev:
604 raise error.Abort(_("please specify a revision to backout"))
604 raise error.Abort(_("please specify a revision to backout"))
605
605
606 date = opts.get('date')
606 date = opts.get('date')
607 if date:
607 if date:
608 opts['date'] = util.parsedate(date)
608 opts['date'] = util.parsedate(date)
609
609
610 cmdutil.checkunfinished(repo)
610 cmdutil.checkunfinished(repo)
611 cmdutil.bailifchanged(repo)
611 cmdutil.bailifchanged(repo)
612 node = scmutil.revsingle(repo, rev).node()
612 node = scmutil.revsingle(repo, rev).node()
613
613
614 op1, op2 = repo.dirstate.parents()
614 op1, op2 = repo.dirstate.parents()
615 if not repo.changelog.isancestor(node, op1):
615 if not repo.changelog.isancestor(node, op1):
616 raise error.Abort(_('cannot backout change that is not an ancestor'))
616 raise error.Abort(_('cannot backout change that is not an ancestor'))
617
617
618 p1, p2 = repo.changelog.parents(node)
618 p1, p2 = repo.changelog.parents(node)
619 if p1 == nullid:
619 if p1 == nullid:
620 raise error.Abort(_('cannot backout a change with no parents'))
620 raise error.Abort(_('cannot backout a change with no parents'))
621 if p2 != nullid:
621 if p2 != nullid:
622 if not opts.get('parent'):
622 if not opts.get('parent'):
623 raise error.Abort(_('cannot backout a merge changeset'))
623 raise error.Abort(_('cannot backout a merge changeset'))
624 p = repo.lookup(opts['parent'])
624 p = repo.lookup(opts['parent'])
625 if p not in (p1, p2):
625 if p not in (p1, p2):
626 raise error.Abort(_('%s is not a parent of %s') %
626 raise error.Abort(_('%s is not a parent of %s') %
627 (short(p), short(node)))
627 (short(p), short(node)))
628 parent = p
628 parent = p
629 else:
629 else:
630 if opts.get('parent'):
630 if opts.get('parent'):
631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
632 parent = p1
632 parent = p1
633
633
634 # the backout should appear on the same branch
634 # the backout should appear on the same branch
635 branch = repo.dirstate.branch()
635 branch = repo.dirstate.branch()
636 bheads = repo.branchheads(branch)
636 bheads = repo.branchheads(branch)
637 rctx = scmutil.revsingle(repo, hex(parent))
637 rctx = scmutil.revsingle(repo, hex(parent))
638 if not opts.get('merge') and op1 != node:
638 if not opts.get('merge') and op1 != node:
639 dsguard = cmdutil.dirstateguard(repo, 'backout')
639 dsguard = cmdutil.dirstateguard(repo, 'backout')
640 try:
640 try:
641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
642 'backout')
642 'backout')
643 stats = mergemod.update(repo, parent, True, True, node, False)
643 stats = mergemod.update(repo, parent, True, True, node, False)
644 repo.setparents(op1, op2)
644 repo.setparents(op1, op2)
645 dsguard.close()
645 dsguard.close()
646 hg._showstats(repo, stats)
646 hg._showstats(repo, stats)
647 if stats[3]:
647 if stats[3]:
648 repo.ui.status(_("use 'hg resolve' to retry unresolved "
648 repo.ui.status(_("use 'hg resolve' to retry unresolved "
649 "file merges\n"))
649 "file merges\n"))
650 return 1
650 return 1
651 elif not commit:
651 elif not commit:
652 msg = _("changeset %s backed out, "
652 msg = _("changeset %s backed out, "
653 "don't forget to commit.\n")
653 "don't forget to commit.\n")
654 ui.status(msg % short(node))
654 ui.status(msg % short(node))
655 return 0
655 return 0
656 finally:
656 finally:
657 ui.setconfig('ui', 'forcemerge', '', '')
657 ui.setconfig('ui', 'forcemerge', '', '')
658 lockmod.release(dsguard)
658 lockmod.release(dsguard)
659 else:
659 else:
660 hg.clean(repo, node, show_stats=False)
660 hg.clean(repo, node, show_stats=False)
661 repo.dirstate.setbranch(branch)
661 repo.dirstate.setbranch(branch)
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
663
663
664
664
665 def commitfunc(ui, repo, message, match, opts):
665 def commitfunc(ui, repo, message, match, opts):
666 editform = 'backout'
666 editform = 'backout'
667 e = cmdutil.getcommiteditor(editform=editform, **opts)
667 e = cmdutil.getcommiteditor(editform=editform, **opts)
668 if not message:
668 if not message:
669 # we don't translate commit messages
669 # we don't translate commit messages
670 message = "Backed out changeset %s" % short(node)
670 message = "Backed out changeset %s" % short(node)
671 e = cmdutil.getcommiteditor(edit=True, editform=editform)
671 e = cmdutil.getcommiteditor(edit=True, editform=editform)
672 return repo.commit(message, opts.get('user'), opts.get('date'),
672 return repo.commit(message, opts.get('user'), opts.get('date'),
673 match, editor=e)
673 match, editor=e)
674 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
674 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
675 if not newnode:
675 if not newnode:
676 ui.status(_("nothing changed\n"))
676 ui.status(_("nothing changed\n"))
677 return 1
677 return 1
678 cmdutil.commitstatus(repo, newnode, branch, bheads)
678 cmdutil.commitstatus(repo, newnode, branch, bheads)
679
679
680 def nice(node):
680 def nice(node):
681 return '%d:%s' % (repo.changelog.rev(node), short(node))
681 return '%d:%s' % (repo.changelog.rev(node), short(node))
682 ui.status(_('changeset %s backs out changeset %s\n') %
682 ui.status(_('changeset %s backs out changeset %s\n') %
683 (nice(repo.changelog.tip()), nice(node)))
683 (nice(repo.changelog.tip()), nice(node)))
684 if opts.get('merge') and op1 != node:
684 if opts.get('merge') and op1 != node:
685 hg.clean(repo, op1, show_stats=False)
685 hg.clean(repo, op1, show_stats=False)
686 ui.status(_('merging with changeset %s\n')
686 ui.status(_('merging with changeset %s\n')
687 % nice(repo.changelog.tip()))
687 % nice(repo.changelog.tip()))
688 try:
688 try:
689 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
689 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 'backout')
690 'backout')
691 return hg.merge(repo, hex(repo.changelog.tip()))
691 return hg.merge(repo, hex(repo.changelog.tip()))
692 finally:
692 finally:
693 ui.setconfig('ui', 'forcemerge', '', '')
693 ui.setconfig('ui', 'forcemerge', '', '')
694 return 0
694 return 0
695
695
696 @command('bisect',
696 @command('bisect',
697 [('r', 'reset', False, _('reset bisect state')),
697 [('r', 'reset', False, _('reset bisect state')),
698 ('g', 'good', False, _('mark changeset good')),
698 ('g', 'good', False, _('mark changeset good')),
699 ('b', 'bad', False, _('mark changeset bad')),
699 ('b', 'bad', False, _('mark changeset bad')),
700 ('s', 'skip', False, _('skip testing changeset')),
700 ('s', 'skip', False, _('skip testing changeset')),
701 ('e', 'extend', False, _('extend the bisect range')),
701 ('e', 'extend', False, _('extend the bisect range')),
702 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
702 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
703 ('U', 'noupdate', False, _('do not update to target'))],
703 ('U', 'noupdate', False, _('do not update to target'))],
704 _("[-gbsr] [-U] [-c CMD] [REV]"))
704 _("[-gbsr] [-U] [-c CMD] [REV]"))
705 def bisect(ui, repo, rev=None, extra=None, command=None,
705 def bisect(ui, repo, rev=None, extra=None, command=None,
706 reset=None, good=None, bad=None, skip=None, extend=None,
706 reset=None, good=None, bad=None, skip=None, extend=None,
707 noupdate=None):
707 noupdate=None):
708 """subdivision search of changesets
708 """subdivision search of changesets
709
709
710 This command helps to find changesets which introduce problems. To
710 This command helps to find changesets which introduce problems. To
711 use, mark the earliest changeset you know exhibits the problem as
711 use, mark the earliest changeset you know exhibits the problem as
712 bad, then mark the latest changeset which is free from the problem
712 bad, then mark the latest changeset which is free from the problem
713 as good. Bisect will update your working directory to a revision
713 as good. Bisect will update your working directory to a revision
714 for testing (unless the -U/--noupdate option is specified). Once
714 for testing (unless the -U/--noupdate option is specified). Once
715 you have performed tests, mark the working directory as good or
715 you have performed tests, mark the working directory as good or
716 bad, and bisect will either update to another candidate changeset
716 bad, and bisect will either update to another candidate changeset
717 or announce that it has found the bad revision.
717 or announce that it has found the bad revision.
718
718
719 As a shortcut, you can also use the revision argument to mark a
719 As a shortcut, you can also use the revision argument to mark a
720 revision as good or bad without checking it out first.
720 revision as good or bad without checking it out first.
721
721
722 If you supply a command, it will be used for automatic bisection.
722 If you supply a command, it will be used for automatic bisection.
723 The environment variable HG_NODE will contain the ID of the
723 The environment variable HG_NODE will contain the ID of the
724 changeset being tested. The exit status of the command will be
724 changeset being tested. The exit status of the command will be
725 used to mark revisions as good or bad: status 0 means good, 125
725 used to mark revisions as good or bad: status 0 means good, 125
726 means to skip the revision, 127 (command not found) will abort the
726 means to skip the revision, 127 (command not found) will abort the
727 bisection, and any other non-zero exit status means the revision
727 bisection, and any other non-zero exit status means the revision
728 is bad.
728 is bad.
729
729
730 .. container:: verbose
730 .. container:: verbose
731
731
732 Some examples:
732 Some examples:
733
733
734 - start a bisection with known bad revision 34, and good revision 12::
734 - start a bisection with known bad revision 34, and good revision 12::
735
735
736 hg bisect --bad 34
736 hg bisect --bad 34
737 hg bisect --good 12
737 hg bisect --good 12
738
738
739 - advance the current bisection by marking current revision as good or
739 - advance the current bisection by marking current revision as good or
740 bad::
740 bad::
741
741
742 hg bisect --good
742 hg bisect --good
743 hg bisect --bad
743 hg bisect --bad
744
744
745 - mark the current revision, or a known revision, to be skipped (e.g. if
745 - mark the current revision, or a known revision, to be skipped (e.g. if
746 that revision is not usable because of another issue)::
746 that revision is not usable because of another issue)::
747
747
748 hg bisect --skip
748 hg bisect --skip
749 hg bisect --skip 23
749 hg bisect --skip 23
750
750
751 - skip all revisions that do not touch directories ``foo`` or ``bar``::
751 - skip all revisions that do not touch directories ``foo`` or ``bar``::
752
752
753 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
753 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
754
754
755 - forget the current bisection::
755 - forget the current bisection::
756
756
757 hg bisect --reset
757 hg bisect --reset
758
758
759 - use 'make && make tests' to automatically find the first broken
759 - use 'make && make tests' to automatically find the first broken
760 revision::
760 revision::
761
761
762 hg bisect --reset
762 hg bisect --reset
763 hg bisect --bad 34
763 hg bisect --bad 34
764 hg bisect --good 12
764 hg bisect --good 12
765 hg bisect --command "make && make tests"
765 hg bisect --command "make && make tests"
766
766
767 - see all changesets whose states are already known in the current
767 - see all changesets whose states are already known in the current
768 bisection::
768 bisection::
769
769
770 hg log -r "bisect(pruned)"
770 hg log -r "bisect(pruned)"
771
771
772 - see the changeset currently being bisected (especially useful
772 - see the changeset currently being bisected (especially useful
773 if running with -U/--noupdate)::
773 if running with -U/--noupdate)::
774
774
775 hg log -r "bisect(current)"
775 hg log -r "bisect(current)"
776
776
777 - see all changesets that took part in the current bisection::
777 - see all changesets that took part in the current bisection::
778
778
779 hg log -r "bisect(range)"
779 hg log -r "bisect(range)"
780
780
781 - you can even get a nice graph::
781 - you can even get a nice graph::
782
782
783 hg log --graph -r "bisect(range)"
783 hg log --graph -r "bisect(range)"
784
784
785 See :hg:`help revsets` for more about the `bisect()` keyword.
785 See :hg:`help revsets` for more about the `bisect()` keyword.
786
786
787 Returns 0 on success.
787 Returns 0 on success.
788 """
788 """
789 def extendbisectrange(nodes, good):
789 def extendbisectrange(nodes, good):
790 # bisect is incomplete when it ends on a merge node and
790 # bisect is incomplete when it ends on a merge node and
791 # one of the parent was not checked.
791 # one of the parent was not checked.
792 parents = repo[nodes[0]].parents()
792 parents = repo[nodes[0]].parents()
793 if len(parents) > 1:
793 if len(parents) > 1:
794 if good:
794 if good:
795 side = state['bad']
795 side = state['bad']
796 else:
796 else:
797 side = state['good']
797 side = state['good']
798 num = len(set(i.node() for i in parents) & set(side))
798 num = len(set(i.node() for i in parents) & set(side))
799 if num == 1:
799 if num == 1:
800 return parents[0].ancestor(parents[1])
800 return parents[0].ancestor(parents[1])
801 return None
801 return None
802
802
803 def print_result(nodes, good):
803 def print_result(nodes, good):
804 displayer = cmdutil.show_changeset(ui, repo, {})
804 displayer = cmdutil.show_changeset(ui, repo, {})
805 if len(nodes) == 1:
805 if len(nodes) == 1:
806 # narrowed it down to a single revision
806 # narrowed it down to a single revision
807 if good:
807 if good:
808 ui.write(_("The first good revision is:\n"))
808 ui.write(_("The first good revision is:\n"))
809 else:
809 else:
810 ui.write(_("The first bad revision is:\n"))
810 ui.write(_("The first bad revision is:\n"))
811 displayer.show(repo[nodes[0]])
811 displayer.show(repo[nodes[0]])
812 extendnode = extendbisectrange(nodes, good)
812 extendnode = extendbisectrange(nodes, good)
813 if extendnode is not None:
813 if extendnode is not None:
814 ui.write(_('Not all ancestors of this changeset have been'
814 ui.write(_('Not all ancestors of this changeset have been'
815 ' checked.\nUse bisect --extend to continue the '
815 ' checked.\nUse bisect --extend to continue the '
816 'bisection from\nthe common ancestor, %s.\n')
816 'bisection from\nthe common ancestor, %s.\n')
817 % extendnode)
817 % extendnode)
818 else:
818 else:
819 # multiple possible revisions
819 # multiple possible revisions
820 if good:
820 if good:
821 ui.write(_("Due to skipped revisions, the first "
821 ui.write(_("Due to skipped revisions, the first "
822 "good revision could be any of:\n"))
822 "good revision could be any of:\n"))
823 else:
823 else:
824 ui.write(_("Due to skipped revisions, the first "
824 ui.write(_("Due to skipped revisions, the first "
825 "bad revision could be any of:\n"))
825 "bad revision could be any of:\n"))
826 for n in nodes:
826 for n in nodes:
827 displayer.show(repo[n])
827 displayer.show(repo[n])
828 displayer.close()
828 displayer.close()
829
829
830 def check_state(state, interactive=True):
830 def check_state(state, interactive=True):
831 if not state['good'] or not state['bad']:
831 if not state['good'] or not state['bad']:
832 if (good or bad or skip or reset) and interactive:
832 if (good or bad or skip or reset) and interactive:
833 return
833 return
834 if not state['good']:
834 if not state['good']:
835 raise error.Abort(_('cannot bisect (no known good revisions)'))
835 raise error.Abort(_('cannot bisect (no known good revisions)'))
836 else:
836 else:
837 raise error.Abort(_('cannot bisect (no known bad revisions)'))
837 raise error.Abort(_('cannot bisect (no known bad revisions)'))
838 return True
838 return True
839
839
840 # backward compatibility
840 # backward compatibility
841 if rev in "good bad reset init".split():
841 if rev in "good bad reset init".split():
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
843 cmd, rev, extra = rev, extra, None
843 cmd, rev, extra = rev, extra, None
844 if cmd == "good":
844 if cmd == "good":
845 good = True
845 good = True
846 elif cmd == "bad":
846 elif cmd == "bad":
847 bad = True
847 bad = True
848 else:
848 else:
849 reset = True
849 reset = True
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
851 raise error.Abort(_('incompatible arguments'))
851 raise error.Abort(_('incompatible arguments'))
852
852
853 cmdutil.checkunfinished(repo)
853 cmdutil.checkunfinished(repo)
854
854
855 if reset:
855 if reset:
856 p = repo.join("bisect.state")
856 p = repo.join("bisect.state")
857 if os.path.exists(p):
857 if os.path.exists(p):
858 os.unlink(p)
858 os.unlink(p)
859 return
859 return
860
860
861 state = hbisect.load_state(repo)
861 state = hbisect.load_state(repo)
862
862
863 if command:
863 if command:
864 changesets = 1
864 changesets = 1
865 if noupdate:
865 if noupdate:
866 try:
866 try:
867 node = state['current'][0]
867 node = state['current'][0]
868 except LookupError:
868 except LookupError:
869 raise error.Abort(_('current bisect revision is unknown - '
869 raise error.Abort(_('current bisect revision is unknown - '
870 'start a new bisect to fix'))
870 'start a new bisect to fix'))
871 else:
871 else:
872 node, p2 = repo.dirstate.parents()
872 node, p2 = repo.dirstate.parents()
873 if p2 != nullid:
873 if p2 != nullid:
874 raise error.Abort(_('current bisect revision is a merge'))
874 raise error.Abort(_('current bisect revision is a merge'))
875 try:
875 try:
876 while changesets:
876 while changesets:
877 # update state
877 # update state
878 state['current'] = [node]
878 state['current'] = [node]
879 hbisect.save_state(repo, state)
879 hbisect.save_state(repo, state)
880 status = ui.system(command, environ={'HG_NODE': hex(node)})
880 status = ui.system(command, environ={'HG_NODE': hex(node)})
881 if status == 125:
881 if status == 125:
882 transition = "skip"
882 transition = "skip"
883 elif status == 0:
883 elif status == 0:
884 transition = "good"
884 transition = "good"
885 # status < 0 means process was killed
885 # status < 0 means process was killed
886 elif status == 127:
886 elif status == 127:
887 raise error.Abort(_("failed to execute %s") % command)
887 raise error.Abort(_("failed to execute %s") % command)
888 elif status < 0:
888 elif status < 0:
889 raise error.Abort(_("%s killed") % command)
889 raise error.Abort(_("%s killed") % command)
890 else:
890 else:
891 transition = "bad"
891 transition = "bad"
892 ctx = scmutil.revsingle(repo, rev, node)
892 ctx = scmutil.revsingle(repo, rev, node)
893 rev = None # clear for future iterations
893 rev = None # clear for future iterations
894 state[transition].append(ctx.node())
894 state[transition].append(ctx.node())
895 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
895 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
896 check_state(state, interactive=False)
896 check_state(state, interactive=False)
897 # bisect
897 # bisect
898 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
898 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
899 # update to next check
899 # update to next check
900 node = nodes[0]
900 node = nodes[0]
901 if not noupdate:
901 if not noupdate:
902 cmdutil.bailifchanged(repo)
902 cmdutil.bailifchanged(repo)
903 hg.clean(repo, node, show_stats=False)
903 hg.clean(repo, node, show_stats=False)
904 finally:
904 finally:
905 state['current'] = [node]
905 state['current'] = [node]
906 hbisect.save_state(repo, state)
906 hbisect.save_state(repo, state)
907 print_result(nodes, bgood)
907 print_result(nodes, bgood)
908 return
908 return
909
909
910 # update state
910 # update state
911
911
912 if rev:
912 if rev:
913 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
913 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
914 else:
914 else:
915 nodes = [repo.lookup('.')]
915 nodes = [repo.lookup('.')]
916
916
917 if good or bad or skip:
917 if good or bad or skip:
918 if good:
918 if good:
919 state['good'] += nodes
919 state['good'] += nodes
920 elif bad:
920 elif bad:
921 state['bad'] += nodes
921 state['bad'] += nodes
922 elif skip:
922 elif skip:
923 state['skip'] += nodes
923 state['skip'] += nodes
924 hbisect.save_state(repo, state)
924 hbisect.save_state(repo, state)
925
925
926 if not check_state(state):
926 if not check_state(state):
927 return
927 return
928
928
929 # actually bisect
929 # actually bisect
930 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
930 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
931 if extend:
931 if extend:
932 if not changesets:
932 if not changesets:
933 extendnode = extendbisectrange(nodes, good)
933 extendnode = extendbisectrange(nodes, good)
934 if extendnode is not None:
934 if extendnode is not None:
935 ui.write(_("Extending search to changeset %d:%s\n")
935 ui.write(_("Extending search to changeset %d:%s\n")
936 % (extendnode.rev(), extendnode))
936 % (extendnode.rev(), extendnode))
937 state['current'] = [extendnode.node()]
937 state['current'] = [extendnode.node()]
938 hbisect.save_state(repo, state)
938 hbisect.save_state(repo, state)
939 if noupdate:
939 if noupdate:
940 return
940 return
941 cmdutil.bailifchanged(repo)
941 cmdutil.bailifchanged(repo)
942 return hg.clean(repo, extendnode.node())
942 return hg.clean(repo, extendnode.node())
943 raise error.Abort(_("nothing to extend"))
943 raise error.Abort(_("nothing to extend"))
944
944
945 if changesets == 0:
945 if changesets == 0:
946 print_result(nodes, good)
946 print_result(nodes, good)
947 else:
947 else:
948 assert len(nodes) == 1 # only a single node can be tested next
948 assert len(nodes) == 1 # only a single node can be tested next
949 node = nodes[0]
949 node = nodes[0]
950 # compute the approximate number of remaining tests
950 # compute the approximate number of remaining tests
951 tests, size = 0, 2
951 tests, size = 0, 2
952 while size <= changesets:
952 while size <= changesets:
953 tests, size = tests + 1, size * 2
953 tests, size = tests + 1, size * 2
954 rev = repo.changelog.rev(node)
954 rev = repo.changelog.rev(node)
955 ui.write(_("Testing changeset %d:%s "
955 ui.write(_("Testing changeset %d:%s "
956 "(%d changesets remaining, ~%d tests)\n")
956 "(%d changesets remaining, ~%d tests)\n")
957 % (rev, short(node), changesets, tests))
957 % (rev, short(node), changesets, tests))
958 state['current'] = [node]
958 state['current'] = [node]
959 hbisect.save_state(repo, state)
959 hbisect.save_state(repo, state)
960 if not noupdate:
960 if not noupdate:
961 cmdutil.bailifchanged(repo)
961 cmdutil.bailifchanged(repo)
962 return hg.clean(repo, node)
962 return hg.clean(repo, node)
963
963
964 @command('bookmarks|bookmark',
964 @command('bookmarks|bookmark',
965 [('f', 'force', False, _('force')),
965 [('f', 'force', False, _('force')),
966 ('r', 'rev', '', _('revision'), _('REV')),
966 ('r', 'rev', '', _('revision'), _('REV')),
967 ('d', 'delete', False, _('delete a given bookmark')),
967 ('d', 'delete', False, _('delete a given bookmark')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
970 ] + formatteropts,
970 ] + formatteropts,
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
972 def bookmark(ui, repo, *names, **opts):
972 def bookmark(ui, repo, *names, **opts):
973 '''create a new bookmark or list existing bookmarks
973 '''create a new bookmark or list existing bookmarks
974
974
975 Bookmarks are labels on changesets to help track lines of development.
975 Bookmarks are labels on changesets to help track lines of development.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
977 Deleting or moving a bookmark has no effect on the associated changesets.
977 Deleting or moving a bookmark has no effect on the associated changesets.
978
978
979 Creating or updating to a bookmark causes it to be marked as 'active'.
979 Creating or updating to a bookmark causes it to be marked as 'active'.
980 The active bookmark is indicated with a '*'.
980 The active bookmark is indicated with a '*'.
981 When a commit is made, the active bookmark will advance to the new commit.
981 When a commit is made, the active bookmark will advance to the new commit.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
983 Updating away from a bookmark will cause it to be deactivated.
983 Updating away from a bookmark will cause it to be deactivated.
984
984
985 Bookmarks can be pushed and pulled between repositories (see
985 Bookmarks can be pushed and pulled between repositories (see
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
988 be created. Using :hg:`merge` will resolve the divergence.
988 be created. Using :hg:`merge` will resolve the divergence.
989
989
990 A bookmark named '@' has the special property that :hg:`clone` will
990 A bookmark named '@' has the special property that :hg:`clone` will
991 check it out by default if it exists.
991 check it out by default if it exists.
992
992
993 .. container:: verbose
993 .. container:: verbose
994
994
995 Examples:
995 Examples:
996
996
997 - create an active bookmark for a new line of development::
997 - create an active bookmark for a new line of development::
998
998
999 hg book new-feature
999 hg book new-feature
1000
1000
1001 - create an inactive bookmark as a place marker::
1001 - create an inactive bookmark as a place marker::
1002
1002
1003 hg book -i reviewed
1003 hg book -i reviewed
1004
1004
1005 - create an inactive bookmark on another changeset::
1005 - create an inactive bookmark on another changeset::
1006
1006
1007 hg book -r .^ tested
1007 hg book -r .^ tested
1008
1008
1009 - rename bookmark turkey to dinner::
1009 - rename bookmark turkey to dinner::
1010
1010
1011 hg book -m turkey dinner
1011 hg book -m turkey dinner
1012
1012
1013 - move the '@' bookmark from another branch::
1013 - move the '@' bookmark from another branch::
1014
1014
1015 hg book -f @
1015 hg book -f @
1016 '''
1016 '''
1017 force = opts.get('force')
1017 force = opts.get('force')
1018 rev = opts.get('rev')
1018 rev = opts.get('rev')
1019 delete = opts.get('delete')
1019 delete = opts.get('delete')
1020 rename = opts.get('rename')
1020 rename = opts.get('rename')
1021 inactive = opts.get('inactive')
1021 inactive = opts.get('inactive')
1022
1022
1023 def checkformat(mark):
1023 def checkformat(mark):
1024 mark = mark.strip()
1024 mark = mark.strip()
1025 if not mark:
1025 if not mark:
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1027 "whitespace"))
1027 "whitespace"))
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1029 return mark
1029 return mark
1030
1030
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1032 if mark in marks and not force:
1032 if mark in marks and not force:
1033 if target:
1033 if target:
1034 if marks[mark] == target and target == cur:
1034 if marks[mark] == target and target == cur:
1035 # re-activating a bookmark
1035 # re-activating a bookmark
1036 return
1036 return
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1038 bmctx = repo[marks[mark]]
1038 bmctx = repo[marks[mark]]
1039 divs = [repo[b].node() for b in marks
1039 divs = [repo[b].node() for b in marks
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1041
1041
1042 # allow resolving a single divergent bookmark even if moving
1042 # allow resolving a single divergent bookmark even if moving
1043 # the bookmark across branches when a revision is specified
1043 # the bookmark across branches when a revision is specified
1044 # that contains a divergent bookmark
1044 # that contains a divergent bookmark
1045 if bmctx.rev() not in anc and target in divs:
1045 if bmctx.rev() not in anc and target in divs:
1046 bookmarks.deletedivergent(repo, [target], mark)
1046 bookmarks.deletedivergent(repo, [target], mark)
1047 return
1047 return
1048
1048
1049 deletefrom = [b for b in divs
1049 deletefrom = [b for b in divs
1050 if repo[b].rev() in anc or b == target]
1050 if repo[b].rev() in anc or b == target]
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1054 (mark, short(bmctx.node())))
1054 (mark, short(bmctx.node())))
1055 return
1055 return
1056 raise error.Abort(_("bookmark '%s' already exists "
1056 raise error.Abort(_("bookmark '%s' already exists "
1057 "(use -f to force)") % mark)
1057 "(use -f to force)") % mark)
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1059 and not force):
1059 and not force):
1060 raise error.Abort(
1060 raise error.Abort(
1061 _("a bookmark cannot have the name of an existing branch"))
1061 _("a bookmark cannot have the name of an existing branch"))
1062
1062
1063 if delete and rename:
1063 if delete and rename:
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1065 if delete and rev:
1065 if delete and rev:
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1067 if rename and rev:
1067 if rename and rev:
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1069 if not names and (delete or rev):
1069 if not names and (delete or rev):
1070 raise error.Abort(_("bookmark name required"))
1070 raise error.Abort(_("bookmark name required"))
1071
1071
1072 if delete or rename or names or inactive:
1072 if delete or rename or names or inactive:
1073 wlock = lock = tr = None
1073 wlock = lock = tr = None
1074 try:
1074 try:
1075 wlock = repo.wlock()
1075 wlock = repo.wlock()
1076 lock = repo.lock()
1076 lock = repo.lock()
1077 cur = repo.changectx('.').node()
1077 cur = repo.changectx('.').node()
1078 marks = repo._bookmarks
1078 marks = repo._bookmarks
1079 if delete:
1079 if delete:
1080 tr = repo.transaction('bookmark')
1080 tr = repo.transaction('bookmark')
1081 for mark in names:
1081 for mark in names:
1082 if mark not in marks:
1082 if mark not in marks:
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1084 mark)
1084 mark)
1085 if mark == repo._activebookmark:
1085 if mark == repo._activebookmark:
1086 bookmarks.deactivate(repo)
1086 bookmarks.deactivate(repo)
1087 del marks[mark]
1087 del marks[mark]
1088
1088
1089 elif rename:
1089 elif rename:
1090 tr = repo.transaction('bookmark')
1090 tr = repo.transaction('bookmark')
1091 if not names:
1091 if not names:
1092 raise error.Abort(_("new bookmark name required"))
1092 raise error.Abort(_("new bookmark name required"))
1093 elif len(names) > 1:
1093 elif len(names) > 1:
1094 raise error.Abort(_("only one new bookmark name allowed"))
1094 raise error.Abort(_("only one new bookmark name allowed"))
1095 mark = checkformat(names[0])
1095 mark = checkformat(names[0])
1096 if rename not in marks:
1096 if rename not in marks:
1097 raise error.Abort(_("bookmark '%s' does not exist")
1097 raise error.Abort(_("bookmark '%s' does not exist")
1098 % rename)
1098 % rename)
1099 checkconflict(repo, mark, cur, force)
1099 checkconflict(repo, mark, cur, force)
1100 marks[mark] = marks[rename]
1100 marks[mark] = marks[rename]
1101 if repo._activebookmark == rename and not inactive:
1101 if repo._activebookmark == rename and not inactive:
1102 bookmarks.activate(repo, mark)
1102 bookmarks.activate(repo, mark)
1103 del marks[rename]
1103 del marks[rename]
1104 elif names:
1104 elif names:
1105 tr = repo.transaction('bookmark')
1105 tr = repo.transaction('bookmark')
1106 newact = None
1106 newact = None
1107 for mark in names:
1107 for mark in names:
1108 mark = checkformat(mark)
1108 mark = checkformat(mark)
1109 if newact is None:
1109 if newact is None:
1110 newact = mark
1110 newact = mark
1111 if inactive and mark == repo._activebookmark:
1111 if inactive and mark == repo._activebookmark:
1112 bookmarks.deactivate(repo)
1112 bookmarks.deactivate(repo)
1113 return
1113 return
1114 tgt = cur
1114 tgt = cur
1115 if rev:
1115 if rev:
1116 tgt = scmutil.revsingle(repo, rev).node()
1116 tgt = scmutil.revsingle(repo, rev).node()
1117 checkconflict(repo, mark, cur, force, tgt)
1117 checkconflict(repo, mark, cur, force, tgt)
1118 marks[mark] = tgt
1118 marks[mark] = tgt
1119 if not inactive and cur == marks[newact] and not rev:
1119 if not inactive and cur == marks[newact] and not rev:
1120 bookmarks.activate(repo, newact)
1120 bookmarks.activate(repo, newact)
1121 elif cur != tgt and newact == repo._activebookmark:
1121 elif cur != tgt and newact == repo._activebookmark:
1122 bookmarks.deactivate(repo)
1122 bookmarks.deactivate(repo)
1123 elif inactive:
1123 elif inactive:
1124 if len(marks) == 0:
1124 if len(marks) == 0:
1125 ui.status(_("no bookmarks set\n"))
1125 ui.status(_("no bookmarks set\n"))
1126 elif not repo._activebookmark:
1126 elif not repo._activebookmark:
1127 ui.status(_("no active bookmark\n"))
1127 ui.status(_("no active bookmark\n"))
1128 else:
1128 else:
1129 bookmarks.deactivate(repo)
1129 bookmarks.deactivate(repo)
1130 if tr is not None:
1130 if tr is not None:
1131 marks.recordchange(tr)
1131 marks.recordchange(tr)
1132 tr.close()
1132 tr.close()
1133 finally:
1133 finally:
1134 lockmod.release(tr, lock, wlock)
1134 lockmod.release(tr, lock, wlock)
1135 else: # show bookmarks
1135 else: # show bookmarks
1136 fm = ui.formatter('bookmarks', opts)
1136 fm = ui.formatter('bookmarks', opts)
1137 hexfn = fm.hexfunc
1137 hexfn = fm.hexfunc
1138 marks = repo._bookmarks
1138 marks = repo._bookmarks
1139 if len(marks) == 0 and not fm:
1139 if len(marks) == 0 and not fm:
1140 ui.status(_("no bookmarks set\n"))
1140 ui.status(_("no bookmarks set\n"))
1141 for bmark, n in sorted(marks.iteritems()):
1141 for bmark, n in sorted(marks.iteritems()):
1142 active = repo._activebookmark
1142 active = repo._activebookmark
1143 if bmark == active:
1143 if bmark == active:
1144 prefix, label = '*', activebookmarklabel
1144 prefix, label = '*', activebookmarklabel
1145 else:
1145 else:
1146 prefix, label = ' ', ''
1146 prefix, label = ' ', ''
1147
1147
1148 fm.startitem()
1148 fm.startitem()
1149 if not ui.quiet:
1149 if not ui.quiet:
1150 fm.plain(' %s ' % prefix, label=label)
1150 fm.plain(' %s ' % prefix, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1152 pad = " " * (25 - encoding.colwidth(bmark))
1152 pad = " " * (25 - encoding.colwidth(bmark))
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1154 repo.changelog.rev(n), hexfn(n), label=label)
1154 repo.changelog.rev(n), hexfn(n), label=label)
1155 fm.data(active=(bmark == active))
1155 fm.data(active=(bmark == active))
1156 fm.plain('\n')
1156 fm.plain('\n')
1157 fm.end()
1157 fm.end()
1158
1158
1159 @command('branch',
1159 @command('branch',
1160 [('f', 'force', None,
1160 [('f', 'force', None,
1161 _('set branch name even if it shadows an existing branch')),
1161 _('set branch name even if it shadows an existing branch')),
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1163 _('[-fC] [NAME]'))
1163 _('[-fC] [NAME]'))
1164 def branch(ui, repo, label=None, **opts):
1164 def branch(ui, repo, label=None, **opts):
1165 """set or show the current branch name
1165 """set or show the current branch name
1166
1166
1167 .. note::
1167 .. note::
1168
1168
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1171 information about named branches and bookmarks.
1171 information about named branches and bookmarks.
1172
1172
1173 With no argument, show the current branch name. With one argument,
1173 With no argument, show the current branch name. With one argument,
1174 set the working directory branch name (the branch will not exist
1174 set the working directory branch name (the branch will not exist
1175 in the repository until the next commit). Standard practice
1175 in the repository until the next commit). Standard practice
1176 recommends that primary development take place on the 'default'
1176 recommends that primary development take place on the 'default'
1177 branch.
1177 branch.
1178
1178
1179 Unless -f/--force is specified, branch will not let you set a
1179 Unless -f/--force is specified, branch will not let you set a
1180 branch name that already exists.
1180 branch name that already exists.
1181
1181
1182 Use -C/--clean to reset the working directory branch to that of
1182 Use -C/--clean to reset the working directory branch to that of
1183 the parent of the working directory, negating a previous branch
1183 the parent of the working directory, negating a previous branch
1184 change.
1184 change.
1185
1185
1186 Use the command :hg:`update` to switch to an existing branch. Use
1186 Use the command :hg:`update` to switch to an existing branch. Use
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1188 When all heads of a branch are closed, the branch will be
1188 When all heads of a branch are closed, the branch will be
1189 considered closed.
1189 considered closed.
1190
1190
1191 Returns 0 on success.
1191 Returns 0 on success.
1192 """
1192 """
1193 if label:
1193 if label:
1194 label = label.strip()
1194 label = label.strip()
1195
1195
1196 if not opts.get('clean') and not label:
1196 if not opts.get('clean') and not label:
1197 ui.write("%s\n" % repo.dirstate.branch())
1197 ui.write("%s\n" % repo.dirstate.branch())
1198 return
1198 return
1199
1199
1200 wlock = repo.wlock()
1200 wlock = repo.wlock()
1201 try:
1201 try:
1202 if opts.get('clean'):
1202 if opts.get('clean'):
1203 label = repo[None].p1().branch()
1203 label = repo[None].p1().branch()
1204 repo.dirstate.setbranch(label)
1204 repo.dirstate.setbranch(label)
1205 ui.status(_('reset working directory to branch %s\n') % label)
1205 ui.status(_('reset working directory to branch %s\n') % label)
1206 elif label:
1206 elif label:
1207 if not opts.get('force') and label in repo.branchmap():
1207 if not opts.get('force') and label in repo.branchmap():
1208 if label not in [p.branch() for p in repo[None].parents()]:
1208 if label not in [p.branch() for p in repo[None].parents()]:
1209 raise error.Abort(_('a branch of the same name already'
1209 raise error.Abort(_('a branch of the same name already'
1210 ' exists'),
1210 ' exists'),
1211 # i18n: "it" refers to an existing branch
1211 # i18n: "it" refers to an existing branch
1212 hint=_("use 'hg update' to switch to it"))
1212 hint=_("use 'hg update' to switch to it"))
1213 scmutil.checknewlabel(repo, label, 'branch')
1213 scmutil.checknewlabel(repo, label, 'branch')
1214 repo.dirstate.setbranch(label)
1214 repo.dirstate.setbranch(label)
1215 ui.status(_('marked working directory as branch %s\n') % label)
1215 ui.status(_('marked working directory as branch %s\n') % label)
1216
1216
1217 # find any open named branches aside from default
1217 # find any open named branches aside from default
1218 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1218 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1219 if n != "default" and not c]
1219 if n != "default" and not c]
1220 if not others:
1220 if not others:
1221 ui.status(_('(branches are permanent and global, '
1221 ui.status(_('(branches are permanent and global, '
1222 'did you want a bookmark?)\n'))
1222 'did you want a bookmark?)\n'))
1223 finally:
1223 finally:
1224 wlock.release()
1224 wlock.release()
1225
1225
1226 @command('branches',
1226 @command('branches',
1227 [('a', 'active', False,
1227 [('a', 'active', False,
1228 _('show only branches that have unmerged heads (DEPRECATED)')),
1228 _('show only branches that have unmerged heads (DEPRECATED)')),
1229 ('c', 'closed', False, _('show normal and closed branches')),
1229 ('c', 'closed', False, _('show normal and closed branches')),
1230 ] + formatteropts,
1230 ] + formatteropts,
1231 _('[-ac]'))
1231 _('[-ac]'))
1232 def branches(ui, repo, active=False, closed=False, **opts):
1232 def branches(ui, repo, active=False, closed=False, **opts):
1233 """list repository named branches
1233 """list repository named branches
1234
1234
1235 List the repository's named branches, indicating which ones are
1235 List the repository's named branches, indicating which ones are
1236 inactive. If -c/--closed is specified, also list branches which have
1236 inactive. If -c/--closed is specified, also list branches which have
1237 been marked closed (see :hg:`commit --close-branch`).
1237 been marked closed (see :hg:`commit --close-branch`).
1238
1238
1239 Use the command :hg:`update` to switch to an existing branch.
1239 Use the command :hg:`update` to switch to an existing branch.
1240
1240
1241 Returns 0.
1241 Returns 0.
1242 """
1242 """
1243
1243
1244 fm = ui.formatter('branches', opts)
1244 fm = ui.formatter('branches', opts)
1245 hexfunc = fm.hexfunc
1245 hexfunc = fm.hexfunc
1246
1246
1247 allheads = set(repo.heads())
1247 allheads = set(repo.heads())
1248 branches = []
1248 branches = []
1249 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1249 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1250 isactive = not isclosed and bool(set(heads) & allheads)
1250 isactive = not isclosed and bool(set(heads) & allheads)
1251 branches.append((tag, repo[tip], isactive, not isclosed))
1251 branches.append((tag, repo[tip], isactive, not isclosed))
1252 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1252 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1253 reverse=True)
1253 reverse=True)
1254
1254
1255 for tag, ctx, isactive, isopen in branches:
1255 for tag, ctx, isactive, isopen in branches:
1256 if active and not isactive:
1256 if active and not isactive:
1257 continue
1257 continue
1258 if isactive:
1258 if isactive:
1259 label = 'branches.active'
1259 label = 'branches.active'
1260 notice = ''
1260 notice = ''
1261 elif not isopen:
1261 elif not isopen:
1262 if not closed:
1262 if not closed:
1263 continue
1263 continue
1264 label = 'branches.closed'
1264 label = 'branches.closed'
1265 notice = _(' (closed)')
1265 notice = _(' (closed)')
1266 else:
1266 else:
1267 label = 'branches.inactive'
1267 label = 'branches.inactive'
1268 notice = _(' (inactive)')
1268 notice = _(' (inactive)')
1269 current = (tag == repo.dirstate.branch())
1269 current = (tag == repo.dirstate.branch())
1270 if current:
1270 if current:
1271 label = 'branches.current'
1271 label = 'branches.current'
1272
1272
1273 fm.startitem()
1273 fm.startitem()
1274 fm.write('branch', '%s', tag, label=label)
1274 fm.write('branch', '%s', tag, label=label)
1275 rev = ctx.rev()
1275 rev = ctx.rev()
1276 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1276 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1277 fmt = ' ' * padsize + ' %d:%s'
1277 fmt = ' ' * padsize + ' %d:%s'
1278 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1278 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1279 label='log.changeset changeset.%s' % ctx.phasestr())
1279 label='log.changeset changeset.%s' % ctx.phasestr())
1280 fm.data(active=isactive, closed=not isopen, current=current)
1280 fm.data(active=isactive, closed=not isopen, current=current)
1281 if not ui.quiet:
1281 if not ui.quiet:
1282 fm.plain(notice)
1282 fm.plain(notice)
1283 fm.plain('\n')
1283 fm.plain('\n')
1284 fm.end()
1284 fm.end()
1285
1285
1286 @command('bundle',
1286 @command('bundle',
1287 [('f', 'force', None, _('run even when the destination is unrelated')),
1287 [('f', 'force', None, _('run even when the destination is unrelated')),
1288 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1288 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1289 _('REV')),
1289 _('REV')),
1290 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1290 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1291 _('BRANCH')),
1291 _('BRANCH')),
1292 ('', 'base', [],
1292 ('', 'base', [],
1293 _('a base changeset assumed to be available at the destination'),
1293 _('a base changeset assumed to be available at the destination'),
1294 _('REV')),
1294 _('REV')),
1295 ('a', 'all', None, _('bundle all changesets in the repository')),
1295 ('a', 'all', None, _('bundle all changesets in the repository')),
1296 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1296 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1297 ] + remoteopts,
1297 ] + remoteopts,
1298 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1298 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1299 def bundle(ui, repo, fname, dest=None, **opts):
1299 def bundle(ui, repo, fname, dest=None, **opts):
1300 """create a changegroup file
1300 """create a changegroup file
1301
1301
1302 Generate a changegroup file collecting changesets to be added
1302 Generate a changegroup file collecting changesets to be added
1303 to a repository.
1303 to a repository.
1304
1304
1305 To create a bundle containing all changesets, use -a/--all
1305 To create a bundle containing all changesets, use -a/--all
1306 (or --base null). Otherwise, hg assumes the destination will have
1306 (or --base null). Otherwise, hg assumes the destination will have
1307 all the nodes you specify with --base parameters. Otherwise, hg
1307 all the nodes you specify with --base parameters. Otherwise, hg
1308 will assume the repository has all the nodes in destination, or
1308 will assume the repository has all the nodes in destination, or
1309 default-push/default if no destination is specified.
1309 default-push/default if no destination is specified.
1310
1310
1311 You can change bundle format with the -t/--type option. You can
1311 You can change bundle format with the -t/--type option. You can
1312 specify a compression, a bundle version or both using a dash
1312 specify a compression, a bundle version or both using a dash
1313 (comp-version). The available compression methods are: none, bzip2,
1313 (comp-version). The available compression methods are: none, bzip2,
1314 and gzip (by default, bundles are compressed using bzip2). The
1314 and gzip (by default, bundles are compressed using bzip2). The
1315 available formats are: v1, v2 (default to most suitable).
1315 available formats are: v1, v2 (default to most suitable).
1316
1316
1317 The bundle file can then be transferred using conventional means
1317 The bundle file can then be transferred using conventional means
1318 and applied to another repository with the unbundle or pull
1318 and applied to another repository with the unbundle or pull
1319 command. This is useful when direct push and pull are not
1319 command. This is useful when direct push and pull are not
1320 available or when exporting an entire repository is undesirable.
1320 available or when exporting an entire repository is undesirable.
1321
1321
1322 Applying bundles preserves all changeset contents including
1322 Applying bundles preserves all changeset contents including
1323 permissions, copy/rename information, and revision history.
1323 permissions, copy/rename information, and revision history.
1324
1324
1325 Returns 0 on success, 1 if no changes found.
1325 Returns 0 on success, 1 if no changes found.
1326 """
1326 """
1327 revs = None
1327 revs = None
1328 if 'rev' in opts:
1328 if 'rev' in opts:
1329 revs = scmutil.revrange(repo, opts['rev'])
1329 revs = scmutil.revrange(repo, opts['rev'])
1330
1330
1331 bundletype = opts.get('type', 'bzip2').lower()
1331 bundletype = opts.get('type', 'bzip2').lower()
1332 try:
1332 try:
1333 bcompression, cgversion, params = exchange.parsebundlespec(
1333 bcompression, cgversion, params = exchange.parsebundlespec(
1334 repo, bundletype, strict=False)
1334 repo, bundletype, strict=False)
1335 except error.UnsupportedBundleSpecification as e:
1335 except error.UnsupportedBundleSpecification as e:
1336 raise error.Abort(str(e),
1336 raise error.Abort(str(e),
1337 hint=_('see "hg help bundle" for supported '
1337 hint=_('see "hg help bundle" for supported '
1338 'values for --type'))
1338 'values for --type'))
1339
1339
1340 # Packed bundles are a pseudo bundle format for now.
1340 # Packed bundles are a pseudo bundle format for now.
1341 if cgversion == 's1':
1341 if cgversion == 's1':
1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1343 hint=_('use "hg debugcreatestreamclonebundle"'))
1343 hint=_('use "hg debugcreatestreamclonebundle"'))
1344
1344
1345 if opts.get('all'):
1345 if opts.get('all'):
1346 if dest:
1346 if dest:
1347 raise error.Abort(_("--all is incompatible with specifying "
1347 raise error.Abort(_("--all is incompatible with specifying "
1348 "a destination"))
1348 "a destination"))
1349 if opts.get('base'):
1349 if opts.get('base'):
1350 ui.warn(_("ignoring --base because --all was specified\n"))
1350 ui.warn(_("ignoring --base because --all was specified\n"))
1351 base = ['null']
1351 base = ['null']
1352 else:
1352 else:
1353 base = scmutil.revrange(repo, opts.get('base'))
1353 base = scmutil.revrange(repo, opts.get('base'))
1354 # TODO: get desired bundlecaps from command line.
1354 # TODO: get desired bundlecaps from command line.
1355 bundlecaps = None
1355 bundlecaps = None
1356 if base:
1356 if base:
1357 if dest:
1357 if dest:
1358 raise error.Abort(_("--base is incompatible with specifying "
1358 raise error.Abort(_("--base is incompatible with specifying "
1359 "a destination"))
1359 "a destination"))
1360 common = [repo.lookup(rev) for rev in base]
1360 common = [repo.lookup(rev) for rev in base]
1361 heads = revs and map(repo.lookup, revs) or revs
1361 heads = revs and map(repo.lookup, revs) or revs
1362 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1362 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1363 common=common, bundlecaps=bundlecaps,
1363 common=common, bundlecaps=bundlecaps,
1364 version=cgversion)
1364 version=cgversion)
1365 outgoing = None
1365 outgoing = None
1366 else:
1366 else:
1367 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1367 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1368 dest, branches = hg.parseurl(dest, opts.get('branch'))
1368 dest, branches = hg.parseurl(dest, opts.get('branch'))
1369 other = hg.peer(repo, opts, dest)
1369 other = hg.peer(repo, opts, dest)
1370 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1370 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1371 heads = revs and map(repo.lookup, revs) or revs
1371 heads = revs and map(repo.lookup, revs) or revs
1372 outgoing = discovery.findcommonoutgoing(repo, other,
1372 outgoing = discovery.findcommonoutgoing(repo, other,
1373 onlyheads=heads,
1373 onlyheads=heads,
1374 force=opts.get('force'),
1374 force=opts.get('force'),
1375 portable=True)
1375 portable=True)
1376 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1376 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1377 bundlecaps, version=cgversion)
1377 bundlecaps, version=cgversion)
1378 if not cg:
1378 if not cg:
1379 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1379 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1380 return 1
1380 return 1
1381
1381
1382 if cgversion == '01': #bundle1
1382 if cgversion == '01': #bundle1
1383 if bcompression is None:
1383 if bcompression is None:
1384 bcompression = 'UN'
1384 bcompression = 'UN'
1385 bversion = 'HG10' + bcompression
1385 bversion = 'HG10' + bcompression
1386 bcompression = None
1386 bcompression = None
1387 else:
1387 else:
1388 assert cgversion == '02'
1388 assert cgversion == '02'
1389 bversion = 'HG20'
1389 bversion = 'HG20'
1390
1390
1391
1391
1392 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1392 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1393
1393
1394 @command('cat',
1394 @command('cat',
1395 [('o', 'output', '',
1395 [('o', 'output', '',
1396 _('print output to file with formatted name'), _('FORMAT')),
1396 _('print output to file with formatted name'), _('FORMAT')),
1397 ('r', 'rev', '', _('print the given revision'), _('REV')),
1397 ('r', 'rev', '', _('print the given revision'), _('REV')),
1398 ('', 'decode', None, _('apply any matching decode filter')),
1398 ('', 'decode', None, _('apply any matching decode filter')),
1399 ] + walkopts,
1399 ] + walkopts,
1400 _('[OPTION]... FILE...'),
1400 _('[OPTION]... FILE...'),
1401 inferrepo=True)
1401 inferrepo=True)
1402 def cat(ui, repo, file1, *pats, **opts):
1402 def cat(ui, repo, file1, *pats, **opts):
1403 """output the current or given revision of files
1403 """output the current or given revision of files
1404
1404
1405 Print the specified files as they were at the given revision. If
1405 Print the specified files as they were at the given revision. If
1406 no revision is given, the parent of the working directory is used.
1406 no revision is given, the parent of the working directory is used.
1407
1407
1408 Output may be to a file, in which case the name of the file is
1408 Output may be to a file, in which case the name of the file is
1409 given using a format string. The formatting rules as follows:
1409 given using a format string. The formatting rules as follows:
1410
1410
1411 :``%%``: literal "%" character
1411 :``%%``: literal "%" character
1412 :``%s``: basename of file being printed
1412 :``%s``: basename of file being printed
1413 :``%d``: dirname of file being printed, or '.' if in repository root
1413 :``%d``: dirname of file being printed, or '.' if in repository root
1414 :``%p``: root-relative path name of file being printed
1414 :``%p``: root-relative path name of file being printed
1415 :``%H``: changeset hash (40 hexadecimal digits)
1415 :``%H``: changeset hash (40 hexadecimal digits)
1416 :``%R``: changeset revision number
1416 :``%R``: changeset revision number
1417 :``%h``: short-form changeset hash (12 hexadecimal digits)
1417 :``%h``: short-form changeset hash (12 hexadecimal digits)
1418 :``%r``: zero-padded changeset revision number
1418 :``%r``: zero-padded changeset revision number
1419 :``%b``: basename of the exporting repository
1419 :``%b``: basename of the exporting repository
1420
1420
1421 Returns 0 on success.
1421 Returns 0 on success.
1422 """
1422 """
1423 ctx = scmutil.revsingle(repo, opts.get('rev'))
1423 ctx = scmutil.revsingle(repo, opts.get('rev'))
1424 m = scmutil.match(ctx, (file1,) + pats, opts)
1424 m = scmutil.match(ctx, (file1,) + pats, opts)
1425
1425
1426 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1426 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1427
1427
1428 @command('^clone',
1428 @command('^clone',
1429 [('U', 'noupdate', None, _('the clone will include an empty working '
1429 [('U', 'noupdate', None, _('the clone will include an empty working '
1430 'directory (only a repository)')),
1430 'directory (only a repository)')),
1431 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1431 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1432 _('REV')),
1432 _('REV')),
1433 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1433 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1434 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1434 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1435 ('', 'pull', None, _('use pull protocol to copy metadata')),
1435 ('', 'pull', None, _('use pull protocol to copy metadata')),
1436 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1436 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1437 ] + remoteopts,
1437 ] + remoteopts,
1438 _('[OPTION]... SOURCE [DEST]'),
1438 _('[OPTION]... SOURCE [DEST]'),
1439 norepo=True)
1439 norepo=True)
1440 def clone(ui, source, dest=None, **opts):
1440 def clone(ui, source, dest=None, **opts):
1441 """make a copy of an existing repository
1441 """make a copy of an existing repository
1442
1442
1443 Create a copy of an existing repository in a new directory.
1443 Create a copy of an existing repository in a new directory.
1444
1444
1445 If no destination directory name is specified, it defaults to the
1445 If no destination directory name is specified, it defaults to the
1446 basename of the source.
1446 basename of the source.
1447
1447
1448 The location of the source is added to the new repository's
1448 The location of the source is added to the new repository's
1449 ``.hg/hgrc`` file, as the default to be used for future pulls.
1449 ``.hg/hgrc`` file, as the default to be used for future pulls.
1450
1450
1451 Only local paths and ``ssh://`` URLs are supported as
1451 Only local paths and ``ssh://`` URLs are supported as
1452 destinations. For ``ssh://`` destinations, no working directory or
1452 destinations. For ``ssh://`` destinations, no working directory or
1453 ``.hg/hgrc`` will be created on the remote side.
1453 ``.hg/hgrc`` will be created on the remote side.
1454
1454
1455 If the source repository has a bookmark called '@' set, that
1455 If the source repository has a bookmark called '@' set, that
1456 revision will be checked out in the new repository by default.
1456 revision will be checked out in the new repository by default.
1457
1457
1458 To check out a particular version, use -u/--update, or
1458 To check out a particular version, use -u/--update, or
1459 -U/--noupdate to create a clone with no working directory.
1459 -U/--noupdate to create a clone with no working directory.
1460
1460
1461 To pull only a subset of changesets, specify one or more revisions
1461 To pull only a subset of changesets, specify one or more revisions
1462 identifiers with -r/--rev or branches with -b/--branch. The
1462 identifiers with -r/--rev or branches with -b/--branch. The
1463 resulting clone will contain only the specified changesets and
1463 resulting clone will contain only the specified changesets and
1464 their ancestors. These options (or 'clone src#rev dest') imply
1464 their ancestors. These options (or 'clone src#rev dest') imply
1465 --pull, even for local source repositories.
1465 --pull, even for local source repositories.
1466
1466
1467 .. note::
1467 .. note::
1468
1468
1469 Specifying a tag will include the tagged changeset but not the
1469 Specifying a tag will include the tagged changeset but not the
1470 changeset containing the tag.
1470 changeset containing the tag.
1471
1471
1472 .. container:: verbose
1472 .. container:: verbose
1473
1473
1474 For efficiency, hardlinks are used for cloning whenever the
1474 For efficiency, hardlinks are used for cloning whenever the
1475 source and destination are on the same filesystem (note this
1475 source and destination are on the same filesystem (note this
1476 applies only to the repository data, not to the working
1476 applies only to the repository data, not to the working
1477 directory). Some filesystems, such as AFS, implement hardlinking
1477 directory). Some filesystems, such as AFS, implement hardlinking
1478 incorrectly, but do not report errors. In these cases, use the
1478 incorrectly, but do not report errors. In these cases, use the
1479 --pull option to avoid hardlinking.
1479 --pull option to avoid hardlinking.
1480
1480
1481 In some cases, you can clone repositories and the working
1481 In some cases, you can clone repositories and the working
1482 directory using full hardlinks with ::
1482 directory using full hardlinks with ::
1483
1483
1484 $ cp -al REPO REPOCLONE
1484 $ cp -al REPO REPOCLONE
1485
1485
1486 This is the fastest way to clone, but it is not always safe. The
1486 This is the fastest way to clone, but it is not always safe. The
1487 operation is not atomic (making sure REPO is not modified during
1487 operation is not atomic (making sure REPO is not modified during
1488 the operation is up to you) and you have to make sure your
1488 the operation is up to you) and you have to make sure your
1489 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1489 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1490 so). Also, this is not compatible with certain extensions that
1490 so). Also, this is not compatible with certain extensions that
1491 place their metadata under the .hg directory, such as mq.
1491 place their metadata under the .hg directory, such as mq.
1492
1492
1493 Mercurial will update the working directory to the first applicable
1493 Mercurial will update the working directory to the first applicable
1494 revision from this list:
1494 revision from this list:
1495
1495
1496 a) null if -U or the source repository has no changesets
1496 a) null if -U or the source repository has no changesets
1497 b) if -u . and the source repository is local, the first parent of
1497 b) if -u . and the source repository is local, the first parent of
1498 the source repository's working directory
1498 the source repository's working directory
1499 c) the changeset specified with -u (if a branch name, this means the
1499 c) the changeset specified with -u (if a branch name, this means the
1500 latest head of that branch)
1500 latest head of that branch)
1501 d) the changeset specified with -r
1501 d) the changeset specified with -r
1502 e) the tipmost head specified with -b
1502 e) the tipmost head specified with -b
1503 f) the tipmost head specified with the url#branch source syntax
1503 f) the tipmost head specified with the url#branch source syntax
1504 g) the revision marked with the '@' bookmark, if present
1504 g) the revision marked with the '@' bookmark, if present
1505 h) the tipmost head of the default branch
1505 h) the tipmost head of the default branch
1506 i) tip
1506 i) tip
1507
1507
1508 Examples:
1508 Examples:
1509
1509
1510 - clone a remote repository to a new directory named hg/::
1510 - clone a remote repository to a new directory named hg/::
1511
1511
1512 hg clone http://selenic.com/hg
1512 hg clone http://selenic.com/hg
1513
1513
1514 - create a lightweight local clone::
1514 - create a lightweight local clone::
1515
1515
1516 hg clone project/ project-feature/
1516 hg clone project/ project-feature/
1517
1517
1518 - clone from an absolute path on an ssh server (note double-slash)::
1518 - clone from an absolute path on an ssh server (note double-slash)::
1519
1519
1520 hg clone ssh://user@server//home/projects/alpha/
1520 hg clone ssh://user@server//home/projects/alpha/
1521
1521
1522 - do a high-speed clone over a LAN while checking out a
1522 - do a high-speed clone over a LAN while checking out a
1523 specified version::
1523 specified version::
1524
1524
1525 hg clone --uncompressed http://server/repo -u 1.5
1525 hg clone --uncompressed http://server/repo -u 1.5
1526
1526
1527 - create a repository without changesets after a particular revision::
1527 - create a repository without changesets after a particular revision::
1528
1528
1529 hg clone -r 04e544 experimental/ good/
1529 hg clone -r 04e544 experimental/ good/
1530
1530
1531 - clone (and track) a particular named branch::
1531 - clone (and track) a particular named branch::
1532
1532
1533 hg clone http://selenic.com/hg#stable
1533 hg clone http://selenic.com/hg#stable
1534
1534
1535 See :hg:`help urls` for details on specifying URLs.
1535 See :hg:`help urls` for details on specifying URLs.
1536
1536
1537 Returns 0 on success.
1537 Returns 0 on success.
1538 """
1538 """
1539 if opts.get('noupdate') and opts.get('updaterev'):
1539 if opts.get('noupdate') and opts.get('updaterev'):
1540 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1540 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1541
1541
1542 r = hg.clone(ui, opts, source, dest,
1542 r = hg.clone(ui, opts, source, dest,
1543 pull=opts.get('pull'),
1543 pull=opts.get('pull'),
1544 stream=opts.get('uncompressed'),
1544 stream=opts.get('uncompressed'),
1545 rev=opts.get('rev'),
1545 rev=opts.get('rev'),
1546 update=opts.get('updaterev') or not opts.get('noupdate'),
1546 update=opts.get('updaterev') or not opts.get('noupdate'),
1547 branch=opts.get('branch'),
1547 branch=opts.get('branch'),
1548 shareopts=opts.get('shareopts'))
1548 shareopts=opts.get('shareopts'))
1549
1549
1550 return r is None
1550 return r is None
1551
1551
1552 @command('^commit|ci',
1552 @command('^commit|ci',
1553 [('A', 'addremove', None,
1553 [('A', 'addremove', None,
1554 _('mark new/missing files as added/removed before committing')),
1554 _('mark new/missing files as added/removed before committing')),
1555 ('', 'close-branch', None,
1555 ('', 'close-branch', None,
1556 _('mark a branch head as closed')),
1556 _('mark a branch head as closed')),
1557 ('', 'amend', None, _('amend the parent of the working directory')),
1557 ('', 'amend', None, _('amend the parent of the working directory')),
1558 ('s', 'secret', None, _('use the secret phase for committing')),
1558 ('s', 'secret', None, _('use the secret phase for committing')),
1559 ('e', 'edit', None, _('invoke editor on commit messages')),
1559 ('e', 'edit', None, _('invoke editor on commit messages')),
1560 ('i', 'interactive', None, _('use interactive mode')),
1560 ('i', 'interactive', None, _('use interactive mode')),
1561 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1561 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1562 _('[OPTION]... [FILE]...'),
1562 _('[OPTION]... [FILE]...'),
1563 inferrepo=True)
1563 inferrepo=True)
1564 def commit(ui, repo, *pats, **opts):
1564 def commit(ui, repo, *pats, **opts):
1565 """commit the specified files or all outstanding changes
1565 """commit the specified files or all outstanding changes
1566
1566
1567 Commit changes to the given files into the repository. Unlike a
1567 Commit changes to the given files into the repository. Unlike a
1568 centralized SCM, this operation is a local operation. See
1568 centralized SCM, this operation is a local operation. See
1569 :hg:`push` for a way to actively distribute your changes.
1569 :hg:`push` for a way to actively distribute your changes.
1570
1570
1571 If a list of files is omitted, all changes reported by :hg:`status`
1571 If a list of files is omitted, all changes reported by :hg:`status`
1572 will be committed.
1572 will be committed.
1573
1573
1574 If you are committing the result of a merge, do not provide any
1574 If you are committing the result of a merge, do not provide any
1575 filenames or -I/-X filters.
1575 filenames or -I/-X filters.
1576
1576
1577 If no commit message is specified, Mercurial starts your
1577 If no commit message is specified, Mercurial starts your
1578 configured editor where you can enter a message. In case your
1578 configured editor where you can enter a message. In case your
1579 commit fails, you will find a backup of your message in
1579 commit fails, you will find a backup of your message in
1580 ``.hg/last-message.txt``.
1580 ``.hg/last-message.txt``.
1581
1581
1582 The --close-branch flag can be used to mark the current branch
1582 The --close-branch flag can be used to mark the current branch
1583 head closed. When all heads of a branch are closed, the branch
1583 head closed. When all heads of a branch are closed, the branch
1584 will be considered closed and no longer listed.
1584 will be considered closed and no longer listed.
1585
1585
1586 The --amend flag can be used to amend the parent of the
1586 The --amend flag can be used to amend the parent of the
1587 working directory with a new commit that contains the changes
1587 working directory with a new commit that contains the changes
1588 in the parent in addition to those currently reported by :hg:`status`,
1588 in the parent in addition to those currently reported by :hg:`status`,
1589 if there are any. The old commit is stored in a backup bundle in
1589 if there are any. The old commit is stored in a backup bundle in
1590 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1590 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1591 on how to restore it).
1591 on how to restore it).
1592
1592
1593 Message, user and date are taken from the amended commit unless
1593 Message, user and date are taken from the amended commit unless
1594 specified. When a message isn't specified on the command line,
1594 specified. When a message isn't specified on the command line,
1595 the editor will open with the message of the amended commit.
1595 the editor will open with the message of the amended commit.
1596
1596
1597 It is not possible to amend public changesets (see :hg:`help phases`)
1597 It is not possible to amend public changesets (see :hg:`help phases`)
1598 or changesets that have children.
1598 or changesets that have children.
1599
1599
1600 See :hg:`help dates` for a list of formats valid for -d/--date.
1600 See :hg:`help dates` for a list of formats valid for -d/--date.
1601
1601
1602 Returns 0 on success, 1 if nothing changed.
1602 Returns 0 on success, 1 if nothing changed.
1603
1603
1604 .. container:: verbose
1604 .. container:: verbose
1605
1605
1606 Examples:
1606 Examples:
1607
1607
1608 - commit all files ending in .py::
1608 - commit all files ending in .py::
1609
1609
1610 hg commit --include "set:**.py"
1610 hg commit --include "set:**.py"
1611
1611
1612 - commit all non-binary files::
1612 - commit all non-binary files::
1613
1613
1614 hg commit --exclude "set:binary()"
1614 hg commit --exclude "set:binary()"
1615
1615
1616 - amend the current commit and set the date to now::
1616 - amend the current commit and set the date to now::
1617
1617
1618 hg commit --amend --date now
1618 hg commit --amend --date now
1619 """
1619 """
1620 wlock = lock = None
1620 wlock = lock = None
1621 try:
1621 try:
1622 wlock = repo.wlock()
1622 wlock = repo.wlock()
1623 lock = repo.lock()
1623 lock = repo.lock()
1624 return _docommit(ui, repo, *pats, **opts)
1624 return _docommit(ui, repo, *pats, **opts)
1625 finally:
1625 finally:
1626 release(lock, wlock)
1626 release(lock, wlock)
1627
1627
1628 def _docommit(ui, repo, *pats, **opts):
1628 def _docommit(ui, repo, *pats, **opts):
1629 if opts.get('interactive'):
1629 if opts.get('interactive'):
1630 opts.pop('interactive')
1630 opts.pop('interactive')
1631 cmdutil.dorecord(ui, repo, commit, None, False,
1631 cmdutil.dorecord(ui, repo, commit, None, False,
1632 cmdutil.recordfilter, *pats, **opts)
1632 cmdutil.recordfilter, *pats, **opts)
1633 return
1633 return
1634
1634
1635 if opts.get('subrepos'):
1635 if opts.get('subrepos'):
1636 if opts.get('amend'):
1636 if opts.get('amend'):
1637 raise error.Abort(_('cannot amend with --subrepos'))
1637 raise error.Abort(_('cannot amend with --subrepos'))
1638 # Let --subrepos on the command line override config setting.
1638 # Let --subrepos on the command line override config setting.
1639 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1639 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1640
1640
1641 cmdutil.checkunfinished(repo, commit=True)
1641 cmdutil.checkunfinished(repo, commit=True)
1642
1642
1643 branch = repo[None].branch()
1643 branch = repo[None].branch()
1644 bheads = repo.branchheads(branch)
1644 bheads = repo.branchheads(branch)
1645
1645
1646 extra = {}
1646 extra = {}
1647 if opts.get('close_branch'):
1647 if opts.get('close_branch'):
1648 extra['close'] = 1
1648 extra['close'] = 1
1649
1649
1650 if not bheads:
1650 if not bheads:
1651 raise error.Abort(_('can only close branch heads'))
1651 raise error.Abort(_('can only close branch heads'))
1652 elif opts.get('amend'):
1652 elif opts.get('amend'):
1653 if repo[None].parents()[0].p1().branch() != branch and \
1653 if repo[None].parents()[0].p1().branch() != branch and \
1654 repo[None].parents()[0].p2().branch() != branch:
1654 repo[None].parents()[0].p2().branch() != branch:
1655 raise error.Abort(_('can only close branch heads'))
1655 raise error.Abort(_('can only close branch heads'))
1656
1656
1657 if opts.get('amend'):
1657 if opts.get('amend'):
1658 if ui.configbool('ui', 'commitsubrepos'):
1658 if ui.configbool('ui', 'commitsubrepos'):
1659 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1659 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1660
1660
1661 old = repo['.']
1661 old = repo['.']
1662 if not old.mutable():
1662 if not old.mutable():
1663 raise error.Abort(_('cannot amend public changesets'))
1663 raise error.Abort(_('cannot amend public changesets'))
1664 if len(repo[None].parents()) > 1:
1664 if len(repo[None].parents()) > 1:
1665 raise error.Abort(_('cannot amend while merging'))
1665 raise error.Abort(_('cannot amend while merging'))
1666 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1666 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1667 if not allowunstable and old.children():
1667 if not allowunstable and old.children():
1668 raise error.Abort(_('cannot amend changeset with children'))
1668 raise error.Abort(_('cannot amend changeset with children'))
1669
1669
1670 newextra = extra.copy()
1670 newextra = extra.copy()
1671 newextra['branch'] = branch
1671 newextra['branch'] = branch
1672 extra = newextra
1672 extra = newextra
1673 # commitfunc is used only for temporary amend commit by cmdutil.amend
1673 # commitfunc is used only for temporary amend commit by cmdutil.amend
1674 def commitfunc(ui, repo, message, match, opts):
1674 def commitfunc(ui, repo, message, match, opts):
1675 return repo.commit(message,
1675 return repo.commit(message,
1676 opts.get('user') or old.user(),
1676 opts.get('user') or old.user(),
1677 opts.get('date') or old.date(),
1677 opts.get('date') or old.date(),
1678 match,
1678 match,
1679 extra=extra)
1679 extra=extra)
1680
1680
1681 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1681 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1682 if node == old.node():
1682 if node == old.node():
1683 ui.status(_("nothing changed\n"))
1683 ui.status(_("nothing changed\n"))
1684 return 1
1684 return 1
1685 else:
1685 else:
1686 def commitfunc(ui, repo, message, match, opts):
1686 def commitfunc(ui, repo, message, match, opts):
1687 backup = ui.backupconfig('phases', 'new-commit')
1687 backup = ui.backupconfig('phases', 'new-commit')
1688 baseui = repo.baseui
1688 baseui = repo.baseui
1689 basebackup = baseui.backupconfig('phases', 'new-commit')
1689 basebackup = baseui.backupconfig('phases', 'new-commit')
1690 try:
1690 try:
1691 if opts.get('secret'):
1691 if opts.get('secret'):
1692 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1692 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1693 # Propagate to subrepos
1693 # Propagate to subrepos
1694 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1694 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1695
1695
1696 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1696 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1697 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1697 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1698 return repo.commit(message, opts.get('user'), opts.get('date'),
1698 return repo.commit(message, opts.get('user'), opts.get('date'),
1699 match,
1699 match,
1700 editor=editor,
1700 editor=editor,
1701 extra=extra)
1701 extra=extra)
1702 finally:
1702 finally:
1703 ui.restoreconfig(backup)
1703 ui.restoreconfig(backup)
1704 repo.baseui.restoreconfig(basebackup)
1704 repo.baseui.restoreconfig(basebackup)
1705
1705
1706
1706
1707 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1707 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1708
1708
1709 if not node:
1709 if not node:
1710 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1710 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1711 if stat[3]:
1711 if stat[3]:
1712 ui.status(_("nothing changed (%d missing files, see "
1712 ui.status(_("nothing changed (%d missing files, see "
1713 "'hg status')\n") % len(stat[3]))
1713 "'hg status')\n") % len(stat[3]))
1714 else:
1714 else:
1715 ui.status(_("nothing changed\n"))
1715 ui.status(_("nothing changed\n"))
1716 return 1
1716 return 1
1717
1717
1718 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1718 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1719
1719
1720 @command('config|showconfig|debugconfig',
1720 @command('config|showconfig|debugconfig',
1721 [('u', 'untrusted', None, _('show untrusted configuration options')),
1721 [('u', 'untrusted', None, _('show untrusted configuration options')),
1722 ('e', 'edit', None, _('edit user config')),
1722 ('e', 'edit', None, _('edit user config')),
1723 ('l', 'local', None, _('edit repository config')),
1723 ('l', 'local', None, _('edit repository config')),
1724 ('g', 'global', None, _('edit global config'))],
1724 ('g', 'global', None, _('edit global config'))],
1725 _('[-u] [NAME]...'),
1725 _('[-u] [NAME]...'),
1726 optionalrepo=True)
1726 optionalrepo=True)
1727 def config(ui, repo, *values, **opts):
1727 def config(ui, repo, *values, **opts):
1728 """show combined config settings from all hgrc files
1728 """show combined config settings from all hgrc files
1729
1729
1730 With no arguments, print names and values of all config items.
1730 With no arguments, print names and values of all config items.
1731
1731
1732 With one argument of the form section.name, print just the value
1732 With one argument of the form section.name, print just the value
1733 of that config item.
1733 of that config item.
1734
1734
1735 With multiple arguments, print names and values of all config
1735 With multiple arguments, print names and values of all config
1736 items with matching section names.
1736 items with matching section names.
1737
1737
1738 With --edit, start an editor on the user-level config file. With
1738 With --edit, start an editor on the user-level config file. With
1739 --global, edit the system-wide config file. With --local, edit the
1739 --global, edit the system-wide config file. With --local, edit the
1740 repository-level config file.
1740 repository-level config file.
1741
1741
1742 With --debug, the source (filename and line number) is printed
1742 With --debug, the source (filename and line number) is printed
1743 for each config item.
1743 for each config item.
1744
1744
1745 See :hg:`help config` for more information about config files.
1745 See :hg:`help config` for more information about config files.
1746
1746
1747 Returns 0 on success, 1 if NAME does not exist.
1747 Returns 0 on success, 1 if NAME does not exist.
1748
1748
1749 """
1749 """
1750
1750
1751 if opts.get('edit') or opts.get('local') or opts.get('global'):
1751 if opts.get('edit') or opts.get('local') or opts.get('global'):
1752 if opts.get('local') and opts.get('global'):
1752 if opts.get('local') and opts.get('global'):
1753 raise error.Abort(_("can't use --local and --global together"))
1753 raise error.Abort(_("can't use --local and --global together"))
1754
1754
1755 if opts.get('local'):
1755 if opts.get('local'):
1756 if not repo:
1756 if not repo:
1757 raise error.Abort(_("can't use --local outside a repository"))
1757 raise error.Abort(_("can't use --local outside a repository"))
1758 paths = [repo.join('hgrc')]
1758 paths = [repo.join('hgrc')]
1759 elif opts.get('global'):
1759 elif opts.get('global'):
1760 paths = scmutil.systemrcpath()
1760 paths = scmutil.systemrcpath()
1761 else:
1761 else:
1762 paths = scmutil.userrcpath()
1762 paths = scmutil.userrcpath()
1763
1763
1764 for f in paths:
1764 for f in paths:
1765 if os.path.exists(f):
1765 if os.path.exists(f):
1766 break
1766 break
1767 else:
1767 else:
1768 if opts.get('global'):
1768 if opts.get('global'):
1769 samplehgrc = uimod.samplehgrcs['global']
1769 samplehgrc = uimod.samplehgrcs['global']
1770 elif opts.get('local'):
1770 elif opts.get('local'):
1771 samplehgrc = uimod.samplehgrcs['local']
1771 samplehgrc = uimod.samplehgrcs['local']
1772 else:
1772 else:
1773 samplehgrc = uimod.samplehgrcs['user']
1773 samplehgrc = uimod.samplehgrcs['user']
1774
1774
1775 f = paths[0]
1775 f = paths[0]
1776 fp = open(f, "w")
1776 fp = open(f, "w")
1777 fp.write(samplehgrc)
1777 fp.write(samplehgrc)
1778 fp.close()
1778 fp.close()
1779
1779
1780 editor = ui.geteditor()
1780 editor = ui.geteditor()
1781 ui.system("%s \"%s\"" % (editor, f),
1781 ui.system("%s \"%s\"" % (editor, f),
1782 onerr=error.Abort, errprefix=_("edit failed"))
1782 onerr=error.Abort, errprefix=_("edit failed"))
1783 return
1783 return
1784
1784
1785 for f in scmutil.rcpath():
1785 for f in scmutil.rcpath():
1786 ui.debug('read config from: %s\n' % f)
1786 ui.debug('read config from: %s\n' % f)
1787 untrusted = bool(opts.get('untrusted'))
1787 untrusted = bool(opts.get('untrusted'))
1788 if values:
1788 if values:
1789 sections = [v for v in values if '.' not in v]
1789 sections = [v for v in values if '.' not in v]
1790 items = [v for v in values if '.' in v]
1790 items = [v for v in values if '.' in v]
1791 if len(items) > 1 or items and sections:
1791 if len(items) > 1 or items and sections:
1792 raise error.Abort(_('only one config item permitted'))
1792 raise error.Abort(_('only one config item permitted'))
1793 matched = False
1793 matched = False
1794 for section, name, value in ui.walkconfig(untrusted=untrusted):
1794 for section, name, value in ui.walkconfig(untrusted=untrusted):
1795 value = str(value).replace('\n', '\\n')
1795 value = str(value).replace('\n', '\\n')
1796 sectname = section + '.' + name
1796 sectname = section + '.' + name
1797 if values:
1797 if values:
1798 for v in values:
1798 for v in values:
1799 if v == section:
1799 if v == section:
1800 ui.debug('%s: ' %
1800 ui.debug('%s: ' %
1801 ui.configsource(section, name, untrusted))
1801 ui.configsource(section, name, untrusted))
1802 ui.write('%s=%s\n' % (sectname, value))
1802 ui.write('%s=%s\n' % (sectname, value))
1803 matched = True
1803 matched = True
1804 elif v == sectname:
1804 elif v == sectname:
1805 ui.debug('%s: ' %
1805 ui.debug('%s: ' %
1806 ui.configsource(section, name, untrusted))
1806 ui.configsource(section, name, untrusted))
1807 ui.write(value, '\n')
1807 ui.write(value, '\n')
1808 matched = True
1808 matched = True
1809 else:
1809 else:
1810 ui.debug('%s: ' %
1810 ui.debug('%s: ' %
1811 ui.configsource(section, name, untrusted))
1811 ui.configsource(section, name, untrusted))
1812 ui.write('%s=%s\n' % (sectname, value))
1812 ui.write('%s=%s\n' % (sectname, value))
1813 matched = True
1813 matched = True
1814 if matched:
1814 if matched:
1815 return 0
1815 return 0
1816 return 1
1816 return 1
1817
1817
1818 @command('copy|cp',
1818 @command('copy|cp',
1819 [('A', 'after', None, _('record a copy that has already occurred')),
1819 [('A', 'after', None, _('record a copy that has already occurred')),
1820 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1820 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1821 ] + walkopts + dryrunopts,
1821 ] + walkopts + dryrunopts,
1822 _('[OPTION]... [SOURCE]... DEST'))
1822 _('[OPTION]... [SOURCE]... DEST'))
1823 def copy(ui, repo, *pats, **opts):
1823 def copy(ui, repo, *pats, **opts):
1824 """mark files as copied for the next commit
1824 """mark files as copied for the next commit
1825
1825
1826 Mark dest as having copies of source files. If dest is a
1826 Mark dest as having copies of source files. If dest is a
1827 directory, copies are put in that directory. If dest is a file,
1827 directory, copies are put in that directory. If dest is a file,
1828 the source must be a single file.
1828 the source must be a single file.
1829
1829
1830 By default, this command copies the contents of files as they
1830 By default, this command copies the contents of files as they
1831 exist in the working directory. If invoked with -A/--after, the
1831 exist in the working directory. If invoked with -A/--after, the
1832 operation is recorded, but no copying is performed.
1832 operation is recorded, but no copying is performed.
1833
1833
1834 This command takes effect with the next commit. To undo a copy
1834 This command takes effect with the next commit. To undo a copy
1835 before that, see :hg:`revert`.
1835 before that, see :hg:`revert`.
1836
1836
1837 Returns 0 on success, 1 if errors are encountered.
1837 Returns 0 on success, 1 if errors are encountered.
1838 """
1838 """
1839 wlock = repo.wlock(False)
1839 wlock = repo.wlock(False)
1840 try:
1840 try:
1841 return cmdutil.copy(ui, repo, pats, opts)
1841 return cmdutil.copy(ui, repo, pats, opts)
1842 finally:
1842 finally:
1843 wlock.release()
1843 wlock.release()
1844
1844
1845 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1845 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1846 def debugancestor(ui, repo, *args):
1846 def debugancestor(ui, repo, *args):
1847 """find the ancestor revision of two revisions in a given index"""
1847 """find the ancestor revision of two revisions in a given index"""
1848 if len(args) == 3:
1848 if len(args) == 3:
1849 index, rev1, rev2 = args
1849 index, rev1, rev2 = args
1850 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1850 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1851 lookup = r.lookup
1851 lookup = r.lookup
1852 elif len(args) == 2:
1852 elif len(args) == 2:
1853 if not repo:
1853 if not repo:
1854 raise error.Abort(_("there is no Mercurial repository here "
1854 raise error.Abort(_("there is no Mercurial repository here "
1855 "(.hg not found)"))
1855 "(.hg not found)"))
1856 rev1, rev2 = args
1856 rev1, rev2 = args
1857 r = repo.changelog
1857 r = repo.changelog
1858 lookup = repo.lookup
1858 lookup = repo.lookup
1859 else:
1859 else:
1860 raise error.Abort(_('either two or three arguments required'))
1860 raise error.Abort(_('either two or three arguments required'))
1861 a = r.ancestor(lookup(rev1), lookup(rev2))
1861 a = r.ancestor(lookup(rev1), lookup(rev2))
1862 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1862 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1863
1863
1864 @command('debugbuilddag',
1864 @command('debugbuilddag',
1865 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1865 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1866 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1866 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1867 ('n', 'new-file', None, _('add new file at each rev'))],
1867 ('n', 'new-file', None, _('add new file at each rev'))],
1868 _('[OPTION]... [TEXT]'))
1868 _('[OPTION]... [TEXT]'))
1869 def debugbuilddag(ui, repo, text=None,
1869 def debugbuilddag(ui, repo, text=None,
1870 mergeable_file=False,
1870 mergeable_file=False,
1871 overwritten_file=False,
1871 overwritten_file=False,
1872 new_file=False):
1872 new_file=False):
1873 """builds a repo with a given DAG from scratch in the current empty repo
1873 """builds a repo with a given DAG from scratch in the current empty repo
1874
1874
1875 The description of the DAG is read from stdin if not given on the
1875 The description of the DAG is read from stdin if not given on the
1876 command line.
1876 command line.
1877
1877
1878 Elements:
1878 Elements:
1879
1879
1880 - "+n" is a linear run of n nodes based on the current default parent
1880 - "+n" is a linear run of n nodes based on the current default parent
1881 - "." is a single node based on the current default parent
1881 - "." is a single node based on the current default parent
1882 - "$" resets the default parent to null (implied at the start);
1882 - "$" resets the default parent to null (implied at the start);
1883 otherwise the default parent is always the last node created
1883 otherwise the default parent is always the last node created
1884 - "<p" sets the default parent to the backref p
1884 - "<p" sets the default parent to the backref p
1885 - "*p" is a fork at parent p, which is a backref
1885 - "*p" is a fork at parent p, which is a backref
1886 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1886 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1887 - "/p2" is a merge of the preceding node and p2
1887 - "/p2" is a merge of the preceding node and p2
1888 - ":tag" defines a local tag for the preceding node
1888 - ":tag" defines a local tag for the preceding node
1889 - "@branch" sets the named branch for subsequent nodes
1889 - "@branch" sets the named branch for subsequent nodes
1890 - "#...\\n" is a comment up to the end of the line
1890 - "#...\\n" is a comment up to the end of the line
1891
1891
1892 Whitespace between the above elements is ignored.
1892 Whitespace between the above elements is ignored.
1893
1893
1894 A backref is either
1894 A backref is either
1895
1895
1896 - a number n, which references the node curr-n, where curr is the current
1896 - a number n, which references the node curr-n, where curr is the current
1897 node, or
1897 node, or
1898 - the name of a local tag you placed earlier using ":tag", or
1898 - the name of a local tag you placed earlier using ":tag", or
1899 - empty to denote the default parent.
1899 - empty to denote the default parent.
1900
1900
1901 All string valued-elements are either strictly alphanumeric, or must
1901 All string valued-elements are either strictly alphanumeric, or must
1902 be enclosed in double quotes ("..."), with "\\" as escape character.
1902 be enclosed in double quotes ("..."), with "\\" as escape character.
1903 """
1903 """
1904
1904
1905 if text is None:
1905 if text is None:
1906 ui.status(_("reading DAG from stdin\n"))
1906 ui.status(_("reading DAG from stdin\n"))
1907 text = ui.fin.read()
1907 text = ui.fin.read()
1908
1908
1909 cl = repo.changelog
1909 cl = repo.changelog
1910 if len(cl) > 0:
1910 if len(cl) > 0:
1911 raise error.Abort(_('repository is not empty'))
1911 raise error.Abort(_('repository is not empty'))
1912
1912
1913 # determine number of revs in DAG
1913 # determine number of revs in DAG
1914 total = 0
1914 total = 0
1915 for type, data in dagparser.parsedag(text):
1915 for type, data in dagparser.parsedag(text):
1916 if type == 'n':
1916 if type == 'n':
1917 total += 1
1917 total += 1
1918
1918
1919 if mergeable_file:
1919 if mergeable_file:
1920 linesperrev = 2
1920 linesperrev = 2
1921 # make a file with k lines per rev
1921 # make a file with k lines per rev
1922 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1922 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1923 initialmergedlines.append("")
1923 initialmergedlines.append("")
1924
1924
1925 tags = []
1925 tags = []
1926
1926
1927 lock = tr = None
1927 lock = tr = None
1928 try:
1928 try:
1929 lock = repo.lock()
1929 lock = repo.lock()
1930 tr = repo.transaction("builddag")
1930 tr = repo.transaction("builddag")
1931
1931
1932 at = -1
1932 at = -1
1933 atbranch = 'default'
1933 atbranch = 'default'
1934 nodeids = []
1934 nodeids = []
1935 id = 0
1935 id = 0
1936 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1936 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1937 for type, data in dagparser.parsedag(text):
1937 for type, data in dagparser.parsedag(text):
1938 if type == 'n':
1938 if type == 'n':
1939 ui.note(('node %s\n' % str(data)))
1939 ui.note(('node %s\n' % str(data)))
1940 id, ps = data
1940 id, ps = data
1941
1941
1942 files = []
1942 files = []
1943 fctxs = {}
1943 fctxs = {}
1944
1944
1945 p2 = None
1945 p2 = None
1946 if mergeable_file:
1946 if mergeable_file:
1947 fn = "mf"
1947 fn = "mf"
1948 p1 = repo[ps[0]]
1948 p1 = repo[ps[0]]
1949 if len(ps) > 1:
1949 if len(ps) > 1:
1950 p2 = repo[ps[1]]
1950 p2 = repo[ps[1]]
1951 pa = p1.ancestor(p2)
1951 pa = p1.ancestor(p2)
1952 base, local, other = [x[fn].data() for x in (pa, p1,
1952 base, local, other = [x[fn].data() for x in (pa, p1,
1953 p2)]
1953 p2)]
1954 m3 = simplemerge.Merge3Text(base, local, other)
1954 m3 = simplemerge.Merge3Text(base, local, other)
1955 ml = [l.strip() for l in m3.merge_lines()]
1955 ml = [l.strip() for l in m3.merge_lines()]
1956 ml.append("")
1956 ml.append("")
1957 elif at > 0:
1957 elif at > 0:
1958 ml = p1[fn].data().split("\n")
1958 ml = p1[fn].data().split("\n")
1959 else:
1959 else:
1960 ml = initialmergedlines
1960 ml = initialmergedlines
1961 ml[id * linesperrev] += " r%i" % id
1961 ml[id * linesperrev] += " r%i" % id
1962 mergedtext = "\n".join(ml)
1962 mergedtext = "\n".join(ml)
1963 files.append(fn)
1963 files.append(fn)
1964 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1964 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1965
1965
1966 if overwritten_file:
1966 if overwritten_file:
1967 fn = "of"
1967 fn = "of"
1968 files.append(fn)
1968 files.append(fn)
1969 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1969 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1970
1970
1971 if new_file:
1971 if new_file:
1972 fn = "nf%i" % id
1972 fn = "nf%i" % id
1973 files.append(fn)
1973 files.append(fn)
1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1975 if len(ps) > 1:
1975 if len(ps) > 1:
1976 if not p2:
1976 if not p2:
1977 p2 = repo[ps[1]]
1977 p2 = repo[ps[1]]
1978 for fn in p2:
1978 for fn in p2:
1979 if fn.startswith("nf"):
1979 if fn.startswith("nf"):
1980 files.append(fn)
1980 files.append(fn)
1981 fctxs[fn] = p2[fn]
1981 fctxs[fn] = p2[fn]
1982
1982
1983 def fctxfn(repo, cx, path):
1983 def fctxfn(repo, cx, path):
1984 return fctxs.get(path)
1984 return fctxs.get(path)
1985
1985
1986 if len(ps) == 0 or ps[0] < 0:
1986 if len(ps) == 0 or ps[0] < 0:
1987 pars = [None, None]
1987 pars = [None, None]
1988 elif len(ps) == 1:
1988 elif len(ps) == 1:
1989 pars = [nodeids[ps[0]], None]
1989 pars = [nodeids[ps[0]], None]
1990 else:
1990 else:
1991 pars = [nodeids[p] for p in ps]
1991 pars = [nodeids[p] for p in ps]
1992 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1992 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1993 date=(id, 0),
1993 date=(id, 0),
1994 user="debugbuilddag",
1994 user="debugbuilddag",
1995 extra={'branch': atbranch})
1995 extra={'branch': atbranch})
1996 nodeid = repo.commitctx(cx)
1996 nodeid = repo.commitctx(cx)
1997 nodeids.append(nodeid)
1997 nodeids.append(nodeid)
1998 at = id
1998 at = id
1999 elif type == 'l':
1999 elif type == 'l':
2000 id, name = data
2000 id, name = data
2001 ui.note(('tag %s\n' % name))
2001 ui.note(('tag %s\n' % name))
2002 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2002 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2003 elif type == 'a':
2003 elif type == 'a':
2004 ui.note(('branch %s\n' % data))
2004 ui.note(('branch %s\n' % data))
2005 atbranch = data
2005 atbranch = data
2006 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2006 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2007 tr.close()
2007 tr.close()
2008
2008
2009 if tags:
2009 if tags:
2010 repo.vfs.write("localtags", "".join(tags))
2010 repo.vfs.write("localtags", "".join(tags))
2011 finally:
2011 finally:
2012 ui.progress(_('building'), None)
2012 ui.progress(_('building'), None)
2013 release(tr, lock)
2013 release(tr, lock)
2014
2014
2015 @command('debugbundle',
2015 @command('debugbundle',
2016 [('a', 'all', None, _('show all details'))],
2016 [('a', 'all', None, _('show all details'))],
2017 _('FILE'),
2017 _('FILE'),
2018 norepo=True)
2018 norepo=True)
2019 def debugbundle(ui, bundlepath, all=None, **opts):
2019 def debugbundle(ui, bundlepath, all=None, **opts):
2020 """lists the contents of a bundle"""
2020 """lists the contents of a bundle"""
2021 f = hg.openpath(ui, bundlepath)
2021 f = hg.openpath(ui, bundlepath)
2022 try:
2022 try:
2023 gen = exchange.readbundle(ui, f, bundlepath)
2023 gen = exchange.readbundle(ui, f, bundlepath)
2024 if isinstance(gen, bundle2.unbundle20):
2024 if isinstance(gen, bundle2.unbundle20):
2025 return _debugbundle2(ui, gen, all=all, **opts)
2025 return _debugbundle2(ui, gen, all=all, **opts)
2026 if all:
2026 if all:
2027 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2027 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2028
2028
2029 def showchunks(named):
2029 def showchunks(named):
2030 ui.write("\n%s\n" % named)
2030 ui.write("\n%s\n" % named)
2031 chain = None
2031 chain = None
2032 while True:
2032 while True:
2033 chunkdata = gen.deltachunk(chain)
2033 chunkdata = gen.deltachunk(chain)
2034 if not chunkdata:
2034 if not chunkdata:
2035 break
2035 break
2036 node = chunkdata['node']
2036 node = chunkdata['node']
2037 p1 = chunkdata['p1']
2037 p1 = chunkdata['p1']
2038 p2 = chunkdata['p2']
2038 p2 = chunkdata['p2']
2039 cs = chunkdata['cs']
2039 cs = chunkdata['cs']
2040 deltabase = chunkdata['deltabase']
2040 deltabase = chunkdata['deltabase']
2041 delta = chunkdata['delta']
2041 delta = chunkdata['delta']
2042 ui.write("%s %s %s %s %s %s\n" %
2042 ui.write("%s %s %s %s %s %s\n" %
2043 (hex(node), hex(p1), hex(p2),
2043 (hex(node), hex(p1), hex(p2),
2044 hex(cs), hex(deltabase), len(delta)))
2044 hex(cs), hex(deltabase), len(delta)))
2045 chain = node
2045 chain = node
2046
2046
2047 chunkdata = gen.changelogheader()
2047 chunkdata = gen.changelogheader()
2048 showchunks("changelog")
2048 showchunks("changelog")
2049 chunkdata = gen.manifestheader()
2049 chunkdata = gen.manifestheader()
2050 showchunks("manifest")
2050 showchunks("manifest")
2051 while True:
2051 while True:
2052 chunkdata = gen.filelogheader()
2052 chunkdata = gen.filelogheader()
2053 if not chunkdata:
2053 if not chunkdata:
2054 break
2054 break
2055 fname = chunkdata['filename']
2055 fname = chunkdata['filename']
2056 showchunks(fname)
2056 showchunks(fname)
2057 else:
2057 else:
2058 if isinstance(gen, bundle2.unbundle20):
2058 if isinstance(gen, bundle2.unbundle20):
2059 raise error.Abort(_('use debugbundle2 for this file'))
2059 raise error.Abort(_('use debugbundle2 for this file'))
2060 chunkdata = gen.changelogheader()
2060 chunkdata = gen.changelogheader()
2061 chain = None
2061 chain = None
2062 while True:
2062 while True:
2063 chunkdata = gen.deltachunk(chain)
2063 chunkdata = gen.deltachunk(chain)
2064 if not chunkdata:
2064 if not chunkdata:
2065 break
2065 break
2066 node = chunkdata['node']
2066 node = chunkdata['node']
2067 ui.write("%s\n" % hex(node))
2067 ui.write("%s\n" % hex(node))
2068 chain = node
2068 chain = node
2069 finally:
2069 finally:
2070 f.close()
2070 f.close()
2071
2071
2072 def _debugbundle2(ui, gen, **opts):
2072 def _debugbundle2(ui, gen, **opts):
2073 """lists the contents of a bundle2"""
2073 """lists the contents of a bundle2"""
2074 if not isinstance(gen, bundle2.unbundle20):
2074 if not isinstance(gen, bundle2.unbundle20):
2075 raise error.Abort(_('not a bundle2 file'))
2075 raise error.Abort(_('not a bundle2 file'))
2076 ui.write(('Stream params: %s\n' % repr(gen.params)))
2076 ui.write(('Stream params: %s\n' % repr(gen.params)))
2077 for part in gen.iterparts():
2077 for part in gen.iterparts():
2078 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2078 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2079 if part.type == 'changegroup':
2079 if part.type == 'changegroup':
2080 version = part.params.get('version', '01')
2080 version = part.params.get('version', '01')
2081 cg = changegroup.getunbundler(version, part, 'UN')
2081 cg = changegroup.getunbundler(version, part, 'UN')
2082 chunkdata = cg.changelogheader()
2082 chunkdata = cg.changelogheader()
2083 chain = None
2083 chain = None
2084 while True:
2084 while True:
2085 chunkdata = cg.deltachunk(chain)
2085 chunkdata = cg.deltachunk(chain)
2086 if not chunkdata:
2086 if not chunkdata:
2087 break
2087 break
2088 node = chunkdata['node']
2088 node = chunkdata['node']
2089 ui.write(" %s\n" % hex(node))
2089 ui.write(" %s\n" % hex(node))
2090 chain = node
2090 chain = node
2091
2091
2092 @command('debugcreatestreamclonebundle', [], 'FILE')
2092 @command('debugcreatestreamclonebundle', [], 'FILE')
2093 def debugcreatestreamclonebundle(ui, repo, fname):
2093 def debugcreatestreamclonebundle(ui, repo, fname):
2094 """create a stream clone bundle file
2094 """create a stream clone bundle file
2095
2095
2096 Stream bundles are special bundles that are essentially archives of
2096 Stream bundles are special bundles that are essentially archives of
2097 revlog files. They are commonly used for cloning very quickly.
2097 revlog files. They are commonly used for cloning very quickly.
2098 """
2098 """
2099 requirements, gen = streamclone.generatebundlev1(repo)
2099 requirements, gen = streamclone.generatebundlev1(repo)
2100 changegroup.writechunks(ui, gen, fname)
2100 changegroup.writechunks(ui, gen, fname)
2101
2101
2102 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2102 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2103
2103
2104 @command('debugapplystreamclonebundle', [], 'FILE')
2104 @command('debugapplystreamclonebundle', [], 'FILE')
2105 def debugapplystreamclonebundle(ui, repo, fname):
2105 def debugapplystreamclonebundle(ui, repo, fname):
2106 """apply a stream clone bundle file"""
2106 """apply a stream clone bundle file"""
2107 f = hg.openpath(ui, fname)
2107 f = hg.openpath(ui, fname)
2108 gen = exchange.readbundle(ui, f, fname)
2108 gen = exchange.readbundle(ui, f, fname)
2109 gen.apply(repo)
2109 gen.apply(repo)
2110
2110
2111 @command('debugcheckstate', [], '')
2111 @command('debugcheckstate', [], '')
2112 def debugcheckstate(ui, repo):
2112 def debugcheckstate(ui, repo):
2113 """validate the correctness of the current dirstate"""
2113 """validate the correctness of the current dirstate"""
2114 parent1, parent2 = repo.dirstate.parents()
2114 parent1, parent2 = repo.dirstate.parents()
2115 m1 = repo[parent1].manifest()
2115 m1 = repo[parent1].manifest()
2116 m2 = repo[parent2].manifest()
2116 m2 = repo[parent2].manifest()
2117 errors = 0
2117 errors = 0
2118 for f in repo.dirstate:
2118 for f in repo.dirstate:
2119 state = repo.dirstate[f]
2119 state = repo.dirstate[f]
2120 if state in "nr" and f not in m1:
2120 if state in "nr" and f not in m1:
2121 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2121 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2122 errors += 1
2122 errors += 1
2123 if state in "a" and f in m1:
2123 if state in "a" and f in m1:
2124 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2124 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2125 errors += 1
2125 errors += 1
2126 if state in "m" and f not in m1 and f not in m2:
2126 if state in "m" and f not in m1 and f not in m2:
2127 ui.warn(_("%s in state %s, but not in either manifest\n") %
2127 ui.warn(_("%s in state %s, but not in either manifest\n") %
2128 (f, state))
2128 (f, state))
2129 errors += 1
2129 errors += 1
2130 for f in m1:
2130 for f in m1:
2131 state = repo.dirstate[f]
2131 state = repo.dirstate[f]
2132 if state not in "nrm":
2132 if state not in "nrm":
2133 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2133 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2134 errors += 1
2134 errors += 1
2135 if errors:
2135 if errors:
2136 error = _(".hg/dirstate inconsistent with current parent's manifest")
2136 error = _(".hg/dirstate inconsistent with current parent's manifest")
2137 raise error.Abort(error)
2137 raise error.Abort(error)
2138
2138
2139 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2139 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2140 def debugcommands(ui, cmd='', *args):
2140 def debugcommands(ui, cmd='', *args):
2141 """list all available commands and options"""
2141 """list all available commands and options"""
2142 for cmd, vals in sorted(table.iteritems()):
2142 for cmd, vals in sorted(table.iteritems()):
2143 cmd = cmd.split('|')[0].strip('^')
2143 cmd = cmd.split('|')[0].strip('^')
2144 opts = ', '.join([i[1] for i in vals[1]])
2144 opts = ', '.join([i[1] for i in vals[1]])
2145 ui.write('%s: %s\n' % (cmd, opts))
2145 ui.write('%s: %s\n' % (cmd, opts))
2146
2146
2147 @command('debugcomplete',
2147 @command('debugcomplete',
2148 [('o', 'options', None, _('show the command options'))],
2148 [('o', 'options', None, _('show the command options'))],
2149 _('[-o] CMD'),
2149 _('[-o] CMD'),
2150 norepo=True)
2150 norepo=True)
2151 def debugcomplete(ui, cmd='', **opts):
2151 def debugcomplete(ui, cmd='', **opts):
2152 """returns the completion list associated with the given command"""
2152 """returns the completion list associated with the given command"""
2153
2153
2154 if opts.get('options'):
2154 if opts.get('options'):
2155 options = []
2155 options = []
2156 otables = [globalopts]
2156 otables = [globalopts]
2157 if cmd:
2157 if cmd:
2158 aliases, entry = cmdutil.findcmd(cmd, table, False)
2158 aliases, entry = cmdutil.findcmd(cmd, table, False)
2159 otables.append(entry[1])
2159 otables.append(entry[1])
2160 for t in otables:
2160 for t in otables:
2161 for o in t:
2161 for o in t:
2162 if "(DEPRECATED)" in o[3]:
2162 if "(DEPRECATED)" in o[3]:
2163 continue
2163 continue
2164 if o[0]:
2164 if o[0]:
2165 options.append('-%s' % o[0])
2165 options.append('-%s' % o[0])
2166 options.append('--%s' % o[1])
2166 options.append('--%s' % o[1])
2167 ui.write("%s\n" % "\n".join(options))
2167 ui.write("%s\n" % "\n".join(options))
2168 return
2168 return
2169
2169
2170 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2170 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2171 if ui.verbose:
2171 if ui.verbose:
2172 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2172 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2173 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2173 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2174
2174
2175 @command('debugdag',
2175 @command('debugdag',
2176 [('t', 'tags', None, _('use tags as labels')),
2176 [('t', 'tags', None, _('use tags as labels')),
2177 ('b', 'branches', None, _('annotate with branch names')),
2177 ('b', 'branches', None, _('annotate with branch names')),
2178 ('', 'dots', None, _('use dots for runs')),
2178 ('', 'dots', None, _('use dots for runs')),
2179 ('s', 'spaces', None, _('separate elements by spaces'))],
2179 ('s', 'spaces', None, _('separate elements by spaces'))],
2180 _('[OPTION]... [FILE [REV]...]'),
2180 _('[OPTION]... [FILE [REV]...]'),
2181 optionalrepo=True)
2181 optionalrepo=True)
2182 def debugdag(ui, repo, file_=None, *revs, **opts):
2182 def debugdag(ui, repo, file_=None, *revs, **opts):
2183 """format the changelog or an index DAG as a concise textual description
2183 """format the changelog or an index DAG as a concise textual description
2184
2184
2185 If you pass a revlog index, the revlog's DAG is emitted. If you list
2185 If you pass a revlog index, the revlog's DAG is emitted. If you list
2186 revision numbers, they get labeled in the output as rN.
2186 revision numbers, they get labeled in the output as rN.
2187
2187
2188 Otherwise, the changelog DAG of the current repo is emitted.
2188 Otherwise, the changelog DAG of the current repo is emitted.
2189 """
2189 """
2190 spaces = opts.get('spaces')
2190 spaces = opts.get('spaces')
2191 dots = opts.get('dots')
2191 dots = opts.get('dots')
2192 if file_:
2192 if file_:
2193 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2193 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2194 revs = set((int(r) for r in revs))
2194 revs = set((int(r) for r in revs))
2195 def events():
2195 def events():
2196 for r in rlog:
2196 for r in rlog:
2197 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2197 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2198 if p != -1))
2198 if p != -1))
2199 if r in revs:
2199 if r in revs:
2200 yield 'l', (r, "r%i" % r)
2200 yield 'l', (r, "r%i" % r)
2201 elif repo:
2201 elif repo:
2202 cl = repo.changelog
2202 cl = repo.changelog
2203 tags = opts.get('tags')
2203 tags = opts.get('tags')
2204 branches = opts.get('branches')
2204 branches = opts.get('branches')
2205 if tags:
2205 if tags:
2206 labels = {}
2206 labels = {}
2207 for l, n in repo.tags().items():
2207 for l, n in repo.tags().items():
2208 labels.setdefault(cl.rev(n), []).append(l)
2208 labels.setdefault(cl.rev(n), []).append(l)
2209 def events():
2209 def events():
2210 b = "default"
2210 b = "default"
2211 for r in cl:
2211 for r in cl:
2212 if branches:
2212 if branches:
2213 newb = cl.read(cl.node(r))[5]['branch']
2213 newb = cl.read(cl.node(r))[5]['branch']
2214 if newb != b:
2214 if newb != b:
2215 yield 'a', newb
2215 yield 'a', newb
2216 b = newb
2216 b = newb
2217 yield 'n', (r, list(p for p in cl.parentrevs(r)
2217 yield 'n', (r, list(p for p in cl.parentrevs(r)
2218 if p != -1))
2218 if p != -1))
2219 if tags:
2219 if tags:
2220 ls = labels.get(r)
2220 ls = labels.get(r)
2221 if ls:
2221 if ls:
2222 for l in ls:
2222 for l in ls:
2223 yield 'l', (r, l)
2223 yield 'l', (r, l)
2224 else:
2224 else:
2225 raise error.Abort(_('need repo for changelog dag'))
2225 raise error.Abort(_('need repo for changelog dag'))
2226
2226
2227 for line in dagparser.dagtextlines(events(),
2227 for line in dagparser.dagtextlines(events(),
2228 addspaces=spaces,
2228 addspaces=spaces,
2229 wraplabels=True,
2229 wraplabels=True,
2230 wrapannotations=True,
2230 wrapannotations=True,
2231 wrapnonlinear=dots,
2231 wrapnonlinear=dots,
2232 usedots=dots,
2232 usedots=dots,
2233 maxlinewidth=70):
2233 maxlinewidth=70):
2234 ui.write(line)
2234 ui.write(line)
2235 ui.write("\n")
2235 ui.write("\n")
2236
2236
2237 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2237 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2238 def debugdata(ui, repo, file_, rev=None, **opts):
2238 def debugdata(ui, repo, file_, rev=None, **opts):
2239 """dump the contents of a data file revision"""
2239 """dump the contents of a data file revision"""
2240 if opts.get('changelog') or opts.get('manifest'):
2240 if opts.get('changelog') or opts.get('manifest'):
2241 file_, rev = None, file_
2241 file_, rev = None, file_
2242 elif rev is None:
2242 elif rev is None:
2243 raise error.CommandError('debugdata', _('invalid arguments'))
2243 raise error.CommandError('debugdata', _('invalid arguments'))
2244 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2244 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2245 try:
2245 try:
2246 ui.write(r.revision(r.lookup(rev)))
2246 ui.write(r.revision(r.lookup(rev)))
2247 except KeyError:
2247 except KeyError:
2248 raise error.Abort(_('invalid revision identifier %s') % rev)
2248 raise error.Abort(_('invalid revision identifier %s') % rev)
2249
2249
2250 @command('debugdate',
2250 @command('debugdate',
2251 [('e', 'extended', None, _('try extended date formats'))],
2251 [('e', 'extended', None, _('try extended date formats'))],
2252 _('[-e] DATE [RANGE]'),
2252 _('[-e] DATE [RANGE]'),
2253 norepo=True, optionalrepo=True)
2253 norepo=True, optionalrepo=True)
2254 def debugdate(ui, date, range=None, **opts):
2254 def debugdate(ui, date, range=None, **opts):
2255 """parse and display a date"""
2255 """parse and display a date"""
2256 if opts["extended"]:
2256 if opts["extended"]:
2257 d = util.parsedate(date, util.extendeddateformats)
2257 d = util.parsedate(date, util.extendeddateformats)
2258 else:
2258 else:
2259 d = util.parsedate(date)
2259 d = util.parsedate(date)
2260 ui.write(("internal: %s %s\n") % d)
2260 ui.write(("internal: %s %s\n") % d)
2261 ui.write(("standard: %s\n") % util.datestr(d))
2261 ui.write(("standard: %s\n") % util.datestr(d))
2262 if range:
2262 if range:
2263 m = util.matchdate(range)
2263 m = util.matchdate(range)
2264 ui.write(("match: %s\n") % m(d[0]))
2264 ui.write(("match: %s\n") % m(d[0]))
2265
2265
2266 @command('debugdiscovery',
2266 @command('debugdiscovery',
2267 [('', 'old', None, _('use old-style discovery')),
2267 [('', 'old', None, _('use old-style discovery')),
2268 ('', 'nonheads', None,
2268 ('', 'nonheads', None,
2269 _('use old-style discovery with non-heads included')),
2269 _('use old-style discovery with non-heads included')),
2270 ] + remoteopts,
2270 ] + remoteopts,
2271 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2271 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2272 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2272 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2273 """runs the changeset discovery protocol in isolation"""
2273 """runs the changeset discovery protocol in isolation"""
2274 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2274 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2275 opts.get('branch'))
2275 opts.get('branch'))
2276 remote = hg.peer(repo, opts, remoteurl)
2276 remote = hg.peer(repo, opts, remoteurl)
2277 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2277 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2278
2278
2279 # make sure tests are repeatable
2279 # make sure tests are repeatable
2280 random.seed(12323)
2280 random.seed(12323)
2281
2281
2282 def doit(localheads, remoteheads, remote=remote):
2282 def doit(localheads, remoteheads, remote=remote):
2283 if opts.get('old'):
2283 if opts.get('old'):
2284 if localheads:
2284 if localheads:
2285 raise error.Abort('cannot use localheads with old style '
2285 raise error.Abort('cannot use localheads with old style '
2286 'discovery')
2286 'discovery')
2287 if not util.safehasattr(remote, 'branches'):
2287 if not util.safehasattr(remote, 'branches'):
2288 # enable in-client legacy support
2288 # enable in-client legacy support
2289 remote = localrepo.locallegacypeer(remote.local())
2289 remote = localrepo.locallegacypeer(remote.local())
2290 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2290 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2291 force=True)
2291 force=True)
2292 common = set(common)
2292 common = set(common)
2293 if not opts.get('nonheads'):
2293 if not opts.get('nonheads'):
2294 ui.write(("unpruned common: %s\n") %
2294 ui.write(("unpruned common: %s\n") %
2295 " ".join(sorted(short(n) for n in common)))
2295 " ".join(sorted(short(n) for n in common)))
2296 dag = dagutil.revlogdag(repo.changelog)
2296 dag = dagutil.revlogdag(repo.changelog)
2297 all = dag.ancestorset(dag.internalizeall(common))
2297 all = dag.ancestorset(dag.internalizeall(common))
2298 common = dag.externalizeall(dag.headsetofconnecteds(all))
2298 common = dag.externalizeall(dag.headsetofconnecteds(all))
2299 else:
2299 else:
2300 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2300 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2301 common = set(common)
2301 common = set(common)
2302 rheads = set(hds)
2302 rheads = set(hds)
2303 lheads = set(repo.heads())
2303 lheads = set(repo.heads())
2304 ui.write(("common heads: %s\n") %
2304 ui.write(("common heads: %s\n") %
2305 " ".join(sorted(short(n) for n in common)))
2305 " ".join(sorted(short(n) for n in common)))
2306 if lheads <= common:
2306 if lheads <= common:
2307 ui.write(("local is subset\n"))
2307 ui.write(("local is subset\n"))
2308 elif rheads <= common:
2308 elif rheads <= common:
2309 ui.write(("remote is subset\n"))
2309 ui.write(("remote is subset\n"))
2310
2310
2311 serverlogs = opts.get('serverlog')
2311 serverlogs = opts.get('serverlog')
2312 if serverlogs:
2312 if serverlogs:
2313 for filename in serverlogs:
2313 for filename in serverlogs:
2314 logfile = open(filename, 'r')
2314 with open(filename, 'r') as logfile:
2315 try:
2316 line = logfile.readline()
2315 line = logfile.readline()
2317 while line:
2316 while line:
2318 parts = line.strip().split(';')
2317 parts = line.strip().split(';')
2319 op = parts[1]
2318 op = parts[1]
2320 if op == 'cg':
2319 if op == 'cg':
2321 pass
2320 pass
2322 elif op == 'cgss':
2321 elif op == 'cgss':
2323 doit(parts[2].split(' '), parts[3].split(' '))
2322 doit(parts[2].split(' '), parts[3].split(' '))
2324 elif op == 'unb':
2323 elif op == 'unb':
2325 doit(parts[3].split(' '), parts[2].split(' '))
2324 doit(parts[3].split(' '), parts[2].split(' '))
2326 line = logfile.readline()
2325 line = logfile.readline()
2327 finally:
2328 logfile.close()
2329
2330 else:
2326 else:
2331 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2327 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2332 opts.get('remote_head'))
2328 opts.get('remote_head'))
2333 localrevs = opts.get('local_head')
2329 localrevs = opts.get('local_head')
2334 doit(localrevs, remoterevs)
2330 doit(localrevs, remoterevs)
2335
2331
2336 @command('debugextensions', formatteropts, [], norepo=True)
2332 @command('debugextensions', formatteropts, [], norepo=True)
2337 def debugextensions(ui, **opts):
2333 def debugextensions(ui, **opts):
2338 '''show information about active extensions'''
2334 '''show information about active extensions'''
2339 exts = extensions.extensions(ui)
2335 exts = extensions.extensions(ui)
2340 fm = ui.formatter('debugextensions', opts)
2336 fm = ui.formatter('debugextensions', opts)
2341 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2337 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2342 extsource = extmod.__file__
2338 extsource = extmod.__file__
2343 exttestedwith = getattr(extmod, 'testedwith', None)
2339 exttestedwith = getattr(extmod, 'testedwith', None)
2344 if exttestedwith is not None:
2340 if exttestedwith is not None:
2345 exttestedwith = exttestedwith.split()
2341 exttestedwith = exttestedwith.split()
2346 extbuglink = getattr(extmod, 'buglink', None)
2342 extbuglink = getattr(extmod, 'buglink', None)
2347
2343
2348 fm.startitem()
2344 fm.startitem()
2349
2345
2350 if ui.quiet or ui.verbose:
2346 if ui.quiet or ui.verbose:
2351 fm.write('name', '%s\n', extname)
2347 fm.write('name', '%s\n', extname)
2352 else:
2348 else:
2353 fm.write('name', '%s', extname)
2349 fm.write('name', '%s', extname)
2354 if not exttestedwith:
2350 if not exttestedwith:
2355 fm.plain(_(' (untested!)\n'))
2351 fm.plain(_(' (untested!)\n'))
2356 else:
2352 else:
2357 if exttestedwith == ['internal'] or \
2353 if exttestedwith == ['internal'] or \
2358 util.version() in exttestedwith:
2354 util.version() in exttestedwith:
2359 fm.plain('\n')
2355 fm.plain('\n')
2360 else:
2356 else:
2361 lasttestedversion = exttestedwith[-1]
2357 lasttestedversion = exttestedwith[-1]
2362 fm.plain(' (%s!)\n' % lasttestedversion)
2358 fm.plain(' (%s!)\n' % lasttestedversion)
2363
2359
2364 fm.condwrite(ui.verbose and extsource, 'source',
2360 fm.condwrite(ui.verbose and extsource, 'source',
2365 _(' location: %s\n'), extsource or "")
2361 _(' location: %s\n'), extsource or "")
2366
2362
2367 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2363 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2368 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2364 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2369
2365
2370 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2366 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2371 _(' bug reporting: %s\n'), extbuglink or "")
2367 _(' bug reporting: %s\n'), extbuglink or "")
2372
2368
2373 fm.end()
2369 fm.end()
2374
2370
2375 @command('debugfileset',
2371 @command('debugfileset',
2376 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2372 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2377 _('[-r REV] FILESPEC'))
2373 _('[-r REV] FILESPEC'))
2378 def debugfileset(ui, repo, expr, **opts):
2374 def debugfileset(ui, repo, expr, **opts):
2379 '''parse and apply a fileset specification'''
2375 '''parse and apply a fileset specification'''
2380 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2376 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2381 if ui.verbose:
2377 if ui.verbose:
2382 tree = fileset.parse(expr)
2378 tree = fileset.parse(expr)
2383 ui.note(fileset.prettyformat(tree), "\n")
2379 ui.note(fileset.prettyformat(tree), "\n")
2384
2380
2385 for f in ctx.getfileset(expr):
2381 for f in ctx.getfileset(expr):
2386 ui.write("%s\n" % f)
2382 ui.write("%s\n" % f)
2387
2383
2388 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2384 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2389 def debugfsinfo(ui, path="."):
2385 def debugfsinfo(ui, path="."):
2390 """show information detected about current filesystem"""
2386 """show information detected about current filesystem"""
2391 util.writefile('.debugfsinfo', '')
2387 util.writefile('.debugfsinfo', '')
2392 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2388 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2393 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2389 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2394 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2390 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2395 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2391 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2396 and 'yes' or 'no'))
2392 and 'yes' or 'no'))
2397 os.unlink('.debugfsinfo')
2393 os.unlink('.debugfsinfo')
2398
2394
2399 @command('debuggetbundle',
2395 @command('debuggetbundle',
2400 [('H', 'head', [], _('id of head node'), _('ID')),
2396 [('H', 'head', [], _('id of head node'), _('ID')),
2401 ('C', 'common', [], _('id of common node'), _('ID')),
2397 ('C', 'common', [], _('id of common node'), _('ID')),
2402 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2398 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2403 _('REPO FILE [-H|-C ID]...'),
2399 _('REPO FILE [-H|-C ID]...'),
2404 norepo=True)
2400 norepo=True)
2405 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2401 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2406 """retrieves a bundle from a repo
2402 """retrieves a bundle from a repo
2407
2403
2408 Every ID must be a full-length hex node id string. Saves the bundle to the
2404 Every ID must be a full-length hex node id string. Saves the bundle to the
2409 given file.
2405 given file.
2410 """
2406 """
2411 repo = hg.peer(ui, opts, repopath)
2407 repo = hg.peer(ui, opts, repopath)
2412 if not repo.capable('getbundle'):
2408 if not repo.capable('getbundle'):
2413 raise error.Abort("getbundle() not supported by target repository")
2409 raise error.Abort("getbundle() not supported by target repository")
2414 args = {}
2410 args = {}
2415 if common:
2411 if common:
2416 args['common'] = [bin(s) for s in common]
2412 args['common'] = [bin(s) for s in common]
2417 if head:
2413 if head:
2418 args['heads'] = [bin(s) for s in head]
2414 args['heads'] = [bin(s) for s in head]
2419 # TODO: get desired bundlecaps from command line.
2415 # TODO: get desired bundlecaps from command line.
2420 args['bundlecaps'] = None
2416 args['bundlecaps'] = None
2421 bundle = repo.getbundle('debug', **args)
2417 bundle = repo.getbundle('debug', **args)
2422
2418
2423 bundletype = opts.get('type', 'bzip2').lower()
2419 bundletype = opts.get('type', 'bzip2').lower()
2424 btypes = {'none': 'HG10UN',
2420 btypes = {'none': 'HG10UN',
2425 'bzip2': 'HG10BZ',
2421 'bzip2': 'HG10BZ',
2426 'gzip': 'HG10GZ',
2422 'gzip': 'HG10GZ',
2427 'bundle2': 'HG20'}
2423 'bundle2': 'HG20'}
2428 bundletype = btypes.get(bundletype)
2424 bundletype = btypes.get(bundletype)
2429 if bundletype not in changegroup.bundletypes:
2425 if bundletype not in changegroup.bundletypes:
2430 raise error.Abort(_('unknown bundle type specified with --type'))
2426 raise error.Abort(_('unknown bundle type specified with --type'))
2431 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2427 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2432
2428
2433 @command('debugignore', [], '[FILE]')
2429 @command('debugignore', [], '[FILE]')
2434 def debugignore(ui, repo, *files, **opts):
2430 def debugignore(ui, repo, *files, **opts):
2435 """display the combined ignore pattern and information about ignored files
2431 """display the combined ignore pattern and information about ignored files
2436
2432
2437 With no argument display the combined ignore pattern.
2433 With no argument display the combined ignore pattern.
2438
2434
2439 Given space separated file names, shows if the given file is ignored and
2435 Given space separated file names, shows if the given file is ignored and
2440 if so, show the ignore rule (file and line number) that matched it.
2436 if so, show the ignore rule (file and line number) that matched it.
2441 """
2437 """
2442 ignore = repo.dirstate._ignore
2438 ignore = repo.dirstate._ignore
2443 if not files:
2439 if not files:
2444 # Show all the patterns
2440 # Show all the patterns
2445 includepat = getattr(ignore, 'includepat', None)
2441 includepat = getattr(ignore, 'includepat', None)
2446 if includepat is not None:
2442 if includepat is not None:
2447 ui.write("%s\n" % includepat)
2443 ui.write("%s\n" % includepat)
2448 else:
2444 else:
2449 raise error.Abort(_("no ignore patterns found"))
2445 raise error.Abort(_("no ignore patterns found"))
2450 else:
2446 else:
2451 for f in files:
2447 for f in files:
2452 ignored = None
2448 ignored = None
2453 ignoredata = None
2449 ignoredata = None
2454 if f != '.':
2450 if f != '.':
2455 if ignore(f):
2451 if ignore(f):
2456 ignored = f
2452 ignored = f
2457 ignoredata = repo.dirstate._ignorefileandline(f)
2453 ignoredata = repo.dirstate._ignorefileandline(f)
2458 else:
2454 else:
2459 for p in util.finddirs(f):
2455 for p in util.finddirs(f):
2460 if ignore(p):
2456 if ignore(p):
2461 ignored = p
2457 ignored = p
2462 ignoredata = repo.dirstate._ignorefileandline(p)
2458 ignoredata = repo.dirstate._ignorefileandline(p)
2463 break
2459 break
2464 if ignored:
2460 if ignored:
2465 if ignored == f:
2461 if ignored == f:
2466 ui.write("%s is ignored\n" % f)
2462 ui.write("%s is ignored\n" % f)
2467 else:
2463 else:
2468 ui.write("%s is ignored because of containing folder %s\n"
2464 ui.write("%s is ignored because of containing folder %s\n"
2469 % (f, ignored))
2465 % (f, ignored))
2470 ignorefile, lineno, line = ignoredata
2466 ignorefile, lineno, line = ignoredata
2471 ui.write("(ignore rule in %s, line %d: '%s')\n"
2467 ui.write("(ignore rule in %s, line %d: '%s')\n"
2472 % (ignorefile, lineno, line))
2468 % (ignorefile, lineno, line))
2473 else:
2469 else:
2474 ui.write("%s is not ignored\n" % f)
2470 ui.write("%s is not ignored\n" % f)
2475
2471
2476 @command('debugindex', debugrevlogopts +
2472 @command('debugindex', debugrevlogopts +
2477 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2473 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2478 _('[-f FORMAT] -c|-m|FILE'),
2474 _('[-f FORMAT] -c|-m|FILE'),
2479 optionalrepo=True)
2475 optionalrepo=True)
2480 def debugindex(ui, repo, file_=None, **opts):
2476 def debugindex(ui, repo, file_=None, **opts):
2481 """dump the contents of an index file"""
2477 """dump the contents of an index file"""
2482 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2478 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2483 format = opts.get('format', 0)
2479 format = opts.get('format', 0)
2484 if format not in (0, 1):
2480 if format not in (0, 1):
2485 raise error.Abort(_("unknown format %d") % format)
2481 raise error.Abort(_("unknown format %d") % format)
2486
2482
2487 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2483 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2488 if generaldelta:
2484 if generaldelta:
2489 basehdr = ' delta'
2485 basehdr = ' delta'
2490 else:
2486 else:
2491 basehdr = ' base'
2487 basehdr = ' base'
2492
2488
2493 if ui.debugflag:
2489 if ui.debugflag:
2494 shortfn = hex
2490 shortfn = hex
2495 else:
2491 else:
2496 shortfn = short
2492 shortfn = short
2497
2493
2498 # There might not be anything in r, so have a sane default
2494 # There might not be anything in r, so have a sane default
2499 idlen = 12
2495 idlen = 12
2500 for i in r:
2496 for i in r:
2501 idlen = len(shortfn(r.node(i)))
2497 idlen = len(shortfn(r.node(i)))
2502 break
2498 break
2503
2499
2504 if format == 0:
2500 if format == 0:
2505 ui.write(" rev offset length " + basehdr + " linkrev"
2501 ui.write(" rev offset length " + basehdr + " linkrev"
2506 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2502 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2507 elif format == 1:
2503 elif format == 1:
2508 ui.write(" rev flag offset length"
2504 ui.write(" rev flag offset length"
2509 " size " + basehdr + " link p1 p2"
2505 " size " + basehdr + " link p1 p2"
2510 " %s\n" % "nodeid".rjust(idlen))
2506 " %s\n" % "nodeid".rjust(idlen))
2511
2507
2512 for i in r:
2508 for i in r:
2513 node = r.node(i)
2509 node = r.node(i)
2514 if generaldelta:
2510 if generaldelta:
2515 base = r.deltaparent(i)
2511 base = r.deltaparent(i)
2516 else:
2512 else:
2517 base = r.chainbase(i)
2513 base = r.chainbase(i)
2518 if format == 0:
2514 if format == 0:
2519 try:
2515 try:
2520 pp = r.parents(node)
2516 pp = r.parents(node)
2521 except Exception:
2517 except Exception:
2522 pp = [nullid, nullid]
2518 pp = [nullid, nullid]
2523 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2519 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2524 i, r.start(i), r.length(i), base, r.linkrev(i),
2520 i, r.start(i), r.length(i), base, r.linkrev(i),
2525 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2521 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2526 elif format == 1:
2522 elif format == 1:
2527 pr = r.parentrevs(i)
2523 pr = r.parentrevs(i)
2528 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2524 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2529 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2525 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2530 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2526 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2531
2527
2532 @command('debugindexdot', debugrevlogopts,
2528 @command('debugindexdot', debugrevlogopts,
2533 _('-c|-m|FILE'), optionalrepo=True)
2529 _('-c|-m|FILE'), optionalrepo=True)
2534 def debugindexdot(ui, repo, file_=None, **opts):
2530 def debugindexdot(ui, repo, file_=None, **opts):
2535 """dump an index DAG as a graphviz dot file"""
2531 """dump an index DAG as a graphviz dot file"""
2536 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2532 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2537 ui.write(("digraph G {\n"))
2533 ui.write(("digraph G {\n"))
2538 for i in r:
2534 for i in r:
2539 node = r.node(i)
2535 node = r.node(i)
2540 pp = r.parents(node)
2536 pp = r.parents(node)
2541 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2537 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2542 if pp[1] != nullid:
2538 if pp[1] != nullid:
2543 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2539 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2544 ui.write("}\n")
2540 ui.write("}\n")
2545
2541
2546 @command('debugdeltachain',
2542 @command('debugdeltachain',
2547 debugrevlogopts + formatteropts,
2543 debugrevlogopts + formatteropts,
2548 _('-c|-m|FILE'),
2544 _('-c|-m|FILE'),
2549 optionalrepo=True)
2545 optionalrepo=True)
2550 def debugdeltachain(ui, repo, file_=None, **opts):
2546 def debugdeltachain(ui, repo, file_=None, **opts):
2551 """dump information about delta chains in a revlog
2547 """dump information about delta chains in a revlog
2552
2548
2553 Output can be templatized. Available template keywords are:
2549 Output can be templatized. Available template keywords are:
2554
2550
2555 rev revision number
2551 rev revision number
2556 chainid delta chain identifier (numbered by unique base)
2552 chainid delta chain identifier (numbered by unique base)
2557 chainlen delta chain length to this revision
2553 chainlen delta chain length to this revision
2558 prevrev previous revision in delta chain
2554 prevrev previous revision in delta chain
2559 deltatype role of delta / how it was computed
2555 deltatype role of delta / how it was computed
2560 compsize compressed size of revision
2556 compsize compressed size of revision
2561 uncompsize uncompressed size of revision
2557 uncompsize uncompressed size of revision
2562 chainsize total size of compressed revisions in chain
2558 chainsize total size of compressed revisions in chain
2563 chainratio total chain size divided by uncompressed revision size
2559 chainratio total chain size divided by uncompressed revision size
2564 (new delta chains typically start at ratio 2.00)
2560 (new delta chains typically start at ratio 2.00)
2565 lindist linear distance from base revision in delta chain to end
2561 lindist linear distance from base revision in delta chain to end
2566 of this revision
2562 of this revision
2567 extradist total size of revisions not part of this delta chain from
2563 extradist total size of revisions not part of this delta chain from
2568 base of delta chain to end of this revision; a measurement
2564 base of delta chain to end of this revision; a measurement
2569 of how much extra data we need to read/seek across to read
2565 of how much extra data we need to read/seek across to read
2570 the delta chain for this revision
2566 the delta chain for this revision
2571 extraratio extradist divided by chainsize; another representation of
2567 extraratio extradist divided by chainsize; another representation of
2572 how much unrelated data is needed to load this delta chain
2568 how much unrelated data is needed to load this delta chain
2573 """
2569 """
2574 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2570 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2575 index = r.index
2571 index = r.index
2576 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2572 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2577
2573
2578 def revinfo(rev):
2574 def revinfo(rev):
2579 e = index[rev]
2575 e = index[rev]
2580 compsize = e[1]
2576 compsize = e[1]
2581 uncompsize = e[2]
2577 uncompsize = e[2]
2582 chainsize = 0
2578 chainsize = 0
2583
2579
2584 if generaldelta:
2580 if generaldelta:
2585 if e[3] == e[5]:
2581 if e[3] == e[5]:
2586 deltatype = 'p1'
2582 deltatype = 'p1'
2587 elif e[3] == e[6]:
2583 elif e[3] == e[6]:
2588 deltatype = 'p2'
2584 deltatype = 'p2'
2589 elif e[3] == rev - 1:
2585 elif e[3] == rev - 1:
2590 deltatype = 'prev'
2586 deltatype = 'prev'
2591 elif e[3] == rev:
2587 elif e[3] == rev:
2592 deltatype = 'base'
2588 deltatype = 'base'
2593 else:
2589 else:
2594 deltatype = 'other'
2590 deltatype = 'other'
2595 else:
2591 else:
2596 if e[3] == rev:
2592 if e[3] == rev:
2597 deltatype = 'base'
2593 deltatype = 'base'
2598 else:
2594 else:
2599 deltatype = 'prev'
2595 deltatype = 'prev'
2600
2596
2601 chain = r._deltachain(rev)[0]
2597 chain = r._deltachain(rev)[0]
2602 for iterrev in chain:
2598 for iterrev in chain:
2603 e = index[iterrev]
2599 e = index[iterrev]
2604 chainsize += e[1]
2600 chainsize += e[1]
2605
2601
2606 return compsize, uncompsize, deltatype, chain, chainsize
2602 return compsize, uncompsize, deltatype, chain, chainsize
2607
2603
2608 fm = ui.formatter('debugdeltachain', opts)
2604 fm = ui.formatter('debugdeltachain', opts)
2609
2605
2610 fm.plain(' rev chain# chainlen prev delta '
2606 fm.plain(' rev chain# chainlen prev delta '
2611 'size rawsize chainsize ratio lindist extradist '
2607 'size rawsize chainsize ratio lindist extradist '
2612 'extraratio\n')
2608 'extraratio\n')
2613
2609
2614 chainbases = {}
2610 chainbases = {}
2615 for rev in r:
2611 for rev in r:
2616 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2612 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2617 chainbase = chain[0]
2613 chainbase = chain[0]
2618 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2614 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2619 basestart = r.start(chainbase)
2615 basestart = r.start(chainbase)
2620 revstart = r.start(rev)
2616 revstart = r.start(rev)
2621 lineardist = revstart + comp - basestart
2617 lineardist = revstart + comp - basestart
2622 extradist = lineardist - chainsize
2618 extradist = lineardist - chainsize
2623 try:
2619 try:
2624 prevrev = chain[-2]
2620 prevrev = chain[-2]
2625 except IndexError:
2621 except IndexError:
2626 prevrev = -1
2622 prevrev = -1
2627
2623
2628 chainratio = float(chainsize) / float(uncomp)
2624 chainratio = float(chainsize) / float(uncomp)
2629 extraratio = float(extradist) / float(chainsize)
2625 extraratio = float(extradist) / float(chainsize)
2630
2626
2631 fm.startitem()
2627 fm.startitem()
2632 fm.write('rev chainid chainlen prevrev deltatype compsize '
2628 fm.write('rev chainid chainlen prevrev deltatype compsize '
2633 'uncompsize chainsize chainratio lindist extradist '
2629 'uncompsize chainsize chainratio lindist extradist '
2634 'extraratio',
2630 'extraratio',
2635 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2631 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2636 rev, chainid, len(chain), prevrev, deltatype, comp,
2632 rev, chainid, len(chain), prevrev, deltatype, comp,
2637 uncomp, chainsize, chainratio, lineardist, extradist,
2633 uncomp, chainsize, chainratio, lineardist, extradist,
2638 extraratio,
2634 extraratio,
2639 rev=rev, chainid=chainid, chainlen=len(chain),
2635 rev=rev, chainid=chainid, chainlen=len(chain),
2640 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2636 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2641 uncompsize=uncomp, chainsize=chainsize,
2637 uncompsize=uncomp, chainsize=chainsize,
2642 chainratio=chainratio, lindist=lineardist,
2638 chainratio=chainratio, lindist=lineardist,
2643 extradist=extradist, extraratio=extraratio)
2639 extradist=extradist, extraratio=extraratio)
2644
2640
2645 fm.end()
2641 fm.end()
2646
2642
2647 @command('debuginstall', [], '', norepo=True)
2643 @command('debuginstall', [], '', norepo=True)
2648 def debuginstall(ui):
2644 def debuginstall(ui):
2649 '''test Mercurial installation
2645 '''test Mercurial installation
2650
2646
2651 Returns 0 on success.
2647 Returns 0 on success.
2652 '''
2648 '''
2653
2649
2654 def writetemp(contents):
2650 def writetemp(contents):
2655 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2651 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2656 f = os.fdopen(fd, "wb")
2652 f = os.fdopen(fd, "wb")
2657 f.write(contents)
2653 f.write(contents)
2658 f.close()
2654 f.close()
2659 return name
2655 return name
2660
2656
2661 problems = 0
2657 problems = 0
2662
2658
2663 # encoding
2659 # encoding
2664 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2660 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2665 try:
2661 try:
2666 encoding.fromlocal("test")
2662 encoding.fromlocal("test")
2667 except error.Abort as inst:
2663 except error.Abort as inst:
2668 ui.write(" %s\n" % inst)
2664 ui.write(" %s\n" % inst)
2669 ui.write(_(" (check that your locale is properly set)\n"))
2665 ui.write(_(" (check that your locale is properly set)\n"))
2670 problems += 1
2666 problems += 1
2671
2667
2672 # Python
2668 # Python
2673 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2669 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2674 ui.status(_("checking Python version (%s)\n")
2670 ui.status(_("checking Python version (%s)\n")
2675 % ("%s.%s.%s" % sys.version_info[:3]))
2671 % ("%s.%s.%s" % sys.version_info[:3]))
2676 ui.status(_("checking Python lib (%s)...\n")
2672 ui.status(_("checking Python lib (%s)...\n")
2677 % os.path.dirname(os.__file__))
2673 % os.path.dirname(os.__file__))
2678
2674
2679 # compiled modules
2675 # compiled modules
2680 ui.status(_("checking installed modules (%s)...\n")
2676 ui.status(_("checking installed modules (%s)...\n")
2681 % os.path.dirname(__file__))
2677 % os.path.dirname(__file__))
2682 try:
2678 try:
2683 import bdiff, mpatch, base85, osutil
2679 import bdiff, mpatch, base85, osutil
2684 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2680 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2685 except Exception as inst:
2681 except Exception as inst:
2686 ui.write(" %s\n" % inst)
2682 ui.write(" %s\n" % inst)
2687 ui.write(_(" One or more extensions could not be found"))
2683 ui.write(_(" One or more extensions could not be found"))
2688 ui.write(_(" (check that you compiled the extensions)\n"))
2684 ui.write(_(" (check that you compiled the extensions)\n"))
2689 problems += 1
2685 problems += 1
2690
2686
2691 # templates
2687 # templates
2692 import templater
2688 import templater
2693 p = templater.templatepaths()
2689 p = templater.templatepaths()
2694 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2690 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2695 if p:
2691 if p:
2696 m = templater.templatepath("map-cmdline.default")
2692 m = templater.templatepath("map-cmdline.default")
2697 if m:
2693 if m:
2698 # template found, check if it is working
2694 # template found, check if it is working
2699 try:
2695 try:
2700 templater.templater(m)
2696 templater.templater(m)
2701 except Exception as inst:
2697 except Exception as inst:
2702 ui.write(" %s\n" % inst)
2698 ui.write(" %s\n" % inst)
2703 p = None
2699 p = None
2704 else:
2700 else:
2705 ui.write(_(" template 'default' not found\n"))
2701 ui.write(_(" template 'default' not found\n"))
2706 p = None
2702 p = None
2707 else:
2703 else:
2708 ui.write(_(" no template directories found\n"))
2704 ui.write(_(" no template directories found\n"))
2709 if not p:
2705 if not p:
2710 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2706 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2711 problems += 1
2707 problems += 1
2712
2708
2713 # editor
2709 # editor
2714 ui.status(_("checking commit editor...\n"))
2710 ui.status(_("checking commit editor...\n"))
2715 editor = ui.geteditor()
2711 editor = ui.geteditor()
2716 editor = util.expandpath(editor)
2712 editor = util.expandpath(editor)
2717 cmdpath = util.findexe(shlex.split(editor)[0])
2713 cmdpath = util.findexe(shlex.split(editor)[0])
2718 if not cmdpath:
2714 if not cmdpath:
2719 if editor == 'vi':
2715 if editor == 'vi':
2720 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2716 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2721 ui.write(_(" (specify a commit editor in your configuration"
2717 ui.write(_(" (specify a commit editor in your configuration"
2722 " file)\n"))
2718 " file)\n"))
2723 else:
2719 else:
2724 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2720 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2725 ui.write(_(" (specify a commit editor in your configuration"
2721 ui.write(_(" (specify a commit editor in your configuration"
2726 " file)\n"))
2722 " file)\n"))
2727 problems += 1
2723 problems += 1
2728
2724
2729 # check username
2725 # check username
2730 ui.status(_("checking username...\n"))
2726 ui.status(_("checking username...\n"))
2731 try:
2727 try:
2732 ui.username()
2728 ui.username()
2733 except error.Abort as e:
2729 except error.Abort as e:
2734 ui.write(" %s\n" % e)
2730 ui.write(" %s\n" % e)
2735 ui.write(_(" (specify a username in your configuration file)\n"))
2731 ui.write(_(" (specify a username in your configuration file)\n"))
2736 problems += 1
2732 problems += 1
2737
2733
2738 if not problems:
2734 if not problems:
2739 ui.status(_("no problems detected\n"))
2735 ui.status(_("no problems detected\n"))
2740 else:
2736 else:
2741 ui.write(_("%s problems detected,"
2737 ui.write(_("%s problems detected,"
2742 " please check your install!\n") % problems)
2738 " please check your install!\n") % problems)
2743
2739
2744 return problems
2740 return problems
2745
2741
2746 @command('debugknown', [], _('REPO ID...'), norepo=True)
2742 @command('debugknown', [], _('REPO ID...'), norepo=True)
2747 def debugknown(ui, repopath, *ids, **opts):
2743 def debugknown(ui, repopath, *ids, **opts):
2748 """test whether node ids are known to a repo
2744 """test whether node ids are known to a repo
2749
2745
2750 Every ID must be a full-length hex node id string. Returns a list of 0s
2746 Every ID must be a full-length hex node id string. Returns a list of 0s
2751 and 1s indicating unknown/known.
2747 and 1s indicating unknown/known.
2752 """
2748 """
2753 repo = hg.peer(ui, opts, repopath)
2749 repo = hg.peer(ui, opts, repopath)
2754 if not repo.capable('known'):
2750 if not repo.capable('known'):
2755 raise error.Abort("known() not supported by target repository")
2751 raise error.Abort("known() not supported by target repository")
2756 flags = repo.known([bin(s) for s in ids])
2752 flags = repo.known([bin(s) for s in ids])
2757 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2753 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2758
2754
2759 @command('debuglabelcomplete', [], _('LABEL...'))
2755 @command('debuglabelcomplete', [], _('LABEL...'))
2760 def debuglabelcomplete(ui, repo, *args):
2756 def debuglabelcomplete(ui, repo, *args):
2761 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2757 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2762 debugnamecomplete(ui, repo, *args)
2758 debugnamecomplete(ui, repo, *args)
2763
2759
2764 @command('debugmergestate', [], '')
2760 @command('debugmergestate', [], '')
2765 def debugmergestate(ui, repo, *args):
2761 def debugmergestate(ui, repo, *args):
2766 """print merge state
2762 """print merge state
2767
2763
2768 Use --verbose to print out information about whether v1 or v2 merge state
2764 Use --verbose to print out information about whether v1 or v2 merge state
2769 was chosen."""
2765 was chosen."""
2770 def _hashornull(h):
2766 def _hashornull(h):
2771 if h == nullhex:
2767 if h == nullhex:
2772 return 'null'
2768 return 'null'
2773 else:
2769 else:
2774 return h
2770 return h
2775
2771
2776 def printrecords(version):
2772 def printrecords(version):
2777 ui.write(('* version %s records\n') % version)
2773 ui.write(('* version %s records\n') % version)
2778 if version == 1:
2774 if version == 1:
2779 records = v1records
2775 records = v1records
2780 else:
2776 else:
2781 records = v2records
2777 records = v2records
2782
2778
2783 for rtype, record in records:
2779 for rtype, record in records:
2784 # pretty print some record types
2780 # pretty print some record types
2785 if rtype == 'L':
2781 if rtype == 'L':
2786 ui.write(('local: %s\n') % record)
2782 ui.write(('local: %s\n') % record)
2787 elif rtype == 'O':
2783 elif rtype == 'O':
2788 ui.write(('other: %s\n') % record)
2784 ui.write(('other: %s\n') % record)
2789 elif rtype == 'm':
2785 elif rtype == 'm':
2790 driver, mdstate = record.split('\0', 1)
2786 driver, mdstate = record.split('\0', 1)
2791 ui.write(('merge driver: %s (state "%s")\n')
2787 ui.write(('merge driver: %s (state "%s")\n')
2792 % (driver, mdstate))
2788 % (driver, mdstate))
2793 elif rtype in 'FDC':
2789 elif rtype in 'FDC':
2794 r = record.split('\0')
2790 r = record.split('\0')
2795 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2791 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2796 if version == 1:
2792 if version == 1:
2797 onode = 'not stored in v1 format'
2793 onode = 'not stored in v1 format'
2798 flags = r[7]
2794 flags = r[7]
2799 else:
2795 else:
2800 onode, flags = r[7:9]
2796 onode, flags = r[7:9]
2801 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2797 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2802 % (f, rtype, state, _hashornull(hash)))
2798 % (f, rtype, state, _hashornull(hash)))
2803 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2799 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2804 ui.write((' ancestor path: %s (node %s)\n')
2800 ui.write((' ancestor path: %s (node %s)\n')
2805 % (afile, _hashornull(anode)))
2801 % (afile, _hashornull(anode)))
2806 ui.write((' other path: %s (node %s)\n')
2802 ui.write((' other path: %s (node %s)\n')
2807 % (ofile, _hashornull(onode)))
2803 % (ofile, _hashornull(onode)))
2808 else:
2804 else:
2809 ui.write(('unrecognized entry: %s\t%s\n')
2805 ui.write(('unrecognized entry: %s\t%s\n')
2810 % (rtype, record.replace('\0', '\t')))
2806 % (rtype, record.replace('\0', '\t')))
2811
2807
2812 # Avoid mergestate.read() since it may raise an exception for unsupported
2808 # Avoid mergestate.read() since it may raise an exception for unsupported
2813 # merge state records. We shouldn't be doing this, but this is OK since this
2809 # merge state records. We shouldn't be doing this, but this is OK since this
2814 # command is pretty low-level.
2810 # command is pretty low-level.
2815 ms = mergemod.mergestate(repo)
2811 ms = mergemod.mergestate(repo)
2816
2812
2817 # sort so that reasonable information is on top
2813 # sort so that reasonable information is on top
2818 v1records = ms._readrecordsv1()
2814 v1records = ms._readrecordsv1()
2819 v2records = ms._readrecordsv2()
2815 v2records = ms._readrecordsv2()
2820 order = 'LOm'
2816 order = 'LOm'
2821 def key(r):
2817 def key(r):
2822 idx = order.find(r[0])
2818 idx = order.find(r[0])
2823 if idx == -1:
2819 if idx == -1:
2824 return (1, r[1])
2820 return (1, r[1])
2825 else:
2821 else:
2826 return (0, idx)
2822 return (0, idx)
2827 v1records.sort(key=key)
2823 v1records.sort(key=key)
2828 v2records.sort(key=key)
2824 v2records.sort(key=key)
2829
2825
2830 if not v1records and not v2records:
2826 if not v1records and not v2records:
2831 ui.write(('no merge state found\n'))
2827 ui.write(('no merge state found\n'))
2832 elif not v2records:
2828 elif not v2records:
2833 ui.note(('no version 2 merge state\n'))
2829 ui.note(('no version 2 merge state\n'))
2834 printrecords(1)
2830 printrecords(1)
2835 elif ms._v1v2match(v1records, v2records):
2831 elif ms._v1v2match(v1records, v2records):
2836 ui.note(('v1 and v2 states match: using v2\n'))
2832 ui.note(('v1 and v2 states match: using v2\n'))
2837 printrecords(2)
2833 printrecords(2)
2838 else:
2834 else:
2839 ui.note(('v1 and v2 states mismatch: using v1\n'))
2835 ui.note(('v1 and v2 states mismatch: using v1\n'))
2840 printrecords(1)
2836 printrecords(1)
2841 if ui.verbose:
2837 if ui.verbose:
2842 printrecords(2)
2838 printrecords(2)
2843
2839
2844 @command('debugnamecomplete', [], _('NAME...'))
2840 @command('debugnamecomplete', [], _('NAME...'))
2845 def debugnamecomplete(ui, repo, *args):
2841 def debugnamecomplete(ui, repo, *args):
2846 '''complete "names" - tags, open branch names, bookmark names'''
2842 '''complete "names" - tags, open branch names, bookmark names'''
2847
2843
2848 names = set()
2844 names = set()
2849 # since we previously only listed open branches, we will handle that
2845 # since we previously only listed open branches, we will handle that
2850 # specially (after this for loop)
2846 # specially (after this for loop)
2851 for name, ns in repo.names.iteritems():
2847 for name, ns in repo.names.iteritems():
2852 if name != 'branches':
2848 if name != 'branches':
2853 names.update(ns.listnames(repo))
2849 names.update(ns.listnames(repo))
2854 names.update(tag for (tag, heads, tip, closed)
2850 names.update(tag for (tag, heads, tip, closed)
2855 in repo.branchmap().iterbranches() if not closed)
2851 in repo.branchmap().iterbranches() if not closed)
2856 completions = set()
2852 completions = set()
2857 if not args:
2853 if not args:
2858 args = ['']
2854 args = ['']
2859 for a in args:
2855 for a in args:
2860 completions.update(n for n in names if n.startswith(a))
2856 completions.update(n for n in names if n.startswith(a))
2861 ui.write('\n'.join(sorted(completions)))
2857 ui.write('\n'.join(sorted(completions)))
2862 ui.write('\n')
2858 ui.write('\n')
2863
2859
2864 @command('debuglocks',
2860 @command('debuglocks',
2865 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2861 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2866 ('W', 'force-wlock', None,
2862 ('W', 'force-wlock', None,
2867 _('free the working state lock (DANGEROUS)'))],
2863 _('free the working state lock (DANGEROUS)'))],
2868 _('[OPTION]...'))
2864 _('[OPTION]...'))
2869 def debuglocks(ui, repo, **opts):
2865 def debuglocks(ui, repo, **opts):
2870 """show or modify state of locks
2866 """show or modify state of locks
2871
2867
2872 By default, this command will show which locks are held. This
2868 By default, this command will show which locks are held. This
2873 includes the user and process holding the lock, the amount of time
2869 includes the user and process holding the lock, the amount of time
2874 the lock has been held, and the machine name where the process is
2870 the lock has been held, and the machine name where the process is
2875 running if it's not local.
2871 running if it's not local.
2876
2872
2877 Locks protect the integrity of Mercurial's data, so should be
2873 Locks protect the integrity of Mercurial's data, so should be
2878 treated with care. System crashes or other interruptions may cause
2874 treated with care. System crashes or other interruptions may cause
2879 locks to not be properly released, though Mercurial will usually
2875 locks to not be properly released, though Mercurial will usually
2880 detect and remove such stale locks automatically.
2876 detect and remove such stale locks automatically.
2881
2877
2882 However, detecting stale locks may not always be possible (for
2878 However, detecting stale locks may not always be possible (for
2883 instance, on a shared filesystem). Removing locks may also be
2879 instance, on a shared filesystem). Removing locks may also be
2884 blocked by filesystem permissions.
2880 blocked by filesystem permissions.
2885
2881
2886 Returns 0 if no locks are held.
2882 Returns 0 if no locks are held.
2887
2883
2888 """
2884 """
2889
2885
2890 if opts.get('force_lock'):
2886 if opts.get('force_lock'):
2891 repo.svfs.unlink('lock')
2887 repo.svfs.unlink('lock')
2892 if opts.get('force_wlock'):
2888 if opts.get('force_wlock'):
2893 repo.vfs.unlink('wlock')
2889 repo.vfs.unlink('wlock')
2894 if opts.get('force_lock') or opts.get('force_lock'):
2890 if opts.get('force_lock') or opts.get('force_lock'):
2895 return 0
2891 return 0
2896
2892
2897 now = time.time()
2893 now = time.time()
2898 held = 0
2894 held = 0
2899
2895
2900 def report(vfs, name, method):
2896 def report(vfs, name, method):
2901 # this causes stale locks to get reaped for more accurate reporting
2897 # this causes stale locks to get reaped for more accurate reporting
2902 try:
2898 try:
2903 l = method(False)
2899 l = method(False)
2904 except error.LockHeld:
2900 except error.LockHeld:
2905 l = None
2901 l = None
2906
2902
2907 if l:
2903 if l:
2908 l.release()
2904 l.release()
2909 else:
2905 else:
2910 try:
2906 try:
2911 stat = vfs.lstat(name)
2907 stat = vfs.lstat(name)
2912 age = now - stat.st_mtime
2908 age = now - stat.st_mtime
2913 user = util.username(stat.st_uid)
2909 user = util.username(stat.st_uid)
2914 locker = vfs.readlock(name)
2910 locker = vfs.readlock(name)
2915 if ":" in locker:
2911 if ":" in locker:
2916 host, pid = locker.split(':')
2912 host, pid = locker.split(':')
2917 if host == socket.gethostname():
2913 if host == socket.gethostname():
2918 locker = 'user %s, process %s' % (user, pid)
2914 locker = 'user %s, process %s' % (user, pid)
2919 else:
2915 else:
2920 locker = 'user %s, process %s, host %s' \
2916 locker = 'user %s, process %s, host %s' \
2921 % (user, pid, host)
2917 % (user, pid, host)
2922 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2918 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2923 return 1
2919 return 1
2924 except OSError as e:
2920 except OSError as e:
2925 if e.errno != errno.ENOENT:
2921 if e.errno != errno.ENOENT:
2926 raise
2922 raise
2927
2923
2928 ui.write("%-6s free\n" % (name + ":"))
2924 ui.write("%-6s free\n" % (name + ":"))
2929 return 0
2925 return 0
2930
2926
2931 held += report(repo.svfs, "lock", repo.lock)
2927 held += report(repo.svfs, "lock", repo.lock)
2932 held += report(repo.vfs, "wlock", repo.wlock)
2928 held += report(repo.vfs, "wlock", repo.wlock)
2933
2929
2934 return held
2930 return held
2935
2931
2936 @command('debugobsolete',
2932 @command('debugobsolete',
2937 [('', 'flags', 0, _('markers flag')),
2933 [('', 'flags', 0, _('markers flag')),
2938 ('', 'record-parents', False,
2934 ('', 'record-parents', False,
2939 _('record parent information for the precursor')),
2935 _('record parent information for the precursor')),
2940 ('r', 'rev', [], _('display markers relevant to REV')),
2936 ('r', 'rev', [], _('display markers relevant to REV')),
2941 ] + commitopts2,
2937 ] + commitopts2,
2942 _('[OBSOLETED [REPLACEMENT ...]]'))
2938 _('[OBSOLETED [REPLACEMENT ...]]'))
2943 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2939 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2944 """create arbitrary obsolete marker
2940 """create arbitrary obsolete marker
2945
2941
2946 With no arguments, displays the list of obsolescence markers."""
2942 With no arguments, displays the list of obsolescence markers."""
2947
2943
2948 def parsenodeid(s):
2944 def parsenodeid(s):
2949 try:
2945 try:
2950 # We do not use revsingle/revrange functions here to accept
2946 # We do not use revsingle/revrange functions here to accept
2951 # arbitrary node identifiers, possibly not present in the
2947 # arbitrary node identifiers, possibly not present in the
2952 # local repository.
2948 # local repository.
2953 n = bin(s)
2949 n = bin(s)
2954 if len(n) != len(nullid):
2950 if len(n) != len(nullid):
2955 raise TypeError()
2951 raise TypeError()
2956 return n
2952 return n
2957 except TypeError:
2953 except TypeError:
2958 raise error.Abort('changeset references must be full hexadecimal '
2954 raise error.Abort('changeset references must be full hexadecimal '
2959 'node identifiers')
2955 'node identifiers')
2960
2956
2961 if precursor is not None:
2957 if precursor is not None:
2962 if opts['rev']:
2958 if opts['rev']:
2963 raise error.Abort('cannot select revision when creating marker')
2959 raise error.Abort('cannot select revision when creating marker')
2964 metadata = {}
2960 metadata = {}
2965 metadata['user'] = opts['user'] or ui.username()
2961 metadata['user'] = opts['user'] or ui.username()
2966 succs = tuple(parsenodeid(succ) for succ in successors)
2962 succs = tuple(parsenodeid(succ) for succ in successors)
2967 l = repo.lock()
2963 l = repo.lock()
2968 try:
2964 try:
2969 tr = repo.transaction('debugobsolete')
2965 tr = repo.transaction('debugobsolete')
2970 try:
2966 try:
2971 date = opts.get('date')
2967 date = opts.get('date')
2972 if date:
2968 if date:
2973 date = util.parsedate(date)
2969 date = util.parsedate(date)
2974 else:
2970 else:
2975 date = None
2971 date = None
2976 prec = parsenodeid(precursor)
2972 prec = parsenodeid(precursor)
2977 parents = None
2973 parents = None
2978 if opts['record_parents']:
2974 if opts['record_parents']:
2979 if prec not in repo.unfiltered():
2975 if prec not in repo.unfiltered():
2980 raise error.Abort('cannot used --record-parents on '
2976 raise error.Abort('cannot used --record-parents on '
2981 'unknown changesets')
2977 'unknown changesets')
2982 parents = repo.unfiltered()[prec].parents()
2978 parents = repo.unfiltered()[prec].parents()
2983 parents = tuple(p.node() for p in parents)
2979 parents = tuple(p.node() for p in parents)
2984 repo.obsstore.create(tr, prec, succs, opts['flags'],
2980 repo.obsstore.create(tr, prec, succs, opts['flags'],
2985 parents=parents, date=date,
2981 parents=parents, date=date,
2986 metadata=metadata)
2982 metadata=metadata)
2987 tr.close()
2983 tr.close()
2988 except ValueError as exc:
2984 except ValueError as exc:
2989 raise error.Abort(_('bad obsmarker input: %s') % exc)
2985 raise error.Abort(_('bad obsmarker input: %s') % exc)
2990 finally:
2986 finally:
2991 tr.release()
2987 tr.release()
2992 finally:
2988 finally:
2993 l.release()
2989 l.release()
2994 else:
2990 else:
2995 if opts['rev']:
2991 if opts['rev']:
2996 revs = scmutil.revrange(repo, opts['rev'])
2992 revs = scmutil.revrange(repo, opts['rev'])
2997 nodes = [repo[r].node() for r in revs]
2993 nodes = [repo[r].node() for r in revs]
2998 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2994 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2999 markers.sort(key=lambda x: x._data)
2995 markers.sort(key=lambda x: x._data)
3000 else:
2996 else:
3001 markers = obsolete.getmarkers(repo)
2997 markers = obsolete.getmarkers(repo)
3002
2998
3003 for m in markers:
2999 for m in markers:
3004 cmdutil.showmarker(ui, m)
3000 cmdutil.showmarker(ui, m)
3005
3001
3006 @command('debugpathcomplete',
3002 @command('debugpathcomplete',
3007 [('f', 'full', None, _('complete an entire path')),
3003 [('f', 'full', None, _('complete an entire path')),
3008 ('n', 'normal', None, _('show only normal files')),
3004 ('n', 'normal', None, _('show only normal files')),
3009 ('a', 'added', None, _('show only added files')),
3005 ('a', 'added', None, _('show only added files')),
3010 ('r', 'removed', None, _('show only removed files'))],
3006 ('r', 'removed', None, _('show only removed files'))],
3011 _('FILESPEC...'))
3007 _('FILESPEC...'))
3012 def debugpathcomplete(ui, repo, *specs, **opts):
3008 def debugpathcomplete(ui, repo, *specs, **opts):
3013 '''complete part or all of a tracked path
3009 '''complete part or all of a tracked path
3014
3010
3015 This command supports shells that offer path name completion. It
3011 This command supports shells that offer path name completion. It
3016 currently completes only files already known to the dirstate.
3012 currently completes only files already known to the dirstate.
3017
3013
3018 Completion extends only to the next path segment unless
3014 Completion extends only to the next path segment unless
3019 --full is specified, in which case entire paths are used.'''
3015 --full is specified, in which case entire paths are used.'''
3020
3016
3021 def complete(path, acceptable):
3017 def complete(path, acceptable):
3022 dirstate = repo.dirstate
3018 dirstate = repo.dirstate
3023 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3019 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3024 rootdir = repo.root + os.sep
3020 rootdir = repo.root + os.sep
3025 if spec != repo.root and not spec.startswith(rootdir):
3021 if spec != repo.root and not spec.startswith(rootdir):
3026 return [], []
3022 return [], []
3027 if os.path.isdir(spec):
3023 if os.path.isdir(spec):
3028 spec += '/'
3024 spec += '/'
3029 spec = spec[len(rootdir):]
3025 spec = spec[len(rootdir):]
3030 fixpaths = os.sep != '/'
3026 fixpaths = os.sep != '/'
3031 if fixpaths:
3027 if fixpaths:
3032 spec = spec.replace(os.sep, '/')
3028 spec = spec.replace(os.sep, '/')
3033 speclen = len(spec)
3029 speclen = len(spec)
3034 fullpaths = opts['full']
3030 fullpaths = opts['full']
3035 files, dirs = set(), set()
3031 files, dirs = set(), set()
3036 adddir, addfile = dirs.add, files.add
3032 adddir, addfile = dirs.add, files.add
3037 for f, st in dirstate.iteritems():
3033 for f, st in dirstate.iteritems():
3038 if f.startswith(spec) and st[0] in acceptable:
3034 if f.startswith(spec) and st[0] in acceptable:
3039 if fixpaths:
3035 if fixpaths:
3040 f = f.replace('/', os.sep)
3036 f = f.replace('/', os.sep)
3041 if fullpaths:
3037 if fullpaths:
3042 addfile(f)
3038 addfile(f)
3043 continue
3039 continue
3044 s = f.find(os.sep, speclen)
3040 s = f.find(os.sep, speclen)
3045 if s >= 0:
3041 if s >= 0:
3046 adddir(f[:s])
3042 adddir(f[:s])
3047 else:
3043 else:
3048 addfile(f)
3044 addfile(f)
3049 return files, dirs
3045 return files, dirs
3050
3046
3051 acceptable = ''
3047 acceptable = ''
3052 if opts['normal']:
3048 if opts['normal']:
3053 acceptable += 'nm'
3049 acceptable += 'nm'
3054 if opts['added']:
3050 if opts['added']:
3055 acceptable += 'a'
3051 acceptable += 'a'
3056 if opts['removed']:
3052 if opts['removed']:
3057 acceptable += 'r'
3053 acceptable += 'r'
3058 cwd = repo.getcwd()
3054 cwd = repo.getcwd()
3059 if not specs:
3055 if not specs:
3060 specs = ['.']
3056 specs = ['.']
3061
3057
3062 files, dirs = set(), set()
3058 files, dirs = set(), set()
3063 for spec in specs:
3059 for spec in specs:
3064 f, d = complete(spec, acceptable or 'nmar')
3060 f, d = complete(spec, acceptable or 'nmar')
3065 files.update(f)
3061 files.update(f)
3066 dirs.update(d)
3062 dirs.update(d)
3067 files.update(dirs)
3063 files.update(dirs)
3068 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3064 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3069 ui.write('\n')
3065 ui.write('\n')
3070
3066
3071 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3067 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3072 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3068 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3073 '''access the pushkey key/value protocol
3069 '''access the pushkey key/value protocol
3074
3070
3075 With two args, list the keys in the given namespace.
3071 With two args, list the keys in the given namespace.
3076
3072
3077 With five args, set a key to new if it currently is set to old.
3073 With five args, set a key to new if it currently is set to old.
3078 Reports success or failure.
3074 Reports success or failure.
3079 '''
3075 '''
3080
3076
3081 target = hg.peer(ui, {}, repopath)
3077 target = hg.peer(ui, {}, repopath)
3082 if keyinfo:
3078 if keyinfo:
3083 key, old, new = keyinfo
3079 key, old, new = keyinfo
3084 r = target.pushkey(namespace, key, old, new)
3080 r = target.pushkey(namespace, key, old, new)
3085 ui.status(str(r) + '\n')
3081 ui.status(str(r) + '\n')
3086 return not r
3082 return not r
3087 else:
3083 else:
3088 for k, v in sorted(target.listkeys(namespace).iteritems()):
3084 for k, v in sorted(target.listkeys(namespace).iteritems()):
3089 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3085 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3090 v.encode('string-escape')))
3086 v.encode('string-escape')))
3091
3087
3092 @command('debugpvec', [], _('A B'))
3088 @command('debugpvec', [], _('A B'))
3093 def debugpvec(ui, repo, a, b=None):
3089 def debugpvec(ui, repo, a, b=None):
3094 ca = scmutil.revsingle(repo, a)
3090 ca = scmutil.revsingle(repo, a)
3095 cb = scmutil.revsingle(repo, b)
3091 cb = scmutil.revsingle(repo, b)
3096 pa = pvec.ctxpvec(ca)
3092 pa = pvec.ctxpvec(ca)
3097 pb = pvec.ctxpvec(cb)
3093 pb = pvec.ctxpvec(cb)
3098 if pa == pb:
3094 if pa == pb:
3099 rel = "="
3095 rel = "="
3100 elif pa > pb:
3096 elif pa > pb:
3101 rel = ">"
3097 rel = ">"
3102 elif pa < pb:
3098 elif pa < pb:
3103 rel = "<"
3099 rel = "<"
3104 elif pa | pb:
3100 elif pa | pb:
3105 rel = "|"
3101 rel = "|"
3106 ui.write(_("a: %s\n") % pa)
3102 ui.write(_("a: %s\n") % pa)
3107 ui.write(_("b: %s\n") % pb)
3103 ui.write(_("b: %s\n") % pb)
3108 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3104 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3109 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3105 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3110 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3106 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3111 pa.distance(pb), rel))
3107 pa.distance(pb), rel))
3112
3108
3113 @command('debugrebuilddirstate|debugrebuildstate',
3109 @command('debugrebuilddirstate|debugrebuildstate',
3114 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3110 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3115 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3111 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3116 'the working copy parent')),
3112 'the working copy parent')),
3117 ],
3113 ],
3118 _('[-r REV]'))
3114 _('[-r REV]'))
3119 def debugrebuilddirstate(ui, repo, rev, **opts):
3115 def debugrebuilddirstate(ui, repo, rev, **opts):
3120 """rebuild the dirstate as it would look like for the given revision
3116 """rebuild the dirstate as it would look like for the given revision
3121
3117
3122 If no revision is specified the first current parent will be used.
3118 If no revision is specified the first current parent will be used.
3123
3119
3124 The dirstate will be set to the files of the given revision.
3120 The dirstate will be set to the files of the given revision.
3125 The actual working directory content or existing dirstate
3121 The actual working directory content or existing dirstate
3126 information such as adds or removes is not considered.
3122 information such as adds or removes is not considered.
3127
3123
3128 ``minimal`` will only rebuild the dirstate status for files that claim to be
3124 ``minimal`` will only rebuild the dirstate status for files that claim to be
3129 tracked but are not in the parent manifest, or that exist in the parent
3125 tracked but are not in the parent manifest, or that exist in the parent
3130 manifest but are not in the dirstate. It will not change adds, removes, or
3126 manifest but are not in the dirstate. It will not change adds, removes, or
3131 modified files that are in the working copy parent.
3127 modified files that are in the working copy parent.
3132
3128
3133 One use of this command is to make the next :hg:`status` invocation
3129 One use of this command is to make the next :hg:`status` invocation
3134 check the actual file content.
3130 check the actual file content.
3135 """
3131 """
3136 ctx = scmutil.revsingle(repo, rev)
3132 ctx = scmutil.revsingle(repo, rev)
3137 wlock = repo.wlock()
3133 wlock = repo.wlock()
3138 try:
3134 try:
3139 dirstate = repo.dirstate
3135 dirstate = repo.dirstate
3140 changedfiles = None
3136 changedfiles = None
3141 # See command doc for what minimal does.
3137 # See command doc for what minimal does.
3142 if opts.get('minimal'):
3138 if opts.get('minimal'):
3143 manifestfiles = set(ctx.manifest().keys())
3139 manifestfiles = set(ctx.manifest().keys())
3144 dirstatefiles = set(dirstate)
3140 dirstatefiles = set(dirstate)
3145 manifestonly = manifestfiles - dirstatefiles
3141 manifestonly = manifestfiles - dirstatefiles
3146 dsonly = dirstatefiles - manifestfiles
3142 dsonly = dirstatefiles - manifestfiles
3147 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3143 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3148 changedfiles = manifestonly | dsnotadded
3144 changedfiles = manifestonly | dsnotadded
3149
3145
3150 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3146 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3151 finally:
3147 finally:
3152 wlock.release()
3148 wlock.release()
3153
3149
3154 @command('debugrebuildfncache', [], '')
3150 @command('debugrebuildfncache', [], '')
3155 def debugrebuildfncache(ui, repo):
3151 def debugrebuildfncache(ui, repo):
3156 """rebuild the fncache file"""
3152 """rebuild the fncache file"""
3157 repair.rebuildfncache(ui, repo)
3153 repair.rebuildfncache(ui, repo)
3158
3154
3159 @command('debugrename',
3155 @command('debugrename',
3160 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3156 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3161 _('[-r REV] FILE'))
3157 _('[-r REV] FILE'))
3162 def debugrename(ui, repo, file1, *pats, **opts):
3158 def debugrename(ui, repo, file1, *pats, **opts):
3163 """dump rename information"""
3159 """dump rename information"""
3164
3160
3165 ctx = scmutil.revsingle(repo, opts.get('rev'))
3161 ctx = scmutil.revsingle(repo, opts.get('rev'))
3166 m = scmutil.match(ctx, (file1,) + pats, opts)
3162 m = scmutil.match(ctx, (file1,) + pats, opts)
3167 for abs in ctx.walk(m):
3163 for abs in ctx.walk(m):
3168 fctx = ctx[abs]
3164 fctx = ctx[abs]
3169 o = fctx.filelog().renamed(fctx.filenode())
3165 o = fctx.filelog().renamed(fctx.filenode())
3170 rel = m.rel(abs)
3166 rel = m.rel(abs)
3171 if o:
3167 if o:
3172 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3168 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3173 else:
3169 else:
3174 ui.write(_("%s not renamed\n") % rel)
3170 ui.write(_("%s not renamed\n") % rel)
3175
3171
3176 @command('debugrevlog', debugrevlogopts +
3172 @command('debugrevlog', debugrevlogopts +
3177 [('d', 'dump', False, _('dump index data'))],
3173 [('d', 'dump', False, _('dump index data'))],
3178 _('-c|-m|FILE'),
3174 _('-c|-m|FILE'),
3179 optionalrepo=True)
3175 optionalrepo=True)
3180 def debugrevlog(ui, repo, file_=None, **opts):
3176 def debugrevlog(ui, repo, file_=None, **opts):
3181 """show data and statistics about a revlog"""
3177 """show data and statistics about a revlog"""
3182 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3178 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3183
3179
3184 if opts.get("dump"):
3180 if opts.get("dump"):
3185 numrevs = len(r)
3181 numrevs = len(r)
3186 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3182 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3187 " rawsize totalsize compression heads chainlen\n")
3183 " rawsize totalsize compression heads chainlen\n")
3188 ts = 0
3184 ts = 0
3189 heads = set()
3185 heads = set()
3190
3186
3191 for rev in xrange(numrevs):
3187 for rev in xrange(numrevs):
3192 dbase = r.deltaparent(rev)
3188 dbase = r.deltaparent(rev)
3193 if dbase == -1:
3189 if dbase == -1:
3194 dbase = rev
3190 dbase = rev
3195 cbase = r.chainbase(rev)
3191 cbase = r.chainbase(rev)
3196 clen = r.chainlen(rev)
3192 clen = r.chainlen(rev)
3197 p1, p2 = r.parentrevs(rev)
3193 p1, p2 = r.parentrevs(rev)
3198 rs = r.rawsize(rev)
3194 rs = r.rawsize(rev)
3199 ts = ts + rs
3195 ts = ts + rs
3200 heads -= set(r.parentrevs(rev))
3196 heads -= set(r.parentrevs(rev))
3201 heads.add(rev)
3197 heads.add(rev)
3202 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3198 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3203 "%11d %5d %8d\n" %
3199 "%11d %5d %8d\n" %
3204 (rev, p1, p2, r.start(rev), r.end(rev),
3200 (rev, p1, p2, r.start(rev), r.end(rev),
3205 r.start(dbase), r.start(cbase),
3201 r.start(dbase), r.start(cbase),
3206 r.start(p1), r.start(p2),
3202 r.start(p1), r.start(p2),
3207 rs, ts, ts / r.end(rev), len(heads), clen))
3203 rs, ts, ts / r.end(rev), len(heads), clen))
3208 return 0
3204 return 0
3209
3205
3210 v = r.version
3206 v = r.version
3211 format = v & 0xFFFF
3207 format = v & 0xFFFF
3212 flags = []
3208 flags = []
3213 gdelta = False
3209 gdelta = False
3214 if v & revlog.REVLOGNGINLINEDATA:
3210 if v & revlog.REVLOGNGINLINEDATA:
3215 flags.append('inline')
3211 flags.append('inline')
3216 if v & revlog.REVLOGGENERALDELTA:
3212 if v & revlog.REVLOGGENERALDELTA:
3217 gdelta = True
3213 gdelta = True
3218 flags.append('generaldelta')
3214 flags.append('generaldelta')
3219 if not flags:
3215 if not flags:
3220 flags = ['(none)']
3216 flags = ['(none)']
3221
3217
3222 nummerges = 0
3218 nummerges = 0
3223 numfull = 0
3219 numfull = 0
3224 numprev = 0
3220 numprev = 0
3225 nump1 = 0
3221 nump1 = 0
3226 nump2 = 0
3222 nump2 = 0
3227 numother = 0
3223 numother = 0
3228 nump1prev = 0
3224 nump1prev = 0
3229 nump2prev = 0
3225 nump2prev = 0
3230 chainlengths = []
3226 chainlengths = []
3231
3227
3232 datasize = [None, 0, 0L]
3228 datasize = [None, 0, 0L]
3233 fullsize = [None, 0, 0L]
3229 fullsize = [None, 0, 0L]
3234 deltasize = [None, 0, 0L]
3230 deltasize = [None, 0, 0L]
3235
3231
3236 def addsize(size, l):
3232 def addsize(size, l):
3237 if l[0] is None or size < l[0]:
3233 if l[0] is None or size < l[0]:
3238 l[0] = size
3234 l[0] = size
3239 if size > l[1]:
3235 if size > l[1]:
3240 l[1] = size
3236 l[1] = size
3241 l[2] += size
3237 l[2] += size
3242
3238
3243 numrevs = len(r)
3239 numrevs = len(r)
3244 for rev in xrange(numrevs):
3240 for rev in xrange(numrevs):
3245 p1, p2 = r.parentrevs(rev)
3241 p1, p2 = r.parentrevs(rev)
3246 delta = r.deltaparent(rev)
3242 delta = r.deltaparent(rev)
3247 if format > 0:
3243 if format > 0:
3248 addsize(r.rawsize(rev), datasize)
3244 addsize(r.rawsize(rev), datasize)
3249 if p2 != nullrev:
3245 if p2 != nullrev:
3250 nummerges += 1
3246 nummerges += 1
3251 size = r.length(rev)
3247 size = r.length(rev)
3252 if delta == nullrev:
3248 if delta == nullrev:
3253 chainlengths.append(0)
3249 chainlengths.append(0)
3254 numfull += 1
3250 numfull += 1
3255 addsize(size, fullsize)
3251 addsize(size, fullsize)
3256 else:
3252 else:
3257 chainlengths.append(chainlengths[delta] + 1)
3253 chainlengths.append(chainlengths[delta] + 1)
3258 addsize(size, deltasize)
3254 addsize(size, deltasize)
3259 if delta == rev - 1:
3255 if delta == rev - 1:
3260 numprev += 1
3256 numprev += 1
3261 if delta == p1:
3257 if delta == p1:
3262 nump1prev += 1
3258 nump1prev += 1
3263 elif delta == p2:
3259 elif delta == p2:
3264 nump2prev += 1
3260 nump2prev += 1
3265 elif delta == p1:
3261 elif delta == p1:
3266 nump1 += 1
3262 nump1 += 1
3267 elif delta == p2:
3263 elif delta == p2:
3268 nump2 += 1
3264 nump2 += 1
3269 elif delta != nullrev:
3265 elif delta != nullrev:
3270 numother += 1
3266 numother += 1
3271
3267
3272 # Adjust size min value for empty cases
3268 # Adjust size min value for empty cases
3273 for size in (datasize, fullsize, deltasize):
3269 for size in (datasize, fullsize, deltasize):
3274 if size[0] is None:
3270 if size[0] is None:
3275 size[0] = 0
3271 size[0] = 0
3276
3272
3277 numdeltas = numrevs - numfull
3273 numdeltas = numrevs - numfull
3278 numoprev = numprev - nump1prev - nump2prev
3274 numoprev = numprev - nump1prev - nump2prev
3279 totalrawsize = datasize[2]
3275 totalrawsize = datasize[2]
3280 datasize[2] /= numrevs
3276 datasize[2] /= numrevs
3281 fulltotal = fullsize[2]
3277 fulltotal = fullsize[2]
3282 fullsize[2] /= numfull
3278 fullsize[2] /= numfull
3283 deltatotal = deltasize[2]
3279 deltatotal = deltasize[2]
3284 if numrevs - numfull > 0:
3280 if numrevs - numfull > 0:
3285 deltasize[2] /= numrevs - numfull
3281 deltasize[2] /= numrevs - numfull
3286 totalsize = fulltotal + deltatotal
3282 totalsize = fulltotal + deltatotal
3287 avgchainlen = sum(chainlengths) / numrevs
3283 avgchainlen = sum(chainlengths) / numrevs
3288 maxchainlen = max(chainlengths)
3284 maxchainlen = max(chainlengths)
3289 compratio = 1
3285 compratio = 1
3290 if totalsize:
3286 if totalsize:
3291 compratio = totalrawsize / totalsize
3287 compratio = totalrawsize / totalsize
3292
3288
3293 basedfmtstr = '%%%dd\n'
3289 basedfmtstr = '%%%dd\n'
3294 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3290 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3295
3291
3296 def dfmtstr(max):
3292 def dfmtstr(max):
3297 return basedfmtstr % len(str(max))
3293 return basedfmtstr % len(str(max))
3298 def pcfmtstr(max, padding=0):
3294 def pcfmtstr(max, padding=0):
3299 return basepcfmtstr % (len(str(max)), ' ' * padding)
3295 return basepcfmtstr % (len(str(max)), ' ' * padding)
3300
3296
3301 def pcfmt(value, total):
3297 def pcfmt(value, total):
3302 if total:
3298 if total:
3303 return (value, 100 * float(value) / total)
3299 return (value, 100 * float(value) / total)
3304 else:
3300 else:
3305 return value, 100.0
3301 return value, 100.0
3306
3302
3307 ui.write(('format : %d\n') % format)
3303 ui.write(('format : %d\n') % format)
3308 ui.write(('flags : %s\n') % ', '.join(flags))
3304 ui.write(('flags : %s\n') % ', '.join(flags))
3309
3305
3310 ui.write('\n')
3306 ui.write('\n')
3311 fmt = pcfmtstr(totalsize)
3307 fmt = pcfmtstr(totalsize)
3312 fmt2 = dfmtstr(totalsize)
3308 fmt2 = dfmtstr(totalsize)
3313 ui.write(('revisions : ') + fmt2 % numrevs)
3309 ui.write(('revisions : ') + fmt2 % numrevs)
3314 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3310 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3315 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3311 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3316 ui.write(('revisions : ') + fmt2 % numrevs)
3312 ui.write(('revisions : ') + fmt2 % numrevs)
3317 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3313 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3318 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3314 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3319 ui.write(('revision size : ') + fmt2 % totalsize)
3315 ui.write(('revision size : ') + fmt2 % totalsize)
3320 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3316 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3321 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3317 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3322
3318
3323 ui.write('\n')
3319 ui.write('\n')
3324 fmt = dfmtstr(max(avgchainlen, compratio))
3320 fmt = dfmtstr(max(avgchainlen, compratio))
3325 ui.write(('avg chain length : ') + fmt % avgchainlen)
3321 ui.write(('avg chain length : ') + fmt % avgchainlen)
3326 ui.write(('max chain length : ') + fmt % maxchainlen)
3322 ui.write(('max chain length : ') + fmt % maxchainlen)
3327 ui.write(('compression ratio : ') + fmt % compratio)
3323 ui.write(('compression ratio : ') + fmt % compratio)
3328
3324
3329 if format > 0:
3325 if format > 0:
3330 ui.write('\n')
3326 ui.write('\n')
3331 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3327 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3332 % tuple(datasize))
3328 % tuple(datasize))
3333 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3329 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3334 % tuple(fullsize))
3330 % tuple(fullsize))
3335 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3331 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3336 % tuple(deltasize))
3332 % tuple(deltasize))
3337
3333
3338 if numdeltas > 0:
3334 if numdeltas > 0:
3339 ui.write('\n')
3335 ui.write('\n')
3340 fmt = pcfmtstr(numdeltas)
3336 fmt = pcfmtstr(numdeltas)
3341 fmt2 = pcfmtstr(numdeltas, 4)
3337 fmt2 = pcfmtstr(numdeltas, 4)
3342 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3338 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3343 if numprev > 0:
3339 if numprev > 0:
3344 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3340 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3345 numprev))
3341 numprev))
3346 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3342 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3347 numprev))
3343 numprev))
3348 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3344 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3349 numprev))
3345 numprev))
3350 if gdelta:
3346 if gdelta:
3351 ui.write(('deltas against p1 : ')
3347 ui.write(('deltas against p1 : ')
3352 + fmt % pcfmt(nump1, numdeltas))
3348 + fmt % pcfmt(nump1, numdeltas))
3353 ui.write(('deltas against p2 : ')
3349 ui.write(('deltas against p2 : ')
3354 + fmt % pcfmt(nump2, numdeltas))
3350 + fmt % pcfmt(nump2, numdeltas))
3355 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3351 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3356 numdeltas))
3352 numdeltas))
3357
3353
3358 @command('debugrevspec',
3354 @command('debugrevspec',
3359 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3355 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3360 ('REVSPEC'))
3356 ('REVSPEC'))
3361 def debugrevspec(ui, repo, expr, **opts):
3357 def debugrevspec(ui, repo, expr, **opts):
3362 """parse and apply a revision specification
3358 """parse and apply a revision specification
3363
3359
3364 Use --verbose to print the parsed tree before and after aliases
3360 Use --verbose to print the parsed tree before and after aliases
3365 expansion.
3361 expansion.
3366 """
3362 """
3367 if ui.verbose:
3363 if ui.verbose:
3368 tree = revset.parse(expr, lookup=repo.__contains__)
3364 tree = revset.parse(expr, lookup=repo.__contains__)
3369 ui.note(revset.prettyformat(tree), "\n")
3365 ui.note(revset.prettyformat(tree), "\n")
3370 newtree = revset.findaliases(ui, tree)
3366 newtree = revset.findaliases(ui, tree)
3371 if newtree != tree:
3367 if newtree != tree:
3372 ui.note(revset.prettyformat(newtree), "\n")
3368 ui.note(revset.prettyformat(newtree), "\n")
3373 tree = newtree
3369 tree = newtree
3374 newtree = revset.foldconcat(tree)
3370 newtree = revset.foldconcat(tree)
3375 if newtree != tree:
3371 if newtree != tree:
3376 ui.note(revset.prettyformat(newtree), "\n")
3372 ui.note(revset.prettyformat(newtree), "\n")
3377 if opts["optimize"]:
3373 if opts["optimize"]:
3378 weight, optimizedtree = revset.optimize(newtree, True)
3374 weight, optimizedtree = revset.optimize(newtree, True)
3379 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3375 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3380 func = revset.match(ui, expr, repo)
3376 func = revset.match(ui, expr, repo)
3381 revs = func(repo)
3377 revs = func(repo)
3382 if ui.verbose:
3378 if ui.verbose:
3383 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3379 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3384 for c in revs:
3380 for c in revs:
3385 ui.write("%s\n" % c)
3381 ui.write("%s\n" % c)
3386
3382
3387 @command('debugsetparents', [], _('REV1 [REV2]'))
3383 @command('debugsetparents', [], _('REV1 [REV2]'))
3388 def debugsetparents(ui, repo, rev1, rev2=None):
3384 def debugsetparents(ui, repo, rev1, rev2=None):
3389 """manually set the parents of the current working directory
3385 """manually set the parents of the current working directory
3390
3386
3391 This is useful for writing repository conversion tools, but should
3387 This is useful for writing repository conversion tools, but should
3392 be used with care. For example, neither the working directory nor the
3388 be used with care. For example, neither the working directory nor the
3393 dirstate is updated, so file status may be incorrect after running this
3389 dirstate is updated, so file status may be incorrect after running this
3394 command.
3390 command.
3395
3391
3396 Returns 0 on success.
3392 Returns 0 on success.
3397 """
3393 """
3398
3394
3399 r1 = scmutil.revsingle(repo, rev1).node()
3395 r1 = scmutil.revsingle(repo, rev1).node()
3400 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3396 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3401
3397
3402 wlock = repo.wlock()
3398 wlock = repo.wlock()
3403 try:
3399 try:
3404 repo.dirstate.beginparentchange()
3400 repo.dirstate.beginparentchange()
3405 repo.setparents(r1, r2)
3401 repo.setparents(r1, r2)
3406 repo.dirstate.endparentchange()
3402 repo.dirstate.endparentchange()
3407 finally:
3403 finally:
3408 wlock.release()
3404 wlock.release()
3409
3405
3410 @command('debugdirstate|debugstate',
3406 @command('debugdirstate|debugstate',
3411 [('', 'nodates', None, _('do not display the saved mtime')),
3407 [('', 'nodates', None, _('do not display the saved mtime')),
3412 ('', 'datesort', None, _('sort by saved mtime'))],
3408 ('', 'datesort', None, _('sort by saved mtime'))],
3413 _('[OPTION]...'))
3409 _('[OPTION]...'))
3414 def debugstate(ui, repo, **opts):
3410 def debugstate(ui, repo, **opts):
3415 """show the contents of the current dirstate"""
3411 """show the contents of the current dirstate"""
3416
3412
3417 nodates = opts.get('nodates')
3413 nodates = opts.get('nodates')
3418 datesort = opts.get('datesort')
3414 datesort = opts.get('datesort')
3419
3415
3420 timestr = ""
3416 timestr = ""
3421 if datesort:
3417 if datesort:
3422 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3418 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3423 else:
3419 else:
3424 keyfunc = None # sort by filename
3420 keyfunc = None # sort by filename
3425 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3421 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3426 if ent[3] == -1:
3422 if ent[3] == -1:
3427 timestr = 'unset '
3423 timestr = 'unset '
3428 elif nodates:
3424 elif nodates:
3429 timestr = 'set '
3425 timestr = 'set '
3430 else:
3426 else:
3431 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3427 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3432 time.localtime(ent[3]))
3428 time.localtime(ent[3]))
3433 if ent[1] & 0o20000:
3429 if ent[1] & 0o20000:
3434 mode = 'lnk'
3430 mode = 'lnk'
3435 else:
3431 else:
3436 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3432 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3437 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3433 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3438 for f in repo.dirstate.copies():
3434 for f in repo.dirstate.copies():
3439 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3435 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3440
3436
3441 @command('debugsub',
3437 @command('debugsub',
3442 [('r', 'rev', '',
3438 [('r', 'rev', '',
3443 _('revision to check'), _('REV'))],
3439 _('revision to check'), _('REV'))],
3444 _('[-r REV] [REV]'))
3440 _('[-r REV] [REV]'))
3445 def debugsub(ui, repo, rev=None):
3441 def debugsub(ui, repo, rev=None):
3446 ctx = scmutil.revsingle(repo, rev, None)
3442 ctx = scmutil.revsingle(repo, rev, None)
3447 for k, v in sorted(ctx.substate.items()):
3443 for k, v in sorted(ctx.substate.items()):
3448 ui.write(('path %s\n') % k)
3444 ui.write(('path %s\n') % k)
3449 ui.write((' source %s\n') % v[0])
3445 ui.write((' source %s\n') % v[0])
3450 ui.write((' revision %s\n') % v[1])
3446 ui.write((' revision %s\n') % v[1])
3451
3447
3452 @command('debugsuccessorssets',
3448 @command('debugsuccessorssets',
3453 [],
3449 [],
3454 _('[REV]'))
3450 _('[REV]'))
3455 def debugsuccessorssets(ui, repo, *revs):
3451 def debugsuccessorssets(ui, repo, *revs):
3456 """show set of successors for revision
3452 """show set of successors for revision
3457
3453
3458 A successors set of changeset A is a consistent group of revisions that
3454 A successors set of changeset A is a consistent group of revisions that
3459 succeed A. It contains non-obsolete changesets only.
3455 succeed A. It contains non-obsolete changesets only.
3460
3456
3461 In most cases a changeset A has a single successors set containing a single
3457 In most cases a changeset A has a single successors set containing a single
3462 successor (changeset A replaced by A').
3458 successor (changeset A replaced by A').
3463
3459
3464 A changeset that is made obsolete with no successors are called "pruned".
3460 A changeset that is made obsolete with no successors are called "pruned".
3465 Such changesets have no successors sets at all.
3461 Such changesets have no successors sets at all.
3466
3462
3467 A changeset that has been "split" will have a successors set containing
3463 A changeset that has been "split" will have a successors set containing
3468 more than one successor.
3464 more than one successor.
3469
3465
3470 A changeset that has been rewritten in multiple different ways is called
3466 A changeset that has been rewritten in multiple different ways is called
3471 "divergent". Such changesets have multiple successor sets (each of which
3467 "divergent". Such changesets have multiple successor sets (each of which
3472 may also be split, i.e. have multiple successors).
3468 may also be split, i.e. have multiple successors).
3473
3469
3474 Results are displayed as follows::
3470 Results are displayed as follows::
3475
3471
3476 <rev1>
3472 <rev1>
3477 <successors-1A>
3473 <successors-1A>
3478 <rev2>
3474 <rev2>
3479 <successors-2A>
3475 <successors-2A>
3480 <successors-2B1> <successors-2B2> <successors-2B3>
3476 <successors-2B1> <successors-2B2> <successors-2B3>
3481
3477
3482 Here rev2 has two possible (i.e. divergent) successors sets. The first
3478 Here rev2 has two possible (i.e. divergent) successors sets. The first
3483 holds one element, whereas the second holds three (i.e. the changeset has
3479 holds one element, whereas the second holds three (i.e. the changeset has
3484 been split).
3480 been split).
3485 """
3481 """
3486 # passed to successorssets caching computation from one call to another
3482 # passed to successorssets caching computation from one call to another
3487 cache = {}
3483 cache = {}
3488 ctx2str = str
3484 ctx2str = str
3489 node2str = short
3485 node2str = short
3490 if ui.debug():
3486 if ui.debug():
3491 def ctx2str(ctx):
3487 def ctx2str(ctx):
3492 return ctx.hex()
3488 return ctx.hex()
3493 node2str = hex
3489 node2str = hex
3494 for rev in scmutil.revrange(repo, revs):
3490 for rev in scmutil.revrange(repo, revs):
3495 ctx = repo[rev]
3491 ctx = repo[rev]
3496 ui.write('%s\n'% ctx2str(ctx))
3492 ui.write('%s\n'% ctx2str(ctx))
3497 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3493 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3498 if succsset:
3494 if succsset:
3499 ui.write(' ')
3495 ui.write(' ')
3500 ui.write(node2str(succsset[0]))
3496 ui.write(node2str(succsset[0]))
3501 for node in succsset[1:]:
3497 for node in succsset[1:]:
3502 ui.write(' ')
3498 ui.write(' ')
3503 ui.write(node2str(node))
3499 ui.write(node2str(node))
3504 ui.write('\n')
3500 ui.write('\n')
3505
3501
3506 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3502 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3507 def debugwalk(ui, repo, *pats, **opts):
3503 def debugwalk(ui, repo, *pats, **opts):
3508 """show how files match on given patterns"""
3504 """show how files match on given patterns"""
3509 m = scmutil.match(repo[None], pats, opts)
3505 m = scmutil.match(repo[None], pats, opts)
3510 items = list(repo.walk(m))
3506 items = list(repo.walk(m))
3511 if not items:
3507 if not items:
3512 return
3508 return
3513 f = lambda fn: fn
3509 f = lambda fn: fn
3514 if ui.configbool('ui', 'slash') and os.sep != '/':
3510 if ui.configbool('ui', 'slash') and os.sep != '/':
3515 f = lambda fn: util.normpath(fn)
3511 f = lambda fn: util.normpath(fn)
3516 fmt = 'f %%-%ds %%-%ds %%s' % (
3512 fmt = 'f %%-%ds %%-%ds %%s' % (
3517 max([len(abs) for abs in items]),
3513 max([len(abs) for abs in items]),
3518 max([len(m.rel(abs)) for abs in items]))
3514 max([len(m.rel(abs)) for abs in items]))
3519 for abs in items:
3515 for abs in items:
3520 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3516 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3521 ui.write("%s\n" % line.rstrip())
3517 ui.write("%s\n" % line.rstrip())
3522
3518
3523 @command('debugwireargs',
3519 @command('debugwireargs',
3524 [('', 'three', '', 'three'),
3520 [('', 'three', '', 'three'),
3525 ('', 'four', '', 'four'),
3521 ('', 'four', '', 'four'),
3526 ('', 'five', '', 'five'),
3522 ('', 'five', '', 'five'),
3527 ] + remoteopts,
3523 ] + remoteopts,
3528 _('REPO [OPTIONS]... [ONE [TWO]]'),
3524 _('REPO [OPTIONS]... [ONE [TWO]]'),
3529 norepo=True)
3525 norepo=True)
3530 def debugwireargs(ui, repopath, *vals, **opts):
3526 def debugwireargs(ui, repopath, *vals, **opts):
3531 repo = hg.peer(ui, opts, repopath)
3527 repo = hg.peer(ui, opts, repopath)
3532 for opt in remoteopts:
3528 for opt in remoteopts:
3533 del opts[opt[1]]
3529 del opts[opt[1]]
3534 args = {}
3530 args = {}
3535 for k, v in opts.iteritems():
3531 for k, v in opts.iteritems():
3536 if v:
3532 if v:
3537 args[k] = v
3533 args[k] = v
3538 # run twice to check that we don't mess up the stream for the next command
3534 # run twice to check that we don't mess up the stream for the next command
3539 res1 = repo.debugwireargs(*vals, **args)
3535 res1 = repo.debugwireargs(*vals, **args)
3540 res2 = repo.debugwireargs(*vals, **args)
3536 res2 = repo.debugwireargs(*vals, **args)
3541 ui.write("%s\n" % res1)
3537 ui.write("%s\n" % res1)
3542 if res1 != res2:
3538 if res1 != res2:
3543 ui.warn("%s\n" % res2)
3539 ui.warn("%s\n" % res2)
3544
3540
3545 @command('^diff',
3541 @command('^diff',
3546 [('r', 'rev', [], _('revision'), _('REV')),
3542 [('r', 'rev', [], _('revision'), _('REV')),
3547 ('c', 'change', '', _('change made by revision'), _('REV'))
3543 ('c', 'change', '', _('change made by revision'), _('REV'))
3548 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3544 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3549 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3545 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3550 inferrepo=True)
3546 inferrepo=True)
3551 def diff(ui, repo, *pats, **opts):
3547 def diff(ui, repo, *pats, **opts):
3552 """diff repository (or selected files)
3548 """diff repository (or selected files)
3553
3549
3554 Show differences between revisions for the specified files.
3550 Show differences between revisions for the specified files.
3555
3551
3556 Differences between files are shown using the unified diff format.
3552 Differences between files are shown using the unified diff format.
3557
3553
3558 .. note::
3554 .. note::
3559
3555
3560 :hg:`diff` may generate unexpected results for merges, as it will
3556 :hg:`diff` may generate unexpected results for merges, as it will
3561 default to comparing against the working directory's first
3557 default to comparing against the working directory's first
3562 parent changeset if no revisions are specified.
3558 parent changeset if no revisions are specified.
3563
3559
3564 When two revision arguments are given, then changes are shown
3560 When two revision arguments are given, then changes are shown
3565 between those revisions. If only one revision is specified then
3561 between those revisions. If only one revision is specified then
3566 that revision is compared to the working directory, and, when no
3562 that revision is compared to the working directory, and, when no
3567 revisions are specified, the working directory files are compared
3563 revisions are specified, the working directory files are compared
3568 to its first parent.
3564 to its first parent.
3569
3565
3570 Alternatively you can specify -c/--change with a revision to see
3566 Alternatively you can specify -c/--change with a revision to see
3571 the changes in that changeset relative to its first parent.
3567 the changes in that changeset relative to its first parent.
3572
3568
3573 Without the -a/--text option, diff will avoid generating diffs of
3569 Without the -a/--text option, diff will avoid generating diffs of
3574 files it detects as binary. With -a, diff will generate a diff
3570 files it detects as binary. With -a, diff will generate a diff
3575 anyway, probably with undesirable results.
3571 anyway, probably with undesirable results.
3576
3572
3577 Use the -g/--git option to generate diffs in the git extended diff
3573 Use the -g/--git option to generate diffs in the git extended diff
3578 format. For more information, read :hg:`help diffs`.
3574 format. For more information, read :hg:`help diffs`.
3579
3575
3580 .. container:: verbose
3576 .. container:: verbose
3581
3577
3582 Examples:
3578 Examples:
3583
3579
3584 - compare a file in the current working directory to its parent::
3580 - compare a file in the current working directory to its parent::
3585
3581
3586 hg diff foo.c
3582 hg diff foo.c
3587
3583
3588 - compare two historical versions of a directory, with rename info::
3584 - compare two historical versions of a directory, with rename info::
3589
3585
3590 hg diff --git -r 1.0:1.2 lib/
3586 hg diff --git -r 1.0:1.2 lib/
3591
3587
3592 - get change stats relative to the last change on some date::
3588 - get change stats relative to the last change on some date::
3593
3589
3594 hg diff --stat -r "date('may 2')"
3590 hg diff --stat -r "date('may 2')"
3595
3591
3596 - diff all newly-added files that contain a keyword::
3592 - diff all newly-added files that contain a keyword::
3597
3593
3598 hg diff "set:added() and grep(GNU)"
3594 hg diff "set:added() and grep(GNU)"
3599
3595
3600 - compare a revision and its parents::
3596 - compare a revision and its parents::
3601
3597
3602 hg diff -c 9353 # compare against first parent
3598 hg diff -c 9353 # compare against first parent
3603 hg diff -r 9353^:9353 # same using revset syntax
3599 hg diff -r 9353^:9353 # same using revset syntax
3604 hg diff -r 9353^2:9353 # compare against the second parent
3600 hg diff -r 9353^2:9353 # compare against the second parent
3605
3601
3606 Returns 0 on success.
3602 Returns 0 on success.
3607 """
3603 """
3608
3604
3609 revs = opts.get('rev')
3605 revs = opts.get('rev')
3610 change = opts.get('change')
3606 change = opts.get('change')
3611 stat = opts.get('stat')
3607 stat = opts.get('stat')
3612 reverse = opts.get('reverse')
3608 reverse = opts.get('reverse')
3613
3609
3614 if revs and change:
3610 if revs and change:
3615 msg = _('cannot specify --rev and --change at the same time')
3611 msg = _('cannot specify --rev and --change at the same time')
3616 raise error.Abort(msg)
3612 raise error.Abort(msg)
3617 elif change:
3613 elif change:
3618 node2 = scmutil.revsingle(repo, change, None).node()
3614 node2 = scmutil.revsingle(repo, change, None).node()
3619 node1 = repo[node2].p1().node()
3615 node1 = repo[node2].p1().node()
3620 else:
3616 else:
3621 node1, node2 = scmutil.revpair(repo, revs)
3617 node1, node2 = scmutil.revpair(repo, revs)
3622
3618
3623 if reverse:
3619 if reverse:
3624 node1, node2 = node2, node1
3620 node1, node2 = node2, node1
3625
3621
3626 diffopts = patch.diffallopts(ui, opts)
3622 diffopts = patch.diffallopts(ui, opts)
3627 m = scmutil.match(repo[node2], pats, opts)
3623 m = scmutil.match(repo[node2], pats, opts)
3628 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3624 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3629 listsubrepos=opts.get('subrepos'),
3625 listsubrepos=opts.get('subrepos'),
3630 root=opts.get('root'))
3626 root=opts.get('root'))
3631
3627
3632 @command('^export',
3628 @command('^export',
3633 [('o', 'output', '',
3629 [('o', 'output', '',
3634 _('print output to file with formatted name'), _('FORMAT')),
3630 _('print output to file with formatted name'), _('FORMAT')),
3635 ('', 'switch-parent', None, _('diff against the second parent')),
3631 ('', 'switch-parent', None, _('diff against the second parent')),
3636 ('r', 'rev', [], _('revisions to export'), _('REV')),
3632 ('r', 'rev', [], _('revisions to export'), _('REV')),
3637 ] + diffopts,
3633 ] + diffopts,
3638 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3634 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3639 def export(ui, repo, *changesets, **opts):
3635 def export(ui, repo, *changesets, **opts):
3640 """dump the header and diffs for one or more changesets
3636 """dump the header and diffs for one or more changesets
3641
3637
3642 Print the changeset header and diffs for one or more revisions.
3638 Print the changeset header and diffs for one or more revisions.
3643 If no revision is given, the parent of the working directory is used.
3639 If no revision is given, the parent of the working directory is used.
3644
3640
3645 The information shown in the changeset header is: author, date,
3641 The information shown in the changeset header is: author, date,
3646 branch name (if non-default), changeset hash, parent(s) and commit
3642 branch name (if non-default), changeset hash, parent(s) and commit
3647 comment.
3643 comment.
3648
3644
3649 .. note::
3645 .. note::
3650
3646
3651 :hg:`export` may generate unexpected diff output for merge
3647 :hg:`export` may generate unexpected diff output for merge
3652 changesets, as it will compare the merge changeset against its
3648 changesets, as it will compare the merge changeset against its
3653 first parent only.
3649 first parent only.
3654
3650
3655 Output may be to a file, in which case the name of the file is
3651 Output may be to a file, in which case the name of the file is
3656 given using a format string. The formatting rules are as follows:
3652 given using a format string. The formatting rules are as follows:
3657
3653
3658 :``%%``: literal "%" character
3654 :``%%``: literal "%" character
3659 :``%H``: changeset hash (40 hexadecimal digits)
3655 :``%H``: changeset hash (40 hexadecimal digits)
3660 :``%N``: number of patches being generated
3656 :``%N``: number of patches being generated
3661 :``%R``: changeset revision number
3657 :``%R``: changeset revision number
3662 :``%b``: basename of the exporting repository
3658 :``%b``: basename of the exporting repository
3663 :``%h``: short-form changeset hash (12 hexadecimal digits)
3659 :``%h``: short-form changeset hash (12 hexadecimal digits)
3664 :``%m``: first line of the commit message (only alphanumeric characters)
3660 :``%m``: first line of the commit message (only alphanumeric characters)
3665 :``%n``: zero-padded sequence number, starting at 1
3661 :``%n``: zero-padded sequence number, starting at 1
3666 :``%r``: zero-padded changeset revision number
3662 :``%r``: zero-padded changeset revision number
3667
3663
3668 Without the -a/--text option, export will avoid generating diffs
3664 Without the -a/--text option, export will avoid generating diffs
3669 of files it detects as binary. With -a, export will generate a
3665 of files it detects as binary. With -a, export will generate a
3670 diff anyway, probably with undesirable results.
3666 diff anyway, probably with undesirable results.
3671
3667
3672 Use the -g/--git option to generate diffs in the git extended diff
3668 Use the -g/--git option to generate diffs in the git extended diff
3673 format. See :hg:`help diffs` for more information.
3669 format. See :hg:`help diffs` for more information.
3674
3670
3675 With the --switch-parent option, the diff will be against the
3671 With the --switch-parent option, the diff will be against the
3676 second parent. It can be useful to review a merge.
3672 second parent. It can be useful to review a merge.
3677
3673
3678 .. container:: verbose
3674 .. container:: verbose
3679
3675
3680 Examples:
3676 Examples:
3681
3677
3682 - use export and import to transplant a bugfix to the current
3678 - use export and import to transplant a bugfix to the current
3683 branch::
3679 branch::
3684
3680
3685 hg export -r 9353 | hg import -
3681 hg export -r 9353 | hg import -
3686
3682
3687 - export all the changesets between two revisions to a file with
3683 - export all the changesets between two revisions to a file with
3688 rename information::
3684 rename information::
3689
3685
3690 hg export --git -r 123:150 > changes.txt
3686 hg export --git -r 123:150 > changes.txt
3691
3687
3692 - split outgoing changes into a series of patches with
3688 - split outgoing changes into a series of patches with
3693 descriptive names::
3689 descriptive names::
3694
3690
3695 hg export -r "outgoing()" -o "%n-%m.patch"
3691 hg export -r "outgoing()" -o "%n-%m.patch"
3696
3692
3697 Returns 0 on success.
3693 Returns 0 on success.
3698 """
3694 """
3699 changesets += tuple(opts.get('rev', []))
3695 changesets += tuple(opts.get('rev', []))
3700 if not changesets:
3696 if not changesets:
3701 changesets = ['.']
3697 changesets = ['.']
3702 revs = scmutil.revrange(repo, changesets)
3698 revs = scmutil.revrange(repo, changesets)
3703 if not revs:
3699 if not revs:
3704 raise error.Abort(_("export requires at least one changeset"))
3700 raise error.Abort(_("export requires at least one changeset"))
3705 if len(revs) > 1:
3701 if len(revs) > 1:
3706 ui.note(_('exporting patches:\n'))
3702 ui.note(_('exporting patches:\n'))
3707 else:
3703 else:
3708 ui.note(_('exporting patch:\n'))
3704 ui.note(_('exporting patch:\n'))
3709 cmdutil.export(repo, revs, template=opts.get('output'),
3705 cmdutil.export(repo, revs, template=opts.get('output'),
3710 switch_parent=opts.get('switch_parent'),
3706 switch_parent=opts.get('switch_parent'),
3711 opts=patch.diffallopts(ui, opts))
3707 opts=patch.diffallopts(ui, opts))
3712
3708
3713 @command('files',
3709 @command('files',
3714 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3710 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3715 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3711 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3716 ] + walkopts + formatteropts + subrepoopts,
3712 ] + walkopts + formatteropts + subrepoopts,
3717 _('[OPTION]... [PATTERN]...'))
3713 _('[OPTION]... [PATTERN]...'))
3718 def files(ui, repo, *pats, **opts):
3714 def files(ui, repo, *pats, **opts):
3719 """list tracked files
3715 """list tracked files
3720
3716
3721 Print files under Mercurial control in the working directory or
3717 Print files under Mercurial control in the working directory or
3722 specified revision whose names match the given patterns (excluding
3718 specified revision whose names match the given patterns (excluding
3723 removed files).
3719 removed files).
3724
3720
3725 If no patterns are given to match, this command prints the names
3721 If no patterns are given to match, this command prints the names
3726 of all files under Mercurial control in the working directory.
3722 of all files under Mercurial control in the working directory.
3727
3723
3728 .. container:: verbose
3724 .. container:: verbose
3729
3725
3730 Examples:
3726 Examples:
3731
3727
3732 - list all files under the current directory::
3728 - list all files under the current directory::
3733
3729
3734 hg files .
3730 hg files .
3735
3731
3736 - shows sizes and flags for current revision::
3732 - shows sizes and flags for current revision::
3737
3733
3738 hg files -vr .
3734 hg files -vr .
3739
3735
3740 - list all files named README::
3736 - list all files named README::
3741
3737
3742 hg files -I "**/README"
3738 hg files -I "**/README"
3743
3739
3744 - list all binary files::
3740 - list all binary files::
3745
3741
3746 hg files "set:binary()"
3742 hg files "set:binary()"
3747
3743
3748 - find files containing a regular expression::
3744 - find files containing a regular expression::
3749
3745
3750 hg files "set:grep('bob')"
3746 hg files "set:grep('bob')"
3751
3747
3752 - search tracked file contents with xargs and grep::
3748 - search tracked file contents with xargs and grep::
3753
3749
3754 hg files -0 | xargs -0 grep foo
3750 hg files -0 | xargs -0 grep foo
3755
3751
3756 See :hg:`help patterns` and :hg:`help filesets` for more information
3752 See :hg:`help patterns` and :hg:`help filesets` for more information
3757 on specifying file patterns.
3753 on specifying file patterns.
3758
3754
3759 Returns 0 if a match is found, 1 otherwise.
3755 Returns 0 if a match is found, 1 otherwise.
3760
3756
3761 """
3757 """
3762 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3758 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3763
3759
3764 end = '\n'
3760 end = '\n'
3765 if opts.get('print0'):
3761 if opts.get('print0'):
3766 end = '\0'
3762 end = '\0'
3767 fm = ui.formatter('files', opts)
3763 fm = ui.formatter('files', opts)
3768 fmt = '%s' + end
3764 fmt = '%s' + end
3769
3765
3770 m = scmutil.match(ctx, pats, opts)
3766 m = scmutil.match(ctx, pats, opts)
3771 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3767 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3772
3768
3773 fm.end()
3769 fm.end()
3774
3770
3775 return ret
3771 return ret
3776
3772
3777 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3773 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3778 def forget(ui, repo, *pats, **opts):
3774 def forget(ui, repo, *pats, **opts):
3779 """forget the specified files on the next commit
3775 """forget the specified files on the next commit
3780
3776
3781 Mark the specified files so they will no longer be tracked
3777 Mark the specified files so they will no longer be tracked
3782 after the next commit.
3778 after the next commit.
3783
3779
3784 This only removes files from the current branch, not from the
3780 This only removes files from the current branch, not from the
3785 entire project history, and it does not delete them from the
3781 entire project history, and it does not delete them from the
3786 working directory.
3782 working directory.
3787
3783
3788 To delete the file from the working directory, see :hg:`remove`.
3784 To delete the file from the working directory, see :hg:`remove`.
3789
3785
3790 To undo a forget before the next commit, see :hg:`add`.
3786 To undo a forget before the next commit, see :hg:`add`.
3791
3787
3792 .. container:: verbose
3788 .. container:: verbose
3793
3789
3794 Examples:
3790 Examples:
3795
3791
3796 - forget newly-added binary files::
3792 - forget newly-added binary files::
3797
3793
3798 hg forget "set:added() and binary()"
3794 hg forget "set:added() and binary()"
3799
3795
3800 - forget files that would be excluded by .hgignore::
3796 - forget files that would be excluded by .hgignore::
3801
3797
3802 hg forget "set:hgignore()"
3798 hg forget "set:hgignore()"
3803
3799
3804 Returns 0 on success.
3800 Returns 0 on success.
3805 """
3801 """
3806
3802
3807 if not pats:
3803 if not pats:
3808 raise error.Abort(_('no files specified'))
3804 raise error.Abort(_('no files specified'))
3809
3805
3810 m = scmutil.match(repo[None], pats, opts)
3806 m = scmutil.match(repo[None], pats, opts)
3811 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3807 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3812 return rejected and 1 or 0
3808 return rejected and 1 or 0
3813
3809
3814 @command(
3810 @command(
3815 'graft',
3811 'graft',
3816 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3812 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3817 ('c', 'continue', False, _('resume interrupted graft')),
3813 ('c', 'continue', False, _('resume interrupted graft')),
3818 ('e', 'edit', False, _('invoke editor on commit messages')),
3814 ('e', 'edit', False, _('invoke editor on commit messages')),
3819 ('', 'log', None, _('append graft info to log message')),
3815 ('', 'log', None, _('append graft info to log message')),
3820 ('f', 'force', False, _('force graft')),
3816 ('f', 'force', False, _('force graft')),
3821 ('D', 'currentdate', False,
3817 ('D', 'currentdate', False,
3822 _('record the current date as commit date')),
3818 _('record the current date as commit date')),
3823 ('U', 'currentuser', False,
3819 ('U', 'currentuser', False,
3824 _('record the current user as committer'), _('DATE'))]
3820 _('record the current user as committer'), _('DATE'))]
3825 + commitopts2 + mergetoolopts + dryrunopts,
3821 + commitopts2 + mergetoolopts + dryrunopts,
3826 _('[OPTION]... [-r] REV...'))
3822 _('[OPTION]... [-r] REV...'))
3827 def graft(ui, repo, *revs, **opts):
3823 def graft(ui, repo, *revs, **opts):
3828 '''copy changes from other branches onto the current branch
3824 '''copy changes from other branches onto the current branch
3829
3825
3830 This command uses Mercurial's merge logic to copy individual
3826 This command uses Mercurial's merge logic to copy individual
3831 changes from other branches without merging branches in the
3827 changes from other branches without merging branches in the
3832 history graph. This is sometimes known as 'backporting' or
3828 history graph. This is sometimes known as 'backporting' or
3833 'cherry-picking'. By default, graft will copy user, date, and
3829 'cherry-picking'. By default, graft will copy user, date, and
3834 description from the source changesets.
3830 description from the source changesets.
3835
3831
3836 Changesets that are ancestors of the current revision, that have
3832 Changesets that are ancestors of the current revision, that have
3837 already been grafted, or that are merges will be skipped.
3833 already been grafted, or that are merges will be skipped.
3838
3834
3839 If --log is specified, log messages will have a comment appended
3835 If --log is specified, log messages will have a comment appended
3840 of the form::
3836 of the form::
3841
3837
3842 (grafted from CHANGESETHASH)
3838 (grafted from CHANGESETHASH)
3843
3839
3844 If --force is specified, revisions will be grafted even if they
3840 If --force is specified, revisions will be grafted even if they
3845 are already ancestors of or have been grafted to the destination.
3841 are already ancestors of or have been grafted to the destination.
3846 This is useful when the revisions have since been backed out.
3842 This is useful when the revisions have since been backed out.
3847
3843
3848 If a graft merge results in conflicts, the graft process is
3844 If a graft merge results in conflicts, the graft process is
3849 interrupted so that the current merge can be manually resolved.
3845 interrupted so that the current merge can be manually resolved.
3850 Once all conflicts are addressed, the graft process can be
3846 Once all conflicts are addressed, the graft process can be
3851 continued with the -c/--continue option.
3847 continued with the -c/--continue option.
3852
3848
3853 .. note::
3849 .. note::
3854
3850
3855 The -c/--continue option does not reapply earlier options, except
3851 The -c/--continue option does not reapply earlier options, except
3856 for --force.
3852 for --force.
3857
3853
3858 .. container:: verbose
3854 .. container:: verbose
3859
3855
3860 Examples:
3856 Examples:
3861
3857
3862 - copy a single change to the stable branch and edit its description::
3858 - copy a single change to the stable branch and edit its description::
3863
3859
3864 hg update stable
3860 hg update stable
3865 hg graft --edit 9393
3861 hg graft --edit 9393
3866
3862
3867 - graft a range of changesets with one exception, updating dates::
3863 - graft a range of changesets with one exception, updating dates::
3868
3864
3869 hg graft -D "2085::2093 and not 2091"
3865 hg graft -D "2085::2093 and not 2091"
3870
3866
3871 - continue a graft after resolving conflicts::
3867 - continue a graft after resolving conflicts::
3872
3868
3873 hg graft -c
3869 hg graft -c
3874
3870
3875 - show the source of a grafted changeset::
3871 - show the source of a grafted changeset::
3876
3872
3877 hg log --debug -r .
3873 hg log --debug -r .
3878
3874
3879 - show revisions sorted by date::
3875 - show revisions sorted by date::
3880
3876
3881 hg log -r 'sort(all(), date)'
3877 hg log -r 'sort(all(), date)'
3882
3878
3883 See :hg:`help revisions` and :hg:`help revsets` for more about
3879 See :hg:`help revisions` and :hg:`help revsets` for more about
3884 specifying revisions.
3880 specifying revisions.
3885
3881
3886 Returns 0 on successful completion.
3882 Returns 0 on successful completion.
3887 '''
3883 '''
3888 wlock = None
3884 wlock = None
3889 try:
3885 try:
3890 wlock = repo.wlock()
3886 wlock = repo.wlock()
3891 return _dograft(ui, repo, *revs, **opts)
3887 return _dograft(ui, repo, *revs, **opts)
3892 finally:
3888 finally:
3893 release(wlock)
3889 release(wlock)
3894
3890
3895 def _dograft(ui, repo, *revs, **opts):
3891 def _dograft(ui, repo, *revs, **opts):
3896 revs = list(revs)
3892 revs = list(revs)
3897 revs.extend(opts['rev'])
3893 revs.extend(opts['rev'])
3898
3894
3899 if not opts.get('user') and opts.get('currentuser'):
3895 if not opts.get('user') and opts.get('currentuser'):
3900 opts['user'] = ui.username()
3896 opts['user'] = ui.username()
3901 if not opts.get('date') and opts.get('currentdate'):
3897 if not opts.get('date') and opts.get('currentdate'):
3902 opts['date'] = "%d %d" % util.makedate()
3898 opts['date'] = "%d %d" % util.makedate()
3903
3899
3904 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3900 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3905
3901
3906 cont = False
3902 cont = False
3907 if opts['continue']:
3903 if opts['continue']:
3908 cont = True
3904 cont = True
3909 if revs:
3905 if revs:
3910 raise error.Abort(_("can't specify --continue and revisions"))
3906 raise error.Abort(_("can't specify --continue and revisions"))
3911 # read in unfinished revisions
3907 # read in unfinished revisions
3912 try:
3908 try:
3913 nodes = repo.vfs.read('graftstate').splitlines()
3909 nodes = repo.vfs.read('graftstate').splitlines()
3914 revs = [repo[node].rev() for node in nodes]
3910 revs = [repo[node].rev() for node in nodes]
3915 except IOError as inst:
3911 except IOError as inst:
3916 if inst.errno != errno.ENOENT:
3912 if inst.errno != errno.ENOENT:
3917 raise
3913 raise
3918 raise error.Abort(_("no graft state found, can't continue"))
3914 raise error.Abort(_("no graft state found, can't continue"))
3919 else:
3915 else:
3920 cmdutil.checkunfinished(repo)
3916 cmdutil.checkunfinished(repo)
3921 cmdutil.bailifchanged(repo)
3917 cmdutil.bailifchanged(repo)
3922 if not revs:
3918 if not revs:
3923 raise error.Abort(_('no revisions specified'))
3919 raise error.Abort(_('no revisions specified'))
3924 revs = scmutil.revrange(repo, revs)
3920 revs = scmutil.revrange(repo, revs)
3925
3921
3926 skipped = set()
3922 skipped = set()
3927 # check for merges
3923 # check for merges
3928 for rev in repo.revs('%ld and merge()', revs):
3924 for rev in repo.revs('%ld and merge()', revs):
3929 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3925 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3930 skipped.add(rev)
3926 skipped.add(rev)
3931 revs = [r for r in revs if r not in skipped]
3927 revs = [r for r in revs if r not in skipped]
3932 if not revs:
3928 if not revs:
3933 return -1
3929 return -1
3934
3930
3935 # Don't check in the --continue case, in effect retaining --force across
3931 # Don't check in the --continue case, in effect retaining --force across
3936 # --continues. That's because without --force, any revisions we decided to
3932 # --continues. That's because without --force, any revisions we decided to
3937 # skip would have been filtered out here, so they wouldn't have made their
3933 # skip would have been filtered out here, so they wouldn't have made their
3938 # way to the graftstate. With --force, any revisions we would have otherwise
3934 # way to the graftstate. With --force, any revisions we would have otherwise
3939 # skipped would not have been filtered out, and if they hadn't been applied
3935 # skipped would not have been filtered out, and if they hadn't been applied
3940 # already, they'd have been in the graftstate.
3936 # already, they'd have been in the graftstate.
3941 if not (cont or opts.get('force')):
3937 if not (cont or opts.get('force')):
3942 # check for ancestors of dest branch
3938 # check for ancestors of dest branch
3943 crev = repo['.'].rev()
3939 crev = repo['.'].rev()
3944 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3940 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3945 # Cannot use x.remove(y) on smart set, this has to be a list.
3941 # Cannot use x.remove(y) on smart set, this has to be a list.
3946 # XXX make this lazy in the future
3942 # XXX make this lazy in the future
3947 revs = list(revs)
3943 revs = list(revs)
3948 # don't mutate while iterating, create a copy
3944 # don't mutate while iterating, create a copy
3949 for rev in list(revs):
3945 for rev in list(revs):
3950 if rev in ancestors:
3946 if rev in ancestors:
3951 ui.warn(_('skipping ancestor revision %d:%s\n') %
3947 ui.warn(_('skipping ancestor revision %d:%s\n') %
3952 (rev, repo[rev]))
3948 (rev, repo[rev]))
3953 # XXX remove on list is slow
3949 # XXX remove on list is slow
3954 revs.remove(rev)
3950 revs.remove(rev)
3955 if not revs:
3951 if not revs:
3956 return -1
3952 return -1
3957
3953
3958 # analyze revs for earlier grafts
3954 # analyze revs for earlier grafts
3959 ids = {}
3955 ids = {}
3960 for ctx in repo.set("%ld", revs):
3956 for ctx in repo.set("%ld", revs):
3961 ids[ctx.hex()] = ctx.rev()
3957 ids[ctx.hex()] = ctx.rev()
3962 n = ctx.extra().get('source')
3958 n = ctx.extra().get('source')
3963 if n:
3959 if n:
3964 ids[n] = ctx.rev()
3960 ids[n] = ctx.rev()
3965
3961
3966 # check ancestors for earlier grafts
3962 # check ancestors for earlier grafts
3967 ui.debug('scanning for duplicate grafts\n')
3963 ui.debug('scanning for duplicate grafts\n')
3968
3964
3969 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3965 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3970 ctx = repo[rev]
3966 ctx = repo[rev]
3971 n = ctx.extra().get('source')
3967 n = ctx.extra().get('source')
3972 if n in ids:
3968 if n in ids:
3973 try:
3969 try:
3974 r = repo[n].rev()
3970 r = repo[n].rev()
3975 except error.RepoLookupError:
3971 except error.RepoLookupError:
3976 r = None
3972 r = None
3977 if r in revs:
3973 if r in revs:
3978 ui.warn(_('skipping revision %d:%s '
3974 ui.warn(_('skipping revision %d:%s '
3979 '(already grafted to %d:%s)\n')
3975 '(already grafted to %d:%s)\n')
3980 % (r, repo[r], rev, ctx))
3976 % (r, repo[r], rev, ctx))
3981 revs.remove(r)
3977 revs.remove(r)
3982 elif ids[n] in revs:
3978 elif ids[n] in revs:
3983 if r is None:
3979 if r is None:
3984 ui.warn(_('skipping already grafted revision %d:%s '
3980 ui.warn(_('skipping already grafted revision %d:%s '
3985 '(%d:%s also has unknown origin %s)\n')
3981 '(%d:%s also has unknown origin %s)\n')
3986 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3982 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3987 else:
3983 else:
3988 ui.warn(_('skipping already grafted revision %d:%s '
3984 ui.warn(_('skipping already grafted revision %d:%s '
3989 '(%d:%s also has origin %d:%s)\n')
3985 '(%d:%s also has origin %d:%s)\n')
3990 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3986 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3991 revs.remove(ids[n])
3987 revs.remove(ids[n])
3992 elif ctx.hex() in ids:
3988 elif ctx.hex() in ids:
3993 r = ids[ctx.hex()]
3989 r = ids[ctx.hex()]
3994 ui.warn(_('skipping already grafted revision %d:%s '
3990 ui.warn(_('skipping already grafted revision %d:%s '
3995 '(was grafted from %d:%s)\n') %
3991 '(was grafted from %d:%s)\n') %
3996 (r, repo[r], rev, ctx))
3992 (r, repo[r], rev, ctx))
3997 revs.remove(r)
3993 revs.remove(r)
3998 if not revs:
3994 if not revs:
3999 return -1
3995 return -1
4000
3996
4001 for pos, ctx in enumerate(repo.set("%ld", revs)):
3997 for pos, ctx in enumerate(repo.set("%ld", revs)):
4002 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3998 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4003 ctx.description().split('\n', 1)[0])
3999 ctx.description().split('\n', 1)[0])
4004 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4000 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4005 if names:
4001 if names:
4006 desc += ' (%s)' % ' '.join(names)
4002 desc += ' (%s)' % ' '.join(names)
4007 ui.status(_('grafting %s\n') % desc)
4003 ui.status(_('grafting %s\n') % desc)
4008 if opts.get('dry_run'):
4004 if opts.get('dry_run'):
4009 continue
4005 continue
4010
4006
4011 extra = ctx.extra().copy()
4007 extra = ctx.extra().copy()
4012 del extra['branch']
4008 del extra['branch']
4013 source = extra.get('source')
4009 source = extra.get('source')
4014 if source:
4010 if source:
4015 extra['intermediate-source'] = ctx.hex()
4011 extra['intermediate-source'] = ctx.hex()
4016 else:
4012 else:
4017 extra['source'] = ctx.hex()
4013 extra['source'] = ctx.hex()
4018 user = ctx.user()
4014 user = ctx.user()
4019 if opts.get('user'):
4015 if opts.get('user'):
4020 user = opts['user']
4016 user = opts['user']
4021 date = ctx.date()
4017 date = ctx.date()
4022 if opts.get('date'):
4018 if opts.get('date'):
4023 date = opts['date']
4019 date = opts['date']
4024 message = ctx.description()
4020 message = ctx.description()
4025 if opts.get('log'):
4021 if opts.get('log'):
4026 message += '\n(grafted from %s)' % ctx.hex()
4022 message += '\n(grafted from %s)' % ctx.hex()
4027
4023
4028 # we don't merge the first commit when continuing
4024 # we don't merge the first commit when continuing
4029 if not cont:
4025 if not cont:
4030 # perform the graft merge with p1(rev) as 'ancestor'
4026 # perform the graft merge with p1(rev) as 'ancestor'
4031 try:
4027 try:
4032 # ui.forcemerge is an internal variable, do not document
4028 # ui.forcemerge is an internal variable, do not document
4033 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4029 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4034 'graft')
4030 'graft')
4035 stats = mergemod.graft(repo, ctx, ctx.p1(),
4031 stats = mergemod.graft(repo, ctx, ctx.p1(),
4036 ['local', 'graft'])
4032 ['local', 'graft'])
4037 finally:
4033 finally:
4038 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4034 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4039 # report any conflicts
4035 # report any conflicts
4040 if stats and stats[3] > 0:
4036 if stats and stats[3] > 0:
4041 # write out state for --continue
4037 # write out state for --continue
4042 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4038 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4043 repo.vfs.write('graftstate', ''.join(nodelines))
4039 repo.vfs.write('graftstate', ''.join(nodelines))
4044 extra = ''
4040 extra = ''
4045 if opts.get('user'):
4041 if opts.get('user'):
4046 extra += ' --user %s' % opts['user']
4042 extra += ' --user %s' % opts['user']
4047 if opts.get('date'):
4043 if opts.get('date'):
4048 extra += ' --date %s' % opts['date']
4044 extra += ' --date %s' % opts['date']
4049 if opts.get('log'):
4045 if opts.get('log'):
4050 extra += ' --log'
4046 extra += ' --log'
4051 hint=_('use hg resolve and hg graft --continue%s') % extra
4047 hint=_('use hg resolve and hg graft --continue%s') % extra
4052 raise error.Abort(
4048 raise error.Abort(
4053 _("unresolved conflicts, can't continue"),
4049 _("unresolved conflicts, can't continue"),
4054 hint=hint)
4050 hint=hint)
4055 else:
4051 else:
4056 cont = False
4052 cont = False
4057
4053
4058 # commit
4054 # commit
4059 node = repo.commit(text=message, user=user,
4055 node = repo.commit(text=message, user=user,
4060 date=date, extra=extra, editor=editor)
4056 date=date, extra=extra, editor=editor)
4061 if node is None:
4057 if node is None:
4062 ui.warn(
4058 ui.warn(
4063 _('note: graft of %d:%s created no changes to commit\n') %
4059 _('note: graft of %d:%s created no changes to commit\n') %
4064 (ctx.rev(), ctx))
4060 (ctx.rev(), ctx))
4065
4061
4066 # remove state when we complete successfully
4062 # remove state when we complete successfully
4067 if not opts.get('dry_run'):
4063 if not opts.get('dry_run'):
4068 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4064 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4069
4065
4070 return 0
4066 return 0
4071
4067
4072 @command('grep',
4068 @command('grep',
4073 [('0', 'print0', None, _('end fields with NUL')),
4069 [('0', 'print0', None, _('end fields with NUL')),
4074 ('', 'all', None, _('print all revisions that match')),
4070 ('', 'all', None, _('print all revisions that match')),
4075 ('a', 'text', None, _('treat all files as text')),
4071 ('a', 'text', None, _('treat all files as text')),
4076 ('f', 'follow', None,
4072 ('f', 'follow', None,
4077 _('follow changeset history,'
4073 _('follow changeset history,'
4078 ' or file history across copies and renames')),
4074 ' or file history across copies and renames')),
4079 ('i', 'ignore-case', None, _('ignore case when matching')),
4075 ('i', 'ignore-case', None, _('ignore case when matching')),
4080 ('l', 'files-with-matches', None,
4076 ('l', 'files-with-matches', None,
4081 _('print only filenames and revisions that match')),
4077 _('print only filenames and revisions that match')),
4082 ('n', 'line-number', None, _('print matching line numbers')),
4078 ('n', 'line-number', None, _('print matching line numbers')),
4083 ('r', 'rev', [],
4079 ('r', 'rev', [],
4084 _('only search files changed within revision range'), _('REV')),
4080 _('only search files changed within revision range'), _('REV')),
4085 ('u', 'user', None, _('list the author (long with -v)')),
4081 ('u', 'user', None, _('list the author (long with -v)')),
4086 ('d', 'date', None, _('list the date (short with -q)')),
4082 ('d', 'date', None, _('list the date (short with -q)')),
4087 ] + walkopts,
4083 ] + walkopts,
4088 _('[OPTION]... PATTERN [FILE]...'),
4084 _('[OPTION]... PATTERN [FILE]...'),
4089 inferrepo=True)
4085 inferrepo=True)
4090 def grep(ui, repo, pattern, *pats, **opts):
4086 def grep(ui, repo, pattern, *pats, **opts):
4091 """search for a pattern in specified files and revisions
4087 """search for a pattern in specified files and revisions
4092
4088
4093 Search revisions of files for a regular expression.
4089 Search revisions of files for a regular expression.
4094
4090
4095 This command behaves differently than Unix grep. It only accepts
4091 This command behaves differently than Unix grep. It only accepts
4096 Python/Perl regexps. It searches repository history, not the
4092 Python/Perl regexps. It searches repository history, not the
4097 working directory. It always prints the revision number in which a
4093 working directory. It always prints the revision number in which a
4098 match appears.
4094 match appears.
4099
4095
4100 By default, grep only prints output for the first revision of a
4096 By default, grep only prints output for the first revision of a
4101 file in which it finds a match. To get it to print every revision
4097 file in which it finds a match. To get it to print every revision
4102 that contains a change in match status ("-" for a match that
4098 that contains a change in match status ("-" for a match that
4103 becomes a non-match, or "+" for a non-match that becomes a match),
4099 becomes a non-match, or "+" for a non-match that becomes a match),
4104 use the --all flag.
4100 use the --all flag.
4105
4101
4106 Returns 0 if a match is found, 1 otherwise.
4102 Returns 0 if a match is found, 1 otherwise.
4107 """
4103 """
4108 reflags = re.M
4104 reflags = re.M
4109 if opts.get('ignore_case'):
4105 if opts.get('ignore_case'):
4110 reflags |= re.I
4106 reflags |= re.I
4111 try:
4107 try:
4112 regexp = util.re.compile(pattern, reflags)
4108 regexp = util.re.compile(pattern, reflags)
4113 except re.error as inst:
4109 except re.error as inst:
4114 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4110 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4115 return 1
4111 return 1
4116 sep, eol = ':', '\n'
4112 sep, eol = ':', '\n'
4117 if opts.get('print0'):
4113 if opts.get('print0'):
4118 sep = eol = '\0'
4114 sep = eol = '\0'
4119
4115
4120 getfile = util.lrucachefunc(repo.file)
4116 getfile = util.lrucachefunc(repo.file)
4121
4117
4122 def matchlines(body):
4118 def matchlines(body):
4123 begin = 0
4119 begin = 0
4124 linenum = 0
4120 linenum = 0
4125 while begin < len(body):
4121 while begin < len(body):
4126 match = regexp.search(body, begin)
4122 match = regexp.search(body, begin)
4127 if not match:
4123 if not match:
4128 break
4124 break
4129 mstart, mend = match.span()
4125 mstart, mend = match.span()
4130 linenum += body.count('\n', begin, mstart) + 1
4126 linenum += body.count('\n', begin, mstart) + 1
4131 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4127 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4132 begin = body.find('\n', mend) + 1 or len(body) + 1
4128 begin = body.find('\n', mend) + 1 or len(body) + 1
4133 lend = begin - 1
4129 lend = begin - 1
4134 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4130 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4135
4131
4136 class linestate(object):
4132 class linestate(object):
4137 def __init__(self, line, linenum, colstart, colend):
4133 def __init__(self, line, linenum, colstart, colend):
4138 self.line = line
4134 self.line = line
4139 self.linenum = linenum
4135 self.linenum = linenum
4140 self.colstart = colstart
4136 self.colstart = colstart
4141 self.colend = colend
4137 self.colend = colend
4142
4138
4143 def __hash__(self):
4139 def __hash__(self):
4144 return hash((self.linenum, self.line))
4140 return hash((self.linenum, self.line))
4145
4141
4146 def __eq__(self, other):
4142 def __eq__(self, other):
4147 return self.line == other.line
4143 return self.line == other.line
4148
4144
4149 def __iter__(self):
4145 def __iter__(self):
4150 yield (self.line[:self.colstart], '')
4146 yield (self.line[:self.colstart], '')
4151 yield (self.line[self.colstart:self.colend], 'grep.match')
4147 yield (self.line[self.colstart:self.colend], 'grep.match')
4152 rest = self.line[self.colend:]
4148 rest = self.line[self.colend:]
4153 while rest != '':
4149 while rest != '':
4154 match = regexp.search(rest)
4150 match = regexp.search(rest)
4155 if not match:
4151 if not match:
4156 yield (rest, '')
4152 yield (rest, '')
4157 break
4153 break
4158 mstart, mend = match.span()
4154 mstart, mend = match.span()
4159 yield (rest[:mstart], '')
4155 yield (rest[:mstart], '')
4160 yield (rest[mstart:mend], 'grep.match')
4156 yield (rest[mstart:mend], 'grep.match')
4161 rest = rest[mend:]
4157 rest = rest[mend:]
4162
4158
4163 matches = {}
4159 matches = {}
4164 copies = {}
4160 copies = {}
4165 def grepbody(fn, rev, body):
4161 def grepbody(fn, rev, body):
4166 matches[rev].setdefault(fn, [])
4162 matches[rev].setdefault(fn, [])
4167 m = matches[rev][fn]
4163 m = matches[rev][fn]
4168 for lnum, cstart, cend, line in matchlines(body):
4164 for lnum, cstart, cend, line in matchlines(body):
4169 s = linestate(line, lnum, cstart, cend)
4165 s = linestate(line, lnum, cstart, cend)
4170 m.append(s)
4166 m.append(s)
4171
4167
4172 def difflinestates(a, b):
4168 def difflinestates(a, b):
4173 sm = difflib.SequenceMatcher(None, a, b)
4169 sm = difflib.SequenceMatcher(None, a, b)
4174 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4170 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4175 if tag == 'insert':
4171 if tag == 'insert':
4176 for i in xrange(blo, bhi):
4172 for i in xrange(blo, bhi):
4177 yield ('+', b[i])
4173 yield ('+', b[i])
4178 elif tag == 'delete':
4174 elif tag == 'delete':
4179 for i in xrange(alo, ahi):
4175 for i in xrange(alo, ahi):
4180 yield ('-', a[i])
4176 yield ('-', a[i])
4181 elif tag == 'replace':
4177 elif tag == 'replace':
4182 for i in xrange(alo, ahi):
4178 for i in xrange(alo, ahi):
4183 yield ('-', a[i])
4179 yield ('-', a[i])
4184 for i in xrange(blo, bhi):
4180 for i in xrange(blo, bhi):
4185 yield ('+', b[i])
4181 yield ('+', b[i])
4186
4182
4187 def display(fn, ctx, pstates, states):
4183 def display(fn, ctx, pstates, states):
4188 rev = ctx.rev()
4184 rev = ctx.rev()
4189 if ui.quiet:
4185 if ui.quiet:
4190 datefunc = util.shortdate
4186 datefunc = util.shortdate
4191 else:
4187 else:
4192 datefunc = util.datestr
4188 datefunc = util.datestr
4193 found = False
4189 found = False
4194 @util.cachefunc
4190 @util.cachefunc
4195 def binary():
4191 def binary():
4196 flog = getfile(fn)
4192 flog = getfile(fn)
4197 return util.binary(flog.read(ctx.filenode(fn)))
4193 return util.binary(flog.read(ctx.filenode(fn)))
4198
4194
4199 if opts.get('all'):
4195 if opts.get('all'):
4200 iter = difflinestates(pstates, states)
4196 iter = difflinestates(pstates, states)
4201 else:
4197 else:
4202 iter = [('', l) for l in states]
4198 iter = [('', l) for l in states]
4203 for change, l in iter:
4199 for change, l in iter:
4204 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4200 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4205
4201
4206 if opts.get('line_number'):
4202 if opts.get('line_number'):
4207 cols.append((str(l.linenum), 'grep.linenumber'))
4203 cols.append((str(l.linenum), 'grep.linenumber'))
4208 if opts.get('all'):
4204 if opts.get('all'):
4209 cols.append((change, 'grep.change'))
4205 cols.append((change, 'grep.change'))
4210 if opts.get('user'):
4206 if opts.get('user'):
4211 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4207 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4212 if opts.get('date'):
4208 if opts.get('date'):
4213 cols.append((datefunc(ctx.date()), 'grep.date'))
4209 cols.append((datefunc(ctx.date()), 'grep.date'))
4214 for col, label in cols[:-1]:
4210 for col, label in cols[:-1]:
4215 ui.write(col, label=label)
4211 ui.write(col, label=label)
4216 ui.write(sep, label='grep.sep')
4212 ui.write(sep, label='grep.sep')
4217 ui.write(cols[-1][0], label=cols[-1][1])
4213 ui.write(cols[-1][0], label=cols[-1][1])
4218 if not opts.get('files_with_matches'):
4214 if not opts.get('files_with_matches'):
4219 ui.write(sep, label='grep.sep')
4215 ui.write(sep, label='grep.sep')
4220 if not opts.get('text') and binary():
4216 if not opts.get('text') and binary():
4221 ui.write(" Binary file matches")
4217 ui.write(" Binary file matches")
4222 else:
4218 else:
4223 for s, label in l:
4219 for s, label in l:
4224 ui.write(s, label=label)
4220 ui.write(s, label=label)
4225 ui.write(eol)
4221 ui.write(eol)
4226 found = True
4222 found = True
4227 if opts.get('files_with_matches'):
4223 if opts.get('files_with_matches'):
4228 break
4224 break
4229 return found
4225 return found
4230
4226
4231 skip = {}
4227 skip = {}
4232 revfiles = {}
4228 revfiles = {}
4233 matchfn = scmutil.match(repo[None], pats, opts)
4229 matchfn = scmutil.match(repo[None], pats, opts)
4234 found = False
4230 found = False
4235 follow = opts.get('follow')
4231 follow = opts.get('follow')
4236
4232
4237 def prep(ctx, fns):
4233 def prep(ctx, fns):
4238 rev = ctx.rev()
4234 rev = ctx.rev()
4239 pctx = ctx.p1()
4235 pctx = ctx.p1()
4240 parent = pctx.rev()
4236 parent = pctx.rev()
4241 matches.setdefault(rev, {})
4237 matches.setdefault(rev, {})
4242 matches.setdefault(parent, {})
4238 matches.setdefault(parent, {})
4243 files = revfiles.setdefault(rev, [])
4239 files = revfiles.setdefault(rev, [])
4244 for fn in fns:
4240 for fn in fns:
4245 flog = getfile(fn)
4241 flog = getfile(fn)
4246 try:
4242 try:
4247 fnode = ctx.filenode(fn)
4243 fnode = ctx.filenode(fn)
4248 except error.LookupError:
4244 except error.LookupError:
4249 continue
4245 continue
4250
4246
4251 copied = flog.renamed(fnode)
4247 copied = flog.renamed(fnode)
4252 copy = follow and copied and copied[0]
4248 copy = follow and copied and copied[0]
4253 if copy:
4249 if copy:
4254 copies.setdefault(rev, {})[fn] = copy
4250 copies.setdefault(rev, {})[fn] = copy
4255 if fn in skip:
4251 if fn in skip:
4256 if copy:
4252 if copy:
4257 skip[copy] = True
4253 skip[copy] = True
4258 continue
4254 continue
4259 files.append(fn)
4255 files.append(fn)
4260
4256
4261 if fn not in matches[rev]:
4257 if fn not in matches[rev]:
4262 grepbody(fn, rev, flog.read(fnode))
4258 grepbody(fn, rev, flog.read(fnode))
4263
4259
4264 pfn = copy or fn
4260 pfn = copy or fn
4265 if pfn not in matches[parent]:
4261 if pfn not in matches[parent]:
4266 try:
4262 try:
4267 fnode = pctx.filenode(pfn)
4263 fnode = pctx.filenode(pfn)
4268 grepbody(pfn, parent, flog.read(fnode))
4264 grepbody(pfn, parent, flog.read(fnode))
4269 except error.LookupError:
4265 except error.LookupError:
4270 pass
4266 pass
4271
4267
4272 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4268 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4273 rev = ctx.rev()
4269 rev = ctx.rev()
4274 parent = ctx.p1().rev()
4270 parent = ctx.p1().rev()
4275 for fn in sorted(revfiles.get(rev, [])):
4271 for fn in sorted(revfiles.get(rev, [])):
4276 states = matches[rev][fn]
4272 states = matches[rev][fn]
4277 copy = copies.get(rev, {}).get(fn)
4273 copy = copies.get(rev, {}).get(fn)
4278 if fn in skip:
4274 if fn in skip:
4279 if copy:
4275 if copy:
4280 skip[copy] = True
4276 skip[copy] = True
4281 continue
4277 continue
4282 pstates = matches.get(parent, {}).get(copy or fn, [])
4278 pstates = matches.get(parent, {}).get(copy or fn, [])
4283 if pstates or states:
4279 if pstates or states:
4284 r = display(fn, ctx, pstates, states)
4280 r = display(fn, ctx, pstates, states)
4285 found = found or r
4281 found = found or r
4286 if r and not opts.get('all'):
4282 if r and not opts.get('all'):
4287 skip[fn] = True
4283 skip[fn] = True
4288 if copy:
4284 if copy:
4289 skip[copy] = True
4285 skip[copy] = True
4290 del matches[rev]
4286 del matches[rev]
4291 del revfiles[rev]
4287 del revfiles[rev]
4292
4288
4293 return not found
4289 return not found
4294
4290
4295 @command('heads',
4291 @command('heads',
4296 [('r', 'rev', '',
4292 [('r', 'rev', '',
4297 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4293 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4298 ('t', 'topo', False, _('show topological heads only')),
4294 ('t', 'topo', False, _('show topological heads only')),
4299 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4295 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4300 ('c', 'closed', False, _('show normal and closed branch heads')),
4296 ('c', 'closed', False, _('show normal and closed branch heads')),
4301 ] + templateopts,
4297 ] + templateopts,
4302 _('[-ct] [-r STARTREV] [REV]...'))
4298 _('[-ct] [-r STARTREV] [REV]...'))
4303 def heads(ui, repo, *branchrevs, **opts):
4299 def heads(ui, repo, *branchrevs, **opts):
4304 """show branch heads
4300 """show branch heads
4305
4301
4306 With no arguments, show all open branch heads in the repository.
4302 With no arguments, show all open branch heads in the repository.
4307 Branch heads are changesets that have no descendants on the
4303 Branch heads are changesets that have no descendants on the
4308 same branch. They are where development generally takes place and
4304 same branch. They are where development generally takes place and
4309 are the usual targets for update and merge operations.
4305 are the usual targets for update and merge operations.
4310
4306
4311 If one or more REVs are given, only open branch heads on the
4307 If one or more REVs are given, only open branch heads on the
4312 branches associated with the specified changesets are shown. This
4308 branches associated with the specified changesets are shown. This
4313 means that you can use :hg:`heads .` to see the heads on the
4309 means that you can use :hg:`heads .` to see the heads on the
4314 currently checked-out branch.
4310 currently checked-out branch.
4315
4311
4316 If -c/--closed is specified, also show branch heads marked closed
4312 If -c/--closed is specified, also show branch heads marked closed
4317 (see :hg:`commit --close-branch`).
4313 (see :hg:`commit --close-branch`).
4318
4314
4319 If STARTREV is specified, only those heads that are descendants of
4315 If STARTREV is specified, only those heads that are descendants of
4320 STARTREV will be displayed.
4316 STARTREV will be displayed.
4321
4317
4322 If -t/--topo is specified, named branch mechanics will be ignored and only
4318 If -t/--topo is specified, named branch mechanics will be ignored and only
4323 topological heads (changesets with no children) will be shown.
4319 topological heads (changesets with no children) will be shown.
4324
4320
4325 Returns 0 if matching heads are found, 1 if not.
4321 Returns 0 if matching heads are found, 1 if not.
4326 """
4322 """
4327
4323
4328 start = None
4324 start = None
4329 if 'rev' in opts:
4325 if 'rev' in opts:
4330 start = scmutil.revsingle(repo, opts['rev'], None).node()
4326 start = scmutil.revsingle(repo, opts['rev'], None).node()
4331
4327
4332 if opts.get('topo'):
4328 if opts.get('topo'):
4333 heads = [repo[h] for h in repo.heads(start)]
4329 heads = [repo[h] for h in repo.heads(start)]
4334 else:
4330 else:
4335 heads = []
4331 heads = []
4336 for branch in repo.branchmap():
4332 for branch in repo.branchmap():
4337 heads += repo.branchheads(branch, start, opts.get('closed'))
4333 heads += repo.branchheads(branch, start, opts.get('closed'))
4338 heads = [repo[h] for h in heads]
4334 heads = [repo[h] for h in heads]
4339
4335
4340 if branchrevs:
4336 if branchrevs:
4341 branches = set(repo[br].branch() for br in branchrevs)
4337 branches = set(repo[br].branch() for br in branchrevs)
4342 heads = [h for h in heads if h.branch() in branches]
4338 heads = [h for h in heads if h.branch() in branches]
4343
4339
4344 if opts.get('active') and branchrevs:
4340 if opts.get('active') and branchrevs:
4345 dagheads = repo.heads(start)
4341 dagheads = repo.heads(start)
4346 heads = [h for h in heads if h.node() in dagheads]
4342 heads = [h for h in heads if h.node() in dagheads]
4347
4343
4348 if branchrevs:
4344 if branchrevs:
4349 haveheads = set(h.branch() for h in heads)
4345 haveheads = set(h.branch() for h in heads)
4350 if branches - haveheads:
4346 if branches - haveheads:
4351 headless = ', '.join(b for b in branches - haveheads)
4347 headless = ', '.join(b for b in branches - haveheads)
4352 msg = _('no open branch heads found on branches %s')
4348 msg = _('no open branch heads found on branches %s')
4353 if opts.get('rev'):
4349 if opts.get('rev'):
4354 msg += _(' (started at %s)') % opts['rev']
4350 msg += _(' (started at %s)') % opts['rev']
4355 ui.warn((msg + '\n') % headless)
4351 ui.warn((msg + '\n') % headless)
4356
4352
4357 if not heads:
4353 if not heads:
4358 return 1
4354 return 1
4359
4355
4360 heads = sorted(heads, key=lambda x: -x.rev())
4356 heads = sorted(heads, key=lambda x: -x.rev())
4361 displayer = cmdutil.show_changeset(ui, repo, opts)
4357 displayer = cmdutil.show_changeset(ui, repo, opts)
4362 for ctx in heads:
4358 for ctx in heads:
4363 displayer.show(ctx)
4359 displayer.show(ctx)
4364 displayer.close()
4360 displayer.close()
4365
4361
4366 @command('help',
4362 @command('help',
4367 [('e', 'extension', None, _('show only help for extensions')),
4363 [('e', 'extension', None, _('show only help for extensions')),
4368 ('c', 'command', None, _('show only help for commands')),
4364 ('c', 'command', None, _('show only help for commands')),
4369 ('k', 'keyword', None, _('show topics matching keyword')),
4365 ('k', 'keyword', None, _('show topics matching keyword')),
4370 ('s', 'system', [], _('show help for specific platform(s)')),
4366 ('s', 'system', [], _('show help for specific platform(s)')),
4371 ],
4367 ],
4372 _('[-ecks] [TOPIC]'),
4368 _('[-ecks] [TOPIC]'),
4373 norepo=True)
4369 norepo=True)
4374 def help_(ui, name=None, **opts):
4370 def help_(ui, name=None, **opts):
4375 """show help for a given topic or a help overview
4371 """show help for a given topic or a help overview
4376
4372
4377 With no arguments, print a list of commands with short help messages.
4373 With no arguments, print a list of commands with short help messages.
4378
4374
4379 Given a topic, extension, or command name, print help for that
4375 Given a topic, extension, or command name, print help for that
4380 topic.
4376 topic.
4381
4377
4382 Returns 0 if successful.
4378 Returns 0 if successful.
4383 """
4379 """
4384
4380
4385 textwidth = min(ui.termwidth(), 80) - 2
4381 textwidth = min(ui.termwidth(), 80) - 2
4386
4382
4387 keep = opts.get('system') or []
4383 keep = opts.get('system') or []
4388 if len(keep) == 0:
4384 if len(keep) == 0:
4389 if sys.platform.startswith('win'):
4385 if sys.platform.startswith('win'):
4390 keep.append('windows')
4386 keep.append('windows')
4391 elif sys.platform == 'OpenVMS':
4387 elif sys.platform == 'OpenVMS':
4392 keep.append('vms')
4388 keep.append('vms')
4393 elif sys.platform == 'plan9':
4389 elif sys.platform == 'plan9':
4394 keep.append('plan9')
4390 keep.append('plan9')
4395 else:
4391 else:
4396 keep.append('unix')
4392 keep.append('unix')
4397 keep.append(sys.platform.lower())
4393 keep.append(sys.platform.lower())
4398 if ui.verbose:
4394 if ui.verbose:
4399 keep.append('verbose')
4395 keep.append('verbose')
4400
4396
4401 section = None
4397 section = None
4402 subtopic = None
4398 subtopic = None
4403 if name and '.' in name:
4399 if name and '.' in name:
4404 name, section = name.split('.', 1)
4400 name, section = name.split('.', 1)
4405 section = section.lower()
4401 section = section.lower()
4406 if '.' in section:
4402 if '.' in section:
4407 subtopic, section = section.split('.', 1)
4403 subtopic, section = section.split('.', 1)
4408 else:
4404 else:
4409 subtopic = section
4405 subtopic = section
4410
4406
4411 text = help.help_(ui, name, subtopic=subtopic, **opts)
4407 text = help.help_(ui, name, subtopic=subtopic, **opts)
4412
4408
4413 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4409 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4414 section=section)
4410 section=section)
4415
4411
4416 # We could have been given a weird ".foo" section without a name
4412 # We could have been given a weird ".foo" section without a name
4417 # to look for, or we could have simply failed to found "foo.bar"
4413 # to look for, or we could have simply failed to found "foo.bar"
4418 # because bar isn't a section of foo
4414 # because bar isn't a section of foo
4419 if section and not (formatted and name):
4415 if section and not (formatted and name):
4420 raise error.Abort(_("help section not found"))
4416 raise error.Abort(_("help section not found"))
4421
4417
4422 if 'verbose' in pruned:
4418 if 'verbose' in pruned:
4423 keep.append('omitted')
4419 keep.append('omitted')
4424 else:
4420 else:
4425 keep.append('notomitted')
4421 keep.append('notomitted')
4426 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4422 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4427 section=section)
4423 section=section)
4428 ui.write(formatted)
4424 ui.write(formatted)
4429
4425
4430
4426
4431 @command('identify|id',
4427 @command('identify|id',
4432 [('r', 'rev', '',
4428 [('r', 'rev', '',
4433 _('identify the specified revision'), _('REV')),
4429 _('identify the specified revision'), _('REV')),
4434 ('n', 'num', None, _('show local revision number')),
4430 ('n', 'num', None, _('show local revision number')),
4435 ('i', 'id', None, _('show global revision id')),
4431 ('i', 'id', None, _('show global revision id')),
4436 ('b', 'branch', None, _('show branch')),
4432 ('b', 'branch', None, _('show branch')),
4437 ('t', 'tags', None, _('show tags')),
4433 ('t', 'tags', None, _('show tags')),
4438 ('B', 'bookmarks', None, _('show bookmarks')),
4434 ('B', 'bookmarks', None, _('show bookmarks')),
4439 ] + remoteopts,
4435 ] + remoteopts,
4440 _('[-nibtB] [-r REV] [SOURCE]'),
4436 _('[-nibtB] [-r REV] [SOURCE]'),
4441 optionalrepo=True)
4437 optionalrepo=True)
4442 def identify(ui, repo, source=None, rev=None,
4438 def identify(ui, repo, source=None, rev=None,
4443 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4439 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4444 """identify the working directory or specified revision
4440 """identify the working directory or specified revision
4445
4441
4446 Print a summary identifying the repository state at REV using one or
4442 Print a summary identifying the repository state at REV using one or
4447 two parent hash identifiers, followed by a "+" if the working
4443 two parent hash identifiers, followed by a "+" if the working
4448 directory has uncommitted changes, the branch name (if not default),
4444 directory has uncommitted changes, the branch name (if not default),
4449 a list of tags, and a list of bookmarks.
4445 a list of tags, and a list of bookmarks.
4450
4446
4451 When REV is not given, print a summary of the current state of the
4447 When REV is not given, print a summary of the current state of the
4452 repository.
4448 repository.
4453
4449
4454 Specifying a path to a repository root or Mercurial bundle will
4450 Specifying a path to a repository root or Mercurial bundle will
4455 cause lookup to operate on that repository/bundle.
4451 cause lookup to operate on that repository/bundle.
4456
4452
4457 .. container:: verbose
4453 .. container:: verbose
4458
4454
4459 Examples:
4455 Examples:
4460
4456
4461 - generate a build identifier for the working directory::
4457 - generate a build identifier for the working directory::
4462
4458
4463 hg id --id > build-id.dat
4459 hg id --id > build-id.dat
4464
4460
4465 - find the revision corresponding to a tag::
4461 - find the revision corresponding to a tag::
4466
4462
4467 hg id -n -r 1.3
4463 hg id -n -r 1.3
4468
4464
4469 - check the most recent revision of a remote repository::
4465 - check the most recent revision of a remote repository::
4470
4466
4471 hg id -r tip http://selenic.com/hg/
4467 hg id -r tip http://selenic.com/hg/
4472
4468
4473 See :hg:`log` for generating more information about specific revisions,
4469 See :hg:`log` for generating more information about specific revisions,
4474 including full hash identifiers.
4470 including full hash identifiers.
4475
4471
4476 Returns 0 if successful.
4472 Returns 0 if successful.
4477 """
4473 """
4478
4474
4479 if not repo and not source:
4475 if not repo and not source:
4480 raise error.Abort(_("there is no Mercurial repository here "
4476 raise error.Abort(_("there is no Mercurial repository here "
4481 "(.hg not found)"))
4477 "(.hg not found)"))
4482
4478
4483 if ui.debugflag:
4479 if ui.debugflag:
4484 hexfunc = hex
4480 hexfunc = hex
4485 else:
4481 else:
4486 hexfunc = short
4482 hexfunc = short
4487 default = not (num or id or branch or tags or bookmarks)
4483 default = not (num or id or branch or tags or bookmarks)
4488 output = []
4484 output = []
4489 revs = []
4485 revs = []
4490
4486
4491 if source:
4487 if source:
4492 source, branches = hg.parseurl(ui.expandpath(source))
4488 source, branches = hg.parseurl(ui.expandpath(source))
4493 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4489 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4494 repo = peer.local()
4490 repo = peer.local()
4495 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4491 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4496
4492
4497 if not repo:
4493 if not repo:
4498 if num or branch or tags:
4494 if num or branch or tags:
4499 raise error.Abort(
4495 raise error.Abort(
4500 _("can't query remote revision number, branch, or tags"))
4496 _("can't query remote revision number, branch, or tags"))
4501 if not rev and revs:
4497 if not rev and revs:
4502 rev = revs[0]
4498 rev = revs[0]
4503 if not rev:
4499 if not rev:
4504 rev = "tip"
4500 rev = "tip"
4505
4501
4506 remoterev = peer.lookup(rev)
4502 remoterev = peer.lookup(rev)
4507 if default or id:
4503 if default or id:
4508 output = [hexfunc(remoterev)]
4504 output = [hexfunc(remoterev)]
4509
4505
4510 def getbms():
4506 def getbms():
4511 bms = []
4507 bms = []
4512
4508
4513 if 'bookmarks' in peer.listkeys('namespaces'):
4509 if 'bookmarks' in peer.listkeys('namespaces'):
4514 hexremoterev = hex(remoterev)
4510 hexremoterev = hex(remoterev)
4515 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4511 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4516 if bmr == hexremoterev]
4512 if bmr == hexremoterev]
4517
4513
4518 return sorted(bms)
4514 return sorted(bms)
4519
4515
4520 if bookmarks:
4516 if bookmarks:
4521 output.extend(getbms())
4517 output.extend(getbms())
4522 elif default and not ui.quiet:
4518 elif default and not ui.quiet:
4523 # multiple bookmarks for a single parent separated by '/'
4519 # multiple bookmarks for a single parent separated by '/'
4524 bm = '/'.join(getbms())
4520 bm = '/'.join(getbms())
4525 if bm:
4521 if bm:
4526 output.append(bm)
4522 output.append(bm)
4527 else:
4523 else:
4528 ctx = scmutil.revsingle(repo, rev, None)
4524 ctx = scmutil.revsingle(repo, rev, None)
4529
4525
4530 if ctx.rev() is None:
4526 if ctx.rev() is None:
4531 ctx = repo[None]
4527 ctx = repo[None]
4532 parents = ctx.parents()
4528 parents = ctx.parents()
4533 taglist = []
4529 taglist = []
4534 for p in parents:
4530 for p in parents:
4535 taglist.extend(p.tags())
4531 taglist.extend(p.tags())
4536
4532
4537 changed = ""
4533 changed = ""
4538 if default or id or num:
4534 if default or id or num:
4539 if (any(repo.status())
4535 if (any(repo.status())
4540 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4536 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4541 changed = '+'
4537 changed = '+'
4542 if default or id:
4538 if default or id:
4543 output = ["%s%s" %
4539 output = ["%s%s" %
4544 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4540 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4545 if num:
4541 if num:
4546 output.append("%s%s" %
4542 output.append("%s%s" %
4547 ('+'.join([str(p.rev()) for p in parents]), changed))
4543 ('+'.join([str(p.rev()) for p in parents]), changed))
4548 else:
4544 else:
4549 if default or id:
4545 if default or id:
4550 output = [hexfunc(ctx.node())]
4546 output = [hexfunc(ctx.node())]
4551 if num:
4547 if num:
4552 output.append(str(ctx.rev()))
4548 output.append(str(ctx.rev()))
4553 taglist = ctx.tags()
4549 taglist = ctx.tags()
4554
4550
4555 if default and not ui.quiet:
4551 if default and not ui.quiet:
4556 b = ctx.branch()
4552 b = ctx.branch()
4557 if b != 'default':
4553 if b != 'default':
4558 output.append("(%s)" % b)
4554 output.append("(%s)" % b)
4559
4555
4560 # multiple tags for a single parent separated by '/'
4556 # multiple tags for a single parent separated by '/'
4561 t = '/'.join(taglist)
4557 t = '/'.join(taglist)
4562 if t:
4558 if t:
4563 output.append(t)
4559 output.append(t)
4564
4560
4565 # multiple bookmarks for a single parent separated by '/'
4561 # multiple bookmarks for a single parent separated by '/'
4566 bm = '/'.join(ctx.bookmarks())
4562 bm = '/'.join(ctx.bookmarks())
4567 if bm:
4563 if bm:
4568 output.append(bm)
4564 output.append(bm)
4569 else:
4565 else:
4570 if branch:
4566 if branch:
4571 output.append(ctx.branch())
4567 output.append(ctx.branch())
4572
4568
4573 if tags:
4569 if tags:
4574 output.extend(taglist)
4570 output.extend(taglist)
4575
4571
4576 if bookmarks:
4572 if bookmarks:
4577 output.extend(ctx.bookmarks())
4573 output.extend(ctx.bookmarks())
4578
4574
4579 ui.write("%s\n" % ' '.join(output))
4575 ui.write("%s\n" % ' '.join(output))
4580
4576
4581 @command('import|patch',
4577 @command('import|patch',
4582 [('p', 'strip', 1,
4578 [('p', 'strip', 1,
4583 _('directory strip option for patch. This has the same '
4579 _('directory strip option for patch. This has the same '
4584 'meaning as the corresponding patch option'), _('NUM')),
4580 'meaning as the corresponding patch option'), _('NUM')),
4585 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4581 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4586 ('e', 'edit', False, _('invoke editor on commit messages')),
4582 ('e', 'edit', False, _('invoke editor on commit messages')),
4587 ('f', 'force', None,
4583 ('f', 'force', None,
4588 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4584 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4589 ('', 'no-commit', None,
4585 ('', 'no-commit', None,
4590 _("don't commit, just update the working directory")),
4586 _("don't commit, just update the working directory")),
4591 ('', 'bypass', None,
4587 ('', 'bypass', None,
4592 _("apply patch without touching the working directory")),
4588 _("apply patch without touching the working directory")),
4593 ('', 'partial', None,
4589 ('', 'partial', None,
4594 _('commit even if some hunks fail')),
4590 _('commit even if some hunks fail')),
4595 ('', 'exact', None,
4591 ('', 'exact', None,
4596 _('apply patch to the nodes from which it was generated')),
4592 _('apply patch to the nodes from which it was generated')),
4597 ('', 'prefix', '',
4593 ('', 'prefix', '',
4598 _('apply patch to subdirectory'), _('DIR')),
4594 _('apply patch to subdirectory'), _('DIR')),
4599 ('', 'import-branch', None,
4595 ('', 'import-branch', None,
4600 _('use any branch information in patch (implied by --exact)'))] +
4596 _('use any branch information in patch (implied by --exact)'))] +
4601 commitopts + commitopts2 + similarityopts,
4597 commitopts + commitopts2 + similarityopts,
4602 _('[OPTION]... PATCH...'))
4598 _('[OPTION]... PATCH...'))
4603 def import_(ui, repo, patch1=None, *patches, **opts):
4599 def import_(ui, repo, patch1=None, *patches, **opts):
4604 """import an ordered set of patches
4600 """import an ordered set of patches
4605
4601
4606 Import a list of patches and commit them individually (unless
4602 Import a list of patches and commit them individually (unless
4607 --no-commit is specified).
4603 --no-commit is specified).
4608
4604
4609 To read a patch from standard input, use "-" as the patch name. If
4605 To read a patch from standard input, use "-" as the patch name. If
4610 a URL is specified, the patch will be downloaded from there.
4606 a URL is specified, the patch will be downloaded from there.
4611
4607
4612 Import first applies changes to the working directory (unless
4608 Import first applies changes to the working directory (unless
4613 --bypass is specified), import will abort if there are outstanding
4609 --bypass is specified), import will abort if there are outstanding
4614 changes.
4610 changes.
4615
4611
4616 Use --bypass to apply and commit patches directly to the
4612 Use --bypass to apply and commit patches directly to the
4617 repository, without affecting the working directory. Without
4613 repository, without affecting the working directory. Without
4618 --exact, patches will be applied on top of the working directory
4614 --exact, patches will be applied on top of the working directory
4619 parent revision.
4615 parent revision.
4620
4616
4621 You can import a patch straight from a mail message. Even patches
4617 You can import a patch straight from a mail message. Even patches
4622 as attachments work (to use the body part, it must have type
4618 as attachments work (to use the body part, it must have type
4623 text/plain or text/x-patch). From and Subject headers of email
4619 text/plain or text/x-patch). From and Subject headers of email
4624 message are used as default committer and commit message. All
4620 message are used as default committer and commit message. All
4625 text/plain body parts before first diff are added to the commit
4621 text/plain body parts before first diff are added to the commit
4626 message.
4622 message.
4627
4623
4628 If the imported patch was generated by :hg:`export`, user and
4624 If the imported patch was generated by :hg:`export`, user and
4629 description from patch override values from message headers and
4625 description from patch override values from message headers and
4630 body. Values given on command line with -m/--message and -u/--user
4626 body. Values given on command line with -m/--message and -u/--user
4631 override these.
4627 override these.
4632
4628
4633 If --exact is specified, import will set the working directory to
4629 If --exact is specified, import will set the working directory to
4634 the parent of each patch before applying it, and will abort if the
4630 the parent of each patch before applying it, and will abort if the
4635 resulting changeset has a different ID than the one recorded in
4631 resulting changeset has a different ID than the one recorded in
4636 the patch. This may happen due to character set problems or other
4632 the patch. This may happen due to character set problems or other
4637 deficiencies in the text patch format.
4633 deficiencies in the text patch format.
4638
4634
4639 Use --partial to ensure a changeset will be created from the patch
4635 Use --partial to ensure a changeset will be created from the patch
4640 even if some hunks fail to apply. Hunks that fail to apply will be
4636 even if some hunks fail to apply. Hunks that fail to apply will be
4641 written to a <target-file>.rej file. Conflicts can then be resolved
4637 written to a <target-file>.rej file. Conflicts can then be resolved
4642 by hand before :hg:`commit --amend` is run to update the created
4638 by hand before :hg:`commit --amend` is run to update the created
4643 changeset. This flag exists to let people import patches that
4639 changeset. This flag exists to let people import patches that
4644 partially apply without losing the associated metadata (author,
4640 partially apply without losing the associated metadata (author,
4645 date, description, ...).
4641 date, description, ...).
4646
4642
4647 .. note::
4643 .. note::
4648
4644
4649 When no hunks apply cleanly, :hg:`import --partial` will create
4645 When no hunks apply cleanly, :hg:`import --partial` will create
4650 an empty changeset, importing only the patch metadata.
4646 an empty changeset, importing only the patch metadata.
4651
4647
4652 With -s/--similarity, hg will attempt to discover renames and
4648 With -s/--similarity, hg will attempt to discover renames and
4653 copies in the patch in the same way as :hg:`addremove`.
4649 copies in the patch in the same way as :hg:`addremove`.
4654
4650
4655 It is possible to use external patch programs to perform the patch
4651 It is possible to use external patch programs to perform the patch
4656 by setting the ``ui.patch`` configuration option. For the default
4652 by setting the ``ui.patch`` configuration option. For the default
4657 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4653 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4658 See :hg:`help config` for more information about configuration
4654 See :hg:`help config` for more information about configuration
4659 files and how to use these options.
4655 files and how to use these options.
4660
4656
4661 See :hg:`help dates` for a list of formats valid for -d/--date.
4657 See :hg:`help dates` for a list of formats valid for -d/--date.
4662
4658
4663 .. container:: verbose
4659 .. container:: verbose
4664
4660
4665 Examples:
4661 Examples:
4666
4662
4667 - import a traditional patch from a website and detect renames::
4663 - import a traditional patch from a website and detect renames::
4668
4664
4669 hg import -s 80 http://example.com/bugfix.patch
4665 hg import -s 80 http://example.com/bugfix.patch
4670
4666
4671 - import a changeset from an hgweb server::
4667 - import a changeset from an hgweb server::
4672
4668
4673 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4669 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4674
4670
4675 - import all the patches in an Unix-style mbox::
4671 - import all the patches in an Unix-style mbox::
4676
4672
4677 hg import incoming-patches.mbox
4673 hg import incoming-patches.mbox
4678
4674
4679 - attempt to exactly restore an exported changeset (not always
4675 - attempt to exactly restore an exported changeset (not always
4680 possible)::
4676 possible)::
4681
4677
4682 hg import --exact proposed-fix.patch
4678 hg import --exact proposed-fix.patch
4683
4679
4684 - use an external tool to apply a patch which is too fuzzy for
4680 - use an external tool to apply a patch which is too fuzzy for
4685 the default internal tool.
4681 the default internal tool.
4686
4682
4687 hg import --config ui.patch="patch --merge" fuzzy.patch
4683 hg import --config ui.patch="patch --merge" fuzzy.patch
4688
4684
4689 - change the default fuzzing from 2 to a less strict 7
4685 - change the default fuzzing from 2 to a less strict 7
4690
4686
4691 hg import --config ui.fuzz=7 fuzz.patch
4687 hg import --config ui.fuzz=7 fuzz.patch
4692
4688
4693 Returns 0 on success, 1 on partial success (see --partial).
4689 Returns 0 on success, 1 on partial success (see --partial).
4694 """
4690 """
4695
4691
4696 if not patch1:
4692 if not patch1:
4697 raise error.Abort(_('need at least one patch to import'))
4693 raise error.Abort(_('need at least one patch to import'))
4698
4694
4699 patches = (patch1,) + patches
4695 patches = (patch1,) + patches
4700
4696
4701 date = opts.get('date')
4697 date = opts.get('date')
4702 if date:
4698 if date:
4703 opts['date'] = util.parsedate(date)
4699 opts['date'] = util.parsedate(date)
4704
4700
4705 exact = opts.get('exact')
4701 exact = opts.get('exact')
4706 update = not opts.get('bypass')
4702 update = not opts.get('bypass')
4707 if not update and opts.get('no_commit'):
4703 if not update and opts.get('no_commit'):
4708 raise error.Abort(_('cannot use --no-commit with --bypass'))
4704 raise error.Abort(_('cannot use --no-commit with --bypass'))
4709 try:
4705 try:
4710 sim = float(opts.get('similarity') or 0)
4706 sim = float(opts.get('similarity') or 0)
4711 except ValueError:
4707 except ValueError:
4712 raise error.Abort(_('similarity must be a number'))
4708 raise error.Abort(_('similarity must be a number'))
4713 if sim < 0 or sim > 100:
4709 if sim < 0 or sim > 100:
4714 raise error.Abort(_('similarity must be between 0 and 100'))
4710 raise error.Abort(_('similarity must be between 0 and 100'))
4715 if sim and not update:
4711 if sim and not update:
4716 raise error.Abort(_('cannot use --similarity with --bypass'))
4712 raise error.Abort(_('cannot use --similarity with --bypass'))
4717 if exact:
4713 if exact:
4718 if opts.get('edit'):
4714 if opts.get('edit'):
4719 raise error.Abort(_('cannot use --exact with --edit'))
4715 raise error.Abort(_('cannot use --exact with --edit'))
4720 if opts.get('prefix'):
4716 if opts.get('prefix'):
4721 raise error.Abort(_('cannot use --exact with --prefix'))
4717 raise error.Abort(_('cannot use --exact with --prefix'))
4722
4718
4723 base = opts["base"]
4719 base = opts["base"]
4724 wlock = dsguard = lock = tr = None
4720 wlock = dsguard = lock = tr = None
4725 msgs = []
4721 msgs = []
4726 ret = 0
4722 ret = 0
4727
4723
4728
4724
4729 try:
4725 try:
4730 wlock = repo.wlock()
4726 wlock = repo.wlock()
4731
4727
4732 if update:
4728 if update:
4733 cmdutil.checkunfinished(repo)
4729 cmdutil.checkunfinished(repo)
4734 if (exact or not opts.get('force')):
4730 if (exact or not opts.get('force')):
4735 cmdutil.bailifchanged(repo)
4731 cmdutil.bailifchanged(repo)
4736
4732
4737 if not opts.get('no_commit'):
4733 if not opts.get('no_commit'):
4738 lock = repo.lock()
4734 lock = repo.lock()
4739 tr = repo.transaction('import')
4735 tr = repo.transaction('import')
4740 else:
4736 else:
4741 dsguard = cmdutil.dirstateguard(repo, 'import')
4737 dsguard = cmdutil.dirstateguard(repo, 'import')
4742 parents = repo[None].parents()
4738 parents = repo[None].parents()
4743 for patchurl in patches:
4739 for patchurl in patches:
4744 if patchurl == '-':
4740 if patchurl == '-':
4745 ui.status(_('applying patch from stdin\n'))
4741 ui.status(_('applying patch from stdin\n'))
4746 patchfile = ui.fin
4742 patchfile = ui.fin
4747 patchurl = 'stdin' # for error message
4743 patchurl = 'stdin' # for error message
4748 else:
4744 else:
4749 patchurl = os.path.join(base, patchurl)
4745 patchurl = os.path.join(base, patchurl)
4750 ui.status(_('applying %s\n') % patchurl)
4746 ui.status(_('applying %s\n') % patchurl)
4751 patchfile = hg.openpath(ui, patchurl)
4747 patchfile = hg.openpath(ui, patchurl)
4752
4748
4753 haspatch = False
4749 haspatch = False
4754 for hunk in patch.split(patchfile):
4750 for hunk in patch.split(patchfile):
4755 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4751 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4756 parents, opts,
4752 parents, opts,
4757 msgs, hg.clean)
4753 msgs, hg.clean)
4758 if msg:
4754 if msg:
4759 haspatch = True
4755 haspatch = True
4760 ui.note(msg + '\n')
4756 ui.note(msg + '\n')
4761 if update or exact:
4757 if update or exact:
4762 parents = repo[None].parents()
4758 parents = repo[None].parents()
4763 else:
4759 else:
4764 parents = [repo[node]]
4760 parents = [repo[node]]
4765 if rej:
4761 if rej:
4766 ui.write_err(_("patch applied partially\n"))
4762 ui.write_err(_("patch applied partially\n"))
4767 ui.write_err(_("(fix the .rej files and run "
4763 ui.write_err(_("(fix the .rej files and run "
4768 "`hg commit --amend`)\n"))
4764 "`hg commit --amend`)\n"))
4769 ret = 1
4765 ret = 1
4770 break
4766 break
4771
4767
4772 if not haspatch:
4768 if not haspatch:
4773 raise error.Abort(_('%s: no diffs found') % patchurl)
4769 raise error.Abort(_('%s: no diffs found') % patchurl)
4774
4770
4775 if tr:
4771 if tr:
4776 tr.close()
4772 tr.close()
4777 if msgs:
4773 if msgs:
4778 repo.savecommitmessage('\n* * *\n'.join(msgs))
4774 repo.savecommitmessage('\n* * *\n'.join(msgs))
4779 if dsguard:
4775 if dsguard:
4780 dsguard.close()
4776 dsguard.close()
4781 return ret
4777 return ret
4782 finally:
4778 finally:
4783 if tr:
4779 if tr:
4784 tr.release()
4780 tr.release()
4785 release(lock, dsguard, wlock)
4781 release(lock, dsguard, wlock)
4786
4782
4787 @command('incoming|in',
4783 @command('incoming|in',
4788 [('f', 'force', None,
4784 [('f', 'force', None,
4789 _('run even if remote repository is unrelated')),
4785 _('run even if remote repository is unrelated')),
4790 ('n', 'newest-first', None, _('show newest record first')),
4786 ('n', 'newest-first', None, _('show newest record first')),
4791 ('', 'bundle', '',
4787 ('', 'bundle', '',
4792 _('file to store the bundles into'), _('FILE')),
4788 _('file to store the bundles into'), _('FILE')),
4793 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4789 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4794 ('B', 'bookmarks', False, _("compare bookmarks")),
4790 ('B', 'bookmarks', False, _("compare bookmarks")),
4795 ('b', 'branch', [],
4791 ('b', 'branch', [],
4796 _('a specific branch you would like to pull'), _('BRANCH')),
4792 _('a specific branch you would like to pull'), _('BRANCH')),
4797 ] + logopts + remoteopts + subrepoopts,
4793 ] + logopts + remoteopts + subrepoopts,
4798 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4794 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4799 def incoming(ui, repo, source="default", **opts):
4795 def incoming(ui, repo, source="default", **opts):
4800 """show new changesets found in source
4796 """show new changesets found in source
4801
4797
4802 Show new changesets found in the specified path/URL or the default
4798 Show new changesets found in the specified path/URL or the default
4803 pull location. These are the changesets that would have been pulled
4799 pull location. These are the changesets that would have been pulled
4804 if a pull at the time you issued this command.
4800 if a pull at the time you issued this command.
4805
4801
4806 See pull for valid source format details.
4802 See pull for valid source format details.
4807
4803
4808 .. container:: verbose
4804 .. container:: verbose
4809
4805
4810 With -B/--bookmarks, the result of bookmark comparison between
4806 With -B/--bookmarks, the result of bookmark comparison between
4811 local and remote repositories is displayed. With -v/--verbose,
4807 local and remote repositories is displayed. With -v/--verbose,
4812 status is also displayed for each bookmark like below::
4808 status is also displayed for each bookmark like below::
4813
4809
4814 BM1 01234567890a added
4810 BM1 01234567890a added
4815 BM2 1234567890ab advanced
4811 BM2 1234567890ab advanced
4816 BM3 234567890abc diverged
4812 BM3 234567890abc diverged
4817 BM4 34567890abcd changed
4813 BM4 34567890abcd changed
4818
4814
4819 The action taken locally when pulling depends on the
4815 The action taken locally when pulling depends on the
4820 status of each bookmark:
4816 status of each bookmark:
4821
4817
4822 :``added``: pull will create it
4818 :``added``: pull will create it
4823 :``advanced``: pull will update it
4819 :``advanced``: pull will update it
4824 :``diverged``: pull will create a divergent bookmark
4820 :``diverged``: pull will create a divergent bookmark
4825 :``changed``: result depends on remote changesets
4821 :``changed``: result depends on remote changesets
4826
4822
4827 From the point of view of pulling behavior, bookmark
4823 From the point of view of pulling behavior, bookmark
4828 existing only in the remote repository are treated as ``added``,
4824 existing only in the remote repository are treated as ``added``,
4829 even if it is in fact locally deleted.
4825 even if it is in fact locally deleted.
4830
4826
4831 .. container:: verbose
4827 .. container:: verbose
4832
4828
4833 For remote repository, using --bundle avoids downloading the
4829 For remote repository, using --bundle avoids downloading the
4834 changesets twice if the incoming is followed by a pull.
4830 changesets twice if the incoming is followed by a pull.
4835
4831
4836 Examples:
4832 Examples:
4837
4833
4838 - show incoming changes with patches and full description::
4834 - show incoming changes with patches and full description::
4839
4835
4840 hg incoming -vp
4836 hg incoming -vp
4841
4837
4842 - show incoming changes excluding merges, store a bundle::
4838 - show incoming changes excluding merges, store a bundle::
4843
4839
4844 hg in -vpM --bundle incoming.hg
4840 hg in -vpM --bundle incoming.hg
4845 hg pull incoming.hg
4841 hg pull incoming.hg
4846
4842
4847 - briefly list changes inside a bundle::
4843 - briefly list changes inside a bundle::
4848
4844
4849 hg in changes.hg -T "{desc|firstline}\\n"
4845 hg in changes.hg -T "{desc|firstline}\\n"
4850
4846
4851 Returns 0 if there are incoming changes, 1 otherwise.
4847 Returns 0 if there are incoming changes, 1 otherwise.
4852 """
4848 """
4853 if opts.get('graph'):
4849 if opts.get('graph'):
4854 cmdutil.checkunsupportedgraphflags([], opts)
4850 cmdutil.checkunsupportedgraphflags([], opts)
4855 def display(other, chlist, displayer):
4851 def display(other, chlist, displayer):
4856 revdag = cmdutil.graphrevs(other, chlist, opts)
4852 revdag = cmdutil.graphrevs(other, chlist, opts)
4857 cmdutil.displaygraph(ui, repo, revdag, displayer,
4853 cmdutil.displaygraph(ui, repo, revdag, displayer,
4858 graphmod.asciiedges)
4854 graphmod.asciiedges)
4859
4855
4860 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4861 return 0
4857 return 0
4862
4858
4863 if opts.get('bundle') and opts.get('subrepos'):
4859 if opts.get('bundle') and opts.get('subrepos'):
4864 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4860 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4865
4861
4866 if opts.get('bookmarks'):
4862 if opts.get('bookmarks'):
4867 source, branches = hg.parseurl(ui.expandpath(source),
4863 source, branches = hg.parseurl(ui.expandpath(source),
4868 opts.get('branch'))
4864 opts.get('branch'))
4869 other = hg.peer(repo, opts, source)
4865 other = hg.peer(repo, opts, source)
4870 if 'bookmarks' not in other.listkeys('namespaces'):
4866 if 'bookmarks' not in other.listkeys('namespaces'):
4871 ui.warn(_("remote doesn't support bookmarks\n"))
4867 ui.warn(_("remote doesn't support bookmarks\n"))
4872 return 0
4868 return 0
4873 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4874 return bookmarks.incoming(ui, repo, other)
4870 return bookmarks.incoming(ui, repo, other)
4875
4871
4876 repo._subtoppath = ui.expandpath(source)
4872 repo._subtoppath = ui.expandpath(source)
4877 try:
4873 try:
4878 return hg.incoming(ui, repo, source, opts)
4874 return hg.incoming(ui, repo, source, opts)
4879 finally:
4875 finally:
4880 del repo._subtoppath
4876 del repo._subtoppath
4881
4877
4882
4878
4883 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4884 norepo=True)
4880 norepo=True)
4885 def init(ui, dest=".", **opts):
4881 def init(ui, dest=".", **opts):
4886 """create a new repository in the given directory
4882 """create a new repository in the given directory
4887
4883
4888 Initialize a new repository in the given directory. If the given
4884 Initialize a new repository in the given directory. If the given
4889 directory does not exist, it will be created.
4885 directory does not exist, it will be created.
4890
4886
4891 If no directory is given, the current directory is used.
4887 If no directory is given, the current directory is used.
4892
4888
4893 It is possible to specify an ``ssh://`` URL as the destination.
4889 It is possible to specify an ``ssh://`` URL as the destination.
4894 See :hg:`help urls` for more information.
4890 See :hg:`help urls` for more information.
4895
4891
4896 Returns 0 on success.
4892 Returns 0 on success.
4897 """
4893 """
4898 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4894 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4899
4895
4900 @command('locate',
4896 @command('locate',
4901 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4897 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4902 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4898 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4903 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4899 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4904 ] + walkopts,
4900 ] + walkopts,
4905 _('[OPTION]... [PATTERN]...'))
4901 _('[OPTION]... [PATTERN]...'))
4906 def locate(ui, repo, *pats, **opts):
4902 def locate(ui, repo, *pats, **opts):
4907 """locate files matching specific patterns (DEPRECATED)
4903 """locate files matching specific patterns (DEPRECATED)
4908
4904
4909 Print files under Mercurial control in the working directory whose
4905 Print files under Mercurial control in the working directory whose
4910 names match the given patterns.
4906 names match the given patterns.
4911
4907
4912 By default, this command searches all directories in the working
4908 By default, this command searches all directories in the working
4913 directory. To search just the current directory and its
4909 directory. To search just the current directory and its
4914 subdirectories, use "--include .".
4910 subdirectories, use "--include .".
4915
4911
4916 If no patterns are given to match, this command prints the names
4912 If no patterns are given to match, this command prints the names
4917 of all files under Mercurial control in the working directory.
4913 of all files under Mercurial control in the working directory.
4918
4914
4919 If you want to feed the output of this command into the "xargs"
4915 If you want to feed the output of this command into the "xargs"
4920 command, use the -0 option to both this command and "xargs". This
4916 command, use the -0 option to both this command and "xargs". This
4921 will avoid the problem of "xargs" treating single filenames that
4917 will avoid the problem of "xargs" treating single filenames that
4922 contain whitespace as multiple filenames.
4918 contain whitespace as multiple filenames.
4923
4919
4924 See :hg:`help files` for a more versatile command.
4920 See :hg:`help files` for a more versatile command.
4925
4921
4926 Returns 0 if a match is found, 1 otherwise.
4922 Returns 0 if a match is found, 1 otherwise.
4927 """
4923 """
4928 if opts.get('print0'):
4924 if opts.get('print0'):
4929 end = '\0'
4925 end = '\0'
4930 else:
4926 else:
4931 end = '\n'
4927 end = '\n'
4932 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4928 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4933
4929
4934 ret = 1
4930 ret = 1
4935 ctx = repo[rev]
4931 ctx = repo[rev]
4936 m = scmutil.match(ctx, pats, opts, default='relglob',
4932 m = scmutil.match(ctx, pats, opts, default='relglob',
4937 badfn=lambda x, y: False)
4933 badfn=lambda x, y: False)
4938
4934
4939 for abs in ctx.matches(m):
4935 for abs in ctx.matches(m):
4940 if opts.get('fullpath'):
4936 if opts.get('fullpath'):
4941 ui.write(repo.wjoin(abs), end)
4937 ui.write(repo.wjoin(abs), end)
4942 else:
4938 else:
4943 ui.write(((pats and m.rel(abs)) or abs), end)
4939 ui.write(((pats and m.rel(abs)) or abs), end)
4944 ret = 0
4940 ret = 0
4945
4941
4946 return ret
4942 return ret
4947
4943
4948 @command('^log|history',
4944 @command('^log|history',
4949 [('f', 'follow', None,
4945 [('f', 'follow', None,
4950 _('follow changeset history, or file history across copies and renames')),
4946 _('follow changeset history, or file history across copies and renames')),
4951 ('', 'follow-first', None,
4947 ('', 'follow-first', None,
4952 _('only follow the first parent of merge changesets (DEPRECATED)')),
4948 _('only follow the first parent of merge changesets (DEPRECATED)')),
4953 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4949 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4954 ('C', 'copies', None, _('show copied files')),
4950 ('C', 'copies', None, _('show copied files')),
4955 ('k', 'keyword', [],
4951 ('k', 'keyword', [],
4956 _('do case-insensitive search for a given text'), _('TEXT')),
4952 _('do case-insensitive search for a given text'), _('TEXT')),
4957 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4953 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4958 ('', 'removed', None, _('include revisions where files were removed')),
4954 ('', 'removed', None, _('include revisions where files were removed')),
4959 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4955 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4960 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4956 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4961 ('', 'only-branch', [],
4957 ('', 'only-branch', [],
4962 _('show only changesets within the given named branch (DEPRECATED)'),
4958 _('show only changesets within the given named branch (DEPRECATED)'),
4963 _('BRANCH')),
4959 _('BRANCH')),
4964 ('b', 'branch', [],
4960 ('b', 'branch', [],
4965 _('show changesets within the given named branch'), _('BRANCH')),
4961 _('show changesets within the given named branch'), _('BRANCH')),
4966 ('P', 'prune', [],
4962 ('P', 'prune', [],
4967 _('do not display revision or any of its ancestors'), _('REV')),
4963 _('do not display revision or any of its ancestors'), _('REV')),
4968 ] + logopts + walkopts,
4964 ] + logopts + walkopts,
4969 _('[OPTION]... [FILE]'),
4965 _('[OPTION]... [FILE]'),
4970 inferrepo=True)
4966 inferrepo=True)
4971 def log(ui, repo, *pats, **opts):
4967 def log(ui, repo, *pats, **opts):
4972 """show revision history of entire repository or files
4968 """show revision history of entire repository or files
4973
4969
4974 Print the revision history of the specified files or the entire
4970 Print the revision history of the specified files or the entire
4975 project.
4971 project.
4976
4972
4977 If no revision range is specified, the default is ``tip:0`` unless
4973 If no revision range is specified, the default is ``tip:0`` unless
4978 --follow is set, in which case the working directory parent is
4974 --follow is set, in which case the working directory parent is
4979 used as the starting revision.
4975 used as the starting revision.
4980
4976
4981 File history is shown without following rename or copy history of
4977 File history is shown without following rename or copy history of
4982 files. Use -f/--follow with a filename to follow history across
4978 files. Use -f/--follow with a filename to follow history across
4983 renames and copies. --follow without a filename will only show
4979 renames and copies. --follow without a filename will only show
4984 ancestors or descendants of the starting revision.
4980 ancestors or descendants of the starting revision.
4985
4981
4986 By default this command prints revision number and changeset id,
4982 By default this command prints revision number and changeset id,
4987 tags, non-trivial parents, user, date and time, and a summary for
4983 tags, non-trivial parents, user, date and time, and a summary for
4988 each commit. When the -v/--verbose switch is used, the list of
4984 each commit. When the -v/--verbose switch is used, the list of
4989 changed files and full commit message are shown.
4985 changed files and full commit message are shown.
4990
4986
4991 With --graph the revisions are shown as an ASCII art DAG with the most
4987 With --graph the revisions are shown as an ASCII art DAG with the most
4992 recent changeset at the top.
4988 recent changeset at the top.
4993 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4989 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4994 and '+' represents a fork where the changeset from the lines below is a
4990 and '+' represents a fork where the changeset from the lines below is a
4995 parent of the 'o' merge on the same line.
4991 parent of the 'o' merge on the same line.
4996
4992
4997 .. note::
4993 .. note::
4998
4994
4999 :hg:`log --patch` may generate unexpected diff output for merge
4995 :hg:`log --patch` may generate unexpected diff output for merge
5000 changesets, as it will only compare the merge changeset against
4996 changesets, as it will only compare the merge changeset against
5001 its first parent. Also, only files different from BOTH parents
4997 its first parent. Also, only files different from BOTH parents
5002 will appear in files:.
4998 will appear in files:.
5003
4999
5004 .. note::
5000 .. note::
5005
5001
5006 For performance reasons, :hg:`log FILE` may omit duplicate changes
5002 For performance reasons, :hg:`log FILE` may omit duplicate changes
5007 made on branches and will not show removals or mode changes. To
5003 made on branches and will not show removals or mode changes. To
5008 see all such changes, use the --removed switch.
5004 see all such changes, use the --removed switch.
5009
5005
5010 .. container:: verbose
5006 .. container:: verbose
5011
5007
5012 Some examples:
5008 Some examples:
5013
5009
5014 - changesets with full descriptions and file lists::
5010 - changesets with full descriptions and file lists::
5015
5011
5016 hg log -v
5012 hg log -v
5017
5013
5018 - changesets ancestral to the working directory::
5014 - changesets ancestral to the working directory::
5019
5015
5020 hg log -f
5016 hg log -f
5021
5017
5022 - last 10 commits on the current branch::
5018 - last 10 commits on the current branch::
5023
5019
5024 hg log -l 10 -b .
5020 hg log -l 10 -b .
5025
5021
5026 - changesets showing all modifications of a file, including removals::
5022 - changesets showing all modifications of a file, including removals::
5027
5023
5028 hg log --removed file.c
5024 hg log --removed file.c
5029
5025
5030 - all changesets that touch a directory, with diffs, excluding merges::
5026 - all changesets that touch a directory, with diffs, excluding merges::
5031
5027
5032 hg log -Mp lib/
5028 hg log -Mp lib/
5033
5029
5034 - all revision numbers that match a keyword::
5030 - all revision numbers that match a keyword::
5035
5031
5036 hg log -k bug --template "{rev}\\n"
5032 hg log -k bug --template "{rev}\\n"
5037
5033
5038 - the full hash identifier of the working directory parent::
5034 - the full hash identifier of the working directory parent::
5039
5035
5040 hg log -r . --template "{node}\\n"
5036 hg log -r . --template "{node}\\n"
5041
5037
5042 - list available log templates::
5038 - list available log templates::
5043
5039
5044 hg log -T list
5040 hg log -T list
5045
5041
5046 - check if a given changeset is included in a tagged release::
5042 - check if a given changeset is included in a tagged release::
5047
5043
5048 hg log -r "a21ccf and ancestor(1.9)"
5044 hg log -r "a21ccf and ancestor(1.9)"
5049
5045
5050 - find all changesets by some user in a date range::
5046 - find all changesets by some user in a date range::
5051
5047
5052 hg log -k alice -d "may 2008 to jul 2008"
5048 hg log -k alice -d "may 2008 to jul 2008"
5053
5049
5054 - summary of all changesets after the last tag::
5050 - summary of all changesets after the last tag::
5055
5051
5056 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5052 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5057
5053
5058 See :hg:`help dates` for a list of formats valid for -d/--date.
5054 See :hg:`help dates` for a list of formats valid for -d/--date.
5059
5055
5060 See :hg:`help revisions` and :hg:`help revsets` for more about
5056 See :hg:`help revisions` and :hg:`help revsets` for more about
5061 specifying and ordering revisions.
5057 specifying and ordering revisions.
5062
5058
5063 See :hg:`help templates` for more about pre-packaged styles and
5059 See :hg:`help templates` for more about pre-packaged styles and
5064 specifying custom templates.
5060 specifying custom templates.
5065
5061
5066 Returns 0 on success.
5062 Returns 0 on success.
5067
5063
5068 """
5064 """
5069 if opts.get('follow') and opts.get('rev'):
5065 if opts.get('follow') and opts.get('rev'):
5070 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5066 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5071 del opts['follow']
5067 del opts['follow']
5072
5068
5073 if opts.get('graph'):
5069 if opts.get('graph'):
5074 return cmdutil.graphlog(ui, repo, *pats, **opts)
5070 return cmdutil.graphlog(ui, repo, *pats, **opts)
5075
5071
5076 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5072 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5077 limit = cmdutil.loglimit(opts)
5073 limit = cmdutil.loglimit(opts)
5078 count = 0
5074 count = 0
5079
5075
5080 getrenamed = None
5076 getrenamed = None
5081 if opts.get('copies'):
5077 if opts.get('copies'):
5082 endrev = None
5078 endrev = None
5083 if opts.get('rev'):
5079 if opts.get('rev'):
5084 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5080 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5085 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5081 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5086
5082
5087 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5083 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5088 for rev in revs:
5084 for rev in revs:
5089 if count == limit:
5085 if count == limit:
5090 break
5086 break
5091 ctx = repo[rev]
5087 ctx = repo[rev]
5092 copies = None
5088 copies = None
5093 if getrenamed is not None and rev:
5089 if getrenamed is not None and rev:
5094 copies = []
5090 copies = []
5095 for fn in ctx.files():
5091 for fn in ctx.files():
5096 rename = getrenamed(fn, rev)
5092 rename = getrenamed(fn, rev)
5097 if rename:
5093 if rename:
5098 copies.append((fn, rename[0]))
5094 copies.append((fn, rename[0]))
5099 if filematcher:
5095 if filematcher:
5100 revmatchfn = filematcher(ctx.rev())
5096 revmatchfn = filematcher(ctx.rev())
5101 else:
5097 else:
5102 revmatchfn = None
5098 revmatchfn = None
5103 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5099 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5104 if displayer.flush(ctx):
5100 if displayer.flush(ctx):
5105 count += 1
5101 count += 1
5106
5102
5107 displayer.close()
5103 displayer.close()
5108
5104
5109 @command('manifest',
5105 @command('manifest',
5110 [('r', 'rev', '', _('revision to display'), _('REV')),
5106 [('r', 'rev', '', _('revision to display'), _('REV')),
5111 ('', 'all', False, _("list files from all revisions"))]
5107 ('', 'all', False, _("list files from all revisions"))]
5112 + formatteropts,
5108 + formatteropts,
5113 _('[-r REV]'))
5109 _('[-r REV]'))
5114 def manifest(ui, repo, node=None, rev=None, **opts):
5110 def manifest(ui, repo, node=None, rev=None, **opts):
5115 """output the current or given revision of the project manifest
5111 """output the current or given revision of the project manifest
5116
5112
5117 Print a list of version controlled files for the given revision.
5113 Print a list of version controlled files for the given revision.
5118 If no revision is given, the first parent of the working directory
5114 If no revision is given, the first parent of the working directory
5119 is used, or the null revision if no revision is checked out.
5115 is used, or the null revision if no revision is checked out.
5120
5116
5121 With -v, print file permissions, symlink and executable bits.
5117 With -v, print file permissions, symlink and executable bits.
5122 With --debug, print file revision hashes.
5118 With --debug, print file revision hashes.
5123
5119
5124 If option --all is specified, the list of all files from all revisions
5120 If option --all is specified, the list of all files from all revisions
5125 is printed. This includes deleted and renamed files.
5121 is printed. This includes deleted and renamed files.
5126
5122
5127 Returns 0 on success.
5123 Returns 0 on success.
5128 """
5124 """
5129
5125
5130 fm = ui.formatter('manifest', opts)
5126 fm = ui.formatter('manifest', opts)
5131
5127
5132 if opts.get('all'):
5128 if opts.get('all'):
5133 if rev or node:
5129 if rev or node:
5134 raise error.Abort(_("can't specify a revision with --all"))
5130 raise error.Abort(_("can't specify a revision with --all"))
5135
5131
5136 res = []
5132 res = []
5137 prefix = "data/"
5133 prefix = "data/"
5138 suffix = ".i"
5134 suffix = ".i"
5139 plen = len(prefix)
5135 plen = len(prefix)
5140 slen = len(suffix)
5136 slen = len(suffix)
5141 lock = repo.lock()
5137 lock = repo.lock()
5142 try:
5138 try:
5143 for fn, b, size in repo.store.datafiles():
5139 for fn, b, size in repo.store.datafiles():
5144 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5140 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5145 res.append(fn[plen:-slen])
5141 res.append(fn[plen:-slen])
5146 finally:
5142 finally:
5147 lock.release()
5143 lock.release()
5148 for f in res:
5144 for f in res:
5149 fm.startitem()
5145 fm.startitem()
5150 fm.write("path", '%s\n', f)
5146 fm.write("path", '%s\n', f)
5151 fm.end()
5147 fm.end()
5152 return
5148 return
5153
5149
5154 if rev and node:
5150 if rev and node:
5155 raise error.Abort(_("please specify just one revision"))
5151 raise error.Abort(_("please specify just one revision"))
5156
5152
5157 if not node:
5153 if not node:
5158 node = rev
5154 node = rev
5159
5155
5160 char = {'l': '@', 'x': '*', '': ''}
5156 char = {'l': '@', 'x': '*', '': ''}
5161 mode = {'l': '644', 'x': '755', '': '644'}
5157 mode = {'l': '644', 'x': '755', '': '644'}
5162 ctx = scmutil.revsingle(repo, node)
5158 ctx = scmutil.revsingle(repo, node)
5163 mf = ctx.manifest()
5159 mf = ctx.manifest()
5164 for f in ctx:
5160 for f in ctx:
5165 fm.startitem()
5161 fm.startitem()
5166 fl = ctx[f].flags()
5162 fl = ctx[f].flags()
5167 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5163 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5168 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5164 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5169 fm.write('path', '%s\n', f)
5165 fm.write('path', '%s\n', f)
5170 fm.end()
5166 fm.end()
5171
5167
5172 @command('^merge',
5168 @command('^merge',
5173 [('f', 'force', None,
5169 [('f', 'force', None,
5174 _('force a merge including outstanding changes (DEPRECATED)')),
5170 _('force a merge including outstanding changes (DEPRECATED)')),
5175 ('r', 'rev', '', _('revision to merge'), _('REV')),
5171 ('r', 'rev', '', _('revision to merge'), _('REV')),
5176 ('P', 'preview', None,
5172 ('P', 'preview', None,
5177 _('review revisions to merge (no merge is performed)'))
5173 _('review revisions to merge (no merge is performed)'))
5178 ] + mergetoolopts,
5174 ] + mergetoolopts,
5179 _('[-P] [-f] [[-r] REV]'))
5175 _('[-P] [-f] [[-r] REV]'))
5180 def merge(ui, repo, node=None, **opts):
5176 def merge(ui, repo, node=None, **opts):
5181 """merge another revision into working directory
5177 """merge another revision into working directory
5182
5178
5183 The current working directory is updated with all changes made in
5179 The current working directory is updated with all changes made in
5184 the requested revision since the last common predecessor revision.
5180 the requested revision since the last common predecessor revision.
5185
5181
5186 Files that changed between either parent are marked as changed for
5182 Files that changed between either parent are marked as changed for
5187 the next commit and a commit must be performed before any further
5183 the next commit and a commit must be performed before any further
5188 updates to the repository are allowed. The next commit will have
5184 updates to the repository are allowed. The next commit will have
5189 two parents.
5185 two parents.
5190
5186
5191 ``--tool`` can be used to specify the merge tool used for file
5187 ``--tool`` can be used to specify the merge tool used for file
5192 merges. It overrides the HGMERGE environment variable and your
5188 merges. It overrides the HGMERGE environment variable and your
5193 configuration files. See :hg:`help merge-tools` for options.
5189 configuration files. See :hg:`help merge-tools` for options.
5194
5190
5195 If no revision is specified, the working directory's parent is a
5191 If no revision is specified, the working directory's parent is a
5196 head revision, and the current branch contains exactly one other
5192 head revision, and the current branch contains exactly one other
5197 head, the other head is merged with by default. Otherwise, an
5193 head, the other head is merged with by default. Otherwise, an
5198 explicit revision with which to merge with must be provided.
5194 explicit revision with which to merge with must be provided.
5199
5195
5200 See :hg:`help resolve` for information on handling file conflicts.
5196 See :hg:`help resolve` for information on handling file conflicts.
5201
5197
5202 To undo an uncommitted merge, use :hg:`update --clean .` which
5198 To undo an uncommitted merge, use :hg:`update --clean .` which
5203 will check out a clean copy of the original merge parent, losing
5199 will check out a clean copy of the original merge parent, losing
5204 all changes.
5200 all changes.
5205
5201
5206 Returns 0 on success, 1 if there are unresolved files.
5202 Returns 0 on success, 1 if there are unresolved files.
5207 """
5203 """
5208
5204
5209 if opts.get('rev') and node:
5205 if opts.get('rev') and node:
5210 raise error.Abort(_("please specify just one revision"))
5206 raise error.Abort(_("please specify just one revision"))
5211 if not node:
5207 if not node:
5212 node = opts.get('rev')
5208 node = opts.get('rev')
5213
5209
5214 if node:
5210 if node:
5215 node = scmutil.revsingle(repo, node).node()
5211 node = scmutil.revsingle(repo, node).node()
5216
5212
5217 if not node:
5213 if not node:
5218 node = repo[destutil.destmerge(repo)].node()
5214 node = repo[destutil.destmerge(repo)].node()
5219
5215
5220 if opts.get('preview'):
5216 if opts.get('preview'):
5221 # find nodes that are ancestors of p2 but not of p1
5217 # find nodes that are ancestors of p2 but not of p1
5222 p1 = repo.lookup('.')
5218 p1 = repo.lookup('.')
5223 p2 = repo.lookup(node)
5219 p2 = repo.lookup(node)
5224 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5220 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5225
5221
5226 displayer = cmdutil.show_changeset(ui, repo, opts)
5222 displayer = cmdutil.show_changeset(ui, repo, opts)
5227 for node in nodes:
5223 for node in nodes:
5228 displayer.show(repo[node])
5224 displayer.show(repo[node])
5229 displayer.close()
5225 displayer.close()
5230 return 0
5226 return 0
5231
5227
5232 try:
5228 try:
5233 # ui.forcemerge is an internal variable, do not document
5229 # ui.forcemerge is an internal variable, do not document
5234 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5230 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5235 return hg.merge(repo, node, force=opts.get('force'))
5231 return hg.merge(repo, node, force=opts.get('force'))
5236 finally:
5232 finally:
5237 ui.setconfig('ui', 'forcemerge', '', 'merge')
5233 ui.setconfig('ui', 'forcemerge', '', 'merge')
5238
5234
5239 @command('outgoing|out',
5235 @command('outgoing|out',
5240 [('f', 'force', None, _('run even when the destination is unrelated')),
5236 [('f', 'force', None, _('run even when the destination is unrelated')),
5241 ('r', 'rev', [],
5237 ('r', 'rev', [],
5242 _('a changeset intended to be included in the destination'), _('REV')),
5238 _('a changeset intended to be included in the destination'), _('REV')),
5243 ('n', 'newest-first', None, _('show newest record first')),
5239 ('n', 'newest-first', None, _('show newest record first')),
5244 ('B', 'bookmarks', False, _('compare bookmarks')),
5240 ('B', 'bookmarks', False, _('compare bookmarks')),
5245 ('b', 'branch', [], _('a specific branch you would like to push'),
5241 ('b', 'branch', [], _('a specific branch you would like to push'),
5246 _('BRANCH')),
5242 _('BRANCH')),
5247 ] + logopts + remoteopts + subrepoopts,
5243 ] + logopts + remoteopts + subrepoopts,
5248 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5244 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5249 def outgoing(ui, repo, dest=None, **opts):
5245 def outgoing(ui, repo, dest=None, **opts):
5250 """show changesets not found in the destination
5246 """show changesets not found in the destination
5251
5247
5252 Show changesets not found in the specified destination repository
5248 Show changesets not found in the specified destination repository
5253 or the default push location. These are the changesets that would
5249 or the default push location. These are the changesets that would
5254 be pushed if a push was requested.
5250 be pushed if a push was requested.
5255
5251
5256 See pull for details of valid destination formats.
5252 See pull for details of valid destination formats.
5257
5253
5258 .. container:: verbose
5254 .. container:: verbose
5259
5255
5260 With -B/--bookmarks, the result of bookmark comparison between
5256 With -B/--bookmarks, the result of bookmark comparison between
5261 local and remote repositories is displayed. With -v/--verbose,
5257 local and remote repositories is displayed. With -v/--verbose,
5262 status is also displayed for each bookmark like below::
5258 status is also displayed for each bookmark like below::
5263
5259
5264 BM1 01234567890a added
5260 BM1 01234567890a added
5265 BM2 deleted
5261 BM2 deleted
5266 BM3 234567890abc advanced
5262 BM3 234567890abc advanced
5267 BM4 34567890abcd diverged
5263 BM4 34567890abcd diverged
5268 BM5 4567890abcde changed
5264 BM5 4567890abcde changed
5269
5265
5270 The action taken when pushing depends on the
5266 The action taken when pushing depends on the
5271 status of each bookmark:
5267 status of each bookmark:
5272
5268
5273 :``added``: push with ``-B`` will create it
5269 :``added``: push with ``-B`` will create it
5274 :``deleted``: push with ``-B`` will delete it
5270 :``deleted``: push with ``-B`` will delete it
5275 :``advanced``: push will update it
5271 :``advanced``: push will update it
5276 :``diverged``: push with ``-B`` will update it
5272 :``diverged``: push with ``-B`` will update it
5277 :``changed``: push with ``-B`` will update it
5273 :``changed``: push with ``-B`` will update it
5278
5274
5279 From the point of view of pushing behavior, bookmarks
5275 From the point of view of pushing behavior, bookmarks
5280 existing only in the remote repository are treated as
5276 existing only in the remote repository are treated as
5281 ``deleted``, even if it is in fact added remotely.
5277 ``deleted``, even if it is in fact added remotely.
5282
5278
5283 Returns 0 if there are outgoing changes, 1 otherwise.
5279 Returns 0 if there are outgoing changes, 1 otherwise.
5284 """
5280 """
5285 if opts.get('graph'):
5281 if opts.get('graph'):
5286 cmdutil.checkunsupportedgraphflags([], opts)
5282 cmdutil.checkunsupportedgraphflags([], opts)
5287 o, other = hg._outgoing(ui, repo, dest, opts)
5283 o, other = hg._outgoing(ui, repo, dest, opts)
5288 if not o:
5284 if not o:
5289 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5285 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5290 return
5286 return
5291
5287
5292 revdag = cmdutil.graphrevs(repo, o, opts)
5288 revdag = cmdutil.graphrevs(repo, o, opts)
5293 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5289 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5294 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5290 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5295 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5291 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5296 return 0
5292 return 0
5297
5293
5298 if opts.get('bookmarks'):
5294 if opts.get('bookmarks'):
5299 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5295 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5300 dest, branches = hg.parseurl(dest, opts.get('branch'))
5296 dest, branches = hg.parseurl(dest, opts.get('branch'))
5301 other = hg.peer(repo, opts, dest)
5297 other = hg.peer(repo, opts, dest)
5302 if 'bookmarks' not in other.listkeys('namespaces'):
5298 if 'bookmarks' not in other.listkeys('namespaces'):
5303 ui.warn(_("remote doesn't support bookmarks\n"))
5299 ui.warn(_("remote doesn't support bookmarks\n"))
5304 return 0
5300 return 0
5305 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5301 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5306 return bookmarks.outgoing(ui, repo, other)
5302 return bookmarks.outgoing(ui, repo, other)
5307
5303
5308 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5304 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5309 try:
5305 try:
5310 return hg.outgoing(ui, repo, dest, opts)
5306 return hg.outgoing(ui, repo, dest, opts)
5311 finally:
5307 finally:
5312 del repo._subtoppath
5308 del repo._subtoppath
5313
5309
5314 @command('parents',
5310 @command('parents',
5315 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5311 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5316 ] + templateopts,
5312 ] + templateopts,
5317 _('[-r REV] [FILE]'),
5313 _('[-r REV] [FILE]'),
5318 inferrepo=True)
5314 inferrepo=True)
5319 def parents(ui, repo, file_=None, **opts):
5315 def parents(ui, repo, file_=None, **opts):
5320 """show the parents of the working directory or revision (DEPRECATED)
5316 """show the parents of the working directory or revision (DEPRECATED)
5321
5317
5322 Print the working directory's parent revisions. If a revision is
5318 Print the working directory's parent revisions. If a revision is
5323 given via -r/--rev, the parent of that revision will be printed.
5319 given via -r/--rev, the parent of that revision will be printed.
5324 If a file argument is given, the revision in which the file was
5320 If a file argument is given, the revision in which the file was
5325 last changed (before the working directory revision or the
5321 last changed (before the working directory revision or the
5326 argument to --rev if given) is printed.
5322 argument to --rev if given) is printed.
5327
5323
5328 This command is equivalent to::
5324 This command is equivalent to::
5329
5325
5330 hg log -r "p1()+p2()" or
5326 hg log -r "p1()+p2()" or
5331 hg log -r "p1(REV)+p2(REV)" or
5327 hg log -r "p1(REV)+p2(REV)" or
5332 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5328 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5333 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5329 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5334
5330
5335 See :hg:`summary` and :hg:`help revsets` for related information.
5331 See :hg:`summary` and :hg:`help revsets` for related information.
5336
5332
5337 Returns 0 on success.
5333 Returns 0 on success.
5338 """
5334 """
5339
5335
5340 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5336 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5341
5337
5342 if file_:
5338 if file_:
5343 m = scmutil.match(ctx, (file_,), opts)
5339 m = scmutil.match(ctx, (file_,), opts)
5344 if m.anypats() or len(m.files()) != 1:
5340 if m.anypats() or len(m.files()) != 1:
5345 raise error.Abort(_('can only specify an explicit filename'))
5341 raise error.Abort(_('can only specify an explicit filename'))
5346 file_ = m.files()[0]
5342 file_ = m.files()[0]
5347 filenodes = []
5343 filenodes = []
5348 for cp in ctx.parents():
5344 for cp in ctx.parents():
5349 if not cp:
5345 if not cp:
5350 continue
5346 continue
5351 try:
5347 try:
5352 filenodes.append(cp.filenode(file_))
5348 filenodes.append(cp.filenode(file_))
5353 except error.LookupError:
5349 except error.LookupError:
5354 pass
5350 pass
5355 if not filenodes:
5351 if not filenodes:
5356 raise error.Abort(_("'%s' not found in manifest!") % file_)
5352 raise error.Abort(_("'%s' not found in manifest!") % file_)
5357 p = []
5353 p = []
5358 for fn in filenodes:
5354 for fn in filenodes:
5359 fctx = repo.filectx(file_, fileid=fn)
5355 fctx = repo.filectx(file_, fileid=fn)
5360 p.append(fctx.node())
5356 p.append(fctx.node())
5361 else:
5357 else:
5362 p = [cp.node() for cp in ctx.parents()]
5358 p = [cp.node() for cp in ctx.parents()]
5363
5359
5364 displayer = cmdutil.show_changeset(ui, repo, opts)
5360 displayer = cmdutil.show_changeset(ui, repo, opts)
5365 for n in p:
5361 for n in p:
5366 if n != nullid:
5362 if n != nullid:
5367 displayer.show(repo[n])
5363 displayer.show(repo[n])
5368 displayer.close()
5364 displayer.close()
5369
5365
5370 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5366 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5371 def paths(ui, repo, search=None, **opts):
5367 def paths(ui, repo, search=None, **opts):
5372 """show aliases for remote repositories
5368 """show aliases for remote repositories
5373
5369
5374 Show definition of symbolic path name NAME. If no name is given,
5370 Show definition of symbolic path name NAME. If no name is given,
5375 show definition of all available names.
5371 show definition of all available names.
5376
5372
5377 Option -q/--quiet suppresses all output when searching for NAME
5373 Option -q/--quiet suppresses all output when searching for NAME
5378 and shows only the path names when listing all definitions.
5374 and shows only the path names when listing all definitions.
5379
5375
5380 Path names are defined in the [paths] section of your
5376 Path names are defined in the [paths] section of your
5381 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5377 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5382 repository, ``.hg/hgrc`` is used, too.
5378 repository, ``.hg/hgrc`` is used, too.
5383
5379
5384 The path names ``default`` and ``default-push`` have a special
5380 The path names ``default`` and ``default-push`` have a special
5385 meaning. When performing a push or pull operation, they are used
5381 meaning. When performing a push or pull operation, they are used
5386 as fallbacks if no location is specified on the command-line.
5382 as fallbacks if no location is specified on the command-line.
5387 When ``default-push`` is set, it will be used for push and
5383 When ``default-push`` is set, it will be used for push and
5388 ``default`` will be used for pull; otherwise ``default`` is used
5384 ``default`` will be used for pull; otherwise ``default`` is used
5389 as the fallback for both. When cloning a repository, the clone
5385 as the fallback for both. When cloning a repository, the clone
5390 source is written as ``default`` in ``.hg/hgrc``.
5386 source is written as ``default`` in ``.hg/hgrc``.
5391
5387
5392 .. note::
5388 .. note::
5393
5389
5394 ``default`` and ``default-push`` apply to all inbound (e.g.
5390 ``default`` and ``default-push`` apply to all inbound (e.g.
5395 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5391 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5396 and :hg:`bundle`) operations.
5392 and :hg:`bundle`) operations.
5397
5393
5398 See :hg:`help urls` for more information.
5394 See :hg:`help urls` for more information.
5399
5395
5400 Returns 0 on success.
5396 Returns 0 on success.
5401 """
5397 """
5402 if search:
5398 if search:
5403 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5399 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5404 if name == search]
5400 if name == search]
5405 else:
5401 else:
5406 pathitems = sorted(ui.paths.iteritems())
5402 pathitems = sorted(ui.paths.iteritems())
5407
5403
5408 fm = ui.formatter('paths', opts)
5404 fm = ui.formatter('paths', opts)
5409 if fm:
5405 if fm:
5410 hidepassword = str
5406 hidepassword = str
5411 else:
5407 else:
5412 hidepassword = util.hidepassword
5408 hidepassword = util.hidepassword
5413 if ui.quiet:
5409 if ui.quiet:
5414 namefmt = '%s\n'
5410 namefmt = '%s\n'
5415 else:
5411 else:
5416 namefmt = '%s = '
5412 namefmt = '%s = '
5417 showsubopts = not search and not ui.quiet
5413 showsubopts = not search and not ui.quiet
5418
5414
5419 for name, path in pathitems:
5415 for name, path in pathitems:
5420 fm.startitem()
5416 fm.startitem()
5421 fm.condwrite(not search, 'name', namefmt, name)
5417 fm.condwrite(not search, 'name', namefmt, name)
5422 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5418 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5423 for subopt, value in sorted(path.suboptions.items()):
5419 for subopt, value in sorted(path.suboptions.items()):
5424 assert subopt not in ('name', 'url')
5420 assert subopt not in ('name', 'url')
5425 if showsubopts:
5421 if showsubopts:
5426 fm.plain('%s:%s = ' % (name, subopt))
5422 fm.plain('%s:%s = ' % (name, subopt))
5427 fm.condwrite(showsubopts, subopt, '%s\n', value)
5423 fm.condwrite(showsubopts, subopt, '%s\n', value)
5428
5424
5429 fm.end()
5425 fm.end()
5430
5426
5431 if search and not pathitems:
5427 if search and not pathitems:
5432 if not ui.quiet:
5428 if not ui.quiet:
5433 ui.warn(_("not found!\n"))
5429 ui.warn(_("not found!\n"))
5434 return 1
5430 return 1
5435 else:
5431 else:
5436 return 0
5432 return 0
5437
5433
5438 @command('phase',
5434 @command('phase',
5439 [('p', 'public', False, _('set changeset phase to public')),
5435 [('p', 'public', False, _('set changeset phase to public')),
5440 ('d', 'draft', False, _('set changeset phase to draft')),
5436 ('d', 'draft', False, _('set changeset phase to draft')),
5441 ('s', 'secret', False, _('set changeset phase to secret')),
5437 ('s', 'secret', False, _('set changeset phase to secret')),
5442 ('f', 'force', False, _('allow to move boundary backward')),
5438 ('f', 'force', False, _('allow to move boundary backward')),
5443 ('r', 'rev', [], _('target revision'), _('REV')),
5439 ('r', 'rev', [], _('target revision'), _('REV')),
5444 ],
5440 ],
5445 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5441 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5446 def phase(ui, repo, *revs, **opts):
5442 def phase(ui, repo, *revs, **opts):
5447 """set or show the current phase name
5443 """set or show the current phase name
5448
5444
5449 With no argument, show the phase name of the current revision(s).
5445 With no argument, show the phase name of the current revision(s).
5450
5446
5451 With one of -p/--public, -d/--draft or -s/--secret, change the
5447 With one of -p/--public, -d/--draft or -s/--secret, change the
5452 phase value of the specified revisions.
5448 phase value of the specified revisions.
5453
5449
5454 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5450 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5455 lower phase to an higher phase. Phases are ordered as follows::
5451 lower phase to an higher phase. Phases are ordered as follows::
5456
5452
5457 public < draft < secret
5453 public < draft < secret
5458
5454
5459 Returns 0 on success, 1 if some phases could not be changed.
5455 Returns 0 on success, 1 if some phases could not be changed.
5460
5456
5461 (For more information about the phases concept, see :hg:`help phases`.)
5457 (For more information about the phases concept, see :hg:`help phases`.)
5462 """
5458 """
5463 # search for a unique phase argument
5459 # search for a unique phase argument
5464 targetphase = None
5460 targetphase = None
5465 for idx, name in enumerate(phases.phasenames):
5461 for idx, name in enumerate(phases.phasenames):
5466 if opts[name]:
5462 if opts[name]:
5467 if targetphase is not None:
5463 if targetphase is not None:
5468 raise error.Abort(_('only one phase can be specified'))
5464 raise error.Abort(_('only one phase can be specified'))
5469 targetphase = idx
5465 targetphase = idx
5470
5466
5471 # look for specified revision
5467 # look for specified revision
5472 revs = list(revs)
5468 revs = list(revs)
5473 revs.extend(opts['rev'])
5469 revs.extend(opts['rev'])
5474 if not revs:
5470 if not revs:
5475 # display both parents as the second parent phase can influence
5471 # display both parents as the second parent phase can influence
5476 # the phase of a merge commit
5472 # the phase of a merge commit
5477 revs = [c.rev() for c in repo[None].parents()]
5473 revs = [c.rev() for c in repo[None].parents()]
5478
5474
5479 revs = scmutil.revrange(repo, revs)
5475 revs = scmutil.revrange(repo, revs)
5480
5476
5481 lock = None
5477 lock = None
5482 ret = 0
5478 ret = 0
5483 if targetphase is None:
5479 if targetphase is None:
5484 # display
5480 # display
5485 for r in revs:
5481 for r in revs:
5486 ctx = repo[r]
5482 ctx = repo[r]
5487 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5483 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5488 else:
5484 else:
5489 tr = None
5485 tr = None
5490 lock = repo.lock()
5486 lock = repo.lock()
5491 try:
5487 try:
5492 tr = repo.transaction("phase")
5488 tr = repo.transaction("phase")
5493 # set phase
5489 # set phase
5494 if not revs:
5490 if not revs:
5495 raise error.Abort(_('empty revision set'))
5491 raise error.Abort(_('empty revision set'))
5496 nodes = [repo[r].node() for r in revs]
5492 nodes = [repo[r].node() for r in revs]
5497 # moving revision from public to draft may hide them
5493 # moving revision from public to draft may hide them
5498 # We have to check result on an unfiltered repository
5494 # We have to check result on an unfiltered repository
5499 unfi = repo.unfiltered()
5495 unfi = repo.unfiltered()
5500 getphase = unfi._phasecache.phase
5496 getphase = unfi._phasecache.phase
5501 olddata = [getphase(unfi, r) for r in unfi]
5497 olddata = [getphase(unfi, r) for r in unfi]
5502 phases.advanceboundary(repo, tr, targetphase, nodes)
5498 phases.advanceboundary(repo, tr, targetphase, nodes)
5503 if opts['force']:
5499 if opts['force']:
5504 phases.retractboundary(repo, tr, targetphase, nodes)
5500 phases.retractboundary(repo, tr, targetphase, nodes)
5505 tr.close()
5501 tr.close()
5506 finally:
5502 finally:
5507 if tr is not None:
5503 if tr is not None:
5508 tr.release()
5504 tr.release()
5509 lock.release()
5505 lock.release()
5510 getphase = unfi._phasecache.phase
5506 getphase = unfi._phasecache.phase
5511 newdata = [getphase(unfi, r) for r in unfi]
5507 newdata = [getphase(unfi, r) for r in unfi]
5512 changes = sum(newdata[r] != olddata[r] for r in unfi)
5508 changes = sum(newdata[r] != olddata[r] for r in unfi)
5513 cl = unfi.changelog
5509 cl = unfi.changelog
5514 rejected = [n for n in nodes
5510 rejected = [n for n in nodes
5515 if newdata[cl.rev(n)] < targetphase]
5511 if newdata[cl.rev(n)] < targetphase]
5516 if rejected:
5512 if rejected:
5517 ui.warn(_('cannot move %i changesets to a higher '
5513 ui.warn(_('cannot move %i changesets to a higher '
5518 'phase, use --force\n') % len(rejected))
5514 'phase, use --force\n') % len(rejected))
5519 ret = 1
5515 ret = 1
5520 if changes:
5516 if changes:
5521 msg = _('phase changed for %i changesets\n') % changes
5517 msg = _('phase changed for %i changesets\n') % changes
5522 if ret:
5518 if ret:
5523 ui.status(msg)
5519 ui.status(msg)
5524 else:
5520 else:
5525 ui.note(msg)
5521 ui.note(msg)
5526 else:
5522 else:
5527 ui.warn(_('no phases changed\n'))
5523 ui.warn(_('no phases changed\n'))
5528 return ret
5524 return ret
5529
5525
5530 def postincoming(ui, repo, modheads, optupdate, checkout):
5526 def postincoming(ui, repo, modheads, optupdate, checkout):
5531 if modheads == 0:
5527 if modheads == 0:
5532 return
5528 return
5533 if optupdate:
5529 if optupdate:
5534 try:
5530 try:
5535 brev = checkout
5531 brev = checkout
5536 movemarkfrom = None
5532 movemarkfrom = None
5537 if not checkout:
5533 if not checkout:
5538 updata = destutil.destupdate(repo)
5534 updata = destutil.destupdate(repo)
5539 checkout, movemarkfrom, brev = updata
5535 checkout, movemarkfrom, brev = updata
5540 ret = hg.update(repo, checkout)
5536 ret = hg.update(repo, checkout)
5541 except error.UpdateAbort as inst:
5537 except error.UpdateAbort as inst:
5542 msg = _("not updating: %s") % str(inst)
5538 msg = _("not updating: %s") % str(inst)
5543 hint = inst.hint
5539 hint = inst.hint
5544 raise error.UpdateAbort(msg, hint=hint)
5540 raise error.UpdateAbort(msg, hint=hint)
5545 if not ret and not checkout:
5541 if not ret and not checkout:
5546 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5542 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5547 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5543 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5548 return ret
5544 return ret
5549 if modheads > 1:
5545 if modheads > 1:
5550 currentbranchheads = len(repo.branchheads())
5546 currentbranchheads = len(repo.branchheads())
5551 if currentbranchheads == modheads:
5547 if currentbranchheads == modheads:
5552 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5548 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5553 elif currentbranchheads > 1:
5549 elif currentbranchheads > 1:
5554 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5550 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5555 "merge)\n"))
5551 "merge)\n"))
5556 else:
5552 else:
5557 ui.status(_("(run 'hg heads' to see heads)\n"))
5553 ui.status(_("(run 'hg heads' to see heads)\n"))
5558 else:
5554 else:
5559 ui.status(_("(run 'hg update' to get a working copy)\n"))
5555 ui.status(_("(run 'hg update' to get a working copy)\n"))
5560
5556
5561 @command('^pull',
5557 @command('^pull',
5562 [('u', 'update', None,
5558 [('u', 'update', None,
5563 _('update to new branch head if changesets were pulled')),
5559 _('update to new branch head if changesets were pulled')),
5564 ('f', 'force', None, _('run even when remote repository is unrelated')),
5560 ('f', 'force', None, _('run even when remote repository is unrelated')),
5565 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5561 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5566 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5562 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5567 ('b', 'branch', [], _('a specific branch you would like to pull'),
5563 ('b', 'branch', [], _('a specific branch you would like to pull'),
5568 _('BRANCH')),
5564 _('BRANCH')),
5569 ] + remoteopts,
5565 ] + remoteopts,
5570 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5566 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5571 def pull(ui, repo, source="default", **opts):
5567 def pull(ui, repo, source="default", **opts):
5572 """pull changes from the specified source
5568 """pull changes from the specified source
5573
5569
5574 Pull changes from a remote repository to a local one.
5570 Pull changes from a remote repository to a local one.
5575
5571
5576 This finds all changes from the repository at the specified path
5572 This finds all changes from the repository at the specified path
5577 or URL and adds them to a local repository (the current one unless
5573 or URL and adds them to a local repository (the current one unless
5578 -R is specified). By default, this does not update the copy of the
5574 -R is specified). By default, this does not update the copy of the
5579 project in the working directory.
5575 project in the working directory.
5580
5576
5581 Use :hg:`incoming` if you want to see what would have been added
5577 Use :hg:`incoming` if you want to see what would have been added
5582 by a pull at the time you issued this command. If you then decide
5578 by a pull at the time you issued this command. If you then decide
5583 to add those changes to the repository, you should use :hg:`pull
5579 to add those changes to the repository, you should use :hg:`pull
5584 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5580 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5585
5581
5586 If SOURCE is omitted, the 'default' path will be used.
5582 If SOURCE is omitted, the 'default' path will be used.
5587 See :hg:`help urls` for more information.
5583 See :hg:`help urls` for more information.
5588
5584
5589 Returns 0 on success, 1 if an update had unresolved files.
5585 Returns 0 on success, 1 if an update had unresolved files.
5590 """
5586 """
5591 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5587 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5592 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5588 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5593 other = hg.peer(repo, opts, source)
5589 other = hg.peer(repo, opts, source)
5594 try:
5590 try:
5595 revs, checkout = hg.addbranchrevs(repo, other, branches,
5591 revs, checkout = hg.addbranchrevs(repo, other, branches,
5596 opts.get('rev'))
5592 opts.get('rev'))
5597
5593
5598
5594
5599 pullopargs = {}
5595 pullopargs = {}
5600 if opts.get('bookmark'):
5596 if opts.get('bookmark'):
5601 if not revs:
5597 if not revs:
5602 revs = []
5598 revs = []
5603 # The list of bookmark used here is not the one used to actually
5599 # The list of bookmark used here is not the one used to actually
5604 # update the bookmark name. This can result in the revision pulled
5600 # update the bookmark name. This can result in the revision pulled
5605 # not ending up with the name of the bookmark because of a race
5601 # not ending up with the name of the bookmark because of a race
5606 # condition on the server. (See issue 4689 for details)
5602 # condition on the server. (See issue 4689 for details)
5607 remotebookmarks = other.listkeys('bookmarks')
5603 remotebookmarks = other.listkeys('bookmarks')
5608 pullopargs['remotebookmarks'] = remotebookmarks
5604 pullopargs['remotebookmarks'] = remotebookmarks
5609 for b in opts['bookmark']:
5605 for b in opts['bookmark']:
5610 if b not in remotebookmarks:
5606 if b not in remotebookmarks:
5611 raise error.Abort(_('remote bookmark %s not found!') % b)
5607 raise error.Abort(_('remote bookmark %s not found!') % b)
5612 revs.append(remotebookmarks[b])
5608 revs.append(remotebookmarks[b])
5613
5609
5614 if revs:
5610 if revs:
5615 try:
5611 try:
5616 # When 'rev' is a bookmark name, we cannot guarantee that it
5612 # When 'rev' is a bookmark name, we cannot guarantee that it
5617 # will be updated with that name because of a race condition
5613 # will be updated with that name because of a race condition
5618 # server side. (See issue 4689 for details)
5614 # server side. (See issue 4689 for details)
5619 oldrevs = revs
5615 oldrevs = revs
5620 revs = [] # actually, nodes
5616 revs = [] # actually, nodes
5621 for r in oldrevs:
5617 for r in oldrevs:
5622 node = other.lookup(r)
5618 node = other.lookup(r)
5623 revs.append(node)
5619 revs.append(node)
5624 if r == checkout:
5620 if r == checkout:
5625 checkout = node
5621 checkout = node
5626 except error.CapabilityError:
5622 except error.CapabilityError:
5627 err = _("other repository doesn't support revision lookup, "
5623 err = _("other repository doesn't support revision lookup, "
5628 "so a rev cannot be specified.")
5624 "so a rev cannot be specified.")
5629 raise error.Abort(err)
5625 raise error.Abort(err)
5630
5626
5631 pullopargs.update(opts.get('opargs', {}))
5627 pullopargs.update(opts.get('opargs', {}))
5632 modheads = exchange.pull(repo, other, heads=revs,
5628 modheads = exchange.pull(repo, other, heads=revs,
5633 force=opts.get('force'),
5629 force=opts.get('force'),
5634 bookmarks=opts.get('bookmark', ()),
5630 bookmarks=opts.get('bookmark', ()),
5635 opargs=pullopargs).cgresult
5631 opargs=pullopargs).cgresult
5636 if checkout:
5632 if checkout:
5637 checkout = str(repo.changelog.rev(checkout))
5633 checkout = str(repo.changelog.rev(checkout))
5638 repo._subtoppath = source
5634 repo._subtoppath = source
5639 try:
5635 try:
5640 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5636 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5641
5637
5642 finally:
5638 finally:
5643 del repo._subtoppath
5639 del repo._subtoppath
5644
5640
5645 finally:
5641 finally:
5646 other.close()
5642 other.close()
5647 return ret
5643 return ret
5648
5644
5649 @command('^push',
5645 @command('^push',
5650 [('f', 'force', None, _('force push')),
5646 [('f', 'force', None, _('force push')),
5651 ('r', 'rev', [],
5647 ('r', 'rev', [],
5652 _('a changeset intended to be included in the destination'),
5648 _('a changeset intended to be included in the destination'),
5653 _('REV')),
5649 _('REV')),
5654 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5650 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5655 ('b', 'branch', [],
5651 ('b', 'branch', [],
5656 _('a specific branch you would like to push'), _('BRANCH')),
5652 _('a specific branch you would like to push'), _('BRANCH')),
5657 ('', 'new-branch', False, _('allow pushing a new branch')),
5653 ('', 'new-branch', False, _('allow pushing a new branch')),
5658 ] + remoteopts,
5654 ] + remoteopts,
5659 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5655 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5660 def push(ui, repo, dest=None, **opts):
5656 def push(ui, repo, dest=None, **opts):
5661 """push changes to the specified destination
5657 """push changes to the specified destination
5662
5658
5663 Push changesets from the local repository to the specified
5659 Push changesets from the local repository to the specified
5664 destination.
5660 destination.
5665
5661
5666 This operation is symmetrical to pull: it is identical to a pull
5662 This operation is symmetrical to pull: it is identical to a pull
5667 in the destination repository from the current one.
5663 in the destination repository from the current one.
5668
5664
5669 By default, push will not allow creation of new heads at the
5665 By default, push will not allow creation of new heads at the
5670 destination, since multiple heads would make it unclear which head
5666 destination, since multiple heads would make it unclear which head
5671 to use. In this situation, it is recommended to pull and merge
5667 to use. In this situation, it is recommended to pull and merge
5672 before pushing.
5668 before pushing.
5673
5669
5674 Use --new-branch if you want to allow push to create a new named
5670 Use --new-branch if you want to allow push to create a new named
5675 branch that is not present at the destination. This allows you to
5671 branch that is not present at the destination. This allows you to
5676 only create a new branch without forcing other changes.
5672 only create a new branch without forcing other changes.
5677
5673
5678 .. note::
5674 .. note::
5679
5675
5680 Extra care should be taken with the -f/--force option,
5676 Extra care should be taken with the -f/--force option,
5681 which will push all new heads on all branches, an action which will
5677 which will push all new heads on all branches, an action which will
5682 almost always cause confusion for collaborators.
5678 almost always cause confusion for collaborators.
5683
5679
5684 If -r/--rev is used, the specified revision and all its ancestors
5680 If -r/--rev is used, the specified revision and all its ancestors
5685 will be pushed to the remote repository.
5681 will be pushed to the remote repository.
5686
5682
5687 If -B/--bookmark is used, the specified bookmarked revision, its
5683 If -B/--bookmark is used, the specified bookmarked revision, its
5688 ancestors, and the bookmark will be pushed to the remote
5684 ancestors, and the bookmark will be pushed to the remote
5689 repository.
5685 repository.
5690
5686
5691 Please see :hg:`help urls` for important details about ``ssh://``
5687 Please see :hg:`help urls` for important details about ``ssh://``
5692 URLs. If DESTINATION is omitted, a default path will be used.
5688 URLs. If DESTINATION is omitted, a default path will be used.
5693
5689
5694 Returns 0 if push was successful, 1 if nothing to push.
5690 Returns 0 if push was successful, 1 if nothing to push.
5695 """
5691 """
5696
5692
5697 if opts.get('bookmark'):
5693 if opts.get('bookmark'):
5698 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5694 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5699 for b in opts['bookmark']:
5695 for b in opts['bookmark']:
5700 # translate -B options to -r so changesets get pushed
5696 # translate -B options to -r so changesets get pushed
5701 if b in repo._bookmarks:
5697 if b in repo._bookmarks:
5702 opts.setdefault('rev', []).append(b)
5698 opts.setdefault('rev', []).append(b)
5703 else:
5699 else:
5704 # if we try to push a deleted bookmark, translate it to null
5700 # if we try to push a deleted bookmark, translate it to null
5705 # this lets simultaneous -r, -b options continue working
5701 # this lets simultaneous -r, -b options continue working
5706 opts.setdefault('rev', []).append("null")
5702 opts.setdefault('rev', []).append("null")
5707
5703
5708 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5704 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5709 if not path:
5705 if not path:
5710 raise error.Abort(_('default repository not configured!'),
5706 raise error.Abort(_('default repository not configured!'),
5711 hint=_('see the "path" section in "hg help config"'))
5707 hint=_('see the "path" section in "hg help config"'))
5712 dest = path.pushloc or path.loc
5708 dest = path.pushloc or path.loc
5713 branches = (path.branch, opts.get('branch') or [])
5709 branches = (path.branch, opts.get('branch') or [])
5714 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5710 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5715 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5711 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5716 other = hg.peer(repo, opts, dest)
5712 other = hg.peer(repo, opts, dest)
5717
5713
5718 if revs:
5714 if revs:
5719 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5715 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5720 if not revs:
5716 if not revs:
5721 raise error.Abort(_("specified revisions evaluate to an empty set"),
5717 raise error.Abort(_("specified revisions evaluate to an empty set"),
5722 hint=_("use different revision arguments"))
5718 hint=_("use different revision arguments"))
5723
5719
5724 repo._subtoppath = dest
5720 repo._subtoppath = dest
5725 try:
5721 try:
5726 # push subrepos depth-first for coherent ordering
5722 # push subrepos depth-first for coherent ordering
5727 c = repo['']
5723 c = repo['']
5728 subs = c.substate # only repos that are committed
5724 subs = c.substate # only repos that are committed
5729 for s in sorted(subs):
5725 for s in sorted(subs):
5730 result = c.sub(s).push(opts)
5726 result = c.sub(s).push(opts)
5731 if result == 0:
5727 if result == 0:
5732 return not result
5728 return not result
5733 finally:
5729 finally:
5734 del repo._subtoppath
5730 del repo._subtoppath
5735 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5731 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5736 newbranch=opts.get('new_branch'),
5732 newbranch=opts.get('new_branch'),
5737 bookmarks=opts.get('bookmark', ()),
5733 bookmarks=opts.get('bookmark', ()),
5738 opargs=opts.get('opargs'))
5734 opargs=opts.get('opargs'))
5739
5735
5740 result = not pushop.cgresult
5736 result = not pushop.cgresult
5741
5737
5742 if pushop.bkresult is not None:
5738 if pushop.bkresult is not None:
5743 if pushop.bkresult == 2:
5739 if pushop.bkresult == 2:
5744 result = 2
5740 result = 2
5745 elif not result and pushop.bkresult:
5741 elif not result and pushop.bkresult:
5746 result = 2
5742 result = 2
5747
5743
5748 return result
5744 return result
5749
5745
5750 @command('recover', [])
5746 @command('recover', [])
5751 def recover(ui, repo):
5747 def recover(ui, repo):
5752 """roll back an interrupted transaction
5748 """roll back an interrupted transaction
5753
5749
5754 Recover from an interrupted commit or pull.
5750 Recover from an interrupted commit or pull.
5755
5751
5756 This command tries to fix the repository status after an
5752 This command tries to fix the repository status after an
5757 interrupted operation. It should only be necessary when Mercurial
5753 interrupted operation. It should only be necessary when Mercurial
5758 suggests it.
5754 suggests it.
5759
5755
5760 Returns 0 if successful, 1 if nothing to recover or verify fails.
5756 Returns 0 if successful, 1 if nothing to recover or verify fails.
5761 """
5757 """
5762 if repo.recover():
5758 if repo.recover():
5763 return hg.verify(repo)
5759 return hg.verify(repo)
5764 return 1
5760 return 1
5765
5761
5766 @command('^remove|rm',
5762 @command('^remove|rm',
5767 [('A', 'after', None, _('record delete for missing files')),
5763 [('A', 'after', None, _('record delete for missing files')),
5768 ('f', 'force', None,
5764 ('f', 'force', None,
5769 _('remove (and delete) file even if added or modified')),
5765 _('remove (and delete) file even if added or modified')),
5770 ] + subrepoopts + walkopts,
5766 ] + subrepoopts + walkopts,
5771 _('[OPTION]... FILE...'),
5767 _('[OPTION]... FILE...'),
5772 inferrepo=True)
5768 inferrepo=True)
5773 def remove(ui, repo, *pats, **opts):
5769 def remove(ui, repo, *pats, **opts):
5774 """remove the specified files on the next commit
5770 """remove the specified files on the next commit
5775
5771
5776 Schedule the indicated files for removal from the current branch.
5772 Schedule the indicated files for removal from the current branch.
5777
5773
5778 This command schedules the files to be removed at the next commit.
5774 This command schedules the files to be removed at the next commit.
5779 To undo a remove before that, see :hg:`revert`. To undo added
5775 To undo a remove before that, see :hg:`revert`. To undo added
5780 files, see :hg:`forget`.
5776 files, see :hg:`forget`.
5781
5777
5782 .. container:: verbose
5778 .. container:: verbose
5783
5779
5784 -A/--after can be used to remove only files that have already
5780 -A/--after can be used to remove only files that have already
5785 been deleted, -f/--force can be used to force deletion, and -Af
5781 been deleted, -f/--force can be used to force deletion, and -Af
5786 can be used to remove files from the next revision without
5782 can be used to remove files from the next revision without
5787 deleting them from the working directory.
5783 deleting them from the working directory.
5788
5784
5789 The following table details the behavior of remove for different
5785 The following table details the behavior of remove for different
5790 file states (columns) and option combinations (rows). The file
5786 file states (columns) and option combinations (rows). The file
5791 states are Added [A], Clean [C], Modified [M] and Missing [!]
5787 states are Added [A], Clean [C], Modified [M] and Missing [!]
5792 (as reported by :hg:`status`). The actions are Warn, Remove
5788 (as reported by :hg:`status`). The actions are Warn, Remove
5793 (from branch) and Delete (from disk):
5789 (from branch) and Delete (from disk):
5794
5790
5795 ========= == == == ==
5791 ========= == == == ==
5796 opt/state A C M !
5792 opt/state A C M !
5797 ========= == == == ==
5793 ========= == == == ==
5798 none W RD W R
5794 none W RD W R
5799 -f R RD RD R
5795 -f R RD RD R
5800 -A W W W R
5796 -A W W W R
5801 -Af R R R R
5797 -Af R R R R
5802 ========= == == == ==
5798 ========= == == == ==
5803
5799
5804 .. note::
5800 .. note::
5805
5801
5806 :hg:`remove` never deletes files in Added [A] state from the
5802 :hg:`remove` never deletes files in Added [A] state from the
5807 working directory, not even if ``--force`` is specified.
5803 working directory, not even if ``--force`` is specified.
5808
5804
5809 Returns 0 on success, 1 if any warnings encountered.
5805 Returns 0 on success, 1 if any warnings encountered.
5810 """
5806 """
5811
5807
5812 after, force = opts.get('after'), opts.get('force')
5808 after, force = opts.get('after'), opts.get('force')
5813 if not pats and not after:
5809 if not pats and not after:
5814 raise error.Abort(_('no files specified'))
5810 raise error.Abort(_('no files specified'))
5815
5811
5816 m = scmutil.match(repo[None], pats, opts)
5812 m = scmutil.match(repo[None], pats, opts)
5817 subrepos = opts.get('subrepos')
5813 subrepos = opts.get('subrepos')
5818 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5814 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5819
5815
5820 @command('rename|move|mv',
5816 @command('rename|move|mv',
5821 [('A', 'after', None, _('record a rename that has already occurred')),
5817 [('A', 'after', None, _('record a rename that has already occurred')),
5822 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5818 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5823 ] + walkopts + dryrunopts,
5819 ] + walkopts + dryrunopts,
5824 _('[OPTION]... SOURCE... DEST'))
5820 _('[OPTION]... SOURCE... DEST'))
5825 def rename(ui, repo, *pats, **opts):
5821 def rename(ui, repo, *pats, **opts):
5826 """rename files; equivalent of copy + remove
5822 """rename files; equivalent of copy + remove
5827
5823
5828 Mark dest as copies of sources; mark sources for deletion. If dest
5824 Mark dest as copies of sources; mark sources for deletion. If dest
5829 is a directory, copies are put in that directory. If dest is a
5825 is a directory, copies are put in that directory. If dest is a
5830 file, there can only be one source.
5826 file, there can only be one source.
5831
5827
5832 By default, this command copies the contents of files as they
5828 By default, this command copies the contents of files as they
5833 exist in the working directory. If invoked with -A/--after, the
5829 exist in the working directory. If invoked with -A/--after, the
5834 operation is recorded, but no copying is performed.
5830 operation is recorded, but no copying is performed.
5835
5831
5836 This command takes effect at the next commit. To undo a rename
5832 This command takes effect at the next commit. To undo a rename
5837 before that, see :hg:`revert`.
5833 before that, see :hg:`revert`.
5838
5834
5839 Returns 0 on success, 1 if errors are encountered.
5835 Returns 0 on success, 1 if errors are encountered.
5840 """
5836 """
5841 wlock = repo.wlock(False)
5837 wlock = repo.wlock(False)
5842 try:
5838 try:
5843 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5839 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5844 finally:
5840 finally:
5845 wlock.release()
5841 wlock.release()
5846
5842
5847 @command('resolve',
5843 @command('resolve',
5848 [('a', 'all', None, _('select all unresolved files')),
5844 [('a', 'all', None, _('select all unresolved files')),
5849 ('l', 'list', None, _('list state of files needing merge')),
5845 ('l', 'list', None, _('list state of files needing merge')),
5850 ('m', 'mark', None, _('mark files as resolved')),
5846 ('m', 'mark', None, _('mark files as resolved')),
5851 ('u', 'unmark', None, _('mark files as unresolved')),
5847 ('u', 'unmark', None, _('mark files as unresolved')),
5852 ('n', 'no-status', None, _('hide status prefix'))]
5848 ('n', 'no-status', None, _('hide status prefix'))]
5853 + mergetoolopts + walkopts + formatteropts,
5849 + mergetoolopts + walkopts + formatteropts,
5854 _('[OPTION]... [FILE]...'),
5850 _('[OPTION]... [FILE]...'),
5855 inferrepo=True)
5851 inferrepo=True)
5856 def resolve(ui, repo, *pats, **opts):
5852 def resolve(ui, repo, *pats, **opts):
5857 """redo merges or set/view the merge status of files
5853 """redo merges or set/view the merge status of files
5858
5854
5859 Merges with unresolved conflicts are often the result of
5855 Merges with unresolved conflicts are often the result of
5860 non-interactive merging using the ``internal:merge`` configuration
5856 non-interactive merging using the ``internal:merge`` configuration
5861 setting, or a command-line merge tool like ``diff3``. The resolve
5857 setting, or a command-line merge tool like ``diff3``. The resolve
5862 command is used to manage the files involved in a merge, after
5858 command is used to manage the files involved in a merge, after
5863 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5859 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5864 working directory must have two parents). See :hg:`help
5860 working directory must have two parents). See :hg:`help
5865 merge-tools` for information on configuring merge tools.
5861 merge-tools` for information on configuring merge tools.
5866
5862
5867 The resolve command can be used in the following ways:
5863 The resolve command can be used in the following ways:
5868
5864
5869 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5865 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5870 files, discarding any previous merge attempts. Re-merging is not
5866 files, discarding any previous merge attempts. Re-merging is not
5871 performed for files already marked as resolved. Use ``--all/-a``
5867 performed for files already marked as resolved. Use ``--all/-a``
5872 to select all unresolved files. ``--tool`` can be used to specify
5868 to select all unresolved files. ``--tool`` can be used to specify
5873 the merge tool used for the given files. It overrides the HGMERGE
5869 the merge tool used for the given files. It overrides the HGMERGE
5874 environment variable and your configuration files. Previous file
5870 environment variable and your configuration files. Previous file
5875 contents are saved with a ``.orig`` suffix.
5871 contents are saved with a ``.orig`` suffix.
5876
5872
5877 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5873 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5878 (e.g. after having manually fixed-up the files). The default is
5874 (e.g. after having manually fixed-up the files). The default is
5879 to mark all unresolved files.
5875 to mark all unresolved files.
5880
5876
5881 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5877 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5882 default is to mark all resolved files.
5878 default is to mark all resolved files.
5883
5879
5884 - :hg:`resolve -l`: list files which had or still have conflicts.
5880 - :hg:`resolve -l`: list files which had or still have conflicts.
5885 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5881 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5886
5882
5887 .. note::
5883 .. note::
5888
5884
5889 Mercurial will not let you commit files with unresolved merge
5885 Mercurial will not let you commit files with unresolved merge
5890 conflicts. You must use :hg:`resolve -m ...` before you can
5886 conflicts. You must use :hg:`resolve -m ...` before you can
5891 commit after a conflicting merge.
5887 commit after a conflicting merge.
5892
5888
5893 Returns 0 on success, 1 if any files fail a resolve attempt.
5889 Returns 0 on success, 1 if any files fail a resolve attempt.
5894 """
5890 """
5895
5891
5896 all, mark, unmark, show, nostatus = \
5892 all, mark, unmark, show, nostatus = \
5897 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5893 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5898
5894
5899 if (show and (mark or unmark)) or (mark and unmark):
5895 if (show and (mark or unmark)) or (mark and unmark):
5900 raise error.Abort(_("too many options specified"))
5896 raise error.Abort(_("too many options specified"))
5901 if pats and all:
5897 if pats and all:
5902 raise error.Abort(_("can't specify --all and patterns"))
5898 raise error.Abort(_("can't specify --all and patterns"))
5903 if not (all or pats or show or mark or unmark):
5899 if not (all or pats or show or mark or unmark):
5904 raise error.Abort(_('no files or directories specified'),
5900 raise error.Abort(_('no files or directories specified'),
5905 hint=('use --all to re-merge all unresolved files'))
5901 hint=('use --all to re-merge all unresolved files'))
5906
5902
5907 if show:
5903 if show:
5908 fm = ui.formatter('resolve', opts)
5904 fm = ui.formatter('resolve', opts)
5909 ms = mergemod.mergestate.read(repo)
5905 ms = mergemod.mergestate.read(repo)
5910 m = scmutil.match(repo[None], pats, opts)
5906 m = scmutil.match(repo[None], pats, opts)
5911 for f in ms:
5907 for f in ms:
5912 if not m(f):
5908 if not m(f):
5913 continue
5909 continue
5914 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5910 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5915 'd': 'driverresolved'}[ms[f]]
5911 'd': 'driverresolved'}[ms[f]]
5916 fm.startitem()
5912 fm.startitem()
5917 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5913 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5918 fm.write('path', '%s\n', f, label=l)
5914 fm.write('path', '%s\n', f, label=l)
5919 fm.end()
5915 fm.end()
5920 return 0
5916 return 0
5921
5917
5922 wlock = repo.wlock()
5918 wlock = repo.wlock()
5923 try:
5919 try:
5924 ms = mergemod.mergestate.read(repo)
5920 ms = mergemod.mergestate.read(repo)
5925
5921
5926 if not (ms.active() or repo.dirstate.p2() != nullid):
5922 if not (ms.active() or repo.dirstate.p2() != nullid):
5927 raise error.Abort(
5923 raise error.Abort(
5928 _('resolve command not applicable when not merging'))
5924 _('resolve command not applicable when not merging'))
5929
5925
5930 wctx = repo[None]
5926 wctx = repo[None]
5931
5927
5932 if ms.mergedriver and ms.mdstate() == 'u':
5928 if ms.mergedriver and ms.mdstate() == 'u':
5933 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5929 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5934 ms.commit()
5930 ms.commit()
5935 # allow mark and unmark to go through
5931 # allow mark and unmark to go through
5936 if not mark and not unmark and not proceed:
5932 if not mark and not unmark and not proceed:
5937 return 1
5933 return 1
5938
5934
5939 m = scmutil.match(wctx, pats, opts)
5935 m = scmutil.match(wctx, pats, opts)
5940 ret = 0
5936 ret = 0
5941 didwork = False
5937 didwork = False
5942 runconclude = False
5938 runconclude = False
5943
5939
5944 tocomplete = []
5940 tocomplete = []
5945 for f in ms:
5941 for f in ms:
5946 if not m(f):
5942 if not m(f):
5947 continue
5943 continue
5948
5944
5949 didwork = True
5945 didwork = True
5950
5946
5951 # don't let driver-resolved files be marked, and run the conclude
5947 # don't let driver-resolved files be marked, and run the conclude
5952 # step if asked to resolve
5948 # step if asked to resolve
5953 if ms[f] == "d":
5949 if ms[f] == "d":
5954 exact = m.exact(f)
5950 exact = m.exact(f)
5955 if mark:
5951 if mark:
5956 if exact:
5952 if exact:
5957 ui.warn(_('not marking %s as it is driver-resolved\n')
5953 ui.warn(_('not marking %s as it is driver-resolved\n')
5958 % f)
5954 % f)
5959 elif unmark:
5955 elif unmark:
5960 if exact:
5956 if exact:
5961 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5957 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5962 % f)
5958 % f)
5963 else:
5959 else:
5964 runconclude = True
5960 runconclude = True
5965 continue
5961 continue
5966
5962
5967 if mark:
5963 if mark:
5968 ms.mark(f, "r")
5964 ms.mark(f, "r")
5969 elif unmark:
5965 elif unmark:
5970 ms.mark(f, "u")
5966 ms.mark(f, "u")
5971 else:
5967 else:
5972 # backup pre-resolve (merge uses .orig for its own purposes)
5968 # backup pre-resolve (merge uses .orig for its own purposes)
5973 a = repo.wjoin(f)
5969 a = repo.wjoin(f)
5974 try:
5970 try:
5975 util.copyfile(a, a + ".resolve")
5971 util.copyfile(a, a + ".resolve")
5976 except (IOError, OSError) as inst:
5972 except (IOError, OSError) as inst:
5977 if inst.errno != errno.ENOENT:
5973 if inst.errno != errno.ENOENT:
5978 raise
5974 raise
5979
5975
5980 try:
5976 try:
5981 # preresolve file
5977 # preresolve file
5982 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5978 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5983 'resolve')
5979 'resolve')
5984 complete, r = ms.preresolve(f, wctx)
5980 complete, r = ms.preresolve(f, wctx)
5985 if not complete:
5981 if not complete:
5986 tocomplete.append(f)
5982 tocomplete.append(f)
5987 elif r:
5983 elif r:
5988 ret = 1
5984 ret = 1
5989 finally:
5985 finally:
5990 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5986 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5991 ms.commit()
5987 ms.commit()
5992
5988
5993 # replace filemerge's .orig file with our resolve file, but only
5989 # replace filemerge's .orig file with our resolve file, but only
5994 # for merges that are complete
5990 # for merges that are complete
5995 if complete:
5991 if complete:
5996 try:
5992 try:
5997 util.rename(a + ".resolve",
5993 util.rename(a + ".resolve",
5998 scmutil.origpath(ui, repo, a))
5994 scmutil.origpath(ui, repo, a))
5999 except OSError as inst:
5995 except OSError as inst:
6000 if inst.errno != errno.ENOENT:
5996 if inst.errno != errno.ENOENT:
6001 raise
5997 raise
6002
5998
6003 for f in tocomplete:
5999 for f in tocomplete:
6004 try:
6000 try:
6005 # resolve file
6001 # resolve file
6006 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6002 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6007 'resolve')
6003 'resolve')
6008 r = ms.resolve(f, wctx)
6004 r = ms.resolve(f, wctx)
6009 if r:
6005 if r:
6010 ret = 1
6006 ret = 1
6011 finally:
6007 finally:
6012 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6008 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6013 ms.commit()
6009 ms.commit()
6014
6010
6015 # replace filemerge's .orig file with our resolve file
6011 # replace filemerge's .orig file with our resolve file
6016 a = repo.wjoin(f)
6012 a = repo.wjoin(f)
6017 try:
6013 try:
6018 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6014 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6019 except OSError as inst:
6015 except OSError as inst:
6020 if inst.errno != errno.ENOENT:
6016 if inst.errno != errno.ENOENT:
6021 raise
6017 raise
6022
6018
6023 ms.commit()
6019 ms.commit()
6024 ms.recordactions()
6020 ms.recordactions()
6025
6021
6026 if not didwork and pats:
6022 if not didwork and pats:
6027 ui.warn(_("arguments do not match paths that need resolving\n"))
6023 ui.warn(_("arguments do not match paths that need resolving\n"))
6028 elif ms.mergedriver and ms.mdstate() != 's':
6024 elif ms.mergedriver and ms.mdstate() != 's':
6029 # run conclude step when either a driver-resolved file is requested
6025 # run conclude step when either a driver-resolved file is requested
6030 # or there are no driver-resolved files
6026 # or there are no driver-resolved files
6031 # we can't use 'ret' to determine whether any files are unresolved
6027 # we can't use 'ret' to determine whether any files are unresolved
6032 # because we might not have tried to resolve some
6028 # because we might not have tried to resolve some
6033 if ((runconclude or not list(ms.driverresolved()))
6029 if ((runconclude or not list(ms.driverresolved()))
6034 and not list(ms.unresolved())):
6030 and not list(ms.unresolved())):
6035 proceed = mergemod.driverconclude(repo, ms, wctx)
6031 proceed = mergemod.driverconclude(repo, ms, wctx)
6036 ms.commit()
6032 ms.commit()
6037 if not proceed:
6033 if not proceed:
6038 return 1
6034 return 1
6039
6035
6040 finally:
6036 finally:
6041 wlock.release()
6037 wlock.release()
6042
6038
6043 # Nudge users into finishing an unfinished operation
6039 # Nudge users into finishing an unfinished operation
6044 unresolvedf = list(ms.unresolved())
6040 unresolvedf = list(ms.unresolved())
6045 driverresolvedf = list(ms.driverresolved())
6041 driverresolvedf = list(ms.driverresolved())
6046 if not unresolvedf and not driverresolvedf:
6042 if not unresolvedf and not driverresolvedf:
6047 ui.status(_('(no more unresolved files)\n'))
6043 ui.status(_('(no more unresolved files)\n'))
6048 cmdutil.checkafterresolved(repo)
6044 cmdutil.checkafterresolved(repo)
6049 elif not unresolvedf:
6045 elif not unresolvedf:
6050 ui.status(_('(no more unresolved files -- '
6046 ui.status(_('(no more unresolved files -- '
6051 'run "hg resolve --all" to conclude)\n'))
6047 'run "hg resolve --all" to conclude)\n'))
6052
6048
6053 return ret
6049 return ret
6054
6050
6055 @command('revert',
6051 @command('revert',
6056 [('a', 'all', None, _('revert all changes when no arguments given')),
6052 [('a', 'all', None, _('revert all changes when no arguments given')),
6057 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6053 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6058 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6054 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6059 ('C', 'no-backup', None, _('do not save backup copies of files')),
6055 ('C', 'no-backup', None, _('do not save backup copies of files')),
6060 ('i', 'interactive', None,
6056 ('i', 'interactive', None,
6061 _('interactively select the changes (EXPERIMENTAL)')),
6057 _('interactively select the changes (EXPERIMENTAL)')),
6062 ] + walkopts + dryrunopts,
6058 ] + walkopts + dryrunopts,
6063 _('[OPTION]... [-r REV] [NAME]...'))
6059 _('[OPTION]... [-r REV] [NAME]...'))
6064 def revert(ui, repo, *pats, **opts):
6060 def revert(ui, repo, *pats, **opts):
6065 """restore files to their checkout state
6061 """restore files to their checkout state
6066
6062
6067 .. note::
6063 .. note::
6068
6064
6069 To check out earlier revisions, you should use :hg:`update REV`.
6065 To check out earlier revisions, you should use :hg:`update REV`.
6070 To cancel an uncommitted merge (and lose your changes),
6066 To cancel an uncommitted merge (and lose your changes),
6071 use :hg:`update --clean .`.
6067 use :hg:`update --clean .`.
6072
6068
6073 With no revision specified, revert the specified files or directories
6069 With no revision specified, revert the specified files or directories
6074 to the contents they had in the parent of the working directory.
6070 to the contents they had in the parent of the working directory.
6075 This restores the contents of files to an unmodified
6071 This restores the contents of files to an unmodified
6076 state and unschedules adds, removes, copies, and renames. If the
6072 state and unschedules adds, removes, copies, and renames. If the
6077 working directory has two parents, you must explicitly specify a
6073 working directory has two parents, you must explicitly specify a
6078 revision.
6074 revision.
6079
6075
6080 Using the -r/--rev or -d/--date options, revert the given files or
6076 Using the -r/--rev or -d/--date options, revert the given files or
6081 directories to their states as of a specific revision. Because
6077 directories to their states as of a specific revision. Because
6082 revert does not change the working directory parents, this will
6078 revert does not change the working directory parents, this will
6083 cause these files to appear modified. This can be helpful to "back
6079 cause these files to appear modified. This can be helpful to "back
6084 out" some or all of an earlier change. See :hg:`backout` for a
6080 out" some or all of an earlier change. See :hg:`backout` for a
6085 related method.
6081 related method.
6086
6082
6087 Modified files are saved with a .orig suffix before reverting.
6083 Modified files are saved with a .orig suffix before reverting.
6088 To disable these backups, use --no-backup.
6084 To disable these backups, use --no-backup.
6089
6085
6090 See :hg:`help dates` for a list of formats valid for -d/--date.
6086 See :hg:`help dates` for a list of formats valid for -d/--date.
6091
6087
6092 See :hg:`help backout` for a way to reverse the effect of an
6088 See :hg:`help backout` for a way to reverse the effect of an
6093 earlier changeset.
6089 earlier changeset.
6094
6090
6095 Returns 0 on success.
6091 Returns 0 on success.
6096 """
6092 """
6097
6093
6098 if opts.get("date"):
6094 if opts.get("date"):
6099 if opts.get("rev"):
6095 if opts.get("rev"):
6100 raise error.Abort(_("you can't specify a revision and a date"))
6096 raise error.Abort(_("you can't specify a revision and a date"))
6101 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6097 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6102
6098
6103 parent, p2 = repo.dirstate.parents()
6099 parent, p2 = repo.dirstate.parents()
6104 if not opts.get('rev') and p2 != nullid:
6100 if not opts.get('rev') and p2 != nullid:
6105 # revert after merge is a trap for new users (issue2915)
6101 # revert after merge is a trap for new users (issue2915)
6106 raise error.Abort(_('uncommitted merge with no revision specified'),
6102 raise error.Abort(_('uncommitted merge with no revision specified'),
6107 hint=_('use "hg update" or see "hg help revert"'))
6103 hint=_('use "hg update" or see "hg help revert"'))
6108
6104
6109 ctx = scmutil.revsingle(repo, opts.get('rev'))
6105 ctx = scmutil.revsingle(repo, opts.get('rev'))
6110
6106
6111 if (not (pats or opts.get('include') or opts.get('exclude') or
6107 if (not (pats or opts.get('include') or opts.get('exclude') or
6112 opts.get('all') or opts.get('interactive'))):
6108 opts.get('all') or opts.get('interactive'))):
6113 msg = _("no files or directories specified")
6109 msg = _("no files or directories specified")
6114 if p2 != nullid:
6110 if p2 != nullid:
6115 hint = _("uncommitted merge, use --all to discard all changes,"
6111 hint = _("uncommitted merge, use --all to discard all changes,"
6116 " or 'hg update -C .' to abort the merge")
6112 " or 'hg update -C .' to abort the merge")
6117 raise error.Abort(msg, hint=hint)
6113 raise error.Abort(msg, hint=hint)
6118 dirty = any(repo.status())
6114 dirty = any(repo.status())
6119 node = ctx.node()
6115 node = ctx.node()
6120 if node != parent:
6116 if node != parent:
6121 if dirty:
6117 if dirty:
6122 hint = _("uncommitted changes, use --all to discard all"
6118 hint = _("uncommitted changes, use --all to discard all"
6123 " changes, or 'hg update %s' to update") % ctx.rev()
6119 " changes, or 'hg update %s' to update") % ctx.rev()
6124 else:
6120 else:
6125 hint = _("use --all to revert all files,"
6121 hint = _("use --all to revert all files,"
6126 " or 'hg update %s' to update") % ctx.rev()
6122 " or 'hg update %s' to update") % ctx.rev()
6127 elif dirty:
6123 elif dirty:
6128 hint = _("uncommitted changes, use --all to discard all changes")
6124 hint = _("uncommitted changes, use --all to discard all changes")
6129 else:
6125 else:
6130 hint = _("use --all to revert all files")
6126 hint = _("use --all to revert all files")
6131 raise error.Abort(msg, hint=hint)
6127 raise error.Abort(msg, hint=hint)
6132
6128
6133 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6129 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6134
6130
6135 @command('rollback', dryrunopts +
6131 @command('rollback', dryrunopts +
6136 [('f', 'force', False, _('ignore safety measures'))])
6132 [('f', 'force', False, _('ignore safety measures'))])
6137 def rollback(ui, repo, **opts):
6133 def rollback(ui, repo, **opts):
6138 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6134 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6139
6135
6140 Please use :hg:`commit --amend` instead of rollback to correct
6136 Please use :hg:`commit --amend` instead of rollback to correct
6141 mistakes in the last commit.
6137 mistakes in the last commit.
6142
6138
6143 This command should be used with care. There is only one level of
6139 This command should be used with care. There is only one level of
6144 rollback, and there is no way to undo a rollback. It will also
6140 rollback, and there is no way to undo a rollback. It will also
6145 restore the dirstate at the time of the last transaction, losing
6141 restore the dirstate at the time of the last transaction, losing
6146 any dirstate changes since that time. This command does not alter
6142 any dirstate changes since that time. This command does not alter
6147 the working directory.
6143 the working directory.
6148
6144
6149 Transactions are used to encapsulate the effects of all commands
6145 Transactions are used to encapsulate the effects of all commands
6150 that create new changesets or propagate existing changesets into a
6146 that create new changesets or propagate existing changesets into a
6151 repository.
6147 repository.
6152
6148
6153 .. container:: verbose
6149 .. container:: verbose
6154
6150
6155 For example, the following commands are transactional, and their
6151 For example, the following commands are transactional, and their
6156 effects can be rolled back:
6152 effects can be rolled back:
6157
6153
6158 - commit
6154 - commit
6159 - import
6155 - import
6160 - pull
6156 - pull
6161 - push (with this repository as the destination)
6157 - push (with this repository as the destination)
6162 - unbundle
6158 - unbundle
6163
6159
6164 To avoid permanent data loss, rollback will refuse to rollback a
6160 To avoid permanent data loss, rollback will refuse to rollback a
6165 commit transaction if it isn't checked out. Use --force to
6161 commit transaction if it isn't checked out. Use --force to
6166 override this protection.
6162 override this protection.
6167
6163
6168 This command is not intended for use on public repositories. Once
6164 This command is not intended for use on public repositories. Once
6169 changes are visible for pull by other users, rolling a transaction
6165 changes are visible for pull by other users, rolling a transaction
6170 back locally is ineffective (someone else may already have pulled
6166 back locally is ineffective (someone else may already have pulled
6171 the changes). Furthermore, a race is possible with readers of the
6167 the changes). Furthermore, a race is possible with readers of the
6172 repository; for example an in-progress pull from the repository
6168 repository; for example an in-progress pull from the repository
6173 may fail if a rollback is performed.
6169 may fail if a rollback is performed.
6174
6170
6175 Returns 0 on success, 1 if no rollback data is available.
6171 Returns 0 on success, 1 if no rollback data is available.
6176 """
6172 """
6177 return repo.rollback(dryrun=opts.get('dry_run'),
6173 return repo.rollback(dryrun=opts.get('dry_run'),
6178 force=opts.get('force'))
6174 force=opts.get('force'))
6179
6175
6180 @command('root', [])
6176 @command('root', [])
6181 def root(ui, repo):
6177 def root(ui, repo):
6182 """print the root (top) of the current working directory
6178 """print the root (top) of the current working directory
6183
6179
6184 Print the root directory of the current repository.
6180 Print the root directory of the current repository.
6185
6181
6186 Returns 0 on success.
6182 Returns 0 on success.
6187 """
6183 """
6188 ui.write(repo.root + "\n")
6184 ui.write(repo.root + "\n")
6189
6185
6190 @command('^serve',
6186 @command('^serve',
6191 [('A', 'accesslog', '', _('name of access log file to write to'),
6187 [('A', 'accesslog', '', _('name of access log file to write to'),
6192 _('FILE')),
6188 _('FILE')),
6193 ('d', 'daemon', None, _('run server in background')),
6189 ('d', 'daemon', None, _('run server in background')),
6194 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6190 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6195 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6191 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6196 # use string type, then we can check if something was passed
6192 # use string type, then we can check if something was passed
6197 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6193 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6198 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6194 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6199 _('ADDR')),
6195 _('ADDR')),
6200 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6196 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6201 _('PREFIX')),
6197 _('PREFIX')),
6202 ('n', 'name', '',
6198 ('n', 'name', '',
6203 _('name to show in web pages (default: working directory)'), _('NAME')),
6199 _('name to show in web pages (default: working directory)'), _('NAME')),
6204 ('', 'web-conf', '',
6200 ('', 'web-conf', '',
6205 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6201 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6206 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6202 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6207 _('FILE')),
6203 _('FILE')),
6208 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6204 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6209 ('', 'stdio', None, _('for remote clients')),
6205 ('', 'stdio', None, _('for remote clients')),
6210 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6206 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6211 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6207 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6212 ('', 'style', '', _('template style to use'), _('STYLE')),
6208 ('', 'style', '', _('template style to use'), _('STYLE')),
6213 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6209 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6214 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6210 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6215 _('[OPTION]...'),
6211 _('[OPTION]...'),
6216 optionalrepo=True)
6212 optionalrepo=True)
6217 def serve(ui, repo, **opts):
6213 def serve(ui, repo, **opts):
6218 """start stand-alone webserver
6214 """start stand-alone webserver
6219
6215
6220 Start a local HTTP repository browser and pull server. You can use
6216 Start a local HTTP repository browser and pull server. You can use
6221 this for ad-hoc sharing and browsing of repositories. It is
6217 this for ad-hoc sharing and browsing of repositories. It is
6222 recommended to use a real web server to serve a repository for
6218 recommended to use a real web server to serve a repository for
6223 longer periods of time.
6219 longer periods of time.
6224
6220
6225 Please note that the server does not implement access control.
6221 Please note that the server does not implement access control.
6226 This means that, by default, anybody can read from the server and
6222 This means that, by default, anybody can read from the server and
6227 nobody can write to it by default. Set the ``web.allow_push``
6223 nobody can write to it by default. Set the ``web.allow_push``
6228 option to ``*`` to allow everybody to push to the server. You
6224 option to ``*`` to allow everybody to push to the server. You
6229 should use a real web server if you need to authenticate users.
6225 should use a real web server if you need to authenticate users.
6230
6226
6231 By default, the server logs accesses to stdout and errors to
6227 By default, the server logs accesses to stdout and errors to
6232 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6228 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6233 files.
6229 files.
6234
6230
6235 To have the server choose a free port number to listen on, specify
6231 To have the server choose a free port number to listen on, specify
6236 a port number of 0; in this case, the server will print the port
6232 a port number of 0; in this case, the server will print the port
6237 number it uses.
6233 number it uses.
6238
6234
6239 Returns 0 on success.
6235 Returns 0 on success.
6240 """
6236 """
6241
6237
6242 if opts["stdio"] and opts["cmdserver"]:
6238 if opts["stdio"] and opts["cmdserver"]:
6243 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6239 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6244
6240
6245 if opts["stdio"]:
6241 if opts["stdio"]:
6246 if repo is None:
6242 if repo is None:
6247 raise error.RepoError(_("there is no Mercurial repository here"
6243 raise error.RepoError(_("there is no Mercurial repository here"
6248 " (.hg not found)"))
6244 " (.hg not found)"))
6249 s = sshserver.sshserver(ui, repo)
6245 s = sshserver.sshserver(ui, repo)
6250 s.serve_forever()
6246 s.serve_forever()
6251
6247
6252 if opts["cmdserver"]:
6248 if opts["cmdserver"]:
6253 service = commandserver.createservice(ui, repo, opts)
6249 service = commandserver.createservice(ui, repo, opts)
6254 else:
6250 else:
6255 service = hgweb.createservice(ui, repo, opts)
6251 service = hgweb.createservice(ui, repo, opts)
6256 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6252 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6257
6253
6258 @command('^status|st',
6254 @command('^status|st',
6259 [('A', 'all', None, _('show status of all files')),
6255 [('A', 'all', None, _('show status of all files')),
6260 ('m', 'modified', None, _('show only modified files')),
6256 ('m', 'modified', None, _('show only modified files')),
6261 ('a', 'added', None, _('show only added files')),
6257 ('a', 'added', None, _('show only added files')),
6262 ('r', 'removed', None, _('show only removed files')),
6258 ('r', 'removed', None, _('show only removed files')),
6263 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6259 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6264 ('c', 'clean', None, _('show only files without changes')),
6260 ('c', 'clean', None, _('show only files without changes')),
6265 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6261 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6266 ('i', 'ignored', None, _('show only ignored files')),
6262 ('i', 'ignored', None, _('show only ignored files')),
6267 ('n', 'no-status', None, _('hide status prefix')),
6263 ('n', 'no-status', None, _('hide status prefix')),
6268 ('C', 'copies', None, _('show source of copied files')),
6264 ('C', 'copies', None, _('show source of copied files')),
6269 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6265 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6270 ('', 'rev', [], _('show difference from revision'), _('REV')),
6266 ('', 'rev', [], _('show difference from revision'), _('REV')),
6271 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6267 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6272 ] + walkopts + subrepoopts + formatteropts,
6268 ] + walkopts + subrepoopts + formatteropts,
6273 _('[OPTION]... [FILE]...'),
6269 _('[OPTION]... [FILE]...'),
6274 inferrepo=True)
6270 inferrepo=True)
6275 def status(ui, repo, *pats, **opts):
6271 def status(ui, repo, *pats, **opts):
6276 """show changed files in the working directory
6272 """show changed files in the working directory
6277
6273
6278 Show status of files in the repository. If names are given, only
6274 Show status of files in the repository. If names are given, only
6279 files that match are shown. Files that are clean or ignored or
6275 files that match are shown. Files that are clean or ignored or
6280 the source of a copy/move operation, are not listed unless
6276 the source of a copy/move operation, are not listed unless
6281 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6277 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6282 Unless options described with "show only ..." are given, the
6278 Unless options described with "show only ..." are given, the
6283 options -mardu are used.
6279 options -mardu are used.
6284
6280
6285 Option -q/--quiet hides untracked (unknown and ignored) files
6281 Option -q/--quiet hides untracked (unknown and ignored) files
6286 unless explicitly requested with -u/--unknown or -i/--ignored.
6282 unless explicitly requested with -u/--unknown or -i/--ignored.
6287
6283
6288 .. note::
6284 .. note::
6289
6285
6290 :hg:`status` may appear to disagree with diff if permissions have
6286 :hg:`status` may appear to disagree with diff if permissions have
6291 changed or a merge has occurred. The standard diff format does
6287 changed or a merge has occurred. The standard diff format does
6292 not report permission changes and diff only reports changes
6288 not report permission changes and diff only reports changes
6293 relative to one merge parent.
6289 relative to one merge parent.
6294
6290
6295 If one revision is given, it is used as the base revision.
6291 If one revision is given, it is used as the base revision.
6296 If two revisions are given, the differences between them are
6292 If two revisions are given, the differences between them are
6297 shown. The --change option can also be used as a shortcut to list
6293 shown. The --change option can also be used as a shortcut to list
6298 the changed files of a revision from its first parent.
6294 the changed files of a revision from its first parent.
6299
6295
6300 The codes used to show the status of files are::
6296 The codes used to show the status of files are::
6301
6297
6302 M = modified
6298 M = modified
6303 A = added
6299 A = added
6304 R = removed
6300 R = removed
6305 C = clean
6301 C = clean
6306 ! = missing (deleted by non-hg command, but still tracked)
6302 ! = missing (deleted by non-hg command, but still tracked)
6307 ? = not tracked
6303 ? = not tracked
6308 I = ignored
6304 I = ignored
6309 = origin of the previous file (with --copies)
6305 = origin of the previous file (with --copies)
6310
6306
6311 .. container:: verbose
6307 .. container:: verbose
6312
6308
6313 Examples:
6309 Examples:
6314
6310
6315 - show changes in the working directory relative to a
6311 - show changes in the working directory relative to a
6316 changeset::
6312 changeset::
6317
6313
6318 hg status --rev 9353
6314 hg status --rev 9353
6319
6315
6320 - show changes in the working directory relative to the
6316 - show changes in the working directory relative to the
6321 current directory (see :hg:`help patterns` for more information)::
6317 current directory (see :hg:`help patterns` for more information)::
6322
6318
6323 hg status re:
6319 hg status re:
6324
6320
6325 - show all changes including copies in an existing changeset::
6321 - show all changes including copies in an existing changeset::
6326
6322
6327 hg status --copies --change 9353
6323 hg status --copies --change 9353
6328
6324
6329 - get a NUL separated list of added files, suitable for xargs::
6325 - get a NUL separated list of added files, suitable for xargs::
6330
6326
6331 hg status -an0
6327 hg status -an0
6332
6328
6333 Returns 0 on success.
6329 Returns 0 on success.
6334 """
6330 """
6335
6331
6336 revs = opts.get('rev')
6332 revs = opts.get('rev')
6337 change = opts.get('change')
6333 change = opts.get('change')
6338
6334
6339 if revs and change:
6335 if revs and change:
6340 msg = _('cannot specify --rev and --change at the same time')
6336 msg = _('cannot specify --rev and --change at the same time')
6341 raise error.Abort(msg)
6337 raise error.Abort(msg)
6342 elif change:
6338 elif change:
6343 node2 = scmutil.revsingle(repo, change, None).node()
6339 node2 = scmutil.revsingle(repo, change, None).node()
6344 node1 = repo[node2].p1().node()
6340 node1 = repo[node2].p1().node()
6345 else:
6341 else:
6346 node1, node2 = scmutil.revpair(repo, revs)
6342 node1, node2 = scmutil.revpair(repo, revs)
6347
6343
6348 if pats:
6344 if pats:
6349 cwd = repo.getcwd()
6345 cwd = repo.getcwd()
6350 else:
6346 else:
6351 cwd = ''
6347 cwd = ''
6352
6348
6353 if opts.get('print0'):
6349 if opts.get('print0'):
6354 end = '\0'
6350 end = '\0'
6355 else:
6351 else:
6356 end = '\n'
6352 end = '\n'
6357 copy = {}
6353 copy = {}
6358 states = 'modified added removed deleted unknown ignored clean'.split()
6354 states = 'modified added removed deleted unknown ignored clean'.split()
6359 show = [k for k in states if opts.get(k)]
6355 show = [k for k in states if opts.get(k)]
6360 if opts.get('all'):
6356 if opts.get('all'):
6361 show += ui.quiet and (states[:4] + ['clean']) or states
6357 show += ui.quiet and (states[:4] + ['clean']) or states
6362 if not show:
6358 if not show:
6363 if ui.quiet:
6359 if ui.quiet:
6364 show = states[:4]
6360 show = states[:4]
6365 else:
6361 else:
6366 show = states[:5]
6362 show = states[:5]
6367
6363
6368 m = scmutil.match(repo[node2], pats, opts)
6364 m = scmutil.match(repo[node2], pats, opts)
6369 stat = repo.status(node1, node2, m,
6365 stat = repo.status(node1, node2, m,
6370 'ignored' in show, 'clean' in show, 'unknown' in show,
6366 'ignored' in show, 'clean' in show, 'unknown' in show,
6371 opts.get('subrepos'))
6367 opts.get('subrepos'))
6372 changestates = zip(states, 'MAR!?IC', stat)
6368 changestates = zip(states, 'MAR!?IC', stat)
6373
6369
6374 if (opts.get('all') or opts.get('copies')
6370 if (opts.get('all') or opts.get('copies')
6375 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6371 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6376 copy = copies.pathcopies(repo[node1], repo[node2], m)
6372 copy = copies.pathcopies(repo[node1], repo[node2], m)
6377
6373
6378 fm = ui.formatter('status', opts)
6374 fm = ui.formatter('status', opts)
6379 fmt = '%s' + end
6375 fmt = '%s' + end
6380 showchar = not opts.get('no_status')
6376 showchar = not opts.get('no_status')
6381
6377
6382 for state, char, files in changestates:
6378 for state, char, files in changestates:
6383 if state in show:
6379 if state in show:
6384 label = 'status.' + state
6380 label = 'status.' + state
6385 for f in files:
6381 for f in files:
6386 fm.startitem()
6382 fm.startitem()
6387 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6383 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6388 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6384 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6389 if f in copy:
6385 if f in copy:
6390 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6386 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6391 label='status.copied')
6387 label='status.copied')
6392 fm.end()
6388 fm.end()
6393
6389
6394 @command('^summary|sum',
6390 @command('^summary|sum',
6395 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6391 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6396 def summary(ui, repo, **opts):
6392 def summary(ui, repo, **opts):
6397 """summarize working directory state
6393 """summarize working directory state
6398
6394
6399 This generates a brief summary of the working directory state,
6395 This generates a brief summary of the working directory state,
6400 including parents, branch, commit status, phase and available updates.
6396 including parents, branch, commit status, phase and available updates.
6401
6397
6402 With the --remote option, this will check the default paths for
6398 With the --remote option, this will check the default paths for
6403 incoming and outgoing changes. This can be time-consuming.
6399 incoming and outgoing changes. This can be time-consuming.
6404
6400
6405 Returns 0 on success.
6401 Returns 0 on success.
6406 """
6402 """
6407
6403
6408 ctx = repo[None]
6404 ctx = repo[None]
6409 parents = ctx.parents()
6405 parents = ctx.parents()
6410 pnode = parents[0].node()
6406 pnode = parents[0].node()
6411 marks = []
6407 marks = []
6412
6408
6413 for p in parents:
6409 for p in parents:
6414 # label with log.changeset (instead of log.parent) since this
6410 # label with log.changeset (instead of log.parent) since this
6415 # shows a working directory parent *changeset*:
6411 # shows a working directory parent *changeset*:
6416 # i18n: column positioning for "hg summary"
6412 # i18n: column positioning for "hg summary"
6417 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6413 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6418 label='log.changeset changeset.%s' % p.phasestr())
6414 label='log.changeset changeset.%s' % p.phasestr())
6419 ui.write(' '.join(p.tags()), label='log.tag')
6415 ui.write(' '.join(p.tags()), label='log.tag')
6420 if p.bookmarks():
6416 if p.bookmarks():
6421 marks.extend(p.bookmarks())
6417 marks.extend(p.bookmarks())
6422 if p.rev() == -1:
6418 if p.rev() == -1:
6423 if not len(repo):
6419 if not len(repo):
6424 ui.write(_(' (empty repository)'))
6420 ui.write(_(' (empty repository)'))
6425 else:
6421 else:
6426 ui.write(_(' (no revision checked out)'))
6422 ui.write(_(' (no revision checked out)'))
6427 ui.write('\n')
6423 ui.write('\n')
6428 if p.description():
6424 if p.description():
6429 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6425 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6430 label='log.summary')
6426 label='log.summary')
6431
6427
6432 branch = ctx.branch()
6428 branch = ctx.branch()
6433 bheads = repo.branchheads(branch)
6429 bheads = repo.branchheads(branch)
6434 # i18n: column positioning for "hg summary"
6430 # i18n: column positioning for "hg summary"
6435 m = _('branch: %s\n') % branch
6431 m = _('branch: %s\n') % branch
6436 if branch != 'default':
6432 if branch != 'default':
6437 ui.write(m, label='log.branch')
6433 ui.write(m, label='log.branch')
6438 else:
6434 else:
6439 ui.status(m, label='log.branch')
6435 ui.status(m, label='log.branch')
6440
6436
6441 if marks:
6437 if marks:
6442 active = repo._activebookmark
6438 active = repo._activebookmark
6443 # i18n: column positioning for "hg summary"
6439 # i18n: column positioning for "hg summary"
6444 ui.write(_('bookmarks:'), label='log.bookmark')
6440 ui.write(_('bookmarks:'), label='log.bookmark')
6445 if active is not None:
6441 if active is not None:
6446 if active in marks:
6442 if active in marks:
6447 ui.write(' *' + active, label=activebookmarklabel)
6443 ui.write(' *' + active, label=activebookmarklabel)
6448 marks.remove(active)
6444 marks.remove(active)
6449 else:
6445 else:
6450 ui.write(' [%s]' % active, label=activebookmarklabel)
6446 ui.write(' [%s]' % active, label=activebookmarklabel)
6451 for m in marks:
6447 for m in marks:
6452 ui.write(' ' + m, label='log.bookmark')
6448 ui.write(' ' + m, label='log.bookmark')
6453 ui.write('\n', label='log.bookmark')
6449 ui.write('\n', label='log.bookmark')
6454
6450
6455 status = repo.status(unknown=True)
6451 status = repo.status(unknown=True)
6456
6452
6457 c = repo.dirstate.copies()
6453 c = repo.dirstate.copies()
6458 copied, renamed = [], []
6454 copied, renamed = [], []
6459 for d, s in c.iteritems():
6455 for d, s in c.iteritems():
6460 if s in status.removed:
6456 if s in status.removed:
6461 status.removed.remove(s)
6457 status.removed.remove(s)
6462 renamed.append(d)
6458 renamed.append(d)
6463 else:
6459 else:
6464 copied.append(d)
6460 copied.append(d)
6465 if d in status.added:
6461 if d in status.added:
6466 status.added.remove(d)
6462 status.added.remove(d)
6467
6463
6468 try:
6464 try:
6469 ms = mergemod.mergestate.read(repo)
6465 ms = mergemod.mergestate.read(repo)
6470 except error.UnsupportedMergeRecords as e:
6466 except error.UnsupportedMergeRecords as e:
6471 s = ' '.join(e.recordtypes)
6467 s = ' '.join(e.recordtypes)
6472 ui.warn(
6468 ui.warn(
6473 _('warning: merge state has unsupported record types: %s\n') % s)
6469 _('warning: merge state has unsupported record types: %s\n') % s)
6474 unresolved = 0
6470 unresolved = 0
6475 else:
6471 else:
6476 unresolved = [f for f in ms if ms[f] == 'u']
6472 unresolved = [f for f in ms if ms[f] == 'u']
6477
6473
6478 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6474 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6479
6475
6480 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6476 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6481 (ui.label(_('%d added'), 'status.added'), status.added),
6477 (ui.label(_('%d added'), 'status.added'), status.added),
6482 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6478 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6483 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6479 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6484 (ui.label(_('%d copied'), 'status.copied'), copied),
6480 (ui.label(_('%d copied'), 'status.copied'), copied),
6485 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6481 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6486 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6482 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6487 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6483 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6488 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6484 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6489 t = []
6485 t = []
6490 for l, s in labels:
6486 for l, s in labels:
6491 if s:
6487 if s:
6492 t.append(l % len(s))
6488 t.append(l % len(s))
6493
6489
6494 t = ', '.join(t)
6490 t = ', '.join(t)
6495 cleanworkdir = False
6491 cleanworkdir = False
6496
6492
6497 if repo.vfs.exists('graftstate'):
6493 if repo.vfs.exists('graftstate'):
6498 t += _(' (graft in progress)')
6494 t += _(' (graft in progress)')
6499 if repo.vfs.exists('updatestate'):
6495 if repo.vfs.exists('updatestate'):
6500 t += _(' (interrupted update)')
6496 t += _(' (interrupted update)')
6501 elif len(parents) > 1:
6497 elif len(parents) > 1:
6502 t += _(' (merge)')
6498 t += _(' (merge)')
6503 elif branch != parents[0].branch():
6499 elif branch != parents[0].branch():
6504 t += _(' (new branch)')
6500 t += _(' (new branch)')
6505 elif (parents[0].closesbranch() and
6501 elif (parents[0].closesbranch() and
6506 pnode in repo.branchheads(branch, closed=True)):
6502 pnode in repo.branchheads(branch, closed=True)):
6507 t += _(' (head closed)')
6503 t += _(' (head closed)')
6508 elif not (status.modified or status.added or status.removed or renamed or
6504 elif not (status.modified or status.added or status.removed or renamed or
6509 copied or subs):
6505 copied or subs):
6510 t += _(' (clean)')
6506 t += _(' (clean)')
6511 cleanworkdir = True
6507 cleanworkdir = True
6512 elif pnode not in bheads:
6508 elif pnode not in bheads:
6513 t += _(' (new branch head)')
6509 t += _(' (new branch head)')
6514
6510
6515 if parents:
6511 if parents:
6516 pendingphase = max(p.phase() for p in parents)
6512 pendingphase = max(p.phase() for p in parents)
6517 else:
6513 else:
6518 pendingphase = phases.public
6514 pendingphase = phases.public
6519
6515
6520 if pendingphase > phases.newcommitphase(ui):
6516 if pendingphase > phases.newcommitphase(ui):
6521 t += ' (%s)' % phases.phasenames[pendingphase]
6517 t += ' (%s)' % phases.phasenames[pendingphase]
6522
6518
6523 if cleanworkdir:
6519 if cleanworkdir:
6524 # i18n: column positioning for "hg summary"
6520 # i18n: column positioning for "hg summary"
6525 ui.status(_('commit: %s\n') % t.strip())
6521 ui.status(_('commit: %s\n') % t.strip())
6526 else:
6522 else:
6527 # i18n: column positioning for "hg summary"
6523 # i18n: column positioning for "hg summary"
6528 ui.write(_('commit: %s\n') % t.strip())
6524 ui.write(_('commit: %s\n') % t.strip())
6529
6525
6530 # all ancestors of branch heads - all ancestors of parent = new csets
6526 # all ancestors of branch heads - all ancestors of parent = new csets
6531 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6527 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6532 bheads))
6528 bheads))
6533
6529
6534 if new == 0:
6530 if new == 0:
6535 # i18n: column positioning for "hg summary"
6531 # i18n: column positioning for "hg summary"
6536 ui.status(_('update: (current)\n'))
6532 ui.status(_('update: (current)\n'))
6537 elif pnode not in bheads:
6533 elif pnode not in bheads:
6538 # i18n: column positioning for "hg summary"
6534 # i18n: column positioning for "hg summary"
6539 ui.write(_('update: %d new changesets (update)\n') % new)
6535 ui.write(_('update: %d new changesets (update)\n') % new)
6540 else:
6536 else:
6541 # i18n: column positioning for "hg summary"
6537 # i18n: column positioning for "hg summary"
6542 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6538 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6543 (new, len(bheads)))
6539 (new, len(bheads)))
6544
6540
6545 t = []
6541 t = []
6546 draft = len(repo.revs('draft()'))
6542 draft = len(repo.revs('draft()'))
6547 if draft:
6543 if draft:
6548 t.append(_('%d draft') % draft)
6544 t.append(_('%d draft') % draft)
6549 secret = len(repo.revs('secret()'))
6545 secret = len(repo.revs('secret()'))
6550 if secret:
6546 if secret:
6551 t.append(_('%d secret') % secret)
6547 t.append(_('%d secret') % secret)
6552
6548
6553 if draft or secret:
6549 if draft or secret:
6554 ui.status(_('phases: %s\n') % ', '.join(t))
6550 ui.status(_('phases: %s\n') % ', '.join(t))
6555
6551
6556 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6552 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6557 for trouble in ("unstable", "divergent", "bumped"):
6553 for trouble in ("unstable", "divergent", "bumped"):
6558 numtrouble = len(repo.revs(trouble + "()"))
6554 numtrouble = len(repo.revs(trouble + "()"))
6559 # We write all the possibilities to ease translation
6555 # We write all the possibilities to ease translation
6560 troublemsg = {
6556 troublemsg = {
6561 "unstable": _("unstable: %d changesets"),
6557 "unstable": _("unstable: %d changesets"),
6562 "divergent": _("divergent: %d changesets"),
6558 "divergent": _("divergent: %d changesets"),
6563 "bumped": _("bumped: %d changesets"),
6559 "bumped": _("bumped: %d changesets"),
6564 }
6560 }
6565 if numtrouble > 0:
6561 if numtrouble > 0:
6566 ui.status(troublemsg[trouble] % numtrouble + "\n")
6562 ui.status(troublemsg[trouble] % numtrouble + "\n")
6567
6563
6568 cmdutil.summaryhooks(ui, repo)
6564 cmdutil.summaryhooks(ui, repo)
6569
6565
6570 if opts.get('remote'):
6566 if opts.get('remote'):
6571 needsincoming, needsoutgoing = True, True
6567 needsincoming, needsoutgoing = True, True
6572 else:
6568 else:
6573 needsincoming, needsoutgoing = False, False
6569 needsincoming, needsoutgoing = False, False
6574 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6570 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6575 if i:
6571 if i:
6576 needsincoming = True
6572 needsincoming = True
6577 if o:
6573 if o:
6578 needsoutgoing = True
6574 needsoutgoing = True
6579 if not needsincoming and not needsoutgoing:
6575 if not needsincoming and not needsoutgoing:
6580 return
6576 return
6581
6577
6582 def getincoming():
6578 def getincoming():
6583 source, branches = hg.parseurl(ui.expandpath('default'))
6579 source, branches = hg.parseurl(ui.expandpath('default'))
6584 sbranch = branches[0]
6580 sbranch = branches[0]
6585 try:
6581 try:
6586 other = hg.peer(repo, {}, source)
6582 other = hg.peer(repo, {}, source)
6587 except error.RepoError:
6583 except error.RepoError:
6588 if opts.get('remote'):
6584 if opts.get('remote'):
6589 raise
6585 raise
6590 return source, sbranch, None, None, None
6586 return source, sbranch, None, None, None
6591 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6587 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6592 if revs:
6588 if revs:
6593 revs = [other.lookup(rev) for rev in revs]
6589 revs = [other.lookup(rev) for rev in revs]
6594 ui.debug('comparing with %s\n' % util.hidepassword(source))
6590 ui.debug('comparing with %s\n' % util.hidepassword(source))
6595 repo.ui.pushbuffer()
6591 repo.ui.pushbuffer()
6596 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6592 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6597 repo.ui.popbuffer()
6593 repo.ui.popbuffer()
6598 return source, sbranch, other, commoninc, commoninc[1]
6594 return source, sbranch, other, commoninc, commoninc[1]
6599
6595
6600 if needsincoming:
6596 if needsincoming:
6601 source, sbranch, sother, commoninc, incoming = getincoming()
6597 source, sbranch, sother, commoninc, incoming = getincoming()
6602 else:
6598 else:
6603 source = sbranch = sother = commoninc = incoming = None
6599 source = sbranch = sother = commoninc = incoming = None
6604
6600
6605 def getoutgoing():
6601 def getoutgoing():
6606 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6602 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6607 dbranch = branches[0]
6603 dbranch = branches[0]
6608 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6604 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6609 if source != dest:
6605 if source != dest:
6610 try:
6606 try:
6611 dother = hg.peer(repo, {}, dest)
6607 dother = hg.peer(repo, {}, dest)
6612 except error.RepoError:
6608 except error.RepoError:
6613 if opts.get('remote'):
6609 if opts.get('remote'):
6614 raise
6610 raise
6615 return dest, dbranch, None, None
6611 return dest, dbranch, None, None
6616 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6612 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6617 elif sother is None:
6613 elif sother is None:
6618 # there is no explicit destination peer, but source one is invalid
6614 # there is no explicit destination peer, but source one is invalid
6619 return dest, dbranch, None, None
6615 return dest, dbranch, None, None
6620 else:
6616 else:
6621 dother = sother
6617 dother = sother
6622 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6618 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6623 common = None
6619 common = None
6624 else:
6620 else:
6625 common = commoninc
6621 common = commoninc
6626 if revs:
6622 if revs:
6627 revs = [repo.lookup(rev) for rev in revs]
6623 revs = [repo.lookup(rev) for rev in revs]
6628 repo.ui.pushbuffer()
6624 repo.ui.pushbuffer()
6629 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6625 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6630 commoninc=common)
6626 commoninc=common)
6631 repo.ui.popbuffer()
6627 repo.ui.popbuffer()
6632 return dest, dbranch, dother, outgoing
6628 return dest, dbranch, dother, outgoing
6633
6629
6634 if needsoutgoing:
6630 if needsoutgoing:
6635 dest, dbranch, dother, outgoing = getoutgoing()
6631 dest, dbranch, dother, outgoing = getoutgoing()
6636 else:
6632 else:
6637 dest = dbranch = dother = outgoing = None
6633 dest = dbranch = dother = outgoing = None
6638
6634
6639 if opts.get('remote'):
6635 if opts.get('remote'):
6640 t = []
6636 t = []
6641 if incoming:
6637 if incoming:
6642 t.append(_('1 or more incoming'))
6638 t.append(_('1 or more incoming'))
6643 o = outgoing.missing
6639 o = outgoing.missing
6644 if o:
6640 if o:
6645 t.append(_('%d outgoing') % len(o))
6641 t.append(_('%d outgoing') % len(o))
6646 other = dother or sother
6642 other = dother or sother
6647 if 'bookmarks' in other.listkeys('namespaces'):
6643 if 'bookmarks' in other.listkeys('namespaces'):
6648 counts = bookmarks.summary(repo, other)
6644 counts = bookmarks.summary(repo, other)
6649 if counts[0] > 0:
6645 if counts[0] > 0:
6650 t.append(_('%d incoming bookmarks') % counts[0])
6646 t.append(_('%d incoming bookmarks') % counts[0])
6651 if counts[1] > 0:
6647 if counts[1] > 0:
6652 t.append(_('%d outgoing bookmarks') % counts[1])
6648 t.append(_('%d outgoing bookmarks') % counts[1])
6653
6649
6654 if t:
6650 if t:
6655 # i18n: column positioning for "hg summary"
6651 # i18n: column positioning for "hg summary"
6656 ui.write(_('remote: %s\n') % (', '.join(t)))
6652 ui.write(_('remote: %s\n') % (', '.join(t)))
6657 else:
6653 else:
6658 # i18n: column positioning for "hg summary"
6654 # i18n: column positioning for "hg summary"
6659 ui.status(_('remote: (synced)\n'))
6655 ui.status(_('remote: (synced)\n'))
6660
6656
6661 cmdutil.summaryremotehooks(ui, repo, opts,
6657 cmdutil.summaryremotehooks(ui, repo, opts,
6662 ((source, sbranch, sother, commoninc),
6658 ((source, sbranch, sother, commoninc),
6663 (dest, dbranch, dother, outgoing)))
6659 (dest, dbranch, dother, outgoing)))
6664
6660
6665 @command('tag',
6661 @command('tag',
6666 [('f', 'force', None, _('force tag')),
6662 [('f', 'force', None, _('force tag')),
6667 ('l', 'local', None, _('make the tag local')),
6663 ('l', 'local', None, _('make the tag local')),
6668 ('r', 'rev', '', _('revision to tag'), _('REV')),
6664 ('r', 'rev', '', _('revision to tag'), _('REV')),
6669 ('', 'remove', None, _('remove a tag')),
6665 ('', 'remove', None, _('remove a tag')),
6670 # -l/--local is already there, commitopts cannot be used
6666 # -l/--local is already there, commitopts cannot be used
6671 ('e', 'edit', None, _('invoke editor on commit messages')),
6667 ('e', 'edit', None, _('invoke editor on commit messages')),
6672 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6668 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6673 ] + commitopts2,
6669 ] + commitopts2,
6674 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6670 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6675 def tag(ui, repo, name1, *names, **opts):
6671 def tag(ui, repo, name1, *names, **opts):
6676 """add one or more tags for the current or given revision
6672 """add one or more tags for the current or given revision
6677
6673
6678 Name a particular revision using <name>.
6674 Name a particular revision using <name>.
6679
6675
6680 Tags are used to name particular revisions of the repository and are
6676 Tags are used to name particular revisions of the repository and are
6681 very useful to compare different revisions, to go back to significant
6677 very useful to compare different revisions, to go back to significant
6682 earlier versions or to mark branch points as releases, etc. Changing
6678 earlier versions or to mark branch points as releases, etc. Changing
6683 an existing tag is normally disallowed; use -f/--force to override.
6679 an existing tag is normally disallowed; use -f/--force to override.
6684
6680
6685 If no revision is given, the parent of the working directory is
6681 If no revision is given, the parent of the working directory is
6686 used.
6682 used.
6687
6683
6688 To facilitate version control, distribution, and merging of tags,
6684 To facilitate version control, distribution, and merging of tags,
6689 they are stored as a file named ".hgtags" which is managed similarly
6685 they are stored as a file named ".hgtags" which is managed similarly
6690 to other project files and can be hand-edited if necessary. This
6686 to other project files and can be hand-edited if necessary. This
6691 also means that tagging creates a new commit. The file
6687 also means that tagging creates a new commit. The file
6692 ".hg/localtags" is used for local tags (not shared among
6688 ".hg/localtags" is used for local tags (not shared among
6693 repositories).
6689 repositories).
6694
6690
6695 Tag commits are usually made at the head of a branch. If the parent
6691 Tag commits are usually made at the head of a branch. If the parent
6696 of the working directory is not a branch head, :hg:`tag` aborts; use
6692 of the working directory is not a branch head, :hg:`tag` aborts; use
6697 -f/--force to force the tag commit to be based on a non-head
6693 -f/--force to force the tag commit to be based on a non-head
6698 changeset.
6694 changeset.
6699
6695
6700 See :hg:`help dates` for a list of formats valid for -d/--date.
6696 See :hg:`help dates` for a list of formats valid for -d/--date.
6701
6697
6702 Since tag names have priority over branch names during revision
6698 Since tag names have priority over branch names during revision
6703 lookup, using an existing branch name as a tag name is discouraged.
6699 lookup, using an existing branch name as a tag name is discouraged.
6704
6700
6705 Returns 0 on success.
6701 Returns 0 on success.
6706 """
6702 """
6707 wlock = lock = None
6703 wlock = lock = None
6708 try:
6704 try:
6709 wlock = repo.wlock()
6705 wlock = repo.wlock()
6710 lock = repo.lock()
6706 lock = repo.lock()
6711 rev_ = "."
6707 rev_ = "."
6712 names = [t.strip() for t in (name1,) + names]
6708 names = [t.strip() for t in (name1,) + names]
6713 if len(names) != len(set(names)):
6709 if len(names) != len(set(names)):
6714 raise error.Abort(_('tag names must be unique'))
6710 raise error.Abort(_('tag names must be unique'))
6715 for n in names:
6711 for n in names:
6716 scmutil.checknewlabel(repo, n, 'tag')
6712 scmutil.checknewlabel(repo, n, 'tag')
6717 if not n:
6713 if not n:
6718 raise error.Abort(_('tag names cannot consist entirely of '
6714 raise error.Abort(_('tag names cannot consist entirely of '
6719 'whitespace'))
6715 'whitespace'))
6720 if opts.get('rev') and opts.get('remove'):
6716 if opts.get('rev') and opts.get('remove'):
6721 raise error.Abort(_("--rev and --remove are incompatible"))
6717 raise error.Abort(_("--rev and --remove are incompatible"))
6722 if opts.get('rev'):
6718 if opts.get('rev'):
6723 rev_ = opts['rev']
6719 rev_ = opts['rev']
6724 message = opts.get('message')
6720 message = opts.get('message')
6725 if opts.get('remove'):
6721 if opts.get('remove'):
6726 if opts.get('local'):
6722 if opts.get('local'):
6727 expectedtype = 'local'
6723 expectedtype = 'local'
6728 else:
6724 else:
6729 expectedtype = 'global'
6725 expectedtype = 'global'
6730
6726
6731 for n in names:
6727 for n in names:
6732 if not repo.tagtype(n):
6728 if not repo.tagtype(n):
6733 raise error.Abort(_("tag '%s' does not exist") % n)
6729 raise error.Abort(_("tag '%s' does not exist") % n)
6734 if repo.tagtype(n) != expectedtype:
6730 if repo.tagtype(n) != expectedtype:
6735 if expectedtype == 'global':
6731 if expectedtype == 'global':
6736 raise error.Abort(_("tag '%s' is not a global tag") % n)
6732 raise error.Abort(_("tag '%s' is not a global tag") % n)
6737 else:
6733 else:
6738 raise error.Abort(_("tag '%s' is not a local tag") % n)
6734 raise error.Abort(_("tag '%s' is not a local tag") % n)
6739 rev_ = 'null'
6735 rev_ = 'null'
6740 if not message:
6736 if not message:
6741 # we don't translate commit messages
6737 # we don't translate commit messages
6742 message = 'Removed tag %s' % ', '.join(names)
6738 message = 'Removed tag %s' % ', '.join(names)
6743 elif not opts.get('force'):
6739 elif not opts.get('force'):
6744 for n in names:
6740 for n in names:
6745 if n in repo.tags():
6741 if n in repo.tags():
6746 raise error.Abort(_("tag '%s' already exists "
6742 raise error.Abort(_("tag '%s' already exists "
6747 "(use -f to force)") % n)
6743 "(use -f to force)") % n)
6748 if not opts.get('local'):
6744 if not opts.get('local'):
6749 p1, p2 = repo.dirstate.parents()
6745 p1, p2 = repo.dirstate.parents()
6750 if p2 != nullid:
6746 if p2 != nullid:
6751 raise error.Abort(_('uncommitted merge'))
6747 raise error.Abort(_('uncommitted merge'))
6752 bheads = repo.branchheads()
6748 bheads = repo.branchheads()
6753 if not opts.get('force') and bheads and p1 not in bheads:
6749 if not opts.get('force') and bheads and p1 not in bheads:
6754 raise error.Abort(_('not at a branch head (use -f to force)'))
6750 raise error.Abort(_('not at a branch head (use -f to force)'))
6755 r = scmutil.revsingle(repo, rev_).node()
6751 r = scmutil.revsingle(repo, rev_).node()
6756
6752
6757 if not message:
6753 if not message:
6758 # we don't translate commit messages
6754 # we don't translate commit messages
6759 message = ('Added tag %s for changeset %s' %
6755 message = ('Added tag %s for changeset %s' %
6760 (', '.join(names), short(r)))
6756 (', '.join(names), short(r)))
6761
6757
6762 date = opts.get('date')
6758 date = opts.get('date')
6763 if date:
6759 if date:
6764 date = util.parsedate(date)
6760 date = util.parsedate(date)
6765
6761
6766 if opts.get('remove'):
6762 if opts.get('remove'):
6767 editform = 'tag.remove'
6763 editform = 'tag.remove'
6768 else:
6764 else:
6769 editform = 'tag.add'
6765 editform = 'tag.add'
6770 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6766 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6771
6767
6772 # don't allow tagging the null rev
6768 # don't allow tagging the null rev
6773 if (not opts.get('remove') and
6769 if (not opts.get('remove') and
6774 scmutil.revsingle(repo, rev_).rev() == nullrev):
6770 scmutil.revsingle(repo, rev_).rev() == nullrev):
6775 raise error.Abort(_("cannot tag null revision"))
6771 raise error.Abort(_("cannot tag null revision"))
6776
6772
6777 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6773 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6778 editor=editor)
6774 editor=editor)
6779 finally:
6775 finally:
6780 release(lock, wlock)
6776 release(lock, wlock)
6781
6777
6782 @command('tags', formatteropts, '')
6778 @command('tags', formatteropts, '')
6783 def tags(ui, repo, **opts):
6779 def tags(ui, repo, **opts):
6784 """list repository tags
6780 """list repository tags
6785
6781
6786 This lists both regular and local tags. When the -v/--verbose
6782 This lists both regular and local tags. When the -v/--verbose
6787 switch is used, a third column "local" is printed for local tags.
6783 switch is used, a third column "local" is printed for local tags.
6788 When the -q/--quiet switch is used, only the tag name is printed.
6784 When the -q/--quiet switch is used, only the tag name is printed.
6789
6785
6790 Returns 0 on success.
6786 Returns 0 on success.
6791 """
6787 """
6792
6788
6793 fm = ui.formatter('tags', opts)
6789 fm = ui.formatter('tags', opts)
6794 hexfunc = fm.hexfunc
6790 hexfunc = fm.hexfunc
6795 tagtype = ""
6791 tagtype = ""
6796
6792
6797 for t, n in reversed(repo.tagslist()):
6793 for t, n in reversed(repo.tagslist()):
6798 hn = hexfunc(n)
6794 hn = hexfunc(n)
6799 label = 'tags.normal'
6795 label = 'tags.normal'
6800 tagtype = ''
6796 tagtype = ''
6801 if repo.tagtype(t) == 'local':
6797 if repo.tagtype(t) == 'local':
6802 label = 'tags.local'
6798 label = 'tags.local'
6803 tagtype = 'local'
6799 tagtype = 'local'
6804
6800
6805 fm.startitem()
6801 fm.startitem()
6806 fm.write('tag', '%s', t, label=label)
6802 fm.write('tag', '%s', t, label=label)
6807 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6803 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6808 fm.condwrite(not ui.quiet, 'rev node', fmt,
6804 fm.condwrite(not ui.quiet, 'rev node', fmt,
6809 repo.changelog.rev(n), hn, label=label)
6805 repo.changelog.rev(n), hn, label=label)
6810 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6806 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6811 tagtype, label=label)
6807 tagtype, label=label)
6812 fm.plain('\n')
6808 fm.plain('\n')
6813 fm.end()
6809 fm.end()
6814
6810
6815 @command('tip',
6811 @command('tip',
6816 [('p', 'patch', None, _('show patch')),
6812 [('p', 'patch', None, _('show patch')),
6817 ('g', 'git', None, _('use git extended diff format')),
6813 ('g', 'git', None, _('use git extended diff format')),
6818 ] + templateopts,
6814 ] + templateopts,
6819 _('[-p] [-g]'))
6815 _('[-p] [-g]'))
6820 def tip(ui, repo, **opts):
6816 def tip(ui, repo, **opts):
6821 """show the tip revision (DEPRECATED)
6817 """show the tip revision (DEPRECATED)
6822
6818
6823 The tip revision (usually just called the tip) is the changeset
6819 The tip revision (usually just called the tip) is the changeset
6824 most recently added to the repository (and therefore the most
6820 most recently added to the repository (and therefore the most
6825 recently changed head).
6821 recently changed head).
6826
6822
6827 If you have just made a commit, that commit will be the tip. If
6823 If you have just made a commit, that commit will be the tip. If
6828 you have just pulled changes from another repository, the tip of
6824 you have just pulled changes from another repository, the tip of
6829 that repository becomes the current tip. The "tip" tag is special
6825 that repository becomes the current tip. The "tip" tag is special
6830 and cannot be renamed or assigned to a different changeset.
6826 and cannot be renamed or assigned to a different changeset.
6831
6827
6832 This command is deprecated, please use :hg:`heads` instead.
6828 This command is deprecated, please use :hg:`heads` instead.
6833
6829
6834 Returns 0 on success.
6830 Returns 0 on success.
6835 """
6831 """
6836 displayer = cmdutil.show_changeset(ui, repo, opts)
6832 displayer = cmdutil.show_changeset(ui, repo, opts)
6837 displayer.show(repo['tip'])
6833 displayer.show(repo['tip'])
6838 displayer.close()
6834 displayer.close()
6839
6835
6840 @command('unbundle',
6836 @command('unbundle',
6841 [('u', 'update', None,
6837 [('u', 'update', None,
6842 _('update to new branch head if changesets were unbundled'))],
6838 _('update to new branch head if changesets were unbundled'))],
6843 _('[-u] FILE...'))
6839 _('[-u] FILE...'))
6844 def unbundle(ui, repo, fname1, *fnames, **opts):
6840 def unbundle(ui, repo, fname1, *fnames, **opts):
6845 """apply one or more changegroup files
6841 """apply one or more changegroup files
6846
6842
6847 Apply one or more compressed changegroup files generated by the
6843 Apply one or more compressed changegroup files generated by the
6848 bundle command.
6844 bundle command.
6849
6845
6850 Returns 0 on success, 1 if an update has unresolved files.
6846 Returns 0 on success, 1 if an update has unresolved files.
6851 """
6847 """
6852 fnames = (fname1,) + fnames
6848 fnames = (fname1,) + fnames
6853
6849
6854 lock = repo.lock()
6850 lock = repo.lock()
6855 try:
6851 try:
6856 for fname in fnames:
6852 for fname in fnames:
6857 f = hg.openpath(ui, fname)
6853 f = hg.openpath(ui, fname)
6858 gen = exchange.readbundle(ui, f, fname)
6854 gen = exchange.readbundle(ui, f, fname)
6859 if isinstance(gen, bundle2.unbundle20):
6855 if isinstance(gen, bundle2.unbundle20):
6860 tr = repo.transaction('unbundle')
6856 tr = repo.transaction('unbundle')
6861 try:
6857 try:
6862 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6858 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6863 url='bundle:' + fname)
6859 url='bundle:' + fname)
6864 tr.close()
6860 tr.close()
6865 except error.BundleUnknownFeatureError as exc:
6861 except error.BundleUnknownFeatureError as exc:
6866 raise error.Abort(_('%s: unknown bundle feature, %s')
6862 raise error.Abort(_('%s: unknown bundle feature, %s')
6867 % (fname, exc),
6863 % (fname, exc),
6868 hint=_("see https://mercurial-scm.org/"
6864 hint=_("see https://mercurial-scm.org/"
6869 "wiki/BundleFeature for more "
6865 "wiki/BundleFeature for more "
6870 "information"))
6866 "information"))
6871 finally:
6867 finally:
6872 if tr:
6868 if tr:
6873 tr.release()
6869 tr.release()
6874 changes = [r.get('return', 0)
6870 changes = [r.get('return', 0)
6875 for r in op.records['changegroup']]
6871 for r in op.records['changegroup']]
6876 modheads = changegroup.combineresults(changes)
6872 modheads = changegroup.combineresults(changes)
6877 elif isinstance(gen, streamclone.streamcloneapplier):
6873 elif isinstance(gen, streamclone.streamcloneapplier):
6878 raise error.Abort(
6874 raise error.Abort(
6879 _('packed bundles cannot be applied with '
6875 _('packed bundles cannot be applied with '
6880 '"hg unbundle"'),
6876 '"hg unbundle"'),
6881 hint=_('use "hg debugapplystreamclonebundle"'))
6877 hint=_('use "hg debugapplystreamclonebundle"'))
6882 else:
6878 else:
6883 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6879 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6884 finally:
6880 finally:
6885 lock.release()
6881 lock.release()
6886
6882
6887 return postincoming(ui, repo, modheads, opts.get('update'), None)
6883 return postincoming(ui, repo, modheads, opts.get('update'), None)
6888
6884
6889 @command('^update|up|checkout|co',
6885 @command('^update|up|checkout|co',
6890 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6886 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6891 ('c', 'check', None,
6887 ('c', 'check', None,
6892 _('update across branches if no uncommitted changes')),
6888 _('update across branches if no uncommitted changes')),
6893 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6889 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6894 ('r', 'rev', '', _('revision'), _('REV'))
6890 ('r', 'rev', '', _('revision'), _('REV'))
6895 ] + mergetoolopts,
6891 ] + mergetoolopts,
6896 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6892 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6897 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6893 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6898 tool=None):
6894 tool=None):
6899 """update working directory (or switch revisions)
6895 """update working directory (or switch revisions)
6900
6896
6901 Update the repository's working directory to the specified
6897 Update the repository's working directory to the specified
6902 changeset. If no changeset is specified, update to the tip of the
6898 changeset. If no changeset is specified, update to the tip of the
6903 current named branch and move the active bookmark (see :hg:`help
6899 current named branch and move the active bookmark (see :hg:`help
6904 bookmarks`).
6900 bookmarks`).
6905
6901
6906 Update sets the working directory's parent revision to the specified
6902 Update sets the working directory's parent revision to the specified
6907 changeset (see :hg:`help parents`).
6903 changeset (see :hg:`help parents`).
6908
6904
6909 If the changeset is not a descendant or ancestor of the working
6905 If the changeset is not a descendant or ancestor of the working
6910 directory's parent, the update is aborted. With the -c/--check
6906 directory's parent, the update is aborted. With the -c/--check
6911 option, the working directory is checked for uncommitted changes; if
6907 option, the working directory is checked for uncommitted changes; if
6912 none are found, the working directory is updated to the specified
6908 none are found, the working directory is updated to the specified
6913 changeset.
6909 changeset.
6914
6910
6915 .. container:: verbose
6911 .. container:: verbose
6916
6912
6917 The following rules apply when the working directory contains
6913 The following rules apply when the working directory contains
6918 uncommitted changes:
6914 uncommitted changes:
6919
6915
6920 1. If neither -c/--check nor -C/--clean is specified, and if
6916 1. If neither -c/--check nor -C/--clean is specified, and if
6921 the requested changeset is an ancestor or descendant of
6917 the requested changeset is an ancestor or descendant of
6922 the working directory's parent, the uncommitted changes
6918 the working directory's parent, the uncommitted changes
6923 are merged into the requested changeset and the merged
6919 are merged into the requested changeset and the merged
6924 result is left uncommitted. If the requested changeset is
6920 result is left uncommitted. If the requested changeset is
6925 not an ancestor or descendant (that is, it is on another
6921 not an ancestor or descendant (that is, it is on another
6926 branch), the update is aborted and the uncommitted changes
6922 branch), the update is aborted and the uncommitted changes
6927 are preserved.
6923 are preserved.
6928
6924
6929 2. With the -c/--check option, the update is aborted and the
6925 2. With the -c/--check option, the update is aborted and the
6930 uncommitted changes are preserved.
6926 uncommitted changes are preserved.
6931
6927
6932 3. With the -C/--clean option, uncommitted changes are discarded and
6928 3. With the -C/--clean option, uncommitted changes are discarded and
6933 the working directory is updated to the requested changeset.
6929 the working directory is updated to the requested changeset.
6934
6930
6935 To cancel an uncommitted merge (and lose your changes), use
6931 To cancel an uncommitted merge (and lose your changes), use
6936 :hg:`update --clean .`.
6932 :hg:`update --clean .`.
6937
6933
6938 Use null as the changeset to remove the working directory (like
6934 Use null as the changeset to remove the working directory (like
6939 :hg:`clone -U`).
6935 :hg:`clone -U`).
6940
6936
6941 If you want to revert just one file to an older revision, use
6937 If you want to revert just one file to an older revision, use
6942 :hg:`revert [-r REV] NAME`.
6938 :hg:`revert [-r REV] NAME`.
6943
6939
6944 See :hg:`help dates` for a list of formats valid for -d/--date.
6940 See :hg:`help dates` for a list of formats valid for -d/--date.
6945
6941
6946 Returns 0 on success, 1 if there are unresolved files.
6942 Returns 0 on success, 1 if there are unresolved files.
6947 """
6943 """
6948 movemarkfrom = None
6944 movemarkfrom = None
6949 if rev and node:
6945 if rev and node:
6950 raise error.Abort(_("please specify just one revision"))
6946 raise error.Abort(_("please specify just one revision"))
6951
6947
6952 if rev is None or rev == '':
6948 if rev is None or rev == '':
6953 rev = node
6949 rev = node
6954
6950
6955 wlock = repo.wlock()
6951 wlock = repo.wlock()
6956 try:
6952 try:
6957 cmdutil.clearunfinished(repo)
6953 cmdutil.clearunfinished(repo)
6958
6954
6959 if date:
6955 if date:
6960 if rev is not None:
6956 if rev is not None:
6961 raise error.Abort(_("you can't specify a revision and a date"))
6957 raise error.Abort(_("you can't specify a revision and a date"))
6962 rev = cmdutil.finddate(ui, repo, date)
6958 rev = cmdutil.finddate(ui, repo, date)
6963
6959
6964 # if we defined a bookmark, we have to remember the original name
6960 # if we defined a bookmark, we have to remember the original name
6965 brev = rev
6961 brev = rev
6966 rev = scmutil.revsingle(repo, rev, rev).rev()
6962 rev = scmutil.revsingle(repo, rev, rev).rev()
6967
6963
6968 if check and clean:
6964 if check and clean:
6969 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6965 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6970 )
6966 )
6971
6967
6972 if check:
6968 if check:
6973 cmdutil.bailifchanged(repo, merge=False)
6969 cmdutil.bailifchanged(repo, merge=False)
6974 if rev is None:
6970 if rev is None:
6975 updata = destutil.destupdate(repo, clean=clean, check=check)
6971 updata = destutil.destupdate(repo, clean=clean, check=check)
6976 rev, movemarkfrom, brev = updata
6972 rev, movemarkfrom, brev = updata
6977
6973
6978 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6974 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6979
6975
6980 if clean:
6976 if clean:
6981 ret = hg.clean(repo, rev)
6977 ret = hg.clean(repo, rev)
6982 else:
6978 else:
6983 ret = hg.update(repo, rev)
6979 ret = hg.update(repo, rev)
6984
6980
6985 if not ret and movemarkfrom:
6981 if not ret and movemarkfrom:
6986 if movemarkfrom == repo['.'].node():
6982 if movemarkfrom == repo['.'].node():
6987 pass # no-op update
6983 pass # no-op update
6988 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6984 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6989 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6985 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6990 else:
6986 else:
6991 # this can happen with a non-linear update
6987 # this can happen with a non-linear update
6992 ui.status(_("(leaving bookmark %s)\n") %
6988 ui.status(_("(leaving bookmark %s)\n") %
6993 repo._activebookmark)
6989 repo._activebookmark)
6994 bookmarks.deactivate(repo)
6990 bookmarks.deactivate(repo)
6995 elif brev in repo._bookmarks:
6991 elif brev in repo._bookmarks:
6996 bookmarks.activate(repo, brev)
6992 bookmarks.activate(repo, brev)
6997 ui.status(_("(activating bookmark %s)\n") % brev)
6993 ui.status(_("(activating bookmark %s)\n") % brev)
6998 elif brev:
6994 elif brev:
6999 if repo._activebookmark:
6995 if repo._activebookmark:
7000 ui.status(_("(leaving bookmark %s)\n") %
6996 ui.status(_("(leaving bookmark %s)\n") %
7001 repo._activebookmark)
6997 repo._activebookmark)
7002 bookmarks.deactivate(repo)
6998 bookmarks.deactivate(repo)
7003 finally:
6999 finally:
7004 wlock.release()
7000 wlock.release()
7005
7001
7006 return ret
7002 return ret
7007
7003
7008 @command('verify', [])
7004 @command('verify', [])
7009 def verify(ui, repo):
7005 def verify(ui, repo):
7010 """verify the integrity of the repository
7006 """verify the integrity of the repository
7011
7007
7012 Verify the integrity of the current repository.
7008 Verify the integrity of the current repository.
7013
7009
7014 This will perform an extensive check of the repository's
7010 This will perform an extensive check of the repository's
7015 integrity, validating the hashes and checksums of each entry in
7011 integrity, validating the hashes and checksums of each entry in
7016 the changelog, manifest, and tracked files, as well as the
7012 the changelog, manifest, and tracked files, as well as the
7017 integrity of their crosslinks and indices.
7013 integrity of their crosslinks and indices.
7018
7014
7019 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7015 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7020 for more information about recovery from corruption of the
7016 for more information about recovery from corruption of the
7021 repository.
7017 repository.
7022
7018
7023 Returns 0 on success, 1 if errors are encountered.
7019 Returns 0 on success, 1 if errors are encountered.
7024 """
7020 """
7025 return hg.verify(repo)
7021 return hg.verify(repo)
7026
7022
7027 @command('version', [], norepo=True)
7023 @command('version', [], norepo=True)
7028 def version_(ui):
7024 def version_(ui):
7029 """output version and copyright information"""
7025 """output version and copyright information"""
7030 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7026 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7031 % util.version())
7027 % util.version())
7032 ui.status(_(
7028 ui.status(_(
7033 "(see https://mercurial-scm.org for more information)\n"
7029 "(see https://mercurial-scm.org for more information)\n"
7034 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7030 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7035 "This is free software; see the source for copying conditions. "
7031 "This is free software; see the source for copying conditions. "
7036 "There is NO\nwarranty; "
7032 "There is NO\nwarranty; "
7037 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7033 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7038 ))
7034 ))
7039
7035
7040 ui.note(_("\nEnabled extensions:\n\n"))
7036 ui.note(_("\nEnabled extensions:\n\n"))
7041 if ui.verbose:
7037 if ui.verbose:
7042 # format names and versions into columns
7038 # format names and versions into columns
7043 names = []
7039 names = []
7044 vers = []
7040 vers = []
7045 for name, module in extensions.extensions():
7041 for name, module in extensions.extensions():
7046 names.append(name)
7042 names.append(name)
7047 vers.append(extensions.moduleversion(module))
7043 vers.append(extensions.moduleversion(module))
7048 if names:
7044 if names:
7049 maxnamelen = max(len(n) for n in names)
7045 maxnamelen = max(len(n) for n in names)
7050 for i, name in enumerate(names):
7046 for i, name in enumerate(names):
7051 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7047 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now