##// END OF EJS Templates
backout: disable --merge with --no-commit (issue4874)...
Yuya Nishihara -
r27954:9960b636 stable
parent child Browse files
Show More
@@ -1,7040 +1,7042 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullhex, nullid, nullrev, short
8 from node import hex, bin, nullhex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb
16 import sshserver, hgweb
17 import extensions
17 import extensions
18 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod, copies
20 import dagparser, context, simplemerge, graphmod, copies
21 import random, operator
21 import random, operator
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 import ui as uimod
24 import ui as uimod
25 import streamclone
25 import streamclone
26 import commandserver
26 import commandserver
27
27
28 table = {}
28 table = {}
29
29
30 command = cmdutil.command(table)
30 command = cmdutil.command(table)
31
31
32 # Space delimited list of commands that don't require local repositories.
32 # Space delimited list of commands that don't require local repositories.
33 # This should be populated by passing norepo=True into the @command decorator.
33 # This should be populated by passing norepo=True into the @command decorator.
34 norepo = ''
34 norepo = ''
35 # Space delimited list of commands that optionally require local repositories.
35 # Space delimited list of commands that optionally require local repositories.
36 # This should be populated by passing optionalrepo=True into the @command
36 # This should be populated by passing optionalrepo=True into the @command
37 # decorator.
37 # decorator.
38 optionalrepo = ''
38 optionalrepo = ''
39 # Space delimited list of commands that will examine arguments looking for
39 # Space delimited list of commands that will examine arguments looking for
40 # a repository. This should be populated by passing inferrepo=True into the
40 # a repository. This should be populated by passing inferrepo=True into the
41 # @command decorator.
41 # @command decorator.
42 inferrepo = ''
42 inferrepo = ''
43
43
44 # label constants
44 # label constants
45 # until 3.5, bookmarks.current was the advertised name, not
45 # until 3.5, bookmarks.current was the advertised name, not
46 # bookmarks.active, so we must use both to avoid breaking old
46 # bookmarks.active, so we must use both to avoid breaking old
47 # custom styles
47 # custom styles
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
49
49
50 # common command options
50 # common command options
51
51
52 globalopts = [
52 globalopts = [
53 ('R', 'repository', '',
53 ('R', 'repository', '',
54 _('repository root directory or name of overlay bundle file'),
54 _('repository root directory or name of overlay bundle file'),
55 _('REPO')),
55 _('REPO')),
56 ('', 'cwd', '',
56 ('', 'cwd', '',
57 _('change working directory'), _('DIR')),
57 _('change working directory'), _('DIR')),
58 ('y', 'noninteractive', None,
58 ('y', 'noninteractive', None,
59 _('do not prompt, automatically pick the first choice for all prompts')),
59 _('do not prompt, automatically pick the first choice for all prompts')),
60 ('q', 'quiet', None, _('suppress output')),
60 ('q', 'quiet', None, _('suppress output')),
61 ('v', 'verbose', None, _('enable additional output')),
61 ('v', 'verbose', None, _('enable additional output')),
62 ('', 'config', [],
62 ('', 'config', [],
63 _('set/override config option (use \'section.name=value\')'),
63 _('set/override config option (use \'section.name=value\')'),
64 _('CONFIG')),
64 _('CONFIG')),
65 ('', 'debug', None, _('enable debugging output')),
65 ('', 'debug', None, _('enable debugging output')),
66 ('', 'debugger', None, _('start debugger')),
66 ('', 'debugger', None, _('start debugger')),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
68 _('ENCODE')),
68 _('ENCODE')),
69 ('', 'encodingmode', encoding.encodingmode,
69 ('', 'encodingmode', encoding.encodingmode,
70 _('set the charset encoding mode'), _('MODE')),
70 _('set the charset encoding mode'), _('MODE')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
72 ('', 'time', None, _('time how long the command takes')),
72 ('', 'time', None, _('time how long the command takes')),
73 ('', 'profile', None, _('print command execution profile')),
73 ('', 'profile', None, _('print command execution profile')),
74 ('', 'version', None, _('output version information and exit')),
74 ('', 'version', None, _('output version information and exit')),
75 ('h', 'help', None, _('display help and exit')),
75 ('h', 'help', None, _('display help and exit')),
76 ('', 'hidden', False, _('consider hidden changesets')),
76 ('', 'hidden', False, _('consider hidden changesets')),
77 ]
77 ]
78
78
79 dryrunopts = [('n', 'dry-run', None,
79 dryrunopts = [('n', 'dry-run', None,
80 _('do not perform actions, just print output'))]
80 _('do not perform actions, just print output'))]
81
81
82 remoteopts = [
82 remoteopts = [
83 ('e', 'ssh', '',
83 ('e', 'ssh', '',
84 _('specify ssh command to use'), _('CMD')),
84 _('specify ssh command to use'), _('CMD')),
85 ('', 'remotecmd', '',
85 ('', 'remotecmd', '',
86 _('specify hg command to run on the remote side'), _('CMD')),
86 _('specify hg command to run on the remote side'), _('CMD')),
87 ('', 'insecure', None,
87 ('', 'insecure', None,
88 _('do not verify server certificate (ignoring web.cacerts config)')),
88 _('do not verify server certificate (ignoring web.cacerts config)')),
89 ]
89 ]
90
90
91 walkopts = [
91 walkopts = [
92 ('I', 'include', [],
92 ('I', 'include', [],
93 _('include names matching the given patterns'), _('PATTERN')),
93 _('include names matching the given patterns'), _('PATTERN')),
94 ('X', 'exclude', [],
94 ('X', 'exclude', [],
95 _('exclude names matching the given patterns'), _('PATTERN')),
95 _('exclude names matching the given patterns'), _('PATTERN')),
96 ]
96 ]
97
97
98 commitopts = [
98 commitopts = [
99 ('m', 'message', '',
99 ('m', 'message', '',
100 _('use text as commit message'), _('TEXT')),
100 _('use text as commit message'), _('TEXT')),
101 ('l', 'logfile', '',
101 ('l', 'logfile', '',
102 _('read commit message from file'), _('FILE')),
102 _('read commit message from file'), _('FILE')),
103 ]
103 ]
104
104
105 commitopts2 = [
105 commitopts2 = [
106 ('d', 'date', '',
106 ('d', 'date', '',
107 _('record the specified date as commit date'), _('DATE')),
107 _('record the specified date as commit date'), _('DATE')),
108 ('u', 'user', '',
108 ('u', 'user', '',
109 _('record the specified user as committer'), _('USER')),
109 _('record the specified user as committer'), _('USER')),
110 ]
110 ]
111
111
112 # hidden for now
112 # hidden for now
113 formatteropts = [
113 formatteropts = [
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 templateopts = [
118 templateopts = [
119 ('', 'style', '',
119 ('', 'style', '',
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
121 ('T', 'template', '',
121 ('T', 'template', '',
122 _('display with template'), _('TEMPLATE')),
122 _('display with template'), _('TEMPLATE')),
123 ]
123 ]
124
124
125 logopts = [
125 logopts = [
126 ('p', 'patch', None, _('show patch')),
126 ('p', 'patch', None, _('show patch')),
127 ('g', 'git', None, _('use git extended diff format')),
127 ('g', 'git', None, _('use git extended diff format')),
128 ('l', 'limit', '',
128 ('l', 'limit', '',
129 _('limit number of changes displayed'), _('NUM')),
129 _('limit number of changes displayed'), _('NUM')),
130 ('M', 'no-merges', None, _('do not show merges')),
130 ('M', 'no-merges', None, _('do not show merges')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
132 ('G', 'graph', None, _("show the revision DAG")),
132 ('G', 'graph', None, _("show the revision DAG")),
133 ] + templateopts
133 ] + templateopts
134
134
135 diffopts = [
135 diffopts = [
136 ('a', 'text', None, _('treat all files as text')),
136 ('a', 'text', None, _('treat all files as text')),
137 ('g', 'git', None, _('use git extended diff format')),
137 ('g', 'git', None, _('use git extended diff format')),
138 ('', 'nodates', None, _('omit dates from diff headers'))
138 ('', 'nodates', None, _('omit dates from diff headers'))
139 ]
139 ]
140
140
141 diffwsopts = [
141 diffwsopts = [
142 ('w', 'ignore-all-space', None,
142 ('w', 'ignore-all-space', None,
143 _('ignore white space when comparing lines')),
143 _('ignore white space when comparing lines')),
144 ('b', 'ignore-space-change', None,
144 ('b', 'ignore-space-change', None,
145 _('ignore changes in the amount of white space')),
145 _('ignore changes in the amount of white space')),
146 ('B', 'ignore-blank-lines', None,
146 ('B', 'ignore-blank-lines', None,
147 _('ignore changes whose lines are all blank')),
147 _('ignore changes whose lines are all blank')),
148 ]
148 ]
149
149
150 diffopts2 = [
150 diffopts2 = [
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
152 ('p', 'show-function', None, _('show which function each change is in')),
152 ('p', 'show-function', None, _('show which function each change is in')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
154 ] + diffwsopts + [
154 ] + diffwsopts + [
155 ('U', 'unified', '',
155 ('U', 'unified', '',
156 _('number of lines of context to show'), _('NUM')),
156 _('number of lines of context to show'), _('NUM')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
159 ]
159 ]
160
160
161 mergetoolopts = [
161 mergetoolopts = [
162 ('t', 'tool', '', _('specify merge tool')),
162 ('t', 'tool', '', _('specify merge tool')),
163 ]
163 ]
164
164
165 similarityopts = [
165 similarityopts = [
166 ('s', 'similarity', '',
166 ('s', 'similarity', '',
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
168 ]
168 ]
169
169
170 subrepoopts = [
170 subrepoopts = [
171 ('S', 'subrepos', None,
171 ('S', 'subrepos', None,
172 _('recurse into subrepositories'))
172 _('recurse into subrepositories'))
173 ]
173 ]
174
174
175 debugrevlogopts = [
175 debugrevlogopts = [
176 ('c', 'changelog', False, _('open changelog')),
176 ('c', 'changelog', False, _('open changelog')),
177 ('m', 'manifest', False, _('open manifest')),
177 ('m', 'manifest', False, _('open manifest')),
178 ('', 'dir', False, _('open directory manifest')),
178 ('', 'dir', False, _('open directory manifest')),
179 ]
179 ]
180
180
181 # Commands start here, listed alphabetically
181 # Commands start here, listed alphabetically
182
182
183 @command('^add',
183 @command('^add',
184 walkopts + subrepoopts + dryrunopts,
184 walkopts + subrepoopts + dryrunopts,
185 _('[OPTION]... [FILE]...'),
185 _('[OPTION]... [FILE]...'),
186 inferrepo=True)
186 inferrepo=True)
187 def add(ui, repo, *pats, **opts):
187 def add(ui, repo, *pats, **opts):
188 """add the specified files on the next commit
188 """add the specified files on the next commit
189
189
190 Schedule files to be version controlled and added to the
190 Schedule files to be version controlled and added to the
191 repository.
191 repository.
192
192
193 The files will be added to the repository at the next commit. To
193 The files will be added to the repository at the next commit. To
194 undo an add before that, see :hg:`forget`.
194 undo an add before that, see :hg:`forget`.
195
195
196 If no names are given, add all files to the repository (except
196 If no names are given, add all files to the repository (except
197 files matching ``.hgignore``).
197 files matching ``.hgignore``).
198
198
199 .. container:: verbose
199 .. container:: verbose
200
200
201 Examples:
201 Examples:
202
202
203 - New (unknown) files are added
203 - New (unknown) files are added
204 automatically by :hg:`add`::
204 automatically by :hg:`add`::
205
205
206 $ ls
206 $ ls
207 foo.c
207 foo.c
208 $ hg status
208 $ hg status
209 ? foo.c
209 ? foo.c
210 $ hg add
210 $ hg add
211 adding foo.c
211 adding foo.c
212 $ hg status
212 $ hg status
213 A foo.c
213 A foo.c
214
214
215 - Specific files to be added can be specified::
215 - Specific files to be added can be specified::
216
216
217 $ ls
217 $ ls
218 bar.c foo.c
218 bar.c foo.c
219 $ hg status
219 $ hg status
220 ? bar.c
220 ? bar.c
221 ? foo.c
221 ? foo.c
222 $ hg add bar.c
222 $ hg add bar.c
223 $ hg status
223 $ hg status
224 A bar.c
224 A bar.c
225 ? foo.c
225 ? foo.c
226
226
227 Returns 0 if all files are successfully added.
227 Returns 0 if all files are successfully added.
228 """
228 """
229
229
230 m = scmutil.match(repo[None], pats, opts)
230 m = scmutil.match(repo[None], pats, opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
232 return rejected and 1 or 0
232 return rejected and 1 or 0
233
233
234 @command('addremove',
234 @command('addremove',
235 similarityopts + subrepoopts + walkopts + dryrunopts,
235 similarityopts + subrepoopts + walkopts + dryrunopts,
236 _('[OPTION]... [FILE]...'),
236 _('[OPTION]... [FILE]...'),
237 inferrepo=True)
237 inferrepo=True)
238 def addremove(ui, repo, *pats, **opts):
238 def addremove(ui, repo, *pats, **opts):
239 """add all new files, delete all missing files
239 """add all new files, delete all missing files
240
240
241 Add all new files and remove all missing files from the
241 Add all new files and remove all missing files from the
242 repository.
242 repository.
243
243
244 Unless names are given, new files are ignored if they match any of
244 Unless names are given, new files are ignored if they match any of
245 the patterns in ``.hgignore``. As with add, these changes take
245 the patterns in ``.hgignore``. As with add, these changes take
246 effect at the next commit.
246 effect at the next commit.
247
247
248 Use the -s/--similarity option to detect renamed files. This
248 Use the -s/--similarity option to detect renamed files. This
249 option takes a percentage between 0 (disabled) and 100 (files must
249 option takes a percentage between 0 (disabled) and 100 (files must
250 be identical) as its parameter. With a parameter greater than 0,
250 be identical) as its parameter. With a parameter greater than 0,
251 this compares every removed file with every added file and records
251 this compares every removed file with every added file and records
252 those similar enough as renames. Detecting renamed files this way
252 those similar enough as renames. Detecting renamed files this way
253 can be expensive. After using this option, :hg:`status -C` can be
253 can be expensive. After using this option, :hg:`status -C` can be
254 used to check which files were identified as moved or renamed. If
254 used to check which files were identified as moved or renamed. If
255 not specified, -s/--similarity defaults to 100 and only renames of
255 not specified, -s/--similarity defaults to 100 and only renames of
256 identical files are detected.
256 identical files are detected.
257
257
258 .. container:: verbose
258 .. container:: verbose
259
259
260 Examples:
260 Examples:
261
261
262 - A number of files (bar.c and foo.c) are new,
262 - A number of files (bar.c and foo.c) are new,
263 while foobar.c has been removed (without using :hg:`remove`)
263 while foobar.c has been removed (without using :hg:`remove`)
264 from the repository::
264 from the repository::
265
265
266 $ ls
266 $ ls
267 bar.c foo.c
267 bar.c foo.c
268 $ hg status
268 $ hg status
269 ! foobar.c
269 ! foobar.c
270 ? bar.c
270 ? bar.c
271 ? foo.c
271 ? foo.c
272 $ hg addremove
272 $ hg addremove
273 adding bar.c
273 adding bar.c
274 adding foo.c
274 adding foo.c
275 removing foobar.c
275 removing foobar.c
276 $ hg status
276 $ hg status
277 A bar.c
277 A bar.c
278 A foo.c
278 A foo.c
279 R foobar.c
279 R foobar.c
280
280
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
282 Afterwards, it was edited slightly::
282 Afterwards, it was edited slightly::
283
283
284 $ ls
284 $ ls
285 foo.c
285 foo.c
286 $ hg status
286 $ hg status
287 ! foobar.c
287 ! foobar.c
288 ? foo.c
288 ? foo.c
289 $ hg addremove --similarity 90
289 $ hg addremove --similarity 90
290 removing foobar.c
290 removing foobar.c
291 adding foo.c
291 adding foo.c
292 recording removal of foobar.c as rename to foo.c (94% similar)
292 recording removal of foobar.c as rename to foo.c (94% similar)
293 $ hg status -C
293 $ hg status -C
294 A foo.c
294 A foo.c
295 foobar.c
295 foobar.c
296 R foobar.c
296 R foobar.c
297
297
298 Returns 0 if all files are successfully added.
298 Returns 0 if all files are successfully added.
299 """
299 """
300 try:
300 try:
301 sim = float(opts.get('similarity') or 100)
301 sim = float(opts.get('similarity') or 100)
302 except ValueError:
302 except ValueError:
303 raise error.Abort(_('similarity must be a number'))
303 raise error.Abort(_('similarity must be a number'))
304 if sim < 0 or sim > 100:
304 if sim < 0 or sim > 100:
305 raise error.Abort(_('similarity must be between 0 and 100'))
305 raise error.Abort(_('similarity must be between 0 and 100'))
306 matcher = scmutil.match(repo[None], pats, opts)
306 matcher = scmutil.match(repo[None], pats, opts)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
308
308
309 @command('^annotate|blame',
309 @command('^annotate|blame',
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
311 ('', 'follow', None,
311 ('', 'follow', None,
312 _('follow copies/renames and list the filename (DEPRECATED)')),
312 _('follow copies/renames and list the filename (DEPRECATED)')),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
314 ('a', 'text', None, _('treat all files as text')),
314 ('a', 'text', None, _('treat all files as text')),
315 ('u', 'user', None, _('list the author (long with -v)')),
315 ('u', 'user', None, _('list the author (long with -v)')),
316 ('f', 'file', None, _('list the filename')),
316 ('f', 'file', None, _('list the filename')),
317 ('d', 'date', None, _('list the date (short with -q)')),
317 ('d', 'date', None, _('list the date (short with -q)')),
318 ('n', 'number', None, _('list the revision number (default)')),
318 ('n', 'number', None, _('list the revision number (default)')),
319 ('c', 'changeset', None, _('list the changeset')),
319 ('c', 'changeset', None, _('list the changeset')),
320 ('l', 'line-number', None, _('show line number at the first appearance'))
320 ('l', 'line-number', None, _('show line number at the first appearance'))
321 ] + diffwsopts + walkopts + formatteropts,
321 ] + diffwsopts + walkopts + formatteropts,
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
323 inferrepo=True)
323 inferrepo=True)
324 def annotate(ui, repo, *pats, **opts):
324 def annotate(ui, repo, *pats, **opts):
325 """show changeset information by line for each file
325 """show changeset information by line for each file
326
326
327 List changes in files, showing the revision id responsible for
327 List changes in files, showing the revision id responsible for
328 each line.
328 each line.
329
329
330 This command is useful for discovering when a change was made and
330 This command is useful for discovering when a change was made and
331 by whom.
331 by whom.
332
332
333 If you include --file, --user, or --date, the revision number is
333 If you include --file, --user, or --date, the revision number is
334 suppressed unless you also include --number.
334 suppressed unless you also include --number.
335
335
336 Without the -a/--text option, annotate will avoid processing files
336 Without the -a/--text option, annotate will avoid processing files
337 it detects as binary. With -a, annotate will annotate the file
337 it detects as binary. With -a, annotate will annotate the file
338 anyway, although the results will probably be neither useful
338 anyway, although the results will probably be neither useful
339 nor desirable.
339 nor desirable.
340
340
341 Returns 0 on success.
341 Returns 0 on success.
342 """
342 """
343 if not pats:
343 if not pats:
344 raise error.Abort(_('at least one filename or pattern is required'))
344 raise error.Abort(_('at least one filename or pattern is required'))
345
345
346 if opts.get('follow'):
346 if opts.get('follow'):
347 # --follow is deprecated and now just an alias for -f/--file
347 # --follow is deprecated and now just an alias for -f/--file
348 # to mimic the behavior of Mercurial before version 1.5
348 # to mimic the behavior of Mercurial before version 1.5
349 opts['file'] = True
349 opts['file'] = True
350
350
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
352
352
353 fm = ui.formatter('annotate', opts)
353 fm = ui.formatter('annotate', opts)
354 if ui.quiet:
354 if ui.quiet:
355 datefunc = util.shortdate
355 datefunc = util.shortdate
356 else:
356 else:
357 datefunc = util.datestr
357 datefunc = util.datestr
358 if ctx.rev() is None:
358 if ctx.rev() is None:
359 def hexfn(node):
359 def hexfn(node):
360 if node is None:
360 if node is None:
361 return None
361 return None
362 else:
362 else:
363 return fm.hexfunc(node)
363 return fm.hexfunc(node)
364 if opts.get('changeset'):
364 if opts.get('changeset'):
365 # omit "+" suffix which is appended to node hex
365 # omit "+" suffix which is appended to node hex
366 def formatrev(rev):
366 def formatrev(rev):
367 if rev is None:
367 if rev is None:
368 return '%d' % ctx.p1().rev()
368 return '%d' % ctx.p1().rev()
369 else:
369 else:
370 return '%d' % rev
370 return '%d' % rev
371 else:
371 else:
372 def formatrev(rev):
372 def formatrev(rev):
373 if rev is None:
373 if rev is None:
374 return '%d+' % ctx.p1().rev()
374 return '%d+' % ctx.p1().rev()
375 else:
375 else:
376 return '%d ' % rev
376 return '%d ' % rev
377 def formathex(hex):
377 def formathex(hex):
378 if hex is None:
378 if hex is None:
379 return '%s+' % fm.hexfunc(ctx.p1().node())
379 return '%s+' % fm.hexfunc(ctx.p1().node())
380 else:
380 else:
381 return '%s ' % hex
381 return '%s ' % hex
382 else:
382 else:
383 hexfn = fm.hexfunc
383 hexfn = fm.hexfunc
384 formatrev = formathex = str
384 formatrev = formathex = str
385
385
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
390 ('file', ' ', lambda x: x[0].path(), str),
390 ('file', ' ', lambda x: x[0].path(), str),
391 ('line_number', ':', lambda x: x[1], str),
391 ('line_number', ':', lambda x: x[1], str),
392 ]
392 ]
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
394
394
395 if (not opts.get('user') and not opts.get('changeset')
395 if (not opts.get('user') and not opts.get('changeset')
396 and not opts.get('date') and not opts.get('file')):
396 and not opts.get('date') and not opts.get('file')):
397 opts['number'] = True
397 opts['number'] = True
398
398
399 linenumber = opts.get('line_number') is not None
399 linenumber = opts.get('line_number') is not None
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
402
402
403 if fm:
403 if fm:
404 def makefunc(get, fmt):
404 def makefunc(get, fmt):
405 return get
405 return get
406 else:
406 else:
407 def makefunc(get, fmt):
407 def makefunc(get, fmt):
408 return lambda x: fmt(get(x))
408 return lambda x: fmt(get(x))
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
410 if opts.get(op)]
410 if opts.get(op)]
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
413 if opts.get(op))
413 if opts.get(op))
414
414
415 def bad(x, y):
415 def bad(x, y):
416 raise error.Abort("%s: %s" % (x, y))
416 raise error.Abort("%s: %s" % (x, y))
417
417
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
419
419
420 follow = not opts.get('no_follow')
420 follow = not opts.get('no_follow')
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
422 whitespace=True)
422 whitespace=True)
423 for abs in ctx.walk(m):
423 for abs in ctx.walk(m):
424 fctx = ctx[abs]
424 fctx = ctx[abs]
425 if not opts.get('text') and util.binary(fctx.data()):
425 if not opts.get('text') and util.binary(fctx.data()):
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
427 continue
427 continue
428
428
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
430 diffopts=diffopts)
430 diffopts=diffopts)
431 formats = []
431 formats = []
432 pieces = []
432 pieces = []
433
433
434 for f, sep in funcmap:
434 for f, sep in funcmap:
435 l = [f(n) for n, dummy in lines]
435 l = [f(n) for n, dummy in lines]
436 if l:
436 if l:
437 if fm:
437 if fm:
438 formats.append(['%s' for x in l])
438 formats.append(['%s' for x in l])
439 else:
439 else:
440 sizes = [encoding.colwidth(x) for x in l]
440 sizes = [encoding.colwidth(x) for x in l]
441 ml = max(sizes)
441 ml = max(sizes)
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
443 pieces.append(l)
443 pieces.append(l)
444
444
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
446 fm.startitem()
446 fm.startitem()
447 fm.write(fields, "".join(f), *p)
447 fm.write(fields, "".join(f), *p)
448 fm.write('line', ": %s", l[1])
448 fm.write('line', ": %s", l[1])
449
449
450 if lines and not lines[-1][1].endswith('\n'):
450 if lines and not lines[-1][1].endswith('\n'):
451 fm.plain('\n')
451 fm.plain('\n')
452
452
453 fm.end()
453 fm.end()
454
454
455 @command('archive',
455 @command('archive',
456 [('', 'no-decode', None, _('do not pass files through decoders')),
456 [('', 'no-decode', None, _('do not pass files through decoders')),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
458 _('PREFIX')),
458 _('PREFIX')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
461 ] + subrepoopts + walkopts,
461 ] + subrepoopts + walkopts,
462 _('[OPTION]... DEST'))
462 _('[OPTION]... DEST'))
463 def archive(ui, repo, dest, **opts):
463 def archive(ui, repo, dest, **opts):
464 '''create an unversioned archive of a repository revision
464 '''create an unversioned archive of a repository revision
465
465
466 By default, the revision used is the parent of the working
466 By default, the revision used is the parent of the working
467 directory; use -r/--rev to specify a different revision.
467 directory; use -r/--rev to specify a different revision.
468
468
469 The archive type is automatically detected based on file
469 The archive type is automatically detected based on file
470 extension (to override, use -t/--type).
470 extension (to override, use -t/--type).
471
471
472 .. container:: verbose
472 .. container:: verbose
473
473
474 Examples:
474 Examples:
475
475
476 - create a zip file containing the 1.0 release::
476 - create a zip file containing the 1.0 release::
477
477
478 hg archive -r 1.0 project-1.0.zip
478 hg archive -r 1.0 project-1.0.zip
479
479
480 - create a tarball excluding .hg files::
480 - create a tarball excluding .hg files::
481
481
482 hg archive project.tar.gz -X ".hg*"
482 hg archive project.tar.gz -X ".hg*"
483
483
484 Valid types are:
484 Valid types are:
485
485
486 :``files``: a directory full of files (default)
486 :``files``: a directory full of files (default)
487 :``tar``: tar archive, uncompressed
487 :``tar``: tar archive, uncompressed
488 :``tbz2``: tar archive, compressed using bzip2
488 :``tbz2``: tar archive, compressed using bzip2
489 :``tgz``: tar archive, compressed using gzip
489 :``tgz``: tar archive, compressed using gzip
490 :``uzip``: zip archive, uncompressed
490 :``uzip``: zip archive, uncompressed
491 :``zip``: zip archive, compressed using deflate
491 :``zip``: zip archive, compressed using deflate
492
492
493 The exact name of the destination archive or directory is given
493 The exact name of the destination archive or directory is given
494 using a format string; see :hg:`help export` for details.
494 using a format string; see :hg:`help export` for details.
495
495
496 Each member added to an archive file has a directory prefix
496 Each member added to an archive file has a directory prefix
497 prepended. Use -p/--prefix to specify a format string for the
497 prepended. Use -p/--prefix to specify a format string for the
498 prefix. The default is the basename of the archive, with suffixes
498 prefix. The default is the basename of the archive, with suffixes
499 removed.
499 removed.
500
500
501 Returns 0 on success.
501 Returns 0 on success.
502 '''
502 '''
503
503
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
505 if not ctx:
505 if not ctx:
506 raise error.Abort(_('no working directory: please specify a revision'))
506 raise error.Abort(_('no working directory: please specify a revision'))
507 node = ctx.node()
507 node = ctx.node()
508 dest = cmdutil.makefilename(repo, dest, node)
508 dest = cmdutil.makefilename(repo, dest, node)
509 if os.path.realpath(dest) == repo.root:
509 if os.path.realpath(dest) == repo.root:
510 raise error.Abort(_('repository root cannot be destination'))
510 raise error.Abort(_('repository root cannot be destination'))
511
511
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
513 prefix = opts.get('prefix')
513 prefix = opts.get('prefix')
514
514
515 if dest == '-':
515 if dest == '-':
516 if kind == 'files':
516 if kind == 'files':
517 raise error.Abort(_('cannot archive plain files to stdout'))
517 raise error.Abort(_('cannot archive plain files to stdout'))
518 dest = cmdutil.makefileobj(repo, dest)
518 dest = cmdutil.makefileobj(repo, dest)
519 if not prefix:
519 if not prefix:
520 prefix = os.path.basename(repo.root) + '-%h'
520 prefix = os.path.basename(repo.root) + '-%h'
521
521
522 prefix = cmdutil.makefilename(repo, prefix, node)
522 prefix = cmdutil.makefilename(repo, prefix, node)
523 matchfn = scmutil.match(ctx, [], opts)
523 matchfn = scmutil.match(ctx, [], opts)
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
525 matchfn, prefix, subrepos=opts.get('subrepos'))
525 matchfn, prefix, subrepos=opts.get('subrepos'))
526
526
527 @command('backout',
527 @command('backout',
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
529 ('', 'commit', None,
529 ('', 'commit', None,
530 _('commit if no conflicts were encountered (DEPRECATED)')),
530 _('commit if no conflicts were encountered (DEPRECATED)')),
531 ('', 'no-commit', None, _('do not commit')),
531 ('', 'no-commit', None, _('do not commit')),
532 ('', 'parent', '',
532 ('', 'parent', '',
533 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
533 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
534 ('r', 'rev', '', _('revision to backout'), _('REV')),
534 ('r', 'rev', '', _('revision to backout'), _('REV')),
535 ('e', 'edit', False, _('invoke editor on commit messages')),
535 ('e', 'edit', False, _('invoke editor on commit messages')),
536 ] + mergetoolopts + walkopts + commitopts + commitopts2,
536 ] + mergetoolopts + walkopts + commitopts + commitopts2,
537 _('[OPTION]... [-r] REV'))
537 _('[OPTION]... [-r] REV'))
538 def backout(ui, repo, node=None, rev=None, **opts):
538 def backout(ui, repo, node=None, rev=None, **opts):
539 '''reverse effect of earlier changeset
539 '''reverse effect of earlier changeset
540
540
541 Prepare a new changeset with the effect of REV undone in the
541 Prepare a new changeset with the effect of REV undone in the
542 current working directory. If no conflicts were encountered,
542 current working directory. If no conflicts were encountered,
543 it will be committed immediately.
543 it will be committed immediately.
544
544
545 If REV is the parent of the working directory, then this new changeset
545 If REV is the parent of the working directory, then this new changeset
546 is committed automatically (unless --no-commit is specified).
546 is committed automatically (unless --no-commit is specified).
547
547
548 .. note::
548 .. note::
549
549
550 :hg:`backout` cannot be used to fix either an unwanted or
550 :hg:`backout` cannot be used to fix either an unwanted or
551 incorrect merge.
551 incorrect merge.
552
552
553 .. container:: verbose
553 .. container:: verbose
554
554
555 Examples:
555 Examples:
556
556
557 - Reverse the effect of the parent of the working directory.
557 - Reverse the effect of the parent of the working directory.
558 This backout will be committed immediately::
558 This backout will be committed immediately::
559
559
560 hg backout -r .
560 hg backout -r .
561
561
562 - Reverse the effect of previous bad revision 23::
562 - Reverse the effect of previous bad revision 23::
563
563
564 hg backout -r 23
564 hg backout -r 23
565
565
566 - Reverse the effect of previous bad revision 23 and
566 - Reverse the effect of previous bad revision 23 and
567 leave changes uncommitted::
567 leave changes uncommitted::
568
568
569 hg backout -r 23 --no-commit
569 hg backout -r 23 --no-commit
570 hg commit -m "Backout revision 23"
570 hg commit -m "Backout revision 23"
571
571
572 By default, the pending changeset will have one parent,
572 By default, the pending changeset will have one parent,
573 maintaining a linear history. With --merge, the pending
573 maintaining a linear history. With --merge, the pending
574 changeset will instead have two parents: the old parent of the
574 changeset will instead have two parents: the old parent of the
575 working directory and a new child of REV that simply undoes REV.
575 working directory and a new child of REV that simply undoes REV.
576
576
577 Before version 1.7, the behavior without --merge was equivalent
577 Before version 1.7, the behavior without --merge was equivalent
578 to specifying --merge followed by :hg:`update --clean .` to
578 to specifying --merge followed by :hg:`update --clean .` to
579 cancel the merge and leave the child of REV as a head to be
579 cancel the merge and leave the child of REV as a head to be
580 merged separately.
580 merged separately.
581
581
582 See :hg:`help dates` for a list of formats valid for -d/--date.
582 See :hg:`help dates` for a list of formats valid for -d/--date.
583
583
584 See :hg:`help revert` for a way to restore files to the state
584 See :hg:`help revert` for a way to restore files to the state
585 of another revision.
585 of another revision.
586
586
587 Returns 0 on success, 1 if nothing to backout or there are unresolved
587 Returns 0 on success, 1 if nothing to backout or there are unresolved
588 files.
588 files.
589 '''
589 '''
590 wlock = lock = None
590 wlock = lock = None
591 try:
591 try:
592 wlock = repo.wlock()
592 wlock = repo.wlock()
593 lock = repo.lock()
593 lock = repo.lock()
594 return _dobackout(ui, repo, node, rev, **opts)
594 return _dobackout(ui, repo, node, rev, **opts)
595 finally:
595 finally:
596 release(lock, wlock)
596 release(lock, wlock)
597
597
598 def _dobackout(ui, repo, node=None, rev=None, **opts):
598 def _dobackout(ui, repo, node=None, rev=None, **opts):
599 if opts.get('commit') and opts.get('no_commit'):
599 if opts.get('commit') and opts.get('no_commit'):
600 raise error.Abort(_("cannot use --commit with --no-commit"))
600 raise error.Abort(_("cannot use --commit with --no-commit"))
601 if opts.get('merge') and opts.get('no_commit'):
602 raise error.Abort(_("cannot use --merge with --no-commit"))
601
603
602 if rev and node:
604 if rev and node:
603 raise error.Abort(_("please specify just one revision"))
605 raise error.Abort(_("please specify just one revision"))
604
606
605 if not rev:
607 if not rev:
606 rev = node
608 rev = node
607
609
608 if not rev:
610 if not rev:
609 raise error.Abort(_("please specify a revision to backout"))
611 raise error.Abort(_("please specify a revision to backout"))
610
612
611 date = opts.get('date')
613 date = opts.get('date')
612 if date:
614 if date:
613 opts['date'] = util.parsedate(date)
615 opts['date'] = util.parsedate(date)
614
616
615 cmdutil.checkunfinished(repo)
617 cmdutil.checkunfinished(repo)
616 cmdutil.bailifchanged(repo)
618 cmdutil.bailifchanged(repo)
617 node = scmutil.revsingle(repo, rev).node()
619 node = scmutil.revsingle(repo, rev).node()
618
620
619 op1, op2 = repo.dirstate.parents()
621 op1, op2 = repo.dirstate.parents()
620 if not repo.changelog.isancestor(node, op1):
622 if not repo.changelog.isancestor(node, op1):
621 raise error.Abort(_('cannot backout change that is not an ancestor'))
623 raise error.Abort(_('cannot backout change that is not an ancestor'))
622
624
623 p1, p2 = repo.changelog.parents(node)
625 p1, p2 = repo.changelog.parents(node)
624 if p1 == nullid:
626 if p1 == nullid:
625 raise error.Abort(_('cannot backout a change with no parents'))
627 raise error.Abort(_('cannot backout a change with no parents'))
626 if p2 != nullid:
628 if p2 != nullid:
627 if not opts.get('parent'):
629 if not opts.get('parent'):
628 raise error.Abort(_('cannot backout a merge changeset'))
630 raise error.Abort(_('cannot backout a merge changeset'))
629 p = repo.lookup(opts['parent'])
631 p = repo.lookup(opts['parent'])
630 if p not in (p1, p2):
632 if p not in (p1, p2):
631 raise error.Abort(_('%s is not a parent of %s') %
633 raise error.Abort(_('%s is not a parent of %s') %
632 (short(p), short(node)))
634 (short(p), short(node)))
633 parent = p
635 parent = p
634 else:
636 else:
635 if opts.get('parent'):
637 if opts.get('parent'):
636 raise error.Abort(_('cannot use --parent on non-merge changeset'))
638 raise error.Abort(_('cannot use --parent on non-merge changeset'))
637 parent = p1
639 parent = p1
638
640
639 # the backout should appear on the same branch
641 # the backout should appear on the same branch
640 branch = repo.dirstate.branch()
642 branch = repo.dirstate.branch()
641 bheads = repo.branchheads(branch)
643 bheads = repo.branchheads(branch)
642 rctx = scmutil.revsingle(repo, hex(parent))
644 rctx = scmutil.revsingle(repo, hex(parent))
643 if not opts.get('merge') and op1 != node:
645 if not opts.get('merge') and op1 != node:
644 dsguard = cmdutil.dirstateguard(repo, 'backout')
646 dsguard = cmdutil.dirstateguard(repo, 'backout')
645 try:
647 try:
646 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
648 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
647 'backout')
649 'backout')
648 stats = mergemod.update(repo, parent, True, True, node, False)
650 stats = mergemod.update(repo, parent, True, True, node, False)
649 repo.setparents(op1, op2)
651 repo.setparents(op1, op2)
650 dsguard.close()
652 dsguard.close()
651 hg._showstats(repo, stats)
653 hg._showstats(repo, stats)
652 if stats[3]:
654 if stats[3]:
653 repo.ui.status(_("use 'hg resolve' to retry unresolved "
655 repo.ui.status(_("use 'hg resolve' to retry unresolved "
654 "file merges\n"))
656 "file merges\n"))
655 return 1
657 return 1
656 finally:
658 finally:
657 ui.setconfig('ui', 'forcemerge', '', '')
659 ui.setconfig('ui', 'forcemerge', '', '')
658 lockmod.release(dsguard)
660 lockmod.release(dsguard)
659 else:
661 else:
660 hg.clean(repo, node, show_stats=False)
662 hg.clean(repo, node, show_stats=False)
661 repo.dirstate.setbranch(branch)
663 repo.dirstate.setbranch(branch)
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
664 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
663
665
664 if opts.get('no_commit'):
666 if opts.get('no_commit'):
665 msg = _("changeset %s backed out, "
667 msg = _("changeset %s backed out, "
666 "don't forget to commit.\n")
668 "don't forget to commit.\n")
667 ui.status(msg % short(node))
669 ui.status(msg % short(node))
668 return 0
670 return 0
669
671
670 def commitfunc(ui, repo, message, match, opts):
672 def commitfunc(ui, repo, message, match, opts):
671 editform = 'backout'
673 editform = 'backout'
672 e = cmdutil.getcommiteditor(editform=editform, **opts)
674 e = cmdutil.getcommiteditor(editform=editform, **opts)
673 if not message:
675 if not message:
674 # we don't translate commit messages
676 # we don't translate commit messages
675 message = "Backed out changeset %s" % short(node)
677 message = "Backed out changeset %s" % short(node)
676 e = cmdutil.getcommiteditor(edit=True, editform=editform)
678 e = cmdutil.getcommiteditor(edit=True, editform=editform)
677 return repo.commit(message, opts.get('user'), opts.get('date'),
679 return repo.commit(message, opts.get('user'), opts.get('date'),
678 match, editor=e)
680 match, editor=e)
679 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
681 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
680 if not newnode:
682 if not newnode:
681 ui.status(_("nothing changed\n"))
683 ui.status(_("nothing changed\n"))
682 return 1
684 return 1
683 cmdutil.commitstatus(repo, newnode, branch, bheads)
685 cmdutil.commitstatus(repo, newnode, branch, bheads)
684
686
685 def nice(node):
687 def nice(node):
686 return '%d:%s' % (repo.changelog.rev(node), short(node))
688 return '%d:%s' % (repo.changelog.rev(node), short(node))
687 ui.status(_('changeset %s backs out changeset %s\n') %
689 ui.status(_('changeset %s backs out changeset %s\n') %
688 (nice(repo.changelog.tip()), nice(node)))
690 (nice(repo.changelog.tip()), nice(node)))
689 if opts.get('merge') and op1 != node:
691 if opts.get('merge') and op1 != node:
690 hg.clean(repo, op1, show_stats=False)
692 hg.clean(repo, op1, show_stats=False)
691 ui.status(_('merging with changeset %s\n')
693 ui.status(_('merging with changeset %s\n')
692 % nice(repo.changelog.tip()))
694 % nice(repo.changelog.tip()))
693 try:
695 try:
694 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
696 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
695 'backout')
697 'backout')
696 return hg.merge(repo, hex(repo.changelog.tip()))
698 return hg.merge(repo, hex(repo.changelog.tip()))
697 finally:
699 finally:
698 ui.setconfig('ui', 'forcemerge', '', '')
700 ui.setconfig('ui', 'forcemerge', '', '')
699 return 0
701 return 0
700
702
701 @command('bisect',
703 @command('bisect',
702 [('r', 'reset', False, _('reset bisect state')),
704 [('r', 'reset', False, _('reset bisect state')),
703 ('g', 'good', False, _('mark changeset good')),
705 ('g', 'good', False, _('mark changeset good')),
704 ('b', 'bad', False, _('mark changeset bad')),
706 ('b', 'bad', False, _('mark changeset bad')),
705 ('s', 'skip', False, _('skip testing changeset')),
707 ('s', 'skip', False, _('skip testing changeset')),
706 ('e', 'extend', False, _('extend the bisect range')),
708 ('e', 'extend', False, _('extend the bisect range')),
707 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
709 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
708 ('U', 'noupdate', False, _('do not update to target'))],
710 ('U', 'noupdate', False, _('do not update to target'))],
709 _("[-gbsr] [-U] [-c CMD] [REV]"))
711 _("[-gbsr] [-U] [-c CMD] [REV]"))
710 def bisect(ui, repo, rev=None, extra=None, command=None,
712 def bisect(ui, repo, rev=None, extra=None, command=None,
711 reset=None, good=None, bad=None, skip=None, extend=None,
713 reset=None, good=None, bad=None, skip=None, extend=None,
712 noupdate=None):
714 noupdate=None):
713 """subdivision search of changesets
715 """subdivision search of changesets
714
716
715 This command helps to find changesets which introduce problems. To
717 This command helps to find changesets which introduce problems. To
716 use, mark the earliest changeset you know exhibits the problem as
718 use, mark the earliest changeset you know exhibits the problem as
717 bad, then mark the latest changeset which is free from the problem
719 bad, then mark the latest changeset which is free from the problem
718 as good. Bisect will update your working directory to a revision
720 as good. Bisect will update your working directory to a revision
719 for testing (unless the -U/--noupdate option is specified). Once
721 for testing (unless the -U/--noupdate option is specified). Once
720 you have performed tests, mark the working directory as good or
722 you have performed tests, mark the working directory as good or
721 bad, and bisect will either update to another candidate changeset
723 bad, and bisect will either update to another candidate changeset
722 or announce that it has found the bad revision.
724 or announce that it has found the bad revision.
723
725
724 As a shortcut, you can also use the revision argument to mark a
726 As a shortcut, you can also use the revision argument to mark a
725 revision as good or bad without checking it out first.
727 revision as good or bad without checking it out first.
726
728
727 If you supply a command, it will be used for automatic bisection.
729 If you supply a command, it will be used for automatic bisection.
728 The environment variable HG_NODE will contain the ID of the
730 The environment variable HG_NODE will contain the ID of the
729 changeset being tested. The exit status of the command will be
731 changeset being tested. The exit status of the command will be
730 used to mark revisions as good or bad: status 0 means good, 125
732 used to mark revisions as good or bad: status 0 means good, 125
731 means to skip the revision, 127 (command not found) will abort the
733 means to skip the revision, 127 (command not found) will abort the
732 bisection, and any other non-zero exit status means the revision
734 bisection, and any other non-zero exit status means the revision
733 is bad.
735 is bad.
734
736
735 .. container:: verbose
737 .. container:: verbose
736
738
737 Some examples:
739 Some examples:
738
740
739 - start a bisection with known bad revision 34, and good revision 12::
741 - start a bisection with known bad revision 34, and good revision 12::
740
742
741 hg bisect --bad 34
743 hg bisect --bad 34
742 hg bisect --good 12
744 hg bisect --good 12
743
745
744 - advance the current bisection by marking current revision as good or
746 - advance the current bisection by marking current revision as good or
745 bad::
747 bad::
746
748
747 hg bisect --good
749 hg bisect --good
748 hg bisect --bad
750 hg bisect --bad
749
751
750 - mark the current revision, or a known revision, to be skipped (e.g. if
752 - mark the current revision, or a known revision, to be skipped (e.g. if
751 that revision is not usable because of another issue)::
753 that revision is not usable because of another issue)::
752
754
753 hg bisect --skip
755 hg bisect --skip
754 hg bisect --skip 23
756 hg bisect --skip 23
755
757
756 - skip all revisions that do not touch directories ``foo`` or ``bar``::
758 - skip all revisions that do not touch directories ``foo`` or ``bar``::
757
759
758 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
760 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
759
761
760 - forget the current bisection::
762 - forget the current bisection::
761
763
762 hg bisect --reset
764 hg bisect --reset
763
765
764 - use 'make && make tests' to automatically find the first broken
766 - use 'make && make tests' to automatically find the first broken
765 revision::
767 revision::
766
768
767 hg bisect --reset
769 hg bisect --reset
768 hg bisect --bad 34
770 hg bisect --bad 34
769 hg bisect --good 12
771 hg bisect --good 12
770 hg bisect --command "make && make tests"
772 hg bisect --command "make && make tests"
771
773
772 - see all changesets whose states are already known in the current
774 - see all changesets whose states are already known in the current
773 bisection::
775 bisection::
774
776
775 hg log -r "bisect(pruned)"
777 hg log -r "bisect(pruned)"
776
778
777 - see the changeset currently being bisected (especially useful
779 - see the changeset currently being bisected (especially useful
778 if running with -U/--noupdate)::
780 if running with -U/--noupdate)::
779
781
780 hg log -r "bisect(current)"
782 hg log -r "bisect(current)"
781
783
782 - see all changesets that took part in the current bisection::
784 - see all changesets that took part in the current bisection::
783
785
784 hg log -r "bisect(range)"
786 hg log -r "bisect(range)"
785
787
786 - you can even get a nice graph::
788 - you can even get a nice graph::
787
789
788 hg log --graph -r "bisect(range)"
790 hg log --graph -r "bisect(range)"
789
791
790 See :hg:`help revsets` for more about the `bisect()` keyword.
792 See :hg:`help revsets` for more about the `bisect()` keyword.
791
793
792 Returns 0 on success.
794 Returns 0 on success.
793 """
795 """
794 def extendbisectrange(nodes, good):
796 def extendbisectrange(nodes, good):
795 # bisect is incomplete when it ends on a merge node and
797 # bisect is incomplete when it ends on a merge node and
796 # one of the parent was not checked.
798 # one of the parent was not checked.
797 parents = repo[nodes[0]].parents()
799 parents = repo[nodes[0]].parents()
798 if len(parents) > 1:
800 if len(parents) > 1:
799 if good:
801 if good:
800 side = state['bad']
802 side = state['bad']
801 else:
803 else:
802 side = state['good']
804 side = state['good']
803 num = len(set(i.node() for i in parents) & set(side))
805 num = len(set(i.node() for i in parents) & set(side))
804 if num == 1:
806 if num == 1:
805 return parents[0].ancestor(parents[1])
807 return parents[0].ancestor(parents[1])
806 return None
808 return None
807
809
808 def print_result(nodes, good):
810 def print_result(nodes, good):
809 displayer = cmdutil.show_changeset(ui, repo, {})
811 displayer = cmdutil.show_changeset(ui, repo, {})
810 if len(nodes) == 1:
812 if len(nodes) == 1:
811 # narrowed it down to a single revision
813 # narrowed it down to a single revision
812 if good:
814 if good:
813 ui.write(_("The first good revision is:\n"))
815 ui.write(_("The first good revision is:\n"))
814 else:
816 else:
815 ui.write(_("The first bad revision is:\n"))
817 ui.write(_("The first bad revision is:\n"))
816 displayer.show(repo[nodes[0]])
818 displayer.show(repo[nodes[0]])
817 extendnode = extendbisectrange(nodes, good)
819 extendnode = extendbisectrange(nodes, good)
818 if extendnode is not None:
820 if extendnode is not None:
819 ui.write(_('Not all ancestors of this changeset have been'
821 ui.write(_('Not all ancestors of this changeset have been'
820 ' checked.\nUse bisect --extend to continue the '
822 ' checked.\nUse bisect --extend to continue the '
821 'bisection from\nthe common ancestor, %s.\n')
823 'bisection from\nthe common ancestor, %s.\n')
822 % extendnode)
824 % extendnode)
823 else:
825 else:
824 # multiple possible revisions
826 # multiple possible revisions
825 if good:
827 if good:
826 ui.write(_("Due to skipped revisions, the first "
828 ui.write(_("Due to skipped revisions, the first "
827 "good revision could be any of:\n"))
829 "good revision could be any of:\n"))
828 else:
830 else:
829 ui.write(_("Due to skipped revisions, the first "
831 ui.write(_("Due to skipped revisions, the first "
830 "bad revision could be any of:\n"))
832 "bad revision could be any of:\n"))
831 for n in nodes:
833 for n in nodes:
832 displayer.show(repo[n])
834 displayer.show(repo[n])
833 displayer.close()
835 displayer.close()
834
836
835 def check_state(state, interactive=True):
837 def check_state(state, interactive=True):
836 if not state['good'] or not state['bad']:
838 if not state['good'] or not state['bad']:
837 if (good or bad or skip or reset) and interactive:
839 if (good or bad or skip or reset) and interactive:
838 return
840 return
839 if not state['good']:
841 if not state['good']:
840 raise error.Abort(_('cannot bisect (no known good revisions)'))
842 raise error.Abort(_('cannot bisect (no known good revisions)'))
841 else:
843 else:
842 raise error.Abort(_('cannot bisect (no known bad revisions)'))
844 raise error.Abort(_('cannot bisect (no known bad revisions)'))
843 return True
845 return True
844
846
845 # backward compatibility
847 # backward compatibility
846 if rev in "good bad reset init".split():
848 if rev in "good bad reset init".split():
847 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
849 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
848 cmd, rev, extra = rev, extra, None
850 cmd, rev, extra = rev, extra, None
849 if cmd == "good":
851 if cmd == "good":
850 good = True
852 good = True
851 elif cmd == "bad":
853 elif cmd == "bad":
852 bad = True
854 bad = True
853 else:
855 else:
854 reset = True
856 reset = True
855 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
857 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
856 raise error.Abort(_('incompatible arguments'))
858 raise error.Abort(_('incompatible arguments'))
857
859
858 cmdutil.checkunfinished(repo)
860 cmdutil.checkunfinished(repo)
859
861
860 if reset:
862 if reset:
861 p = repo.join("bisect.state")
863 p = repo.join("bisect.state")
862 if os.path.exists(p):
864 if os.path.exists(p):
863 os.unlink(p)
865 os.unlink(p)
864 return
866 return
865
867
866 state = hbisect.load_state(repo)
868 state = hbisect.load_state(repo)
867
869
868 if command:
870 if command:
869 changesets = 1
871 changesets = 1
870 if noupdate:
872 if noupdate:
871 try:
873 try:
872 node = state['current'][0]
874 node = state['current'][0]
873 except LookupError:
875 except LookupError:
874 raise error.Abort(_('current bisect revision is unknown - '
876 raise error.Abort(_('current bisect revision is unknown - '
875 'start a new bisect to fix'))
877 'start a new bisect to fix'))
876 else:
878 else:
877 node, p2 = repo.dirstate.parents()
879 node, p2 = repo.dirstate.parents()
878 if p2 != nullid:
880 if p2 != nullid:
879 raise error.Abort(_('current bisect revision is a merge'))
881 raise error.Abort(_('current bisect revision is a merge'))
880 try:
882 try:
881 while changesets:
883 while changesets:
882 # update state
884 # update state
883 state['current'] = [node]
885 state['current'] = [node]
884 hbisect.save_state(repo, state)
886 hbisect.save_state(repo, state)
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
887 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 if status == 125:
888 if status == 125:
887 transition = "skip"
889 transition = "skip"
888 elif status == 0:
890 elif status == 0:
889 transition = "good"
891 transition = "good"
890 # status < 0 means process was killed
892 # status < 0 means process was killed
891 elif status == 127:
893 elif status == 127:
892 raise error.Abort(_("failed to execute %s") % command)
894 raise error.Abort(_("failed to execute %s") % command)
893 elif status < 0:
895 elif status < 0:
894 raise error.Abort(_("%s killed") % command)
896 raise error.Abort(_("%s killed") % command)
895 else:
897 else:
896 transition = "bad"
898 transition = "bad"
897 ctx = scmutil.revsingle(repo, rev, node)
899 ctx = scmutil.revsingle(repo, rev, node)
898 rev = None # clear for future iterations
900 rev = None # clear for future iterations
899 state[transition].append(ctx.node())
901 state[transition].append(ctx.node())
900 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
902 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
901 check_state(state, interactive=False)
903 check_state(state, interactive=False)
902 # bisect
904 # bisect
903 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
905 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
904 # update to next check
906 # update to next check
905 node = nodes[0]
907 node = nodes[0]
906 if not noupdate:
908 if not noupdate:
907 cmdutil.bailifchanged(repo)
909 cmdutil.bailifchanged(repo)
908 hg.clean(repo, node, show_stats=False)
910 hg.clean(repo, node, show_stats=False)
909 finally:
911 finally:
910 state['current'] = [node]
912 state['current'] = [node]
911 hbisect.save_state(repo, state)
913 hbisect.save_state(repo, state)
912 print_result(nodes, bgood)
914 print_result(nodes, bgood)
913 return
915 return
914
916
915 # update state
917 # update state
916
918
917 if rev:
919 if rev:
918 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
920 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
919 else:
921 else:
920 nodes = [repo.lookup('.')]
922 nodes = [repo.lookup('.')]
921
923
922 if good or bad or skip:
924 if good or bad or skip:
923 if good:
925 if good:
924 state['good'] += nodes
926 state['good'] += nodes
925 elif bad:
927 elif bad:
926 state['bad'] += nodes
928 state['bad'] += nodes
927 elif skip:
929 elif skip:
928 state['skip'] += nodes
930 state['skip'] += nodes
929 hbisect.save_state(repo, state)
931 hbisect.save_state(repo, state)
930
932
931 if not check_state(state):
933 if not check_state(state):
932 return
934 return
933
935
934 # actually bisect
936 # actually bisect
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
937 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
936 if extend:
938 if extend:
937 if not changesets:
939 if not changesets:
938 extendnode = extendbisectrange(nodes, good)
940 extendnode = extendbisectrange(nodes, good)
939 if extendnode is not None:
941 if extendnode is not None:
940 ui.write(_("Extending search to changeset %d:%s\n")
942 ui.write(_("Extending search to changeset %d:%s\n")
941 % (extendnode.rev(), extendnode))
943 % (extendnode.rev(), extendnode))
942 state['current'] = [extendnode.node()]
944 state['current'] = [extendnode.node()]
943 hbisect.save_state(repo, state)
945 hbisect.save_state(repo, state)
944 if noupdate:
946 if noupdate:
945 return
947 return
946 cmdutil.bailifchanged(repo)
948 cmdutil.bailifchanged(repo)
947 return hg.clean(repo, extendnode.node())
949 return hg.clean(repo, extendnode.node())
948 raise error.Abort(_("nothing to extend"))
950 raise error.Abort(_("nothing to extend"))
949
951
950 if changesets == 0:
952 if changesets == 0:
951 print_result(nodes, good)
953 print_result(nodes, good)
952 else:
954 else:
953 assert len(nodes) == 1 # only a single node can be tested next
955 assert len(nodes) == 1 # only a single node can be tested next
954 node = nodes[0]
956 node = nodes[0]
955 # compute the approximate number of remaining tests
957 # compute the approximate number of remaining tests
956 tests, size = 0, 2
958 tests, size = 0, 2
957 while size <= changesets:
959 while size <= changesets:
958 tests, size = tests + 1, size * 2
960 tests, size = tests + 1, size * 2
959 rev = repo.changelog.rev(node)
961 rev = repo.changelog.rev(node)
960 ui.write(_("Testing changeset %d:%s "
962 ui.write(_("Testing changeset %d:%s "
961 "(%d changesets remaining, ~%d tests)\n")
963 "(%d changesets remaining, ~%d tests)\n")
962 % (rev, short(node), changesets, tests))
964 % (rev, short(node), changesets, tests))
963 state['current'] = [node]
965 state['current'] = [node]
964 hbisect.save_state(repo, state)
966 hbisect.save_state(repo, state)
965 if not noupdate:
967 if not noupdate:
966 cmdutil.bailifchanged(repo)
968 cmdutil.bailifchanged(repo)
967 return hg.clean(repo, node)
969 return hg.clean(repo, node)
968
970
969 @command('bookmarks|bookmark',
971 @command('bookmarks|bookmark',
970 [('f', 'force', False, _('force')),
972 [('f', 'force', False, _('force')),
971 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
973 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
972 ('d', 'delete', False, _('delete a given bookmark')),
974 ('d', 'delete', False, _('delete a given bookmark')),
973 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
975 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
974 ('i', 'inactive', False, _('mark a bookmark inactive')),
976 ('i', 'inactive', False, _('mark a bookmark inactive')),
975 ] + formatteropts,
977 ] + formatteropts,
976 _('hg bookmarks [OPTIONS]... [NAME]...'))
978 _('hg bookmarks [OPTIONS]... [NAME]...'))
977 def bookmark(ui, repo, *names, **opts):
979 def bookmark(ui, repo, *names, **opts):
978 '''create a new bookmark or list existing bookmarks
980 '''create a new bookmark or list existing bookmarks
979
981
980 Bookmarks are labels on changesets to help track lines of development.
982 Bookmarks are labels on changesets to help track lines of development.
981 Bookmarks are unversioned and can be moved, renamed and deleted.
983 Bookmarks are unversioned and can be moved, renamed and deleted.
982 Deleting or moving a bookmark has no effect on the associated changesets.
984 Deleting or moving a bookmark has no effect on the associated changesets.
983
985
984 Creating or updating to a bookmark causes it to be marked as 'active'.
986 Creating or updating to a bookmark causes it to be marked as 'active'.
985 The active bookmark is indicated with a '*'.
987 The active bookmark is indicated with a '*'.
986 When a commit is made, the active bookmark will advance to the new commit.
988 When a commit is made, the active bookmark will advance to the new commit.
987 A plain :hg:`update` will also advance an active bookmark, if possible.
989 A plain :hg:`update` will also advance an active bookmark, if possible.
988 Updating away from a bookmark will cause it to be deactivated.
990 Updating away from a bookmark will cause it to be deactivated.
989
991
990 Bookmarks can be pushed and pulled between repositories (see
992 Bookmarks can be pushed and pulled between repositories (see
991 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
993 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
992 diverged, a new 'divergent bookmark' of the form 'name@path' will
994 diverged, a new 'divergent bookmark' of the form 'name@path' will
993 be created. Using :hg:`merge` will resolve the divergence.
995 be created. Using :hg:`merge` will resolve the divergence.
994
996
995 A bookmark named '@' has the special property that :hg:`clone` will
997 A bookmark named '@' has the special property that :hg:`clone` will
996 check it out by default if it exists.
998 check it out by default if it exists.
997
999
998 .. container:: verbose
1000 .. container:: verbose
999
1001
1000 Examples:
1002 Examples:
1001
1003
1002 - create an active bookmark for a new line of development::
1004 - create an active bookmark for a new line of development::
1003
1005
1004 hg book new-feature
1006 hg book new-feature
1005
1007
1006 - create an inactive bookmark as a place marker::
1008 - create an inactive bookmark as a place marker::
1007
1009
1008 hg book -i reviewed
1010 hg book -i reviewed
1009
1011
1010 - create an inactive bookmark on another changeset::
1012 - create an inactive bookmark on another changeset::
1011
1013
1012 hg book -r .^ tested
1014 hg book -r .^ tested
1013
1015
1014 - rename bookmark turkey to dinner::
1016 - rename bookmark turkey to dinner::
1015
1017
1016 hg book -m turkey dinner
1018 hg book -m turkey dinner
1017
1019
1018 - move the '@' bookmark from another branch::
1020 - move the '@' bookmark from another branch::
1019
1021
1020 hg book -f @
1022 hg book -f @
1021 '''
1023 '''
1022 force = opts.get('force')
1024 force = opts.get('force')
1023 rev = opts.get('rev')
1025 rev = opts.get('rev')
1024 delete = opts.get('delete')
1026 delete = opts.get('delete')
1025 rename = opts.get('rename')
1027 rename = opts.get('rename')
1026 inactive = opts.get('inactive')
1028 inactive = opts.get('inactive')
1027
1029
1028 def checkformat(mark):
1030 def checkformat(mark):
1029 mark = mark.strip()
1031 mark = mark.strip()
1030 if not mark:
1032 if not mark:
1031 raise error.Abort(_("bookmark names cannot consist entirely of "
1033 raise error.Abort(_("bookmark names cannot consist entirely of "
1032 "whitespace"))
1034 "whitespace"))
1033 scmutil.checknewlabel(repo, mark, 'bookmark')
1035 scmutil.checknewlabel(repo, mark, 'bookmark')
1034 return mark
1036 return mark
1035
1037
1036 def checkconflict(repo, mark, cur, force=False, target=None):
1038 def checkconflict(repo, mark, cur, force=False, target=None):
1037 if mark in marks and not force:
1039 if mark in marks and not force:
1038 if target:
1040 if target:
1039 if marks[mark] == target and target == cur:
1041 if marks[mark] == target and target == cur:
1040 # re-activating a bookmark
1042 # re-activating a bookmark
1041 return
1043 return
1042 anc = repo.changelog.ancestors([repo[target].rev()])
1044 anc = repo.changelog.ancestors([repo[target].rev()])
1043 bmctx = repo[marks[mark]]
1045 bmctx = repo[marks[mark]]
1044 divs = [repo[b].node() for b in marks
1046 divs = [repo[b].node() for b in marks
1045 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1047 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1046
1048
1047 # allow resolving a single divergent bookmark even if moving
1049 # allow resolving a single divergent bookmark even if moving
1048 # the bookmark across branches when a revision is specified
1050 # the bookmark across branches when a revision is specified
1049 # that contains a divergent bookmark
1051 # that contains a divergent bookmark
1050 if bmctx.rev() not in anc and target in divs:
1052 if bmctx.rev() not in anc and target in divs:
1051 bookmarks.deletedivergent(repo, [target], mark)
1053 bookmarks.deletedivergent(repo, [target], mark)
1052 return
1054 return
1053
1055
1054 deletefrom = [b for b in divs
1056 deletefrom = [b for b in divs
1055 if repo[b].rev() in anc or b == target]
1057 if repo[b].rev() in anc or b == target]
1056 bookmarks.deletedivergent(repo, deletefrom, mark)
1058 bookmarks.deletedivergent(repo, deletefrom, mark)
1057 if bookmarks.validdest(repo, bmctx, repo[target]):
1059 if bookmarks.validdest(repo, bmctx, repo[target]):
1058 ui.status(_("moving bookmark '%s' forward from %s\n") %
1060 ui.status(_("moving bookmark '%s' forward from %s\n") %
1059 (mark, short(bmctx.node())))
1061 (mark, short(bmctx.node())))
1060 return
1062 return
1061 raise error.Abort(_("bookmark '%s' already exists "
1063 raise error.Abort(_("bookmark '%s' already exists "
1062 "(use -f to force)") % mark)
1064 "(use -f to force)") % mark)
1063 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1065 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1064 and not force):
1066 and not force):
1065 raise error.Abort(
1067 raise error.Abort(
1066 _("a bookmark cannot have the name of an existing branch"))
1068 _("a bookmark cannot have the name of an existing branch"))
1067
1069
1068 if delete and rename:
1070 if delete and rename:
1069 raise error.Abort(_("--delete and --rename are incompatible"))
1071 raise error.Abort(_("--delete and --rename are incompatible"))
1070 if delete and rev:
1072 if delete and rev:
1071 raise error.Abort(_("--rev is incompatible with --delete"))
1073 raise error.Abort(_("--rev is incompatible with --delete"))
1072 if rename and rev:
1074 if rename and rev:
1073 raise error.Abort(_("--rev is incompatible with --rename"))
1075 raise error.Abort(_("--rev is incompatible with --rename"))
1074 if not names and (delete or rev):
1076 if not names and (delete or rev):
1075 raise error.Abort(_("bookmark name required"))
1077 raise error.Abort(_("bookmark name required"))
1076
1078
1077 if delete or rename or names or inactive:
1079 if delete or rename or names or inactive:
1078 wlock = lock = tr = None
1080 wlock = lock = tr = None
1079 try:
1081 try:
1080 wlock = repo.wlock()
1082 wlock = repo.wlock()
1081 lock = repo.lock()
1083 lock = repo.lock()
1082 cur = repo.changectx('.').node()
1084 cur = repo.changectx('.').node()
1083 marks = repo._bookmarks
1085 marks = repo._bookmarks
1084 if delete:
1086 if delete:
1085 tr = repo.transaction('bookmark')
1087 tr = repo.transaction('bookmark')
1086 for mark in names:
1088 for mark in names:
1087 if mark not in marks:
1089 if mark not in marks:
1088 raise error.Abort(_("bookmark '%s' does not exist") %
1090 raise error.Abort(_("bookmark '%s' does not exist") %
1089 mark)
1091 mark)
1090 if mark == repo._activebookmark:
1092 if mark == repo._activebookmark:
1091 bookmarks.deactivate(repo)
1093 bookmarks.deactivate(repo)
1092 del marks[mark]
1094 del marks[mark]
1093
1095
1094 elif rename:
1096 elif rename:
1095 tr = repo.transaction('bookmark')
1097 tr = repo.transaction('bookmark')
1096 if not names:
1098 if not names:
1097 raise error.Abort(_("new bookmark name required"))
1099 raise error.Abort(_("new bookmark name required"))
1098 elif len(names) > 1:
1100 elif len(names) > 1:
1099 raise error.Abort(_("only one new bookmark name allowed"))
1101 raise error.Abort(_("only one new bookmark name allowed"))
1100 mark = checkformat(names[0])
1102 mark = checkformat(names[0])
1101 if rename not in marks:
1103 if rename not in marks:
1102 raise error.Abort(_("bookmark '%s' does not exist")
1104 raise error.Abort(_("bookmark '%s' does not exist")
1103 % rename)
1105 % rename)
1104 checkconflict(repo, mark, cur, force)
1106 checkconflict(repo, mark, cur, force)
1105 marks[mark] = marks[rename]
1107 marks[mark] = marks[rename]
1106 if repo._activebookmark == rename and not inactive:
1108 if repo._activebookmark == rename and not inactive:
1107 bookmarks.activate(repo, mark)
1109 bookmarks.activate(repo, mark)
1108 del marks[rename]
1110 del marks[rename]
1109 elif names:
1111 elif names:
1110 tr = repo.transaction('bookmark')
1112 tr = repo.transaction('bookmark')
1111 newact = None
1113 newact = None
1112 for mark in names:
1114 for mark in names:
1113 mark = checkformat(mark)
1115 mark = checkformat(mark)
1114 if newact is None:
1116 if newact is None:
1115 newact = mark
1117 newact = mark
1116 if inactive and mark == repo._activebookmark:
1118 if inactive and mark == repo._activebookmark:
1117 bookmarks.deactivate(repo)
1119 bookmarks.deactivate(repo)
1118 return
1120 return
1119 tgt = cur
1121 tgt = cur
1120 if rev:
1122 if rev:
1121 tgt = scmutil.revsingle(repo, rev).node()
1123 tgt = scmutil.revsingle(repo, rev).node()
1122 checkconflict(repo, mark, cur, force, tgt)
1124 checkconflict(repo, mark, cur, force, tgt)
1123 marks[mark] = tgt
1125 marks[mark] = tgt
1124 if not inactive and cur == marks[newact] and not rev:
1126 if not inactive and cur == marks[newact] and not rev:
1125 bookmarks.activate(repo, newact)
1127 bookmarks.activate(repo, newact)
1126 elif cur != tgt and newact == repo._activebookmark:
1128 elif cur != tgt and newact == repo._activebookmark:
1127 bookmarks.deactivate(repo)
1129 bookmarks.deactivate(repo)
1128 elif inactive:
1130 elif inactive:
1129 if len(marks) == 0:
1131 if len(marks) == 0:
1130 ui.status(_("no bookmarks set\n"))
1132 ui.status(_("no bookmarks set\n"))
1131 elif not repo._activebookmark:
1133 elif not repo._activebookmark:
1132 ui.status(_("no active bookmark\n"))
1134 ui.status(_("no active bookmark\n"))
1133 else:
1135 else:
1134 bookmarks.deactivate(repo)
1136 bookmarks.deactivate(repo)
1135 if tr is not None:
1137 if tr is not None:
1136 marks.recordchange(tr)
1138 marks.recordchange(tr)
1137 tr.close()
1139 tr.close()
1138 finally:
1140 finally:
1139 lockmod.release(tr, lock, wlock)
1141 lockmod.release(tr, lock, wlock)
1140 else: # show bookmarks
1142 else: # show bookmarks
1141 fm = ui.formatter('bookmarks', opts)
1143 fm = ui.formatter('bookmarks', opts)
1142 hexfn = fm.hexfunc
1144 hexfn = fm.hexfunc
1143 marks = repo._bookmarks
1145 marks = repo._bookmarks
1144 if len(marks) == 0 and not fm:
1146 if len(marks) == 0 and not fm:
1145 ui.status(_("no bookmarks set\n"))
1147 ui.status(_("no bookmarks set\n"))
1146 for bmark, n in sorted(marks.iteritems()):
1148 for bmark, n in sorted(marks.iteritems()):
1147 active = repo._activebookmark
1149 active = repo._activebookmark
1148 if bmark == active:
1150 if bmark == active:
1149 prefix, label = '*', activebookmarklabel
1151 prefix, label = '*', activebookmarklabel
1150 else:
1152 else:
1151 prefix, label = ' ', ''
1153 prefix, label = ' ', ''
1152
1154
1153 fm.startitem()
1155 fm.startitem()
1154 if not ui.quiet:
1156 if not ui.quiet:
1155 fm.plain(' %s ' % prefix, label=label)
1157 fm.plain(' %s ' % prefix, label=label)
1156 fm.write('bookmark', '%s', bmark, label=label)
1158 fm.write('bookmark', '%s', bmark, label=label)
1157 pad = " " * (25 - encoding.colwidth(bmark))
1159 pad = " " * (25 - encoding.colwidth(bmark))
1158 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1160 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1159 repo.changelog.rev(n), hexfn(n), label=label)
1161 repo.changelog.rev(n), hexfn(n), label=label)
1160 fm.data(active=(bmark == active))
1162 fm.data(active=(bmark == active))
1161 fm.plain('\n')
1163 fm.plain('\n')
1162 fm.end()
1164 fm.end()
1163
1165
1164 @command('branch',
1166 @command('branch',
1165 [('f', 'force', None,
1167 [('f', 'force', None,
1166 _('set branch name even if it shadows an existing branch')),
1168 _('set branch name even if it shadows an existing branch')),
1167 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1169 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1168 _('[-fC] [NAME]'))
1170 _('[-fC] [NAME]'))
1169 def branch(ui, repo, label=None, **opts):
1171 def branch(ui, repo, label=None, **opts):
1170 """set or show the current branch name
1172 """set or show the current branch name
1171
1173
1172 .. note::
1174 .. note::
1173
1175
1174 Branch names are permanent and global. Use :hg:`bookmark` to create a
1176 Branch names are permanent and global. Use :hg:`bookmark` to create a
1175 light-weight bookmark instead. See :hg:`help glossary` for more
1177 light-weight bookmark instead. See :hg:`help glossary` for more
1176 information about named branches and bookmarks.
1178 information about named branches and bookmarks.
1177
1179
1178 With no argument, show the current branch name. With one argument,
1180 With no argument, show the current branch name. With one argument,
1179 set the working directory branch name (the branch will not exist
1181 set the working directory branch name (the branch will not exist
1180 in the repository until the next commit). Standard practice
1182 in the repository until the next commit). Standard practice
1181 recommends that primary development take place on the 'default'
1183 recommends that primary development take place on the 'default'
1182 branch.
1184 branch.
1183
1185
1184 Unless -f/--force is specified, branch will not let you set a
1186 Unless -f/--force is specified, branch will not let you set a
1185 branch name that already exists.
1187 branch name that already exists.
1186
1188
1187 Use -C/--clean to reset the working directory branch to that of
1189 Use -C/--clean to reset the working directory branch to that of
1188 the parent of the working directory, negating a previous branch
1190 the parent of the working directory, negating a previous branch
1189 change.
1191 change.
1190
1192
1191 Use the command :hg:`update` to switch to an existing branch. Use
1193 Use the command :hg:`update` to switch to an existing branch. Use
1192 :hg:`commit --close-branch` to mark this branch head as closed.
1194 :hg:`commit --close-branch` to mark this branch head as closed.
1193 When all heads of a branch are closed, the branch will be
1195 When all heads of a branch are closed, the branch will be
1194 considered closed.
1196 considered closed.
1195
1197
1196 Returns 0 on success.
1198 Returns 0 on success.
1197 """
1199 """
1198 if label:
1200 if label:
1199 label = label.strip()
1201 label = label.strip()
1200
1202
1201 if not opts.get('clean') and not label:
1203 if not opts.get('clean') and not label:
1202 ui.write("%s\n" % repo.dirstate.branch())
1204 ui.write("%s\n" % repo.dirstate.branch())
1203 return
1205 return
1204
1206
1205 with repo.wlock():
1207 with repo.wlock():
1206 if opts.get('clean'):
1208 if opts.get('clean'):
1207 label = repo[None].p1().branch()
1209 label = repo[None].p1().branch()
1208 repo.dirstate.setbranch(label)
1210 repo.dirstate.setbranch(label)
1209 ui.status(_('reset working directory to branch %s\n') % label)
1211 ui.status(_('reset working directory to branch %s\n') % label)
1210 elif label:
1212 elif label:
1211 if not opts.get('force') and label in repo.branchmap():
1213 if not opts.get('force') and label in repo.branchmap():
1212 if label not in [p.branch() for p in repo[None].parents()]:
1214 if label not in [p.branch() for p in repo[None].parents()]:
1213 raise error.Abort(_('a branch of the same name already'
1215 raise error.Abort(_('a branch of the same name already'
1214 ' exists'),
1216 ' exists'),
1215 # i18n: "it" refers to an existing branch
1217 # i18n: "it" refers to an existing branch
1216 hint=_("use 'hg update' to switch to it"))
1218 hint=_("use 'hg update' to switch to it"))
1217 scmutil.checknewlabel(repo, label, 'branch')
1219 scmutil.checknewlabel(repo, label, 'branch')
1218 repo.dirstate.setbranch(label)
1220 repo.dirstate.setbranch(label)
1219 ui.status(_('marked working directory as branch %s\n') % label)
1221 ui.status(_('marked working directory as branch %s\n') % label)
1220
1222
1221 # find any open named branches aside from default
1223 # find any open named branches aside from default
1222 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1224 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1223 if n != "default" and not c]
1225 if n != "default" and not c]
1224 if not others:
1226 if not others:
1225 ui.status(_('(branches are permanent and global, '
1227 ui.status(_('(branches are permanent and global, '
1226 'did you want a bookmark?)\n'))
1228 'did you want a bookmark?)\n'))
1227
1229
1228 @command('branches',
1230 @command('branches',
1229 [('a', 'active', False,
1231 [('a', 'active', False,
1230 _('show only branches that have unmerged heads (DEPRECATED)')),
1232 _('show only branches that have unmerged heads (DEPRECATED)')),
1231 ('c', 'closed', False, _('show normal and closed branches')),
1233 ('c', 'closed', False, _('show normal and closed branches')),
1232 ] + formatteropts,
1234 ] + formatteropts,
1233 _('[-ac]'))
1235 _('[-ac]'))
1234 def branches(ui, repo, active=False, closed=False, **opts):
1236 def branches(ui, repo, active=False, closed=False, **opts):
1235 """list repository named branches
1237 """list repository named branches
1236
1238
1237 List the repository's named branches, indicating which ones are
1239 List the repository's named branches, indicating which ones are
1238 inactive. If -c/--closed is specified, also list branches which have
1240 inactive. If -c/--closed is specified, also list branches which have
1239 been marked closed (see :hg:`commit --close-branch`).
1241 been marked closed (see :hg:`commit --close-branch`).
1240
1242
1241 Use the command :hg:`update` to switch to an existing branch.
1243 Use the command :hg:`update` to switch to an existing branch.
1242
1244
1243 Returns 0.
1245 Returns 0.
1244 """
1246 """
1245
1247
1246 fm = ui.formatter('branches', opts)
1248 fm = ui.formatter('branches', opts)
1247 hexfunc = fm.hexfunc
1249 hexfunc = fm.hexfunc
1248
1250
1249 allheads = set(repo.heads())
1251 allheads = set(repo.heads())
1250 branches = []
1252 branches = []
1251 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1253 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1252 isactive = not isclosed and bool(set(heads) & allheads)
1254 isactive = not isclosed and bool(set(heads) & allheads)
1253 branches.append((tag, repo[tip], isactive, not isclosed))
1255 branches.append((tag, repo[tip], isactive, not isclosed))
1254 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1256 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1255 reverse=True)
1257 reverse=True)
1256
1258
1257 for tag, ctx, isactive, isopen in branches:
1259 for tag, ctx, isactive, isopen in branches:
1258 if active and not isactive:
1260 if active and not isactive:
1259 continue
1261 continue
1260 if isactive:
1262 if isactive:
1261 label = 'branches.active'
1263 label = 'branches.active'
1262 notice = ''
1264 notice = ''
1263 elif not isopen:
1265 elif not isopen:
1264 if not closed:
1266 if not closed:
1265 continue
1267 continue
1266 label = 'branches.closed'
1268 label = 'branches.closed'
1267 notice = _(' (closed)')
1269 notice = _(' (closed)')
1268 else:
1270 else:
1269 label = 'branches.inactive'
1271 label = 'branches.inactive'
1270 notice = _(' (inactive)')
1272 notice = _(' (inactive)')
1271 current = (tag == repo.dirstate.branch())
1273 current = (tag == repo.dirstate.branch())
1272 if current:
1274 if current:
1273 label = 'branches.current'
1275 label = 'branches.current'
1274
1276
1275 fm.startitem()
1277 fm.startitem()
1276 fm.write('branch', '%s', tag, label=label)
1278 fm.write('branch', '%s', tag, label=label)
1277 rev = ctx.rev()
1279 rev = ctx.rev()
1278 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1280 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1279 fmt = ' ' * padsize + ' %d:%s'
1281 fmt = ' ' * padsize + ' %d:%s'
1280 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1282 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1281 label='log.changeset changeset.%s' % ctx.phasestr())
1283 label='log.changeset changeset.%s' % ctx.phasestr())
1282 fm.data(active=isactive, closed=not isopen, current=current)
1284 fm.data(active=isactive, closed=not isopen, current=current)
1283 if not ui.quiet:
1285 if not ui.quiet:
1284 fm.plain(notice)
1286 fm.plain(notice)
1285 fm.plain('\n')
1287 fm.plain('\n')
1286 fm.end()
1288 fm.end()
1287
1289
1288 @command('bundle',
1290 @command('bundle',
1289 [('f', 'force', None, _('run even when the destination is unrelated')),
1291 [('f', 'force', None, _('run even when the destination is unrelated')),
1290 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1292 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1291 _('REV')),
1293 _('REV')),
1292 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1294 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1293 _('BRANCH')),
1295 _('BRANCH')),
1294 ('', 'base', [],
1296 ('', 'base', [],
1295 _('a base changeset assumed to be available at the destination'),
1297 _('a base changeset assumed to be available at the destination'),
1296 _('REV')),
1298 _('REV')),
1297 ('a', 'all', None, _('bundle all changesets in the repository')),
1299 ('a', 'all', None, _('bundle all changesets in the repository')),
1298 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1300 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1299 ] + remoteopts,
1301 ] + remoteopts,
1300 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1302 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1301 def bundle(ui, repo, fname, dest=None, **opts):
1303 def bundle(ui, repo, fname, dest=None, **opts):
1302 """create a changegroup file
1304 """create a changegroup file
1303
1305
1304 Generate a changegroup file collecting changesets to be added
1306 Generate a changegroup file collecting changesets to be added
1305 to a repository.
1307 to a repository.
1306
1308
1307 To create a bundle containing all changesets, use -a/--all
1309 To create a bundle containing all changesets, use -a/--all
1308 (or --base null). Otherwise, hg assumes the destination will have
1310 (or --base null). Otherwise, hg assumes the destination will have
1309 all the nodes you specify with --base parameters. Otherwise, hg
1311 all the nodes you specify with --base parameters. Otherwise, hg
1310 will assume the repository has all the nodes in destination, or
1312 will assume the repository has all the nodes in destination, or
1311 default-push/default if no destination is specified.
1313 default-push/default if no destination is specified.
1312
1314
1313 You can change bundle format with the -t/--type option. You can
1315 You can change bundle format with the -t/--type option. You can
1314 specify a compression, a bundle version or both using a dash
1316 specify a compression, a bundle version or both using a dash
1315 (comp-version). The available compression methods are: none, bzip2,
1317 (comp-version). The available compression methods are: none, bzip2,
1316 and gzip (by default, bundles are compressed using bzip2). The
1318 and gzip (by default, bundles are compressed using bzip2). The
1317 available formats are: v1, v2 (default to most suitable).
1319 available formats are: v1, v2 (default to most suitable).
1318
1320
1319 The bundle file can then be transferred using conventional means
1321 The bundle file can then be transferred using conventional means
1320 and applied to another repository with the unbundle or pull
1322 and applied to another repository with the unbundle or pull
1321 command. This is useful when direct push and pull are not
1323 command. This is useful when direct push and pull are not
1322 available or when exporting an entire repository is undesirable.
1324 available or when exporting an entire repository is undesirable.
1323
1325
1324 Applying bundles preserves all changeset contents including
1326 Applying bundles preserves all changeset contents including
1325 permissions, copy/rename information, and revision history.
1327 permissions, copy/rename information, and revision history.
1326
1328
1327 Returns 0 on success, 1 if no changes found.
1329 Returns 0 on success, 1 if no changes found.
1328 """
1330 """
1329 revs = None
1331 revs = None
1330 if 'rev' in opts:
1332 if 'rev' in opts:
1331 revstrings = opts['rev']
1333 revstrings = opts['rev']
1332 revs = scmutil.revrange(repo, revstrings)
1334 revs = scmutil.revrange(repo, revstrings)
1333 if revstrings and not revs:
1335 if revstrings and not revs:
1334 raise error.Abort(_('no commits to bundle'))
1336 raise error.Abort(_('no commits to bundle'))
1335
1337
1336 bundletype = opts.get('type', 'bzip2').lower()
1338 bundletype = opts.get('type', 'bzip2').lower()
1337 try:
1339 try:
1338 bcompression, cgversion, params = exchange.parsebundlespec(
1340 bcompression, cgversion, params = exchange.parsebundlespec(
1339 repo, bundletype, strict=False)
1341 repo, bundletype, strict=False)
1340 except error.UnsupportedBundleSpecification as e:
1342 except error.UnsupportedBundleSpecification as e:
1341 raise error.Abort(str(e),
1343 raise error.Abort(str(e),
1342 hint=_('see "hg help bundle" for supported '
1344 hint=_('see "hg help bundle" for supported '
1343 'values for --type'))
1345 'values for --type'))
1344
1346
1345 # Packed bundles are a pseudo bundle format for now.
1347 # Packed bundles are a pseudo bundle format for now.
1346 if cgversion == 's1':
1348 if cgversion == 's1':
1347 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1349 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1348 hint=_('use "hg debugcreatestreamclonebundle"'))
1350 hint=_('use "hg debugcreatestreamclonebundle"'))
1349
1351
1350 if opts.get('all'):
1352 if opts.get('all'):
1351 if dest:
1353 if dest:
1352 raise error.Abort(_("--all is incompatible with specifying "
1354 raise error.Abort(_("--all is incompatible with specifying "
1353 "a destination"))
1355 "a destination"))
1354 if opts.get('base'):
1356 if opts.get('base'):
1355 ui.warn(_("ignoring --base because --all was specified\n"))
1357 ui.warn(_("ignoring --base because --all was specified\n"))
1356 base = ['null']
1358 base = ['null']
1357 else:
1359 else:
1358 base = scmutil.revrange(repo, opts.get('base'))
1360 base = scmutil.revrange(repo, opts.get('base'))
1359 # TODO: get desired bundlecaps from command line.
1361 # TODO: get desired bundlecaps from command line.
1360 bundlecaps = None
1362 bundlecaps = None
1361 if base:
1363 if base:
1362 if dest:
1364 if dest:
1363 raise error.Abort(_("--base is incompatible with specifying "
1365 raise error.Abort(_("--base is incompatible with specifying "
1364 "a destination"))
1366 "a destination"))
1365 common = [repo.lookup(rev) for rev in base]
1367 common = [repo.lookup(rev) for rev in base]
1366 heads = revs and map(repo.lookup, revs) or revs
1368 heads = revs and map(repo.lookup, revs) or revs
1367 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1369 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1368 common=common, bundlecaps=bundlecaps,
1370 common=common, bundlecaps=bundlecaps,
1369 version=cgversion)
1371 version=cgversion)
1370 outgoing = None
1372 outgoing = None
1371 else:
1373 else:
1372 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1374 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1373 dest, branches = hg.parseurl(dest, opts.get('branch'))
1375 dest, branches = hg.parseurl(dest, opts.get('branch'))
1374 other = hg.peer(repo, opts, dest)
1376 other = hg.peer(repo, opts, dest)
1375 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1377 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1376 heads = revs and map(repo.lookup, revs) or revs
1378 heads = revs and map(repo.lookup, revs) or revs
1377 outgoing = discovery.findcommonoutgoing(repo, other,
1379 outgoing = discovery.findcommonoutgoing(repo, other,
1378 onlyheads=heads,
1380 onlyheads=heads,
1379 force=opts.get('force'),
1381 force=opts.get('force'),
1380 portable=True)
1382 portable=True)
1381 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1383 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1382 bundlecaps, version=cgversion)
1384 bundlecaps, version=cgversion)
1383 if not cg:
1385 if not cg:
1384 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1386 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1385 return 1
1387 return 1
1386
1388
1387 if cgversion == '01': #bundle1
1389 if cgversion == '01': #bundle1
1388 if bcompression is None:
1390 if bcompression is None:
1389 bcompression = 'UN'
1391 bcompression = 'UN'
1390 bversion = 'HG10' + bcompression
1392 bversion = 'HG10' + bcompression
1391 bcompression = None
1393 bcompression = None
1392 else:
1394 else:
1393 assert cgversion == '02'
1395 assert cgversion == '02'
1394 bversion = 'HG20'
1396 bversion = 'HG20'
1395
1397
1396
1398
1397 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1399 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1398
1400
1399 @command('cat',
1401 @command('cat',
1400 [('o', 'output', '',
1402 [('o', 'output', '',
1401 _('print output to file with formatted name'), _('FORMAT')),
1403 _('print output to file with formatted name'), _('FORMAT')),
1402 ('r', 'rev', '', _('print the given revision'), _('REV')),
1404 ('r', 'rev', '', _('print the given revision'), _('REV')),
1403 ('', 'decode', None, _('apply any matching decode filter')),
1405 ('', 'decode', None, _('apply any matching decode filter')),
1404 ] + walkopts,
1406 ] + walkopts,
1405 _('[OPTION]... FILE...'),
1407 _('[OPTION]... FILE...'),
1406 inferrepo=True)
1408 inferrepo=True)
1407 def cat(ui, repo, file1, *pats, **opts):
1409 def cat(ui, repo, file1, *pats, **opts):
1408 """output the current or given revision of files
1410 """output the current or given revision of files
1409
1411
1410 Print the specified files as they were at the given revision. If
1412 Print the specified files as they were at the given revision. If
1411 no revision is given, the parent of the working directory is used.
1413 no revision is given, the parent of the working directory is used.
1412
1414
1413 Output may be to a file, in which case the name of the file is
1415 Output may be to a file, in which case the name of the file is
1414 given using a format string. The formatting rules as follows:
1416 given using a format string. The formatting rules as follows:
1415
1417
1416 :``%%``: literal "%" character
1418 :``%%``: literal "%" character
1417 :``%s``: basename of file being printed
1419 :``%s``: basename of file being printed
1418 :``%d``: dirname of file being printed, or '.' if in repository root
1420 :``%d``: dirname of file being printed, or '.' if in repository root
1419 :``%p``: root-relative path name of file being printed
1421 :``%p``: root-relative path name of file being printed
1420 :``%H``: changeset hash (40 hexadecimal digits)
1422 :``%H``: changeset hash (40 hexadecimal digits)
1421 :``%R``: changeset revision number
1423 :``%R``: changeset revision number
1422 :``%h``: short-form changeset hash (12 hexadecimal digits)
1424 :``%h``: short-form changeset hash (12 hexadecimal digits)
1423 :``%r``: zero-padded changeset revision number
1425 :``%r``: zero-padded changeset revision number
1424 :``%b``: basename of the exporting repository
1426 :``%b``: basename of the exporting repository
1425
1427
1426 Returns 0 on success.
1428 Returns 0 on success.
1427 """
1429 """
1428 ctx = scmutil.revsingle(repo, opts.get('rev'))
1430 ctx = scmutil.revsingle(repo, opts.get('rev'))
1429 m = scmutil.match(ctx, (file1,) + pats, opts)
1431 m = scmutil.match(ctx, (file1,) + pats, opts)
1430
1432
1431 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1433 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1432
1434
1433 @command('^clone',
1435 @command('^clone',
1434 [('U', 'noupdate', None, _('the clone will include an empty working '
1436 [('U', 'noupdate', None, _('the clone will include an empty working '
1435 'directory (only a repository)')),
1437 'directory (only a repository)')),
1436 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1438 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1437 _('REV')),
1439 _('REV')),
1438 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1440 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1439 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1441 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1440 ('', 'pull', None, _('use pull protocol to copy metadata')),
1442 ('', 'pull', None, _('use pull protocol to copy metadata')),
1441 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1443 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1442 ] + remoteopts,
1444 ] + remoteopts,
1443 _('[OPTION]... SOURCE [DEST]'),
1445 _('[OPTION]... SOURCE [DEST]'),
1444 norepo=True)
1446 norepo=True)
1445 def clone(ui, source, dest=None, **opts):
1447 def clone(ui, source, dest=None, **opts):
1446 """make a copy of an existing repository
1448 """make a copy of an existing repository
1447
1449
1448 Create a copy of an existing repository in a new directory.
1450 Create a copy of an existing repository in a new directory.
1449
1451
1450 If no destination directory name is specified, it defaults to the
1452 If no destination directory name is specified, it defaults to the
1451 basename of the source.
1453 basename of the source.
1452
1454
1453 The location of the source is added to the new repository's
1455 The location of the source is added to the new repository's
1454 ``.hg/hgrc`` file, as the default to be used for future pulls.
1456 ``.hg/hgrc`` file, as the default to be used for future pulls.
1455
1457
1456 Only local paths and ``ssh://`` URLs are supported as
1458 Only local paths and ``ssh://`` URLs are supported as
1457 destinations. For ``ssh://`` destinations, no working directory or
1459 destinations. For ``ssh://`` destinations, no working directory or
1458 ``.hg/hgrc`` will be created on the remote side.
1460 ``.hg/hgrc`` will be created on the remote side.
1459
1461
1460 If the source repository has a bookmark called '@' set, that
1462 If the source repository has a bookmark called '@' set, that
1461 revision will be checked out in the new repository by default.
1463 revision will be checked out in the new repository by default.
1462
1464
1463 To check out a particular version, use -u/--update, or
1465 To check out a particular version, use -u/--update, or
1464 -U/--noupdate to create a clone with no working directory.
1466 -U/--noupdate to create a clone with no working directory.
1465
1467
1466 To pull only a subset of changesets, specify one or more revisions
1468 To pull only a subset of changesets, specify one or more revisions
1467 identifiers with -r/--rev or branches with -b/--branch. The
1469 identifiers with -r/--rev or branches with -b/--branch. The
1468 resulting clone will contain only the specified changesets and
1470 resulting clone will contain only the specified changesets and
1469 their ancestors. These options (or 'clone src#rev dest') imply
1471 their ancestors. These options (or 'clone src#rev dest') imply
1470 --pull, even for local source repositories.
1472 --pull, even for local source repositories.
1471
1473
1472 .. note::
1474 .. note::
1473
1475
1474 Specifying a tag will include the tagged changeset but not the
1476 Specifying a tag will include the tagged changeset but not the
1475 changeset containing the tag.
1477 changeset containing the tag.
1476
1478
1477 .. container:: verbose
1479 .. container:: verbose
1478
1480
1479 For efficiency, hardlinks are used for cloning whenever the
1481 For efficiency, hardlinks are used for cloning whenever the
1480 source and destination are on the same filesystem (note this
1482 source and destination are on the same filesystem (note this
1481 applies only to the repository data, not to the working
1483 applies only to the repository data, not to the working
1482 directory). Some filesystems, such as AFS, implement hardlinking
1484 directory). Some filesystems, such as AFS, implement hardlinking
1483 incorrectly, but do not report errors. In these cases, use the
1485 incorrectly, but do not report errors. In these cases, use the
1484 --pull option to avoid hardlinking.
1486 --pull option to avoid hardlinking.
1485
1487
1486 In some cases, you can clone repositories and the working
1488 In some cases, you can clone repositories and the working
1487 directory using full hardlinks with ::
1489 directory using full hardlinks with ::
1488
1490
1489 $ cp -al REPO REPOCLONE
1491 $ cp -al REPO REPOCLONE
1490
1492
1491 This is the fastest way to clone, but it is not always safe. The
1493 This is the fastest way to clone, but it is not always safe. The
1492 operation is not atomic (making sure REPO is not modified during
1494 operation is not atomic (making sure REPO is not modified during
1493 the operation is up to you) and you have to make sure your
1495 the operation is up to you) and you have to make sure your
1494 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1496 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1495 so). Also, this is not compatible with certain extensions that
1497 so). Also, this is not compatible with certain extensions that
1496 place their metadata under the .hg directory, such as mq.
1498 place their metadata under the .hg directory, such as mq.
1497
1499
1498 Mercurial will update the working directory to the first applicable
1500 Mercurial will update the working directory to the first applicable
1499 revision from this list:
1501 revision from this list:
1500
1502
1501 a) null if -U or the source repository has no changesets
1503 a) null if -U or the source repository has no changesets
1502 b) if -u . and the source repository is local, the first parent of
1504 b) if -u . and the source repository is local, the first parent of
1503 the source repository's working directory
1505 the source repository's working directory
1504 c) the changeset specified with -u (if a branch name, this means the
1506 c) the changeset specified with -u (if a branch name, this means the
1505 latest head of that branch)
1507 latest head of that branch)
1506 d) the changeset specified with -r
1508 d) the changeset specified with -r
1507 e) the tipmost head specified with -b
1509 e) the tipmost head specified with -b
1508 f) the tipmost head specified with the url#branch source syntax
1510 f) the tipmost head specified with the url#branch source syntax
1509 g) the revision marked with the '@' bookmark, if present
1511 g) the revision marked with the '@' bookmark, if present
1510 h) the tipmost head of the default branch
1512 h) the tipmost head of the default branch
1511 i) tip
1513 i) tip
1512
1514
1513 When cloning from servers that support it, Mercurial may fetch
1515 When cloning from servers that support it, Mercurial may fetch
1514 pre-generated data from a server-advertised URL. When this is done,
1516 pre-generated data from a server-advertised URL. When this is done,
1515 hooks operating on incoming changesets and changegroups may fire twice,
1517 hooks operating on incoming changesets and changegroups may fire twice,
1516 once for the bundle fetched from the URL and another for any additional
1518 once for the bundle fetched from the URL and another for any additional
1517 data not fetched from this URL. In addition, if an error occurs, the
1519 data not fetched from this URL. In addition, if an error occurs, the
1518 repository may be rolled back to a partial clone. This behavior may
1520 repository may be rolled back to a partial clone. This behavior may
1519 change in future releases. See :hg:`help -e clonebundles` for more.
1521 change in future releases. See :hg:`help -e clonebundles` for more.
1520
1522
1521 Examples:
1523 Examples:
1522
1524
1523 - clone a remote repository to a new directory named hg/::
1525 - clone a remote repository to a new directory named hg/::
1524
1526
1525 hg clone http://selenic.com/hg
1527 hg clone http://selenic.com/hg
1526
1528
1527 - create a lightweight local clone::
1529 - create a lightweight local clone::
1528
1530
1529 hg clone project/ project-feature/
1531 hg clone project/ project-feature/
1530
1532
1531 - clone from an absolute path on an ssh server (note double-slash)::
1533 - clone from an absolute path on an ssh server (note double-slash)::
1532
1534
1533 hg clone ssh://user@server//home/projects/alpha/
1535 hg clone ssh://user@server//home/projects/alpha/
1534
1536
1535 - do a high-speed clone over a LAN while checking out a
1537 - do a high-speed clone over a LAN while checking out a
1536 specified version::
1538 specified version::
1537
1539
1538 hg clone --uncompressed http://server/repo -u 1.5
1540 hg clone --uncompressed http://server/repo -u 1.5
1539
1541
1540 - create a repository without changesets after a particular revision::
1542 - create a repository without changesets after a particular revision::
1541
1543
1542 hg clone -r 04e544 experimental/ good/
1544 hg clone -r 04e544 experimental/ good/
1543
1545
1544 - clone (and track) a particular named branch::
1546 - clone (and track) a particular named branch::
1545
1547
1546 hg clone http://selenic.com/hg#stable
1548 hg clone http://selenic.com/hg#stable
1547
1549
1548 See :hg:`help urls` for details on specifying URLs.
1550 See :hg:`help urls` for details on specifying URLs.
1549
1551
1550 Returns 0 on success.
1552 Returns 0 on success.
1551 """
1553 """
1552 if opts.get('noupdate') and opts.get('updaterev'):
1554 if opts.get('noupdate') and opts.get('updaterev'):
1553 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1555 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1554
1556
1555 r = hg.clone(ui, opts, source, dest,
1557 r = hg.clone(ui, opts, source, dest,
1556 pull=opts.get('pull'),
1558 pull=opts.get('pull'),
1557 stream=opts.get('uncompressed'),
1559 stream=opts.get('uncompressed'),
1558 rev=opts.get('rev'),
1560 rev=opts.get('rev'),
1559 update=opts.get('updaterev') or not opts.get('noupdate'),
1561 update=opts.get('updaterev') or not opts.get('noupdate'),
1560 branch=opts.get('branch'),
1562 branch=opts.get('branch'),
1561 shareopts=opts.get('shareopts'))
1563 shareopts=opts.get('shareopts'))
1562
1564
1563 return r is None
1565 return r is None
1564
1566
1565 @command('^commit|ci',
1567 @command('^commit|ci',
1566 [('A', 'addremove', None,
1568 [('A', 'addremove', None,
1567 _('mark new/missing files as added/removed before committing')),
1569 _('mark new/missing files as added/removed before committing')),
1568 ('', 'close-branch', None,
1570 ('', 'close-branch', None,
1569 _('mark a branch head as closed')),
1571 _('mark a branch head as closed')),
1570 ('', 'amend', None, _('amend the parent of the working directory')),
1572 ('', 'amend', None, _('amend the parent of the working directory')),
1571 ('s', 'secret', None, _('use the secret phase for committing')),
1573 ('s', 'secret', None, _('use the secret phase for committing')),
1572 ('e', 'edit', None, _('invoke editor on commit messages')),
1574 ('e', 'edit', None, _('invoke editor on commit messages')),
1573 ('i', 'interactive', None, _('use interactive mode')),
1575 ('i', 'interactive', None, _('use interactive mode')),
1574 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1576 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1575 _('[OPTION]... [FILE]...'),
1577 _('[OPTION]... [FILE]...'),
1576 inferrepo=True)
1578 inferrepo=True)
1577 def commit(ui, repo, *pats, **opts):
1579 def commit(ui, repo, *pats, **opts):
1578 """commit the specified files or all outstanding changes
1580 """commit the specified files or all outstanding changes
1579
1581
1580 Commit changes to the given files into the repository. Unlike a
1582 Commit changes to the given files into the repository. Unlike a
1581 centralized SCM, this operation is a local operation. See
1583 centralized SCM, this operation is a local operation. See
1582 :hg:`push` for a way to actively distribute your changes.
1584 :hg:`push` for a way to actively distribute your changes.
1583
1585
1584 If a list of files is omitted, all changes reported by :hg:`status`
1586 If a list of files is omitted, all changes reported by :hg:`status`
1585 will be committed.
1587 will be committed.
1586
1588
1587 If you are committing the result of a merge, do not provide any
1589 If you are committing the result of a merge, do not provide any
1588 filenames or -I/-X filters.
1590 filenames or -I/-X filters.
1589
1591
1590 If no commit message is specified, Mercurial starts your
1592 If no commit message is specified, Mercurial starts your
1591 configured editor where you can enter a message. In case your
1593 configured editor where you can enter a message. In case your
1592 commit fails, you will find a backup of your message in
1594 commit fails, you will find a backup of your message in
1593 ``.hg/last-message.txt``.
1595 ``.hg/last-message.txt``.
1594
1596
1595 The --close-branch flag can be used to mark the current branch
1597 The --close-branch flag can be used to mark the current branch
1596 head closed. When all heads of a branch are closed, the branch
1598 head closed. When all heads of a branch are closed, the branch
1597 will be considered closed and no longer listed.
1599 will be considered closed and no longer listed.
1598
1600
1599 The --amend flag can be used to amend the parent of the
1601 The --amend flag can be used to amend the parent of the
1600 working directory with a new commit that contains the changes
1602 working directory with a new commit that contains the changes
1601 in the parent in addition to those currently reported by :hg:`status`,
1603 in the parent in addition to those currently reported by :hg:`status`,
1602 if there are any. The old commit is stored in a backup bundle in
1604 if there are any. The old commit is stored in a backup bundle in
1603 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1605 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1604 on how to restore it).
1606 on how to restore it).
1605
1607
1606 Message, user and date are taken from the amended commit unless
1608 Message, user and date are taken from the amended commit unless
1607 specified. When a message isn't specified on the command line,
1609 specified. When a message isn't specified on the command line,
1608 the editor will open with the message of the amended commit.
1610 the editor will open with the message of the amended commit.
1609
1611
1610 It is not possible to amend public changesets (see :hg:`help phases`)
1612 It is not possible to amend public changesets (see :hg:`help phases`)
1611 or changesets that have children.
1613 or changesets that have children.
1612
1614
1613 See :hg:`help dates` for a list of formats valid for -d/--date.
1615 See :hg:`help dates` for a list of formats valid for -d/--date.
1614
1616
1615 Returns 0 on success, 1 if nothing changed.
1617 Returns 0 on success, 1 if nothing changed.
1616
1618
1617 .. container:: verbose
1619 .. container:: verbose
1618
1620
1619 Examples:
1621 Examples:
1620
1622
1621 - commit all files ending in .py::
1623 - commit all files ending in .py::
1622
1624
1623 hg commit --include "set:**.py"
1625 hg commit --include "set:**.py"
1624
1626
1625 - commit all non-binary files::
1627 - commit all non-binary files::
1626
1628
1627 hg commit --exclude "set:binary()"
1629 hg commit --exclude "set:binary()"
1628
1630
1629 - amend the current commit and set the date to now::
1631 - amend the current commit and set the date to now::
1630
1632
1631 hg commit --amend --date now
1633 hg commit --amend --date now
1632 """
1634 """
1633 wlock = lock = None
1635 wlock = lock = None
1634 try:
1636 try:
1635 wlock = repo.wlock()
1637 wlock = repo.wlock()
1636 lock = repo.lock()
1638 lock = repo.lock()
1637 return _docommit(ui, repo, *pats, **opts)
1639 return _docommit(ui, repo, *pats, **opts)
1638 finally:
1640 finally:
1639 release(lock, wlock)
1641 release(lock, wlock)
1640
1642
1641 def _docommit(ui, repo, *pats, **opts):
1643 def _docommit(ui, repo, *pats, **opts):
1642 if opts.get('interactive'):
1644 if opts.get('interactive'):
1643 opts.pop('interactive')
1645 opts.pop('interactive')
1644 cmdutil.dorecord(ui, repo, commit, None, False,
1646 cmdutil.dorecord(ui, repo, commit, None, False,
1645 cmdutil.recordfilter, *pats, **opts)
1647 cmdutil.recordfilter, *pats, **opts)
1646 return
1648 return
1647
1649
1648 if opts.get('subrepos'):
1650 if opts.get('subrepos'):
1649 if opts.get('amend'):
1651 if opts.get('amend'):
1650 raise error.Abort(_('cannot amend with --subrepos'))
1652 raise error.Abort(_('cannot amend with --subrepos'))
1651 # Let --subrepos on the command line override config setting.
1653 # Let --subrepos on the command line override config setting.
1652 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1654 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1653
1655
1654 cmdutil.checkunfinished(repo, commit=True)
1656 cmdutil.checkunfinished(repo, commit=True)
1655
1657
1656 branch = repo[None].branch()
1658 branch = repo[None].branch()
1657 bheads = repo.branchheads(branch)
1659 bheads = repo.branchheads(branch)
1658
1660
1659 extra = {}
1661 extra = {}
1660 if opts.get('close_branch'):
1662 if opts.get('close_branch'):
1661 extra['close'] = 1
1663 extra['close'] = 1
1662
1664
1663 if not bheads:
1665 if not bheads:
1664 raise error.Abort(_('can only close branch heads'))
1666 raise error.Abort(_('can only close branch heads'))
1665 elif opts.get('amend'):
1667 elif opts.get('amend'):
1666 if repo[None].parents()[0].p1().branch() != branch and \
1668 if repo[None].parents()[0].p1().branch() != branch and \
1667 repo[None].parents()[0].p2().branch() != branch:
1669 repo[None].parents()[0].p2().branch() != branch:
1668 raise error.Abort(_('can only close branch heads'))
1670 raise error.Abort(_('can only close branch heads'))
1669
1671
1670 if opts.get('amend'):
1672 if opts.get('amend'):
1671 if ui.configbool('ui', 'commitsubrepos'):
1673 if ui.configbool('ui', 'commitsubrepos'):
1672 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1674 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1673
1675
1674 old = repo['.']
1676 old = repo['.']
1675 if not old.mutable():
1677 if not old.mutable():
1676 raise error.Abort(_('cannot amend public changesets'))
1678 raise error.Abort(_('cannot amend public changesets'))
1677 if len(repo[None].parents()) > 1:
1679 if len(repo[None].parents()) > 1:
1678 raise error.Abort(_('cannot amend while merging'))
1680 raise error.Abort(_('cannot amend while merging'))
1679 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1681 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1680 if not allowunstable and old.children():
1682 if not allowunstable and old.children():
1681 raise error.Abort(_('cannot amend changeset with children'))
1683 raise error.Abort(_('cannot amend changeset with children'))
1682
1684
1683 newextra = extra.copy()
1685 newextra = extra.copy()
1684 newextra['branch'] = branch
1686 newextra['branch'] = branch
1685 extra = newextra
1687 extra = newextra
1686 # commitfunc is used only for temporary amend commit by cmdutil.amend
1688 # commitfunc is used only for temporary amend commit by cmdutil.amend
1687 def commitfunc(ui, repo, message, match, opts):
1689 def commitfunc(ui, repo, message, match, opts):
1688 return repo.commit(message,
1690 return repo.commit(message,
1689 opts.get('user') or old.user(),
1691 opts.get('user') or old.user(),
1690 opts.get('date') or old.date(),
1692 opts.get('date') or old.date(),
1691 match,
1693 match,
1692 extra=extra)
1694 extra=extra)
1693
1695
1694 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1696 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1695 if node == old.node():
1697 if node == old.node():
1696 ui.status(_("nothing changed\n"))
1698 ui.status(_("nothing changed\n"))
1697 return 1
1699 return 1
1698 else:
1700 else:
1699 def commitfunc(ui, repo, message, match, opts):
1701 def commitfunc(ui, repo, message, match, opts):
1700 backup = ui.backupconfig('phases', 'new-commit')
1702 backup = ui.backupconfig('phases', 'new-commit')
1701 baseui = repo.baseui
1703 baseui = repo.baseui
1702 basebackup = baseui.backupconfig('phases', 'new-commit')
1704 basebackup = baseui.backupconfig('phases', 'new-commit')
1703 try:
1705 try:
1704 if opts.get('secret'):
1706 if opts.get('secret'):
1705 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1707 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1706 # Propagate to subrepos
1708 # Propagate to subrepos
1707 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1709 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1708
1710
1709 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1711 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1710 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1712 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1711 return repo.commit(message, opts.get('user'), opts.get('date'),
1713 return repo.commit(message, opts.get('user'), opts.get('date'),
1712 match,
1714 match,
1713 editor=editor,
1715 editor=editor,
1714 extra=extra)
1716 extra=extra)
1715 finally:
1717 finally:
1716 ui.restoreconfig(backup)
1718 ui.restoreconfig(backup)
1717 repo.baseui.restoreconfig(basebackup)
1719 repo.baseui.restoreconfig(basebackup)
1718
1720
1719
1721
1720 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1722 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1721
1723
1722 if not node:
1724 if not node:
1723 stat = cmdutil.postcommitstatus(repo, pats, opts)
1725 stat = cmdutil.postcommitstatus(repo, pats, opts)
1724 if stat[3]:
1726 if stat[3]:
1725 ui.status(_("nothing changed (%d missing files, see "
1727 ui.status(_("nothing changed (%d missing files, see "
1726 "'hg status')\n") % len(stat[3]))
1728 "'hg status')\n") % len(stat[3]))
1727 else:
1729 else:
1728 ui.status(_("nothing changed\n"))
1730 ui.status(_("nothing changed\n"))
1729 return 1
1731 return 1
1730
1732
1731 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1733 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1732
1734
1733 @command('config|showconfig|debugconfig',
1735 @command('config|showconfig|debugconfig',
1734 [('u', 'untrusted', None, _('show untrusted configuration options')),
1736 [('u', 'untrusted', None, _('show untrusted configuration options')),
1735 ('e', 'edit', None, _('edit user config')),
1737 ('e', 'edit', None, _('edit user config')),
1736 ('l', 'local', None, _('edit repository config')),
1738 ('l', 'local', None, _('edit repository config')),
1737 ('g', 'global', None, _('edit global config'))],
1739 ('g', 'global', None, _('edit global config'))],
1738 _('[-u] [NAME]...'),
1740 _('[-u] [NAME]...'),
1739 optionalrepo=True)
1741 optionalrepo=True)
1740 def config(ui, repo, *values, **opts):
1742 def config(ui, repo, *values, **opts):
1741 """show combined config settings from all hgrc files
1743 """show combined config settings from all hgrc files
1742
1744
1743 With no arguments, print names and values of all config items.
1745 With no arguments, print names and values of all config items.
1744
1746
1745 With one argument of the form section.name, print just the value
1747 With one argument of the form section.name, print just the value
1746 of that config item.
1748 of that config item.
1747
1749
1748 With multiple arguments, print names and values of all config
1750 With multiple arguments, print names and values of all config
1749 items with matching section names.
1751 items with matching section names.
1750
1752
1751 With --edit, start an editor on the user-level config file. With
1753 With --edit, start an editor on the user-level config file. With
1752 --global, edit the system-wide config file. With --local, edit the
1754 --global, edit the system-wide config file. With --local, edit the
1753 repository-level config file.
1755 repository-level config file.
1754
1756
1755 With --debug, the source (filename and line number) is printed
1757 With --debug, the source (filename and line number) is printed
1756 for each config item.
1758 for each config item.
1757
1759
1758 See :hg:`help config` for more information about config files.
1760 See :hg:`help config` for more information about config files.
1759
1761
1760 Returns 0 on success, 1 if NAME does not exist.
1762 Returns 0 on success, 1 if NAME does not exist.
1761
1763
1762 """
1764 """
1763
1765
1764 if opts.get('edit') or opts.get('local') or opts.get('global'):
1766 if opts.get('edit') or opts.get('local') or opts.get('global'):
1765 if opts.get('local') and opts.get('global'):
1767 if opts.get('local') and opts.get('global'):
1766 raise error.Abort(_("can't use --local and --global together"))
1768 raise error.Abort(_("can't use --local and --global together"))
1767
1769
1768 if opts.get('local'):
1770 if opts.get('local'):
1769 if not repo:
1771 if not repo:
1770 raise error.Abort(_("can't use --local outside a repository"))
1772 raise error.Abort(_("can't use --local outside a repository"))
1771 paths = [repo.join('hgrc')]
1773 paths = [repo.join('hgrc')]
1772 elif opts.get('global'):
1774 elif opts.get('global'):
1773 paths = scmutil.systemrcpath()
1775 paths = scmutil.systemrcpath()
1774 else:
1776 else:
1775 paths = scmutil.userrcpath()
1777 paths = scmutil.userrcpath()
1776
1778
1777 for f in paths:
1779 for f in paths:
1778 if os.path.exists(f):
1780 if os.path.exists(f):
1779 break
1781 break
1780 else:
1782 else:
1781 if opts.get('global'):
1783 if opts.get('global'):
1782 samplehgrc = uimod.samplehgrcs['global']
1784 samplehgrc = uimod.samplehgrcs['global']
1783 elif opts.get('local'):
1785 elif opts.get('local'):
1784 samplehgrc = uimod.samplehgrcs['local']
1786 samplehgrc = uimod.samplehgrcs['local']
1785 else:
1787 else:
1786 samplehgrc = uimod.samplehgrcs['user']
1788 samplehgrc = uimod.samplehgrcs['user']
1787
1789
1788 f = paths[0]
1790 f = paths[0]
1789 fp = open(f, "w")
1791 fp = open(f, "w")
1790 fp.write(samplehgrc)
1792 fp.write(samplehgrc)
1791 fp.close()
1793 fp.close()
1792
1794
1793 editor = ui.geteditor()
1795 editor = ui.geteditor()
1794 ui.system("%s \"%s\"" % (editor, f),
1796 ui.system("%s \"%s\"" % (editor, f),
1795 onerr=error.Abort, errprefix=_("edit failed"))
1797 onerr=error.Abort, errprefix=_("edit failed"))
1796 return
1798 return
1797
1799
1798 for f in scmutil.rcpath():
1800 for f in scmutil.rcpath():
1799 ui.debug('read config from: %s\n' % f)
1801 ui.debug('read config from: %s\n' % f)
1800 untrusted = bool(opts.get('untrusted'))
1802 untrusted = bool(opts.get('untrusted'))
1801 if values:
1803 if values:
1802 sections = [v for v in values if '.' not in v]
1804 sections = [v for v in values if '.' not in v]
1803 items = [v for v in values if '.' in v]
1805 items = [v for v in values if '.' in v]
1804 if len(items) > 1 or items and sections:
1806 if len(items) > 1 or items and sections:
1805 raise error.Abort(_('only one config item permitted'))
1807 raise error.Abort(_('only one config item permitted'))
1806 matched = False
1808 matched = False
1807 for section, name, value in ui.walkconfig(untrusted=untrusted):
1809 for section, name, value in ui.walkconfig(untrusted=untrusted):
1808 value = str(value).replace('\n', '\\n')
1810 value = str(value).replace('\n', '\\n')
1809 sectname = section + '.' + name
1811 sectname = section + '.' + name
1810 if values:
1812 if values:
1811 for v in values:
1813 for v in values:
1812 if v == section:
1814 if v == section:
1813 ui.debug('%s: ' %
1815 ui.debug('%s: ' %
1814 ui.configsource(section, name, untrusted))
1816 ui.configsource(section, name, untrusted))
1815 ui.write('%s=%s\n' % (sectname, value))
1817 ui.write('%s=%s\n' % (sectname, value))
1816 matched = True
1818 matched = True
1817 elif v == sectname:
1819 elif v == sectname:
1818 ui.debug('%s: ' %
1820 ui.debug('%s: ' %
1819 ui.configsource(section, name, untrusted))
1821 ui.configsource(section, name, untrusted))
1820 ui.write(value, '\n')
1822 ui.write(value, '\n')
1821 matched = True
1823 matched = True
1822 else:
1824 else:
1823 ui.debug('%s: ' %
1825 ui.debug('%s: ' %
1824 ui.configsource(section, name, untrusted))
1826 ui.configsource(section, name, untrusted))
1825 ui.write('%s=%s\n' % (sectname, value))
1827 ui.write('%s=%s\n' % (sectname, value))
1826 matched = True
1828 matched = True
1827 if matched:
1829 if matched:
1828 return 0
1830 return 0
1829 return 1
1831 return 1
1830
1832
1831 @command('copy|cp',
1833 @command('copy|cp',
1832 [('A', 'after', None, _('record a copy that has already occurred')),
1834 [('A', 'after', None, _('record a copy that has already occurred')),
1833 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1834 ] + walkopts + dryrunopts,
1836 ] + walkopts + dryrunopts,
1835 _('[OPTION]... [SOURCE]... DEST'))
1837 _('[OPTION]... [SOURCE]... DEST'))
1836 def copy(ui, repo, *pats, **opts):
1838 def copy(ui, repo, *pats, **opts):
1837 """mark files as copied for the next commit
1839 """mark files as copied for the next commit
1838
1840
1839 Mark dest as having copies of source files. If dest is a
1841 Mark dest as having copies of source files. If dest is a
1840 directory, copies are put in that directory. If dest is a file,
1842 directory, copies are put in that directory. If dest is a file,
1841 the source must be a single file.
1843 the source must be a single file.
1842
1844
1843 By default, this command copies the contents of files as they
1845 By default, this command copies the contents of files as they
1844 exist in the working directory. If invoked with -A/--after, the
1846 exist in the working directory. If invoked with -A/--after, the
1845 operation is recorded, but no copying is performed.
1847 operation is recorded, but no copying is performed.
1846
1848
1847 This command takes effect with the next commit. To undo a copy
1849 This command takes effect with the next commit. To undo a copy
1848 before that, see :hg:`revert`.
1850 before that, see :hg:`revert`.
1849
1851
1850 Returns 0 on success, 1 if errors are encountered.
1852 Returns 0 on success, 1 if errors are encountered.
1851 """
1853 """
1852 with repo.wlock(False):
1854 with repo.wlock(False):
1853 return cmdutil.copy(ui, repo, pats, opts)
1855 return cmdutil.copy(ui, repo, pats, opts)
1854
1856
1855 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1857 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1856 def debugancestor(ui, repo, *args):
1858 def debugancestor(ui, repo, *args):
1857 """find the ancestor revision of two revisions in a given index"""
1859 """find the ancestor revision of two revisions in a given index"""
1858 if len(args) == 3:
1860 if len(args) == 3:
1859 index, rev1, rev2 = args
1861 index, rev1, rev2 = args
1860 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1862 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1861 lookup = r.lookup
1863 lookup = r.lookup
1862 elif len(args) == 2:
1864 elif len(args) == 2:
1863 if not repo:
1865 if not repo:
1864 raise error.Abort(_("there is no Mercurial repository here "
1866 raise error.Abort(_("there is no Mercurial repository here "
1865 "(.hg not found)"))
1867 "(.hg not found)"))
1866 rev1, rev2 = args
1868 rev1, rev2 = args
1867 r = repo.changelog
1869 r = repo.changelog
1868 lookup = repo.lookup
1870 lookup = repo.lookup
1869 else:
1871 else:
1870 raise error.Abort(_('either two or three arguments required'))
1872 raise error.Abort(_('either two or three arguments required'))
1871 a = r.ancestor(lookup(rev1), lookup(rev2))
1873 a = r.ancestor(lookup(rev1), lookup(rev2))
1872 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1874 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1873
1875
1874 @command('debugbuilddag',
1876 @command('debugbuilddag',
1875 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1877 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1876 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1878 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1877 ('n', 'new-file', None, _('add new file at each rev'))],
1879 ('n', 'new-file', None, _('add new file at each rev'))],
1878 _('[OPTION]... [TEXT]'))
1880 _('[OPTION]... [TEXT]'))
1879 def debugbuilddag(ui, repo, text=None,
1881 def debugbuilddag(ui, repo, text=None,
1880 mergeable_file=False,
1882 mergeable_file=False,
1881 overwritten_file=False,
1883 overwritten_file=False,
1882 new_file=False):
1884 new_file=False):
1883 """builds a repo with a given DAG from scratch in the current empty repo
1885 """builds a repo with a given DAG from scratch in the current empty repo
1884
1886
1885 The description of the DAG is read from stdin if not given on the
1887 The description of the DAG is read from stdin if not given on the
1886 command line.
1888 command line.
1887
1889
1888 Elements:
1890 Elements:
1889
1891
1890 - "+n" is a linear run of n nodes based on the current default parent
1892 - "+n" is a linear run of n nodes based on the current default parent
1891 - "." is a single node based on the current default parent
1893 - "." is a single node based on the current default parent
1892 - "$" resets the default parent to null (implied at the start);
1894 - "$" resets the default parent to null (implied at the start);
1893 otherwise the default parent is always the last node created
1895 otherwise the default parent is always the last node created
1894 - "<p" sets the default parent to the backref p
1896 - "<p" sets the default parent to the backref p
1895 - "*p" is a fork at parent p, which is a backref
1897 - "*p" is a fork at parent p, which is a backref
1896 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1898 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1897 - "/p2" is a merge of the preceding node and p2
1899 - "/p2" is a merge of the preceding node and p2
1898 - ":tag" defines a local tag for the preceding node
1900 - ":tag" defines a local tag for the preceding node
1899 - "@branch" sets the named branch for subsequent nodes
1901 - "@branch" sets the named branch for subsequent nodes
1900 - "#...\\n" is a comment up to the end of the line
1902 - "#...\\n" is a comment up to the end of the line
1901
1903
1902 Whitespace between the above elements is ignored.
1904 Whitespace between the above elements is ignored.
1903
1905
1904 A backref is either
1906 A backref is either
1905
1907
1906 - a number n, which references the node curr-n, where curr is the current
1908 - a number n, which references the node curr-n, where curr is the current
1907 node, or
1909 node, or
1908 - the name of a local tag you placed earlier using ":tag", or
1910 - the name of a local tag you placed earlier using ":tag", or
1909 - empty to denote the default parent.
1911 - empty to denote the default parent.
1910
1912
1911 All string valued-elements are either strictly alphanumeric, or must
1913 All string valued-elements are either strictly alphanumeric, or must
1912 be enclosed in double quotes ("..."), with "\\" as escape character.
1914 be enclosed in double quotes ("..."), with "\\" as escape character.
1913 """
1915 """
1914
1916
1915 if text is None:
1917 if text is None:
1916 ui.status(_("reading DAG from stdin\n"))
1918 ui.status(_("reading DAG from stdin\n"))
1917 text = ui.fin.read()
1919 text = ui.fin.read()
1918
1920
1919 cl = repo.changelog
1921 cl = repo.changelog
1920 if len(cl) > 0:
1922 if len(cl) > 0:
1921 raise error.Abort(_('repository is not empty'))
1923 raise error.Abort(_('repository is not empty'))
1922
1924
1923 # determine number of revs in DAG
1925 # determine number of revs in DAG
1924 total = 0
1926 total = 0
1925 for type, data in dagparser.parsedag(text):
1927 for type, data in dagparser.parsedag(text):
1926 if type == 'n':
1928 if type == 'n':
1927 total += 1
1929 total += 1
1928
1930
1929 if mergeable_file:
1931 if mergeable_file:
1930 linesperrev = 2
1932 linesperrev = 2
1931 # make a file with k lines per rev
1933 # make a file with k lines per rev
1932 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1934 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1933 initialmergedlines.append("")
1935 initialmergedlines.append("")
1934
1936
1935 tags = []
1937 tags = []
1936
1938
1937 lock = tr = None
1939 lock = tr = None
1938 try:
1940 try:
1939 lock = repo.lock()
1941 lock = repo.lock()
1940 tr = repo.transaction("builddag")
1942 tr = repo.transaction("builddag")
1941
1943
1942 at = -1
1944 at = -1
1943 atbranch = 'default'
1945 atbranch = 'default'
1944 nodeids = []
1946 nodeids = []
1945 id = 0
1947 id = 0
1946 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1948 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1947 for type, data in dagparser.parsedag(text):
1949 for type, data in dagparser.parsedag(text):
1948 if type == 'n':
1950 if type == 'n':
1949 ui.note(('node %s\n' % str(data)))
1951 ui.note(('node %s\n' % str(data)))
1950 id, ps = data
1952 id, ps = data
1951
1953
1952 files = []
1954 files = []
1953 fctxs = {}
1955 fctxs = {}
1954
1956
1955 p2 = None
1957 p2 = None
1956 if mergeable_file:
1958 if mergeable_file:
1957 fn = "mf"
1959 fn = "mf"
1958 p1 = repo[ps[0]]
1960 p1 = repo[ps[0]]
1959 if len(ps) > 1:
1961 if len(ps) > 1:
1960 p2 = repo[ps[1]]
1962 p2 = repo[ps[1]]
1961 pa = p1.ancestor(p2)
1963 pa = p1.ancestor(p2)
1962 base, local, other = [x[fn].data() for x in (pa, p1,
1964 base, local, other = [x[fn].data() for x in (pa, p1,
1963 p2)]
1965 p2)]
1964 m3 = simplemerge.Merge3Text(base, local, other)
1966 m3 = simplemerge.Merge3Text(base, local, other)
1965 ml = [l.strip() for l in m3.merge_lines()]
1967 ml = [l.strip() for l in m3.merge_lines()]
1966 ml.append("")
1968 ml.append("")
1967 elif at > 0:
1969 elif at > 0:
1968 ml = p1[fn].data().split("\n")
1970 ml = p1[fn].data().split("\n")
1969 else:
1971 else:
1970 ml = initialmergedlines
1972 ml = initialmergedlines
1971 ml[id * linesperrev] += " r%i" % id
1973 ml[id * linesperrev] += " r%i" % id
1972 mergedtext = "\n".join(ml)
1974 mergedtext = "\n".join(ml)
1973 files.append(fn)
1975 files.append(fn)
1974 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1976 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1975
1977
1976 if overwritten_file:
1978 if overwritten_file:
1977 fn = "of"
1979 fn = "of"
1978 files.append(fn)
1980 files.append(fn)
1979 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1981 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1980
1982
1981 if new_file:
1983 if new_file:
1982 fn = "nf%i" % id
1984 fn = "nf%i" % id
1983 files.append(fn)
1985 files.append(fn)
1984 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1986 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1985 if len(ps) > 1:
1987 if len(ps) > 1:
1986 if not p2:
1988 if not p2:
1987 p2 = repo[ps[1]]
1989 p2 = repo[ps[1]]
1988 for fn in p2:
1990 for fn in p2:
1989 if fn.startswith("nf"):
1991 if fn.startswith("nf"):
1990 files.append(fn)
1992 files.append(fn)
1991 fctxs[fn] = p2[fn]
1993 fctxs[fn] = p2[fn]
1992
1994
1993 def fctxfn(repo, cx, path):
1995 def fctxfn(repo, cx, path):
1994 return fctxs.get(path)
1996 return fctxs.get(path)
1995
1997
1996 if len(ps) == 0 or ps[0] < 0:
1998 if len(ps) == 0 or ps[0] < 0:
1997 pars = [None, None]
1999 pars = [None, None]
1998 elif len(ps) == 1:
2000 elif len(ps) == 1:
1999 pars = [nodeids[ps[0]], None]
2001 pars = [nodeids[ps[0]], None]
2000 else:
2002 else:
2001 pars = [nodeids[p] for p in ps]
2003 pars = [nodeids[p] for p in ps]
2002 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2004 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2003 date=(id, 0),
2005 date=(id, 0),
2004 user="debugbuilddag",
2006 user="debugbuilddag",
2005 extra={'branch': atbranch})
2007 extra={'branch': atbranch})
2006 nodeid = repo.commitctx(cx)
2008 nodeid = repo.commitctx(cx)
2007 nodeids.append(nodeid)
2009 nodeids.append(nodeid)
2008 at = id
2010 at = id
2009 elif type == 'l':
2011 elif type == 'l':
2010 id, name = data
2012 id, name = data
2011 ui.note(('tag %s\n' % name))
2013 ui.note(('tag %s\n' % name))
2012 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2014 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2013 elif type == 'a':
2015 elif type == 'a':
2014 ui.note(('branch %s\n' % data))
2016 ui.note(('branch %s\n' % data))
2015 atbranch = data
2017 atbranch = data
2016 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2018 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2017 tr.close()
2019 tr.close()
2018
2020
2019 if tags:
2021 if tags:
2020 repo.vfs.write("localtags", "".join(tags))
2022 repo.vfs.write("localtags", "".join(tags))
2021 finally:
2023 finally:
2022 ui.progress(_('building'), None)
2024 ui.progress(_('building'), None)
2023 release(tr, lock)
2025 release(tr, lock)
2024
2026
2025 @command('debugbundle',
2027 @command('debugbundle',
2026 [('a', 'all', None, _('show all details')),
2028 [('a', 'all', None, _('show all details')),
2027 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2029 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2028 _('FILE'),
2030 _('FILE'),
2029 norepo=True)
2031 norepo=True)
2030 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2032 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2031 """lists the contents of a bundle"""
2033 """lists the contents of a bundle"""
2032 with hg.openpath(ui, bundlepath) as f:
2034 with hg.openpath(ui, bundlepath) as f:
2033 if spec:
2035 if spec:
2034 spec = exchange.getbundlespec(ui, f)
2036 spec = exchange.getbundlespec(ui, f)
2035 ui.write('%s\n' % spec)
2037 ui.write('%s\n' % spec)
2036 return
2038 return
2037
2039
2038 gen = exchange.readbundle(ui, f, bundlepath)
2040 gen = exchange.readbundle(ui, f, bundlepath)
2039 if isinstance(gen, bundle2.unbundle20):
2041 if isinstance(gen, bundle2.unbundle20):
2040 return _debugbundle2(ui, gen, all=all, **opts)
2042 return _debugbundle2(ui, gen, all=all, **opts)
2041 if all:
2043 if all:
2042 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2044 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2043
2045
2044 def showchunks(named):
2046 def showchunks(named):
2045 ui.write("\n%s\n" % named)
2047 ui.write("\n%s\n" % named)
2046 chain = None
2048 chain = None
2047 while True:
2049 while True:
2048 chunkdata = gen.deltachunk(chain)
2050 chunkdata = gen.deltachunk(chain)
2049 if not chunkdata:
2051 if not chunkdata:
2050 break
2052 break
2051 node = chunkdata['node']
2053 node = chunkdata['node']
2052 p1 = chunkdata['p1']
2054 p1 = chunkdata['p1']
2053 p2 = chunkdata['p2']
2055 p2 = chunkdata['p2']
2054 cs = chunkdata['cs']
2056 cs = chunkdata['cs']
2055 deltabase = chunkdata['deltabase']
2057 deltabase = chunkdata['deltabase']
2056 delta = chunkdata['delta']
2058 delta = chunkdata['delta']
2057 ui.write("%s %s %s %s %s %s\n" %
2059 ui.write("%s %s %s %s %s %s\n" %
2058 (hex(node), hex(p1), hex(p2),
2060 (hex(node), hex(p1), hex(p2),
2059 hex(cs), hex(deltabase), len(delta)))
2061 hex(cs), hex(deltabase), len(delta)))
2060 chain = node
2062 chain = node
2061
2063
2062 chunkdata = gen.changelogheader()
2064 chunkdata = gen.changelogheader()
2063 showchunks("changelog")
2065 showchunks("changelog")
2064 chunkdata = gen.manifestheader()
2066 chunkdata = gen.manifestheader()
2065 showchunks("manifest")
2067 showchunks("manifest")
2066 while True:
2068 while True:
2067 chunkdata = gen.filelogheader()
2069 chunkdata = gen.filelogheader()
2068 if not chunkdata:
2070 if not chunkdata:
2069 break
2071 break
2070 fname = chunkdata['filename']
2072 fname = chunkdata['filename']
2071 showchunks(fname)
2073 showchunks(fname)
2072 else:
2074 else:
2073 if isinstance(gen, bundle2.unbundle20):
2075 if isinstance(gen, bundle2.unbundle20):
2074 raise error.Abort(_('use debugbundle2 for this file'))
2076 raise error.Abort(_('use debugbundle2 for this file'))
2075 chunkdata = gen.changelogheader()
2077 chunkdata = gen.changelogheader()
2076 chain = None
2078 chain = None
2077 while True:
2079 while True:
2078 chunkdata = gen.deltachunk(chain)
2080 chunkdata = gen.deltachunk(chain)
2079 if not chunkdata:
2081 if not chunkdata:
2080 break
2082 break
2081 node = chunkdata['node']
2083 node = chunkdata['node']
2082 ui.write("%s\n" % hex(node))
2084 ui.write("%s\n" % hex(node))
2083 chain = node
2085 chain = node
2084
2086
2085 def _debugbundle2(ui, gen, **opts):
2087 def _debugbundle2(ui, gen, **opts):
2086 """lists the contents of a bundle2"""
2088 """lists the contents of a bundle2"""
2087 if not isinstance(gen, bundle2.unbundle20):
2089 if not isinstance(gen, bundle2.unbundle20):
2088 raise error.Abort(_('not a bundle2 file'))
2090 raise error.Abort(_('not a bundle2 file'))
2089 ui.write(('Stream params: %s\n' % repr(gen.params)))
2091 ui.write(('Stream params: %s\n' % repr(gen.params)))
2090 for part in gen.iterparts():
2092 for part in gen.iterparts():
2091 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2093 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2092 if part.type == 'changegroup':
2094 if part.type == 'changegroup':
2093 version = part.params.get('version', '01')
2095 version = part.params.get('version', '01')
2094 cg = changegroup.getunbundler(version, part, 'UN')
2096 cg = changegroup.getunbundler(version, part, 'UN')
2095 chunkdata = cg.changelogheader()
2097 chunkdata = cg.changelogheader()
2096 chain = None
2098 chain = None
2097 while True:
2099 while True:
2098 chunkdata = cg.deltachunk(chain)
2100 chunkdata = cg.deltachunk(chain)
2099 if not chunkdata:
2101 if not chunkdata:
2100 break
2102 break
2101 node = chunkdata['node']
2103 node = chunkdata['node']
2102 ui.write(" %s\n" % hex(node))
2104 ui.write(" %s\n" % hex(node))
2103 chain = node
2105 chain = node
2104
2106
2105 @command('debugcreatestreamclonebundle', [], 'FILE')
2107 @command('debugcreatestreamclonebundle', [], 'FILE')
2106 def debugcreatestreamclonebundle(ui, repo, fname):
2108 def debugcreatestreamclonebundle(ui, repo, fname):
2107 """create a stream clone bundle file
2109 """create a stream clone bundle file
2108
2110
2109 Stream bundles are special bundles that are essentially archives of
2111 Stream bundles are special bundles that are essentially archives of
2110 revlog files. They are commonly used for cloning very quickly.
2112 revlog files. They are commonly used for cloning very quickly.
2111 """
2113 """
2112 requirements, gen = streamclone.generatebundlev1(repo)
2114 requirements, gen = streamclone.generatebundlev1(repo)
2113 changegroup.writechunks(ui, gen, fname)
2115 changegroup.writechunks(ui, gen, fname)
2114
2116
2115 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2117 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2116
2118
2117 @command('debugapplystreamclonebundle', [], 'FILE')
2119 @command('debugapplystreamclonebundle', [], 'FILE')
2118 def debugapplystreamclonebundle(ui, repo, fname):
2120 def debugapplystreamclonebundle(ui, repo, fname):
2119 """apply a stream clone bundle file"""
2121 """apply a stream clone bundle file"""
2120 f = hg.openpath(ui, fname)
2122 f = hg.openpath(ui, fname)
2121 gen = exchange.readbundle(ui, f, fname)
2123 gen = exchange.readbundle(ui, f, fname)
2122 gen.apply(repo)
2124 gen.apply(repo)
2123
2125
2124 @command('debugcheckstate', [], '')
2126 @command('debugcheckstate', [], '')
2125 def debugcheckstate(ui, repo):
2127 def debugcheckstate(ui, repo):
2126 """validate the correctness of the current dirstate"""
2128 """validate the correctness of the current dirstate"""
2127 parent1, parent2 = repo.dirstate.parents()
2129 parent1, parent2 = repo.dirstate.parents()
2128 m1 = repo[parent1].manifest()
2130 m1 = repo[parent1].manifest()
2129 m2 = repo[parent2].manifest()
2131 m2 = repo[parent2].manifest()
2130 errors = 0
2132 errors = 0
2131 for f in repo.dirstate:
2133 for f in repo.dirstate:
2132 state = repo.dirstate[f]
2134 state = repo.dirstate[f]
2133 if state in "nr" and f not in m1:
2135 if state in "nr" and f not in m1:
2134 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2136 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2135 errors += 1
2137 errors += 1
2136 if state in "a" and f in m1:
2138 if state in "a" and f in m1:
2137 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2139 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2138 errors += 1
2140 errors += 1
2139 if state in "m" and f not in m1 and f not in m2:
2141 if state in "m" and f not in m1 and f not in m2:
2140 ui.warn(_("%s in state %s, but not in either manifest\n") %
2142 ui.warn(_("%s in state %s, but not in either manifest\n") %
2141 (f, state))
2143 (f, state))
2142 errors += 1
2144 errors += 1
2143 for f in m1:
2145 for f in m1:
2144 state = repo.dirstate[f]
2146 state = repo.dirstate[f]
2145 if state not in "nrm":
2147 if state not in "nrm":
2146 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2148 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2147 errors += 1
2149 errors += 1
2148 if errors:
2150 if errors:
2149 error = _(".hg/dirstate inconsistent with current parent's manifest")
2151 error = _(".hg/dirstate inconsistent with current parent's manifest")
2150 raise error.Abort(error)
2152 raise error.Abort(error)
2151
2153
2152 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2154 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2153 def debugcommands(ui, cmd='', *args):
2155 def debugcommands(ui, cmd='', *args):
2154 """list all available commands and options"""
2156 """list all available commands and options"""
2155 for cmd, vals in sorted(table.iteritems()):
2157 for cmd, vals in sorted(table.iteritems()):
2156 cmd = cmd.split('|')[0].strip('^')
2158 cmd = cmd.split('|')[0].strip('^')
2157 opts = ', '.join([i[1] for i in vals[1]])
2159 opts = ', '.join([i[1] for i in vals[1]])
2158 ui.write('%s: %s\n' % (cmd, opts))
2160 ui.write('%s: %s\n' % (cmd, opts))
2159
2161
2160 @command('debugcomplete',
2162 @command('debugcomplete',
2161 [('o', 'options', None, _('show the command options'))],
2163 [('o', 'options', None, _('show the command options'))],
2162 _('[-o] CMD'),
2164 _('[-o] CMD'),
2163 norepo=True)
2165 norepo=True)
2164 def debugcomplete(ui, cmd='', **opts):
2166 def debugcomplete(ui, cmd='', **opts):
2165 """returns the completion list associated with the given command"""
2167 """returns the completion list associated with the given command"""
2166
2168
2167 if opts.get('options'):
2169 if opts.get('options'):
2168 options = []
2170 options = []
2169 otables = [globalopts]
2171 otables = [globalopts]
2170 if cmd:
2172 if cmd:
2171 aliases, entry = cmdutil.findcmd(cmd, table, False)
2173 aliases, entry = cmdutil.findcmd(cmd, table, False)
2172 otables.append(entry[1])
2174 otables.append(entry[1])
2173 for t in otables:
2175 for t in otables:
2174 for o in t:
2176 for o in t:
2175 if "(DEPRECATED)" in o[3]:
2177 if "(DEPRECATED)" in o[3]:
2176 continue
2178 continue
2177 if o[0]:
2179 if o[0]:
2178 options.append('-%s' % o[0])
2180 options.append('-%s' % o[0])
2179 options.append('--%s' % o[1])
2181 options.append('--%s' % o[1])
2180 ui.write("%s\n" % "\n".join(options))
2182 ui.write("%s\n" % "\n".join(options))
2181 return
2183 return
2182
2184
2183 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2185 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2184 if ui.verbose:
2186 if ui.verbose:
2185 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2187 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2186 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2188 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2187
2189
2188 @command('debugdag',
2190 @command('debugdag',
2189 [('t', 'tags', None, _('use tags as labels')),
2191 [('t', 'tags', None, _('use tags as labels')),
2190 ('b', 'branches', None, _('annotate with branch names')),
2192 ('b', 'branches', None, _('annotate with branch names')),
2191 ('', 'dots', None, _('use dots for runs')),
2193 ('', 'dots', None, _('use dots for runs')),
2192 ('s', 'spaces', None, _('separate elements by spaces'))],
2194 ('s', 'spaces', None, _('separate elements by spaces'))],
2193 _('[OPTION]... [FILE [REV]...]'),
2195 _('[OPTION]... [FILE [REV]...]'),
2194 optionalrepo=True)
2196 optionalrepo=True)
2195 def debugdag(ui, repo, file_=None, *revs, **opts):
2197 def debugdag(ui, repo, file_=None, *revs, **opts):
2196 """format the changelog or an index DAG as a concise textual description
2198 """format the changelog or an index DAG as a concise textual description
2197
2199
2198 If you pass a revlog index, the revlog's DAG is emitted. If you list
2200 If you pass a revlog index, the revlog's DAG is emitted. If you list
2199 revision numbers, they get labeled in the output as rN.
2201 revision numbers, they get labeled in the output as rN.
2200
2202
2201 Otherwise, the changelog DAG of the current repo is emitted.
2203 Otherwise, the changelog DAG of the current repo is emitted.
2202 """
2204 """
2203 spaces = opts.get('spaces')
2205 spaces = opts.get('spaces')
2204 dots = opts.get('dots')
2206 dots = opts.get('dots')
2205 if file_:
2207 if file_:
2206 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2208 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2207 revs = set((int(r) for r in revs))
2209 revs = set((int(r) for r in revs))
2208 def events():
2210 def events():
2209 for r in rlog:
2211 for r in rlog:
2210 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2212 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2211 if p != -1))
2213 if p != -1))
2212 if r in revs:
2214 if r in revs:
2213 yield 'l', (r, "r%i" % r)
2215 yield 'l', (r, "r%i" % r)
2214 elif repo:
2216 elif repo:
2215 cl = repo.changelog
2217 cl = repo.changelog
2216 tags = opts.get('tags')
2218 tags = opts.get('tags')
2217 branches = opts.get('branches')
2219 branches = opts.get('branches')
2218 if tags:
2220 if tags:
2219 labels = {}
2221 labels = {}
2220 for l, n in repo.tags().items():
2222 for l, n in repo.tags().items():
2221 labels.setdefault(cl.rev(n), []).append(l)
2223 labels.setdefault(cl.rev(n), []).append(l)
2222 def events():
2224 def events():
2223 b = "default"
2225 b = "default"
2224 for r in cl:
2226 for r in cl:
2225 if branches:
2227 if branches:
2226 newb = cl.read(cl.node(r))[5]['branch']
2228 newb = cl.read(cl.node(r))[5]['branch']
2227 if newb != b:
2229 if newb != b:
2228 yield 'a', newb
2230 yield 'a', newb
2229 b = newb
2231 b = newb
2230 yield 'n', (r, list(p for p in cl.parentrevs(r)
2232 yield 'n', (r, list(p for p in cl.parentrevs(r)
2231 if p != -1))
2233 if p != -1))
2232 if tags:
2234 if tags:
2233 ls = labels.get(r)
2235 ls = labels.get(r)
2234 if ls:
2236 if ls:
2235 for l in ls:
2237 for l in ls:
2236 yield 'l', (r, l)
2238 yield 'l', (r, l)
2237 else:
2239 else:
2238 raise error.Abort(_('need repo for changelog dag'))
2240 raise error.Abort(_('need repo for changelog dag'))
2239
2241
2240 for line in dagparser.dagtextlines(events(),
2242 for line in dagparser.dagtextlines(events(),
2241 addspaces=spaces,
2243 addspaces=spaces,
2242 wraplabels=True,
2244 wraplabels=True,
2243 wrapannotations=True,
2245 wrapannotations=True,
2244 wrapnonlinear=dots,
2246 wrapnonlinear=dots,
2245 usedots=dots,
2247 usedots=dots,
2246 maxlinewidth=70):
2248 maxlinewidth=70):
2247 ui.write(line)
2249 ui.write(line)
2248 ui.write("\n")
2250 ui.write("\n")
2249
2251
2250 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2252 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2251 def debugdata(ui, repo, file_, rev=None, **opts):
2253 def debugdata(ui, repo, file_, rev=None, **opts):
2252 """dump the contents of a data file revision"""
2254 """dump the contents of a data file revision"""
2253 if opts.get('changelog') or opts.get('manifest'):
2255 if opts.get('changelog') or opts.get('manifest'):
2254 file_, rev = None, file_
2256 file_, rev = None, file_
2255 elif rev is None:
2257 elif rev is None:
2256 raise error.CommandError('debugdata', _('invalid arguments'))
2258 raise error.CommandError('debugdata', _('invalid arguments'))
2257 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2259 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2258 try:
2260 try:
2259 ui.write(r.revision(r.lookup(rev)))
2261 ui.write(r.revision(r.lookup(rev)))
2260 except KeyError:
2262 except KeyError:
2261 raise error.Abort(_('invalid revision identifier %s') % rev)
2263 raise error.Abort(_('invalid revision identifier %s') % rev)
2262
2264
2263 @command('debugdate',
2265 @command('debugdate',
2264 [('e', 'extended', None, _('try extended date formats'))],
2266 [('e', 'extended', None, _('try extended date formats'))],
2265 _('[-e] DATE [RANGE]'),
2267 _('[-e] DATE [RANGE]'),
2266 norepo=True, optionalrepo=True)
2268 norepo=True, optionalrepo=True)
2267 def debugdate(ui, date, range=None, **opts):
2269 def debugdate(ui, date, range=None, **opts):
2268 """parse and display a date"""
2270 """parse and display a date"""
2269 if opts["extended"]:
2271 if opts["extended"]:
2270 d = util.parsedate(date, util.extendeddateformats)
2272 d = util.parsedate(date, util.extendeddateformats)
2271 else:
2273 else:
2272 d = util.parsedate(date)
2274 d = util.parsedate(date)
2273 ui.write(("internal: %s %s\n") % d)
2275 ui.write(("internal: %s %s\n") % d)
2274 ui.write(("standard: %s\n") % util.datestr(d))
2276 ui.write(("standard: %s\n") % util.datestr(d))
2275 if range:
2277 if range:
2276 m = util.matchdate(range)
2278 m = util.matchdate(range)
2277 ui.write(("match: %s\n") % m(d[0]))
2279 ui.write(("match: %s\n") % m(d[0]))
2278
2280
2279 @command('debugdiscovery',
2281 @command('debugdiscovery',
2280 [('', 'old', None, _('use old-style discovery')),
2282 [('', 'old', None, _('use old-style discovery')),
2281 ('', 'nonheads', None,
2283 ('', 'nonheads', None,
2282 _('use old-style discovery with non-heads included')),
2284 _('use old-style discovery with non-heads included')),
2283 ] + remoteopts,
2285 ] + remoteopts,
2284 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2286 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2285 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2287 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2286 """runs the changeset discovery protocol in isolation"""
2288 """runs the changeset discovery protocol in isolation"""
2287 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2289 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2288 opts.get('branch'))
2290 opts.get('branch'))
2289 remote = hg.peer(repo, opts, remoteurl)
2291 remote = hg.peer(repo, opts, remoteurl)
2290 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2292 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2291
2293
2292 # make sure tests are repeatable
2294 # make sure tests are repeatable
2293 random.seed(12323)
2295 random.seed(12323)
2294
2296
2295 def doit(localheads, remoteheads, remote=remote):
2297 def doit(localheads, remoteheads, remote=remote):
2296 if opts.get('old'):
2298 if opts.get('old'):
2297 if localheads:
2299 if localheads:
2298 raise error.Abort('cannot use localheads with old style '
2300 raise error.Abort('cannot use localheads with old style '
2299 'discovery')
2301 'discovery')
2300 if not util.safehasattr(remote, 'branches'):
2302 if not util.safehasattr(remote, 'branches'):
2301 # enable in-client legacy support
2303 # enable in-client legacy support
2302 remote = localrepo.locallegacypeer(remote.local())
2304 remote = localrepo.locallegacypeer(remote.local())
2303 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2305 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2304 force=True)
2306 force=True)
2305 common = set(common)
2307 common = set(common)
2306 if not opts.get('nonheads'):
2308 if not opts.get('nonheads'):
2307 ui.write(("unpruned common: %s\n") %
2309 ui.write(("unpruned common: %s\n") %
2308 " ".join(sorted(short(n) for n in common)))
2310 " ".join(sorted(short(n) for n in common)))
2309 dag = dagutil.revlogdag(repo.changelog)
2311 dag = dagutil.revlogdag(repo.changelog)
2310 all = dag.ancestorset(dag.internalizeall(common))
2312 all = dag.ancestorset(dag.internalizeall(common))
2311 common = dag.externalizeall(dag.headsetofconnecteds(all))
2313 common = dag.externalizeall(dag.headsetofconnecteds(all))
2312 else:
2314 else:
2313 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2315 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2314 common = set(common)
2316 common = set(common)
2315 rheads = set(hds)
2317 rheads = set(hds)
2316 lheads = set(repo.heads())
2318 lheads = set(repo.heads())
2317 ui.write(("common heads: %s\n") %
2319 ui.write(("common heads: %s\n") %
2318 " ".join(sorted(short(n) for n in common)))
2320 " ".join(sorted(short(n) for n in common)))
2319 if lheads <= common:
2321 if lheads <= common:
2320 ui.write(("local is subset\n"))
2322 ui.write(("local is subset\n"))
2321 elif rheads <= common:
2323 elif rheads <= common:
2322 ui.write(("remote is subset\n"))
2324 ui.write(("remote is subset\n"))
2323
2325
2324 serverlogs = opts.get('serverlog')
2326 serverlogs = opts.get('serverlog')
2325 if serverlogs:
2327 if serverlogs:
2326 for filename in serverlogs:
2328 for filename in serverlogs:
2327 with open(filename, 'r') as logfile:
2329 with open(filename, 'r') as logfile:
2328 line = logfile.readline()
2330 line = logfile.readline()
2329 while line:
2331 while line:
2330 parts = line.strip().split(';')
2332 parts = line.strip().split(';')
2331 op = parts[1]
2333 op = parts[1]
2332 if op == 'cg':
2334 if op == 'cg':
2333 pass
2335 pass
2334 elif op == 'cgss':
2336 elif op == 'cgss':
2335 doit(parts[2].split(' '), parts[3].split(' '))
2337 doit(parts[2].split(' '), parts[3].split(' '))
2336 elif op == 'unb':
2338 elif op == 'unb':
2337 doit(parts[3].split(' '), parts[2].split(' '))
2339 doit(parts[3].split(' '), parts[2].split(' '))
2338 line = logfile.readline()
2340 line = logfile.readline()
2339 else:
2341 else:
2340 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2342 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2341 opts.get('remote_head'))
2343 opts.get('remote_head'))
2342 localrevs = opts.get('local_head')
2344 localrevs = opts.get('local_head')
2343 doit(localrevs, remoterevs)
2345 doit(localrevs, remoterevs)
2344
2346
2345 @command('debugextensions', formatteropts, [], norepo=True)
2347 @command('debugextensions', formatteropts, [], norepo=True)
2346 def debugextensions(ui, **opts):
2348 def debugextensions(ui, **opts):
2347 '''show information about active extensions'''
2349 '''show information about active extensions'''
2348 exts = extensions.extensions(ui)
2350 exts = extensions.extensions(ui)
2349 fm = ui.formatter('debugextensions', opts)
2351 fm = ui.formatter('debugextensions', opts)
2350 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2352 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2351 extsource = extmod.__file__
2353 extsource = extmod.__file__
2352 exttestedwith = getattr(extmod, 'testedwith', None)
2354 exttestedwith = getattr(extmod, 'testedwith', None)
2353 if exttestedwith is not None:
2355 if exttestedwith is not None:
2354 exttestedwith = exttestedwith.split()
2356 exttestedwith = exttestedwith.split()
2355 extbuglink = getattr(extmod, 'buglink', None)
2357 extbuglink = getattr(extmod, 'buglink', None)
2356
2358
2357 fm.startitem()
2359 fm.startitem()
2358
2360
2359 if ui.quiet or ui.verbose:
2361 if ui.quiet or ui.verbose:
2360 fm.write('name', '%s\n', extname)
2362 fm.write('name', '%s\n', extname)
2361 else:
2363 else:
2362 fm.write('name', '%s', extname)
2364 fm.write('name', '%s', extname)
2363 if not exttestedwith:
2365 if not exttestedwith:
2364 fm.plain(_(' (untested!)\n'))
2366 fm.plain(_(' (untested!)\n'))
2365 else:
2367 else:
2366 if exttestedwith == ['internal'] or \
2368 if exttestedwith == ['internal'] or \
2367 util.version() in exttestedwith:
2369 util.version() in exttestedwith:
2368 fm.plain('\n')
2370 fm.plain('\n')
2369 else:
2371 else:
2370 lasttestedversion = exttestedwith[-1]
2372 lasttestedversion = exttestedwith[-1]
2371 fm.plain(' (%s!)\n' % lasttestedversion)
2373 fm.plain(' (%s!)\n' % lasttestedversion)
2372
2374
2373 fm.condwrite(ui.verbose and extsource, 'source',
2375 fm.condwrite(ui.verbose and extsource, 'source',
2374 _(' location: %s\n'), extsource or "")
2376 _(' location: %s\n'), extsource or "")
2375
2377
2376 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2378 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2377 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2379 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2378
2380
2379 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2381 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2380 _(' bug reporting: %s\n'), extbuglink or "")
2382 _(' bug reporting: %s\n'), extbuglink or "")
2381
2383
2382 fm.end()
2384 fm.end()
2383
2385
2384 @command('debugfileset',
2386 @command('debugfileset',
2385 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2387 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2386 _('[-r REV] FILESPEC'))
2388 _('[-r REV] FILESPEC'))
2387 def debugfileset(ui, repo, expr, **opts):
2389 def debugfileset(ui, repo, expr, **opts):
2388 '''parse and apply a fileset specification'''
2390 '''parse and apply a fileset specification'''
2389 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2391 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2390 if ui.verbose:
2392 if ui.verbose:
2391 tree = fileset.parse(expr)
2393 tree = fileset.parse(expr)
2392 ui.note(fileset.prettyformat(tree), "\n")
2394 ui.note(fileset.prettyformat(tree), "\n")
2393
2395
2394 for f in ctx.getfileset(expr):
2396 for f in ctx.getfileset(expr):
2395 ui.write("%s\n" % f)
2397 ui.write("%s\n" % f)
2396
2398
2397 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2399 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2398 def debugfsinfo(ui, path="."):
2400 def debugfsinfo(ui, path="."):
2399 """show information detected about current filesystem"""
2401 """show information detected about current filesystem"""
2400 util.writefile('.debugfsinfo', '')
2402 util.writefile('.debugfsinfo', '')
2401 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2403 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2402 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2404 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2403 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2405 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2404 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2406 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2405 and 'yes' or 'no'))
2407 and 'yes' or 'no'))
2406 os.unlink('.debugfsinfo')
2408 os.unlink('.debugfsinfo')
2407
2409
2408 @command('debuggetbundle',
2410 @command('debuggetbundle',
2409 [('H', 'head', [], _('id of head node'), _('ID')),
2411 [('H', 'head', [], _('id of head node'), _('ID')),
2410 ('C', 'common', [], _('id of common node'), _('ID')),
2412 ('C', 'common', [], _('id of common node'), _('ID')),
2411 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2413 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2412 _('REPO FILE [-H|-C ID]...'),
2414 _('REPO FILE [-H|-C ID]...'),
2413 norepo=True)
2415 norepo=True)
2414 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2416 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2415 """retrieves a bundle from a repo
2417 """retrieves a bundle from a repo
2416
2418
2417 Every ID must be a full-length hex node id string. Saves the bundle to the
2419 Every ID must be a full-length hex node id string. Saves the bundle to the
2418 given file.
2420 given file.
2419 """
2421 """
2420 repo = hg.peer(ui, opts, repopath)
2422 repo = hg.peer(ui, opts, repopath)
2421 if not repo.capable('getbundle'):
2423 if not repo.capable('getbundle'):
2422 raise error.Abort("getbundle() not supported by target repository")
2424 raise error.Abort("getbundle() not supported by target repository")
2423 args = {}
2425 args = {}
2424 if common:
2426 if common:
2425 args['common'] = [bin(s) for s in common]
2427 args['common'] = [bin(s) for s in common]
2426 if head:
2428 if head:
2427 args['heads'] = [bin(s) for s in head]
2429 args['heads'] = [bin(s) for s in head]
2428 # TODO: get desired bundlecaps from command line.
2430 # TODO: get desired bundlecaps from command line.
2429 args['bundlecaps'] = None
2431 args['bundlecaps'] = None
2430 bundle = repo.getbundle('debug', **args)
2432 bundle = repo.getbundle('debug', **args)
2431
2433
2432 bundletype = opts.get('type', 'bzip2').lower()
2434 bundletype = opts.get('type', 'bzip2').lower()
2433 btypes = {'none': 'HG10UN',
2435 btypes = {'none': 'HG10UN',
2434 'bzip2': 'HG10BZ',
2436 'bzip2': 'HG10BZ',
2435 'gzip': 'HG10GZ',
2437 'gzip': 'HG10GZ',
2436 'bundle2': 'HG20'}
2438 'bundle2': 'HG20'}
2437 bundletype = btypes.get(bundletype)
2439 bundletype = btypes.get(bundletype)
2438 if bundletype not in changegroup.bundletypes:
2440 if bundletype not in changegroup.bundletypes:
2439 raise error.Abort(_('unknown bundle type specified with --type'))
2441 raise error.Abort(_('unknown bundle type specified with --type'))
2440 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2442 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2441
2443
2442 @command('debugignore', [], '[FILE]')
2444 @command('debugignore', [], '[FILE]')
2443 def debugignore(ui, repo, *files, **opts):
2445 def debugignore(ui, repo, *files, **opts):
2444 """display the combined ignore pattern and information about ignored files
2446 """display the combined ignore pattern and information about ignored files
2445
2447
2446 With no argument display the combined ignore pattern.
2448 With no argument display the combined ignore pattern.
2447
2449
2448 Given space separated file names, shows if the given file is ignored and
2450 Given space separated file names, shows if the given file is ignored and
2449 if so, show the ignore rule (file and line number) that matched it.
2451 if so, show the ignore rule (file and line number) that matched it.
2450 """
2452 """
2451 ignore = repo.dirstate._ignore
2453 ignore = repo.dirstate._ignore
2452 if not files:
2454 if not files:
2453 # Show all the patterns
2455 # Show all the patterns
2454 includepat = getattr(ignore, 'includepat', None)
2456 includepat = getattr(ignore, 'includepat', None)
2455 if includepat is not None:
2457 if includepat is not None:
2456 ui.write("%s\n" % includepat)
2458 ui.write("%s\n" % includepat)
2457 else:
2459 else:
2458 raise error.Abort(_("no ignore patterns found"))
2460 raise error.Abort(_("no ignore patterns found"))
2459 else:
2461 else:
2460 for f in files:
2462 for f in files:
2461 ignored = None
2463 ignored = None
2462 ignoredata = None
2464 ignoredata = None
2463 if f != '.':
2465 if f != '.':
2464 if ignore(f):
2466 if ignore(f):
2465 ignored = f
2467 ignored = f
2466 ignoredata = repo.dirstate._ignorefileandline(f)
2468 ignoredata = repo.dirstate._ignorefileandline(f)
2467 else:
2469 else:
2468 for p in util.finddirs(f):
2470 for p in util.finddirs(f):
2469 if ignore(p):
2471 if ignore(p):
2470 ignored = p
2472 ignored = p
2471 ignoredata = repo.dirstate._ignorefileandline(p)
2473 ignoredata = repo.dirstate._ignorefileandline(p)
2472 break
2474 break
2473 if ignored:
2475 if ignored:
2474 if ignored == f:
2476 if ignored == f:
2475 ui.write("%s is ignored\n" % f)
2477 ui.write("%s is ignored\n" % f)
2476 else:
2478 else:
2477 ui.write("%s is ignored because of containing folder %s\n"
2479 ui.write("%s is ignored because of containing folder %s\n"
2478 % (f, ignored))
2480 % (f, ignored))
2479 ignorefile, lineno, line = ignoredata
2481 ignorefile, lineno, line = ignoredata
2480 ui.write("(ignore rule in %s, line %d: '%s')\n"
2482 ui.write("(ignore rule in %s, line %d: '%s')\n"
2481 % (ignorefile, lineno, line))
2483 % (ignorefile, lineno, line))
2482 else:
2484 else:
2483 ui.write("%s is not ignored\n" % f)
2485 ui.write("%s is not ignored\n" % f)
2484
2486
2485 @command('debugindex', debugrevlogopts +
2487 @command('debugindex', debugrevlogopts +
2486 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2488 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2487 _('[-f FORMAT] -c|-m|FILE'),
2489 _('[-f FORMAT] -c|-m|FILE'),
2488 optionalrepo=True)
2490 optionalrepo=True)
2489 def debugindex(ui, repo, file_=None, **opts):
2491 def debugindex(ui, repo, file_=None, **opts):
2490 """dump the contents of an index file"""
2492 """dump the contents of an index file"""
2491 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2493 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2492 format = opts.get('format', 0)
2494 format = opts.get('format', 0)
2493 if format not in (0, 1):
2495 if format not in (0, 1):
2494 raise error.Abort(_("unknown format %d") % format)
2496 raise error.Abort(_("unknown format %d") % format)
2495
2497
2496 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2498 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2497 if generaldelta:
2499 if generaldelta:
2498 basehdr = ' delta'
2500 basehdr = ' delta'
2499 else:
2501 else:
2500 basehdr = ' base'
2502 basehdr = ' base'
2501
2503
2502 if ui.debugflag:
2504 if ui.debugflag:
2503 shortfn = hex
2505 shortfn = hex
2504 else:
2506 else:
2505 shortfn = short
2507 shortfn = short
2506
2508
2507 # There might not be anything in r, so have a sane default
2509 # There might not be anything in r, so have a sane default
2508 idlen = 12
2510 idlen = 12
2509 for i in r:
2511 for i in r:
2510 idlen = len(shortfn(r.node(i)))
2512 idlen = len(shortfn(r.node(i)))
2511 break
2513 break
2512
2514
2513 if format == 0:
2515 if format == 0:
2514 ui.write(" rev offset length " + basehdr + " linkrev"
2516 ui.write(" rev offset length " + basehdr + " linkrev"
2515 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2517 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2516 elif format == 1:
2518 elif format == 1:
2517 ui.write(" rev flag offset length"
2519 ui.write(" rev flag offset length"
2518 " size " + basehdr + " link p1 p2"
2520 " size " + basehdr + " link p1 p2"
2519 " %s\n" % "nodeid".rjust(idlen))
2521 " %s\n" % "nodeid".rjust(idlen))
2520
2522
2521 for i in r:
2523 for i in r:
2522 node = r.node(i)
2524 node = r.node(i)
2523 if generaldelta:
2525 if generaldelta:
2524 base = r.deltaparent(i)
2526 base = r.deltaparent(i)
2525 else:
2527 else:
2526 base = r.chainbase(i)
2528 base = r.chainbase(i)
2527 if format == 0:
2529 if format == 0:
2528 try:
2530 try:
2529 pp = r.parents(node)
2531 pp = r.parents(node)
2530 except Exception:
2532 except Exception:
2531 pp = [nullid, nullid]
2533 pp = [nullid, nullid]
2532 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2534 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2533 i, r.start(i), r.length(i), base, r.linkrev(i),
2535 i, r.start(i), r.length(i), base, r.linkrev(i),
2534 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2536 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2535 elif format == 1:
2537 elif format == 1:
2536 pr = r.parentrevs(i)
2538 pr = r.parentrevs(i)
2537 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2539 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2538 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2540 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2539 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2541 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2540
2542
2541 @command('debugindexdot', debugrevlogopts,
2543 @command('debugindexdot', debugrevlogopts,
2542 _('-c|-m|FILE'), optionalrepo=True)
2544 _('-c|-m|FILE'), optionalrepo=True)
2543 def debugindexdot(ui, repo, file_=None, **opts):
2545 def debugindexdot(ui, repo, file_=None, **opts):
2544 """dump an index DAG as a graphviz dot file"""
2546 """dump an index DAG as a graphviz dot file"""
2545 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2547 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2546 ui.write(("digraph G {\n"))
2548 ui.write(("digraph G {\n"))
2547 for i in r:
2549 for i in r:
2548 node = r.node(i)
2550 node = r.node(i)
2549 pp = r.parents(node)
2551 pp = r.parents(node)
2550 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2552 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2551 if pp[1] != nullid:
2553 if pp[1] != nullid:
2552 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2554 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2553 ui.write("}\n")
2555 ui.write("}\n")
2554
2556
2555 @command('debugdeltachain',
2557 @command('debugdeltachain',
2556 debugrevlogopts + formatteropts,
2558 debugrevlogopts + formatteropts,
2557 _('-c|-m|FILE'),
2559 _('-c|-m|FILE'),
2558 optionalrepo=True)
2560 optionalrepo=True)
2559 def debugdeltachain(ui, repo, file_=None, **opts):
2561 def debugdeltachain(ui, repo, file_=None, **opts):
2560 """dump information about delta chains in a revlog
2562 """dump information about delta chains in a revlog
2561
2563
2562 Output can be templatized. Available template keywords are:
2564 Output can be templatized. Available template keywords are:
2563
2565
2564 rev revision number
2566 rev revision number
2565 chainid delta chain identifier (numbered by unique base)
2567 chainid delta chain identifier (numbered by unique base)
2566 chainlen delta chain length to this revision
2568 chainlen delta chain length to this revision
2567 prevrev previous revision in delta chain
2569 prevrev previous revision in delta chain
2568 deltatype role of delta / how it was computed
2570 deltatype role of delta / how it was computed
2569 compsize compressed size of revision
2571 compsize compressed size of revision
2570 uncompsize uncompressed size of revision
2572 uncompsize uncompressed size of revision
2571 chainsize total size of compressed revisions in chain
2573 chainsize total size of compressed revisions in chain
2572 chainratio total chain size divided by uncompressed revision size
2574 chainratio total chain size divided by uncompressed revision size
2573 (new delta chains typically start at ratio 2.00)
2575 (new delta chains typically start at ratio 2.00)
2574 lindist linear distance from base revision in delta chain to end
2576 lindist linear distance from base revision in delta chain to end
2575 of this revision
2577 of this revision
2576 extradist total size of revisions not part of this delta chain from
2578 extradist total size of revisions not part of this delta chain from
2577 base of delta chain to end of this revision; a measurement
2579 base of delta chain to end of this revision; a measurement
2578 of how much extra data we need to read/seek across to read
2580 of how much extra data we need to read/seek across to read
2579 the delta chain for this revision
2581 the delta chain for this revision
2580 extraratio extradist divided by chainsize; another representation of
2582 extraratio extradist divided by chainsize; another representation of
2581 how much unrelated data is needed to load this delta chain
2583 how much unrelated data is needed to load this delta chain
2582 """
2584 """
2583 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2585 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2584 index = r.index
2586 index = r.index
2585 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2587 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2586
2588
2587 def revinfo(rev):
2589 def revinfo(rev):
2588 e = index[rev]
2590 e = index[rev]
2589 compsize = e[1]
2591 compsize = e[1]
2590 uncompsize = e[2]
2592 uncompsize = e[2]
2591 chainsize = 0
2593 chainsize = 0
2592
2594
2593 if generaldelta:
2595 if generaldelta:
2594 if e[3] == e[5]:
2596 if e[3] == e[5]:
2595 deltatype = 'p1'
2597 deltatype = 'p1'
2596 elif e[3] == e[6]:
2598 elif e[3] == e[6]:
2597 deltatype = 'p2'
2599 deltatype = 'p2'
2598 elif e[3] == rev - 1:
2600 elif e[3] == rev - 1:
2599 deltatype = 'prev'
2601 deltatype = 'prev'
2600 elif e[3] == rev:
2602 elif e[3] == rev:
2601 deltatype = 'base'
2603 deltatype = 'base'
2602 else:
2604 else:
2603 deltatype = 'other'
2605 deltatype = 'other'
2604 else:
2606 else:
2605 if e[3] == rev:
2607 if e[3] == rev:
2606 deltatype = 'base'
2608 deltatype = 'base'
2607 else:
2609 else:
2608 deltatype = 'prev'
2610 deltatype = 'prev'
2609
2611
2610 chain = r._deltachain(rev)[0]
2612 chain = r._deltachain(rev)[0]
2611 for iterrev in chain:
2613 for iterrev in chain:
2612 e = index[iterrev]
2614 e = index[iterrev]
2613 chainsize += e[1]
2615 chainsize += e[1]
2614
2616
2615 return compsize, uncompsize, deltatype, chain, chainsize
2617 return compsize, uncompsize, deltatype, chain, chainsize
2616
2618
2617 fm = ui.formatter('debugdeltachain', opts)
2619 fm = ui.formatter('debugdeltachain', opts)
2618
2620
2619 fm.plain(' rev chain# chainlen prev delta '
2621 fm.plain(' rev chain# chainlen prev delta '
2620 'size rawsize chainsize ratio lindist extradist '
2622 'size rawsize chainsize ratio lindist extradist '
2621 'extraratio\n')
2623 'extraratio\n')
2622
2624
2623 chainbases = {}
2625 chainbases = {}
2624 for rev in r:
2626 for rev in r:
2625 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2627 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2626 chainbase = chain[0]
2628 chainbase = chain[0]
2627 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2629 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2628 basestart = r.start(chainbase)
2630 basestart = r.start(chainbase)
2629 revstart = r.start(rev)
2631 revstart = r.start(rev)
2630 lineardist = revstart + comp - basestart
2632 lineardist = revstart + comp - basestart
2631 extradist = lineardist - chainsize
2633 extradist = lineardist - chainsize
2632 try:
2634 try:
2633 prevrev = chain[-2]
2635 prevrev = chain[-2]
2634 except IndexError:
2636 except IndexError:
2635 prevrev = -1
2637 prevrev = -1
2636
2638
2637 chainratio = float(chainsize) / float(uncomp)
2639 chainratio = float(chainsize) / float(uncomp)
2638 extraratio = float(extradist) / float(chainsize)
2640 extraratio = float(extradist) / float(chainsize)
2639
2641
2640 fm.startitem()
2642 fm.startitem()
2641 fm.write('rev chainid chainlen prevrev deltatype compsize '
2643 fm.write('rev chainid chainlen prevrev deltatype compsize '
2642 'uncompsize chainsize chainratio lindist extradist '
2644 'uncompsize chainsize chainratio lindist extradist '
2643 'extraratio',
2645 'extraratio',
2644 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2646 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2645 rev, chainid, len(chain), prevrev, deltatype, comp,
2647 rev, chainid, len(chain), prevrev, deltatype, comp,
2646 uncomp, chainsize, chainratio, lineardist, extradist,
2648 uncomp, chainsize, chainratio, lineardist, extradist,
2647 extraratio,
2649 extraratio,
2648 rev=rev, chainid=chainid, chainlen=len(chain),
2650 rev=rev, chainid=chainid, chainlen=len(chain),
2649 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2651 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2650 uncompsize=uncomp, chainsize=chainsize,
2652 uncompsize=uncomp, chainsize=chainsize,
2651 chainratio=chainratio, lindist=lineardist,
2653 chainratio=chainratio, lindist=lineardist,
2652 extradist=extradist, extraratio=extraratio)
2654 extradist=extradist, extraratio=extraratio)
2653
2655
2654 fm.end()
2656 fm.end()
2655
2657
2656 @command('debuginstall', [], '', norepo=True)
2658 @command('debuginstall', [], '', norepo=True)
2657 def debuginstall(ui):
2659 def debuginstall(ui):
2658 '''test Mercurial installation
2660 '''test Mercurial installation
2659
2661
2660 Returns 0 on success.
2662 Returns 0 on success.
2661 '''
2663 '''
2662
2664
2663 def writetemp(contents):
2665 def writetemp(contents):
2664 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2666 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2665 f = os.fdopen(fd, "wb")
2667 f = os.fdopen(fd, "wb")
2666 f.write(contents)
2668 f.write(contents)
2667 f.close()
2669 f.close()
2668 return name
2670 return name
2669
2671
2670 problems = 0
2672 problems = 0
2671
2673
2672 # encoding
2674 # encoding
2673 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2675 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2674 try:
2676 try:
2675 encoding.fromlocal("test")
2677 encoding.fromlocal("test")
2676 except error.Abort as inst:
2678 except error.Abort as inst:
2677 ui.write(" %s\n" % inst)
2679 ui.write(" %s\n" % inst)
2678 ui.write(_(" (check that your locale is properly set)\n"))
2680 ui.write(_(" (check that your locale is properly set)\n"))
2679 problems += 1
2681 problems += 1
2680
2682
2681 # Python
2683 # Python
2682 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2684 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2683 ui.status(_("checking Python version (%s)\n")
2685 ui.status(_("checking Python version (%s)\n")
2684 % ("%s.%s.%s" % sys.version_info[:3]))
2686 % ("%s.%s.%s" % sys.version_info[:3]))
2685 ui.status(_("checking Python lib (%s)...\n")
2687 ui.status(_("checking Python lib (%s)...\n")
2686 % os.path.dirname(os.__file__))
2688 % os.path.dirname(os.__file__))
2687
2689
2688 # compiled modules
2690 # compiled modules
2689 ui.status(_("checking installed modules (%s)...\n")
2691 ui.status(_("checking installed modules (%s)...\n")
2690 % os.path.dirname(__file__))
2692 % os.path.dirname(__file__))
2691 try:
2693 try:
2692 import bdiff, mpatch, base85, osutil
2694 import bdiff, mpatch, base85, osutil
2693 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2695 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2694 except Exception as inst:
2696 except Exception as inst:
2695 ui.write(" %s\n" % inst)
2697 ui.write(" %s\n" % inst)
2696 ui.write(_(" One or more extensions could not be found"))
2698 ui.write(_(" One or more extensions could not be found"))
2697 ui.write(_(" (check that you compiled the extensions)\n"))
2699 ui.write(_(" (check that you compiled the extensions)\n"))
2698 problems += 1
2700 problems += 1
2699
2701
2700 # templates
2702 # templates
2701 import templater
2703 import templater
2702 p = templater.templatepaths()
2704 p = templater.templatepaths()
2703 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2705 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2704 if p:
2706 if p:
2705 m = templater.templatepath("map-cmdline.default")
2707 m = templater.templatepath("map-cmdline.default")
2706 if m:
2708 if m:
2707 # template found, check if it is working
2709 # template found, check if it is working
2708 try:
2710 try:
2709 templater.templater(m)
2711 templater.templater(m)
2710 except Exception as inst:
2712 except Exception as inst:
2711 ui.write(" %s\n" % inst)
2713 ui.write(" %s\n" % inst)
2712 p = None
2714 p = None
2713 else:
2715 else:
2714 ui.write(_(" template 'default' not found\n"))
2716 ui.write(_(" template 'default' not found\n"))
2715 p = None
2717 p = None
2716 else:
2718 else:
2717 ui.write(_(" no template directories found\n"))
2719 ui.write(_(" no template directories found\n"))
2718 if not p:
2720 if not p:
2719 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2721 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2720 problems += 1
2722 problems += 1
2721
2723
2722 # editor
2724 # editor
2723 ui.status(_("checking commit editor...\n"))
2725 ui.status(_("checking commit editor...\n"))
2724 editor = ui.geteditor()
2726 editor = ui.geteditor()
2725 editor = util.expandpath(editor)
2727 editor = util.expandpath(editor)
2726 cmdpath = util.findexe(shlex.split(editor)[0])
2728 cmdpath = util.findexe(shlex.split(editor)[0])
2727 if not cmdpath:
2729 if not cmdpath:
2728 if editor == 'vi':
2730 if editor == 'vi':
2729 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2731 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2730 ui.write(_(" (specify a commit editor in your configuration"
2732 ui.write(_(" (specify a commit editor in your configuration"
2731 " file)\n"))
2733 " file)\n"))
2732 else:
2734 else:
2733 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2735 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2734 ui.write(_(" (specify a commit editor in your configuration"
2736 ui.write(_(" (specify a commit editor in your configuration"
2735 " file)\n"))
2737 " file)\n"))
2736 problems += 1
2738 problems += 1
2737
2739
2738 # check username
2740 # check username
2739 ui.status(_("checking username...\n"))
2741 ui.status(_("checking username...\n"))
2740 try:
2742 try:
2741 ui.username()
2743 ui.username()
2742 except error.Abort as e:
2744 except error.Abort as e:
2743 ui.write(" %s\n" % e)
2745 ui.write(" %s\n" % e)
2744 ui.write(_(" (specify a username in your configuration file)\n"))
2746 ui.write(_(" (specify a username in your configuration file)\n"))
2745 problems += 1
2747 problems += 1
2746
2748
2747 if not problems:
2749 if not problems:
2748 ui.status(_("no problems detected\n"))
2750 ui.status(_("no problems detected\n"))
2749 else:
2751 else:
2750 ui.write(_("%s problems detected,"
2752 ui.write(_("%s problems detected,"
2751 " please check your install!\n") % problems)
2753 " please check your install!\n") % problems)
2752
2754
2753 return problems
2755 return problems
2754
2756
2755 @command('debugknown', [], _('REPO ID...'), norepo=True)
2757 @command('debugknown', [], _('REPO ID...'), norepo=True)
2756 def debugknown(ui, repopath, *ids, **opts):
2758 def debugknown(ui, repopath, *ids, **opts):
2757 """test whether node ids are known to a repo
2759 """test whether node ids are known to a repo
2758
2760
2759 Every ID must be a full-length hex node id string. Returns a list of 0s
2761 Every ID must be a full-length hex node id string. Returns a list of 0s
2760 and 1s indicating unknown/known.
2762 and 1s indicating unknown/known.
2761 """
2763 """
2762 repo = hg.peer(ui, opts, repopath)
2764 repo = hg.peer(ui, opts, repopath)
2763 if not repo.capable('known'):
2765 if not repo.capable('known'):
2764 raise error.Abort("known() not supported by target repository")
2766 raise error.Abort("known() not supported by target repository")
2765 flags = repo.known([bin(s) for s in ids])
2767 flags = repo.known([bin(s) for s in ids])
2766 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2768 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2767
2769
2768 @command('debuglabelcomplete', [], _('LABEL...'))
2770 @command('debuglabelcomplete', [], _('LABEL...'))
2769 def debuglabelcomplete(ui, repo, *args):
2771 def debuglabelcomplete(ui, repo, *args):
2770 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2772 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2771 debugnamecomplete(ui, repo, *args)
2773 debugnamecomplete(ui, repo, *args)
2772
2774
2773 @command('debugmergestate', [], '')
2775 @command('debugmergestate', [], '')
2774 def debugmergestate(ui, repo, *args):
2776 def debugmergestate(ui, repo, *args):
2775 """print merge state
2777 """print merge state
2776
2778
2777 Use --verbose to print out information about whether v1 or v2 merge state
2779 Use --verbose to print out information about whether v1 or v2 merge state
2778 was chosen."""
2780 was chosen."""
2779 def _hashornull(h):
2781 def _hashornull(h):
2780 if h == nullhex:
2782 if h == nullhex:
2781 return 'null'
2783 return 'null'
2782 else:
2784 else:
2783 return h
2785 return h
2784
2786
2785 def printrecords(version):
2787 def printrecords(version):
2786 ui.write(('* version %s records\n') % version)
2788 ui.write(('* version %s records\n') % version)
2787 if version == 1:
2789 if version == 1:
2788 records = v1records
2790 records = v1records
2789 else:
2791 else:
2790 records = v2records
2792 records = v2records
2791
2793
2792 for rtype, record in records:
2794 for rtype, record in records:
2793 # pretty print some record types
2795 # pretty print some record types
2794 if rtype == 'L':
2796 if rtype == 'L':
2795 ui.write(('local: %s\n') % record)
2797 ui.write(('local: %s\n') % record)
2796 elif rtype == 'O':
2798 elif rtype == 'O':
2797 ui.write(('other: %s\n') % record)
2799 ui.write(('other: %s\n') % record)
2798 elif rtype == 'm':
2800 elif rtype == 'm':
2799 driver, mdstate = record.split('\0', 1)
2801 driver, mdstate = record.split('\0', 1)
2800 ui.write(('merge driver: %s (state "%s")\n')
2802 ui.write(('merge driver: %s (state "%s")\n')
2801 % (driver, mdstate))
2803 % (driver, mdstate))
2802 elif rtype in 'FDC':
2804 elif rtype in 'FDC':
2803 r = record.split('\0')
2805 r = record.split('\0')
2804 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2806 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2805 if version == 1:
2807 if version == 1:
2806 onode = 'not stored in v1 format'
2808 onode = 'not stored in v1 format'
2807 flags = r[7]
2809 flags = r[7]
2808 else:
2810 else:
2809 onode, flags = r[7:9]
2811 onode, flags = r[7:9]
2810 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2812 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2811 % (f, rtype, state, _hashornull(hash)))
2813 % (f, rtype, state, _hashornull(hash)))
2812 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2814 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2813 ui.write((' ancestor path: %s (node %s)\n')
2815 ui.write((' ancestor path: %s (node %s)\n')
2814 % (afile, _hashornull(anode)))
2816 % (afile, _hashornull(anode)))
2815 ui.write((' other path: %s (node %s)\n')
2817 ui.write((' other path: %s (node %s)\n')
2816 % (ofile, _hashornull(onode)))
2818 % (ofile, _hashornull(onode)))
2817 else:
2819 else:
2818 ui.write(('unrecognized entry: %s\t%s\n')
2820 ui.write(('unrecognized entry: %s\t%s\n')
2819 % (rtype, record.replace('\0', '\t')))
2821 % (rtype, record.replace('\0', '\t')))
2820
2822
2821 # Avoid mergestate.read() since it may raise an exception for unsupported
2823 # Avoid mergestate.read() since it may raise an exception for unsupported
2822 # merge state records. We shouldn't be doing this, but this is OK since this
2824 # merge state records. We shouldn't be doing this, but this is OK since this
2823 # command is pretty low-level.
2825 # command is pretty low-level.
2824 ms = mergemod.mergestate(repo)
2826 ms = mergemod.mergestate(repo)
2825
2827
2826 # sort so that reasonable information is on top
2828 # sort so that reasonable information is on top
2827 v1records = ms._readrecordsv1()
2829 v1records = ms._readrecordsv1()
2828 v2records = ms._readrecordsv2()
2830 v2records = ms._readrecordsv2()
2829 order = 'LOm'
2831 order = 'LOm'
2830 def key(r):
2832 def key(r):
2831 idx = order.find(r[0])
2833 idx = order.find(r[0])
2832 if idx == -1:
2834 if idx == -1:
2833 return (1, r[1])
2835 return (1, r[1])
2834 else:
2836 else:
2835 return (0, idx)
2837 return (0, idx)
2836 v1records.sort(key=key)
2838 v1records.sort(key=key)
2837 v2records.sort(key=key)
2839 v2records.sort(key=key)
2838
2840
2839 if not v1records and not v2records:
2841 if not v1records and not v2records:
2840 ui.write(('no merge state found\n'))
2842 ui.write(('no merge state found\n'))
2841 elif not v2records:
2843 elif not v2records:
2842 ui.note(('no version 2 merge state\n'))
2844 ui.note(('no version 2 merge state\n'))
2843 printrecords(1)
2845 printrecords(1)
2844 elif ms._v1v2match(v1records, v2records):
2846 elif ms._v1v2match(v1records, v2records):
2845 ui.note(('v1 and v2 states match: using v2\n'))
2847 ui.note(('v1 and v2 states match: using v2\n'))
2846 printrecords(2)
2848 printrecords(2)
2847 else:
2849 else:
2848 ui.note(('v1 and v2 states mismatch: using v1\n'))
2850 ui.note(('v1 and v2 states mismatch: using v1\n'))
2849 printrecords(1)
2851 printrecords(1)
2850 if ui.verbose:
2852 if ui.verbose:
2851 printrecords(2)
2853 printrecords(2)
2852
2854
2853 @command('debugnamecomplete', [], _('NAME...'))
2855 @command('debugnamecomplete', [], _('NAME...'))
2854 def debugnamecomplete(ui, repo, *args):
2856 def debugnamecomplete(ui, repo, *args):
2855 '''complete "names" - tags, open branch names, bookmark names'''
2857 '''complete "names" - tags, open branch names, bookmark names'''
2856
2858
2857 names = set()
2859 names = set()
2858 # since we previously only listed open branches, we will handle that
2860 # since we previously only listed open branches, we will handle that
2859 # specially (after this for loop)
2861 # specially (after this for loop)
2860 for name, ns in repo.names.iteritems():
2862 for name, ns in repo.names.iteritems():
2861 if name != 'branches':
2863 if name != 'branches':
2862 names.update(ns.listnames(repo))
2864 names.update(ns.listnames(repo))
2863 names.update(tag for (tag, heads, tip, closed)
2865 names.update(tag for (tag, heads, tip, closed)
2864 in repo.branchmap().iterbranches() if not closed)
2866 in repo.branchmap().iterbranches() if not closed)
2865 completions = set()
2867 completions = set()
2866 if not args:
2868 if not args:
2867 args = ['']
2869 args = ['']
2868 for a in args:
2870 for a in args:
2869 completions.update(n for n in names if n.startswith(a))
2871 completions.update(n for n in names if n.startswith(a))
2870 ui.write('\n'.join(sorted(completions)))
2872 ui.write('\n'.join(sorted(completions)))
2871 ui.write('\n')
2873 ui.write('\n')
2872
2874
2873 @command('debuglocks',
2875 @command('debuglocks',
2874 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2876 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2875 ('W', 'force-wlock', None,
2877 ('W', 'force-wlock', None,
2876 _('free the working state lock (DANGEROUS)'))],
2878 _('free the working state lock (DANGEROUS)'))],
2877 _('[OPTION]...'))
2879 _('[OPTION]...'))
2878 def debuglocks(ui, repo, **opts):
2880 def debuglocks(ui, repo, **opts):
2879 """show or modify state of locks
2881 """show or modify state of locks
2880
2882
2881 By default, this command will show which locks are held. This
2883 By default, this command will show which locks are held. This
2882 includes the user and process holding the lock, the amount of time
2884 includes the user and process holding the lock, the amount of time
2883 the lock has been held, and the machine name where the process is
2885 the lock has been held, and the machine name where the process is
2884 running if it's not local.
2886 running if it's not local.
2885
2887
2886 Locks protect the integrity of Mercurial's data, so should be
2888 Locks protect the integrity of Mercurial's data, so should be
2887 treated with care. System crashes or other interruptions may cause
2889 treated with care. System crashes or other interruptions may cause
2888 locks to not be properly released, though Mercurial will usually
2890 locks to not be properly released, though Mercurial will usually
2889 detect and remove such stale locks automatically.
2891 detect and remove such stale locks automatically.
2890
2892
2891 However, detecting stale locks may not always be possible (for
2893 However, detecting stale locks may not always be possible (for
2892 instance, on a shared filesystem). Removing locks may also be
2894 instance, on a shared filesystem). Removing locks may also be
2893 blocked by filesystem permissions.
2895 blocked by filesystem permissions.
2894
2896
2895 Returns 0 if no locks are held.
2897 Returns 0 if no locks are held.
2896
2898
2897 """
2899 """
2898
2900
2899 if opts.get('force_lock'):
2901 if opts.get('force_lock'):
2900 repo.svfs.unlink('lock')
2902 repo.svfs.unlink('lock')
2901 if opts.get('force_wlock'):
2903 if opts.get('force_wlock'):
2902 repo.vfs.unlink('wlock')
2904 repo.vfs.unlink('wlock')
2903 if opts.get('force_lock') or opts.get('force_lock'):
2905 if opts.get('force_lock') or opts.get('force_lock'):
2904 return 0
2906 return 0
2905
2907
2906 now = time.time()
2908 now = time.time()
2907 held = 0
2909 held = 0
2908
2910
2909 def report(vfs, name, method):
2911 def report(vfs, name, method):
2910 # this causes stale locks to get reaped for more accurate reporting
2912 # this causes stale locks to get reaped for more accurate reporting
2911 try:
2913 try:
2912 l = method(False)
2914 l = method(False)
2913 except error.LockHeld:
2915 except error.LockHeld:
2914 l = None
2916 l = None
2915
2917
2916 if l:
2918 if l:
2917 l.release()
2919 l.release()
2918 else:
2920 else:
2919 try:
2921 try:
2920 stat = vfs.lstat(name)
2922 stat = vfs.lstat(name)
2921 age = now - stat.st_mtime
2923 age = now - stat.st_mtime
2922 user = util.username(stat.st_uid)
2924 user = util.username(stat.st_uid)
2923 locker = vfs.readlock(name)
2925 locker = vfs.readlock(name)
2924 if ":" in locker:
2926 if ":" in locker:
2925 host, pid = locker.split(':')
2927 host, pid = locker.split(':')
2926 if host == socket.gethostname():
2928 if host == socket.gethostname():
2927 locker = 'user %s, process %s' % (user, pid)
2929 locker = 'user %s, process %s' % (user, pid)
2928 else:
2930 else:
2929 locker = 'user %s, process %s, host %s' \
2931 locker = 'user %s, process %s, host %s' \
2930 % (user, pid, host)
2932 % (user, pid, host)
2931 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2933 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2932 return 1
2934 return 1
2933 except OSError as e:
2935 except OSError as e:
2934 if e.errno != errno.ENOENT:
2936 if e.errno != errno.ENOENT:
2935 raise
2937 raise
2936
2938
2937 ui.write("%-6s free\n" % (name + ":"))
2939 ui.write("%-6s free\n" % (name + ":"))
2938 return 0
2940 return 0
2939
2941
2940 held += report(repo.svfs, "lock", repo.lock)
2942 held += report(repo.svfs, "lock", repo.lock)
2941 held += report(repo.vfs, "wlock", repo.wlock)
2943 held += report(repo.vfs, "wlock", repo.wlock)
2942
2944
2943 return held
2945 return held
2944
2946
2945 @command('debugobsolete',
2947 @command('debugobsolete',
2946 [('', 'flags', 0, _('markers flag')),
2948 [('', 'flags', 0, _('markers flag')),
2947 ('', 'record-parents', False,
2949 ('', 'record-parents', False,
2948 _('record parent information for the precursor')),
2950 _('record parent information for the precursor')),
2949 ('r', 'rev', [], _('display markers relevant to REV')),
2951 ('r', 'rev', [], _('display markers relevant to REV')),
2950 ] + commitopts2,
2952 ] + commitopts2,
2951 _('[OBSOLETED [REPLACEMENT ...]]'))
2953 _('[OBSOLETED [REPLACEMENT ...]]'))
2952 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2954 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2953 """create arbitrary obsolete marker
2955 """create arbitrary obsolete marker
2954
2956
2955 With no arguments, displays the list of obsolescence markers."""
2957 With no arguments, displays the list of obsolescence markers."""
2956
2958
2957 def parsenodeid(s):
2959 def parsenodeid(s):
2958 try:
2960 try:
2959 # We do not use revsingle/revrange functions here to accept
2961 # We do not use revsingle/revrange functions here to accept
2960 # arbitrary node identifiers, possibly not present in the
2962 # arbitrary node identifiers, possibly not present in the
2961 # local repository.
2963 # local repository.
2962 n = bin(s)
2964 n = bin(s)
2963 if len(n) != len(nullid):
2965 if len(n) != len(nullid):
2964 raise TypeError()
2966 raise TypeError()
2965 return n
2967 return n
2966 except TypeError:
2968 except TypeError:
2967 raise error.Abort('changeset references must be full hexadecimal '
2969 raise error.Abort('changeset references must be full hexadecimal '
2968 'node identifiers')
2970 'node identifiers')
2969
2971
2970 if precursor is not None:
2972 if precursor is not None:
2971 if opts['rev']:
2973 if opts['rev']:
2972 raise error.Abort('cannot select revision when creating marker')
2974 raise error.Abort('cannot select revision when creating marker')
2973 metadata = {}
2975 metadata = {}
2974 metadata['user'] = opts['user'] or ui.username()
2976 metadata['user'] = opts['user'] or ui.username()
2975 succs = tuple(parsenodeid(succ) for succ in successors)
2977 succs = tuple(parsenodeid(succ) for succ in successors)
2976 l = repo.lock()
2978 l = repo.lock()
2977 try:
2979 try:
2978 tr = repo.transaction('debugobsolete')
2980 tr = repo.transaction('debugobsolete')
2979 try:
2981 try:
2980 date = opts.get('date')
2982 date = opts.get('date')
2981 if date:
2983 if date:
2982 date = util.parsedate(date)
2984 date = util.parsedate(date)
2983 else:
2985 else:
2984 date = None
2986 date = None
2985 prec = parsenodeid(precursor)
2987 prec = parsenodeid(precursor)
2986 parents = None
2988 parents = None
2987 if opts['record_parents']:
2989 if opts['record_parents']:
2988 if prec not in repo.unfiltered():
2990 if prec not in repo.unfiltered():
2989 raise error.Abort('cannot used --record-parents on '
2991 raise error.Abort('cannot used --record-parents on '
2990 'unknown changesets')
2992 'unknown changesets')
2991 parents = repo.unfiltered()[prec].parents()
2993 parents = repo.unfiltered()[prec].parents()
2992 parents = tuple(p.node() for p in parents)
2994 parents = tuple(p.node() for p in parents)
2993 repo.obsstore.create(tr, prec, succs, opts['flags'],
2995 repo.obsstore.create(tr, prec, succs, opts['flags'],
2994 parents=parents, date=date,
2996 parents=parents, date=date,
2995 metadata=metadata)
2997 metadata=metadata)
2996 tr.close()
2998 tr.close()
2997 except ValueError as exc:
2999 except ValueError as exc:
2998 raise error.Abort(_('bad obsmarker input: %s') % exc)
3000 raise error.Abort(_('bad obsmarker input: %s') % exc)
2999 finally:
3001 finally:
3000 tr.release()
3002 tr.release()
3001 finally:
3003 finally:
3002 l.release()
3004 l.release()
3003 else:
3005 else:
3004 if opts['rev']:
3006 if opts['rev']:
3005 revs = scmutil.revrange(repo, opts['rev'])
3007 revs = scmutil.revrange(repo, opts['rev'])
3006 nodes = [repo[r].node() for r in revs]
3008 nodes = [repo[r].node() for r in revs]
3007 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3009 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3008 markers.sort(key=lambda x: x._data)
3010 markers.sort(key=lambda x: x._data)
3009 else:
3011 else:
3010 markers = obsolete.getmarkers(repo)
3012 markers = obsolete.getmarkers(repo)
3011
3013
3012 for m in markers:
3014 for m in markers:
3013 cmdutil.showmarker(ui, m)
3015 cmdutil.showmarker(ui, m)
3014
3016
3015 @command('debugpathcomplete',
3017 @command('debugpathcomplete',
3016 [('f', 'full', None, _('complete an entire path')),
3018 [('f', 'full', None, _('complete an entire path')),
3017 ('n', 'normal', None, _('show only normal files')),
3019 ('n', 'normal', None, _('show only normal files')),
3018 ('a', 'added', None, _('show only added files')),
3020 ('a', 'added', None, _('show only added files')),
3019 ('r', 'removed', None, _('show only removed files'))],
3021 ('r', 'removed', None, _('show only removed files'))],
3020 _('FILESPEC...'))
3022 _('FILESPEC...'))
3021 def debugpathcomplete(ui, repo, *specs, **opts):
3023 def debugpathcomplete(ui, repo, *specs, **opts):
3022 '''complete part or all of a tracked path
3024 '''complete part or all of a tracked path
3023
3025
3024 This command supports shells that offer path name completion. It
3026 This command supports shells that offer path name completion. It
3025 currently completes only files already known to the dirstate.
3027 currently completes only files already known to the dirstate.
3026
3028
3027 Completion extends only to the next path segment unless
3029 Completion extends only to the next path segment unless
3028 --full is specified, in which case entire paths are used.'''
3030 --full is specified, in which case entire paths are used.'''
3029
3031
3030 def complete(path, acceptable):
3032 def complete(path, acceptable):
3031 dirstate = repo.dirstate
3033 dirstate = repo.dirstate
3032 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3034 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3033 rootdir = repo.root + os.sep
3035 rootdir = repo.root + os.sep
3034 if spec != repo.root and not spec.startswith(rootdir):
3036 if spec != repo.root and not spec.startswith(rootdir):
3035 return [], []
3037 return [], []
3036 if os.path.isdir(spec):
3038 if os.path.isdir(spec):
3037 spec += '/'
3039 spec += '/'
3038 spec = spec[len(rootdir):]
3040 spec = spec[len(rootdir):]
3039 fixpaths = os.sep != '/'
3041 fixpaths = os.sep != '/'
3040 if fixpaths:
3042 if fixpaths:
3041 spec = spec.replace(os.sep, '/')
3043 spec = spec.replace(os.sep, '/')
3042 speclen = len(spec)
3044 speclen = len(spec)
3043 fullpaths = opts['full']
3045 fullpaths = opts['full']
3044 files, dirs = set(), set()
3046 files, dirs = set(), set()
3045 adddir, addfile = dirs.add, files.add
3047 adddir, addfile = dirs.add, files.add
3046 for f, st in dirstate.iteritems():
3048 for f, st in dirstate.iteritems():
3047 if f.startswith(spec) and st[0] in acceptable:
3049 if f.startswith(spec) and st[0] in acceptable:
3048 if fixpaths:
3050 if fixpaths:
3049 f = f.replace('/', os.sep)
3051 f = f.replace('/', os.sep)
3050 if fullpaths:
3052 if fullpaths:
3051 addfile(f)
3053 addfile(f)
3052 continue
3054 continue
3053 s = f.find(os.sep, speclen)
3055 s = f.find(os.sep, speclen)
3054 if s >= 0:
3056 if s >= 0:
3055 adddir(f[:s])
3057 adddir(f[:s])
3056 else:
3058 else:
3057 addfile(f)
3059 addfile(f)
3058 return files, dirs
3060 return files, dirs
3059
3061
3060 acceptable = ''
3062 acceptable = ''
3061 if opts['normal']:
3063 if opts['normal']:
3062 acceptable += 'nm'
3064 acceptable += 'nm'
3063 if opts['added']:
3065 if opts['added']:
3064 acceptable += 'a'
3066 acceptable += 'a'
3065 if opts['removed']:
3067 if opts['removed']:
3066 acceptable += 'r'
3068 acceptable += 'r'
3067 cwd = repo.getcwd()
3069 cwd = repo.getcwd()
3068 if not specs:
3070 if not specs:
3069 specs = ['.']
3071 specs = ['.']
3070
3072
3071 files, dirs = set(), set()
3073 files, dirs = set(), set()
3072 for spec in specs:
3074 for spec in specs:
3073 f, d = complete(spec, acceptable or 'nmar')
3075 f, d = complete(spec, acceptable or 'nmar')
3074 files.update(f)
3076 files.update(f)
3075 dirs.update(d)
3077 dirs.update(d)
3076 files.update(dirs)
3078 files.update(dirs)
3077 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3079 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3078 ui.write('\n')
3080 ui.write('\n')
3079
3081
3080 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3082 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3081 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3083 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3082 '''access the pushkey key/value protocol
3084 '''access the pushkey key/value protocol
3083
3085
3084 With two args, list the keys in the given namespace.
3086 With two args, list the keys in the given namespace.
3085
3087
3086 With five args, set a key to new if it currently is set to old.
3088 With five args, set a key to new if it currently is set to old.
3087 Reports success or failure.
3089 Reports success or failure.
3088 '''
3090 '''
3089
3091
3090 target = hg.peer(ui, {}, repopath)
3092 target = hg.peer(ui, {}, repopath)
3091 if keyinfo:
3093 if keyinfo:
3092 key, old, new = keyinfo
3094 key, old, new = keyinfo
3093 r = target.pushkey(namespace, key, old, new)
3095 r = target.pushkey(namespace, key, old, new)
3094 ui.status(str(r) + '\n')
3096 ui.status(str(r) + '\n')
3095 return not r
3097 return not r
3096 else:
3098 else:
3097 for k, v in sorted(target.listkeys(namespace).iteritems()):
3099 for k, v in sorted(target.listkeys(namespace).iteritems()):
3098 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3100 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3099 v.encode('string-escape')))
3101 v.encode('string-escape')))
3100
3102
3101 @command('debugpvec', [], _('A B'))
3103 @command('debugpvec', [], _('A B'))
3102 def debugpvec(ui, repo, a, b=None):
3104 def debugpvec(ui, repo, a, b=None):
3103 ca = scmutil.revsingle(repo, a)
3105 ca = scmutil.revsingle(repo, a)
3104 cb = scmutil.revsingle(repo, b)
3106 cb = scmutil.revsingle(repo, b)
3105 pa = pvec.ctxpvec(ca)
3107 pa = pvec.ctxpvec(ca)
3106 pb = pvec.ctxpvec(cb)
3108 pb = pvec.ctxpvec(cb)
3107 if pa == pb:
3109 if pa == pb:
3108 rel = "="
3110 rel = "="
3109 elif pa > pb:
3111 elif pa > pb:
3110 rel = ">"
3112 rel = ">"
3111 elif pa < pb:
3113 elif pa < pb:
3112 rel = "<"
3114 rel = "<"
3113 elif pa | pb:
3115 elif pa | pb:
3114 rel = "|"
3116 rel = "|"
3115 ui.write(_("a: %s\n") % pa)
3117 ui.write(_("a: %s\n") % pa)
3116 ui.write(_("b: %s\n") % pb)
3118 ui.write(_("b: %s\n") % pb)
3117 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3119 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3118 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3120 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3119 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3121 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3120 pa.distance(pb), rel))
3122 pa.distance(pb), rel))
3121
3123
3122 @command('debugrebuilddirstate|debugrebuildstate',
3124 @command('debugrebuilddirstate|debugrebuildstate',
3123 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3125 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3124 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3126 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3125 'the working copy parent')),
3127 'the working copy parent')),
3126 ],
3128 ],
3127 _('[-r REV]'))
3129 _('[-r REV]'))
3128 def debugrebuilddirstate(ui, repo, rev, **opts):
3130 def debugrebuilddirstate(ui, repo, rev, **opts):
3129 """rebuild the dirstate as it would look like for the given revision
3131 """rebuild the dirstate as it would look like for the given revision
3130
3132
3131 If no revision is specified the first current parent will be used.
3133 If no revision is specified the first current parent will be used.
3132
3134
3133 The dirstate will be set to the files of the given revision.
3135 The dirstate will be set to the files of the given revision.
3134 The actual working directory content or existing dirstate
3136 The actual working directory content or existing dirstate
3135 information such as adds or removes is not considered.
3137 information such as adds or removes is not considered.
3136
3138
3137 ``minimal`` will only rebuild the dirstate status for files that claim to be
3139 ``minimal`` will only rebuild the dirstate status for files that claim to be
3138 tracked but are not in the parent manifest, or that exist in the parent
3140 tracked but are not in the parent manifest, or that exist in the parent
3139 manifest but are not in the dirstate. It will not change adds, removes, or
3141 manifest but are not in the dirstate. It will not change adds, removes, or
3140 modified files that are in the working copy parent.
3142 modified files that are in the working copy parent.
3141
3143
3142 One use of this command is to make the next :hg:`status` invocation
3144 One use of this command is to make the next :hg:`status` invocation
3143 check the actual file content.
3145 check the actual file content.
3144 """
3146 """
3145 ctx = scmutil.revsingle(repo, rev)
3147 ctx = scmutil.revsingle(repo, rev)
3146 with repo.wlock():
3148 with repo.wlock():
3147 dirstate = repo.dirstate
3149 dirstate = repo.dirstate
3148 changedfiles = None
3150 changedfiles = None
3149 # See command doc for what minimal does.
3151 # See command doc for what minimal does.
3150 if opts.get('minimal'):
3152 if opts.get('minimal'):
3151 manifestfiles = set(ctx.manifest().keys())
3153 manifestfiles = set(ctx.manifest().keys())
3152 dirstatefiles = set(dirstate)
3154 dirstatefiles = set(dirstate)
3153 manifestonly = manifestfiles - dirstatefiles
3155 manifestonly = manifestfiles - dirstatefiles
3154 dsonly = dirstatefiles - manifestfiles
3156 dsonly = dirstatefiles - manifestfiles
3155 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3157 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3156 changedfiles = manifestonly | dsnotadded
3158 changedfiles = manifestonly | dsnotadded
3157
3159
3158 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3160 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3159
3161
3160 @command('debugrebuildfncache', [], '')
3162 @command('debugrebuildfncache', [], '')
3161 def debugrebuildfncache(ui, repo):
3163 def debugrebuildfncache(ui, repo):
3162 """rebuild the fncache file"""
3164 """rebuild the fncache file"""
3163 repair.rebuildfncache(ui, repo)
3165 repair.rebuildfncache(ui, repo)
3164
3166
3165 @command('debugrename',
3167 @command('debugrename',
3166 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3168 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3167 _('[-r REV] FILE'))
3169 _('[-r REV] FILE'))
3168 def debugrename(ui, repo, file1, *pats, **opts):
3170 def debugrename(ui, repo, file1, *pats, **opts):
3169 """dump rename information"""
3171 """dump rename information"""
3170
3172
3171 ctx = scmutil.revsingle(repo, opts.get('rev'))
3173 ctx = scmutil.revsingle(repo, opts.get('rev'))
3172 m = scmutil.match(ctx, (file1,) + pats, opts)
3174 m = scmutil.match(ctx, (file1,) + pats, opts)
3173 for abs in ctx.walk(m):
3175 for abs in ctx.walk(m):
3174 fctx = ctx[abs]
3176 fctx = ctx[abs]
3175 o = fctx.filelog().renamed(fctx.filenode())
3177 o = fctx.filelog().renamed(fctx.filenode())
3176 rel = m.rel(abs)
3178 rel = m.rel(abs)
3177 if o:
3179 if o:
3178 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3180 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3179 else:
3181 else:
3180 ui.write(_("%s not renamed\n") % rel)
3182 ui.write(_("%s not renamed\n") % rel)
3181
3183
3182 @command('debugrevlog', debugrevlogopts +
3184 @command('debugrevlog', debugrevlogopts +
3183 [('d', 'dump', False, _('dump index data'))],
3185 [('d', 'dump', False, _('dump index data'))],
3184 _('-c|-m|FILE'),
3186 _('-c|-m|FILE'),
3185 optionalrepo=True)
3187 optionalrepo=True)
3186 def debugrevlog(ui, repo, file_=None, **opts):
3188 def debugrevlog(ui, repo, file_=None, **opts):
3187 """show data and statistics about a revlog"""
3189 """show data and statistics about a revlog"""
3188 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3190 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3189
3191
3190 if opts.get("dump"):
3192 if opts.get("dump"):
3191 numrevs = len(r)
3193 numrevs = len(r)
3192 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3194 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3193 " rawsize totalsize compression heads chainlen\n")
3195 " rawsize totalsize compression heads chainlen\n")
3194 ts = 0
3196 ts = 0
3195 heads = set()
3197 heads = set()
3196
3198
3197 for rev in xrange(numrevs):
3199 for rev in xrange(numrevs):
3198 dbase = r.deltaparent(rev)
3200 dbase = r.deltaparent(rev)
3199 if dbase == -1:
3201 if dbase == -1:
3200 dbase = rev
3202 dbase = rev
3201 cbase = r.chainbase(rev)
3203 cbase = r.chainbase(rev)
3202 clen = r.chainlen(rev)
3204 clen = r.chainlen(rev)
3203 p1, p2 = r.parentrevs(rev)
3205 p1, p2 = r.parentrevs(rev)
3204 rs = r.rawsize(rev)
3206 rs = r.rawsize(rev)
3205 ts = ts + rs
3207 ts = ts + rs
3206 heads -= set(r.parentrevs(rev))
3208 heads -= set(r.parentrevs(rev))
3207 heads.add(rev)
3209 heads.add(rev)
3208 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3210 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3209 "%11d %5d %8d\n" %
3211 "%11d %5d %8d\n" %
3210 (rev, p1, p2, r.start(rev), r.end(rev),
3212 (rev, p1, p2, r.start(rev), r.end(rev),
3211 r.start(dbase), r.start(cbase),
3213 r.start(dbase), r.start(cbase),
3212 r.start(p1), r.start(p2),
3214 r.start(p1), r.start(p2),
3213 rs, ts, ts / r.end(rev), len(heads), clen))
3215 rs, ts, ts / r.end(rev), len(heads), clen))
3214 return 0
3216 return 0
3215
3217
3216 v = r.version
3218 v = r.version
3217 format = v & 0xFFFF
3219 format = v & 0xFFFF
3218 flags = []
3220 flags = []
3219 gdelta = False
3221 gdelta = False
3220 if v & revlog.REVLOGNGINLINEDATA:
3222 if v & revlog.REVLOGNGINLINEDATA:
3221 flags.append('inline')
3223 flags.append('inline')
3222 if v & revlog.REVLOGGENERALDELTA:
3224 if v & revlog.REVLOGGENERALDELTA:
3223 gdelta = True
3225 gdelta = True
3224 flags.append('generaldelta')
3226 flags.append('generaldelta')
3225 if not flags:
3227 if not flags:
3226 flags = ['(none)']
3228 flags = ['(none)']
3227
3229
3228 nummerges = 0
3230 nummerges = 0
3229 numfull = 0
3231 numfull = 0
3230 numprev = 0
3232 numprev = 0
3231 nump1 = 0
3233 nump1 = 0
3232 nump2 = 0
3234 nump2 = 0
3233 numother = 0
3235 numother = 0
3234 nump1prev = 0
3236 nump1prev = 0
3235 nump2prev = 0
3237 nump2prev = 0
3236 chainlengths = []
3238 chainlengths = []
3237
3239
3238 datasize = [None, 0, 0L]
3240 datasize = [None, 0, 0L]
3239 fullsize = [None, 0, 0L]
3241 fullsize = [None, 0, 0L]
3240 deltasize = [None, 0, 0L]
3242 deltasize = [None, 0, 0L]
3241
3243
3242 def addsize(size, l):
3244 def addsize(size, l):
3243 if l[0] is None or size < l[0]:
3245 if l[0] is None or size < l[0]:
3244 l[0] = size
3246 l[0] = size
3245 if size > l[1]:
3247 if size > l[1]:
3246 l[1] = size
3248 l[1] = size
3247 l[2] += size
3249 l[2] += size
3248
3250
3249 numrevs = len(r)
3251 numrevs = len(r)
3250 for rev in xrange(numrevs):
3252 for rev in xrange(numrevs):
3251 p1, p2 = r.parentrevs(rev)
3253 p1, p2 = r.parentrevs(rev)
3252 delta = r.deltaparent(rev)
3254 delta = r.deltaparent(rev)
3253 if format > 0:
3255 if format > 0:
3254 addsize(r.rawsize(rev), datasize)
3256 addsize(r.rawsize(rev), datasize)
3255 if p2 != nullrev:
3257 if p2 != nullrev:
3256 nummerges += 1
3258 nummerges += 1
3257 size = r.length(rev)
3259 size = r.length(rev)
3258 if delta == nullrev:
3260 if delta == nullrev:
3259 chainlengths.append(0)
3261 chainlengths.append(0)
3260 numfull += 1
3262 numfull += 1
3261 addsize(size, fullsize)
3263 addsize(size, fullsize)
3262 else:
3264 else:
3263 chainlengths.append(chainlengths[delta] + 1)
3265 chainlengths.append(chainlengths[delta] + 1)
3264 addsize(size, deltasize)
3266 addsize(size, deltasize)
3265 if delta == rev - 1:
3267 if delta == rev - 1:
3266 numprev += 1
3268 numprev += 1
3267 if delta == p1:
3269 if delta == p1:
3268 nump1prev += 1
3270 nump1prev += 1
3269 elif delta == p2:
3271 elif delta == p2:
3270 nump2prev += 1
3272 nump2prev += 1
3271 elif delta == p1:
3273 elif delta == p1:
3272 nump1 += 1
3274 nump1 += 1
3273 elif delta == p2:
3275 elif delta == p2:
3274 nump2 += 1
3276 nump2 += 1
3275 elif delta != nullrev:
3277 elif delta != nullrev:
3276 numother += 1
3278 numother += 1
3277
3279
3278 # Adjust size min value for empty cases
3280 # Adjust size min value for empty cases
3279 for size in (datasize, fullsize, deltasize):
3281 for size in (datasize, fullsize, deltasize):
3280 if size[0] is None:
3282 if size[0] is None:
3281 size[0] = 0
3283 size[0] = 0
3282
3284
3283 numdeltas = numrevs - numfull
3285 numdeltas = numrevs - numfull
3284 numoprev = numprev - nump1prev - nump2prev
3286 numoprev = numprev - nump1prev - nump2prev
3285 totalrawsize = datasize[2]
3287 totalrawsize = datasize[2]
3286 datasize[2] /= numrevs
3288 datasize[2] /= numrevs
3287 fulltotal = fullsize[2]
3289 fulltotal = fullsize[2]
3288 fullsize[2] /= numfull
3290 fullsize[2] /= numfull
3289 deltatotal = deltasize[2]
3291 deltatotal = deltasize[2]
3290 if numrevs - numfull > 0:
3292 if numrevs - numfull > 0:
3291 deltasize[2] /= numrevs - numfull
3293 deltasize[2] /= numrevs - numfull
3292 totalsize = fulltotal + deltatotal
3294 totalsize = fulltotal + deltatotal
3293 avgchainlen = sum(chainlengths) / numrevs
3295 avgchainlen = sum(chainlengths) / numrevs
3294 maxchainlen = max(chainlengths)
3296 maxchainlen = max(chainlengths)
3295 compratio = 1
3297 compratio = 1
3296 if totalsize:
3298 if totalsize:
3297 compratio = totalrawsize / totalsize
3299 compratio = totalrawsize / totalsize
3298
3300
3299 basedfmtstr = '%%%dd\n'
3301 basedfmtstr = '%%%dd\n'
3300 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3302 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3301
3303
3302 def dfmtstr(max):
3304 def dfmtstr(max):
3303 return basedfmtstr % len(str(max))
3305 return basedfmtstr % len(str(max))
3304 def pcfmtstr(max, padding=0):
3306 def pcfmtstr(max, padding=0):
3305 return basepcfmtstr % (len(str(max)), ' ' * padding)
3307 return basepcfmtstr % (len(str(max)), ' ' * padding)
3306
3308
3307 def pcfmt(value, total):
3309 def pcfmt(value, total):
3308 if total:
3310 if total:
3309 return (value, 100 * float(value) / total)
3311 return (value, 100 * float(value) / total)
3310 else:
3312 else:
3311 return value, 100.0
3313 return value, 100.0
3312
3314
3313 ui.write(('format : %d\n') % format)
3315 ui.write(('format : %d\n') % format)
3314 ui.write(('flags : %s\n') % ', '.join(flags))
3316 ui.write(('flags : %s\n') % ', '.join(flags))
3315
3317
3316 ui.write('\n')
3318 ui.write('\n')
3317 fmt = pcfmtstr(totalsize)
3319 fmt = pcfmtstr(totalsize)
3318 fmt2 = dfmtstr(totalsize)
3320 fmt2 = dfmtstr(totalsize)
3319 ui.write(('revisions : ') + fmt2 % numrevs)
3321 ui.write(('revisions : ') + fmt2 % numrevs)
3320 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3322 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3321 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3323 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3322 ui.write(('revisions : ') + fmt2 % numrevs)
3324 ui.write(('revisions : ') + fmt2 % numrevs)
3323 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3325 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3324 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3326 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3325 ui.write(('revision size : ') + fmt2 % totalsize)
3327 ui.write(('revision size : ') + fmt2 % totalsize)
3326 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3328 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3327 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3329 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3328
3330
3329 ui.write('\n')
3331 ui.write('\n')
3330 fmt = dfmtstr(max(avgchainlen, compratio))
3332 fmt = dfmtstr(max(avgchainlen, compratio))
3331 ui.write(('avg chain length : ') + fmt % avgchainlen)
3333 ui.write(('avg chain length : ') + fmt % avgchainlen)
3332 ui.write(('max chain length : ') + fmt % maxchainlen)
3334 ui.write(('max chain length : ') + fmt % maxchainlen)
3333 ui.write(('compression ratio : ') + fmt % compratio)
3335 ui.write(('compression ratio : ') + fmt % compratio)
3334
3336
3335 if format > 0:
3337 if format > 0:
3336 ui.write('\n')
3338 ui.write('\n')
3337 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3339 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3338 % tuple(datasize))
3340 % tuple(datasize))
3339 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3341 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3340 % tuple(fullsize))
3342 % tuple(fullsize))
3341 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3343 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3342 % tuple(deltasize))
3344 % tuple(deltasize))
3343
3345
3344 if numdeltas > 0:
3346 if numdeltas > 0:
3345 ui.write('\n')
3347 ui.write('\n')
3346 fmt = pcfmtstr(numdeltas)
3348 fmt = pcfmtstr(numdeltas)
3347 fmt2 = pcfmtstr(numdeltas, 4)
3349 fmt2 = pcfmtstr(numdeltas, 4)
3348 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3350 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3349 if numprev > 0:
3351 if numprev > 0:
3350 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3352 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3351 numprev))
3353 numprev))
3352 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3354 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3353 numprev))
3355 numprev))
3354 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3356 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3355 numprev))
3357 numprev))
3356 if gdelta:
3358 if gdelta:
3357 ui.write(('deltas against p1 : ')
3359 ui.write(('deltas against p1 : ')
3358 + fmt % pcfmt(nump1, numdeltas))
3360 + fmt % pcfmt(nump1, numdeltas))
3359 ui.write(('deltas against p2 : ')
3361 ui.write(('deltas against p2 : ')
3360 + fmt % pcfmt(nump2, numdeltas))
3362 + fmt % pcfmt(nump2, numdeltas))
3361 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3363 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3362 numdeltas))
3364 numdeltas))
3363
3365
3364 @command('debugrevspec',
3366 @command('debugrevspec',
3365 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3367 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3366 ('REVSPEC'))
3368 ('REVSPEC'))
3367 def debugrevspec(ui, repo, expr, **opts):
3369 def debugrevspec(ui, repo, expr, **opts):
3368 """parse and apply a revision specification
3370 """parse and apply a revision specification
3369
3371
3370 Use --verbose to print the parsed tree before and after aliases
3372 Use --verbose to print the parsed tree before and after aliases
3371 expansion.
3373 expansion.
3372 """
3374 """
3373 if ui.verbose:
3375 if ui.verbose:
3374 tree = revset.parse(expr, lookup=repo.__contains__)
3376 tree = revset.parse(expr, lookup=repo.__contains__)
3375 ui.note(revset.prettyformat(tree), "\n")
3377 ui.note(revset.prettyformat(tree), "\n")
3376 newtree = revset.findaliases(ui, tree)
3378 newtree = revset.findaliases(ui, tree)
3377 if newtree != tree:
3379 if newtree != tree:
3378 ui.note(revset.prettyformat(newtree), "\n")
3380 ui.note(revset.prettyformat(newtree), "\n")
3379 tree = newtree
3381 tree = newtree
3380 newtree = revset.foldconcat(tree)
3382 newtree = revset.foldconcat(tree)
3381 if newtree != tree:
3383 if newtree != tree:
3382 ui.note(revset.prettyformat(newtree), "\n")
3384 ui.note(revset.prettyformat(newtree), "\n")
3383 if opts["optimize"]:
3385 if opts["optimize"]:
3384 weight, optimizedtree = revset.optimize(newtree, True)
3386 weight, optimizedtree = revset.optimize(newtree, True)
3385 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3387 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3386 func = revset.match(ui, expr, repo)
3388 func = revset.match(ui, expr, repo)
3387 revs = func(repo)
3389 revs = func(repo)
3388 if ui.verbose:
3390 if ui.verbose:
3389 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3391 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3390 for c in revs:
3392 for c in revs:
3391 ui.write("%s\n" % c)
3393 ui.write("%s\n" % c)
3392
3394
3393 @command('debugsetparents', [], _('REV1 [REV2]'))
3395 @command('debugsetparents', [], _('REV1 [REV2]'))
3394 def debugsetparents(ui, repo, rev1, rev2=None):
3396 def debugsetparents(ui, repo, rev1, rev2=None):
3395 """manually set the parents of the current working directory
3397 """manually set the parents of the current working directory
3396
3398
3397 This is useful for writing repository conversion tools, but should
3399 This is useful for writing repository conversion tools, but should
3398 be used with care. For example, neither the working directory nor the
3400 be used with care. For example, neither the working directory nor the
3399 dirstate is updated, so file status may be incorrect after running this
3401 dirstate is updated, so file status may be incorrect after running this
3400 command.
3402 command.
3401
3403
3402 Returns 0 on success.
3404 Returns 0 on success.
3403 """
3405 """
3404
3406
3405 r1 = scmutil.revsingle(repo, rev1).node()
3407 r1 = scmutil.revsingle(repo, rev1).node()
3406 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3408 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3407
3409
3408 with repo.wlock():
3410 with repo.wlock():
3409 repo.dirstate.beginparentchange()
3411 repo.dirstate.beginparentchange()
3410 repo.setparents(r1, r2)
3412 repo.setparents(r1, r2)
3411 repo.dirstate.endparentchange()
3413 repo.dirstate.endparentchange()
3412
3414
3413 @command('debugdirstate|debugstate',
3415 @command('debugdirstate|debugstate',
3414 [('', 'nodates', None, _('do not display the saved mtime')),
3416 [('', 'nodates', None, _('do not display the saved mtime')),
3415 ('', 'datesort', None, _('sort by saved mtime'))],
3417 ('', 'datesort', None, _('sort by saved mtime'))],
3416 _('[OPTION]...'))
3418 _('[OPTION]...'))
3417 def debugstate(ui, repo, **opts):
3419 def debugstate(ui, repo, **opts):
3418 """show the contents of the current dirstate"""
3420 """show the contents of the current dirstate"""
3419
3421
3420 nodates = opts.get('nodates')
3422 nodates = opts.get('nodates')
3421 datesort = opts.get('datesort')
3423 datesort = opts.get('datesort')
3422
3424
3423 timestr = ""
3425 timestr = ""
3424 if datesort:
3426 if datesort:
3425 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3427 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3426 else:
3428 else:
3427 keyfunc = None # sort by filename
3429 keyfunc = None # sort by filename
3428 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3430 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3429 if ent[3] == -1:
3431 if ent[3] == -1:
3430 timestr = 'unset '
3432 timestr = 'unset '
3431 elif nodates:
3433 elif nodates:
3432 timestr = 'set '
3434 timestr = 'set '
3433 else:
3435 else:
3434 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3436 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3435 time.localtime(ent[3]))
3437 time.localtime(ent[3]))
3436 if ent[1] & 0o20000:
3438 if ent[1] & 0o20000:
3437 mode = 'lnk'
3439 mode = 'lnk'
3438 else:
3440 else:
3439 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3441 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3440 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3442 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3441 for f in repo.dirstate.copies():
3443 for f in repo.dirstate.copies():
3442 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3444 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3443
3445
3444 @command('debugsub',
3446 @command('debugsub',
3445 [('r', 'rev', '',
3447 [('r', 'rev', '',
3446 _('revision to check'), _('REV'))],
3448 _('revision to check'), _('REV'))],
3447 _('[-r REV] [REV]'))
3449 _('[-r REV] [REV]'))
3448 def debugsub(ui, repo, rev=None):
3450 def debugsub(ui, repo, rev=None):
3449 ctx = scmutil.revsingle(repo, rev, None)
3451 ctx = scmutil.revsingle(repo, rev, None)
3450 for k, v in sorted(ctx.substate.items()):
3452 for k, v in sorted(ctx.substate.items()):
3451 ui.write(('path %s\n') % k)
3453 ui.write(('path %s\n') % k)
3452 ui.write((' source %s\n') % v[0])
3454 ui.write((' source %s\n') % v[0])
3453 ui.write((' revision %s\n') % v[1])
3455 ui.write((' revision %s\n') % v[1])
3454
3456
3455 @command('debugsuccessorssets',
3457 @command('debugsuccessorssets',
3456 [],
3458 [],
3457 _('[REV]'))
3459 _('[REV]'))
3458 def debugsuccessorssets(ui, repo, *revs):
3460 def debugsuccessorssets(ui, repo, *revs):
3459 """show set of successors for revision
3461 """show set of successors for revision
3460
3462
3461 A successors set of changeset A is a consistent group of revisions that
3463 A successors set of changeset A is a consistent group of revisions that
3462 succeed A. It contains non-obsolete changesets only.
3464 succeed A. It contains non-obsolete changesets only.
3463
3465
3464 In most cases a changeset A has a single successors set containing a single
3466 In most cases a changeset A has a single successors set containing a single
3465 successor (changeset A replaced by A').
3467 successor (changeset A replaced by A').
3466
3468
3467 A changeset that is made obsolete with no successors are called "pruned".
3469 A changeset that is made obsolete with no successors are called "pruned".
3468 Such changesets have no successors sets at all.
3470 Such changesets have no successors sets at all.
3469
3471
3470 A changeset that has been "split" will have a successors set containing
3472 A changeset that has been "split" will have a successors set containing
3471 more than one successor.
3473 more than one successor.
3472
3474
3473 A changeset that has been rewritten in multiple different ways is called
3475 A changeset that has been rewritten in multiple different ways is called
3474 "divergent". Such changesets have multiple successor sets (each of which
3476 "divergent". Such changesets have multiple successor sets (each of which
3475 may also be split, i.e. have multiple successors).
3477 may also be split, i.e. have multiple successors).
3476
3478
3477 Results are displayed as follows::
3479 Results are displayed as follows::
3478
3480
3479 <rev1>
3481 <rev1>
3480 <successors-1A>
3482 <successors-1A>
3481 <rev2>
3483 <rev2>
3482 <successors-2A>
3484 <successors-2A>
3483 <successors-2B1> <successors-2B2> <successors-2B3>
3485 <successors-2B1> <successors-2B2> <successors-2B3>
3484
3486
3485 Here rev2 has two possible (i.e. divergent) successors sets. The first
3487 Here rev2 has two possible (i.e. divergent) successors sets. The first
3486 holds one element, whereas the second holds three (i.e. the changeset has
3488 holds one element, whereas the second holds three (i.e. the changeset has
3487 been split).
3489 been split).
3488 """
3490 """
3489 # passed to successorssets caching computation from one call to another
3491 # passed to successorssets caching computation from one call to another
3490 cache = {}
3492 cache = {}
3491 ctx2str = str
3493 ctx2str = str
3492 node2str = short
3494 node2str = short
3493 if ui.debug():
3495 if ui.debug():
3494 def ctx2str(ctx):
3496 def ctx2str(ctx):
3495 return ctx.hex()
3497 return ctx.hex()
3496 node2str = hex
3498 node2str = hex
3497 for rev in scmutil.revrange(repo, revs):
3499 for rev in scmutil.revrange(repo, revs):
3498 ctx = repo[rev]
3500 ctx = repo[rev]
3499 ui.write('%s\n'% ctx2str(ctx))
3501 ui.write('%s\n'% ctx2str(ctx))
3500 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3502 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3501 if succsset:
3503 if succsset:
3502 ui.write(' ')
3504 ui.write(' ')
3503 ui.write(node2str(succsset[0]))
3505 ui.write(node2str(succsset[0]))
3504 for node in succsset[1:]:
3506 for node in succsset[1:]:
3505 ui.write(' ')
3507 ui.write(' ')
3506 ui.write(node2str(node))
3508 ui.write(node2str(node))
3507 ui.write('\n')
3509 ui.write('\n')
3508
3510
3509 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3511 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3510 def debugwalk(ui, repo, *pats, **opts):
3512 def debugwalk(ui, repo, *pats, **opts):
3511 """show how files match on given patterns"""
3513 """show how files match on given patterns"""
3512 m = scmutil.match(repo[None], pats, opts)
3514 m = scmutil.match(repo[None], pats, opts)
3513 items = list(repo.walk(m))
3515 items = list(repo.walk(m))
3514 if not items:
3516 if not items:
3515 return
3517 return
3516 f = lambda fn: fn
3518 f = lambda fn: fn
3517 if ui.configbool('ui', 'slash') and os.sep != '/':
3519 if ui.configbool('ui', 'slash') and os.sep != '/':
3518 f = lambda fn: util.normpath(fn)
3520 f = lambda fn: util.normpath(fn)
3519 fmt = 'f %%-%ds %%-%ds %%s' % (
3521 fmt = 'f %%-%ds %%-%ds %%s' % (
3520 max([len(abs) for abs in items]),
3522 max([len(abs) for abs in items]),
3521 max([len(m.rel(abs)) for abs in items]))
3523 max([len(m.rel(abs)) for abs in items]))
3522 for abs in items:
3524 for abs in items:
3523 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3525 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3524 ui.write("%s\n" % line.rstrip())
3526 ui.write("%s\n" % line.rstrip())
3525
3527
3526 @command('debugwireargs',
3528 @command('debugwireargs',
3527 [('', 'three', '', 'three'),
3529 [('', 'three', '', 'three'),
3528 ('', 'four', '', 'four'),
3530 ('', 'four', '', 'four'),
3529 ('', 'five', '', 'five'),
3531 ('', 'five', '', 'five'),
3530 ] + remoteopts,
3532 ] + remoteopts,
3531 _('REPO [OPTIONS]... [ONE [TWO]]'),
3533 _('REPO [OPTIONS]... [ONE [TWO]]'),
3532 norepo=True)
3534 norepo=True)
3533 def debugwireargs(ui, repopath, *vals, **opts):
3535 def debugwireargs(ui, repopath, *vals, **opts):
3534 repo = hg.peer(ui, opts, repopath)
3536 repo = hg.peer(ui, opts, repopath)
3535 for opt in remoteopts:
3537 for opt in remoteopts:
3536 del opts[opt[1]]
3538 del opts[opt[1]]
3537 args = {}
3539 args = {}
3538 for k, v in opts.iteritems():
3540 for k, v in opts.iteritems():
3539 if v:
3541 if v:
3540 args[k] = v
3542 args[k] = v
3541 # run twice to check that we don't mess up the stream for the next command
3543 # run twice to check that we don't mess up the stream for the next command
3542 res1 = repo.debugwireargs(*vals, **args)
3544 res1 = repo.debugwireargs(*vals, **args)
3543 res2 = repo.debugwireargs(*vals, **args)
3545 res2 = repo.debugwireargs(*vals, **args)
3544 ui.write("%s\n" % res1)
3546 ui.write("%s\n" % res1)
3545 if res1 != res2:
3547 if res1 != res2:
3546 ui.warn("%s\n" % res2)
3548 ui.warn("%s\n" % res2)
3547
3549
3548 @command('^diff',
3550 @command('^diff',
3549 [('r', 'rev', [], _('revision'), _('REV')),
3551 [('r', 'rev', [], _('revision'), _('REV')),
3550 ('c', 'change', '', _('change made by revision'), _('REV'))
3552 ('c', 'change', '', _('change made by revision'), _('REV'))
3551 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3553 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3552 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3554 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3553 inferrepo=True)
3555 inferrepo=True)
3554 def diff(ui, repo, *pats, **opts):
3556 def diff(ui, repo, *pats, **opts):
3555 """diff repository (or selected files)
3557 """diff repository (or selected files)
3556
3558
3557 Show differences between revisions for the specified files.
3559 Show differences between revisions for the specified files.
3558
3560
3559 Differences between files are shown using the unified diff format.
3561 Differences between files are shown using the unified diff format.
3560
3562
3561 .. note::
3563 .. note::
3562
3564
3563 :hg:`diff` may generate unexpected results for merges, as it will
3565 :hg:`diff` may generate unexpected results for merges, as it will
3564 default to comparing against the working directory's first
3566 default to comparing against the working directory's first
3565 parent changeset if no revisions are specified.
3567 parent changeset if no revisions are specified.
3566
3568
3567 When two revision arguments are given, then changes are shown
3569 When two revision arguments are given, then changes are shown
3568 between those revisions. If only one revision is specified then
3570 between those revisions. If only one revision is specified then
3569 that revision is compared to the working directory, and, when no
3571 that revision is compared to the working directory, and, when no
3570 revisions are specified, the working directory files are compared
3572 revisions are specified, the working directory files are compared
3571 to its first parent.
3573 to its first parent.
3572
3574
3573 Alternatively you can specify -c/--change with a revision to see
3575 Alternatively you can specify -c/--change with a revision to see
3574 the changes in that changeset relative to its first parent.
3576 the changes in that changeset relative to its first parent.
3575
3577
3576 Without the -a/--text option, diff will avoid generating diffs of
3578 Without the -a/--text option, diff will avoid generating diffs of
3577 files it detects as binary. With -a, diff will generate a diff
3579 files it detects as binary. With -a, diff will generate a diff
3578 anyway, probably with undesirable results.
3580 anyway, probably with undesirable results.
3579
3581
3580 Use the -g/--git option to generate diffs in the git extended diff
3582 Use the -g/--git option to generate diffs in the git extended diff
3581 format. For more information, read :hg:`help diffs`.
3583 format. For more information, read :hg:`help diffs`.
3582
3584
3583 .. container:: verbose
3585 .. container:: verbose
3584
3586
3585 Examples:
3587 Examples:
3586
3588
3587 - compare a file in the current working directory to its parent::
3589 - compare a file in the current working directory to its parent::
3588
3590
3589 hg diff foo.c
3591 hg diff foo.c
3590
3592
3591 - compare two historical versions of a directory, with rename info::
3593 - compare two historical versions of a directory, with rename info::
3592
3594
3593 hg diff --git -r 1.0:1.2 lib/
3595 hg diff --git -r 1.0:1.2 lib/
3594
3596
3595 - get change stats relative to the last change on some date::
3597 - get change stats relative to the last change on some date::
3596
3598
3597 hg diff --stat -r "date('may 2')"
3599 hg diff --stat -r "date('may 2')"
3598
3600
3599 - diff all newly-added files that contain a keyword::
3601 - diff all newly-added files that contain a keyword::
3600
3602
3601 hg diff "set:added() and grep(GNU)"
3603 hg diff "set:added() and grep(GNU)"
3602
3604
3603 - compare a revision and its parents::
3605 - compare a revision and its parents::
3604
3606
3605 hg diff -c 9353 # compare against first parent
3607 hg diff -c 9353 # compare against first parent
3606 hg diff -r 9353^:9353 # same using revset syntax
3608 hg diff -r 9353^:9353 # same using revset syntax
3607 hg diff -r 9353^2:9353 # compare against the second parent
3609 hg diff -r 9353^2:9353 # compare against the second parent
3608
3610
3609 Returns 0 on success.
3611 Returns 0 on success.
3610 """
3612 """
3611
3613
3612 revs = opts.get('rev')
3614 revs = opts.get('rev')
3613 change = opts.get('change')
3615 change = opts.get('change')
3614 stat = opts.get('stat')
3616 stat = opts.get('stat')
3615 reverse = opts.get('reverse')
3617 reverse = opts.get('reverse')
3616
3618
3617 if revs and change:
3619 if revs and change:
3618 msg = _('cannot specify --rev and --change at the same time')
3620 msg = _('cannot specify --rev and --change at the same time')
3619 raise error.Abort(msg)
3621 raise error.Abort(msg)
3620 elif change:
3622 elif change:
3621 node2 = scmutil.revsingle(repo, change, None).node()
3623 node2 = scmutil.revsingle(repo, change, None).node()
3622 node1 = repo[node2].p1().node()
3624 node1 = repo[node2].p1().node()
3623 else:
3625 else:
3624 node1, node2 = scmutil.revpair(repo, revs)
3626 node1, node2 = scmutil.revpair(repo, revs)
3625
3627
3626 if reverse:
3628 if reverse:
3627 node1, node2 = node2, node1
3629 node1, node2 = node2, node1
3628
3630
3629 diffopts = patch.diffallopts(ui, opts)
3631 diffopts = patch.diffallopts(ui, opts)
3630 m = scmutil.match(repo[node2], pats, opts)
3632 m = scmutil.match(repo[node2], pats, opts)
3631 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3633 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3632 listsubrepos=opts.get('subrepos'),
3634 listsubrepos=opts.get('subrepos'),
3633 root=opts.get('root'))
3635 root=opts.get('root'))
3634
3636
3635 @command('^export',
3637 @command('^export',
3636 [('o', 'output', '',
3638 [('o', 'output', '',
3637 _('print output to file with formatted name'), _('FORMAT')),
3639 _('print output to file with formatted name'), _('FORMAT')),
3638 ('', 'switch-parent', None, _('diff against the second parent')),
3640 ('', 'switch-parent', None, _('diff against the second parent')),
3639 ('r', 'rev', [], _('revisions to export'), _('REV')),
3641 ('r', 'rev', [], _('revisions to export'), _('REV')),
3640 ] + diffopts,
3642 ] + diffopts,
3641 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3643 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3642 def export(ui, repo, *changesets, **opts):
3644 def export(ui, repo, *changesets, **opts):
3643 """dump the header and diffs for one or more changesets
3645 """dump the header and diffs for one or more changesets
3644
3646
3645 Print the changeset header and diffs for one or more revisions.
3647 Print the changeset header and diffs for one or more revisions.
3646 If no revision is given, the parent of the working directory is used.
3648 If no revision is given, the parent of the working directory is used.
3647
3649
3648 The information shown in the changeset header is: author, date,
3650 The information shown in the changeset header is: author, date,
3649 branch name (if non-default), changeset hash, parent(s) and commit
3651 branch name (if non-default), changeset hash, parent(s) and commit
3650 comment.
3652 comment.
3651
3653
3652 .. note::
3654 .. note::
3653
3655
3654 :hg:`export` may generate unexpected diff output for merge
3656 :hg:`export` may generate unexpected diff output for merge
3655 changesets, as it will compare the merge changeset against its
3657 changesets, as it will compare the merge changeset against its
3656 first parent only.
3658 first parent only.
3657
3659
3658 Output may be to a file, in which case the name of the file is
3660 Output may be to a file, in which case the name of the file is
3659 given using a format string. The formatting rules are as follows:
3661 given using a format string. The formatting rules are as follows:
3660
3662
3661 :``%%``: literal "%" character
3663 :``%%``: literal "%" character
3662 :``%H``: changeset hash (40 hexadecimal digits)
3664 :``%H``: changeset hash (40 hexadecimal digits)
3663 :``%N``: number of patches being generated
3665 :``%N``: number of patches being generated
3664 :``%R``: changeset revision number
3666 :``%R``: changeset revision number
3665 :``%b``: basename of the exporting repository
3667 :``%b``: basename of the exporting repository
3666 :``%h``: short-form changeset hash (12 hexadecimal digits)
3668 :``%h``: short-form changeset hash (12 hexadecimal digits)
3667 :``%m``: first line of the commit message (only alphanumeric characters)
3669 :``%m``: first line of the commit message (only alphanumeric characters)
3668 :``%n``: zero-padded sequence number, starting at 1
3670 :``%n``: zero-padded sequence number, starting at 1
3669 :``%r``: zero-padded changeset revision number
3671 :``%r``: zero-padded changeset revision number
3670
3672
3671 Without the -a/--text option, export will avoid generating diffs
3673 Without the -a/--text option, export will avoid generating diffs
3672 of files it detects as binary. With -a, export will generate a
3674 of files it detects as binary. With -a, export will generate a
3673 diff anyway, probably with undesirable results.
3675 diff anyway, probably with undesirable results.
3674
3676
3675 Use the -g/--git option to generate diffs in the git extended diff
3677 Use the -g/--git option to generate diffs in the git extended diff
3676 format. See :hg:`help diffs` for more information.
3678 format. See :hg:`help diffs` for more information.
3677
3679
3678 With the --switch-parent option, the diff will be against the
3680 With the --switch-parent option, the diff will be against the
3679 second parent. It can be useful to review a merge.
3681 second parent. It can be useful to review a merge.
3680
3682
3681 .. container:: verbose
3683 .. container:: verbose
3682
3684
3683 Examples:
3685 Examples:
3684
3686
3685 - use export and import to transplant a bugfix to the current
3687 - use export and import to transplant a bugfix to the current
3686 branch::
3688 branch::
3687
3689
3688 hg export -r 9353 | hg import -
3690 hg export -r 9353 | hg import -
3689
3691
3690 - export all the changesets between two revisions to a file with
3692 - export all the changesets between two revisions to a file with
3691 rename information::
3693 rename information::
3692
3694
3693 hg export --git -r 123:150 > changes.txt
3695 hg export --git -r 123:150 > changes.txt
3694
3696
3695 - split outgoing changes into a series of patches with
3697 - split outgoing changes into a series of patches with
3696 descriptive names::
3698 descriptive names::
3697
3699
3698 hg export -r "outgoing()" -o "%n-%m.patch"
3700 hg export -r "outgoing()" -o "%n-%m.patch"
3699
3701
3700 Returns 0 on success.
3702 Returns 0 on success.
3701 """
3703 """
3702 changesets += tuple(opts.get('rev', []))
3704 changesets += tuple(opts.get('rev', []))
3703 if not changesets:
3705 if not changesets:
3704 changesets = ['.']
3706 changesets = ['.']
3705 revs = scmutil.revrange(repo, changesets)
3707 revs = scmutil.revrange(repo, changesets)
3706 if not revs:
3708 if not revs:
3707 raise error.Abort(_("export requires at least one changeset"))
3709 raise error.Abort(_("export requires at least one changeset"))
3708 if len(revs) > 1:
3710 if len(revs) > 1:
3709 ui.note(_('exporting patches:\n'))
3711 ui.note(_('exporting patches:\n'))
3710 else:
3712 else:
3711 ui.note(_('exporting patch:\n'))
3713 ui.note(_('exporting patch:\n'))
3712 cmdutil.export(repo, revs, template=opts.get('output'),
3714 cmdutil.export(repo, revs, template=opts.get('output'),
3713 switch_parent=opts.get('switch_parent'),
3715 switch_parent=opts.get('switch_parent'),
3714 opts=patch.diffallopts(ui, opts))
3716 opts=patch.diffallopts(ui, opts))
3715
3717
3716 @command('files',
3718 @command('files',
3717 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3719 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3718 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3720 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3719 ] + walkopts + formatteropts + subrepoopts,
3721 ] + walkopts + formatteropts + subrepoopts,
3720 _('[OPTION]... [PATTERN]...'))
3722 _('[OPTION]... [PATTERN]...'))
3721 def files(ui, repo, *pats, **opts):
3723 def files(ui, repo, *pats, **opts):
3722 """list tracked files
3724 """list tracked files
3723
3725
3724 Print files under Mercurial control in the working directory or
3726 Print files under Mercurial control in the working directory or
3725 specified revision whose names match the given patterns (excluding
3727 specified revision whose names match the given patterns (excluding
3726 removed files).
3728 removed files).
3727
3729
3728 If no patterns are given to match, this command prints the names
3730 If no patterns are given to match, this command prints the names
3729 of all files under Mercurial control in the working directory.
3731 of all files under Mercurial control in the working directory.
3730
3732
3731 .. container:: verbose
3733 .. container:: verbose
3732
3734
3733 Examples:
3735 Examples:
3734
3736
3735 - list all files under the current directory::
3737 - list all files under the current directory::
3736
3738
3737 hg files .
3739 hg files .
3738
3740
3739 - shows sizes and flags for current revision::
3741 - shows sizes and flags for current revision::
3740
3742
3741 hg files -vr .
3743 hg files -vr .
3742
3744
3743 - list all files named README::
3745 - list all files named README::
3744
3746
3745 hg files -I "**/README"
3747 hg files -I "**/README"
3746
3748
3747 - list all binary files::
3749 - list all binary files::
3748
3750
3749 hg files "set:binary()"
3751 hg files "set:binary()"
3750
3752
3751 - find files containing a regular expression::
3753 - find files containing a regular expression::
3752
3754
3753 hg files "set:grep('bob')"
3755 hg files "set:grep('bob')"
3754
3756
3755 - search tracked file contents with xargs and grep::
3757 - search tracked file contents with xargs and grep::
3756
3758
3757 hg files -0 | xargs -0 grep foo
3759 hg files -0 | xargs -0 grep foo
3758
3760
3759 See :hg:`help patterns` and :hg:`help filesets` for more information
3761 See :hg:`help patterns` and :hg:`help filesets` for more information
3760 on specifying file patterns.
3762 on specifying file patterns.
3761
3763
3762 Returns 0 if a match is found, 1 otherwise.
3764 Returns 0 if a match is found, 1 otherwise.
3763
3765
3764 """
3766 """
3765 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3767 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3766
3768
3767 end = '\n'
3769 end = '\n'
3768 if opts.get('print0'):
3770 if opts.get('print0'):
3769 end = '\0'
3771 end = '\0'
3770 fm = ui.formatter('files', opts)
3772 fm = ui.formatter('files', opts)
3771 fmt = '%s' + end
3773 fmt = '%s' + end
3772
3774
3773 m = scmutil.match(ctx, pats, opts)
3775 m = scmutil.match(ctx, pats, opts)
3774 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3776 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3775
3777
3776 fm.end()
3778 fm.end()
3777
3779
3778 return ret
3780 return ret
3779
3781
3780 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3782 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3781 def forget(ui, repo, *pats, **opts):
3783 def forget(ui, repo, *pats, **opts):
3782 """forget the specified files on the next commit
3784 """forget the specified files on the next commit
3783
3785
3784 Mark the specified files so they will no longer be tracked
3786 Mark the specified files so they will no longer be tracked
3785 after the next commit.
3787 after the next commit.
3786
3788
3787 This only removes files from the current branch, not from the
3789 This only removes files from the current branch, not from the
3788 entire project history, and it does not delete them from the
3790 entire project history, and it does not delete them from the
3789 working directory.
3791 working directory.
3790
3792
3791 To delete the file from the working directory, see :hg:`remove`.
3793 To delete the file from the working directory, see :hg:`remove`.
3792
3794
3793 To undo a forget before the next commit, see :hg:`add`.
3795 To undo a forget before the next commit, see :hg:`add`.
3794
3796
3795 .. container:: verbose
3797 .. container:: verbose
3796
3798
3797 Examples:
3799 Examples:
3798
3800
3799 - forget newly-added binary files::
3801 - forget newly-added binary files::
3800
3802
3801 hg forget "set:added() and binary()"
3803 hg forget "set:added() and binary()"
3802
3804
3803 - forget files that would be excluded by .hgignore::
3805 - forget files that would be excluded by .hgignore::
3804
3806
3805 hg forget "set:hgignore()"
3807 hg forget "set:hgignore()"
3806
3808
3807 Returns 0 on success.
3809 Returns 0 on success.
3808 """
3810 """
3809
3811
3810 if not pats:
3812 if not pats:
3811 raise error.Abort(_('no files specified'))
3813 raise error.Abort(_('no files specified'))
3812
3814
3813 m = scmutil.match(repo[None], pats, opts)
3815 m = scmutil.match(repo[None], pats, opts)
3814 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3816 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3815 return rejected and 1 or 0
3817 return rejected and 1 or 0
3816
3818
3817 @command(
3819 @command(
3818 'graft',
3820 'graft',
3819 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3821 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3820 ('c', 'continue', False, _('resume interrupted graft')),
3822 ('c', 'continue', False, _('resume interrupted graft')),
3821 ('e', 'edit', False, _('invoke editor on commit messages')),
3823 ('e', 'edit', False, _('invoke editor on commit messages')),
3822 ('', 'log', None, _('append graft info to log message')),
3824 ('', 'log', None, _('append graft info to log message')),
3823 ('f', 'force', False, _('force graft')),
3825 ('f', 'force', False, _('force graft')),
3824 ('D', 'currentdate', False,
3826 ('D', 'currentdate', False,
3825 _('record the current date as commit date')),
3827 _('record the current date as commit date')),
3826 ('U', 'currentuser', False,
3828 ('U', 'currentuser', False,
3827 _('record the current user as committer'), _('DATE'))]
3829 _('record the current user as committer'), _('DATE'))]
3828 + commitopts2 + mergetoolopts + dryrunopts,
3830 + commitopts2 + mergetoolopts + dryrunopts,
3829 _('[OPTION]... [-r REV]... REV...'))
3831 _('[OPTION]... [-r REV]... REV...'))
3830 def graft(ui, repo, *revs, **opts):
3832 def graft(ui, repo, *revs, **opts):
3831 '''copy changes from other branches onto the current branch
3833 '''copy changes from other branches onto the current branch
3832
3834
3833 This command uses Mercurial's merge logic to copy individual
3835 This command uses Mercurial's merge logic to copy individual
3834 changes from other branches without merging branches in the
3836 changes from other branches without merging branches in the
3835 history graph. This is sometimes known as 'backporting' or
3837 history graph. This is sometimes known as 'backporting' or
3836 'cherry-picking'. By default, graft will copy user, date, and
3838 'cherry-picking'. By default, graft will copy user, date, and
3837 description from the source changesets.
3839 description from the source changesets.
3838
3840
3839 Changesets that are ancestors of the current revision, that have
3841 Changesets that are ancestors of the current revision, that have
3840 already been grafted, or that are merges will be skipped.
3842 already been grafted, or that are merges will be skipped.
3841
3843
3842 If --log is specified, log messages will have a comment appended
3844 If --log is specified, log messages will have a comment appended
3843 of the form::
3845 of the form::
3844
3846
3845 (grafted from CHANGESETHASH)
3847 (grafted from CHANGESETHASH)
3846
3848
3847 If --force is specified, revisions will be grafted even if they
3849 If --force is specified, revisions will be grafted even if they
3848 are already ancestors of or have been grafted to the destination.
3850 are already ancestors of or have been grafted to the destination.
3849 This is useful when the revisions have since been backed out.
3851 This is useful when the revisions have since been backed out.
3850
3852
3851 If a graft merge results in conflicts, the graft process is
3853 If a graft merge results in conflicts, the graft process is
3852 interrupted so that the current merge can be manually resolved.
3854 interrupted so that the current merge can be manually resolved.
3853 Once all conflicts are addressed, the graft process can be
3855 Once all conflicts are addressed, the graft process can be
3854 continued with the -c/--continue option.
3856 continued with the -c/--continue option.
3855
3857
3856 .. note::
3858 .. note::
3857
3859
3858 The -c/--continue option does not reapply earlier options, except
3860 The -c/--continue option does not reapply earlier options, except
3859 for --force.
3861 for --force.
3860
3862
3861 .. container:: verbose
3863 .. container:: verbose
3862
3864
3863 Examples:
3865 Examples:
3864
3866
3865 - copy a single change to the stable branch and edit its description::
3867 - copy a single change to the stable branch and edit its description::
3866
3868
3867 hg update stable
3869 hg update stable
3868 hg graft --edit 9393
3870 hg graft --edit 9393
3869
3871
3870 - graft a range of changesets with one exception, updating dates::
3872 - graft a range of changesets with one exception, updating dates::
3871
3873
3872 hg graft -D "2085::2093 and not 2091"
3874 hg graft -D "2085::2093 and not 2091"
3873
3875
3874 - continue a graft after resolving conflicts::
3876 - continue a graft after resolving conflicts::
3875
3877
3876 hg graft -c
3878 hg graft -c
3877
3879
3878 - show the source of a grafted changeset::
3880 - show the source of a grafted changeset::
3879
3881
3880 hg log --debug -r .
3882 hg log --debug -r .
3881
3883
3882 - show revisions sorted by date::
3884 - show revisions sorted by date::
3883
3885
3884 hg log -r 'sort(all(), date)'
3886 hg log -r 'sort(all(), date)'
3885
3887
3886 See :hg:`help revisions` and :hg:`help revsets` for more about
3888 See :hg:`help revisions` and :hg:`help revsets` for more about
3887 specifying revisions.
3889 specifying revisions.
3888
3890
3889 Returns 0 on successful completion.
3891 Returns 0 on successful completion.
3890 '''
3892 '''
3891 with repo.wlock():
3893 with repo.wlock():
3892 return _dograft(ui, repo, *revs, **opts)
3894 return _dograft(ui, repo, *revs, **opts)
3893
3895
3894 def _dograft(ui, repo, *revs, **opts):
3896 def _dograft(ui, repo, *revs, **opts):
3895 if revs and opts['rev']:
3897 if revs and opts['rev']:
3896 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3898 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3897 'revision ordering!\n'))
3899 'revision ordering!\n'))
3898
3900
3899 revs = list(revs)
3901 revs = list(revs)
3900 revs.extend(opts['rev'])
3902 revs.extend(opts['rev'])
3901
3903
3902 if not opts.get('user') and opts.get('currentuser'):
3904 if not opts.get('user') and opts.get('currentuser'):
3903 opts['user'] = ui.username()
3905 opts['user'] = ui.username()
3904 if not opts.get('date') and opts.get('currentdate'):
3906 if not opts.get('date') and opts.get('currentdate'):
3905 opts['date'] = "%d %d" % util.makedate()
3907 opts['date'] = "%d %d" % util.makedate()
3906
3908
3907 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3909 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3908
3910
3909 cont = False
3911 cont = False
3910 if opts['continue']:
3912 if opts['continue']:
3911 cont = True
3913 cont = True
3912 if revs:
3914 if revs:
3913 raise error.Abort(_("can't specify --continue and revisions"))
3915 raise error.Abort(_("can't specify --continue and revisions"))
3914 # read in unfinished revisions
3916 # read in unfinished revisions
3915 try:
3917 try:
3916 nodes = repo.vfs.read('graftstate').splitlines()
3918 nodes = repo.vfs.read('graftstate').splitlines()
3917 revs = [repo[node].rev() for node in nodes]
3919 revs = [repo[node].rev() for node in nodes]
3918 except IOError as inst:
3920 except IOError as inst:
3919 if inst.errno != errno.ENOENT:
3921 if inst.errno != errno.ENOENT:
3920 raise
3922 raise
3921 raise error.Abort(_("no graft state found, can't continue"))
3923 raise error.Abort(_("no graft state found, can't continue"))
3922 else:
3924 else:
3923 cmdutil.checkunfinished(repo)
3925 cmdutil.checkunfinished(repo)
3924 cmdutil.bailifchanged(repo)
3926 cmdutil.bailifchanged(repo)
3925 if not revs:
3927 if not revs:
3926 raise error.Abort(_('no revisions specified'))
3928 raise error.Abort(_('no revisions specified'))
3927 revs = scmutil.revrange(repo, revs)
3929 revs = scmutil.revrange(repo, revs)
3928
3930
3929 skipped = set()
3931 skipped = set()
3930 # check for merges
3932 # check for merges
3931 for rev in repo.revs('%ld and merge()', revs):
3933 for rev in repo.revs('%ld and merge()', revs):
3932 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3934 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3933 skipped.add(rev)
3935 skipped.add(rev)
3934 revs = [r for r in revs if r not in skipped]
3936 revs = [r for r in revs if r not in skipped]
3935 if not revs:
3937 if not revs:
3936 return -1
3938 return -1
3937
3939
3938 # Don't check in the --continue case, in effect retaining --force across
3940 # Don't check in the --continue case, in effect retaining --force across
3939 # --continues. That's because without --force, any revisions we decided to
3941 # --continues. That's because without --force, any revisions we decided to
3940 # skip would have been filtered out here, so they wouldn't have made their
3942 # skip would have been filtered out here, so they wouldn't have made their
3941 # way to the graftstate. With --force, any revisions we would have otherwise
3943 # way to the graftstate. With --force, any revisions we would have otherwise
3942 # skipped would not have been filtered out, and if they hadn't been applied
3944 # skipped would not have been filtered out, and if they hadn't been applied
3943 # already, they'd have been in the graftstate.
3945 # already, they'd have been in the graftstate.
3944 if not (cont or opts.get('force')):
3946 if not (cont or opts.get('force')):
3945 # check for ancestors of dest branch
3947 # check for ancestors of dest branch
3946 crev = repo['.'].rev()
3948 crev = repo['.'].rev()
3947 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3949 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3948 # Cannot use x.remove(y) on smart set, this has to be a list.
3950 # Cannot use x.remove(y) on smart set, this has to be a list.
3949 # XXX make this lazy in the future
3951 # XXX make this lazy in the future
3950 revs = list(revs)
3952 revs = list(revs)
3951 # don't mutate while iterating, create a copy
3953 # don't mutate while iterating, create a copy
3952 for rev in list(revs):
3954 for rev in list(revs):
3953 if rev in ancestors:
3955 if rev in ancestors:
3954 ui.warn(_('skipping ancestor revision %d:%s\n') %
3956 ui.warn(_('skipping ancestor revision %d:%s\n') %
3955 (rev, repo[rev]))
3957 (rev, repo[rev]))
3956 # XXX remove on list is slow
3958 # XXX remove on list is slow
3957 revs.remove(rev)
3959 revs.remove(rev)
3958 if not revs:
3960 if not revs:
3959 return -1
3961 return -1
3960
3962
3961 # analyze revs for earlier grafts
3963 # analyze revs for earlier grafts
3962 ids = {}
3964 ids = {}
3963 for ctx in repo.set("%ld", revs):
3965 for ctx in repo.set("%ld", revs):
3964 ids[ctx.hex()] = ctx.rev()
3966 ids[ctx.hex()] = ctx.rev()
3965 n = ctx.extra().get('source')
3967 n = ctx.extra().get('source')
3966 if n:
3968 if n:
3967 ids[n] = ctx.rev()
3969 ids[n] = ctx.rev()
3968
3970
3969 # check ancestors for earlier grafts
3971 # check ancestors for earlier grafts
3970 ui.debug('scanning for duplicate grafts\n')
3972 ui.debug('scanning for duplicate grafts\n')
3971
3973
3972 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3974 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3973 ctx = repo[rev]
3975 ctx = repo[rev]
3974 n = ctx.extra().get('source')
3976 n = ctx.extra().get('source')
3975 if n in ids:
3977 if n in ids:
3976 try:
3978 try:
3977 r = repo[n].rev()
3979 r = repo[n].rev()
3978 except error.RepoLookupError:
3980 except error.RepoLookupError:
3979 r = None
3981 r = None
3980 if r in revs:
3982 if r in revs:
3981 ui.warn(_('skipping revision %d:%s '
3983 ui.warn(_('skipping revision %d:%s '
3982 '(already grafted to %d:%s)\n')
3984 '(already grafted to %d:%s)\n')
3983 % (r, repo[r], rev, ctx))
3985 % (r, repo[r], rev, ctx))
3984 revs.remove(r)
3986 revs.remove(r)
3985 elif ids[n] in revs:
3987 elif ids[n] in revs:
3986 if r is None:
3988 if r is None:
3987 ui.warn(_('skipping already grafted revision %d:%s '
3989 ui.warn(_('skipping already grafted revision %d:%s '
3988 '(%d:%s also has unknown origin %s)\n')
3990 '(%d:%s also has unknown origin %s)\n')
3989 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3991 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3990 else:
3992 else:
3991 ui.warn(_('skipping already grafted revision %d:%s '
3993 ui.warn(_('skipping already grafted revision %d:%s '
3992 '(%d:%s also has origin %d:%s)\n')
3994 '(%d:%s also has origin %d:%s)\n')
3993 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3995 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3994 revs.remove(ids[n])
3996 revs.remove(ids[n])
3995 elif ctx.hex() in ids:
3997 elif ctx.hex() in ids:
3996 r = ids[ctx.hex()]
3998 r = ids[ctx.hex()]
3997 ui.warn(_('skipping already grafted revision %d:%s '
3999 ui.warn(_('skipping already grafted revision %d:%s '
3998 '(was grafted from %d:%s)\n') %
4000 '(was grafted from %d:%s)\n') %
3999 (r, repo[r], rev, ctx))
4001 (r, repo[r], rev, ctx))
4000 revs.remove(r)
4002 revs.remove(r)
4001 if not revs:
4003 if not revs:
4002 return -1
4004 return -1
4003
4005
4004 for pos, ctx in enumerate(repo.set("%ld", revs)):
4006 for pos, ctx in enumerate(repo.set("%ld", revs)):
4005 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4007 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4006 ctx.description().split('\n', 1)[0])
4008 ctx.description().split('\n', 1)[0])
4007 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4009 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4008 if names:
4010 if names:
4009 desc += ' (%s)' % ' '.join(names)
4011 desc += ' (%s)' % ' '.join(names)
4010 ui.status(_('grafting %s\n') % desc)
4012 ui.status(_('grafting %s\n') % desc)
4011 if opts.get('dry_run'):
4013 if opts.get('dry_run'):
4012 continue
4014 continue
4013
4015
4014 extra = ctx.extra().copy()
4016 extra = ctx.extra().copy()
4015 del extra['branch']
4017 del extra['branch']
4016 source = extra.get('source')
4018 source = extra.get('source')
4017 if source:
4019 if source:
4018 extra['intermediate-source'] = ctx.hex()
4020 extra['intermediate-source'] = ctx.hex()
4019 else:
4021 else:
4020 extra['source'] = ctx.hex()
4022 extra['source'] = ctx.hex()
4021 user = ctx.user()
4023 user = ctx.user()
4022 if opts.get('user'):
4024 if opts.get('user'):
4023 user = opts['user']
4025 user = opts['user']
4024 date = ctx.date()
4026 date = ctx.date()
4025 if opts.get('date'):
4027 if opts.get('date'):
4026 date = opts['date']
4028 date = opts['date']
4027 message = ctx.description()
4029 message = ctx.description()
4028 if opts.get('log'):
4030 if opts.get('log'):
4029 message += '\n(grafted from %s)' % ctx.hex()
4031 message += '\n(grafted from %s)' % ctx.hex()
4030
4032
4031 # we don't merge the first commit when continuing
4033 # we don't merge the first commit when continuing
4032 if not cont:
4034 if not cont:
4033 # perform the graft merge with p1(rev) as 'ancestor'
4035 # perform the graft merge with p1(rev) as 'ancestor'
4034 try:
4036 try:
4035 # ui.forcemerge is an internal variable, do not document
4037 # ui.forcemerge is an internal variable, do not document
4036 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4038 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4037 'graft')
4039 'graft')
4038 stats = mergemod.graft(repo, ctx, ctx.p1(),
4040 stats = mergemod.graft(repo, ctx, ctx.p1(),
4039 ['local', 'graft'])
4041 ['local', 'graft'])
4040 finally:
4042 finally:
4041 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4043 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4042 # report any conflicts
4044 # report any conflicts
4043 if stats and stats[3] > 0:
4045 if stats and stats[3] > 0:
4044 # write out state for --continue
4046 # write out state for --continue
4045 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4047 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4046 repo.vfs.write('graftstate', ''.join(nodelines))
4048 repo.vfs.write('graftstate', ''.join(nodelines))
4047 extra = ''
4049 extra = ''
4048 if opts.get('user'):
4050 if opts.get('user'):
4049 extra += ' --user %s' % opts['user']
4051 extra += ' --user %s' % opts['user']
4050 if opts.get('date'):
4052 if opts.get('date'):
4051 extra += ' --date %s' % opts['date']
4053 extra += ' --date %s' % opts['date']
4052 if opts.get('log'):
4054 if opts.get('log'):
4053 extra += ' --log'
4055 extra += ' --log'
4054 hint=_('use hg resolve and hg graft --continue%s') % extra
4056 hint=_('use hg resolve and hg graft --continue%s') % extra
4055 raise error.Abort(
4057 raise error.Abort(
4056 _("unresolved conflicts, can't continue"),
4058 _("unresolved conflicts, can't continue"),
4057 hint=hint)
4059 hint=hint)
4058 else:
4060 else:
4059 cont = False
4061 cont = False
4060
4062
4061 # commit
4063 # commit
4062 node = repo.commit(text=message, user=user,
4064 node = repo.commit(text=message, user=user,
4063 date=date, extra=extra, editor=editor)
4065 date=date, extra=extra, editor=editor)
4064 if node is None:
4066 if node is None:
4065 ui.warn(
4067 ui.warn(
4066 _('note: graft of %d:%s created no changes to commit\n') %
4068 _('note: graft of %d:%s created no changes to commit\n') %
4067 (ctx.rev(), ctx))
4069 (ctx.rev(), ctx))
4068
4070
4069 # remove state when we complete successfully
4071 # remove state when we complete successfully
4070 if not opts.get('dry_run'):
4072 if not opts.get('dry_run'):
4071 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4073 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4072
4074
4073 return 0
4075 return 0
4074
4076
4075 @command('grep',
4077 @command('grep',
4076 [('0', 'print0', None, _('end fields with NUL')),
4078 [('0', 'print0', None, _('end fields with NUL')),
4077 ('', 'all', None, _('print all revisions that match')),
4079 ('', 'all', None, _('print all revisions that match')),
4078 ('a', 'text', None, _('treat all files as text')),
4080 ('a', 'text', None, _('treat all files as text')),
4079 ('f', 'follow', None,
4081 ('f', 'follow', None,
4080 _('follow changeset history,'
4082 _('follow changeset history,'
4081 ' or file history across copies and renames')),
4083 ' or file history across copies and renames')),
4082 ('i', 'ignore-case', None, _('ignore case when matching')),
4084 ('i', 'ignore-case', None, _('ignore case when matching')),
4083 ('l', 'files-with-matches', None,
4085 ('l', 'files-with-matches', None,
4084 _('print only filenames and revisions that match')),
4086 _('print only filenames and revisions that match')),
4085 ('n', 'line-number', None, _('print matching line numbers')),
4087 ('n', 'line-number', None, _('print matching line numbers')),
4086 ('r', 'rev', [],
4088 ('r', 'rev', [],
4087 _('only search files changed within revision range'), _('REV')),
4089 _('only search files changed within revision range'), _('REV')),
4088 ('u', 'user', None, _('list the author (long with -v)')),
4090 ('u', 'user', None, _('list the author (long with -v)')),
4089 ('d', 'date', None, _('list the date (short with -q)')),
4091 ('d', 'date', None, _('list the date (short with -q)')),
4090 ] + walkopts,
4092 ] + walkopts,
4091 _('[OPTION]... PATTERN [FILE]...'),
4093 _('[OPTION]... PATTERN [FILE]...'),
4092 inferrepo=True)
4094 inferrepo=True)
4093 def grep(ui, repo, pattern, *pats, **opts):
4095 def grep(ui, repo, pattern, *pats, **opts):
4094 """search for a pattern in specified files and revisions
4096 """search for a pattern in specified files and revisions
4095
4097
4096 Search revisions of files for a regular expression.
4098 Search revisions of files for a regular expression.
4097
4099
4098 This command behaves differently than Unix grep. It only accepts
4100 This command behaves differently than Unix grep. It only accepts
4099 Python/Perl regexps. It searches repository history, not the
4101 Python/Perl regexps. It searches repository history, not the
4100 working directory. It always prints the revision number in which a
4102 working directory. It always prints the revision number in which a
4101 match appears.
4103 match appears.
4102
4104
4103 By default, grep only prints output for the first revision of a
4105 By default, grep only prints output for the first revision of a
4104 file in which it finds a match. To get it to print every revision
4106 file in which it finds a match. To get it to print every revision
4105 that contains a change in match status ("-" for a match that
4107 that contains a change in match status ("-" for a match that
4106 becomes a non-match, or "+" for a non-match that becomes a match),
4108 becomes a non-match, or "+" for a non-match that becomes a match),
4107 use the --all flag.
4109 use the --all flag.
4108
4110
4109 Returns 0 if a match is found, 1 otherwise.
4111 Returns 0 if a match is found, 1 otherwise.
4110 """
4112 """
4111 reflags = re.M
4113 reflags = re.M
4112 if opts.get('ignore_case'):
4114 if opts.get('ignore_case'):
4113 reflags |= re.I
4115 reflags |= re.I
4114 try:
4116 try:
4115 regexp = util.re.compile(pattern, reflags)
4117 regexp = util.re.compile(pattern, reflags)
4116 except re.error as inst:
4118 except re.error as inst:
4117 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4119 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4118 return 1
4120 return 1
4119 sep, eol = ':', '\n'
4121 sep, eol = ':', '\n'
4120 if opts.get('print0'):
4122 if opts.get('print0'):
4121 sep = eol = '\0'
4123 sep = eol = '\0'
4122
4124
4123 getfile = util.lrucachefunc(repo.file)
4125 getfile = util.lrucachefunc(repo.file)
4124
4126
4125 def matchlines(body):
4127 def matchlines(body):
4126 begin = 0
4128 begin = 0
4127 linenum = 0
4129 linenum = 0
4128 while begin < len(body):
4130 while begin < len(body):
4129 match = regexp.search(body, begin)
4131 match = regexp.search(body, begin)
4130 if not match:
4132 if not match:
4131 break
4133 break
4132 mstart, mend = match.span()
4134 mstart, mend = match.span()
4133 linenum += body.count('\n', begin, mstart) + 1
4135 linenum += body.count('\n', begin, mstart) + 1
4134 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4136 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4135 begin = body.find('\n', mend) + 1 or len(body) + 1
4137 begin = body.find('\n', mend) + 1 or len(body) + 1
4136 lend = begin - 1
4138 lend = begin - 1
4137 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4139 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4138
4140
4139 class linestate(object):
4141 class linestate(object):
4140 def __init__(self, line, linenum, colstart, colend):
4142 def __init__(self, line, linenum, colstart, colend):
4141 self.line = line
4143 self.line = line
4142 self.linenum = linenum
4144 self.linenum = linenum
4143 self.colstart = colstart
4145 self.colstart = colstart
4144 self.colend = colend
4146 self.colend = colend
4145
4147
4146 def __hash__(self):
4148 def __hash__(self):
4147 return hash((self.linenum, self.line))
4149 return hash((self.linenum, self.line))
4148
4150
4149 def __eq__(self, other):
4151 def __eq__(self, other):
4150 return self.line == other.line
4152 return self.line == other.line
4151
4153
4152 def __iter__(self):
4154 def __iter__(self):
4153 yield (self.line[:self.colstart], '')
4155 yield (self.line[:self.colstart], '')
4154 yield (self.line[self.colstart:self.colend], 'grep.match')
4156 yield (self.line[self.colstart:self.colend], 'grep.match')
4155 rest = self.line[self.colend:]
4157 rest = self.line[self.colend:]
4156 while rest != '':
4158 while rest != '':
4157 match = regexp.search(rest)
4159 match = regexp.search(rest)
4158 if not match:
4160 if not match:
4159 yield (rest, '')
4161 yield (rest, '')
4160 break
4162 break
4161 mstart, mend = match.span()
4163 mstart, mend = match.span()
4162 yield (rest[:mstart], '')
4164 yield (rest[:mstart], '')
4163 yield (rest[mstart:mend], 'grep.match')
4165 yield (rest[mstart:mend], 'grep.match')
4164 rest = rest[mend:]
4166 rest = rest[mend:]
4165
4167
4166 matches = {}
4168 matches = {}
4167 copies = {}
4169 copies = {}
4168 def grepbody(fn, rev, body):
4170 def grepbody(fn, rev, body):
4169 matches[rev].setdefault(fn, [])
4171 matches[rev].setdefault(fn, [])
4170 m = matches[rev][fn]
4172 m = matches[rev][fn]
4171 for lnum, cstart, cend, line in matchlines(body):
4173 for lnum, cstart, cend, line in matchlines(body):
4172 s = linestate(line, lnum, cstart, cend)
4174 s = linestate(line, lnum, cstart, cend)
4173 m.append(s)
4175 m.append(s)
4174
4176
4175 def difflinestates(a, b):
4177 def difflinestates(a, b):
4176 sm = difflib.SequenceMatcher(None, a, b)
4178 sm = difflib.SequenceMatcher(None, a, b)
4177 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4179 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4178 if tag == 'insert':
4180 if tag == 'insert':
4179 for i in xrange(blo, bhi):
4181 for i in xrange(blo, bhi):
4180 yield ('+', b[i])
4182 yield ('+', b[i])
4181 elif tag == 'delete':
4183 elif tag == 'delete':
4182 for i in xrange(alo, ahi):
4184 for i in xrange(alo, ahi):
4183 yield ('-', a[i])
4185 yield ('-', a[i])
4184 elif tag == 'replace':
4186 elif tag == 'replace':
4185 for i in xrange(alo, ahi):
4187 for i in xrange(alo, ahi):
4186 yield ('-', a[i])
4188 yield ('-', a[i])
4187 for i in xrange(blo, bhi):
4189 for i in xrange(blo, bhi):
4188 yield ('+', b[i])
4190 yield ('+', b[i])
4189
4191
4190 def display(fn, ctx, pstates, states):
4192 def display(fn, ctx, pstates, states):
4191 rev = ctx.rev()
4193 rev = ctx.rev()
4192 if ui.quiet:
4194 if ui.quiet:
4193 datefunc = util.shortdate
4195 datefunc = util.shortdate
4194 else:
4196 else:
4195 datefunc = util.datestr
4197 datefunc = util.datestr
4196 found = False
4198 found = False
4197 @util.cachefunc
4199 @util.cachefunc
4198 def binary():
4200 def binary():
4199 flog = getfile(fn)
4201 flog = getfile(fn)
4200 return util.binary(flog.read(ctx.filenode(fn)))
4202 return util.binary(flog.read(ctx.filenode(fn)))
4201
4203
4202 if opts.get('all'):
4204 if opts.get('all'):
4203 iter = difflinestates(pstates, states)
4205 iter = difflinestates(pstates, states)
4204 else:
4206 else:
4205 iter = [('', l) for l in states]
4207 iter = [('', l) for l in states]
4206 for change, l in iter:
4208 for change, l in iter:
4207 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4209 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4208
4210
4209 if opts.get('line_number'):
4211 if opts.get('line_number'):
4210 cols.append((str(l.linenum), 'grep.linenumber'))
4212 cols.append((str(l.linenum), 'grep.linenumber'))
4211 if opts.get('all'):
4213 if opts.get('all'):
4212 cols.append((change, 'grep.change'))
4214 cols.append((change, 'grep.change'))
4213 if opts.get('user'):
4215 if opts.get('user'):
4214 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4216 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4215 if opts.get('date'):
4217 if opts.get('date'):
4216 cols.append((datefunc(ctx.date()), 'grep.date'))
4218 cols.append((datefunc(ctx.date()), 'grep.date'))
4217 for col, label in cols[:-1]:
4219 for col, label in cols[:-1]:
4218 ui.write(col, label=label)
4220 ui.write(col, label=label)
4219 ui.write(sep, label='grep.sep')
4221 ui.write(sep, label='grep.sep')
4220 ui.write(cols[-1][0], label=cols[-1][1])
4222 ui.write(cols[-1][0], label=cols[-1][1])
4221 if not opts.get('files_with_matches'):
4223 if not opts.get('files_with_matches'):
4222 ui.write(sep, label='grep.sep')
4224 ui.write(sep, label='grep.sep')
4223 if not opts.get('text') and binary():
4225 if not opts.get('text') and binary():
4224 ui.write(" Binary file matches")
4226 ui.write(" Binary file matches")
4225 else:
4227 else:
4226 for s, label in l:
4228 for s, label in l:
4227 ui.write(s, label=label)
4229 ui.write(s, label=label)
4228 ui.write(eol)
4230 ui.write(eol)
4229 found = True
4231 found = True
4230 if opts.get('files_with_matches'):
4232 if opts.get('files_with_matches'):
4231 break
4233 break
4232 return found
4234 return found
4233
4235
4234 skip = {}
4236 skip = {}
4235 revfiles = {}
4237 revfiles = {}
4236 matchfn = scmutil.match(repo[None], pats, opts)
4238 matchfn = scmutil.match(repo[None], pats, opts)
4237 found = False
4239 found = False
4238 follow = opts.get('follow')
4240 follow = opts.get('follow')
4239
4241
4240 def prep(ctx, fns):
4242 def prep(ctx, fns):
4241 rev = ctx.rev()
4243 rev = ctx.rev()
4242 pctx = ctx.p1()
4244 pctx = ctx.p1()
4243 parent = pctx.rev()
4245 parent = pctx.rev()
4244 matches.setdefault(rev, {})
4246 matches.setdefault(rev, {})
4245 matches.setdefault(parent, {})
4247 matches.setdefault(parent, {})
4246 files = revfiles.setdefault(rev, [])
4248 files = revfiles.setdefault(rev, [])
4247 for fn in fns:
4249 for fn in fns:
4248 flog = getfile(fn)
4250 flog = getfile(fn)
4249 try:
4251 try:
4250 fnode = ctx.filenode(fn)
4252 fnode = ctx.filenode(fn)
4251 except error.LookupError:
4253 except error.LookupError:
4252 continue
4254 continue
4253
4255
4254 copied = flog.renamed(fnode)
4256 copied = flog.renamed(fnode)
4255 copy = follow and copied and copied[0]
4257 copy = follow and copied and copied[0]
4256 if copy:
4258 if copy:
4257 copies.setdefault(rev, {})[fn] = copy
4259 copies.setdefault(rev, {})[fn] = copy
4258 if fn in skip:
4260 if fn in skip:
4259 if copy:
4261 if copy:
4260 skip[copy] = True
4262 skip[copy] = True
4261 continue
4263 continue
4262 files.append(fn)
4264 files.append(fn)
4263
4265
4264 if fn not in matches[rev]:
4266 if fn not in matches[rev]:
4265 grepbody(fn, rev, flog.read(fnode))
4267 grepbody(fn, rev, flog.read(fnode))
4266
4268
4267 pfn = copy or fn
4269 pfn = copy or fn
4268 if pfn not in matches[parent]:
4270 if pfn not in matches[parent]:
4269 try:
4271 try:
4270 fnode = pctx.filenode(pfn)
4272 fnode = pctx.filenode(pfn)
4271 grepbody(pfn, parent, flog.read(fnode))
4273 grepbody(pfn, parent, flog.read(fnode))
4272 except error.LookupError:
4274 except error.LookupError:
4273 pass
4275 pass
4274
4276
4275 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4277 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4276 rev = ctx.rev()
4278 rev = ctx.rev()
4277 parent = ctx.p1().rev()
4279 parent = ctx.p1().rev()
4278 for fn in sorted(revfiles.get(rev, [])):
4280 for fn in sorted(revfiles.get(rev, [])):
4279 states = matches[rev][fn]
4281 states = matches[rev][fn]
4280 copy = copies.get(rev, {}).get(fn)
4282 copy = copies.get(rev, {}).get(fn)
4281 if fn in skip:
4283 if fn in skip:
4282 if copy:
4284 if copy:
4283 skip[copy] = True
4285 skip[copy] = True
4284 continue
4286 continue
4285 pstates = matches.get(parent, {}).get(copy or fn, [])
4287 pstates = matches.get(parent, {}).get(copy or fn, [])
4286 if pstates or states:
4288 if pstates or states:
4287 r = display(fn, ctx, pstates, states)
4289 r = display(fn, ctx, pstates, states)
4288 found = found or r
4290 found = found or r
4289 if r and not opts.get('all'):
4291 if r and not opts.get('all'):
4290 skip[fn] = True
4292 skip[fn] = True
4291 if copy:
4293 if copy:
4292 skip[copy] = True
4294 skip[copy] = True
4293 del matches[rev]
4295 del matches[rev]
4294 del revfiles[rev]
4296 del revfiles[rev]
4295
4297
4296 return not found
4298 return not found
4297
4299
4298 @command('heads',
4300 @command('heads',
4299 [('r', 'rev', '',
4301 [('r', 'rev', '',
4300 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4302 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4301 ('t', 'topo', False, _('show topological heads only')),
4303 ('t', 'topo', False, _('show topological heads only')),
4302 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4304 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4303 ('c', 'closed', False, _('show normal and closed branch heads')),
4305 ('c', 'closed', False, _('show normal and closed branch heads')),
4304 ] + templateopts,
4306 ] + templateopts,
4305 _('[-ct] [-r STARTREV] [REV]...'))
4307 _('[-ct] [-r STARTREV] [REV]...'))
4306 def heads(ui, repo, *branchrevs, **opts):
4308 def heads(ui, repo, *branchrevs, **opts):
4307 """show branch heads
4309 """show branch heads
4308
4310
4309 With no arguments, show all open branch heads in the repository.
4311 With no arguments, show all open branch heads in the repository.
4310 Branch heads are changesets that have no descendants on the
4312 Branch heads are changesets that have no descendants on the
4311 same branch. They are where development generally takes place and
4313 same branch. They are where development generally takes place and
4312 are the usual targets for update and merge operations.
4314 are the usual targets for update and merge operations.
4313
4315
4314 If one or more REVs are given, only open branch heads on the
4316 If one or more REVs are given, only open branch heads on the
4315 branches associated with the specified changesets are shown. This
4317 branches associated with the specified changesets are shown. This
4316 means that you can use :hg:`heads .` to see the heads on the
4318 means that you can use :hg:`heads .` to see the heads on the
4317 currently checked-out branch.
4319 currently checked-out branch.
4318
4320
4319 If -c/--closed is specified, also show branch heads marked closed
4321 If -c/--closed is specified, also show branch heads marked closed
4320 (see :hg:`commit --close-branch`).
4322 (see :hg:`commit --close-branch`).
4321
4323
4322 If STARTREV is specified, only those heads that are descendants of
4324 If STARTREV is specified, only those heads that are descendants of
4323 STARTREV will be displayed.
4325 STARTREV will be displayed.
4324
4326
4325 If -t/--topo is specified, named branch mechanics will be ignored and only
4327 If -t/--topo is specified, named branch mechanics will be ignored and only
4326 topological heads (changesets with no children) will be shown.
4328 topological heads (changesets with no children) will be shown.
4327
4329
4328 Returns 0 if matching heads are found, 1 if not.
4330 Returns 0 if matching heads are found, 1 if not.
4329 """
4331 """
4330
4332
4331 start = None
4333 start = None
4332 if 'rev' in opts:
4334 if 'rev' in opts:
4333 start = scmutil.revsingle(repo, opts['rev'], None).node()
4335 start = scmutil.revsingle(repo, opts['rev'], None).node()
4334
4336
4335 if opts.get('topo'):
4337 if opts.get('topo'):
4336 heads = [repo[h] for h in repo.heads(start)]
4338 heads = [repo[h] for h in repo.heads(start)]
4337 else:
4339 else:
4338 heads = []
4340 heads = []
4339 for branch in repo.branchmap():
4341 for branch in repo.branchmap():
4340 heads += repo.branchheads(branch, start, opts.get('closed'))
4342 heads += repo.branchheads(branch, start, opts.get('closed'))
4341 heads = [repo[h] for h in heads]
4343 heads = [repo[h] for h in heads]
4342
4344
4343 if branchrevs:
4345 if branchrevs:
4344 branches = set(repo[br].branch() for br in branchrevs)
4346 branches = set(repo[br].branch() for br in branchrevs)
4345 heads = [h for h in heads if h.branch() in branches]
4347 heads = [h for h in heads if h.branch() in branches]
4346
4348
4347 if opts.get('active') and branchrevs:
4349 if opts.get('active') and branchrevs:
4348 dagheads = repo.heads(start)
4350 dagheads = repo.heads(start)
4349 heads = [h for h in heads if h.node() in dagheads]
4351 heads = [h for h in heads if h.node() in dagheads]
4350
4352
4351 if branchrevs:
4353 if branchrevs:
4352 haveheads = set(h.branch() for h in heads)
4354 haveheads = set(h.branch() for h in heads)
4353 if branches - haveheads:
4355 if branches - haveheads:
4354 headless = ', '.join(b for b in branches - haveheads)
4356 headless = ', '.join(b for b in branches - haveheads)
4355 msg = _('no open branch heads found on branches %s')
4357 msg = _('no open branch heads found on branches %s')
4356 if opts.get('rev'):
4358 if opts.get('rev'):
4357 msg += _(' (started at %s)') % opts['rev']
4359 msg += _(' (started at %s)') % opts['rev']
4358 ui.warn((msg + '\n') % headless)
4360 ui.warn((msg + '\n') % headless)
4359
4361
4360 if not heads:
4362 if not heads:
4361 return 1
4363 return 1
4362
4364
4363 heads = sorted(heads, key=lambda x: -x.rev())
4365 heads = sorted(heads, key=lambda x: -x.rev())
4364 displayer = cmdutil.show_changeset(ui, repo, opts)
4366 displayer = cmdutil.show_changeset(ui, repo, opts)
4365 for ctx in heads:
4367 for ctx in heads:
4366 displayer.show(ctx)
4368 displayer.show(ctx)
4367 displayer.close()
4369 displayer.close()
4368
4370
4369 @command('help',
4371 @command('help',
4370 [('e', 'extension', None, _('show only help for extensions')),
4372 [('e', 'extension', None, _('show only help for extensions')),
4371 ('c', 'command', None, _('show only help for commands')),
4373 ('c', 'command', None, _('show only help for commands')),
4372 ('k', 'keyword', None, _('show topics matching keyword')),
4374 ('k', 'keyword', None, _('show topics matching keyword')),
4373 ('s', 'system', [], _('show help for specific platform(s)')),
4375 ('s', 'system', [], _('show help for specific platform(s)')),
4374 ],
4376 ],
4375 _('[-ecks] [TOPIC]'),
4377 _('[-ecks] [TOPIC]'),
4376 norepo=True)
4378 norepo=True)
4377 def help_(ui, name=None, **opts):
4379 def help_(ui, name=None, **opts):
4378 """show help for a given topic or a help overview
4380 """show help for a given topic or a help overview
4379
4381
4380 With no arguments, print a list of commands with short help messages.
4382 With no arguments, print a list of commands with short help messages.
4381
4383
4382 Given a topic, extension, or command name, print help for that
4384 Given a topic, extension, or command name, print help for that
4383 topic.
4385 topic.
4384
4386
4385 Returns 0 if successful.
4387 Returns 0 if successful.
4386 """
4388 """
4387
4389
4388 textwidth = min(ui.termwidth(), 80) - 2
4390 textwidth = min(ui.termwidth(), 80) - 2
4389
4391
4390 keep = opts.get('system') or []
4392 keep = opts.get('system') or []
4391 if len(keep) == 0:
4393 if len(keep) == 0:
4392 if sys.platform.startswith('win'):
4394 if sys.platform.startswith('win'):
4393 keep.append('windows')
4395 keep.append('windows')
4394 elif sys.platform == 'OpenVMS':
4396 elif sys.platform == 'OpenVMS':
4395 keep.append('vms')
4397 keep.append('vms')
4396 elif sys.platform == 'plan9':
4398 elif sys.platform == 'plan9':
4397 keep.append('plan9')
4399 keep.append('plan9')
4398 else:
4400 else:
4399 keep.append('unix')
4401 keep.append('unix')
4400 keep.append(sys.platform.lower())
4402 keep.append(sys.platform.lower())
4401 if ui.verbose:
4403 if ui.verbose:
4402 keep.append('verbose')
4404 keep.append('verbose')
4403
4405
4404 section = None
4406 section = None
4405 subtopic = None
4407 subtopic = None
4406 if name and '.' in name:
4408 if name and '.' in name:
4407 name, section = name.split('.', 1)
4409 name, section = name.split('.', 1)
4408 section = section.lower()
4410 section = section.lower()
4409 if '.' in section:
4411 if '.' in section:
4410 subtopic, section = section.split('.', 1)
4412 subtopic, section = section.split('.', 1)
4411 else:
4413 else:
4412 subtopic = section
4414 subtopic = section
4413
4415
4414 text = help.help_(ui, name, subtopic=subtopic, **opts)
4416 text = help.help_(ui, name, subtopic=subtopic, **opts)
4415
4417
4416 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4418 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4417 section=section)
4419 section=section)
4418
4420
4419 # We could have been given a weird ".foo" section without a name
4421 # We could have been given a weird ".foo" section without a name
4420 # to look for, or we could have simply failed to found "foo.bar"
4422 # to look for, or we could have simply failed to found "foo.bar"
4421 # because bar isn't a section of foo
4423 # because bar isn't a section of foo
4422 if section and not (formatted and name):
4424 if section and not (formatted and name):
4423 raise error.Abort(_("help section not found"))
4425 raise error.Abort(_("help section not found"))
4424
4426
4425 if 'verbose' in pruned:
4427 if 'verbose' in pruned:
4426 keep.append('omitted')
4428 keep.append('omitted')
4427 else:
4429 else:
4428 keep.append('notomitted')
4430 keep.append('notomitted')
4429 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4431 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4430 section=section)
4432 section=section)
4431 ui.write(formatted)
4433 ui.write(formatted)
4432
4434
4433
4435
4434 @command('identify|id',
4436 @command('identify|id',
4435 [('r', 'rev', '',
4437 [('r', 'rev', '',
4436 _('identify the specified revision'), _('REV')),
4438 _('identify the specified revision'), _('REV')),
4437 ('n', 'num', None, _('show local revision number')),
4439 ('n', 'num', None, _('show local revision number')),
4438 ('i', 'id', None, _('show global revision id')),
4440 ('i', 'id', None, _('show global revision id')),
4439 ('b', 'branch', None, _('show branch')),
4441 ('b', 'branch', None, _('show branch')),
4440 ('t', 'tags', None, _('show tags')),
4442 ('t', 'tags', None, _('show tags')),
4441 ('B', 'bookmarks', None, _('show bookmarks')),
4443 ('B', 'bookmarks', None, _('show bookmarks')),
4442 ] + remoteopts,
4444 ] + remoteopts,
4443 _('[-nibtB] [-r REV] [SOURCE]'),
4445 _('[-nibtB] [-r REV] [SOURCE]'),
4444 optionalrepo=True)
4446 optionalrepo=True)
4445 def identify(ui, repo, source=None, rev=None,
4447 def identify(ui, repo, source=None, rev=None,
4446 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4448 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4447 """identify the working directory or specified revision
4449 """identify the working directory or specified revision
4448
4450
4449 Print a summary identifying the repository state at REV using one or
4451 Print a summary identifying the repository state at REV using one or
4450 two parent hash identifiers, followed by a "+" if the working
4452 two parent hash identifiers, followed by a "+" if the working
4451 directory has uncommitted changes, the branch name (if not default),
4453 directory has uncommitted changes, the branch name (if not default),
4452 a list of tags, and a list of bookmarks.
4454 a list of tags, and a list of bookmarks.
4453
4455
4454 When REV is not given, print a summary of the current state of the
4456 When REV is not given, print a summary of the current state of the
4455 repository.
4457 repository.
4456
4458
4457 Specifying a path to a repository root or Mercurial bundle will
4459 Specifying a path to a repository root or Mercurial bundle will
4458 cause lookup to operate on that repository/bundle.
4460 cause lookup to operate on that repository/bundle.
4459
4461
4460 .. container:: verbose
4462 .. container:: verbose
4461
4463
4462 Examples:
4464 Examples:
4463
4465
4464 - generate a build identifier for the working directory::
4466 - generate a build identifier for the working directory::
4465
4467
4466 hg id --id > build-id.dat
4468 hg id --id > build-id.dat
4467
4469
4468 - find the revision corresponding to a tag::
4470 - find the revision corresponding to a tag::
4469
4471
4470 hg id -n -r 1.3
4472 hg id -n -r 1.3
4471
4473
4472 - check the most recent revision of a remote repository::
4474 - check the most recent revision of a remote repository::
4473
4475
4474 hg id -r tip http://selenic.com/hg/
4476 hg id -r tip http://selenic.com/hg/
4475
4477
4476 See :hg:`log` for generating more information about specific revisions,
4478 See :hg:`log` for generating more information about specific revisions,
4477 including full hash identifiers.
4479 including full hash identifiers.
4478
4480
4479 Returns 0 if successful.
4481 Returns 0 if successful.
4480 """
4482 """
4481
4483
4482 if not repo and not source:
4484 if not repo and not source:
4483 raise error.Abort(_("there is no Mercurial repository here "
4485 raise error.Abort(_("there is no Mercurial repository here "
4484 "(.hg not found)"))
4486 "(.hg not found)"))
4485
4487
4486 if ui.debugflag:
4488 if ui.debugflag:
4487 hexfunc = hex
4489 hexfunc = hex
4488 else:
4490 else:
4489 hexfunc = short
4491 hexfunc = short
4490 default = not (num or id or branch or tags or bookmarks)
4492 default = not (num or id or branch or tags or bookmarks)
4491 output = []
4493 output = []
4492 revs = []
4494 revs = []
4493
4495
4494 if source:
4496 if source:
4495 source, branches = hg.parseurl(ui.expandpath(source))
4497 source, branches = hg.parseurl(ui.expandpath(source))
4496 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4498 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4497 repo = peer.local()
4499 repo = peer.local()
4498 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4500 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4499
4501
4500 if not repo:
4502 if not repo:
4501 if num or branch or tags:
4503 if num or branch or tags:
4502 raise error.Abort(
4504 raise error.Abort(
4503 _("can't query remote revision number, branch, or tags"))
4505 _("can't query remote revision number, branch, or tags"))
4504 if not rev and revs:
4506 if not rev and revs:
4505 rev = revs[0]
4507 rev = revs[0]
4506 if not rev:
4508 if not rev:
4507 rev = "tip"
4509 rev = "tip"
4508
4510
4509 remoterev = peer.lookup(rev)
4511 remoterev = peer.lookup(rev)
4510 if default or id:
4512 if default or id:
4511 output = [hexfunc(remoterev)]
4513 output = [hexfunc(remoterev)]
4512
4514
4513 def getbms():
4515 def getbms():
4514 bms = []
4516 bms = []
4515
4517
4516 if 'bookmarks' in peer.listkeys('namespaces'):
4518 if 'bookmarks' in peer.listkeys('namespaces'):
4517 hexremoterev = hex(remoterev)
4519 hexremoterev = hex(remoterev)
4518 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4520 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4519 if bmr == hexremoterev]
4521 if bmr == hexremoterev]
4520
4522
4521 return sorted(bms)
4523 return sorted(bms)
4522
4524
4523 if bookmarks:
4525 if bookmarks:
4524 output.extend(getbms())
4526 output.extend(getbms())
4525 elif default and not ui.quiet:
4527 elif default and not ui.quiet:
4526 # multiple bookmarks for a single parent separated by '/'
4528 # multiple bookmarks for a single parent separated by '/'
4527 bm = '/'.join(getbms())
4529 bm = '/'.join(getbms())
4528 if bm:
4530 if bm:
4529 output.append(bm)
4531 output.append(bm)
4530 else:
4532 else:
4531 ctx = scmutil.revsingle(repo, rev, None)
4533 ctx = scmutil.revsingle(repo, rev, None)
4532
4534
4533 if ctx.rev() is None:
4535 if ctx.rev() is None:
4534 ctx = repo[None]
4536 ctx = repo[None]
4535 parents = ctx.parents()
4537 parents = ctx.parents()
4536 taglist = []
4538 taglist = []
4537 for p in parents:
4539 for p in parents:
4538 taglist.extend(p.tags())
4540 taglist.extend(p.tags())
4539
4541
4540 changed = ""
4542 changed = ""
4541 if default or id or num:
4543 if default or id or num:
4542 if (any(repo.status())
4544 if (any(repo.status())
4543 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4545 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4544 changed = '+'
4546 changed = '+'
4545 if default or id:
4547 if default or id:
4546 output = ["%s%s" %
4548 output = ["%s%s" %
4547 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4549 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4548 if num:
4550 if num:
4549 output.append("%s%s" %
4551 output.append("%s%s" %
4550 ('+'.join([str(p.rev()) for p in parents]), changed))
4552 ('+'.join([str(p.rev()) for p in parents]), changed))
4551 else:
4553 else:
4552 if default or id:
4554 if default or id:
4553 output = [hexfunc(ctx.node())]
4555 output = [hexfunc(ctx.node())]
4554 if num:
4556 if num:
4555 output.append(str(ctx.rev()))
4557 output.append(str(ctx.rev()))
4556 taglist = ctx.tags()
4558 taglist = ctx.tags()
4557
4559
4558 if default and not ui.quiet:
4560 if default and not ui.quiet:
4559 b = ctx.branch()
4561 b = ctx.branch()
4560 if b != 'default':
4562 if b != 'default':
4561 output.append("(%s)" % b)
4563 output.append("(%s)" % b)
4562
4564
4563 # multiple tags for a single parent separated by '/'
4565 # multiple tags for a single parent separated by '/'
4564 t = '/'.join(taglist)
4566 t = '/'.join(taglist)
4565 if t:
4567 if t:
4566 output.append(t)
4568 output.append(t)
4567
4569
4568 # multiple bookmarks for a single parent separated by '/'
4570 # multiple bookmarks for a single parent separated by '/'
4569 bm = '/'.join(ctx.bookmarks())
4571 bm = '/'.join(ctx.bookmarks())
4570 if bm:
4572 if bm:
4571 output.append(bm)
4573 output.append(bm)
4572 else:
4574 else:
4573 if branch:
4575 if branch:
4574 output.append(ctx.branch())
4576 output.append(ctx.branch())
4575
4577
4576 if tags:
4578 if tags:
4577 output.extend(taglist)
4579 output.extend(taglist)
4578
4580
4579 if bookmarks:
4581 if bookmarks:
4580 output.extend(ctx.bookmarks())
4582 output.extend(ctx.bookmarks())
4581
4583
4582 ui.write("%s\n" % ' '.join(output))
4584 ui.write("%s\n" % ' '.join(output))
4583
4585
4584 @command('import|patch',
4586 @command('import|patch',
4585 [('p', 'strip', 1,
4587 [('p', 'strip', 1,
4586 _('directory strip option for patch. This has the same '
4588 _('directory strip option for patch. This has the same '
4587 'meaning as the corresponding patch option'), _('NUM')),
4589 'meaning as the corresponding patch option'), _('NUM')),
4588 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4590 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4589 ('e', 'edit', False, _('invoke editor on commit messages')),
4591 ('e', 'edit', False, _('invoke editor on commit messages')),
4590 ('f', 'force', None,
4592 ('f', 'force', None,
4591 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4593 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4592 ('', 'no-commit', None,
4594 ('', 'no-commit', None,
4593 _("don't commit, just update the working directory")),
4595 _("don't commit, just update the working directory")),
4594 ('', 'bypass', None,
4596 ('', 'bypass', None,
4595 _("apply patch without touching the working directory")),
4597 _("apply patch without touching the working directory")),
4596 ('', 'partial', None,
4598 ('', 'partial', None,
4597 _('commit even if some hunks fail')),
4599 _('commit even if some hunks fail')),
4598 ('', 'exact', None,
4600 ('', 'exact', None,
4599 _('apply patch to the nodes from which it was generated')),
4601 _('apply patch to the nodes from which it was generated')),
4600 ('', 'prefix', '',
4602 ('', 'prefix', '',
4601 _('apply patch to subdirectory'), _('DIR')),
4603 _('apply patch to subdirectory'), _('DIR')),
4602 ('', 'import-branch', None,
4604 ('', 'import-branch', None,
4603 _('use any branch information in patch (implied by --exact)'))] +
4605 _('use any branch information in patch (implied by --exact)'))] +
4604 commitopts + commitopts2 + similarityopts,
4606 commitopts + commitopts2 + similarityopts,
4605 _('[OPTION]... PATCH...'))
4607 _('[OPTION]... PATCH...'))
4606 def import_(ui, repo, patch1=None, *patches, **opts):
4608 def import_(ui, repo, patch1=None, *patches, **opts):
4607 """import an ordered set of patches
4609 """import an ordered set of patches
4608
4610
4609 Import a list of patches and commit them individually (unless
4611 Import a list of patches and commit them individually (unless
4610 --no-commit is specified).
4612 --no-commit is specified).
4611
4613
4612 To read a patch from standard input, use "-" as the patch name. If
4614 To read a patch from standard input, use "-" as the patch name. If
4613 a URL is specified, the patch will be downloaded from there.
4615 a URL is specified, the patch will be downloaded from there.
4614
4616
4615 Import first applies changes to the working directory (unless
4617 Import first applies changes to the working directory (unless
4616 --bypass is specified), import will abort if there are outstanding
4618 --bypass is specified), import will abort if there are outstanding
4617 changes.
4619 changes.
4618
4620
4619 Use --bypass to apply and commit patches directly to the
4621 Use --bypass to apply and commit patches directly to the
4620 repository, without affecting the working directory. Without
4622 repository, without affecting the working directory. Without
4621 --exact, patches will be applied on top of the working directory
4623 --exact, patches will be applied on top of the working directory
4622 parent revision.
4624 parent revision.
4623
4625
4624 You can import a patch straight from a mail message. Even patches
4626 You can import a patch straight from a mail message. Even patches
4625 as attachments work (to use the body part, it must have type
4627 as attachments work (to use the body part, it must have type
4626 text/plain or text/x-patch). From and Subject headers of email
4628 text/plain or text/x-patch). From and Subject headers of email
4627 message are used as default committer and commit message. All
4629 message are used as default committer and commit message. All
4628 text/plain body parts before first diff are added to the commit
4630 text/plain body parts before first diff are added to the commit
4629 message.
4631 message.
4630
4632
4631 If the imported patch was generated by :hg:`export`, user and
4633 If the imported patch was generated by :hg:`export`, user and
4632 description from patch override values from message headers and
4634 description from patch override values from message headers and
4633 body. Values given on command line with -m/--message and -u/--user
4635 body. Values given on command line with -m/--message and -u/--user
4634 override these.
4636 override these.
4635
4637
4636 If --exact is specified, import will set the working directory to
4638 If --exact is specified, import will set the working directory to
4637 the parent of each patch before applying it, and will abort if the
4639 the parent of each patch before applying it, and will abort if the
4638 resulting changeset has a different ID than the one recorded in
4640 resulting changeset has a different ID than the one recorded in
4639 the patch. This may happen due to character set problems or other
4641 the patch. This may happen due to character set problems or other
4640 deficiencies in the text patch format.
4642 deficiencies in the text patch format.
4641
4643
4642 Use --partial to ensure a changeset will be created from the patch
4644 Use --partial to ensure a changeset will be created from the patch
4643 even if some hunks fail to apply. Hunks that fail to apply will be
4645 even if some hunks fail to apply. Hunks that fail to apply will be
4644 written to a <target-file>.rej file. Conflicts can then be resolved
4646 written to a <target-file>.rej file. Conflicts can then be resolved
4645 by hand before :hg:`commit --amend` is run to update the created
4647 by hand before :hg:`commit --amend` is run to update the created
4646 changeset. This flag exists to let people import patches that
4648 changeset. This flag exists to let people import patches that
4647 partially apply without losing the associated metadata (author,
4649 partially apply without losing the associated metadata (author,
4648 date, description, ...).
4650 date, description, ...).
4649
4651
4650 .. note::
4652 .. note::
4651
4653
4652 When no hunks apply cleanly, :hg:`import --partial` will create
4654 When no hunks apply cleanly, :hg:`import --partial` will create
4653 an empty changeset, importing only the patch metadata.
4655 an empty changeset, importing only the patch metadata.
4654
4656
4655 With -s/--similarity, hg will attempt to discover renames and
4657 With -s/--similarity, hg will attempt to discover renames and
4656 copies in the patch in the same way as :hg:`addremove`.
4658 copies in the patch in the same way as :hg:`addremove`.
4657
4659
4658 It is possible to use external patch programs to perform the patch
4660 It is possible to use external patch programs to perform the patch
4659 by setting the ``ui.patch`` configuration option. For the default
4661 by setting the ``ui.patch`` configuration option. For the default
4660 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4662 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4661 See :hg:`help config` for more information about configuration
4663 See :hg:`help config` for more information about configuration
4662 files and how to use these options.
4664 files and how to use these options.
4663
4665
4664 See :hg:`help dates` for a list of formats valid for -d/--date.
4666 See :hg:`help dates` for a list of formats valid for -d/--date.
4665
4667
4666 .. container:: verbose
4668 .. container:: verbose
4667
4669
4668 Examples:
4670 Examples:
4669
4671
4670 - import a traditional patch from a website and detect renames::
4672 - import a traditional patch from a website and detect renames::
4671
4673
4672 hg import -s 80 http://example.com/bugfix.patch
4674 hg import -s 80 http://example.com/bugfix.patch
4673
4675
4674 - import a changeset from an hgweb server::
4676 - import a changeset from an hgweb server::
4675
4677
4676 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4678 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4677
4679
4678 - import all the patches in an Unix-style mbox::
4680 - import all the patches in an Unix-style mbox::
4679
4681
4680 hg import incoming-patches.mbox
4682 hg import incoming-patches.mbox
4681
4683
4682 - attempt to exactly restore an exported changeset (not always
4684 - attempt to exactly restore an exported changeset (not always
4683 possible)::
4685 possible)::
4684
4686
4685 hg import --exact proposed-fix.patch
4687 hg import --exact proposed-fix.patch
4686
4688
4687 - use an external tool to apply a patch which is too fuzzy for
4689 - use an external tool to apply a patch which is too fuzzy for
4688 the default internal tool.
4690 the default internal tool.
4689
4691
4690 hg import --config ui.patch="patch --merge" fuzzy.patch
4692 hg import --config ui.patch="patch --merge" fuzzy.patch
4691
4693
4692 - change the default fuzzing from 2 to a less strict 7
4694 - change the default fuzzing from 2 to a less strict 7
4693
4695
4694 hg import --config ui.fuzz=7 fuzz.patch
4696 hg import --config ui.fuzz=7 fuzz.patch
4695
4697
4696 Returns 0 on success, 1 on partial success (see --partial).
4698 Returns 0 on success, 1 on partial success (see --partial).
4697 """
4699 """
4698
4700
4699 if not patch1:
4701 if not patch1:
4700 raise error.Abort(_('need at least one patch to import'))
4702 raise error.Abort(_('need at least one patch to import'))
4701
4703
4702 patches = (patch1,) + patches
4704 patches = (patch1,) + patches
4703
4705
4704 date = opts.get('date')
4706 date = opts.get('date')
4705 if date:
4707 if date:
4706 opts['date'] = util.parsedate(date)
4708 opts['date'] = util.parsedate(date)
4707
4709
4708 exact = opts.get('exact')
4710 exact = opts.get('exact')
4709 update = not opts.get('bypass')
4711 update = not opts.get('bypass')
4710 if not update and opts.get('no_commit'):
4712 if not update and opts.get('no_commit'):
4711 raise error.Abort(_('cannot use --no-commit with --bypass'))
4713 raise error.Abort(_('cannot use --no-commit with --bypass'))
4712 try:
4714 try:
4713 sim = float(opts.get('similarity') or 0)
4715 sim = float(opts.get('similarity') or 0)
4714 except ValueError:
4716 except ValueError:
4715 raise error.Abort(_('similarity must be a number'))
4717 raise error.Abort(_('similarity must be a number'))
4716 if sim < 0 or sim > 100:
4718 if sim < 0 or sim > 100:
4717 raise error.Abort(_('similarity must be between 0 and 100'))
4719 raise error.Abort(_('similarity must be between 0 and 100'))
4718 if sim and not update:
4720 if sim and not update:
4719 raise error.Abort(_('cannot use --similarity with --bypass'))
4721 raise error.Abort(_('cannot use --similarity with --bypass'))
4720 if exact:
4722 if exact:
4721 if opts.get('edit'):
4723 if opts.get('edit'):
4722 raise error.Abort(_('cannot use --exact with --edit'))
4724 raise error.Abort(_('cannot use --exact with --edit'))
4723 if opts.get('prefix'):
4725 if opts.get('prefix'):
4724 raise error.Abort(_('cannot use --exact with --prefix'))
4726 raise error.Abort(_('cannot use --exact with --prefix'))
4725
4727
4726 base = opts["base"]
4728 base = opts["base"]
4727 wlock = dsguard = lock = tr = None
4729 wlock = dsguard = lock = tr = None
4728 msgs = []
4730 msgs = []
4729 ret = 0
4731 ret = 0
4730
4732
4731
4733
4732 try:
4734 try:
4733 wlock = repo.wlock()
4735 wlock = repo.wlock()
4734
4736
4735 if update:
4737 if update:
4736 cmdutil.checkunfinished(repo)
4738 cmdutil.checkunfinished(repo)
4737 if (exact or not opts.get('force')):
4739 if (exact or not opts.get('force')):
4738 cmdutil.bailifchanged(repo)
4740 cmdutil.bailifchanged(repo)
4739
4741
4740 if not opts.get('no_commit'):
4742 if not opts.get('no_commit'):
4741 lock = repo.lock()
4743 lock = repo.lock()
4742 tr = repo.transaction('import')
4744 tr = repo.transaction('import')
4743 else:
4745 else:
4744 dsguard = cmdutil.dirstateguard(repo, 'import')
4746 dsguard = cmdutil.dirstateguard(repo, 'import')
4745 parents = repo[None].parents()
4747 parents = repo[None].parents()
4746 for patchurl in patches:
4748 for patchurl in patches:
4747 if patchurl == '-':
4749 if patchurl == '-':
4748 ui.status(_('applying patch from stdin\n'))
4750 ui.status(_('applying patch from stdin\n'))
4749 patchfile = ui.fin
4751 patchfile = ui.fin
4750 patchurl = 'stdin' # for error message
4752 patchurl = 'stdin' # for error message
4751 else:
4753 else:
4752 patchurl = os.path.join(base, patchurl)
4754 patchurl = os.path.join(base, patchurl)
4753 ui.status(_('applying %s\n') % patchurl)
4755 ui.status(_('applying %s\n') % patchurl)
4754 patchfile = hg.openpath(ui, patchurl)
4756 patchfile = hg.openpath(ui, patchurl)
4755
4757
4756 haspatch = False
4758 haspatch = False
4757 for hunk in patch.split(patchfile):
4759 for hunk in patch.split(patchfile):
4758 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4760 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4759 parents, opts,
4761 parents, opts,
4760 msgs, hg.clean)
4762 msgs, hg.clean)
4761 if msg:
4763 if msg:
4762 haspatch = True
4764 haspatch = True
4763 ui.note(msg + '\n')
4765 ui.note(msg + '\n')
4764 if update or exact:
4766 if update or exact:
4765 parents = repo[None].parents()
4767 parents = repo[None].parents()
4766 else:
4768 else:
4767 parents = [repo[node]]
4769 parents = [repo[node]]
4768 if rej:
4770 if rej:
4769 ui.write_err(_("patch applied partially\n"))
4771 ui.write_err(_("patch applied partially\n"))
4770 ui.write_err(_("(fix the .rej files and run "
4772 ui.write_err(_("(fix the .rej files and run "
4771 "`hg commit --amend`)\n"))
4773 "`hg commit --amend`)\n"))
4772 ret = 1
4774 ret = 1
4773 break
4775 break
4774
4776
4775 if not haspatch:
4777 if not haspatch:
4776 raise error.Abort(_('%s: no diffs found') % patchurl)
4778 raise error.Abort(_('%s: no diffs found') % patchurl)
4777
4779
4778 if tr:
4780 if tr:
4779 tr.close()
4781 tr.close()
4780 if msgs:
4782 if msgs:
4781 repo.savecommitmessage('\n* * *\n'.join(msgs))
4783 repo.savecommitmessage('\n* * *\n'.join(msgs))
4782 if dsguard:
4784 if dsguard:
4783 dsguard.close()
4785 dsguard.close()
4784 return ret
4786 return ret
4785 finally:
4787 finally:
4786 if tr:
4788 if tr:
4787 tr.release()
4789 tr.release()
4788 release(lock, dsguard, wlock)
4790 release(lock, dsguard, wlock)
4789
4791
4790 @command('incoming|in',
4792 @command('incoming|in',
4791 [('f', 'force', None,
4793 [('f', 'force', None,
4792 _('run even if remote repository is unrelated')),
4794 _('run even if remote repository is unrelated')),
4793 ('n', 'newest-first', None, _('show newest record first')),
4795 ('n', 'newest-first', None, _('show newest record first')),
4794 ('', 'bundle', '',
4796 ('', 'bundle', '',
4795 _('file to store the bundles into'), _('FILE')),
4797 _('file to store the bundles into'), _('FILE')),
4796 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4798 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4797 ('B', 'bookmarks', False, _("compare bookmarks")),
4799 ('B', 'bookmarks', False, _("compare bookmarks")),
4798 ('b', 'branch', [],
4800 ('b', 'branch', [],
4799 _('a specific branch you would like to pull'), _('BRANCH')),
4801 _('a specific branch you would like to pull'), _('BRANCH')),
4800 ] + logopts + remoteopts + subrepoopts,
4802 ] + logopts + remoteopts + subrepoopts,
4801 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4803 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4802 def incoming(ui, repo, source="default", **opts):
4804 def incoming(ui, repo, source="default", **opts):
4803 """show new changesets found in source
4805 """show new changesets found in source
4804
4806
4805 Show new changesets found in the specified path/URL or the default
4807 Show new changesets found in the specified path/URL or the default
4806 pull location. These are the changesets that would have been pulled
4808 pull location. These are the changesets that would have been pulled
4807 if a pull at the time you issued this command.
4809 if a pull at the time you issued this command.
4808
4810
4809 See pull for valid source format details.
4811 See pull for valid source format details.
4810
4812
4811 .. container:: verbose
4813 .. container:: verbose
4812
4814
4813 With -B/--bookmarks, the result of bookmark comparison between
4815 With -B/--bookmarks, the result of bookmark comparison between
4814 local and remote repositories is displayed. With -v/--verbose,
4816 local and remote repositories is displayed. With -v/--verbose,
4815 status is also displayed for each bookmark like below::
4817 status is also displayed for each bookmark like below::
4816
4818
4817 BM1 01234567890a added
4819 BM1 01234567890a added
4818 BM2 1234567890ab advanced
4820 BM2 1234567890ab advanced
4819 BM3 234567890abc diverged
4821 BM3 234567890abc diverged
4820 BM4 34567890abcd changed
4822 BM4 34567890abcd changed
4821
4823
4822 The action taken locally when pulling depends on the
4824 The action taken locally when pulling depends on the
4823 status of each bookmark:
4825 status of each bookmark:
4824
4826
4825 :``added``: pull will create it
4827 :``added``: pull will create it
4826 :``advanced``: pull will update it
4828 :``advanced``: pull will update it
4827 :``diverged``: pull will create a divergent bookmark
4829 :``diverged``: pull will create a divergent bookmark
4828 :``changed``: result depends on remote changesets
4830 :``changed``: result depends on remote changesets
4829
4831
4830 From the point of view of pulling behavior, bookmark
4832 From the point of view of pulling behavior, bookmark
4831 existing only in the remote repository are treated as ``added``,
4833 existing only in the remote repository are treated as ``added``,
4832 even if it is in fact locally deleted.
4834 even if it is in fact locally deleted.
4833
4835
4834 .. container:: verbose
4836 .. container:: verbose
4835
4837
4836 For remote repository, using --bundle avoids downloading the
4838 For remote repository, using --bundle avoids downloading the
4837 changesets twice if the incoming is followed by a pull.
4839 changesets twice if the incoming is followed by a pull.
4838
4840
4839 Examples:
4841 Examples:
4840
4842
4841 - show incoming changes with patches and full description::
4843 - show incoming changes with patches and full description::
4842
4844
4843 hg incoming -vp
4845 hg incoming -vp
4844
4846
4845 - show incoming changes excluding merges, store a bundle::
4847 - show incoming changes excluding merges, store a bundle::
4846
4848
4847 hg in -vpM --bundle incoming.hg
4849 hg in -vpM --bundle incoming.hg
4848 hg pull incoming.hg
4850 hg pull incoming.hg
4849
4851
4850 - briefly list changes inside a bundle::
4852 - briefly list changes inside a bundle::
4851
4853
4852 hg in changes.hg -T "{desc|firstline}\\n"
4854 hg in changes.hg -T "{desc|firstline}\\n"
4853
4855
4854 Returns 0 if there are incoming changes, 1 otherwise.
4856 Returns 0 if there are incoming changes, 1 otherwise.
4855 """
4857 """
4856 if opts.get('graph'):
4858 if opts.get('graph'):
4857 cmdutil.checkunsupportedgraphflags([], opts)
4859 cmdutil.checkunsupportedgraphflags([], opts)
4858 def display(other, chlist, displayer):
4860 def display(other, chlist, displayer):
4859 revdag = cmdutil.graphrevs(other, chlist, opts)
4861 revdag = cmdutil.graphrevs(other, chlist, opts)
4860 cmdutil.displaygraph(ui, repo, revdag, displayer,
4862 cmdutil.displaygraph(ui, repo, revdag, displayer,
4861 graphmod.asciiedges)
4863 graphmod.asciiedges)
4862
4864
4863 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4865 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4864 return 0
4866 return 0
4865
4867
4866 if opts.get('bundle') and opts.get('subrepos'):
4868 if opts.get('bundle') and opts.get('subrepos'):
4867 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4869 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4868
4870
4869 if opts.get('bookmarks'):
4871 if opts.get('bookmarks'):
4870 source, branches = hg.parseurl(ui.expandpath(source),
4872 source, branches = hg.parseurl(ui.expandpath(source),
4871 opts.get('branch'))
4873 opts.get('branch'))
4872 other = hg.peer(repo, opts, source)
4874 other = hg.peer(repo, opts, source)
4873 if 'bookmarks' not in other.listkeys('namespaces'):
4875 if 'bookmarks' not in other.listkeys('namespaces'):
4874 ui.warn(_("remote doesn't support bookmarks\n"))
4876 ui.warn(_("remote doesn't support bookmarks\n"))
4875 return 0
4877 return 0
4876 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4878 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4877 return bookmarks.incoming(ui, repo, other)
4879 return bookmarks.incoming(ui, repo, other)
4878
4880
4879 repo._subtoppath = ui.expandpath(source)
4881 repo._subtoppath = ui.expandpath(source)
4880 try:
4882 try:
4881 return hg.incoming(ui, repo, source, opts)
4883 return hg.incoming(ui, repo, source, opts)
4882 finally:
4884 finally:
4883 del repo._subtoppath
4885 del repo._subtoppath
4884
4886
4885
4887
4886 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4888 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4887 norepo=True)
4889 norepo=True)
4888 def init(ui, dest=".", **opts):
4890 def init(ui, dest=".", **opts):
4889 """create a new repository in the given directory
4891 """create a new repository in the given directory
4890
4892
4891 Initialize a new repository in the given directory. If the given
4893 Initialize a new repository in the given directory. If the given
4892 directory does not exist, it will be created.
4894 directory does not exist, it will be created.
4893
4895
4894 If no directory is given, the current directory is used.
4896 If no directory is given, the current directory is used.
4895
4897
4896 It is possible to specify an ``ssh://`` URL as the destination.
4898 It is possible to specify an ``ssh://`` URL as the destination.
4897 See :hg:`help urls` for more information.
4899 See :hg:`help urls` for more information.
4898
4900
4899 Returns 0 on success.
4901 Returns 0 on success.
4900 """
4902 """
4901 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4903 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4902
4904
4903 @command('locate',
4905 @command('locate',
4904 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4906 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4905 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4907 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4906 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4908 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4907 ] + walkopts,
4909 ] + walkopts,
4908 _('[OPTION]... [PATTERN]...'))
4910 _('[OPTION]... [PATTERN]...'))
4909 def locate(ui, repo, *pats, **opts):
4911 def locate(ui, repo, *pats, **opts):
4910 """locate files matching specific patterns (DEPRECATED)
4912 """locate files matching specific patterns (DEPRECATED)
4911
4913
4912 Print files under Mercurial control in the working directory whose
4914 Print files under Mercurial control in the working directory whose
4913 names match the given patterns.
4915 names match the given patterns.
4914
4916
4915 By default, this command searches all directories in the working
4917 By default, this command searches all directories in the working
4916 directory. To search just the current directory and its
4918 directory. To search just the current directory and its
4917 subdirectories, use "--include .".
4919 subdirectories, use "--include .".
4918
4920
4919 If no patterns are given to match, this command prints the names
4921 If no patterns are given to match, this command prints the names
4920 of all files under Mercurial control in the working directory.
4922 of all files under Mercurial control in the working directory.
4921
4923
4922 If you want to feed the output of this command into the "xargs"
4924 If you want to feed the output of this command into the "xargs"
4923 command, use the -0 option to both this command and "xargs". This
4925 command, use the -0 option to both this command and "xargs". This
4924 will avoid the problem of "xargs" treating single filenames that
4926 will avoid the problem of "xargs" treating single filenames that
4925 contain whitespace as multiple filenames.
4927 contain whitespace as multiple filenames.
4926
4928
4927 See :hg:`help files` for a more versatile command.
4929 See :hg:`help files` for a more versatile command.
4928
4930
4929 Returns 0 if a match is found, 1 otherwise.
4931 Returns 0 if a match is found, 1 otherwise.
4930 """
4932 """
4931 if opts.get('print0'):
4933 if opts.get('print0'):
4932 end = '\0'
4934 end = '\0'
4933 else:
4935 else:
4934 end = '\n'
4936 end = '\n'
4935 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4937 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4936
4938
4937 ret = 1
4939 ret = 1
4938 ctx = repo[rev]
4940 ctx = repo[rev]
4939 m = scmutil.match(ctx, pats, opts, default='relglob',
4941 m = scmutil.match(ctx, pats, opts, default='relglob',
4940 badfn=lambda x, y: False)
4942 badfn=lambda x, y: False)
4941
4943
4942 for abs in ctx.matches(m):
4944 for abs in ctx.matches(m):
4943 if opts.get('fullpath'):
4945 if opts.get('fullpath'):
4944 ui.write(repo.wjoin(abs), end)
4946 ui.write(repo.wjoin(abs), end)
4945 else:
4947 else:
4946 ui.write(((pats and m.rel(abs)) or abs), end)
4948 ui.write(((pats and m.rel(abs)) or abs), end)
4947 ret = 0
4949 ret = 0
4948
4950
4949 return ret
4951 return ret
4950
4952
4951 @command('^log|history',
4953 @command('^log|history',
4952 [('f', 'follow', None,
4954 [('f', 'follow', None,
4953 _('follow changeset history, or file history across copies and renames')),
4955 _('follow changeset history, or file history across copies and renames')),
4954 ('', 'follow-first', None,
4956 ('', 'follow-first', None,
4955 _('only follow the first parent of merge changesets (DEPRECATED)')),
4957 _('only follow the first parent of merge changesets (DEPRECATED)')),
4956 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4958 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4957 ('C', 'copies', None, _('show copied files')),
4959 ('C', 'copies', None, _('show copied files')),
4958 ('k', 'keyword', [],
4960 ('k', 'keyword', [],
4959 _('do case-insensitive search for a given text'), _('TEXT')),
4961 _('do case-insensitive search for a given text'), _('TEXT')),
4960 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4962 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4961 ('', 'removed', None, _('include revisions where files were removed')),
4963 ('', 'removed', None, _('include revisions where files were removed')),
4962 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4964 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4963 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4965 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4964 ('', 'only-branch', [],
4966 ('', 'only-branch', [],
4965 _('show only changesets within the given named branch (DEPRECATED)'),
4967 _('show only changesets within the given named branch (DEPRECATED)'),
4966 _('BRANCH')),
4968 _('BRANCH')),
4967 ('b', 'branch', [],
4969 ('b', 'branch', [],
4968 _('show changesets within the given named branch'), _('BRANCH')),
4970 _('show changesets within the given named branch'), _('BRANCH')),
4969 ('P', 'prune', [],
4971 ('P', 'prune', [],
4970 _('do not display revision or any of its ancestors'), _('REV')),
4972 _('do not display revision or any of its ancestors'), _('REV')),
4971 ] + logopts + walkopts,
4973 ] + logopts + walkopts,
4972 _('[OPTION]... [FILE]'),
4974 _('[OPTION]... [FILE]'),
4973 inferrepo=True)
4975 inferrepo=True)
4974 def log(ui, repo, *pats, **opts):
4976 def log(ui, repo, *pats, **opts):
4975 """show revision history of entire repository or files
4977 """show revision history of entire repository or files
4976
4978
4977 Print the revision history of the specified files or the entire
4979 Print the revision history of the specified files or the entire
4978 project.
4980 project.
4979
4981
4980 If no revision range is specified, the default is ``tip:0`` unless
4982 If no revision range is specified, the default is ``tip:0`` unless
4981 --follow is set, in which case the working directory parent is
4983 --follow is set, in which case the working directory parent is
4982 used as the starting revision.
4984 used as the starting revision.
4983
4985
4984 File history is shown without following rename or copy history of
4986 File history is shown without following rename or copy history of
4985 files. Use -f/--follow with a filename to follow history across
4987 files. Use -f/--follow with a filename to follow history across
4986 renames and copies. --follow without a filename will only show
4988 renames and copies. --follow without a filename will only show
4987 ancestors or descendants of the starting revision.
4989 ancestors or descendants of the starting revision.
4988
4990
4989 By default this command prints revision number and changeset id,
4991 By default this command prints revision number and changeset id,
4990 tags, non-trivial parents, user, date and time, and a summary for
4992 tags, non-trivial parents, user, date and time, and a summary for
4991 each commit. When the -v/--verbose switch is used, the list of
4993 each commit. When the -v/--verbose switch is used, the list of
4992 changed files and full commit message are shown.
4994 changed files and full commit message are shown.
4993
4995
4994 With --graph the revisions are shown as an ASCII art DAG with the most
4996 With --graph the revisions are shown as an ASCII art DAG with the most
4995 recent changeset at the top.
4997 recent changeset at the top.
4996 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4998 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4997 and '+' represents a fork where the changeset from the lines below is a
4999 and '+' represents a fork where the changeset from the lines below is a
4998 parent of the 'o' merge on the same line.
5000 parent of the 'o' merge on the same line.
4999
5001
5000 .. note::
5002 .. note::
5001
5003
5002 :hg:`log --patch` may generate unexpected diff output for merge
5004 :hg:`log --patch` may generate unexpected diff output for merge
5003 changesets, as it will only compare the merge changeset against
5005 changesets, as it will only compare the merge changeset against
5004 its first parent. Also, only files different from BOTH parents
5006 its first parent. Also, only files different from BOTH parents
5005 will appear in files:.
5007 will appear in files:.
5006
5008
5007 .. note::
5009 .. note::
5008
5010
5009 For performance reasons, :hg:`log FILE` may omit duplicate changes
5011 For performance reasons, :hg:`log FILE` may omit duplicate changes
5010 made on branches and will not show removals or mode changes. To
5012 made on branches and will not show removals or mode changes. To
5011 see all such changes, use the --removed switch.
5013 see all such changes, use the --removed switch.
5012
5014
5013 .. container:: verbose
5015 .. container:: verbose
5014
5016
5015 Some examples:
5017 Some examples:
5016
5018
5017 - changesets with full descriptions and file lists::
5019 - changesets with full descriptions and file lists::
5018
5020
5019 hg log -v
5021 hg log -v
5020
5022
5021 - changesets ancestral to the working directory::
5023 - changesets ancestral to the working directory::
5022
5024
5023 hg log -f
5025 hg log -f
5024
5026
5025 - last 10 commits on the current branch::
5027 - last 10 commits on the current branch::
5026
5028
5027 hg log -l 10 -b .
5029 hg log -l 10 -b .
5028
5030
5029 - changesets showing all modifications of a file, including removals::
5031 - changesets showing all modifications of a file, including removals::
5030
5032
5031 hg log --removed file.c
5033 hg log --removed file.c
5032
5034
5033 - all changesets that touch a directory, with diffs, excluding merges::
5035 - all changesets that touch a directory, with diffs, excluding merges::
5034
5036
5035 hg log -Mp lib/
5037 hg log -Mp lib/
5036
5038
5037 - all revision numbers that match a keyword::
5039 - all revision numbers that match a keyword::
5038
5040
5039 hg log -k bug --template "{rev}\\n"
5041 hg log -k bug --template "{rev}\\n"
5040
5042
5041 - the full hash identifier of the working directory parent::
5043 - the full hash identifier of the working directory parent::
5042
5044
5043 hg log -r . --template "{node}\\n"
5045 hg log -r . --template "{node}\\n"
5044
5046
5045 - list available log templates::
5047 - list available log templates::
5046
5048
5047 hg log -T list
5049 hg log -T list
5048
5050
5049 - check if a given changeset is included in a tagged release::
5051 - check if a given changeset is included in a tagged release::
5050
5052
5051 hg log -r "a21ccf and ancestor(1.9)"
5053 hg log -r "a21ccf and ancestor(1.9)"
5052
5054
5053 - find all changesets by some user in a date range::
5055 - find all changesets by some user in a date range::
5054
5056
5055 hg log -k alice -d "may 2008 to jul 2008"
5057 hg log -k alice -d "may 2008 to jul 2008"
5056
5058
5057 - summary of all changesets after the last tag::
5059 - summary of all changesets after the last tag::
5058
5060
5059 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5061 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5060
5062
5061 See :hg:`help dates` for a list of formats valid for -d/--date.
5063 See :hg:`help dates` for a list of formats valid for -d/--date.
5062
5064
5063 See :hg:`help revisions` and :hg:`help revsets` for more about
5065 See :hg:`help revisions` and :hg:`help revsets` for more about
5064 specifying and ordering revisions.
5066 specifying and ordering revisions.
5065
5067
5066 See :hg:`help templates` for more about pre-packaged styles and
5068 See :hg:`help templates` for more about pre-packaged styles and
5067 specifying custom templates.
5069 specifying custom templates.
5068
5070
5069 Returns 0 on success.
5071 Returns 0 on success.
5070
5072
5071 """
5073 """
5072 if opts.get('follow') and opts.get('rev'):
5074 if opts.get('follow') and opts.get('rev'):
5073 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5075 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5074 del opts['follow']
5076 del opts['follow']
5075
5077
5076 if opts.get('graph'):
5078 if opts.get('graph'):
5077 return cmdutil.graphlog(ui, repo, *pats, **opts)
5079 return cmdutil.graphlog(ui, repo, *pats, **opts)
5078
5080
5079 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5081 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5080 limit = cmdutil.loglimit(opts)
5082 limit = cmdutil.loglimit(opts)
5081 count = 0
5083 count = 0
5082
5084
5083 getrenamed = None
5085 getrenamed = None
5084 if opts.get('copies'):
5086 if opts.get('copies'):
5085 endrev = None
5087 endrev = None
5086 if opts.get('rev'):
5088 if opts.get('rev'):
5087 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5089 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5088 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5090 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5089
5091
5090 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5092 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5091 for rev in revs:
5093 for rev in revs:
5092 if count == limit:
5094 if count == limit:
5093 break
5095 break
5094 ctx = repo[rev]
5096 ctx = repo[rev]
5095 copies = None
5097 copies = None
5096 if getrenamed is not None and rev:
5098 if getrenamed is not None and rev:
5097 copies = []
5099 copies = []
5098 for fn in ctx.files():
5100 for fn in ctx.files():
5099 rename = getrenamed(fn, rev)
5101 rename = getrenamed(fn, rev)
5100 if rename:
5102 if rename:
5101 copies.append((fn, rename[0]))
5103 copies.append((fn, rename[0]))
5102 if filematcher:
5104 if filematcher:
5103 revmatchfn = filematcher(ctx.rev())
5105 revmatchfn = filematcher(ctx.rev())
5104 else:
5106 else:
5105 revmatchfn = None
5107 revmatchfn = None
5106 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5108 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5107 if displayer.flush(ctx):
5109 if displayer.flush(ctx):
5108 count += 1
5110 count += 1
5109
5111
5110 displayer.close()
5112 displayer.close()
5111
5113
5112 @command('manifest',
5114 @command('manifest',
5113 [('r', 'rev', '', _('revision to display'), _('REV')),
5115 [('r', 'rev', '', _('revision to display'), _('REV')),
5114 ('', 'all', False, _("list files from all revisions"))]
5116 ('', 'all', False, _("list files from all revisions"))]
5115 + formatteropts,
5117 + formatteropts,
5116 _('[-r REV]'))
5118 _('[-r REV]'))
5117 def manifest(ui, repo, node=None, rev=None, **opts):
5119 def manifest(ui, repo, node=None, rev=None, **opts):
5118 """output the current or given revision of the project manifest
5120 """output the current or given revision of the project manifest
5119
5121
5120 Print a list of version controlled files for the given revision.
5122 Print a list of version controlled files for the given revision.
5121 If no revision is given, the first parent of the working directory
5123 If no revision is given, the first parent of the working directory
5122 is used, or the null revision if no revision is checked out.
5124 is used, or the null revision if no revision is checked out.
5123
5125
5124 With -v, print file permissions, symlink and executable bits.
5126 With -v, print file permissions, symlink and executable bits.
5125 With --debug, print file revision hashes.
5127 With --debug, print file revision hashes.
5126
5128
5127 If option --all is specified, the list of all files from all revisions
5129 If option --all is specified, the list of all files from all revisions
5128 is printed. This includes deleted and renamed files.
5130 is printed. This includes deleted and renamed files.
5129
5131
5130 Returns 0 on success.
5132 Returns 0 on success.
5131 """
5133 """
5132
5134
5133 fm = ui.formatter('manifest', opts)
5135 fm = ui.formatter('manifest', opts)
5134
5136
5135 if opts.get('all'):
5137 if opts.get('all'):
5136 if rev or node:
5138 if rev or node:
5137 raise error.Abort(_("can't specify a revision with --all"))
5139 raise error.Abort(_("can't specify a revision with --all"))
5138
5140
5139 res = []
5141 res = []
5140 prefix = "data/"
5142 prefix = "data/"
5141 suffix = ".i"
5143 suffix = ".i"
5142 plen = len(prefix)
5144 plen = len(prefix)
5143 slen = len(suffix)
5145 slen = len(suffix)
5144 with repo.lock():
5146 with repo.lock():
5145 for fn, b, size in repo.store.datafiles():
5147 for fn, b, size in repo.store.datafiles():
5146 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5148 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5147 res.append(fn[plen:-slen])
5149 res.append(fn[plen:-slen])
5148 for f in res:
5150 for f in res:
5149 fm.startitem()
5151 fm.startitem()
5150 fm.write("path", '%s\n', f)
5152 fm.write("path", '%s\n', f)
5151 fm.end()
5153 fm.end()
5152 return
5154 return
5153
5155
5154 if rev and node:
5156 if rev and node:
5155 raise error.Abort(_("please specify just one revision"))
5157 raise error.Abort(_("please specify just one revision"))
5156
5158
5157 if not node:
5159 if not node:
5158 node = rev
5160 node = rev
5159
5161
5160 char = {'l': '@', 'x': '*', '': ''}
5162 char = {'l': '@', 'x': '*', '': ''}
5161 mode = {'l': '644', 'x': '755', '': '644'}
5163 mode = {'l': '644', 'x': '755', '': '644'}
5162 ctx = scmutil.revsingle(repo, node)
5164 ctx = scmutil.revsingle(repo, node)
5163 mf = ctx.manifest()
5165 mf = ctx.manifest()
5164 for f in ctx:
5166 for f in ctx:
5165 fm.startitem()
5167 fm.startitem()
5166 fl = ctx[f].flags()
5168 fl = ctx[f].flags()
5167 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5169 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5168 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5170 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5169 fm.write('path', '%s\n', f)
5171 fm.write('path', '%s\n', f)
5170 fm.end()
5172 fm.end()
5171
5173
5172 @command('^merge',
5174 @command('^merge',
5173 [('f', 'force', None,
5175 [('f', 'force', None,
5174 _('force a merge including outstanding changes (DEPRECATED)')),
5176 _('force a merge including outstanding changes (DEPRECATED)')),
5175 ('r', 'rev', '', _('revision to merge'), _('REV')),
5177 ('r', 'rev', '', _('revision to merge'), _('REV')),
5176 ('P', 'preview', None,
5178 ('P', 'preview', None,
5177 _('review revisions to merge (no merge is performed)'))
5179 _('review revisions to merge (no merge is performed)'))
5178 ] + mergetoolopts,
5180 ] + mergetoolopts,
5179 _('[-P] [-f] [[-r] REV]'))
5181 _('[-P] [-f] [[-r] REV]'))
5180 def merge(ui, repo, node=None, **opts):
5182 def merge(ui, repo, node=None, **opts):
5181 """merge another revision into working directory
5183 """merge another revision into working directory
5182
5184
5183 The current working directory is updated with all changes made in
5185 The current working directory is updated with all changes made in
5184 the requested revision since the last common predecessor revision.
5186 the requested revision since the last common predecessor revision.
5185
5187
5186 Files that changed between either parent are marked as changed for
5188 Files that changed between either parent are marked as changed for
5187 the next commit and a commit must be performed before any further
5189 the next commit and a commit must be performed before any further
5188 updates to the repository are allowed. The next commit will have
5190 updates to the repository are allowed. The next commit will have
5189 two parents.
5191 two parents.
5190
5192
5191 ``--tool`` can be used to specify the merge tool used for file
5193 ``--tool`` can be used to specify the merge tool used for file
5192 merges. It overrides the HGMERGE environment variable and your
5194 merges. It overrides the HGMERGE environment variable and your
5193 configuration files. See :hg:`help merge-tools` for options.
5195 configuration files. See :hg:`help merge-tools` for options.
5194
5196
5195 If no revision is specified, the working directory's parent is a
5197 If no revision is specified, the working directory's parent is a
5196 head revision, and the current branch contains exactly one other
5198 head revision, and the current branch contains exactly one other
5197 head, the other head is merged with by default. Otherwise, an
5199 head, the other head is merged with by default. Otherwise, an
5198 explicit revision with which to merge with must be provided.
5200 explicit revision with which to merge with must be provided.
5199
5201
5200 See :hg:`help resolve` for information on handling file conflicts.
5202 See :hg:`help resolve` for information on handling file conflicts.
5201
5203
5202 To undo an uncommitted merge, use :hg:`update --clean .` which
5204 To undo an uncommitted merge, use :hg:`update --clean .` which
5203 will check out a clean copy of the original merge parent, losing
5205 will check out a clean copy of the original merge parent, losing
5204 all changes.
5206 all changes.
5205
5207
5206 Returns 0 on success, 1 if there are unresolved files.
5208 Returns 0 on success, 1 if there are unresolved files.
5207 """
5209 """
5208
5210
5209 if opts.get('rev') and node:
5211 if opts.get('rev') and node:
5210 raise error.Abort(_("please specify just one revision"))
5212 raise error.Abort(_("please specify just one revision"))
5211 if not node:
5213 if not node:
5212 node = opts.get('rev')
5214 node = opts.get('rev')
5213
5215
5214 if node:
5216 if node:
5215 node = scmutil.revsingle(repo, node).node()
5217 node = scmutil.revsingle(repo, node).node()
5216
5218
5217 if not node:
5219 if not node:
5218 node = repo[destutil.destmerge(repo)].node()
5220 node = repo[destutil.destmerge(repo)].node()
5219
5221
5220 if opts.get('preview'):
5222 if opts.get('preview'):
5221 # find nodes that are ancestors of p2 but not of p1
5223 # find nodes that are ancestors of p2 but not of p1
5222 p1 = repo.lookup('.')
5224 p1 = repo.lookup('.')
5223 p2 = repo.lookup(node)
5225 p2 = repo.lookup(node)
5224 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5226 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5225
5227
5226 displayer = cmdutil.show_changeset(ui, repo, opts)
5228 displayer = cmdutil.show_changeset(ui, repo, opts)
5227 for node in nodes:
5229 for node in nodes:
5228 displayer.show(repo[node])
5230 displayer.show(repo[node])
5229 displayer.close()
5231 displayer.close()
5230 return 0
5232 return 0
5231
5233
5232 try:
5234 try:
5233 # ui.forcemerge is an internal variable, do not document
5235 # ui.forcemerge is an internal variable, do not document
5234 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5236 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5235 return hg.merge(repo, node, force=opts.get('force'))
5237 return hg.merge(repo, node, force=opts.get('force'))
5236 finally:
5238 finally:
5237 ui.setconfig('ui', 'forcemerge', '', 'merge')
5239 ui.setconfig('ui', 'forcemerge', '', 'merge')
5238
5240
5239 @command('outgoing|out',
5241 @command('outgoing|out',
5240 [('f', 'force', None, _('run even when the destination is unrelated')),
5242 [('f', 'force', None, _('run even when the destination is unrelated')),
5241 ('r', 'rev', [],
5243 ('r', 'rev', [],
5242 _('a changeset intended to be included in the destination'), _('REV')),
5244 _('a changeset intended to be included in the destination'), _('REV')),
5243 ('n', 'newest-first', None, _('show newest record first')),
5245 ('n', 'newest-first', None, _('show newest record first')),
5244 ('B', 'bookmarks', False, _('compare bookmarks')),
5246 ('B', 'bookmarks', False, _('compare bookmarks')),
5245 ('b', 'branch', [], _('a specific branch you would like to push'),
5247 ('b', 'branch', [], _('a specific branch you would like to push'),
5246 _('BRANCH')),
5248 _('BRANCH')),
5247 ] + logopts + remoteopts + subrepoopts,
5249 ] + logopts + remoteopts + subrepoopts,
5248 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5250 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5249 def outgoing(ui, repo, dest=None, **opts):
5251 def outgoing(ui, repo, dest=None, **opts):
5250 """show changesets not found in the destination
5252 """show changesets not found in the destination
5251
5253
5252 Show changesets not found in the specified destination repository
5254 Show changesets not found in the specified destination repository
5253 or the default push location. These are the changesets that would
5255 or the default push location. These are the changesets that would
5254 be pushed if a push was requested.
5256 be pushed if a push was requested.
5255
5257
5256 See pull for details of valid destination formats.
5258 See pull for details of valid destination formats.
5257
5259
5258 .. container:: verbose
5260 .. container:: verbose
5259
5261
5260 With -B/--bookmarks, the result of bookmark comparison between
5262 With -B/--bookmarks, the result of bookmark comparison between
5261 local and remote repositories is displayed. With -v/--verbose,
5263 local and remote repositories is displayed. With -v/--verbose,
5262 status is also displayed for each bookmark like below::
5264 status is also displayed for each bookmark like below::
5263
5265
5264 BM1 01234567890a added
5266 BM1 01234567890a added
5265 BM2 deleted
5267 BM2 deleted
5266 BM3 234567890abc advanced
5268 BM3 234567890abc advanced
5267 BM4 34567890abcd diverged
5269 BM4 34567890abcd diverged
5268 BM5 4567890abcde changed
5270 BM5 4567890abcde changed
5269
5271
5270 The action taken when pushing depends on the
5272 The action taken when pushing depends on the
5271 status of each bookmark:
5273 status of each bookmark:
5272
5274
5273 :``added``: push with ``-B`` will create it
5275 :``added``: push with ``-B`` will create it
5274 :``deleted``: push with ``-B`` will delete it
5276 :``deleted``: push with ``-B`` will delete it
5275 :``advanced``: push will update it
5277 :``advanced``: push will update it
5276 :``diverged``: push with ``-B`` will update it
5278 :``diverged``: push with ``-B`` will update it
5277 :``changed``: push with ``-B`` will update it
5279 :``changed``: push with ``-B`` will update it
5278
5280
5279 From the point of view of pushing behavior, bookmarks
5281 From the point of view of pushing behavior, bookmarks
5280 existing only in the remote repository are treated as
5282 existing only in the remote repository are treated as
5281 ``deleted``, even if it is in fact added remotely.
5283 ``deleted``, even if it is in fact added remotely.
5282
5284
5283 Returns 0 if there are outgoing changes, 1 otherwise.
5285 Returns 0 if there are outgoing changes, 1 otherwise.
5284 """
5286 """
5285 if opts.get('graph'):
5287 if opts.get('graph'):
5286 cmdutil.checkunsupportedgraphflags([], opts)
5288 cmdutil.checkunsupportedgraphflags([], opts)
5287 o, other = hg._outgoing(ui, repo, dest, opts)
5289 o, other = hg._outgoing(ui, repo, dest, opts)
5288 if not o:
5290 if not o:
5289 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5291 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5290 return
5292 return
5291
5293
5292 revdag = cmdutil.graphrevs(repo, o, opts)
5294 revdag = cmdutil.graphrevs(repo, o, opts)
5293 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5295 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5294 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5296 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5295 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5297 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5296 return 0
5298 return 0
5297
5299
5298 if opts.get('bookmarks'):
5300 if opts.get('bookmarks'):
5299 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5301 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5300 dest, branches = hg.parseurl(dest, opts.get('branch'))
5302 dest, branches = hg.parseurl(dest, opts.get('branch'))
5301 other = hg.peer(repo, opts, dest)
5303 other = hg.peer(repo, opts, dest)
5302 if 'bookmarks' not in other.listkeys('namespaces'):
5304 if 'bookmarks' not in other.listkeys('namespaces'):
5303 ui.warn(_("remote doesn't support bookmarks\n"))
5305 ui.warn(_("remote doesn't support bookmarks\n"))
5304 return 0
5306 return 0
5305 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5307 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5306 return bookmarks.outgoing(ui, repo, other)
5308 return bookmarks.outgoing(ui, repo, other)
5307
5309
5308 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5310 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5309 try:
5311 try:
5310 return hg.outgoing(ui, repo, dest, opts)
5312 return hg.outgoing(ui, repo, dest, opts)
5311 finally:
5313 finally:
5312 del repo._subtoppath
5314 del repo._subtoppath
5313
5315
5314 @command('parents',
5316 @command('parents',
5315 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5317 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5316 ] + templateopts,
5318 ] + templateopts,
5317 _('[-r REV] [FILE]'),
5319 _('[-r REV] [FILE]'),
5318 inferrepo=True)
5320 inferrepo=True)
5319 def parents(ui, repo, file_=None, **opts):
5321 def parents(ui, repo, file_=None, **opts):
5320 """show the parents of the working directory or revision (DEPRECATED)
5322 """show the parents of the working directory or revision (DEPRECATED)
5321
5323
5322 Print the working directory's parent revisions. If a revision is
5324 Print the working directory's parent revisions. If a revision is
5323 given via -r/--rev, the parent of that revision will be printed.
5325 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
5326 If a file argument is given, the revision in which the file was
5325 last changed (before the working directory revision or the
5327 last changed (before the working directory revision or the
5326 argument to --rev if given) is printed.
5328 argument to --rev if given) is printed.
5327
5329
5328 This command is equivalent to::
5330 This command is equivalent to::
5329
5331
5330 hg log -r "p1()+p2()" or
5332 hg log -r "p1()+p2()" or
5331 hg log -r "p1(REV)+p2(REV)" or
5333 hg log -r "p1(REV)+p2(REV)" or
5332 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5334 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))"
5335 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5334
5336
5335 See :hg:`summary` and :hg:`help revsets` for related information.
5337 See :hg:`summary` and :hg:`help revsets` for related information.
5336
5338
5337 Returns 0 on success.
5339 Returns 0 on success.
5338 """
5340 """
5339
5341
5340 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5342 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5341
5343
5342 if file_:
5344 if file_:
5343 m = scmutil.match(ctx, (file_,), opts)
5345 m = scmutil.match(ctx, (file_,), opts)
5344 if m.anypats() or len(m.files()) != 1:
5346 if m.anypats() or len(m.files()) != 1:
5345 raise error.Abort(_('can only specify an explicit filename'))
5347 raise error.Abort(_('can only specify an explicit filename'))
5346 file_ = m.files()[0]
5348 file_ = m.files()[0]
5347 filenodes = []
5349 filenodes = []
5348 for cp in ctx.parents():
5350 for cp in ctx.parents():
5349 if not cp:
5351 if not cp:
5350 continue
5352 continue
5351 try:
5353 try:
5352 filenodes.append(cp.filenode(file_))
5354 filenodes.append(cp.filenode(file_))
5353 except error.LookupError:
5355 except error.LookupError:
5354 pass
5356 pass
5355 if not filenodes:
5357 if not filenodes:
5356 raise error.Abort(_("'%s' not found in manifest!") % file_)
5358 raise error.Abort(_("'%s' not found in manifest!") % file_)
5357 p = []
5359 p = []
5358 for fn in filenodes:
5360 for fn in filenodes:
5359 fctx = repo.filectx(file_, fileid=fn)
5361 fctx = repo.filectx(file_, fileid=fn)
5360 p.append(fctx.node())
5362 p.append(fctx.node())
5361 else:
5363 else:
5362 p = [cp.node() for cp in ctx.parents()]
5364 p = [cp.node() for cp in ctx.parents()]
5363
5365
5364 displayer = cmdutil.show_changeset(ui, repo, opts)
5366 displayer = cmdutil.show_changeset(ui, repo, opts)
5365 for n in p:
5367 for n in p:
5366 if n != nullid:
5368 if n != nullid:
5367 displayer.show(repo[n])
5369 displayer.show(repo[n])
5368 displayer.close()
5370 displayer.close()
5369
5371
5370 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5372 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5371 def paths(ui, repo, search=None, **opts):
5373 def paths(ui, repo, search=None, **opts):
5372 """show aliases for remote repositories
5374 """show aliases for remote repositories
5373
5375
5374 Show definition of symbolic path name NAME. If no name is given,
5376 Show definition of symbolic path name NAME. If no name is given,
5375 show definition of all available names.
5377 show definition of all available names.
5376
5378
5377 Option -q/--quiet suppresses all output when searching for NAME
5379 Option -q/--quiet suppresses all output when searching for NAME
5378 and shows only the path names when listing all definitions.
5380 and shows only the path names when listing all definitions.
5379
5381
5380 Path names are defined in the [paths] section of your
5382 Path names are defined in the [paths] section of your
5381 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5383 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5382 repository, ``.hg/hgrc`` is used, too.
5384 repository, ``.hg/hgrc`` is used, too.
5383
5385
5384 The path names ``default`` and ``default-push`` have a special
5386 The path names ``default`` and ``default-push`` have a special
5385 meaning. When performing a push or pull operation, they are used
5387 meaning. When performing a push or pull operation, they are used
5386 as fallbacks if no location is specified on the command-line.
5388 as fallbacks if no location is specified on the command-line.
5387 When ``default-push`` is set, it will be used for push and
5389 When ``default-push`` is set, it will be used for push and
5388 ``default`` will be used for pull; otherwise ``default`` is used
5390 ``default`` will be used for pull; otherwise ``default`` is used
5389 as the fallback for both. When cloning a repository, the clone
5391 as the fallback for both. When cloning a repository, the clone
5390 source is written as ``default`` in ``.hg/hgrc``.
5392 source is written as ``default`` in ``.hg/hgrc``.
5391
5393
5392 .. note::
5394 .. note::
5393
5395
5394 ``default`` and ``default-push`` apply to all inbound (e.g.
5396 ``default`` and ``default-push`` apply to all inbound (e.g.
5395 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5397 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5396 and :hg:`bundle`) operations.
5398 and :hg:`bundle`) operations.
5397
5399
5398 See :hg:`help urls` for more information.
5400 See :hg:`help urls` for more information.
5399
5401
5400 Returns 0 on success.
5402 Returns 0 on success.
5401 """
5403 """
5402 if search:
5404 if search:
5403 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5405 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5404 if name == search]
5406 if name == search]
5405 else:
5407 else:
5406 pathitems = sorted(ui.paths.iteritems())
5408 pathitems = sorted(ui.paths.iteritems())
5407
5409
5408 fm = ui.formatter('paths', opts)
5410 fm = ui.formatter('paths', opts)
5409 if fm:
5411 if fm:
5410 hidepassword = str
5412 hidepassword = str
5411 else:
5413 else:
5412 hidepassword = util.hidepassword
5414 hidepassword = util.hidepassword
5413 if ui.quiet:
5415 if ui.quiet:
5414 namefmt = '%s\n'
5416 namefmt = '%s\n'
5415 else:
5417 else:
5416 namefmt = '%s = '
5418 namefmt = '%s = '
5417 showsubopts = not search and not ui.quiet
5419 showsubopts = not search and not ui.quiet
5418
5420
5419 for name, path in pathitems:
5421 for name, path in pathitems:
5420 fm.startitem()
5422 fm.startitem()
5421 fm.condwrite(not search, 'name', namefmt, name)
5423 fm.condwrite(not search, 'name', namefmt, name)
5422 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5424 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5423 for subopt, value in sorted(path.suboptions.items()):
5425 for subopt, value in sorted(path.suboptions.items()):
5424 assert subopt not in ('name', 'url')
5426 assert subopt not in ('name', 'url')
5425 if showsubopts:
5427 if showsubopts:
5426 fm.plain('%s:%s = ' % (name, subopt))
5428 fm.plain('%s:%s = ' % (name, subopt))
5427 fm.condwrite(showsubopts, subopt, '%s\n', value)
5429 fm.condwrite(showsubopts, subopt, '%s\n', value)
5428
5430
5429 fm.end()
5431 fm.end()
5430
5432
5431 if search and not pathitems:
5433 if search and not pathitems:
5432 if not ui.quiet:
5434 if not ui.quiet:
5433 ui.warn(_("not found!\n"))
5435 ui.warn(_("not found!\n"))
5434 return 1
5436 return 1
5435 else:
5437 else:
5436 return 0
5438 return 0
5437
5439
5438 @command('phase',
5440 @command('phase',
5439 [('p', 'public', False, _('set changeset phase to public')),
5441 [('p', 'public', False, _('set changeset phase to public')),
5440 ('d', 'draft', False, _('set changeset phase to draft')),
5442 ('d', 'draft', False, _('set changeset phase to draft')),
5441 ('s', 'secret', False, _('set changeset phase to secret')),
5443 ('s', 'secret', False, _('set changeset phase to secret')),
5442 ('f', 'force', False, _('allow to move boundary backward')),
5444 ('f', 'force', False, _('allow to move boundary backward')),
5443 ('r', 'rev', [], _('target revision'), _('REV')),
5445 ('r', 'rev', [], _('target revision'), _('REV')),
5444 ],
5446 ],
5445 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5447 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5446 def phase(ui, repo, *revs, **opts):
5448 def phase(ui, repo, *revs, **opts):
5447 """set or show the current phase name
5449 """set or show the current phase name
5448
5450
5449 With no argument, show the phase name of the current revision(s).
5451 With no argument, show the phase name of the current revision(s).
5450
5452
5451 With one of -p/--public, -d/--draft or -s/--secret, change the
5453 With one of -p/--public, -d/--draft or -s/--secret, change the
5452 phase value of the specified revisions.
5454 phase value of the specified revisions.
5453
5455
5454 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5456 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::
5457 lower phase to an higher phase. Phases are ordered as follows::
5456
5458
5457 public < draft < secret
5459 public < draft < secret
5458
5460
5459 Returns 0 on success, 1 if some phases could not be changed.
5461 Returns 0 on success, 1 if some phases could not be changed.
5460
5462
5461 (For more information about the phases concept, see :hg:`help phases`.)
5463 (For more information about the phases concept, see :hg:`help phases`.)
5462 """
5464 """
5463 # search for a unique phase argument
5465 # search for a unique phase argument
5464 targetphase = None
5466 targetphase = None
5465 for idx, name in enumerate(phases.phasenames):
5467 for idx, name in enumerate(phases.phasenames):
5466 if opts[name]:
5468 if opts[name]:
5467 if targetphase is not None:
5469 if targetphase is not None:
5468 raise error.Abort(_('only one phase can be specified'))
5470 raise error.Abort(_('only one phase can be specified'))
5469 targetphase = idx
5471 targetphase = idx
5470
5472
5471 # look for specified revision
5473 # look for specified revision
5472 revs = list(revs)
5474 revs = list(revs)
5473 revs.extend(opts['rev'])
5475 revs.extend(opts['rev'])
5474 if not revs:
5476 if not revs:
5475 # display both parents as the second parent phase can influence
5477 # display both parents as the second parent phase can influence
5476 # the phase of a merge commit
5478 # the phase of a merge commit
5477 revs = [c.rev() for c in repo[None].parents()]
5479 revs = [c.rev() for c in repo[None].parents()]
5478
5480
5479 revs = scmutil.revrange(repo, revs)
5481 revs = scmutil.revrange(repo, revs)
5480
5482
5481 lock = None
5483 lock = None
5482 ret = 0
5484 ret = 0
5483 if targetphase is None:
5485 if targetphase is None:
5484 # display
5486 # display
5485 for r in revs:
5487 for r in revs:
5486 ctx = repo[r]
5488 ctx = repo[r]
5487 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5489 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5488 else:
5490 else:
5489 tr = None
5491 tr = None
5490 lock = repo.lock()
5492 lock = repo.lock()
5491 try:
5493 try:
5492 tr = repo.transaction("phase")
5494 tr = repo.transaction("phase")
5493 # set phase
5495 # set phase
5494 if not revs:
5496 if not revs:
5495 raise error.Abort(_('empty revision set'))
5497 raise error.Abort(_('empty revision set'))
5496 nodes = [repo[r].node() for r in revs]
5498 nodes = [repo[r].node() for r in revs]
5497 # moving revision from public to draft may hide them
5499 # moving revision from public to draft may hide them
5498 # We have to check result on an unfiltered repository
5500 # We have to check result on an unfiltered repository
5499 unfi = repo.unfiltered()
5501 unfi = repo.unfiltered()
5500 getphase = unfi._phasecache.phase
5502 getphase = unfi._phasecache.phase
5501 olddata = [getphase(unfi, r) for r in unfi]
5503 olddata = [getphase(unfi, r) for r in unfi]
5502 phases.advanceboundary(repo, tr, targetphase, nodes)
5504 phases.advanceboundary(repo, tr, targetphase, nodes)
5503 if opts['force']:
5505 if opts['force']:
5504 phases.retractboundary(repo, tr, targetphase, nodes)
5506 phases.retractboundary(repo, tr, targetphase, nodes)
5505 tr.close()
5507 tr.close()
5506 finally:
5508 finally:
5507 if tr is not None:
5509 if tr is not None:
5508 tr.release()
5510 tr.release()
5509 lock.release()
5511 lock.release()
5510 getphase = unfi._phasecache.phase
5512 getphase = unfi._phasecache.phase
5511 newdata = [getphase(unfi, r) for r in unfi]
5513 newdata = [getphase(unfi, r) for r in unfi]
5512 changes = sum(newdata[r] != olddata[r] for r in unfi)
5514 changes = sum(newdata[r] != olddata[r] for r in unfi)
5513 cl = unfi.changelog
5515 cl = unfi.changelog
5514 rejected = [n for n in nodes
5516 rejected = [n for n in nodes
5515 if newdata[cl.rev(n)] < targetphase]
5517 if newdata[cl.rev(n)] < targetphase]
5516 if rejected:
5518 if rejected:
5517 ui.warn(_('cannot move %i changesets to a higher '
5519 ui.warn(_('cannot move %i changesets to a higher '
5518 'phase, use --force\n') % len(rejected))
5520 'phase, use --force\n') % len(rejected))
5519 ret = 1
5521 ret = 1
5520 if changes:
5522 if changes:
5521 msg = _('phase changed for %i changesets\n') % changes
5523 msg = _('phase changed for %i changesets\n') % changes
5522 if ret:
5524 if ret:
5523 ui.status(msg)
5525 ui.status(msg)
5524 else:
5526 else:
5525 ui.note(msg)
5527 ui.note(msg)
5526 else:
5528 else:
5527 ui.warn(_('no phases changed\n'))
5529 ui.warn(_('no phases changed\n'))
5528 return ret
5530 return ret
5529
5531
5530 def postincoming(ui, repo, modheads, optupdate, checkout):
5532 def postincoming(ui, repo, modheads, optupdate, checkout):
5531 if modheads == 0:
5533 if modheads == 0:
5532 return
5534 return
5533 if optupdate:
5535 if optupdate:
5534 try:
5536 try:
5535 brev = checkout
5537 brev = checkout
5536 movemarkfrom = None
5538 movemarkfrom = None
5537 if not checkout:
5539 if not checkout:
5538 updata = destutil.destupdate(repo)
5540 updata = destutil.destupdate(repo)
5539 checkout, movemarkfrom, brev = updata
5541 checkout, movemarkfrom, brev = updata
5540 ret = hg.update(repo, checkout)
5542 ret = hg.update(repo, checkout)
5541 except error.UpdateAbort as inst:
5543 except error.UpdateAbort as inst:
5542 msg = _("not updating: %s") % str(inst)
5544 msg = _("not updating: %s") % str(inst)
5543 hint = inst.hint
5545 hint = inst.hint
5544 raise error.UpdateAbort(msg, hint=hint)
5546 raise error.UpdateAbort(msg, hint=hint)
5545 if not ret and movemarkfrom:
5547 if not ret and movemarkfrom:
5546 if movemarkfrom == repo['.'].node():
5548 if movemarkfrom == repo['.'].node():
5547 pass # no-op update
5549 pass # no-op update
5548 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5550 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5549 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5551 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5550 return ret
5552 return ret
5551 if modheads > 1:
5553 if modheads > 1:
5552 currentbranchheads = len(repo.branchheads())
5554 currentbranchheads = len(repo.branchheads())
5553 if currentbranchheads == modheads:
5555 if currentbranchheads == modheads:
5554 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5556 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5555 elif currentbranchheads > 1:
5557 elif currentbranchheads > 1:
5556 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5558 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5557 "merge)\n"))
5559 "merge)\n"))
5558 else:
5560 else:
5559 ui.status(_("(run 'hg heads' to see heads)\n"))
5561 ui.status(_("(run 'hg heads' to see heads)\n"))
5560 else:
5562 else:
5561 ui.status(_("(run 'hg update' to get a working copy)\n"))
5563 ui.status(_("(run 'hg update' to get a working copy)\n"))
5562
5564
5563 @command('^pull',
5565 @command('^pull',
5564 [('u', 'update', None,
5566 [('u', 'update', None,
5565 _('update to new branch head if changesets were pulled')),
5567 _('update to new branch head if changesets were pulled')),
5566 ('f', 'force', None, _('run even when remote repository is unrelated')),
5568 ('f', 'force', None, _('run even when remote repository is unrelated')),
5567 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5569 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5568 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5570 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5569 ('b', 'branch', [], _('a specific branch you would like to pull'),
5571 ('b', 'branch', [], _('a specific branch you would like to pull'),
5570 _('BRANCH')),
5572 _('BRANCH')),
5571 ] + remoteopts,
5573 ] + remoteopts,
5572 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5574 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5573 def pull(ui, repo, source="default", **opts):
5575 def pull(ui, repo, source="default", **opts):
5574 """pull changes from the specified source
5576 """pull changes from the specified source
5575
5577
5576 Pull changes from a remote repository to a local one.
5578 Pull changes from a remote repository to a local one.
5577
5579
5578 This finds all changes from the repository at the specified path
5580 This finds all changes from the repository at the specified path
5579 or URL and adds them to a local repository (the current one unless
5581 or URL and adds them to a local repository (the current one unless
5580 -R is specified). By default, this does not update the copy of the
5582 -R is specified). By default, this does not update the copy of the
5581 project in the working directory.
5583 project in the working directory.
5582
5584
5583 Use :hg:`incoming` if you want to see what would have been added
5585 Use :hg:`incoming` if you want to see what would have been added
5584 by a pull at the time you issued this command. If you then decide
5586 by a pull at the time you issued this command. If you then decide
5585 to add those changes to the repository, you should use :hg:`pull
5587 to add those changes to the repository, you should use :hg:`pull
5586 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5588 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5587
5589
5588 If SOURCE is omitted, the 'default' path will be used.
5590 If SOURCE is omitted, the 'default' path will be used.
5589 See :hg:`help urls` for more information.
5591 See :hg:`help urls` for more information.
5590
5592
5591 Returns 0 on success, 1 if an update had unresolved files.
5593 Returns 0 on success, 1 if an update had unresolved files.
5592 """
5594 """
5593 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5595 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5594 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5596 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5595 other = hg.peer(repo, opts, source)
5597 other = hg.peer(repo, opts, source)
5596 try:
5598 try:
5597 revs, checkout = hg.addbranchrevs(repo, other, branches,
5599 revs, checkout = hg.addbranchrevs(repo, other, branches,
5598 opts.get('rev'))
5600 opts.get('rev'))
5599
5601
5600
5602
5601 pullopargs = {}
5603 pullopargs = {}
5602 if opts.get('bookmark'):
5604 if opts.get('bookmark'):
5603 if not revs:
5605 if not revs:
5604 revs = []
5606 revs = []
5605 # The list of bookmark used here is not the one used to actually
5607 # The list of bookmark used here is not the one used to actually
5606 # update the bookmark name. This can result in the revision pulled
5608 # update the bookmark name. This can result in the revision pulled
5607 # not ending up with the name of the bookmark because of a race
5609 # not ending up with the name of the bookmark because of a race
5608 # condition on the server. (See issue 4689 for details)
5610 # condition on the server. (See issue 4689 for details)
5609 remotebookmarks = other.listkeys('bookmarks')
5611 remotebookmarks = other.listkeys('bookmarks')
5610 pullopargs['remotebookmarks'] = remotebookmarks
5612 pullopargs['remotebookmarks'] = remotebookmarks
5611 for b in opts['bookmark']:
5613 for b in opts['bookmark']:
5612 if b not in remotebookmarks:
5614 if b not in remotebookmarks:
5613 raise error.Abort(_('remote bookmark %s not found!') % b)
5615 raise error.Abort(_('remote bookmark %s not found!') % b)
5614 revs.append(remotebookmarks[b])
5616 revs.append(remotebookmarks[b])
5615
5617
5616 if revs:
5618 if revs:
5617 try:
5619 try:
5618 # When 'rev' is a bookmark name, we cannot guarantee that it
5620 # When 'rev' is a bookmark name, we cannot guarantee that it
5619 # will be updated with that name because of a race condition
5621 # will be updated with that name because of a race condition
5620 # server side. (See issue 4689 for details)
5622 # server side. (See issue 4689 for details)
5621 oldrevs = revs
5623 oldrevs = revs
5622 revs = [] # actually, nodes
5624 revs = [] # actually, nodes
5623 for r in oldrevs:
5625 for r in oldrevs:
5624 node = other.lookup(r)
5626 node = other.lookup(r)
5625 revs.append(node)
5627 revs.append(node)
5626 if r == checkout:
5628 if r == checkout:
5627 checkout = node
5629 checkout = node
5628 except error.CapabilityError:
5630 except error.CapabilityError:
5629 err = _("other repository doesn't support revision lookup, "
5631 err = _("other repository doesn't support revision lookup, "
5630 "so a rev cannot be specified.")
5632 "so a rev cannot be specified.")
5631 raise error.Abort(err)
5633 raise error.Abort(err)
5632
5634
5633 pullopargs.update(opts.get('opargs', {}))
5635 pullopargs.update(opts.get('opargs', {}))
5634 modheads = exchange.pull(repo, other, heads=revs,
5636 modheads = exchange.pull(repo, other, heads=revs,
5635 force=opts.get('force'),
5637 force=opts.get('force'),
5636 bookmarks=opts.get('bookmark', ()),
5638 bookmarks=opts.get('bookmark', ()),
5637 opargs=pullopargs).cgresult
5639 opargs=pullopargs).cgresult
5638 if checkout:
5640 if checkout:
5639 checkout = str(repo.changelog.rev(checkout))
5641 checkout = str(repo.changelog.rev(checkout))
5640 repo._subtoppath = source
5642 repo._subtoppath = source
5641 try:
5643 try:
5642 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5644 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5643
5645
5644 finally:
5646 finally:
5645 del repo._subtoppath
5647 del repo._subtoppath
5646
5648
5647 finally:
5649 finally:
5648 other.close()
5650 other.close()
5649 return ret
5651 return ret
5650
5652
5651 @command('^push',
5653 @command('^push',
5652 [('f', 'force', None, _('force push')),
5654 [('f', 'force', None, _('force push')),
5653 ('r', 'rev', [],
5655 ('r', 'rev', [],
5654 _('a changeset intended to be included in the destination'),
5656 _('a changeset intended to be included in the destination'),
5655 _('REV')),
5657 _('REV')),
5656 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5658 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5657 ('b', 'branch', [],
5659 ('b', 'branch', [],
5658 _('a specific branch you would like to push'), _('BRANCH')),
5660 _('a specific branch you would like to push'), _('BRANCH')),
5659 ('', 'new-branch', False, _('allow pushing a new branch')),
5661 ('', 'new-branch', False, _('allow pushing a new branch')),
5660 ] + remoteopts,
5662 ] + remoteopts,
5661 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5663 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5662 def push(ui, repo, dest=None, **opts):
5664 def push(ui, repo, dest=None, **opts):
5663 """push changes to the specified destination
5665 """push changes to the specified destination
5664
5666
5665 Push changesets from the local repository to the specified
5667 Push changesets from the local repository to the specified
5666 destination.
5668 destination.
5667
5669
5668 This operation is symmetrical to pull: it is identical to a pull
5670 This operation is symmetrical to pull: it is identical to a pull
5669 in the destination repository from the current one.
5671 in the destination repository from the current one.
5670
5672
5671 By default, push will not allow creation of new heads at the
5673 By default, push will not allow creation of new heads at the
5672 destination, since multiple heads would make it unclear which head
5674 destination, since multiple heads would make it unclear which head
5673 to use. In this situation, it is recommended to pull and merge
5675 to use. In this situation, it is recommended to pull and merge
5674 before pushing.
5676 before pushing.
5675
5677
5676 Use --new-branch if you want to allow push to create a new named
5678 Use --new-branch if you want to allow push to create a new named
5677 branch that is not present at the destination. This allows you to
5679 branch that is not present at the destination. This allows you to
5678 only create a new branch without forcing other changes.
5680 only create a new branch without forcing other changes.
5679
5681
5680 .. note::
5682 .. note::
5681
5683
5682 Extra care should be taken with the -f/--force option,
5684 Extra care should be taken with the -f/--force option,
5683 which will push all new heads on all branches, an action which will
5685 which will push all new heads on all branches, an action which will
5684 almost always cause confusion for collaborators.
5686 almost always cause confusion for collaborators.
5685
5687
5686 If -r/--rev is used, the specified revision and all its ancestors
5688 If -r/--rev is used, the specified revision and all its ancestors
5687 will be pushed to the remote repository.
5689 will be pushed to the remote repository.
5688
5690
5689 If -B/--bookmark is used, the specified bookmarked revision, its
5691 If -B/--bookmark is used, the specified bookmarked revision, its
5690 ancestors, and the bookmark will be pushed to the remote
5692 ancestors, and the bookmark will be pushed to the remote
5691 repository.
5693 repository.
5692
5694
5693 Please see :hg:`help urls` for important details about ``ssh://``
5695 Please see :hg:`help urls` for important details about ``ssh://``
5694 URLs. If DESTINATION is omitted, a default path will be used.
5696 URLs. If DESTINATION is omitted, a default path will be used.
5695
5697
5696 Returns 0 if push was successful, 1 if nothing to push.
5698 Returns 0 if push was successful, 1 if nothing to push.
5697 """
5699 """
5698
5700
5699 if opts.get('bookmark'):
5701 if opts.get('bookmark'):
5700 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5702 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5701 for b in opts['bookmark']:
5703 for b in opts['bookmark']:
5702 # translate -B options to -r so changesets get pushed
5704 # translate -B options to -r so changesets get pushed
5703 if b in repo._bookmarks:
5705 if b in repo._bookmarks:
5704 opts.setdefault('rev', []).append(b)
5706 opts.setdefault('rev', []).append(b)
5705 else:
5707 else:
5706 # if we try to push a deleted bookmark, translate it to null
5708 # if we try to push a deleted bookmark, translate it to null
5707 # this lets simultaneous -r, -b options continue working
5709 # this lets simultaneous -r, -b options continue working
5708 opts.setdefault('rev', []).append("null")
5710 opts.setdefault('rev', []).append("null")
5709
5711
5710 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5712 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5711 if not path:
5713 if not path:
5712 raise error.Abort(_('default repository not configured!'),
5714 raise error.Abort(_('default repository not configured!'),
5713 hint=_('see the "path" section in "hg help config"'))
5715 hint=_('see the "path" section in "hg help config"'))
5714 dest = path.pushloc or path.loc
5716 dest = path.pushloc or path.loc
5715 branches = (path.branch, opts.get('branch') or [])
5717 branches = (path.branch, opts.get('branch') or [])
5716 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5718 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5717 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5719 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5718 other = hg.peer(repo, opts, dest)
5720 other = hg.peer(repo, opts, dest)
5719
5721
5720 if revs:
5722 if revs:
5721 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5723 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5722 if not revs:
5724 if not revs:
5723 raise error.Abort(_("specified revisions evaluate to an empty set"),
5725 raise error.Abort(_("specified revisions evaluate to an empty set"),
5724 hint=_("use different revision arguments"))
5726 hint=_("use different revision arguments"))
5725
5727
5726 repo._subtoppath = dest
5728 repo._subtoppath = dest
5727 try:
5729 try:
5728 # push subrepos depth-first for coherent ordering
5730 # push subrepos depth-first for coherent ordering
5729 c = repo['']
5731 c = repo['']
5730 subs = c.substate # only repos that are committed
5732 subs = c.substate # only repos that are committed
5731 for s in sorted(subs):
5733 for s in sorted(subs):
5732 result = c.sub(s).push(opts)
5734 result = c.sub(s).push(opts)
5733 if result == 0:
5735 if result == 0:
5734 return not result
5736 return not result
5735 finally:
5737 finally:
5736 del repo._subtoppath
5738 del repo._subtoppath
5737 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5739 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5738 newbranch=opts.get('new_branch'),
5740 newbranch=opts.get('new_branch'),
5739 bookmarks=opts.get('bookmark', ()),
5741 bookmarks=opts.get('bookmark', ()),
5740 opargs=opts.get('opargs'))
5742 opargs=opts.get('opargs'))
5741
5743
5742 result = not pushop.cgresult
5744 result = not pushop.cgresult
5743
5745
5744 if pushop.bkresult is not None:
5746 if pushop.bkresult is not None:
5745 if pushop.bkresult == 2:
5747 if pushop.bkresult == 2:
5746 result = 2
5748 result = 2
5747 elif not result and pushop.bkresult:
5749 elif not result and pushop.bkresult:
5748 result = 2
5750 result = 2
5749
5751
5750 return result
5752 return result
5751
5753
5752 @command('recover', [])
5754 @command('recover', [])
5753 def recover(ui, repo):
5755 def recover(ui, repo):
5754 """roll back an interrupted transaction
5756 """roll back an interrupted transaction
5755
5757
5756 Recover from an interrupted commit or pull.
5758 Recover from an interrupted commit or pull.
5757
5759
5758 This command tries to fix the repository status after an
5760 This command tries to fix the repository status after an
5759 interrupted operation. It should only be necessary when Mercurial
5761 interrupted operation. It should only be necessary when Mercurial
5760 suggests it.
5762 suggests it.
5761
5763
5762 Returns 0 if successful, 1 if nothing to recover or verify fails.
5764 Returns 0 if successful, 1 if nothing to recover or verify fails.
5763 """
5765 """
5764 if repo.recover():
5766 if repo.recover():
5765 return hg.verify(repo)
5767 return hg.verify(repo)
5766 return 1
5768 return 1
5767
5769
5768 @command('^remove|rm',
5770 @command('^remove|rm',
5769 [('A', 'after', None, _('record delete for missing files')),
5771 [('A', 'after', None, _('record delete for missing files')),
5770 ('f', 'force', None,
5772 ('f', 'force', None,
5771 _('remove (and delete) file even if added or modified')),
5773 _('remove (and delete) file even if added or modified')),
5772 ] + subrepoopts + walkopts,
5774 ] + subrepoopts + walkopts,
5773 _('[OPTION]... FILE...'),
5775 _('[OPTION]... FILE...'),
5774 inferrepo=True)
5776 inferrepo=True)
5775 def remove(ui, repo, *pats, **opts):
5777 def remove(ui, repo, *pats, **opts):
5776 """remove the specified files on the next commit
5778 """remove the specified files on the next commit
5777
5779
5778 Schedule the indicated files for removal from the current branch.
5780 Schedule the indicated files for removal from the current branch.
5779
5781
5780 This command schedules the files to be removed at the next commit.
5782 This command schedules the files to be removed at the next commit.
5781 To undo a remove before that, see :hg:`revert`. To undo added
5783 To undo a remove before that, see :hg:`revert`. To undo added
5782 files, see :hg:`forget`.
5784 files, see :hg:`forget`.
5783
5785
5784 .. container:: verbose
5786 .. container:: verbose
5785
5787
5786 -A/--after can be used to remove only files that have already
5788 -A/--after can be used to remove only files that have already
5787 been deleted, -f/--force can be used to force deletion, and -Af
5789 been deleted, -f/--force can be used to force deletion, and -Af
5788 can be used to remove files from the next revision without
5790 can be used to remove files from the next revision without
5789 deleting them from the working directory.
5791 deleting them from the working directory.
5790
5792
5791 The following table details the behavior of remove for different
5793 The following table details the behavior of remove for different
5792 file states (columns) and option combinations (rows). The file
5794 file states (columns) and option combinations (rows). The file
5793 states are Added [A], Clean [C], Modified [M] and Missing [!]
5795 states are Added [A], Clean [C], Modified [M] and Missing [!]
5794 (as reported by :hg:`status`). The actions are Warn, Remove
5796 (as reported by :hg:`status`). The actions are Warn, Remove
5795 (from branch) and Delete (from disk):
5797 (from branch) and Delete (from disk):
5796
5798
5797 ========= == == == ==
5799 ========= == == == ==
5798 opt/state A C M !
5800 opt/state A C M !
5799 ========= == == == ==
5801 ========= == == == ==
5800 none W RD W R
5802 none W RD W R
5801 -f R RD RD R
5803 -f R RD RD R
5802 -A W W W R
5804 -A W W W R
5803 -Af R R R R
5805 -Af R R R R
5804 ========= == == == ==
5806 ========= == == == ==
5805
5807
5806 .. note::
5808 .. note::
5807
5809
5808 :hg:`remove` never deletes files in Added [A] state from the
5810 :hg:`remove` never deletes files in Added [A] state from the
5809 working directory, not even if ``--force`` is specified.
5811 working directory, not even if ``--force`` is specified.
5810
5812
5811 Returns 0 on success, 1 if any warnings encountered.
5813 Returns 0 on success, 1 if any warnings encountered.
5812 """
5814 """
5813
5815
5814 after, force = opts.get('after'), opts.get('force')
5816 after, force = opts.get('after'), opts.get('force')
5815 if not pats and not after:
5817 if not pats and not after:
5816 raise error.Abort(_('no files specified'))
5818 raise error.Abort(_('no files specified'))
5817
5819
5818 m = scmutil.match(repo[None], pats, opts)
5820 m = scmutil.match(repo[None], pats, opts)
5819 subrepos = opts.get('subrepos')
5821 subrepos = opts.get('subrepos')
5820 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5822 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5821
5823
5822 @command('rename|move|mv',
5824 @command('rename|move|mv',
5823 [('A', 'after', None, _('record a rename that has already occurred')),
5825 [('A', 'after', None, _('record a rename that has already occurred')),
5824 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5826 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5825 ] + walkopts + dryrunopts,
5827 ] + walkopts + dryrunopts,
5826 _('[OPTION]... SOURCE... DEST'))
5828 _('[OPTION]... SOURCE... DEST'))
5827 def rename(ui, repo, *pats, **opts):
5829 def rename(ui, repo, *pats, **opts):
5828 """rename files; equivalent of copy + remove
5830 """rename files; equivalent of copy + remove
5829
5831
5830 Mark dest as copies of sources; mark sources for deletion. If dest
5832 Mark dest as copies of sources; mark sources for deletion. If dest
5831 is a directory, copies are put in that directory. If dest is a
5833 is a directory, copies are put in that directory. If dest is a
5832 file, there can only be one source.
5834 file, there can only be one source.
5833
5835
5834 By default, this command copies the contents of files as they
5836 By default, this command copies the contents of files as they
5835 exist in the working directory. If invoked with -A/--after, the
5837 exist in the working directory. If invoked with -A/--after, the
5836 operation is recorded, but no copying is performed.
5838 operation is recorded, but no copying is performed.
5837
5839
5838 This command takes effect at the next commit. To undo a rename
5840 This command takes effect at the next commit. To undo a rename
5839 before that, see :hg:`revert`.
5841 before that, see :hg:`revert`.
5840
5842
5841 Returns 0 on success, 1 if errors are encountered.
5843 Returns 0 on success, 1 if errors are encountered.
5842 """
5844 """
5843 with repo.wlock(False):
5845 with repo.wlock(False):
5844 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5846 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5845
5847
5846 @command('resolve',
5848 @command('resolve',
5847 [('a', 'all', None, _('select all unresolved files')),
5849 [('a', 'all', None, _('select all unresolved files')),
5848 ('l', 'list', None, _('list state of files needing merge')),
5850 ('l', 'list', None, _('list state of files needing merge')),
5849 ('m', 'mark', None, _('mark files as resolved')),
5851 ('m', 'mark', None, _('mark files as resolved')),
5850 ('u', 'unmark', None, _('mark files as unresolved')),
5852 ('u', 'unmark', None, _('mark files as unresolved')),
5851 ('n', 'no-status', None, _('hide status prefix'))]
5853 ('n', 'no-status', None, _('hide status prefix'))]
5852 + mergetoolopts + walkopts + formatteropts,
5854 + mergetoolopts + walkopts + formatteropts,
5853 _('[OPTION]... [FILE]...'),
5855 _('[OPTION]... [FILE]...'),
5854 inferrepo=True)
5856 inferrepo=True)
5855 def resolve(ui, repo, *pats, **opts):
5857 def resolve(ui, repo, *pats, **opts):
5856 """redo merges or set/view the merge status of files
5858 """redo merges or set/view the merge status of files
5857
5859
5858 Merges with unresolved conflicts are often the result of
5860 Merges with unresolved conflicts are often the result of
5859 non-interactive merging using the ``internal:merge`` configuration
5861 non-interactive merging using the ``internal:merge`` configuration
5860 setting, or a command-line merge tool like ``diff3``. The resolve
5862 setting, or a command-line merge tool like ``diff3``. The resolve
5861 command is used to manage the files involved in a merge, after
5863 command is used to manage the files involved in a merge, after
5862 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5864 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5863 working directory must have two parents). See :hg:`help
5865 working directory must have two parents). See :hg:`help
5864 merge-tools` for information on configuring merge tools.
5866 merge-tools` for information on configuring merge tools.
5865
5867
5866 The resolve command can be used in the following ways:
5868 The resolve command can be used in the following ways:
5867
5869
5868 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5870 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5869 files, discarding any previous merge attempts. Re-merging is not
5871 files, discarding any previous merge attempts. Re-merging is not
5870 performed for files already marked as resolved. Use ``--all/-a``
5872 performed for files already marked as resolved. Use ``--all/-a``
5871 to select all unresolved files. ``--tool`` can be used to specify
5873 to select all unresolved files. ``--tool`` can be used to specify
5872 the merge tool used for the given files. It overrides the HGMERGE
5874 the merge tool used for the given files. It overrides the HGMERGE
5873 environment variable and your configuration files. Previous file
5875 environment variable and your configuration files. Previous file
5874 contents are saved with a ``.orig`` suffix.
5876 contents are saved with a ``.orig`` suffix.
5875
5877
5876 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5878 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5877 (e.g. after having manually fixed-up the files). The default is
5879 (e.g. after having manually fixed-up the files). The default is
5878 to mark all unresolved files.
5880 to mark all unresolved files.
5879
5881
5880 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5882 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5881 default is to mark all resolved files.
5883 default is to mark all resolved files.
5882
5884
5883 - :hg:`resolve -l`: list files which had or still have conflicts.
5885 - :hg:`resolve -l`: list files which had or still have conflicts.
5884 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5886 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5885
5887
5886 .. note::
5888 .. note::
5887
5889
5888 Mercurial will not let you commit files with unresolved merge
5890 Mercurial will not let you commit files with unresolved merge
5889 conflicts. You must use :hg:`resolve -m ...` before you can
5891 conflicts. You must use :hg:`resolve -m ...` before you can
5890 commit after a conflicting merge.
5892 commit after a conflicting merge.
5891
5893
5892 Returns 0 on success, 1 if any files fail a resolve attempt.
5894 Returns 0 on success, 1 if any files fail a resolve attempt.
5893 """
5895 """
5894
5896
5895 all, mark, unmark, show, nostatus = \
5897 all, mark, unmark, show, nostatus = \
5896 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5898 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5897
5899
5898 if (show and (mark or unmark)) or (mark and unmark):
5900 if (show and (mark or unmark)) or (mark and unmark):
5899 raise error.Abort(_("too many options specified"))
5901 raise error.Abort(_("too many options specified"))
5900 if pats and all:
5902 if pats and all:
5901 raise error.Abort(_("can't specify --all and patterns"))
5903 raise error.Abort(_("can't specify --all and patterns"))
5902 if not (all or pats or show or mark or unmark):
5904 if not (all or pats or show or mark or unmark):
5903 raise error.Abort(_('no files or directories specified'),
5905 raise error.Abort(_('no files or directories specified'),
5904 hint=('use --all to re-merge all unresolved files'))
5906 hint=('use --all to re-merge all unresolved files'))
5905
5907
5906 if show:
5908 if show:
5907 fm = ui.formatter('resolve', opts)
5909 fm = ui.formatter('resolve', opts)
5908 ms = mergemod.mergestate.read(repo)
5910 ms = mergemod.mergestate.read(repo)
5909 m = scmutil.match(repo[None], pats, opts)
5911 m = scmutil.match(repo[None], pats, opts)
5910 for f in ms:
5912 for f in ms:
5911 if not m(f):
5913 if not m(f):
5912 continue
5914 continue
5913 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5915 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5914 'd': 'driverresolved'}[ms[f]]
5916 'd': 'driverresolved'}[ms[f]]
5915 fm.startitem()
5917 fm.startitem()
5916 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5918 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5917 fm.write('path', '%s\n', f, label=l)
5919 fm.write('path', '%s\n', f, label=l)
5918 fm.end()
5920 fm.end()
5919 return 0
5921 return 0
5920
5922
5921 with repo.wlock():
5923 with repo.wlock():
5922 ms = mergemod.mergestate.read(repo)
5924 ms = mergemod.mergestate.read(repo)
5923
5925
5924 if not (ms.active() or repo.dirstate.p2() != nullid):
5926 if not (ms.active() or repo.dirstate.p2() != nullid):
5925 raise error.Abort(
5927 raise error.Abort(
5926 _('resolve command not applicable when not merging'))
5928 _('resolve command not applicable when not merging'))
5927
5929
5928 wctx = repo[None]
5930 wctx = repo[None]
5929
5931
5930 if ms.mergedriver and ms.mdstate() == 'u':
5932 if ms.mergedriver and ms.mdstate() == 'u':
5931 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5933 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5932 ms.commit()
5934 ms.commit()
5933 # allow mark and unmark to go through
5935 # allow mark and unmark to go through
5934 if not mark and not unmark and not proceed:
5936 if not mark and not unmark and not proceed:
5935 return 1
5937 return 1
5936
5938
5937 m = scmutil.match(wctx, pats, opts)
5939 m = scmutil.match(wctx, pats, opts)
5938 ret = 0
5940 ret = 0
5939 didwork = False
5941 didwork = False
5940 runconclude = False
5942 runconclude = False
5941
5943
5942 tocomplete = []
5944 tocomplete = []
5943 for f in ms:
5945 for f in ms:
5944 if not m(f):
5946 if not m(f):
5945 continue
5947 continue
5946
5948
5947 didwork = True
5949 didwork = True
5948
5950
5949 # don't let driver-resolved files be marked, and run the conclude
5951 # don't let driver-resolved files be marked, and run the conclude
5950 # step if asked to resolve
5952 # step if asked to resolve
5951 if ms[f] == "d":
5953 if ms[f] == "d":
5952 exact = m.exact(f)
5954 exact = m.exact(f)
5953 if mark:
5955 if mark:
5954 if exact:
5956 if exact:
5955 ui.warn(_('not marking %s as it is driver-resolved\n')
5957 ui.warn(_('not marking %s as it is driver-resolved\n')
5956 % f)
5958 % f)
5957 elif unmark:
5959 elif unmark:
5958 if exact:
5960 if exact:
5959 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5961 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5960 % f)
5962 % f)
5961 else:
5963 else:
5962 runconclude = True
5964 runconclude = True
5963 continue
5965 continue
5964
5966
5965 if mark:
5967 if mark:
5966 ms.mark(f, "r")
5968 ms.mark(f, "r")
5967 elif unmark:
5969 elif unmark:
5968 ms.mark(f, "u")
5970 ms.mark(f, "u")
5969 else:
5971 else:
5970 # backup pre-resolve (merge uses .orig for its own purposes)
5972 # backup pre-resolve (merge uses .orig for its own purposes)
5971 a = repo.wjoin(f)
5973 a = repo.wjoin(f)
5972 try:
5974 try:
5973 util.copyfile(a, a + ".resolve")
5975 util.copyfile(a, a + ".resolve")
5974 except (IOError, OSError) as inst:
5976 except (IOError, OSError) as inst:
5975 if inst.errno != errno.ENOENT:
5977 if inst.errno != errno.ENOENT:
5976 raise
5978 raise
5977
5979
5978 try:
5980 try:
5979 # preresolve file
5981 # preresolve file
5980 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5982 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5981 'resolve')
5983 'resolve')
5982 complete, r = ms.preresolve(f, wctx)
5984 complete, r = ms.preresolve(f, wctx)
5983 if not complete:
5985 if not complete:
5984 tocomplete.append(f)
5986 tocomplete.append(f)
5985 elif r:
5987 elif r:
5986 ret = 1
5988 ret = 1
5987 finally:
5989 finally:
5988 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5990 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5989 ms.commit()
5991 ms.commit()
5990
5992
5991 # replace filemerge's .orig file with our resolve file, but only
5993 # replace filemerge's .orig file with our resolve file, but only
5992 # for merges that are complete
5994 # for merges that are complete
5993 if complete:
5995 if complete:
5994 try:
5996 try:
5995 util.rename(a + ".resolve",
5997 util.rename(a + ".resolve",
5996 scmutil.origpath(ui, repo, a))
5998 scmutil.origpath(ui, repo, a))
5997 except OSError as inst:
5999 except OSError as inst:
5998 if inst.errno != errno.ENOENT:
6000 if inst.errno != errno.ENOENT:
5999 raise
6001 raise
6000
6002
6001 for f in tocomplete:
6003 for f in tocomplete:
6002 try:
6004 try:
6003 # resolve file
6005 # resolve file
6004 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6006 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6005 'resolve')
6007 'resolve')
6006 r = ms.resolve(f, wctx)
6008 r = ms.resolve(f, wctx)
6007 if r:
6009 if r:
6008 ret = 1
6010 ret = 1
6009 finally:
6011 finally:
6010 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6012 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6011 ms.commit()
6013 ms.commit()
6012
6014
6013 # replace filemerge's .orig file with our resolve file
6015 # replace filemerge's .orig file with our resolve file
6014 a = repo.wjoin(f)
6016 a = repo.wjoin(f)
6015 try:
6017 try:
6016 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6018 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6017 except OSError as inst:
6019 except OSError as inst:
6018 if inst.errno != errno.ENOENT:
6020 if inst.errno != errno.ENOENT:
6019 raise
6021 raise
6020
6022
6021 ms.commit()
6023 ms.commit()
6022 ms.recordactions()
6024 ms.recordactions()
6023
6025
6024 if not didwork and pats:
6026 if not didwork and pats:
6025 ui.warn(_("arguments do not match paths that need resolving\n"))
6027 ui.warn(_("arguments do not match paths that need resolving\n"))
6026 elif ms.mergedriver and ms.mdstate() != 's':
6028 elif ms.mergedriver and ms.mdstate() != 's':
6027 # run conclude step when either a driver-resolved file is requested
6029 # run conclude step when either a driver-resolved file is requested
6028 # or there are no driver-resolved files
6030 # or there are no driver-resolved files
6029 # we can't use 'ret' to determine whether any files are unresolved
6031 # we can't use 'ret' to determine whether any files are unresolved
6030 # because we might not have tried to resolve some
6032 # because we might not have tried to resolve some
6031 if ((runconclude or not list(ms.driverresolved()))
6033 if ((runconclude or not list(ms.driverresolved()))
6032 and not list(ms.unresolved())):
6034 and not list(ms.unresolved())):
6033 proceed = mergemod.driverconclude(repo, ms, wctx)
6035 proceed = mergemod.driverconclude(repo, ms, wctx)
6034 ms.commit()
6036 ms.commit()
6035 if not proceed:
6037 if not proceed:
6036 return 1
6038 return 1
6037
6039
6038 # Nudge users into finishing an unfinished operation
6040 # Nudge users into finishing an unfinished operation
6039 unresolvedf = list(ms.unresolved())
6041 unresolvedf = list(ms.unresolved())
6040 driverresolvedf = list(ms.driverresolved())
6042 driverresolvedf = list(ms.driverresolved())
6041 if not unresolvedf and not driverresolvedf:
6043 if not unresolvedf and not driverresolvedf:
6042 ui.status(_('(no more unresolved files)\n'))
6044 ui.status(_('(no more unresolved files)\n'))
6043 cmdutil.checkafterresolved(repo)
6045 cmdutil.checkafterresolved(repo)
6044 elif not unresolvedf:
6046 elif not unresolvedf:
6045 ui.status(_('(no more unresolved files -- '
6047 ui.status(_('(no more unresolved files -- '
6046 'run "hg resolve --all" to conclude)\n'))
6048 'run "hg resolve --all" to conclude)\n'))
6047
6049
6048 return ret
6050 return ret
6049
6051
6050 @command('revert',
6052 @command('revert',
6051 [('a', 'all', None, _('revert all changes when no arguments given')),
6053 [('a', 'all', None, _('revert all changes when no arguments given')),
6052 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6054 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6053 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6055 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6054 ('C', 'no-backup', None, _('do not save backup copies of files')),
6056 ('C', 'no-backup', None, _('do not save backup copies of files')),
6055 ('i', 'interactive', None,
6057 ('i', 'interactive', None,
6056 _('interactively select the changes (EXPERIMENTAL)')),
6058 _('interactively select the changes (EXPERIMENTAL)')),
6057 ] + walkopts + dryrunopts,
6059 ] + walkopts + dryrunopts,
6058 _('[OPTION]... [-r REV] [NAME]...'))
6060 _('[OPTION]... [-r REV] [NAME]...'))
6059 def revert(ui, repo, *pats, **opts):
6061 def revert(ui, repo, *pats, **opts):
6060 """restore files to their checkout state
6062 """restore files to their checkout state
6061
6063
6062 .. note::
6064 .. note::
6063
6065
6064 To check out earlier revisions, you should use :hg:`update REV`.
6066 To check out earlier revisions, you should use :hg:`update REV`.
6065 To cancel an uncommitted merge (and lose your changes),
6067 To cancel an uncommitted merge (and lose your changes),
6066 use :hg:`update --clean .`.
6068 use :hg:`update --clean .`.
6067
6069
6068 With no revision specified, revert the specified files or directories
6070 With no revision specified, revert the specified files or directories
6069 to the contents they had in the parent of the working directory.
6071 to the contents they had in the parent of the working directory.
6070 This restores the contents of files to an unmodified
6072 This restores the contents of files to an unmodified
6071 state and unschedules adds, removes, copies, and renames. If the
6073 state and unschedules adds, removes, copies, and renames. If the
6072 working directory has two parents, you must explicitly specify a
6074 working directory has two parents, you must explicitly specify a
6073 revision.
6075 revision.
6074
6076
6075 Using the -r/--rev or -d/--date options, revert the given files or
6077 Using the -r/--rev or -d/--date options, revert the given files or
6076 directories to their states as of a specific revision. Because
6078 directories to their states as of a specific revision. Because
6077 revert does not change the working directory parents, this will
6079 revert does not change the working directory parents, this will
6078 cause these files to appear modified. This can be helpful to "back
6080 cause these files to appear modified. This can be helpful to "back
6079 out" some or all of an earlier change. See :hg:`backout` for a
6081 out" some or all of an earlier change. See :hg:`backout` for a
6080 related method.
6082 related method.
6081
6083
6082 Modified files are saved with a .orig suffix before reverting.
6084 Modified files are saved with a .orig suffix before reverting.
6083 To disable these backups, use --no-backup.
6085 To disable these backups, use --no-backup.
6084
6086
6085 See :hg:`help dates` for a list of formats valid for -d/--date.
6087 See :hg:`help dates` for a list of formats valid for -d/--date.
6086
6088
6087 See :hg:`help backout` for a way to reverse the effect of an
6089 See :hg:`help backout` for a way to reverse the effect of an
6088 earlier changeset.
6090 earlier changeset.
6089
6091
6090 Returns 0 on success.
6092 Returns 0 on success.
6091 """
6093 """
6092
6094
6093 if opts.get("date"):
6095 if opts.get("date"):
6094 if opts.get("rev"):
6096 if opts.get("rev"):
6095 raise error.Abort(_("you can't specify a revision and a date"))
6097 raise error.Abort(_("you can't specify a revision and a date"))
6096 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6098 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6097
6099
6098 parent, p2 = repo.dirstate.parents()
6100 parent, p2 = repo.dirstate.parents()
6099 if not opts.get('rev') and p2 != nullid:
6101 if not opts.get('rev') and p2 != nullid:
6100 # revert after merge is a trap for new users (issue2915)
6102 # revert after merge is a trap for new users (issue2915)
6101 raise error.Abort(_('uncommitted merge with no revision specified'),
6103 raise error.Abort(_('uncommitted merge with no revision specified'),
6102 hint=_('use "hg update" or see "hg help revert"'))
6104 hint=_('use "hg update" or see "hg help revert"'))
6103
6105
6104 ctx = scmutil.revsingle(repo, opts.get('rev'))
6106 ctx = scmutil.revsingle(repo, opts.get('rev'))
6105
6107
6106 if (not (pats or opts.get('include') or opts.get('exclude') or
6108 if (not (pats or opts.get('include') or opts.get('exclude') or
6107 opts.get('all') or opts.get('interactive'))):
6109 opts.get('all') or opts.get('interactive'))):
6108 msg = _("no files or directories specified")
6110 msg = _("no files or directories specified")
6109 if p2 != nullid:
6111 if p2 != nullid:
6110 hint = _("uncommitted merge, use --all to discard all changes,"
6112 hint = _("uncommitted merge, use --all to discard all changes,"
6111 " or 'hg update -C .' to abort the merge")
6113 " or 'hg update -C .' to abort the merge")
6112 raise error.Abort(msg, hint=hint)
6114 raise error.Abort(msg, hint=hint)
6113 dirty = any(repo.status())
6115 dirty = any(repo.status())
6114 node = ctx.node()
6116 node = ctx.node()
6115 if node != parent:
6117 if node != parent:
6116 if dirty:
6118 if dirty:
6117 hint = _("uncommitted changes, use --all to discard all"
6119 hint = _("uncommitted changes, use --all to discard all"
6118 " changes, or 'hg update %s' to update") % ctx.rev()
6120 " changes, or 'hg update %s' to update") % ctx.rev()
6119 else:
6121 else:
6120 hint = _("use --all to revert all files,"
6122 hint = _("use --all to revert all files,"
6121 " or 'hg update %s' to update") % ctx.rev()
6123 " or 'hg update %s' to update") % ctx.rev()
6122 elif dirty:
6124 elif dirty:
6123 hint = _("uncommitted changes, use --all to discard all changes")
6125 hint = _("uncommitted changes, use --all to discard all changes")
6124 else:
6126 else:
6125 hint = _("use --all to revert all files")
6127 hint = _("use --all to revert all files")
6126 raise error.Abort(msg, hint=hint)
6128 raise error.Abort(msg, hint=hint)
6127
6129
6128 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6130 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6129
6131
6130 @command('rollback', dryrunopts +
6132 @command('rollback', dryrunopts +
6131 [('f', 'force', False, _('ignore safety measures'))])
6133 [('f', 'force', False, _('ignore safety measures'))])
6132 def rollback(ui, repo, **opts):
6134 def rollback(ui, repo, **opts):
6133 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6135 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6134
6136
6135 Please use :hg:`commit --amend` instead of rollback to correct
6137 Please use :hg:`commit --amend` instead of rollback to correct
6136 mistakes in the last commit.
6138 mistakes in the last commit.
6137
6139
6138 This command should be used with care. There is only one level of
6140 This command should be used with care. There is only one level of
6139 rollback, and there is no way to undo a rollback. It will also
6141 rollback, and there is no way to undo a rollback. It will also
6140 restore the dirstate at the time of the last transaction, losing
6142 restore the dirstate at the time of the last transaction, losing
6141 any dirstate changes since that time. This command does not alter
6143 any dirstate changes since that time. This command does not alter
6142 the working directory.
6144 the working directory.
6143
6145
6144 Transactions are used to encapsulate the effects of all commands
6146 Transactions are used to encapsulate the effects of all commands
6145 that create new changesets or propagate existing changesets into a
6147 that create new changesets or propagate existing changesets into a
6146 repository.
6148 repository.
6147
6149
6148 .. container:: verbose
6150 .. container:: verbose
6149
6151
6150 For example, the following commands are transactional, and their
6152 For example, the following commands are transactional, and their
6151 effects can be rolled back:
6153 effects can be rolled back:
6152
6154
6153 - commit
6155 - commit
6154 - import
6156 - import
6155 - pull
6157 - pull
6156 - push (with this repository as the destination)
6158 - push (with this repository as the destination)
6157 - unbundle
6159 - unbundle
6158
6160
6159 To avoid permanent data loss, rollback will refuse to rollback a
6161 To avoid permanent data loss, rollback will refuse to rollback a
6160 commit transaction if it isn't checked out. Use --force to
6162 commit transaction if it isn't checked out. Use --force to
6161 override this protection.
6163 override this protection.
6162
6164
6163 This command is not intended for use on public repositories. Once
6165 This command is not intended for use on public repositories. Once
6164 changes are visible for pull by other users, rolling a transaction
6166 changes are visible for pull by other users, rolling a transaction
6165 back locally is ineffective (someone else may already have pulled
6167 back locally is ineffective (someone else may already have pulled
6166 the changes). Furthermore, a race is possible with readers of the
6168 the changes). Furthermore, a race is possible with readers of the
6167 repository; for example an in-progress pull from the repository
6169 repository; for example an in-progress pull from the repository
6168 may fail if a rollback is performed.
6170 may fail if a rollback is performed.
6169
6171
6170 Returns 0 on success, 1 if no rollback data is available.
6172 Returns 0 on success, 1 if no rollback data is available.
6171 """
6173 """
6172 return repo.rollback(dryrun=opts.get('dry_run'),
6174 return repo.rollback(dryrun=opts.get('dry_run'),
6173 force=opts.get('force'))
6175 force=opts.get('force'))
6174
6176
6175 @command('root', [])
6177 @command('root', [])
6176 def root(ui, repo):
6178 def root(ui, repo):
6177 """print the root (top) of the current working directory
6179 """print the root (top) of the current working directory
6178
6180
6179 Print the root directory of the current repository.
6181 Print the root directory of the current repository.
6180
6182
6181 Returns 0 on success.
6183 Returns 0 on success.
6182 """
6184 """
6183 ui.write(repo.root + "\n")
6185 ui.write(repo.root + "\n")
6184
6186
6185 @command('^serve',
6187 @command('^serve',
6186 [('A', 'accesslog', '', _('name of access log file to write to'),
6188 [('A', 'accesslog', '', _('name of access log file to write to'),
6187 _('FILE')),
6189 _('FILE')),
6188 ('d', 'daemon', None, _('run server in background')),
6190 ('d', 'daemon', None, _('run server in background')),
6189 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6191 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6190 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6192 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6191 # use string type, then we can check if something was passed
6193 # use string type, then we can check if something was passed
6192 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6194 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6193 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6195 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6194 _('ADDR')),
6196 _('ADDR')),
6195 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6197 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6196 _('PREFIX')),
6198 _('PREFIX')),
6197 ('n', 'name', '',
6199 ('n', 'name', '',
6198 _('name to show in web pages (default: working directory)'), _('NAME')),
6200 _('name to show in web pages (default: working directory)'), _('NAME')),
6199 ('', 'web-conf', '',
6201 ('', 'web-conf', '',
6200 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6202 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6201 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6203 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6202 _('FILE')),
6204 _('FILE')),
6203 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6205 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6204 ('', 'stdio', None, _('for remote clients')),
6206 ('', 'stdio', None, _('for remote clients')),
6205 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6207 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6206 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6208 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6207 ('', 'style', '', _('template style to use'), _('STYLE')),
6209 ('', 'style', '', _('template style to use'), _('STYLE')),
6208 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6210 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6209 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6211 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6210 _('[OPTION]...'),
6212 _('[OPTION]...'),
6211 optionalrepo=True)
6213 optionalrepo=True)
6212 def serve(ui, repo, **opts):
6214 def serve(ui, repo, **opts):
6213 """start stand-alone webserver
6215 """start stand-alone webserver
6214
6216
6215 Start a local HTTP repository browser and pull server. You can use
6217 Start a local HTTP repository browser and pull server. You can use
6216 this for ad-hoc sharing and browsing of repositories. It is
6218 this for ad-hoc sharing and browsing of repositories. It is
6217 recommended to use a real web server to serve a repository for
6219 recommended to use a real web server to serve a repository for
6218 longer periods of time.
6220 longer periods of time.
6219
6221
6220 Please note that the server does not implement access control.
6222 Please note that the server does not implement access control.
6221 This means that, by default, anybody can read from the server and
6223 This means that, by default, anybody can read from the server and
6222 nobody can write to it by default. Set the ``web.allow_push``
6224 nobody can write to it by default. Set the ``web.allow_push``
6223 option to ``*`` to allow everybody to push to the server. You
6225 option to ``*`` to allow everybody to push to the server. You
6224 should use a real web server if you need to authenticate users.
6226 should use a real web server if you need to authenticate users.
6225
6227
6226 By default, the server logs accesses to stdout and errors to
6228 By default, the server logs accesses to stdout and errors to
6227 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6229 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6228 files.
6230 files.
6229
6231
6230 To have the server choose a free port number to listen on, specify
6232 To have the server choose a free port number to listen on, specify
6231 a port number of 0; in this case, the server will print the port
6233 a port number of 0; in this case, the server will print the port
6232 number it uses.
6234 number it uses.
6233
6235
6234 Returns 0 on success.
6236 Returns 0 on success.
6235 """
6237 """
6236
6238
6237 if opts["stdio"] and opts["cmdserver"]:
6239 if opts["stdio"] and opts["cmdserver"]:
6238 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6240 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6239
6241
6240 if opts["stdio"]:
6242 if opts["stdio"]:
6241 if repo is None:
6243 if repo is None:
6242 raise error.RepoError(_("there is no Mercurial repository here"
6244 raise error.RepoError(_("there is no Mercurial repository here"
6243 " (.hg not found)"))
6245 " (.hg not found)"))
6244 s = sshserver.sshserver(ui, repo)
6246 s = sshserver.sshserver(ui, repo)
6245 s.serve_forever()
6247 s.serve_forever()
6246
6248
6247 if opts["cmdserver"]:
6249 if opts["cmdserver"]:
6248 service = commandserver.createservice(ui, repo, opts)
6250 service = commandserver.createservice(ui, repo, opts)
6249 else:
6251 else:
6250 service = hgweb.createservice(ui, repo, opts)
6252 service = hgweb.createservice(ui, repo, opts)
6251 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6253 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6252
6254
6253 @command('^status|st',
6255 @command('^status|st',
6254 [('A', 'all', None, _('show status of all files')),
6256 [('A', 'all', None, _('show status of all files')),
6255 ('m', 'modified', None, _('show only modified files')),
6257 ('m', 'modified', None, _('show only modified files')),
6256 ('a', 'added', None, _('show only added files')),
6258 ('a', 'added', None, _('show only added files')),
6257 ('r', 'removed', None, _('show only removed files')),
6259 ('r', 'removed', None, _('show only removed files')),
6258 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6260 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6259 ('c', 'clean', None, _('show only files without changes')),
6261 ('c', 'clean', None, _('show only files without changes')),
6260 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6262 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6261 ('i', 'ignored', None, _('show only ignored files')),
6263 ('i', 'ignored', None, _('show only ignored files')),
6262 ('n', 'no-status', None, _('hide status prefix')),
6264 ('n', 'no-status', None, _('hide status prefix')),
6263 ('C', 'copies', None, _('show source of copied files')),
6265 ('C', 'copies', None, _('show source of copied files')),
6264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6266 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6265 ('', 'rev', [], _('show difference from revision'), _('REV')),
6267 ('', 'rev', [], _('show difference from revision'), _('REV')),
6266 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6268 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6267 ] + walkopts + subrepoopts + formatteropts,
6269 ] + walkopts + subrepoopts + formatteropts,
6268 _('[OPTION]... [FILE]...'),
6270 _('[OPTION]... [FILE]...'),
6269 inferrepo=True)
6271 inferrepo=True)
6270 def status(ui, repo, *pats, **opts):
6272 def status(ui, repo, *pats, **opts):
6271 """show changed files in the working directory
6273 """show changed files in the working directory
6272
6274
6273 Show status of files in the repository. If names are given, only
6275 Show status of files in the repository. If names are given, only
6274 files that match are shown. Files that are clean or ignored or
6276 files that match are shown. Files that are clean or ignored or
6275 the source of a copy/move operation, are not listed unless
6277 the source of a copy/move operation, are not listed unless
6276 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6278 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6277 Unless options described with "show only ..." are given, the
6279 Unless options described with "show only ..." are given, the
6278 options -mardu are used.
6280 options -mardu are used.
6279
6281
6280 Option -q/--quiet hides untracked (unknown and ignored) files
6282 Option -q/--quiet hides untracked (unknown and ignored) files
6281 unless explicitly requested with -u/--unknown or -i/--ignored.
6283 unless explicitly requested with -u/--unknown or -i/--ignored.
6282
6284
6283 .. note::
6285 .. note::
6284
6286
6285 :hg:`status` may appear to disagree with diff if permissions have
6287 :hg:`status` may appear to disagree with diff if permissions have
6286 changed or a merge has occurred. The standard diff format does
6288 changed or a merge has occurred. The standard diff format does
6287 not report permission changes and diff only reports changes
6289 not report permission changes and diff only reports changes
6288 relative to one merge parent.
6290 relative to one merge parent.
6289
6291
6290 If one revision is given, it is used as the base revision.
6292 If one revision is given, it is used as the base revision.
6291 If two revisions are given, the differences between them are
6293 If two revisions are given, the differences between them are
6292 shown. The --change option can also be used as a shortcut to list
6294 shown. The --change option can also be used as a shortcut to list
6293 the changed files of a revision from its first parent.
6295 the changed files of a revision from its first parent.
6294
6296
6295 The codes used to show the status of files are::
6297 The codes used to show the status of files are::
6296
6298
6297 M = modified
6299 M = modified
6298 A = added
6300 A = added
6299 R = removed
6301 R = removed
6300 C = clean
6302 C = clean
6301 ! = missing (deleted by non-hg command, but still tracked)
6303 ! = missing (deleted by non-hg command, but still tracked)
6302 ? = not tracked
6304 ? = not tracked
6303 I = ignored
6305 I = ignored
6304 = origin of the previous file (with --copies)
6306 = origin of the previous file (with --copies)
6305
6307
6306 .. container:: verbose
6308 .. container:: verbose
6307
6309
6308 Examples:
6310 Examples:
6309
6311
6310 - show changes in the working directory relative to a
6312 - show changes in the working directory relative to a
6311 changeset::
6313 changeset::
6312
6314
6313 hg status --rev 9353
6315 hg status --rev 9353
6314
6316
6315 - show changes in the working directory relative to the
6317 - show changes in the working directory relative to the
6316 current directory (see :hg:`help patterns` for more information)::
6318 current directory (see :hg:`help patterns` for more information)::
6317
6319
6318 hg status re:
6320 hg status re:
6319
6321
6320 - show all changes including copies in an existing changeset::
6322 - show all changes including copies in an existing changeset::
6321
6323
6322 hg status --copies --change 9353
6324 hg status --copies --change 9353
6323
6325
6324 - get a NUL separated list of added files, suitable for xargs::
6326 - get a NUL separated list of added files, suitable for xargs::
6325
6327
6326 hg status -an0
6328 hg status -an0
6327
6329
6328 Returns 0 on success.
6330 Returns 0 on success.
6329 """
6331 """
6330
6332
6331 revs = opts.get('rev')
6333 revs = opts.get('rev')
6332 change = opts.get('change')
6334 change = opts.get('change')
6333
6335
6334 if revs and change:
6336 if revs and change:
6335 msg = _('cannot specify --rev and --change at the same time')
6337 msg = _('cannot specify --rev and --change at the same time')
6336 raise error.Abort(msg)
6338 raise error.Abort(msg)
6337 elif change:
6339 elif change:
6338 node2 = scmutil.revsingle(repo, change, None).node()
6340 node2 = scmutil.revsingle(repo, change, None).node()
6339 node1 = repo[node2].p1().node()
6341 node1 = repo[node2].p1().node()
6340 else:
6342 else:
6341 node1, node2 = scmutil.revpair(repo, revs)
6343 node1, node2 = scmutil.revpair(repo, revs)
6342
6344
6343 if pats:
6345 if pats:
6344 cwd = repo.getcwd()
6346 cwd = repo.getcwd()
6345 else:
6347 else:
6346 cwd = ''
6348 cwd = ''
6347
6349
6348 if opts.get('print0'):
6350 if opts.get('print0'):
6349 end = '\0'
6351 end = '\0'
6350 else:
6352 else:
6351 end = '\n'
6353 end = '\n'
6352 copy = {}
6354 copy = {}
6353 states = 'modified added removed deleted unknown ignored clean'.split()
6355 states = 'modified added removed deleted unknown ignored clean'.split()
6354 show = [k for k in states if opts.get(k)]
6356 show = [k for k in states if opts.get(k)]
6355 if opts.get('all'):
6357 if opts.get('all'):
6356 show += ui.quiet and (states[:4] + ['clean']) or states
6358 show += ui.quiet and (states[:4] + ['clean']) or states
6357 if not show:
6359 if not show:
6358 if ui.quiet:
6360 if ui.quiet:
6359 show = states[:4]
6361 show = states[:4]
6360 else:
6362 else:
6361 show = states[:5]
6363 show = states[:5]
6362
6364
6363 m = scmutil.match(repo[node2], pats, opts)
6365 m = scmutil.match(repo[node2], pats, opts)
6364 stat = repo.status(node1, node2, m,
6366 stat = repo.status(node1, node2, m,
6365 'ignored' in show, 'clean' in show, 'unknown' in show,
6367 'ignored' in show, 'clean' in show, 'unknown' in show,
6366 opts.get('subrepos'))
6368 opts.get('subrepos'))
6367 changestates = zip(states, 'MAR!?IC', stat)
6369 changestates = zip(states, 'MAR!?IC', stat)
6368
6370
6369 if (opts.get('all') or opts.get('copies')
6371 if (opts.get('all') or opts.get('copies')
6370 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6372 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6371 copy = copies.pathcopies(repo[node1], repo[node2], m)
6373 copy = copies.pathcopies(repo[node1], repo[node2], m)
6372
6374
6373 fm = ui.formatter('status', opts)
6375 fm = ui.formatter('status', opts)
6374 fmt = '%s' + end
6376 fmt = '%s' + end
6375 showchar = not opts.get('no_status')
6377 showchar = not opts.get('no_status')
6376
6378
6377 for state, char, files in changestates:
6379 for state, char, files in changestates:
6378 if state in show:
6380 if state in show:
6379 label = 'status.' + state
6381 label = 'status.' + state
6380 for f in files:
6382 for f in files:
6381 fm.startitem()
6383 fm.startitem()
6382 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6384 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6383 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6385 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6384 if f in copy:
6386 if f in copy:
6385 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6387 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6386 label='status.copied')
6388 label='status.copied')
6387 fm.end()
6389 fm.end()
6388
6390
6389 @command('^summary|sum',
6391 @command('^summary|sum',
6390 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6392 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6391 def summary(ui, repo, **opts):
6393 def summary(ui, repo, **opts):
6392 """summarize working directory state
6394 """summarize working directory state
6393
6395
6394 This generates a brief summary of the working directory state,
6396 This generates a brief summary of the working directory state,
6395 including parents, branch, commit status, phase and available updates.
6397 including parents, branch, commit status, phase and available updates.
6396
6398
6397 With the --remote option, this will check the default paths for
6399 With the --remote option, this will check the default paths for
6398 incoming and outgoing changes. This can be time-consuming.
6400 incoming and outgoing changes. This can be time-consuming.
6399
6401
6400 Returns 0 on success.
6402 Returns 0 on success.
6401 """
6403 """
6402
6404
6403 ctx = repo[None]
6405 ctx = repo[None]
6404 parents = ctx.parents()
6406 parents = ctx.parents()
6405 pnode = parents[0].node()
6407 pnode = parents[0].node()
6406 marks = []
6408 marks = []
6407
6409
6408 for p in parents:
6410 for p in parents:
6409 # label with log.changeset (instead of log.parent) since this
6411 # label with log.changeset (instead of log.parent) since this
6410 # shows a working directory parent *changeset*:
6412 # shows a working directory parent *changeset*:
6411 # i18n: column positioning for "hg summary"
6413 # i18n: column positioning for "hg summary"
6412 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6414 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6413 label='log.changeset changeset.%s' % p.phasestr())
6415 label='log.changeset changeset.%s' % p.phasestr())
6414 ui.write(' '.join(p.tags()), label='log.tag')
6416 ui.write(' '.join(p.tags()), label='log.tag')
6415 if p.bookmarks():
6417 if p.bookmarks():
6416 marks.extend(p.bookmarks())
6418 marks.extend(p.bookmarks())
6417 if p.rev() == -1:
6419 if p.rev() == -1:
6418 if not len(repo):
6420 if not len(repo):
6419 ui.write(_(' (empty repository)'))
6421 ui.write(_(' (empty repository)'))
6420 else:
6422 else:
6421 ui.write(_(' (no revision checked out)'))
6423 ui.write(_(' (no revision checked out)'))
6422 ui.write('\n')
6424 ui.write('\n')
6423 if p.description():
6425 if p.description():
6424 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6426 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6425 label='log.summary')
6427 label='log.summary')
6426
6428
6427 branch = ctx.branch()
6429 branch = ctx.branch()
6428 bheads = repo.branchheads(branch)
6430 bheads = repo.branchheads(branch)
6429 # i18n: column positioning for "hg summary"
6431 # i18n: column positioning for "hg summary"
6430 m = _('branch: %s\n') % branch
6432 m = _('branch: %s\n') % branch
6431 if branch != 'default':
6433 if branch != 'default':
6432 ui.write(m, label='log.branch')
6434 ui.write(m, label='log.branch')
6433 else:
6435 else:
6434 ui.status(m, label='log.branch')
6436 ui.status(m, label='log.branch')
6435
6437
6436 if marks:
6438 if marks:
6437 active = repo._activebookmark
6439 active = repo._activebookmark
6438 # i18n: column positioning for "hg summary"
6440 # i18n: column positioning for "hg summary"
6439 ui.write(_('bookmarks:'), label='log.bookmark')
6441 ui.write(_('bookmarks:'), label='log.bookmark')
6440 if active is not None:
6442 if active is not None:
6441 if active in marks:
6443 if active in marks:
6442 ui.write(' *' + active, label=activebookmarklabel)
6444 ui.write(' *' + active, label=activebookmarklabel)
6443 marks.remove(active)
6445 marks.remove(active)
6444 else:
6446 else:
6445 ui.write(' [%s]' % active, label=activebookmarklabel)
6447 ui.write(' [%s]' % active, label=activebookmarklabel)
6446 for m in marks:
6448 for m in marks:
6447 ui.write(' ' + m, label='log.bookmark')
6449 ui.write(' ' + m, label='log.bookmark')
6448 ui.write('\n', label='log.bookmark')
6450 ui.write('\n', label='log.bookmark')
6449
6451
6450 status = repo.status(unknown=True)
6452 status = repo.status(unknown=True)
6451
6453
6452 c = repo.dirstate.copies()
6454 c = repo.dirstate.copies()
6453 copied, renamed = [], []
6455 copied, renamed = [], []
6454 for d, s in c.iteritems():
6456 for d, s in c.iteritems():
6455 if s in status.removed:
6457 if s in status.removed:
6456 status.removed.remove(s)
6458 status.removed.remove(s)
6457 renamed.append(d)
6459 renamed.append(d)
6458 else:
6460 else:
6459 copied.append(d)
6461 copied.append(d)
6460 if d in status.added:
6462 if d in status.added:
6461 status.added.remove(d)
6463 status.added.remove(d)
6462
6464
6463 try:
6465 try:
6464 ms = mergemod.mergestate.read(repo)
6466 ms = mergemod.mergestate.read(repo)
6465 except error.UnsupportedMergeRecords as e:
6467 except error.UnsupportedMergeRecords as e:
6466 s = ' '.join(e.recordtypes)
6468 s = ' '.join(e.recordtypes)
6467 ui.warn(
6469 ui.warn(
6468 _('warning: merge state has unsupported record types: %s\n') % s)
6470 _('warning: merge state has unsupported record types: %s\n') % s)
6469 unresolved = 0
6471 unresolved = 0
6470 else:
6472 else:
6471 unresolved = [f for f in ms if ms[f] == 'u']
6473 unresolved = [f for f in ms if ms[f] == 'u']
6472
6474
6473 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6475 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6474
6476
6475 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6477 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6476 (ui.label(_('%d added'), 'status.added'), status.added),
6478 (ui.label(_('%d added'), 'status.added'), status.added),
6477 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6479 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6478 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6480 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6479 (ui.label(_('%d copied'), 'status.copied'), copied),
6481 (ui.label(_('%d copied'), 'status.copied'), copied),
6480 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6482 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6481 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6483 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6482 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6484 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6483 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6485 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6484 t = []
6486 t = []
6485 for l, s in labels:
6487 for l, s in labels:
6486 if s:
6488 if s:
6487 t.append(l % len(s))
6489 t.append(l % len(s))
6488
6490
6489 t = ', '.join(t)
6491 t = ', '.join(t)
6490 cleanworkdir = False
6492 cleanworkdir = False
6491
6493
6492 if repo.vfs.exists('graftstate'):
6494 if repo.vfs.exists('graftstate'):
6493 t += _(' (graft in progress)')
6495 t += _(' (graft in progress)')
6494 if repo.vfs.exists('updatestate'):
6496 if repo.vfs.exists('updatestate'):
6495 t += _(' (interrupted update)')
6497 t += _(' (interrupted update)')
6496 elif len(parents) > 1:
6498 elif len(parents) > 1:
6497 t += _(' (merge)')
6499 t += _(' (merge)')
6498 elif branch != parents[0].branch():
6500 elif branch != parents[0].branch():
6499 t += _(' (new branch)')
6501 t += _(' (new branch)')
6500 elif (parents[0].closesbranch() and
6502 elif (parents[0].closesbranch() and
6501 pnode in repo.branchheads(branch, closed=True)):
6503 pnode in repo.branchheads(branch, closed=True)):
6502 t += _(' (head closed)')
6504 t += _(' (head closed)')
6503 elif not (status.modified or status.added or status.removed or renamed or
6505 elif not (status.modified or status.added or status.removed or renamed or
6504 copied or subs):
6506 copied or subs):
6505 t += _(' (clean)')
6507 t += _(' (clean)')
6506 cleanworkdir = True
6508 cleanworkdir = True
6507 elif pnode not in bheads:
6509 elif pnode not in bheads:
6508 t += _(' (new branch head)')
6510 t += _(' (new branch head)')
6509
6511
6510 if parents:
6512 if parents:
6511 pendingphase = max(p.phase() for p in parents)
6513 pendingphase = max(p.phase() for p in parents)
6512 else:
6514 else:
6513 pendingphase = phases.public
6515 pendingphase = phases.public
6514
6516
6515 if pendingphase > phases.newcommitphase(ui):
6517 if pendingphase > phases.newcommitphase(ui):
6516 t += ' (%s)' % phases.phasenames[pendingphase]
6518 t += ' (%s)' % phases.phasenames[pendingphase]
6517
6519
6518 if cleanworkdir:
6520 if cleanworkdir:
6519 # i18n: column positioning for "hg summary"
6521 # i18n: column positioning for "hg summary"
6520 ui.status(_('commit: %s\n') % t.strip())
6522 ui.status(_('commit: %s\n') % t.strip())
6521 else:
6523 else:
6522 # i18n: column positioning for "hg summary"
6524 # i18n: column positioning for "hg summary"
6523 ui.write(_('commit: %s\n') % t.strip())
6525 ui.write(_('commit: %s\n') % t.strip())
6524
6526
6525 # all ancestors of branch heads - all ancestors of parent = new csets
6527 # all ancestors of branch heads - all ancestors of parent = new csets
6526 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6528 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6527 bheads))
6529 bheads))
6528
6530
6529 if new == 0:
6531 if new == 0:
6530 # i18n: column positioning for "hg summary"
6532 # i18n: column positioning for "hg summary"
6531 ui.status(_('update: (current)\n'))
6533 ui.status(_('update: (current)\n'))
6532 elif pnode not in bheads:
6534 elif pnode not in bheads:
6533 # i18n: column positioning for "hg summary"
6535 # i18n: column positioning for "hg summary"
6534 ui.write(_('update: %d new changesets (update)\n') % new)
6536 ui.write(_('update: %d new changesets (update)\n') % new)
6535 else:
6537 else:
6536 # i18n: column positioning for "hg summary"
6538 # i18n: column positioning for "hg summary"
6537 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6539 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6538 (new, len(bheads)))
6540 (new, len(bheads)))
6539
6541
6540 t = []
6542 t = []
6541 draft = len(repo.revs('draft()'))
6543 draft = len(repo.revs('draft()'))
6542 if draft:
6544 if draft:
6543 t.append(_('%d draft') % draft)
6545 t.append(_('%d draft') % draft)
6544 secret = len(repo.revs('secret()'))
6546 secret = len(repo.revs('secret()'))
6545 if secret:
6547 if secret:
6546 t.append(_('%d secret') % secret)
6548 t.append(_('%d secret') % secret)
6547
6549
6548 if draft or secret:
6550 if draft or secret:
6549 ui.status(_('phases: %s\n') % ', '.join(t))
6551 ui.status(_('phases: %s\n') % ', '.join(t))
6550
6552
6551 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6553 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6552 for trouble in ("unstable", "divergent", "bumped"):
6554 for trouble in ("unstable", "divergent", "bumped"):
6553 numtrouble = len(repo.revs(trouble + "()"))
6555 numtrouble = len(repo.revs(trouble + "()"))
6554 # We write all the possibilities to ease translation
6556 # We write all the possibilities to ease translation
6555 troublemsg = {
6557 troublemsg = {
6556 "unstable": _("unstable: %d changesets"),
6558 "unstable": _("unstable: %d changesets"),
6557 "divergent": _("divergent: %d changesets"),
6559 "divergent": _("divergent: %d changesets"),
6558 "bumped": _("bumped: %d changesets"),
6560 "bumped": _("bumped: %d changesets"),
6559 }
6561 }
6560 if numtrouble > 0:
6562 if numtrouble > 0:
6561 ui.status(troublemsg[trouble] % numtrouble + "\n")
6563 ui.status(troublemsg[trouble] % numtrouble + "\n")
6562
6564
6563 cmdutil.summaryhooks(ui, repo)
6565 cmdutil.summaryhooks(ui, repo)
6564
6566
6565 if opts.get('remote'):
6567 if opts.get('remote'):
6566 needsincoming, needsoutgoing = True, True
6568 needsincoming, needsoutgoing = True, True
6567 else:
6569 else:
6568 needsincoming, needsoutgoing = False, False
6570 needsincoming, needsoutgoing = False, False
6569 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6571 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6570 if i:
6572 if i:
6571 needsincoming = True
6573 needsincoming = True
6572 if o:
6574 if o:
6573 needsoutgoing = True
6575 needsoutgoing = True
6574 if not needsincoming and not needsoutgoing:
6576 if not needsincoming and not needsoutgoing:
6575 return
6577 return
6576
6578
6577 def getincoming():
6579 def getincoming():
6578 source, branches = hg.parseurl(ui.expandpath('default'))
6580 source, branches = hg.parseurl(ui.expandpath('default'))
6579 sbranch = branches[0]
6581 sbranch = branches[0]
6580 try:
6582 try:
6581 other = hg.peer(repo, {}, source)
6583 other = hg.peer(repo, {}, source)
6582 except error.RepoError:
6584 except error.RepoError:
6583 if opts.get('remote'):
6585 if opts.get('remote'):
6584 raise
6586 raise
6585 return source, sbranch, None, None, None
6587 return source, sbranch, None, None, None
6586 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6588 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6587 if revs:
6589 if revs:
6588 revs = [other.lookup(rev) for rev in revs]
6590 revs = [other.lookup(rev) for rev in revs]
6589 ui.debug('comparing with %s\n' % util.hidepassword(source))
6591 ui.debug('comparing with %s\n' % util.hidepassword(source))
6590 repo.ui.pushbuffer()
6592 repo.ui.pushbuffer()
6591 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6593 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6592 repo.ui.popbuffer()
6594 repo.ui.popbuffer()
6593 return source, sbranch, other, commoninc, commoninc[1]
6595 return source, sbranch, other, commoninc, commoninc[1]
6594
6596
6595 if needsincoming:
6597 if needsincoming:
6596 source, sbranch, sother, commoninc, incoming = getincoming()
6598 source, sbranch, sother, commoninc, incoming = getincoming()
6597 else:
6599 else:
6598 source = sbranch = sother = commoninc = incoming = None
6600 source = sbranch = sother = commoninc = incoming = None
6599
6601
6600 def getoutgoing():
6602 def getoutgoing():
6601 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6603 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6602 dbranch = branches[0]
6604 dbranch = branches[0]
6603 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6605 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6604 if source != dest:
6606 if source != dest:
6605 try:
6607 try:
6606 dother = hg.peer(repo, {}, dest)
6608 dother = hg.peer(repo, {}, dest)
6607 except error.RepoError:
6609 except error.RepoError:
6608 if opts.get('remote'):
6610 if opts.get('remote'):
6609 raise
6611 raise
6610 return dest, dbranch, None, None
6612 return dest, dbranch, None, None
6611 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6613 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6612 elif sother is None:
6614 elif sother is None:
6613 # there is no explicit destination peer, but source one is invalid
6615 # there is no explicit destination peer, but source one is invalid
6614 return dest, dbranch, None, None
6616 return dest, dbranch, None, None
6615 else:
6617 else:
6616 dother = sother
6618 dother = sother
6617 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6619 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6618 common = None
6620 common = None
6619 else:
6621 else:
6620 common = commoninc
6622 common = commoninc
6621 if revs:
6623 if revs:
6622 revs = [repo.lookup(rev) for rev in revs]
6624 revs = [repo.lookup(rev) for rev in revs]
6623 repo.ui.pushbuffer()
6625 repo.ui.pushbuffer()
6624 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6626 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6625 commoninc=common)
6627 commoninc=common)
6626 repo.ui.popbuffer()
6628 repo.ui.popbuffer()
6627 return dest, dbranch, dother, outgoing
6629 return dest, dbranch, dother, outgoing
6628
6630
6629 if needsoutgoing:
6631 if needsoutgoing:
6630 dest, dbranch, dother, outgoing = getoutgoing()
6632 dest, dbranch, dother, outgoing = getoutgoing()
6631 else:
6633 else:
6632 dest = dbranch = dother = outgoing = None
6634 dest = dbranch = dother = outgoing = None
6633
6635
6634 if opts.get('remote'):
6636 if opts.get('remote'):
6635 t = []
6637 t = []
6636 if incoming:
6638 if incoming:
6637 t.append(_('1 or more incoming'))
6639 t.append(_('1 or more incoming'))
6638 o = outgoing.missing
6640 o = outgoing.missing
6639 if o:
6641 if o:
6640 t.append(_('%d outgoing') % len(o))
6642 t.append(_('%d outgoing') % len(o))
6641 other = dother or sother
6643 other = dother or sother
6642 if 'bookmarks' in other.listkeys('namespaces'):
6644 if 'bookmarks' in other.listkeys('namespaces'):
6643 counts = bookmarks.summary(repo, other)
6645 counts = bookmarks.summary(repo, other)
6644 if counts[0] > 0:
6646 if counts[0] > 0:
6645 t.append(_('%d incoming bookmarks') % counts[0])
6647 t.append(_('%d incoming bookmarks') % counts[0])
6646 if counts[1] > 0:
6648 if counts[1] > 0:
6647 t.append(_('%d outgoing bookmarks') % counts[1])
6649 t.append(_('%d outgoing bookmarks') % counts[1])
6648
6650
6649 if t:
6651 if t:
6650 # i18n: column positioning for "hg summary"
6652 # i18n: column positioning for "hg summary"
6651 ui.write(_('remote: %s\n') % (', '.join(t)))
6653 ui.write(_('remote: %s\n') % (', '.join(t)))
6652 else:
6654 else:
6653 # i18n: column positioning for "hg summary"
6655 # i18n: column positioning for "hg summary"
6654 ui.status(_('remote: (synced)\n'))
6656 ui.status(_('remote: (synced)\n'))
6655
6657
6656 cmdutil.summaryremotehooks(ui, repo, opts,
6658 cmdutil.summaryremotehooks(ui, repo, opts,
6657 ((source, sbranch, sother, commoninc),
6659 ((source, sbranch, sother, commoninc),
6658 (dest, dbranch, dother, outgoing)))
6660 (dest, dbranch, dother, outgoing)))
6659
6661
6660 @command('tag',
6662 @command('tag',
6661 [('f', 'force', None, _('force tag')),
6663 [('f', 'force', None, _('force tag')),
6662 ('l', 'local', None, _('make the tag local')),
6664 ('l', 'local', None, _('make the tag local')),
6663 ('r', 'rev', '', _('revision to tag'), _('REV')),
6665 ('r', 'rev', '', _('revision to tag'), _('REV')),
6664 ('', 'remove', None, _('remove a tag')),
6666 ('', 'remove', None, _('remove a tag')),
6665 # -l/--local is already there, commitopts cannot be used
6667 # -l/--local is already there, commitopts cannot be used
6666 ('e', 'edit', None, _('invoke editor on commit messages')),
6668 ('e', 'edit', None, _('invoke editor on commit messages')),
6667 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6669 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6668 ] + commitopts2,
6670 ] + commitopts2,
6669 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6671 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6670 def tag(ui, repo, name1, *names, **opts):
6672 def tag(ui, repo, name1, *names, **opts):
6671 """add one or more tags for the current or given revision
6673 """add one or more tags for the current or given revision
6672
6674
6673 Name a particular revision using <name>.
6675 Name a particular revision using <name>.
6674
6676
6675 Tags are used to name particular revisions of the repository and are
6677 Tags are used to name particular revisions of the repository and are
6676 very useful to compare different revisions, to go back to significant
6678 very useful to compare different revisions, to go back to significant
6677 earlier versions or to mark branch points as releases, etc. Changing
6679 earlier versions or to mark branch points as releases, etc. Changing
6678 an existing tag is normally disallowed; use -f/--force to override.
6680 an existing tag is normally disallowed; use -f/--force to override.
6679
6681
6680 If no revision is given, the parent of the working directory is
6682 If no revision is given, the parent of the working directory is
6681 used.
6683 used.
6682
6684
6683 To facilitate version control, distribution, and merging of tags,
6685 To facilitate version control, distribution, and merging of tags,
6684 they are stored as a file named ".hgtags" which is managed similarly
6686 they are stored as a file named ".hgtags" which is managed similarly
6685 to other project files and can be hand-edited if necessary. This
6687 to other project files and can be hand-edited if necessary. This
6686 also means that tagging creates a new commit. The file
6688 also means that tagging creates a new commit. The file
6687 ".hg/localtags" is used for local tags (not shared among
6689 ".hg/localtags" is used for local tags (not shared among
6688 repositories).
6690 repositories).
6689
6691
6690 Tag commits are usually made at the head of a branch. If the parent
6692 Tag commits are usually made at the head of a branch. If the parent
6691 of the working directory is not a branch head, :hg:`tag` aborts; use
6693 of the working directory is not a branch head, :hg:`tag` aborts; use
6692 -f/--force to force the tag commit to be based on a non-head
6694 -f/--force to force the tag commit to be based on a non-head
6693 changeset.
6695 changeset.
6694
6696
6695 See :hg:`help dates` for a list of formats valid for -d/--date.
6697 See :hg:`help dates` for a list of formats valid for -d/--date.
6696
6698
6697 Since tag names have priority over branch names during revision
6699 Since tag names have priority over branch names during revision
6698 lookup, using an existing branch name as a tag name is discouraged.
6700 lookup, using an existing branch name as a tag name is discouraged.
6699
6701
6700 Returns 0 on success.
6702 Returns 0 on success.
6701 """
6703 """
6702 wlock = lock = None
6704 wlock = lock = None
6703 try:
6705 try:
6704 wlock = repo.wlock()
6706 wlock = repo.wlock()
6705 lock = repo.lock()
6707 lock = repo.lock()
6706 rev_ = "."
6708 rev_ = "."
6707 names = [t.strip() for t in (name1,) + names]
6709 names = [t.strip() for t in (name1,) + names]
6708 if len(names) != len(set(names)):
6710 if len(names) != len(set(names)):
6709 raise error.Abort(_('tag names must be unique'))
6711 raise error.Abort(_('tag names must be unique'))
6710 for n in names:
6712 for n in names:
6711 scmutil.checknewlabel(repo, n, 'tag')
6713 scmutil.checknewlabel(repo, n, 'tag')
6712 if not n:
6714 if not n:
6713 raise error.Abort(_('tag names cannot consist entirely of '
6715 raise error.Abort(_('tag names cannot consist entirely of '
6714 'whitespace'))
6716 'whitespace'))
6715 if opts.get('rev') and opts.get('remove'):
6717 if opts.get('rev') and opts.get('remove'):
6716 raise error.Abort(_("--rev and --remove are incompatible"))
6718 raise error.Abort(_("--rev and --remove are incompatible"))
6717 if opts.get('rev'):
6719 if opts.get('rev'):
6718 rev_ = opts['rev']
6720 rev_ = opts['rev']
6719 message = opts.get('message')
6721 message = opts.get('message')
6720 if opts.get('remove'):
6722 if opts.get('remove'):
6721 if opts.get('local'):
6723 if opts.get('local'):
6722 expectedtype = 'local'
6724 expectedtype = 'local'
6723 else:
6725 else:
6724 expectedtype = 'global'
6726 expectedtype = 'global'
6725
6727
6726 for n in names:
6728 for n in names:
6727 if not repo.tagtype(n):
6729 if not repo.tagtype(n):
6728 raise error.Abort(_("tag '%s' does not exist") % n)
6730 raise error.Abort(_("tag '%s' does not exist") % n)
6729 if repo.tagtype(n) != expectedtype:
6731 if repo.tagtype(n) != expectedtype:
6730 if expectedtype == 'global':
6732 if expectedtype == 'global':
6731 raise error.Abort(_("tag '%s' is not a global tag") % n)
6733 raise error.Abort(_("tag '%s' is not a global tag") % n)
6732 else:
6734 else:
6733 raise error.Abort(_("tag '%s' is not a local tag") % n)
6735 raise error.Abort(_("tag '%s' is not a local tag") % n)
6734 rev_ = 'null'
6736 rev_ = 'null'
6735 if not message:
6737 if not message:
6736 # we don't translate commit messages
6738 # we don't translate commit messages
6737 message = 'Removed tag %s' % ', '.join(names)
6739 message = 'Removed tag %s' % ', '.join(names)
6738 elif not opts.get('force'):
6740 elif not opts.get('force'):
6739 for n in names:
6741 for n in names:
6740 if n in repo.tags():
6742 if n in repo.tags():
6741 raise error.Abort(_("tag '%s' already exists "
6743 raise error.Abort(_("tag '%s' already exists "
6742 "(use -f to force)") % n)
6744 "(use -f to force)") % n)
6743 if not opts.get('local'):
6745 if not opts.get('local'):
6744 p1, p2 = repo.dirstate.parents()
6746 p1, p2 = repo.dirstate.parents()
6745 if p2 != nullid:
6747 if p2 != nullid:
6746 raise error.Abort(_('uncommitted merge'))
6748 raise error.Abort(_('uncommitted merge'))
6747 bheads = repo.branchheads()
6749 bheads = repo.branchheads()
6748 if not opts.get('force') and bheads and p1 not in bheads:
6750 if not opts.get('force') and bheads and p1 not in bheads:
6749 raise error.Abort(_('not at a branch head (use -f to force)'))
6751 raise error.Abort(_('not at a branch head (use -f to force)'))
6750 r = scmutil.revsingle(repo, rev_).node()
6752 r = scmutil.revsingle(repo, rev_).node()
6751
6753
6752 if not message:
6754 if not message:
6753 # we don't translate commit messages
6755 # we don't translate commit messages
6754 message = ('Added tag %s for changeset %s' %
6756 message = ('Added tag %s for changeset %s' %
6755 (', '.join(names), short(r)))
6757 (', '.join(names), short(r)))
6756
6758
6757 date = opts.get('date')
6759 date = opts.get('date')
6758 if date:
6760 if date:
6759 date = util.parsedate(date)
6761 date = util.parsedate(date)
6760
6762
6761 if opts.get('remove'):
6763 if opts.get('remove'):
6762 editform = 'tag.remove'
6764 editform = 'tag.remove'
6763 else:
6765 else:
6764 editform = 'tag.add'
6766 editform = 'tag.add'
6765 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6767 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6766
6768
6767 # don't allow tagging the null rev
6769 # don't allow tagging the null rev
6768 if (not opts.get('remove') and
6770 if (not opts.get('remove') and
6769 scmutil.revsingle(repo, rev_).rev() == nullrev):
6771 scmutil.revsingle(repo, rev_).rev() == nullrev):
6770 raise error.Abort(_("cannot tag null revision"))
6772 raise error.Abort(_("cannot tag null revision"))
6771
6773
6772 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6774 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6773 editor=editor)
6775 editor=editor)
6774 finally:
6776 finally:
6775 release(lock, wlock)
6777 release(lock, wlock)
6776
6778
6777 @command('tags', formatteropts, '')
6779 @command('tags', formatteropts, '')
6778 def tags(ui, repo, **opts):
6780 def tags(ui, repo, **opts):
6779 """list repository tags
6781 """list repository tags
6780
6782
6781 This lists both regular and local tags. When the -v/--verbose
6783 This lists both regular and local tags. When the -v/--verbose
6782 switch is used, a third column "local" is printed for local tags.
6784 switch is used, a third column "local" is printed for local tags.
6783 When the -q/--quiet switch is used, only the tag name is printed.
6785 When the -q/--quiet switch is used, only the tag name is printed.
6784
6786
6785 Returns 0 on success.
6787 Returns 0 on success.
6786 """
6788 """
6787
6789
6788 fm = ui.formatter('tags', opts)
6790 fm = ui.formatter('tags', opts)
6789 hexfunc = fm.hexfunc
6791 hexfunc = fm.hexfunc
6790 tagtype = ""
6792 tagtype = ""
6791
6793
6792 for t, n in reversed(repo.tagslist()):
6794 for t, n in reversed(repo.tagslist()):
6793 hn = hexfunc(n)
6795 hn = hexfunc(n)
6794 label = 'tags.normal'
6796 label = 'tags.normal'
6795 tagtype = ''
6797 tagtype = ''
6796 if repo.tagtype(t) == 'local':
6798 if repo.tagtype(t) == 'local':
6797 label = 'tags.local'
6799 label = 'tags.local'
6798 tagtype = 'local'
6800 tagtype = 'local'
6799
6801
6800 fm.startitem()
6802 fm.startitem()
6801 fm.write('tag', '%s', t, label=label)
6803 fm.write('tag', '%s', t, label=label)
6802 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6804 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6803 fm.condwrite(not ui.quiet, 'rev node', fmt,
6805 fm.condwrite(not ui.quiet, 'rev node', fmt,
6804 repo.changelog.rev(n), hn, label=label)
6806 repo.changelog.rev(n), hn, label=label)
6805 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6807 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6806 tagtype, label=label)
6808 tagtype, label=label)
6807 fm.plain('\n')
6809 fm.plain('\n')
6808 fm.end()
6810 fm.end()
6809
6811
6810 @command('tip',
6812 @command('tip',
6811 [('p', 'patch', None, _('show patch')),
6813 [('p', 'patch', None, _('show patch')),
6812 ('g', 'git', None, _('use git extended diff format')),
6814 ('g', 'git', None, _('use git extended diff format')),
6813 ] + templateopts,
6815 ] + templateopts,
6814 _('[-p] [-g]'))
6816 _('[-p] [-g]'))
6815 def tip(ui, repo, **opts):
6817 def tip(ui, repo, **opts):
6816 """show the tip revision (DEPRECATED)
6818 """show the tip revision (DEPRECATED)
6817
6819
6818 The tip revision (usually just called the tip) is the changeset
6820 The tip revision (usually just called the tip) is the changeset
6819 most recently added to the repository (and therefore the most
6821 most recently added to the repository (and therefore the most
6820 recently changed head).
6822 recently changed head).
6821
6823
6822 If you have just made a commit, that commit will be the tip. If
6824 If you have just made a commit, that commit will be the tip. If
6823 you have just pulled changes from another repository, the tip of
6825 you have just pulled changes from another repository, the tip of
6824 that repository becomes the current tip. The "tip" tag is special
6826 that repository becomes the current tip. The "tip" tag is special
6825 and cannot be renamed or assigned to a different changeset.
6827 and cannot be renamed or assigned to a different changeset.
6826
6828
6827 This command is deprecated, please use :hg:`heads` instead.
6829 This command is deprecated, please use :hg:`heads` instead.
6828
6830
6829 Returns 0 on success.
6831 Returns 0 on success.
6830 """
6832 """
6831 displayer = cmdutil.show_changeset(ui, repo, opts)
6833 displayer = cmdutil.show_changeset(ui, repo, opts)
6832 displayer.show(repo['tip'])
6834 displayer.show(repo['tip'])
6833 displayer.close()
6835 displayer.close()
6834
6836
6835 @command('unbundle',
6837 @command('unbundle',
6836 [('u', 'update', None,
6838 [('u', 'update', None,
6837 _('update to new branch head if changesets were unbundled'))],
6839 _('update to new branch head if changesets were unbundled'))],
6838 _('[-u] FILE...'))
6840 _('[-u] FILE...'))
6839 def unbundle(ui, repo, fname1, *fnames, **opts):
6841 def unbundle(ui, repo, fname1, *fnames, **opts):
6840 """apply one or more changegroup files
6842 """apply one or more changegroup files
6841
6843
6842 Apply one or more compressed changegroup files generated by the
6844 Apply one or more compressed changegroup files generated by the
6843 bundle command.
6845 bundle command.
6844
6846
6845 Returns 0 on success, 1 if an update has unresolved files.
6847 Returns 0 on success, 1 if an update has unresolved files.
6846 """
6848 """
6847 fnames = (fname1,) + fnames
6849 fnames = (fname1,) + fnames
6848
6850
6849 with repo.lock():
6851 with repo.lock():
6850 for fname in fnames:
6852 for fname in fnames:
6851 f = hg.openpath(ui, fname)
6853 f = hg.openpath(ui, fname)
6852 gen = exchange.readbundle(ui, f, fname)
6854 gen = exchange.readbundle(ui, f, fname)
6853 if isinstance(gen, bundle2.unbundle20):
6855 if isinstance(gen, bundle2.unbundle20):
6854 tr = repo.transaction('unbundle')
6856 tr = repo.transaction('unbundle')
6855 try:
6857 try:
6856 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6858 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6857 url='bundle:' + fname)
6859 url='bundle:' + fname)
6858 tr.close()
6860 tr.close()
6859 except error.BundleUnknownFeatureError as exc:
6861 except error.BundleUnknownFeatureError as exc:
6860 raise error.Abort(_('%s: unknown bundle feature, %s')
6862 raise error.Abort(_('%s: unknown bundle feature, %s')
6861 % (fname, exc),
6863 % (fname, exc),
6862 hint=_("see https://mercurial-scm.org/"
6864 hint=_("see https://mercurial-scm.org/"
6863 "wiki/BundleFeature for more "
6865 "wiki/BundleFeature for more "
6864 "information"))
6866 "information"))
6865 finally:
6867 finally:
6866 if tr:
6868 if tr:
6867 tr.release()
6869 tr.release()
6868 changes = [r.get('return', 0)
6870 changes = [r.get('return', 0)
6869 for r in op.records['changegroup']]
6871 for r in op.records['changegroup']]
6870 modheads = changegroup.combineresults(changes)
6872 modheads = changegroup.combineresults(changes)
6871 elif isinstance(gen, streamclone.streamcloneapplier):
6873 elif isinstance(gen, streamclone.streamcloneapplier):
6872 raise error.Abort(
6874 raise error.Abort(
6873 _('packed bundles cannot be applied with '
6875 _('packed bundles cannot be applied with '
6874 '"hg unbundle"'),
6876 '"hg unbundle"'),
6875 hint=_('use "hg debugapplystreamclonebundle"'))
6877 hint=_('use "hg debugapplystreamclonebundle"'))
6876 else:
6878 else:
6877 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6879 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6878
6880
6879 return postincoming(ui, repo, modheads, opts.get('update'), None)
6881 return postincoming(ui, repo, modheads, opts.get('update'), None)
6880
6882
6881 @command('^update|up|checkout|co',
6883 @command('^update|up|checkout|co',
6882 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6884 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6883 ('c', 'check', None,
6885 ('c', 'check', None,
6884 _('update across branches if no uncommitted changes')),
6886 _('update across branches if no uncommitted changes')),
6885 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6887 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6886 ('r', 'rev', '', _('revision'), _('REV'))
6888 ('r', 'rev', '', _('revision'), _('REV'))
6887 ] + mergetoolopts,
6889 ] + mergetoolopts,
6888 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6890 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6889 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6891 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6890 tool=None):
6892 tool=None):
6891 """update working directory (or switch revisions)
6893 """update working directory (or switch revisions)
6892
6894
6893 Update the repository's working directory to the specified
6895 Update the repository's working directory to the specified
6894 changeset. If no changeset is specified, update to the tip of the
6896 changeset. If no changeset is specified, update to the tip of the
6895 current named branch and move the active bookmark (see :hg:`help
6897 current named branch and move the active bookmark (see :hg:`help
6896 bookmarks`).
6898 bookmarks`).
6897
6899
6898 Update sets the working directory's parent revision to the specified
6900 Update sets the working directory's parent revision to the specified
6899 changeset (see :hg:`help parents`).
6901 changeset (see :hg:`help parents`).
6900
6902
6901 If the changeset is not a descendant or ancestor of the working
6903 If the changeset is not a descendant or ancestor of the working
6902 directory's parent, the update is aborted. With the -c/--check
6904 directory's parent, the update is aborted. With the -c/--check
6903 option, the working directory is checked for uncommitted changes; if
6905 option, the working directory is checked for uncommitted changes; if
6904 none are found, the working directory is updated to the specified
6906 none are found, the working directory is updated to the specified
6905 changeset.
6907 changeset.
6906
6908
6907 .. container:: verbose
6909 .. container:: verbose
6908
6910
6909 The following rules apply when the working directory contains
6911 The following rules apply when the working directory contains
6910 uncommitted changes:
6912 uncommitted changes:
6911
6913
6912 1. If neither -c/--check nor -C/--clean is specified, and if
6914 1. If neither -c/--check nor -C/--clean is specified, and if
6913 the requested changeset is an ancestor or descendant of
6915 the requested changeset is an ancestor or descendant of
6914 the working directory's parent, the uncommitted changes
6916 the working directory's parent, the uncommitted changes
6915 are merged into the requested changeset and the merged
6917 are merged into the requested changeset and the merged
6916 result is left uncommitted. If the requested changeset is
6918 result is left uncommitted. If the requested changeset is
6917 not an ancestor or descendant (that is, it is on another
6919 not an ancestor or descendant (that is, it is on another
6918 branch), the update is aborted and the uncommitted changes
6920 branch), the update is aborted and the uncommitted changes
6919 are preserved.
6921 are preserved.
6920
6922
6921 2. With the -c/--check option, the update is aborted and the
6923 2. With the -c/--check option, the update is aborted and the
6922 uncommitted changes are preserved.
6924 uncommitted changes are preserved.
6923
6925
6924 3. With the -C/--clean option, uncommitted changes are discarded and
6926 3. With the -C/--clean option, uncommitted changes are discarded and
6925 the working directory is updated to the requested changeset.
6927 the working directory is updated to the requested changeset.
6926
6928
6927 To cancel an uncommitted merge (and lose your changes), use
6929 To cancel an uncommitted merge (and lose your changes), use
6928 :hg:`update --clean .`.
6930 :hg:`update --clean .`.
6929
6931
6930 Use null as the changeset to remove the working directory (like
6932 Use null as the changeset to remove the working directory (like
6931 :hg:`clone -U`).
6933 :hg:`clone -U`).
6932
6934
6933 If you want to revert just one file to an older revision, use
6935 If you want to revert just one file to an older revision, use
6934 :hg:`revert [-r REV] NAME`.
6936 :hg:`revert [-r REV] NAME`.
6935
6937
6936 See :hg:`help dates` for a list of formats valid for -d/--date.
6938 See :hg:`help dates` for a list of formats valid for -d/--date.
6937
6939
6938 Returns 0 on success, 1 if there are unresolved files.
6940 Returns 0 on success, 1 if there are unresolved files.
6939 """
6941 """
6940 movemarkfrom = None
6942 movemarkfrom = None
6941 if rev and node:
6943 if rev and node:
6942 raise error.Abort(_("please specify just one revision"))
6944 raise error.Abort(_("please specify just one revision"))
6943
6945
6944 if rev is None or rev == '':
6946 if rev is None or rev == '':
6945 rev = node
6947 rev = node
6946
6948
6947 with repo.wlock():
6949 with repo.wlock():
6948 cmdutil.clearunfinished(repo)
6950 cmdutil.clearunfinished(repo)
6949
6951
6950 if date:
6952 if date:
6951 if rev is not None:
6953 if rev is not None:
6952 raise error.Abort(_("you can't specify a revision and a date"))
6954 raise error.Abort(_("you can't specify a revision and a date"))
6953 rev = cmdutil.finddate(ui, repo, date)
6955 rev = cmdutil.finddate(ui, repo, date)
6954
6956
6955 # if we defined a bookmark, we have to remember the original name
6957 # if we defined a bookmark, we have to remember the original name
6956 brev = rev
6958 brev = rev
6957 rev = scmutil.revsingle(repo, rev, rev).rev()
6959 rev = scmutil.revsingle(repo, rev, rev).rev()
6958
6960
6959 if check and clean:
6961 if check and clean:
6960 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6962 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6961 )
6963 )
6962
6964
6963 if check:
6965 if check:
6964 cmdutil.bailifchanged(repo, merge=False)
6966 cmdutil.bailifchanged(repo, merge=False)
6965 if rev is None:
6967 if rev is None:
6966 updata = destutil.destupdate(repo, clean=clean, check=check)
6968 updata = destutil.destupdate(repo, clean=clean, check=check)
6967 rev, movemarkfrom, brev = updata
6969 rev, movemarkfrom, brev = updata
6968
6970
6969 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6971 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6970
6972
6971 if clean:
6973 if clean:
6972 ret = hg.clean(repo, rev)
6974 ret = hg.clean(repo, rev)
6973 else:
6975 else:
6974 ret = hg.update(repo, rev)
6976 ret = hg.update(repo, rev)
6975
6977
6976 if not ret and movemarkfrom:
6978 if not ret and movemarkfrom:
6977 if movemarkfrom == repo['.'].node():
6979 if movemarkfrom == repo['.'].node():
6978 pass # no-op update
6980 pass # no-op update
6979 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6981 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6980 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6982 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6981 else:
6983 else:
6982 # this can happen with a non-linear update
6984 # this can happen with a non-linear update
6983 ui.status(_("(leaving bookmark %s)\n") %
6985 ui.status(_("(leaving bookmark %s)\n") %
6984 repo._activebookmark)
6986 repo._activebookmark)
6985 bookmarks.deactivate(repo)
6987 bookmarks.deactivate(repo)
6986 elif brev in repo._bookmarks:
6988 elif brev in repo._bookmarks:
6987 bookmarks.activate(repo, brev)
6989 bookmarks.activate(repo, brev)
6988 ui.status(_("(activating bookmark %s)\n") % brev)
6990 ui.status(_("(activating bookmark %s)\n") % brev)
6989 elif brev:
6991 elif brev:
6990 if repo._activebookmark:
6992 if repo._activebookmark:
6991 ui.status(_("(leaving bookmark %s)\n") %
6993 ui.status(_("(leaving bookmark %s)\n") %
6992 repo._activebookmark)
6994 repo._activebookmark)
6993 bookmarks.deactivate(repo)
6995 bookmarks.deactivate(repo)
6994
6996
6995 return ret
6997 return ret
6996
6998
6997 @command('verify', [])
6999 @command('verify', [])
6998 def verify(ui, repo):
7000 def verify(ui, repo):
6999 """verify the integrity of the repository
7001 """verify the integrity of the repository
7000
7002
7001 Verify the integrity of the current repository.
7003 Verify the integrity of the current repository.
7002
7004
7003 This will perform an extensive check of the repository's
7005 This will perform an extensive check of the repository's
7004 integrity, validating the hashes and checksums of each entry in
7006 integrity, validating the hashes and checksums of each entry in
7005 the changelog, manifest, and tracked files, as well as the
7007 the changelog, manifest, and tracked files, as well as the
7006 integrity of their crosslinks and indices.
7008 integrity of their crosslinks and indices.
7007
7009
7008 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7010 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7009 for more information about recovery from corruption of the
7011 for more information about recovery from corruption of the
7010 repository.
7012 repository.
7011
7013
7012 Returns 0 on success, 1 if errors are encountered.
7014 Returns 0 on success, 1 if errors are encountered.
7013 """
7015 """
7014 return hg.verify(repo)
7016 return hg.verify(repo)
7015
7017
7016 @command('version', [], norepo=True)
7018 @command('version', [], norepo=True)
7017 def version_(ui):
7019 def version_(ui):
7018 """output version and copyright information"""
7020 """output version and copyright information"""
7019 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7021 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7020 % util.version())
7022 % util.version())
7021 ui.status(_(
7023 ui.status(_(
7022 "(see https://mercurial-scm.org for more information)\n"
7024 "(see https://mercurial-scm.org for more information)\n"
7023 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7025 "\nCopyright (C) 2005-2016 Matt Mackall and others\n"
7024 "This is free software; see the source for copying conditions. "
7026 "This is free software; see the source for copying conditions. "
7025 "There is NO\nwarranty; "
7027 "There is NO\nwarranty; "
7026 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7028 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7027 ))
7029 ))
7028
7030
7029 ui.note(_("\nEnabled extensions:\n\n"))
7031 ui.note(_("\nEnabled extensions:\n\n"))
7030 if ui.verbose:
7032 if ui.verbose:
7031 # format names and versions into columns
7033 # format names and versions into columns
7032 names = []
7034 names = []
7033 vers = []
7035 vers = []
7034 for name, module in extensions.extensions():
7036 for name, module in extensions.extensions():
7035 names.append(name)
7037 names.append(name)
7036 vers.append(extensions.moduleversion(module))
7038 vers.append(extensions.moduleversion(module))
7037 if names:
7039 if names:
7038 maxnamelen = max(len(n) for n in names)
7040 maxnamelen = max(len(n) for n in names)
7039 for i, name in enumerate(names):
7041 for i, name in enumerate(names):
7040 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7042 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,755 +1,762 b''
1 $ hg init basic
1 $ hg init basic
2 $ cd basic
2 $ cd basic
3
3
4 should complain
4 should complain
5
5
6 $ hg backout
6 $ hg backout
7 abort: please specify a revision to backout
7 abort: please specify a revision to backout
8 [255]
8 [255]
9 $ hg backout -r 0 0
9 $ hg backout -r 0 0
10 abort: please specify just one revision
10 abort: please specify just one revision
11 [255]
11 [255]
12
12
13 basic operation
13 basic operation
14 (this also tests that editor is invoked if the commit message is not
14 (this also tests that editor is invoked if the commit message is not
15 specified explicitly)
15 specified explicitly)
16
16
17 $ echo a > a
17 $ echo a > a
18 $ hg commit -d '0 0' -A -m a
18 $ hg commit -d '0 0' -A -m a
19 adding a
19 adding a
20 $ echo b >> a
20 $ echo b >> a
21 $ hg commit -d '1 0' -m b
21 $ hg commit -d '1 0' -m b
22
22
23 $ hg status --rev tip --rev "tip^1"
23 $ hg status --rev tip --rev "tip^1"
24 M a
24 M a
25 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true
25 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true
26 reverting a
26 reverting a
27 Backed out changeset a820f4f40a57
27 Backed out changeset a820f4f40a57
28
28
29
29
30 HG: Enter commit message. Lines beginning with 'HG:' are removed.
30 HG: Enter commit message. Lines beginning with 'HG:' are removed.
31 HG: Leave message empty to abort commit.
31 HG: Leave message empty to abort commit.
32 HG: --
32 HG: --
33 HG: user: test
33 HG: user: test
34 HG: branch 'default'
34 HG: branch 'default'
35 HG: changed a
35 HG: changed a
36 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
36 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
37 $ cat a
37 $ cat a
38 a
38 a
39 $ hg summary
39 $ hg summary
40 parent: 2:2929462c3dff tip
40 parent: 2:2929462c3dff tip
41 Backed out changeset a820f4f40a57
41 Backed out changeset a820f4f40a57
42 branch: default
42 branch: default
43 commit: (clean)
43 commit: (clean)
44 update: (current)
44 update: (current)
45 phases: 3 draft
45 phases: 3 draft
46
46
47 commit option
47 commit option
48
48
49 $ cd ..
49 $ cd ..
50 $ hg init commit
50 $ hg init commit
51 $ cd commit
51 $ cd commit
52
52
53 $ echo tomatoes > a
53 $ echo tomatoes > a
54 $ hg add a
54 $ hg add a
55 $ hg commit -d '0 0' -m tomatoes
55 $ hg commit -d '0 0' -m tomatoes
56
56
57 $ echo chair > b
57 $ echo chair > b
58 $ hg add b
58 $ hg add b
59 $ hg commit -d '1 0' -m chair
59 $ hg commit -d '1 0' -m chair
60
60
61 $ echo grapes >> a
61 $ echo grapes >> a
62 $ hg commit -d '2 0' -m grapes
62 $ hg commit -d '2 0' -m grapes
63
63
64 $ hg backout -d '4 0' 1 --tool=:fail
64 $ hg backout -d '4 0' 1 --tool=:fail
65 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
65 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
66 changeset 3:1c2161e97c0a backs out changeset 1:22cb4f70d813
66 changeset 3:1c2161e97c0a backs out changeset 1:22cb4f70d813
67 $ hg summary
67 $ hg summary
68 parent: 3:1c2161e97c0a tip
68 parent: 3:1c2161e97c0a tip
69 Backed out changeset 22cb4f70d813
69 Backed out changeset 22cb4f70d813
70 branch: default
70 branch: default
71 commit: (clean)
71 commit: (clean)
72 update: (current)
72 update: (current)
73 phases: 4 draft
73 phases: 4 draft
74
74
75 $ echo ypples > a
75 $ echo ypples > a
76 $ hg commit -d '5 0' -m ypples
76 $ hg commit -d '5 0' -m ypples
77
77
78 $ hg backout -d '6 0' 2 --tool=:fail
78 $ hg backout -d '6 0' 2 --tool=:fail
79 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
79 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
80 use 'hg resolve' to retry unresolved file merges
80 use 'hg resolve' to retry unresolved file merges
81 [1]
81 [1]
82 $ hg summary
82 $ hg summary
83 parent: 4:ed99997b793d tip
83 parent: 4:ed99997b793d tip
84 ypples
84 ypples
85 branch: default
85 branch: default
86 commit: 1 unresolved (clean)
86 commit: 1 unresolved (clean)
87 update: (current)
87 update: (current)
88 phases: 5 draft
88 phases: 5 draft
89
89
90 file that was removed is recreated
90 file that was removed is recreated
91 (this also tests that editor is not invoked if the commit message is
91 (this also tests that editor is not invoked if the commit message is
92 specified explicitly)
92 specified explicitly)
93
93
94 $ cd ..
94 $ cd ..
95 $ hg init remove
95 $ hg init remove
96 $ cd remove
96 $ cd remove
97
97
98 $ echo content > a
98 $ echo content > a
99 $ hg commit -d '0 0' -A -m a
99 $ hg commit -d '0 0' -A -m a
100 adding a
100 adding a
101
101
102 $ hg rm a
102 $ hg rm a
103 $ hg commit -d '1 0' -m b
103 $ hg commit -d '1 0' -m b
104
104
105 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true -m "Backed out changeset 76862dcce372"
105 $ HGEDITOR=cat hg backout -d '2 0' tip --tool=true -m "Backed out changeset 76862dcce372"
106 adding a
106 adding a
107 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
107 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
108 $ cat a
108 $ cat a
109 content
109 content
110 $ hg summary
110 $ hg summary
111 parent: 2:de31bdc76c0d tip
111 parent: 2:de31bdc76c0d tip
112 Backed out changeset 76862dcce372
112 Backed out changeset 76862dcce372
113 branch: default
113 branch: default
114 commit: (clean)
114 commit: (clean)
115 update: (current)
115 update: (current)
116 phases: 3 draft
116 phases: 3 draft
117
117
118 backout of backout is as if nothing happened
118 backout of backout is as if nothing happened
119
119
120 $ hg backout -d '3 0' --merge tip --tool=true
120 $ hg backout -d '3 0' --merge tip --tool=true
121 removing a
121 removing a
122 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
122 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
123 $ test -f a
123 $ test -f a
124 [1]
124 [1]
125 $ hg summary
125 $ hg summary
126 parent: 3:7f6d0f120113 tip
126 parent: 3:7f6d0f120113 tip
127 Backed out changeset de31bdc76c0d
127 Backed out changeset de31bdc76c0d
128 branch: default
128 branch: default
129 commit: (clean)
129 commit: (clean)
130 update: (current)
130 update: (current)
131 phases: 4 draft
131 phases: 4 draft
132
132
133 Test that 'hg rollback' restores dirstate just before opening
133 Test that 'hg rollback' restores dirstate just before opening
134 transaction: in-memory dirstate changes should be written into
134 transaction: in-memory dirstate changes should be written into
135 '.hg/journal.dirstate' as expected.
135 '.hg/journal.dirstate' as expected.
136
136
137 $ echo 'removed soon' > b
137 $ echo 'removed soon' > b
138 $ hg commit -A -d '4 0' -m 'prepare for subsequent removing'
138 $ hg commit -A -d '4 0' -m 'prepare for subsequent removing'
139 adding b
139 adding b
140 $ echo 'newly added' > c
140 $ echo 'newly added' > c
141 $ hg add c
141 $ hg add c
142 $ hg remove b
142 $ hg remove b
143 $ hg commit -d '5 0' -m 'prepare for subsequent backout'
143 $ hg commit -d '5 0' -m 'prepare for subsequent backout'
144 $ touch -t 200001010000 c
144 $ touch -t 200001010000 c
145 $ hg status -A
145 $ hg status -A
146 C c
146 C c
147 $ hg debugstate --nodates
147 $ hg debugstate --nodates
148 n 644 12 set c
148 n 644 12 set c
149 $ hg backout -d '6 0' -m 'to be rollback-ed soon' -r .
149 $ hg backout -d '6 0' -m 'to be rollback-ed soon' -r .
150 adding b
150 adding b
151 removing c
151 removing c
152 changeset 6:4bfec048029d backs out changeset 5:fac0b729a654
152 changeset 6:4bfec048029d backs out changeset 5:fac0b729a654
153 $ hg rollback -q
153 $ hg rollback -q
154 $ hg status -A
154 $ hg status -A
155 A b
155 A b
156 R c
156 R c
157 $ hg debugstate --nodates
157 $ hg debugstate --nodates
158 a 0 -1 unset b
158 a 0 -1 unset b
159 r 0 0 set c
159 r 0 0 set c
160
160
161 across branch
161 across branch
162
162
163 $ cd ..
163 $ cd ..
164 $ hg init branch
164 $ hg init branch
165 $ cd branch
165 $ cd branch
166 $ echo a > a
166 $ echo a > a
167 $ hg ci -Am0
167 $ hg ci -Am0
168 adding a
168 adding a
169 $ echo b > b
169 $ echo b > b
170 $ hg ci -Am1
170 $ hg ci -Am1
171 adding b
171 adding b
172 $ hg co -C 0
172 $ hg co -C 0
173 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
173 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
174 $ hg summary
174 $ hg summary
175 parent: 0:f7b1eb17ad24
175 parent: 0:f7b1eb17ad24
176 0
176 0
177 branch: default
177 branch: default
178 commit: (clean)
178 commit: (clean)
179 update: 1 new changesets (update)
179 update: 1 new changesets (update)
180 phases: 2 draft
180 phases: 2 draft
181
181
182 should fail
182 should fail
183
183
184 $ hg backout 1
184 $ hg backout 1
185 abort: cannot backout change that is not an ancestor
185 abort: cannot backout change that is not an ancestor
186 [255]
186 [255]
187 $ echo c > c
187 $ echo c > c
188 $ hg ci -Am2
188 $ hg ci -Am2
189 adding c
189 adding c
190 created new head
190 created new head
191 $ hg summary
191 $ hg summary
192 parent: 2:db815d6d32e6 tip
192 parent: 2:db815d6d32e6 tip
193 2
193 2
194 branch: default
194 branch: default
195 commit: (clean)
195 commit: (clean)
196 update: 1 new changesets, 2 branch heads (merge)
196 update: 1 new changesets, 2 branch heads (merge)
197 phases: 3 draft
197 phases: 3 draft
198
198
199 should fail
199 should fail
200
200
201 $ hg backout 1
201 $ hg backout 1
202 abort: cannot backout change that is not an ancestor
202 abort: cannot backout change that is not an ancestor
203 [255]
203 [255]
204 $ hg summary
204 $ hg summary
205 parent: 2:db815d6d32e6 tip
205 parent: 2:db815d6d32e6 tip
206 2
206 2
207 branch: default
207 branch: default
208 commit: (clean)
208 commit: (clean)
209 update: 1 new changesets, 2 branch heads (merge)
209 update: 1 new changesets, 2 branch heads (merge)
210 phases: 3 draft
210 phases: 3 draft
211
211
212 backout with merge
212 backout with merge
213
213
214 $ cd ..
214 $ cd ..
215 $ hg init merge
215 $ hg init merge
216 $ cd merge
216 $ cd merge
217
217
218 $ echo line 1 > a
218 $ echo line 1 > a
219 $ echo line 2 >> a
219 $ echo line 2 >> a
220 $ hg commit -d '0 0' -A -m a
220 $ hg commit -d '0 0' -A -m a
221 adding a
221 adding a
222 $ hg summary
222 $ hg summary
223 parent: 0:59395513a13a tip
223 parent: 0:59395513a13a tip
224 a
224 a
225 branch: default
225 branch: default
226 commit: (clean)
226 commit: (clean)
227 update: (current)
227 update: (current)
228 phases: 1 draft
228 phases: 1 draft
229
229
230 remove line 1
230 remove line 1
231
231
232 $ echo line 2 > a
232 $ echo line 2 > a
233 $ hg commit -d '1 0' -m b
233 $ hg commit -d '1 0' -m b
234
234
235 $ echo line 3 >> a
235 $ echo line 3 >> a
236 $ hg commit -d '2 0' -m c
236 $ hg commit -d '2 0' -m c
237
237
238 $ hg backout --merge -d '3 0' 1 --tool=true
238 $ hg backout --merge -d '3 0' 1 --tool=true
239 reverting a
239 reverting a
240 created new head
240 created new head
241 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
241 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
242 merging with changeset 3:26b8ccb9ad91
242 merging with changeset 3:26b8ccb9ad91
243 merging a
243 merging a
244 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
244 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
245 (branch merge, don't forget to commit)
245 (branch merge, don't forget to commit)
246 $ hg commit -d '4 0' -m d
246 $ hg commit -d '4 0' -m d
247 $ hg summary
247 $ hg summary
248 parent: 4:c7df5e0b9c09 tip
248 parent: 4:c7df5e0b9c09 tip
249 d
249 d
250 branch: default
250 branch: default
251 commit: (clean)
251 commit: (clean)
252 update: (current)
252 update: (current)
253 phases: 5 draft
253 phases: 5 draft
254
254
255 check line 1 is back
255 check line 1 is back
256
256
257 $ cat a
257 $ cat a
258 line 1
258 line 1
259 line 2
259 line 2
260 line 3
260 line 3
261
261
262 Test visibility of in-memory dirstate changes outside transaction to
262 Test visibility of in-memory dirstate changes outside transaction to
263 external hook process
263 external hook process
264
264
265 $ cat > $TESTTMP/checkvisibility.sh <<EOF
265 $ cat > $TESTTMP/checkvisibility.sh <<EOF
266 > echo "==== \$1:"
266 > echo "==== \$1:"
267 > hg parents --template "{rev}:{node|short}\n"
267 > hg parents --template "{rev}:{node|short}\n"
268 > echo "===="
268 > echo "===="
269 > EOF
269 > EOF
270
270
271 "hg backout --merge REV1" at REV2 below implies steps below:
271 "hg backout --merge REV1" at REV2 below implies steps below:
272
272
273 (1) update to REV1 (REV2 => REV1)
273 (1) update to REV1 (REV2 => REV1)
274 (2) revert by REV1^1
274 (2) revert by REV1^1
275 (3) commit backnig out revision (REV3)
275 (3) commit backnig out revision (REV3)
276 (4) update to REV2 (REV3 => REV2)
276 (4) update to REV2 (REV3 => REV2)
277 (5) merge with REV3 (REV2 => REV2, REV3)
277 (5) merge with REV3 (REV2 => REV2, REV3)
278
278
279 == test visibility to external preupdate hook
279 == test visibility to external preupdate hook
280
280
281 $ hg update -q -C 2
281 $ hg update -q -C 2
282 $ hg --config extensions.strip= strip 3
282 $ hg --config extensions.strip= strip 3
283 saved backup bundle to * (glob)
283 saved backup bundle to * (glob)
284
284
285 $ cat >> .hg/hgrc <<EOF
285 $ cat >> .hg/hgrc <<EOF
286 > [hooks]
286 > [hooks]
287 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
287 > preupdate.visibility = sh $TESTTMP/checkvisibility.sh preupdate
288 > EOF
288 > EOF
289
289
290 ("-m" is needed to avoid writing dirstte changes out at other than
290 ("-m" is needed to avoid writing dirstte changes out at other than
291 invocation of the hook to be examined)
291 invocation of the hook to be examined)
292
292
293 $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment'
293 $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment'
294 ==== preupdate:
294 ==== preupdate:
295 2:6ea3f2a197a2
295 2:6ea3f2a197a2
296 ====
296 ====
297 reverting a
297 reverting a
298 created new head
298 created new head
299 changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182
299 changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182
300 ==== preupdate:
300 ==== preupdate:
301 3:d92a3f57f067
301 3:d92a3f57f067
302 ====
302 ====
303 merging with changeset 3:d92a3f57f067
303 merging with changeset 3:d92a3f57f067
304 ==== preupdate:
304 ==== preupdate:
305 2:6ea3f2a197a2
305 2:6ea3f2a197a2
306 ====
306 ====
307 merging a
307 merging a
308 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
308 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
309 (branch merge, don't forget to commit)
309 (branch merge, don't forget to commit)
310
310
311 $ cat >> .hg/hgrc <<EOF
311 $ cat >> .hg/hgrc <<EOF
312 > [hooks]
312 > [hooks]
313 > preupdate.visibility =
313 > preupdate.visibility =
314 > EOF
314 > EOF
315
315
316 == test visibility to external update hook
316 == test visibility to external update hook
317
317
318 $ hg update -q -C 2
318 $ hg update -q -C 2
319 $ hg --config extensions.strip= strip 3
319 $ hg --config extensions.strip= strip 3
320 saved backup bundle to * (glob)
320 saved backup bundle to * (glob)
321
321
322 $ cat >> .hg/hgrc <<EOF
322 $ cat >> .hg/hgrc <<EOF
323 > [hooks]
323 > [hooks]
324 > update.visibility = sh $TESTTMP/checkvisibility.sh update
324 > update.visibility = sh $TESTTMP/checkvisibility.sh update
325 > EOF
325 > EOF
326
326
327 $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment'
327 $ hg backout --merge -d '3 0' 1 --tool=true -m 'fixed comment'
328 ==== update:
328 ==== update:
329 1:5a50a024c182
329 1:5a50a024c182
330 ====
330 ====
331 reverting a
331 reverting a
332 created new head
332 created new head
333 changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182
333 changeset 3:d92a3f57f067 backs out changeset 1:5a50a024c182
334 ==== update:
334 ==== update:
335 2:6ea3f2a197a2
335 2:6ea3f2a197a2
336 ====
336 ====
337 merging with changeset 3:d92a3f57f067
337 merging with changeset 3:d92a3f57f067
338 merging a
338 merging a
339 ==== update:
339 ==== update:
340 2:6ea3f2a197a2
340 2:6ea3f2a197a2
341 3:d92a3f57f067
341 3:d92a3f57f067
342 ====
342 ====
343 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
343 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
344 (branch merge, don't forget to commit)
344 (branch merge, don't forget to commit)
345
345
346 $ cat >> .hg/hgrc <<EOF
346 $ cat >> .hg/hgrc <<EOF
347 > [hooks]
347 > [hooks]
348 > update.visibility =
348 > update.visibility =
349 > EOF
349 > EOF
350
350
351 $ cd ..
351 $ cd ..
352
352
353 backout should not back out subsequent changesets
353 backout should not back out subsequent changesets
354
354
355 $ hg init onecs
355 $ hg init onecs
356 $ cd onecs
356 $ cd onecs
357 $ echo 1 > a
357 $ echo 1 > a
358 $ hg commit -d '0 0' -A -m a
358 $ hg commit -d '0 0' -A -m a
359 adding a
359 adding a
360 $ echo 2 >> a
360 $ echo 2 >> a
361 $ hg commit -d '1 0' -m b
361 $ hg commit -d '1 0' -m b
362 $ echo 1 > b
362 $ echo 1 > b
363 $ hg commit -d '2 0' -A -m c
363 $ hg commit -d '2 0' -A -m c
364 adding b
364 adding b
365 $ hg summary
365 $ hg summary
366 parent: 2:882396649954 tip
366 parent: 2:882396649954 tip
367 c
367 c
368 branch: default
368 branch: default
369 commit: (clean)
369 commit: (clean)
370 update: (current)
370 update: (current)
371 phases: 3 draft
371 phases: 3 draft
372
372
373 without --merge
373 without --merge
374 $ hg backout --no-commit -d '3 0' 1 --tool=true
374 $ hg backout --no-commit -d '3 0' 1 --tool=true
375 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
375 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
376 changeset 22bca4c721e5 backed out, don't forget to commit.
376 changeset 22bca4c721e5 backed out, don't forget to commit.
377 $ hg locate b
377 $ hg locate b
378 b
378 b
379 $ hg update -C tip
379 $ hg update -C tip
380 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
380 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 $ hg locate b
381 $ hg locate b
382 b
382 b
383 $ hg summary
383 $ hg summary
384 parent: 2:882396649954 tip
384 parent: 2:882396649954 tip
385 c
385 c
386 branch: default
386 branch: default
387 commit: (clean)
387 commit: (clean)
388 update: (current)
388 update: (current)
389 phases: 3 draft
389 phases: 3 draft
390
390
391 with --merge
391 with --merge
392 $ hg backout --merge -d '3 0' 1 --tool=true
392 $ hg backout --merge -d '3 0' 1 --tool=true
393 reverting a
393 reverting a
394 created new head
394 created new head
395 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
395 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
396 merging with changeset 3:3202beb76721
396 merging with changeset 3:3202beb76721
397 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
397 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
398 (branch merge, don't forget to commit)
398 (branch merge, don't forget to commit)
399 $ hg locate b
399 $ hg locate b
400 b
400 b
401 $ hg update -C tip
401 $ hg update -C tip
402 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
402 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
403 $ hg locate b
403 $ hg locate b
404 [1]
404 [1]
405
405
406 $ cd ..
406 $ cd ..
407 $ hg init m
407 $ hg init m
408 $ cd m
408 $ cd m
409 $ echo a > a
409 $ echo a > a
410 $ hg commit -d '0 0' -A -m a
410 $ hg commit -d '0 0' -A -m a
411 adding a
411 adding a
412 $ echo b > b
412 $ echo b > b
413 $ hg commit -d '1 0' -A -m b
413 $ hg commit -d '1 0' -A -m b
414 adding b
414 adding b
415 $ echo c > c
415 $ echo c > c
416 $ hg commit -d '2 0' -A -m b
416 $ hg commit -d '2 0' -A -m b
417 adding c
417 adding c
418 $ hg update 1
418 $ hg update 1
419 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
419 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
420 $ echo d > d
420 $ echo d > d
421 $ hg commit -d '3 0' -A -m c
421 $ hg commit -d '3 0' -A -m c
422 adding d
422 adding d
423 created new head
423 created new head
424 $ hg merge 2
424 $ hg merge 2
425 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
425 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 (branch merge, don't forget to commit)
426 (branch merge, don't forget to commit)
427 $ hg commit -d '4 0' -A -m d
427 $ hg commit -d '4 0' -A -m d
428 $ hg summary
428 $ hg summary
429 parent: 4:b2f3bb92043e tip
429 parent: 4:b2f3bb92043e tip
430 d
430 d
431 branch: default
431 branch: default
432 commit: (clean)
432 commit: (clean)
433 update: (current)
433 update: (current)
434 phases: 5 draft
434 phases: 5 draft
435
435
436 backout of merge should fail
436 backout of merge should fail
437
437
438 $ hg backout 4
438 $ hg backout 4
439 abort: cannot backout a merge changeset
439 abort: cannot backout a merge changeset
440 [255]
440 [255]
441
441
442 backout of merge with bad parent should fail
442 backout of merge with bad parent should fail
443
443
444 $ hg backout --parent 0 4
444 $ hg backout --parent 0 4
445 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
445 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
446 [255]
446 [255]
447
447
448 backout of non-merge with parent should fail
448 backout of non-merge with parent should fail
449
449
450 $ hg backout --parent 0 3
450 $ hg backout --parent 0 3
451 abort: cannot use --parent on non-merge changeset
451 abort: cannot use --parent on non-merge changeset
452 [255]
452 [255]
453
453
454 backout with valid parent should be ok
454 backout with valid parent should be ok
455
455
456 $ hg backout -d '5 0' --parent 2 4 --tool=true
456 $ hg backout -d '5 0' --parent 2 4 --tool=true
457 removing d
457 removing d
458 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
458 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
459 $ hg summary
459 $ hg summary
460 parent: 5:10e5328c8435 tip
460 parent: 5:10e5328c8435 tip
461 Backed out changeset b2f3bb92043e
461 Backed out changeset b2f3bb92043e
462 branch: default
462 branch: default
463 commit: (clean)
463 commit: (clean)
464 update: (current)
464 update: (current)
465 phases: 6 draft
465 phases: 6 draft
466
466
467 $ hg rollback
467 $ hg rollback
468 repository tip rolled back to revision 4 (undo commit)
468 repository tip rolled back to revision 4 (undo commit)
469 working directory now based on revision 4
469 working directory now based on revision 4
470 $ hg update -C
470 $ hg update -C
471 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
471 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
472 $ hg summary
472 $ hg summary
473 parent: 4:b2f3bb92043e tip
473 parent: 4:b2f3bb92043e tip
474 d
474 d
475 branch: default
475 branch: default
476 commit: (clean)
476 commit: (clean)
477 update: (current)
477 update: (current)
478 phases: 5 draft
478 phases: 5 draft
479
479
480 $ hg backout -d '6 0' --parent 3 4 --tool=true
480 $ hg backout -d '6 0' --parent 3 4 --tool=true
481 removing c
481 removing c
482 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
482 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
483 $ hg summary
483 $ hg summary
484 parent: 5:033590168430 tip
484 parent: 5:033590168430 tip
485 Backed out changeset b2f3bb92043e
485 Backed out changeset b2f3bb92043e
486 branch: default
486 branch: default
487 commit: (clean)
487 commit: (clean)
488 update: (current)
488 update: (current)
489 phases: 6 draft
489 phases: 6 draft
490
490
491 $ cd ..
491 $ cd ..
492
492
493 named branches
493 named branches
494
494
495 $ hg init named_branches
495 $ hg init named_branches
496 $ cd named_branches
496 $ cd named_branches
497
497
498 $ echo default > default
498 $ echo default > default
499 $ hg ci -d '0 0' -Am default
499 $ hg ci -d '0 0' -Am default
500 adding default
500 adding default
501 $ hg branch branch1
501 $ hg branch branch1
502 marked working directory as branch branch1
502 marked working directory as branch branch1
503 (branches are permanent and global, did you want a bookmark?)
503 (branches are permanent and global, did you want a bookmark?)
504 $ echo branch1 > file1
504 $ echo branch1 > file1
505 $ hg ci -d '1 0' -Am file1
505 $ hg ci -d '1 0' -Am file1
506 adding file1
506 adding file1
507 $ hg branch branch2
507 $ hg branch branch2
508 marked working directory as branch branch2
508 marked working directory as branch branch2
509 $ echo branch2 > file2
509 $ echo branch2 > file2
510 $ hg ci -d '2 0' -Am file2
510 $ hg ci -d '2 0' -Am file2
511 adding file2
511 adding file2
512
512
513 without --merge
513 without --merge
514 $ hg backout --no-commit -r 1 --tool=true
514 $ hg backout --no-commit -r 1 --tool=true
515 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
515 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
516 changeset bf1602f437f3 backed out, don't forget to commit.
516 changeset bf1602f437f3 backed out, don't forget to commit.
517 $ hg branch
517 $ hg branch
518 branch2
518 branch2
519 $ hg status -A
519 $ hg status -A
520 R file1
520 R file1
521 C default
521 C default
522 C file2
522 C file2
523 $ hg summary
523 $ hg summary
524 parent: 2:45bbcd363bf0 tip
524 parent: 2:45bbcd363bf0 tip
525 file2
525 file2
526 branch: branch2
526 branch: branch2
527 commit: 1 removed
527 commit: 1 removed
528 update: (current)
528 update: (current)
529 phases: 3 draft
529 phases: 3 draft
530
530
531 with --merge
531 with --merge
532 (this also tests that editor is invoked if '--edit' is specified
532 (this also tests that editor is invoked if '--edit' is specified
533 explicitly regardless of '--message')
533 explicitly regardless of '--message')
534
534
535 $ hg update -qC
535 $ hg update -qC
536 $ HGEDITOR=cat hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true --edit
536 $ HGEDITOR=cat hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true --edit
537 removing file1
537 removing file1
538 backout on branch1
538 backout on branch1
539
539
540
540
541 HG: Enter commit message. Lines beginning with 'HG:' are removed.
541 HG: Enter commit message. Lines beginning with 'HG:' are removed.
542 HG: Leave message empty to abort commit.
542 HG: Leave message empty to abort commit.
543 HG: --
543 HG: --
544 HG: user: test
544 HG: user: test
545 HG: branch 'branch2'
545 HG: branch 'branch2'
546 HG: removed file1
546 HG: removed file1
547 created new head
547 created new head
548 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
548 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
549 merging with changeset 3:d4e8f6db59fb
549 merging with changeset 3:d4e8f6db59fb
550 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
550 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
551 (branch merge, don't forget to commit)
551 (branch merge, don't forget to commit)
552 $ hg summary
552 $ hg summary
553 parent: 2:45bbcd363bf0
553 parent: 2:45bbcd363bf0
554 file2
554 file2
555 parent: 3:d4e8f6db59fb tip
555 parent: 3:d4e8f6db59fb tip
556 backout on branch1
556 backout on branch1
557 branch: branch2
557 branch: branch2
558 commit: 1 removed (merge)
558 commit: 1 removed (merge)
559 update: (current)
559 update: (current)
560 phases: 4 draft
560 phases: 4 draft
561 $ hg update -q -C 2
561 $ hg update -q -C 2
562
562
563 on branch2 with branch1 not merged, so file1 should still exist:
563 on branch2 with branch1 not merged, so file1 should still exist:
564
564
565 $ hg id
565 $ hg id
566 45bbcd363bf0 (branch2)
566 45bbcd363bf0 (branch2)
567 $ hg st -A
567 $ hg st -A
568 C default
568 C default
569 C file1
569 C file1
570 C file2
570 C file2
571 $ hg summary
571 $ hg summary
572 parent: 2:45bbcd363bf0
572 parent: 2:45bbcd363bf0
573 file2
573 file2
574 branch: branch2
574 branch: branch2
575 commit: (clean)
575 commit: (clean)
576 update: 1 new changesets, 2 branch heads (merge)
576 update: 1 new changesets, 2 branch heads (merge)
577 phases: 4 draft
577 phases: 4 draft
578
578
579 on branch2 with branch1 merged, so file1 should be gone:
579 on branch2 with branch1 merged, so file1 should be gone:
580
580
581 $ hg merge
581 $ hg merge
582 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
582 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
583 (branch merge, don't forget to commit)
583 (branch merge, don't forget to commit)
584 $ hg ci -d '4 0' -m 'merge backout of branch1'
584 $ hg ci -d '4 0' -m 'merge backout of branch1'
585 $ hg id
585 $ hg id
586 22149cdde76d (branch2) tip
586 22149cdde76d (branch2) tip
587 $ hg st -A
587 $ hg st -A
588 C default
588 C default
589 C file2
589 C file2
590 $ hg summary
590 $ hg summary
591 parent: 4:22149cdde76d tip
591 parent: 4:22149cdde76d tip
592 merge backout of branch1
592 merge backout of branch1
593 branch: branch2
593 branch: branch2
594 commit: (clean)
594 commit: (clean)
595 update: (current)
595 update: (current)
596 phases: 5 draft
596 phases: 5 draft
597
597
598 on branch1, so no file1 and file2:
598 on branch1, so no file1 and file2:
599
599
600 $ hg co -C branch1
600 $ hg co -C branch1
601 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
601 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
602 $ hg id
602 $ hg id
603 bf1602f437f3 (branch1)
603 bf1602f437f3 (branch1)
604 $ hg st -A
604 $ hg st -A
605 C default
605 C default
606 C file1
606 C file1
607 $ hg summary
607 $ hg summary
608 parent: 1:bf1602f437f3
608 parent: 1:bf1602f437f3
609 file1
609 file1
610 branch: branch1
610 branch: branch1
611 commit: (clean)
611 commit: (clean)
612 update: (current)
612 update: (current)
613 phases: 5 draft
613 phases: 5 draft
614
614
615 $ cd ..
615 $ cd ..
616
616
617 backout of empty changeset (issue4190)
617 backout of empty changeset (issue4190)
618
618
619 $ hg init emptycommit
619 $ hg init emptycommit
620 $ cd emptycommit
620 $ cd emptycommit
621
621
622 $ touch file1
622 $ touch file1
623 $ hg ci -Aqm file1
623 $ hg ci -Aqm file1
624 $ hg branch -q branch1
624 $ hg branch -q branch1
625 $ hg ci -qm branch1
625 $ hg ci -qm branch1
626 $ hg backout -v 1
626 $ hg backout -v 1
627 resolving manifests
627 resolving manifests
628 nothing changed
628 nothing changed
629 [1]
629 [1]
630
630
631 $ cd ..
631 $ cd ..
632
632
633
633
634 Test usage of `hg resolve` in case of conflict
634 Test usage of `hg resolve` in case of conflict
635 (issue4163)
635 (issue4163)
636
636
637 $ hg init issue4163
637 $ hg init issue4163
638 $ cd issue4163
638 $ cd issue4163
639 $ touch foo
639 $ touch foo
640 $ hg add foo
640 $ hg add foo
641 $ cat > foo << EOF
641 $ cat > foo << EOF
642 > one
642 > one
643 > two
643 > two
644 > three
644 > three
645 > four
645 > four
646 > five
646 > five
647 > six
647 > six
648 > seven
648 > seven
649 > height
649 > height
650 > nine
650 > nine
651 > ten
651 > ten
652 > EOF
652 > EOF
653 $ hg ci -m 'initial'
653 $ hg ci -m 'initial'
654 $ cat > foo << EOF
654 $ cat > foo << EOF
655 > one
655 > one
656 > two
656 > two
657 > THREE
657 > THREE
658 > four
658 > four
659 > five
659 > five
660 > six
660 > six
661 > seven
661 > seven
662 > height
662 > height
663 > nine
663 > nine
664 > ten
664 > ten
665 > EOF
665 > EOF
666 $ hg ci -m 'capital three'
666 $ hg ci -m 'capital three'
667 $ cat > foo << EOF
667 $ cat > foo << EOF
668 > one
668 > one
669 > two
669 > two
670 > THREE
670 > THREE
671 > four
671 > four
672 > five
672 > five
673 > six
673 > six
674 > seven
674 > seven
675 > height
675 > height
676 > nine
676 > nine
677 > TEN
677 > TEN
678 > EOF
678 > EOF
679 $ hg ci -m 'capital ten'
679 $ hg ci -m 'capital ten'
680 $ hg backout -r 'desc("capital three")' --tool internal:fail
680 $ hg backout -r 'desc("capital three")' --tool internal:fail
681 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
681 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
682 use 'hg resolve' to retry unresolved file merges
682 use 'hg resolve' to retry unresolved file merges
683 [1]
683 [1]
684 $ hg status
684 $ hg status
685 $ hg debugmergestate
685 $ hg debugmergestate
686 * version 2 records
686 * version 2 records
687 local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
687 local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
688 other: a30dd8addae3ce71b8667868478542bc417439e6
688 other: a30dd8addae3ce71b8667868478542bc417439e6
689 file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
689 file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
690 local path: foo (flags "")
690 local path: foo (flags "")
691 ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
691 ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
692 other path: foo (node f50039b486d6fa1a90ae51778388cad161f425ee)
692 other path: foo (node f50039b486d6fa1a90ae51778388cad161f425ee)
693 $ mv .hg/merge/state2 .hg/merge/state2-moved
693 $ mv .hg/merge/state2 .hg/merge/state2-moved
694 $ hg debugmergestate
694 $ hg debugmergestate
695 * version 1 records
695 * version 1 records
696 local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
696 local: b71750c4b0fdf719734971e3ef90dbeab5919a2d
697 file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
697 file: foo (record type "F", state "u", hash 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33)
698 local path: foo (flags "")
698 local path: foo (flags "")
699 ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
699 ancestor path: foo (node f89532f44c247a0e993d63e3a734dd781ab04708)
700 other path: foo (node not stored in v1 format)
700 other path: foo (node not stored in v1 format)
701 $ mv .hg/merge/state2-moved .hg/merge/state2
701 $ mv .hg/merge/state2-moved .hg/merge/state2
702 $ hg resolve -l # still unresolved
702 $ hg resolve -l # still unresolved
703 U foo
703 U foo
704 $ hg summary
704 $ hg summary
705 parent: 2:b71750c4b0fd tip
705 parent: 2:b71750c4b0fd tip
706 capital ten
706 capital ten
707 branch: default
707 branch: default
708 commit: 1 unresolved (clean)
708 commit: 1 unresolved (clean)
709 update: (current)
709 update: (current)
710 phases: 3 draft
710 phases: 3 draft
711 $ hg resolve --all --debug
711 $ hg resolve --all --debug
712 picked tool ':merge' for foo (binary False symlink False changedelete False)
712 picked tool ':merge' for foo (binary False symlink False changedelete False)
713 merging foo
713 merging foo
714 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
714 my foo@b71750c4b0fd+ other foo@a30dd8addae3 ancestor foo@913609522437
715 premerge successful
715 premerge successful
716 (no more unresolved files)
716 (no more unresolved files)
717 continue: hg commit
717 continue: hg commit
718 $ hg status
718 $ hg status
719 M foo
719 M foo
720 ? foo.orig
720 ? foo.orig
721 $ hg resolve -l
721 $ hg resolve -l
722 R foo
722 R foo
723 $ hg summary
723 $ hg summary
724 parent: 2:b71750c4b0fd tip
724 parent: 2:b71750c4b0fd tip
725 capital ten
725 capital ten
726 branch: default
726 branch: default
727 commit: 1 modified, 1 unknown
727 commit: 1 modified, 1 unknown
728 update: (current)
728 update: (current)
729 phases: 3 draft
729 phases: 3 draft
730 $ cat foo
730 $ cat foo
731 one
731 one
732 two
732 two
733 three
733 three
734 four
734 four
735 five
735 five
736 six
736 six
737 seven
737 seven
738 height
738 height
739 nine
739 nine
740 TEN
740 TEN
741
741
742 --no-commit shouldn't commit
742 --no-commit shouldn't commit
743
743
744 $ hg init a
744 $ hg init a
745 $ cd a
745 $ cd a
746 $ for i in 1 2 3; do
746 $ for i in 1 2 3; do
747 > touch $i
747 > touch $i
748 > hg ci -Am $i
748 > hg ci -Am $i
749 > done
749 > done
750 adding 1
750 adding 1
751 adding 2
751 adding 2
752 adding 3
752 adding 3
753 $ hg backout --no-commit .
753 $ hg backout --no-commit .
754 removing 3
754 removing 3
755 changeset cccc23d9d68f backed out, don't forget to commit.
755 changeset cccc23d9d68f backed out, don't forget to commit.
756 $ hg revert -aq
757
758 --no-commit can't be used with --merge
759
760 $ hg backout --merge --no-commit 2
761 abort: cannot use --merge with --no-commit
762 [255]
General Comments 0
You need to be logged in to leave comments. Login now