##// END OF EJS Templates
graft: warn when -r is combined with revisions as positional arguments...
Mads Kiilerich -
r27899:78b9fdb8 default
parent child Browse files
Show More
@@ -1,7031 +1,7035
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
601
602 if rev and node:
602 if rev and node:
603 raise error.Abort(_("please specify just one revision"))
603 raise error.Abort(_("please specify just one revision"))
604
604
605 if not rev:
605 if not rev:
606 rev = node
606 rev = node
607
607
608 if not rev:
608 if not rev:
609 raise error.Abort(_("please specify a revision to backout"))
609 raise error.Abort(_("please specify a revision to backout"))
610
610
611 date = opts.get('date')
611 date = opts.get('date')
612 if date:
612 if date:
613 opts['date'] = util.parsedate(date)
613 opts['date'] = util.parsedate(date)
614
614
615 cmdutil.checkunfinished(repo)
615 cmdutil.checkunfinished(repo)
616 cmdutil.bailifchanged(repo)
616 cmdutil.bailifchanged(repo)
617 node = scmutil.revsingle(repo, rev).node()
617 node = scmutil.revsingle(repo, rev).node()
618
618
619 op1, op2 = repo.dirstate.parents()
619 op1, op2 = repo.dirstate.parents()
620 if not repo.changelog.isancestor(node, op1):
620 if not repo.changelog.isancestor(node, op1):
621 raise error.Abort(_('cannot backout change that is not an ancestor'))
621 raise error.Abort(_('cannot backout change that is not an ancestor'))
622
622
623 p1, p2 = repo.changelog.parents(node)
623 p1, p2 = repo.changelog.parents(node)
624 if p1 == nullid:
624 if p1 == nullid:
625 raise error.Abort(_('cannot backout a change with no parents'))
625 raise error.Abort(_('cannot backout a change with no parents'))
626 if p2 != nullid:
626 if p2 != nullid:
627 if not opts.get('parent'):
627 if not opts.get('parent'):
628 raise error.Abort(_('cannot backout a merge changeset'))
628 raise error.Abort(_('cannot backout a merge changeset'))
629 p = repo.lookup(opts['parent'])
629 p = repo.lookup(opts['parent'])
630 if p not in (p1, p2):
630 if p not in (p1, p2):
631 raise error.Abort(_('%s is not a parent of %s') %
631 raise error.Abort(_('%s is not a parent of %s') %
632 (short(p), short(node)))
632 (short(p), short(node)))
633 parent = p
633 parent = p
634 else:
634 else:
635 if opts.get('parent'):
635 if opts.get('parent'):
636 raise error.Abort(_('cannot use --parent on non-merge changeset'))
636 raise error.Abort(_('cannot use --parent on non-merge changeset'))
637 parent = p1
637 parent = p1
638
638
639 # the backout should appear on the same branch
639 # the backout should appear on the same branch
640 branch = repo.dirstate.branch()
640 branch = repo.dirstate.branch()
641 bheads = repo.branchheads(branch)
641 bheads = repo.branchheads(branch)
642 rctx = scmutil.revsingle(repo, hex(parent))
642 rctx = scmutil.revsingle(repo, hex(parent))
643 if not opts.get('merge') and op1 != node:
643 if not opts.get('merge') and op1 != node:
644 dsguard = cmdutil.dirstateguard(repo, 'backout')
644 dsguard = cmdutil.dirstateguard(repo, 'backout')
645 try:
645 try:
646 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
646 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
647 'backout')
647 'backout')
648 stats = mergemod.update(repo, parent, True, True, node, False)
648 stats = mergemod.update(repo, parent, True, True, node, False)
649 repo.setparents(op1, op2)
649 repo.setparents(op1, op2)
650 dsguard.close()
650 dsguard.close()
651 hg._showstats(repo, stats)
651 hg._showstats(repo, stats)
652 if stats[3]:
652 if stats[3]:
653 repo.ui.status(_("use 'hg resolve' to retry unresolved "
653 repo.ui.status(_("use 'hg resolve' to retry unresolved "
654 "file merges\n"))
654 "file merges\n"))
655 return 1
655 return 1
656 elif opts.get('no_commit'):
656 elif opts.get('no_commit'):
657 msg = _("changeset %s backed out, "
657 msg = _("changeset %s backed out, "
658 "don't forget to commit.\n")
658 "don't forget to commit.\n")
659 ui.status(msg % short(node))
659 ui.status(msg % short(node))
660 return 0
660 return 0
661 finally:
661 finally:
662 ui.setconfig('ui', 'forcemerge', '', '')
662 ui.setconfig('ui', 'forcemerge', '', '')
663 lockmod.release(dsguard)
663 lockmod.release(dsguard)
664 else:
664 else:
665 hg.clean(repo, node, show_stats=False)
665 hg.clean(repo, node, show_stats=False)
666 repo.dirstate.setbranch(branch)
666 repo.dirstate.setbranch(branch)
667 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
667 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
668
668
669
669
670 def commitfunc(ui, repo, message, match, opts):
670 def commitfunc(ui, repo, message, match, opts):
671 editform = 'backout'
671 editform = 'backout'
672 e = cmdutil.getcommiteditor(editform=editform, **opts)
672 e = cmdutil.getcommiteditor(editform=editform, **opts)
673 if not message:
673 if not message:
674 # we don't translate commit messages
674 # we don't translate commit messages
675 message = "Backed out changeset %s" % short(node)
675 message = "Backed out changeset %s" % short(node)
676 e = cmdutil.getcommiteditor(edit=True, editform=editform)
676 e = cmdutil.getcommiteditor(edit=True, editform=editform)
677 return repo.commit(message, opts.get('user'), opts.get('date'),
677 return repo.commit(message, opts.get('user'), opts.get('date'),
678 match, editor=e)
678 match, editor=e)
679 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
679 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
680 if not newnode:
680 if not newnode:
681 ui.status(_("nothing changed\n"))
681 ui.status(_("nothing changed\n"))
682 return 1
682 return 1
683 cmdutil.commitstatus(repo, newnode, branch, bheads)
683 cmdutil.commitstatus(repo, newnode, branch, bheads)
684
684
685 def nice(node):
685 def nice(node):
686 return '%d:%s' % (repo.changelog.rev(node), short(node))
686 return '%d:%s' % (repo.changelog.rev(node), short(node))
687 ui.status(_('changeset %s backs out changeset %s\n') %
687 ui.status(_('changeset %s backs out changeset %s\n') %
688 (nice(repo.changelog.tip()), nice(node)))
688 (nice(repo.changelog.tip()), nice(node)))
689 if opts.get('merge') and op1 != node:
689 if opts.get('merge') and op1 != node:
690 hg.clean(repo, op1, show_stats=False)
690 hg.clean(repo, op1, show_stats=False)
691 ui.status(_('merging with changeset %s\n')
691 ui.status(_('merging with changeset %s\n')
692 % nice(repo.changelog.tip()))
692 % nice(repo.changelog.tip()))
693 try:
693 try:
694 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
694 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
695 'backout')
695 'backout')
696 return hg.merge(repo, hex(repo.changelog.tip()))
696 return hg.merge(repo, hex(repo.changelog.tip()))
697 finally:
697 finally:
698 ui.setconfig('ui', 'forcemerge', '', '')
698 ui.setconfig('ui', 'forcemerge', '', '')
699 return 0
699 return 0
700
700
701 @command('bisect',
701 @command('bisect',
702 [('r', 'reset', False, _('reset bisect state')),
702 [('r', 'reset', False, _('reset bisect state')),
703 ('g', 'good', False, _('mark changeset good')),
703 ('g', 'good', False, _('mark changeset good')),
704 ('b', 'bad', False, _('mark changeset bad')),
704 ('b', 'bad', False, _('mark changeset bad')),
705 ('s', 'skip', False, _('skip testing changeset')),
705 ('s', 'skip', False, _('skip testing changeset')),
706 ('e', 'extend', False, _('extend the bisect range')),
706 ('e', 'extend', False, _('extend the bisect range')),
707 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
707 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
708 ('U', 'noupdate', False, _('do not update to target'))],
708 ('U', 'noupdate', False, _('do not update to target'))],
709 _("[-gbsr] [-U] [-c CMD] [REV]"))
709 _("[-gbsr] [-U] [-c CMD] [REV]"))
710 def bisect(ui, repo, rev=None, extra=None, command=None,
710 def bisect(ui, repo, rev=None, extra=None, command=None,
711 reset=None, good=None, bad=None, skip=None, extend=None,
711 reset=None, good=None, bad=None, skip=None, extend=None,
712 noupdate=None):
712 noupdate=None):
713 """subdivision search of changesets
713 """subdivision search of changesets
714
714
715 This command helps to find changesets which introduce problems. To
715 This command helps to find changesets which introduce problems. To
716 use, mark the earliest changeset you know exhibits the problem as
716 use, mark the earliest changeset you know exhibits the problem as
717 bad, then mark the latest changeset which is free from the problem
717 bad, then mark the latest changeset which is free from the problem
718 as good. Bisect will update your working directory to a revision
718 as good. Bisect will update your working directory to a revision
719 for testing (unless the -U/--noupdate option is specified). Once
719 for testing (unless the -U/--noupdate option is specified). Once
720 you have performed tests, mark the working directory as good or
720 you have performed tests, mark the working directory as good or
721 bad, and bisect will either update to another candidate changeset
721 bad, and bisect will either update to another candidate changeset
722 or announce that it has found the bad revision.
722 or announce that it has found the bad revision.
723
723
724 As a shortcut, you can also use the revision argument to mark a
724 As a shortcut, you can also use the revision argument to mark a
725 revision as good or bad without checking it out first.
725 revision as good or bad without checking it out first.
726
726
727 If you supply a command, it will be used for automatic bisection.
727 If you supply a command, it will be used for automatic bisection.
728 The environment variable HG_NODE will contain the ID of the
728 The environment variable HG_NODE will contain the ID of the
729 changeset being tested. The exit status of the command will be
729 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
730 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
731 means to skip the revision, 127 (command not found) will abort the
732 bisection, and any other non-zero exit status means the revision
732 bisection, and any other non-zero exit status means the revision
733 is bad.
733 is bad.
734
734
735 .. container:: verbose
735 .. container:: verbose
736
736
737 Some examples:
737 Some examples:
738
738
739 - start a bisection with known bad revision 34, and good revision 12::
739 - start a bisection with known bad revision 34, and good revision 12::
740
740
741 hg bisect --bad 34
741 hg bisect --bad 34
742 hg bisect --good 12
742 hg bisect --good 12
743
743
744 - advance the current bisection by marking current revision as good or
744 - advance the current bisection by marking current revision as good or
745 bad::
745 bad::
746
746
747 hg bisect --good
747 hg bisect --good
748 hg bisect --bad
748 hg bisect --bad
749
749
750 - mark the current revision, or a known revision, to be skipped (e.g. if
750 - mark the current revision, or a known revision, to be skipped (e.g. if
751 that revision is not usable because of another issue)::
751 that revision is not usable because of another issue)::
752
752
753 hg bisect --skip
753 hg bisect --skip
754 hg bisect --skip 23
754 hg bisect --skip 23
755
755
756 - skip all revisions that do not touch directories ``foo`` or ``bar``::
756 - skip all revisions that do not touch directories ``foo`` or ``bar``::
757
757
758 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
758 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
759
759
760 - forget the current bisection::
760 - forget the current bisection::
761
761
762 hg bisect --reset
762 hg bisect --reset
763
763
764 - use 'make && make tests' to automatically find the first broken
764 - use 'make && make tests' to automatically find the first broken
765 revision::
765 revision::
766
766
767 hg bisect --reset
767 hg bisect --reset
768 hg bisect --bad 34
768 hg bisect --bad 34
769 hg bisect --good 12
769 hg bisect --good 12
770 hg bisect --command "make && make tests"
770 hg bisect --command "make && make tests"
771
771
772 - see all changesets whose states are already known in the current
772 - see all changesets whose states are already known in the current
773 bisection::
773 bisection::
774
774
775 hg log -r "bisect(pruned)"
775 hg log -r "bisect(pruned)"
776
776
777 - see the changeset currently being bisected (especially useful
777 - see the changeset currently being bisected (especially useful
778 if running with -U/--noupdate)::
778 if running with -U/--noupdate)::
779
779
780 hg log -r "bisect(current)"
780 hg log -r "bisect(current)"
781
781
782 - see all changesets that took part in the current bisection::
782 - see all changesets that took part in the current bisection::
783
783
784 hg log -r "bisect(range)"
784 hg log -r "bisect(range)"
785
785
786 - you can even get a nice graph::
786 - you can even get a nice graph::
787
787
788 hg log --graph -r "bisect(range)"
788 hg log --graph -r "bisect(range)"
789
789
790 See :hg:`help revsets` for more about the `bisect()` keyword.
790 See :hg:`help revsets` for more about the `bisect()` keyword.
791
791
792 Returns 0 on success.
792 Returns 0 on success.
793 """
793 """
794 def extendbisectrange(nodes, good):
794 def extendbisectrange(nodes, good):
795 # bisect is incomplete when it ends on a merge node and
795 # bisect is incomplete when it ends on a merge node and
796 # one of the parent was not checked.
796 # one of the parent was not checked.
797 parents = repo[nodes[0]].parents()
797 parents = repo[nodes[0]].parents()
798 if len(parents) > 1:
798 if len(parents) > 1:
799 if good:
799 if good:
800 side = state['bad']
800 side = state['bad']
801 else:
801 else:
802 side = state['good']
802 side = state['good']
803 num = len(set(i.node() for i in parents) & set(side))
803 num = len(set(i.node() for i in parents) & set(side))
804 if num == 1:
804 if num == 1:
805 return parents[0].ancestor(parents[1])
805 return parents[0].ancestor(parents[1])
806 return None
806 return None
807
807
808 def print_result(nodes, good):
808 def print_result(nodes, good):
809 displayer = cmdutil.show_changeset(ui, repo, {})
809 displayer = cmdutil.show_changeset(ui, repo, {})
810 if len(nodes) == 1:
810 if len(nodes) == 1:
811 # narrowed it down to a single revision
811 # narrowed it down to a single revision
812 if good:
812 if good:
813 ui.write(_("The first good revision is:\n"))
813 ui.write(_("The first good revision is:\n"))
814 else:
814 else:
815 ui.write(_("The first bad revision is:\n"))
815 ui.write(_("The first bad revision is:\n"))
816 displayer.show(repo[nodes[0]])
816 displayer.show(repo[nodes[0]])
817 extendnode = extendbisectrange(nodes, good)
817 extendnode = extendbisectrange(nodes, good)
818 if extendnode is not None:
818 if extendnode is not None:
819 ui.write(_('Not all ancestors of this changeset have been'
819 ui.write(_('Not all ancestors of this changeset have been'
820 ' checked.\nUse bisect --extend to continue the '
820 ' checked.\nUse bisect --extend to continue the '
821 'bisection from\nthe common ancestor, %s.\n')
821 'bisection from\nthe common ancestor, %s.\n')
822 % extendnode)
822 % extendnode)
823 else:
823 else:
824 # multiple possible revisions
824 # multiple possible revisions
825 if good:
825 if good:
826 ui.write(_("Due to skipped revisions, the first "
826 ui.write(_("Due to skipped revisions, the first "
827 "good revision could be any of:\n"))
827 "good revision could be any of:\n"))
828 else:
828 else:
829 ui.write(_("Due to skipped revisions, the first "
829 ui.write(_("Due to skipped revisions, the first "
830 "bad revision could be any of:\n"))
830 "bad revision could be any of:\n"))
831 for n in nodes:
831 for n in nodes:
832 displayer.show(repo[n])
832 displayer.show(repo[n])
833 displayer.close()
833 displayer.close()
834
834
835 def check_state(state, interactive=True):
835 def check_state(state, interactive=True):
836 if not state['good'] or not state['bad']:
836 if not state['good'] or not state['bad']:
837 if (good or bad or skip or reset) and interactive:
837 if (good or bad or skip or reset) and interactive:
838 return
838 return
839 if not state['good']:
839 if not state['good']:
840 raise error.Abort(_('cannot bisect (no known good revisions)'))
840 raise error.Abort(_('cannot bisect (no known good revisions)'))
841 else:
841 else:
842 raise error.Abort(_('cannot bisect (no known bad revisions)'))
842 raise error.Abort(_('cannot bisect (no known bad revisions)'))
843 return True
843 return True
844
844
845 # backward compatibility
845 # backward compatibility
846 if rev in "good bad reset init".split():
846 if rev in "good bad reset init".split():
847 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
847 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
848 cmd, rev, extra = rev, extra, None
848 cmd, rev, extra = rev, extra, None
849 if cmd == "good":
849 if cmd == "good":
850 good = True
850 good = True
851 elif cmd == "bad":
851 elif cmd == "bad":
852 bad = True
852 bad = True
853 else:
853 else:
854 reset = True
854 reset = True
855 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
855 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
856 raise error.Abort(_('incompatible arguments'))
856 raise error.Abort(_('incompatible arguments'))
857
857
858 cmdutil.checkunfinished(repo)
858 cmdutil.checkunfinished(repo)
859
859
860 if reset:
860 if reset:
861 p = repo.join("bisect.state")
861 p = repo.join("bisect.state")
862 if os.path.exists(p):
862 if os.path.exists(p):
863 os.unlink(p)
863 os.unlink(p)
864 return
864 return
865
865
866 state = hbisect.load_state(repo)
866 state = hbisect.load_state(repo)
867
867
868 if command:
868 if command:
869 changesets = 1
869 changesets = 1
870 if noupdate:
870 if noupdate:
871 try:
871 try:
872 node = state['current'][0]
872 node = state['current'][0]
873 except LookupError:
873 except LookupError:
874 raise error.Abort(_('current bisect revision is unknown - '
874 raise error.Abort(_('current bisect revision is unknown - '
875 'start a new bisect to fix'))
875 'start a new bisect to fix'))
876 else:
876 else:
877 node, p2 = repo.dirstate.parents()
877 node, p2 = repo.dirstate.parents()
878 if p2 != nullid:
878 if p2 != nullid:
879 raise error.Abort(_('current bisect revision is a merge'))
879 raise error.Abort(_('current bisect revision is a merge'))
880 try:
880 try:
881 while changesets:
881 while changesets:
882 # update state
882 # update state
883 state['current'] = [node]
883 state['current'] = [node]
884 hbisect.save_state(repo, state)
884 hbisect.save_state(repo, state)
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 if status == 125:
886 if status == 125:
887 transition = "skip"
887 transition = "skip"
888 elif status == 0:
888 elif status == 0:
889 transition = "good"
889 transition = "good"
890 # status < 0 means process was killed
890 # status < 0 means process was killed
891 elif status == 127:
891 elif status == 127:
892 raise error.Abort(_("failed to execute %s") % command)
892 raise error.Abort(_("failed to execute %s") % command)
893 elif status < 0:
893 elif status < 0:
894 raise error.Abort(_("%s killed") % command)
894 raise error.Abort(_("%s killed") % command)
895 else:
895 else:
896 transition = "bad"
896 transition = "bad"
897 ctx = scmutil.revsingle(repo, rev, node)
897 ctx = scmutil.revsingle(repo, rev, node)
898 rev = None # clear for future iterations
898 rev = None # clear for future iterations
899 state[transition].append(ctx.node())
899 state[transition].append(ctx.node())
900 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
900 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
901 check_state(state, interactive=False)
901 check_state(state, interactive=False)
902 # bisect
902 # bisect
903 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
903 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
904 # update to next check
904 # update to next check
905 node = nodes[0]
905 node = nodes[0]
906 if not noupdate:
906 if not noupdate:
907 cmdutil.bailifchanged(repo)
907 cmdutil.bailifchanged(repo)
908 hg.clean(repo, node, show_stats=False)
908 hg.clean(repo, node, show_stats=False)
909 finally:
909 finally:
910 state['current'] = [node]
910 state['current'] = [node]
911 hbisect.save_state(repo, state)
911 hbisect.save_state(repo, state)
912 print_result(nodes, bgood)
912 print_result(nodes, bgood)
913 return
913 return
914
914
915 # update state
915 # update state
916
916
917 if rev:
917 if rev:
918 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
918 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
919 else:
919 else:
920 nodes = [repo.lookup('.')]
920 nodes = [repo.lookup('.')]
921
921
922 if good or bad or skip:
922 if good or bad or skip:
923 if good:
923 if good:
924 state['good'] += nodes
924 state['good'] += nodes
925 elif bad:
925 elif bad:
926 state['bad'] += nodes
926 state['bad'] += nodes
927 elif skip:
927 elif skip:
928 state['skip'] += nodes
928 state['skip'] += nodes
929 hbisect.save_state(repo, state)
929 hbisect.save_state(repo, state)
930
930
931 if not check_state(state):
931 if not check_state(state):
932 return
932 return
933
933
934 # actually bisect
934 # actually bisect
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
935 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
936 if extend:
936 if extend:
937 if not changesets:
937 if not changesets:
938 extendnode = extendbisectrange(nodes, good)
938 extendnode = extendbisectrange(nodes, good)
939 if extendnode is not None:
939 if extendnode is not None:
940 ui.write(_("Extending search to changeset %d:%s\n")
940 ui.write(_("Extending search to changeset %d:%s\n")
941 % (extendnode.rev(), extendnode))
941 % (extendnode.rev(), extendnode))
942 state['current'] = [extendnode.node()]
942 state['current'] = [extendnode.node()]
943 hbisect.save_state(repo, state)
943 hbisect.save_state(repo, state)
944 if noupdate:
944 if noupdate:
945 return
945 return
946 cmdutil.bailifchanged(repo)
946 cmdutil.bailifchanged(repo)
947 return hg.clean(repo, extendnode.node())
947 return hg.clean(repo, extendnode.node())
948 raise error.Abort(_("nothing to extend"))
948 raise error.Abort(_("nothing to extend"))
949
949
950 if changesets == 0:
950 if changesets == 0:
951 print_result(nodes, good)
951 print_result(nodes, good)
952 else:
952 else:
953 assert len(nodes) == 1 # only a single node can be tested next
953 assert len(nodes) == 1 # only a single node can be tested next
954 node = nodes[0]
954 node = nodes[0]
955 # compute the approximate number of remaining tests
955 # compute the approximate number of remaining tests
956 tests, size = 0, 2
956 tests, size = 0, 2
957 while size <= changesets:
957 while size <= changesets:
958 tests, size = tests + 1, size * 2
958 tests, size = tests + 1, size * 2
959 rev = repo.changelog.rev(node)
959 rev = repo.changelog.rev(node)
960 ui.write(_("Testing changeset %d:%s "
960 ui.write(_("Testing changeset %d:%s "
961 "(%d changesets remaining, ~%d tests)\n")
961 "(%d changesets remaining, ~%d tests)\n")
962 % (rev, short(node), changesets, tests))
962 % (rev, short(node), changesets, tests))
963 state['current'] = [node]
963 state['current'] = [node]
964 hbisect.save_state(repo, state)
964 hbisect.save_state(repo, state)
965 if not noupdate:
965 if not noupdate:
966 cmdutil.bailifchanged(repo)
966 cmdutil.bailifchanged(repo)
967 return hg.clean(repo, node)
967 return hg.clean(repo, node)
968
968
969 @command('bookmarks|bookmark',
969 @command('bookmarks|bookmark',
970 [('f', 'force', False, _('force')),
970 [('f', 'force', False, _('force')),
971 ('r', 'rev', '', _('revision'), _('REV')),
971 ('r', 'rev', '', _('revision'), _('REV')),
972 ('d', 'delete', False, _('delete a given bookmark')),
972 ('d', 'delete', False, _('delete a given bookmark')),
973 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
973 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
974 ('i', 'inactive', False, _('mark a bookmark inactive')),
974 ('i', 'inactive', False, _('mark a bookmark inactive')),
975 ] + formatteropts,
975 ] + formatteropts,
976 _('hg bookmarks [OPTIONS]... [NAME]...'))
976 _('hg bookmarks [OPTIONS]... [NAME]...'))
977 def bookmark(ui, repo, *names, **opts):
977 def bookmark(ui, repo, *names, **opts):
978 '''create a new bookmark or list existing bookmarks
978 '''create a new bookmark or list existing bookmarks
979
979
980 Bookmarks are labels on changesets to help track lines of development.
980 Bookmarks are labels on changesets to help track lines of development.
981 Bookmarks are unversioned and can be moved, renamed and deleted.
981 Bookmarks are unversioned and can be moved, renamed and deleted.
982 Deleting or moving a bookmark has no effect on the associated changesets.
982 Deleting or moving a bookmark has no effect on the associated changesets.
983
983
984 Creating or updating to a bookmark causes it to be marked as 'active'.
984 Creating or updating to a bookmark causes it to be marked as 'active'.
985 The active bookmark is indicated with a '*'.
985 The active bookmark is indicated with a '*'.
986 When a commit is made, the active bookmark will advance to the new commit.
986 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.
987 A plain :hg:`update` will also advance an active bookmark, if possible.
988 Updating away from a bookmark will cause it to be deactivated.
988 Updating away from a bookmark will cause it to be deactivated.
989
989
990 Bookmarks can be pushed and pulled between repositories (see
990 Bookmarks can be pushed and pulled between repositories (see
991 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
991 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
992 diverged, a new 'divergent bookmark' of the form 'name@path' will
992 diverged, a new 'divergent bookmark' of the form 'name@path' will
993 be created. Using :hg:`merge` will resolve the divergence.
993 be created. Using :hg:`merge` will resolve the divergence.
994
994
995 A bookmark named '@' has the special property that :hg:`clone` will
995 A bookmark named '@' has the special property that :hg:`clone` will
996 check it out by default if it exists.
996 check it out by default if it exists.
997
997
998 .. container:: verbose
998 .. container:: verbose
999
999
1000 Examples:
1000 Examples:
1001
1001
1002 - create an active bookmark for a new line of development::
1002 - create an active bookmark for a new line of development::
1003
1003
1004 hg book new-feature
1004 hg book new-feature
1005
1005
1006 - create an inactive bookmark as a place marker::
1006 - create an inactive bookmark as a place marker::
1007
1007
1008 hg book -i reviewed
1008 hg book -i reviewed
1009
1009
1010 - create an inactive bookmark on another changeset::
1010 - create an inactive bookmark on another changeset::
1011
1011
1012 hg book -r .^ tested
1012 hg book -r .^ tested
1013
1013
1014 - rename bookmark turkey to dinner::
1014 - rename bookmark turkey to dinner::
1015
1015
1016 hg book -m turkey dinner
1016 hg book -m turkey dinner
1017
1017
1018 - move the '@' bookmark from another branch::
1018 - move the '@' bookmark from another branch::
1019
1019
1020 hg book -f @
1020 hg book -f @
1021 '''
1021 '''
1022 force = opts.get('force')
1022 force = opts.get('force')
1023 rev = opts.get('rev')
1023 rev = opts.get('rev')
1024 delete = opts.get('delete')
1024 delete = opts.get('delete')
1025 rename = opts.get('rename')
1025 rename = opts.get('rename')
1026 inactive = opts.get('inactive')
1026 inactive = opts.get('inactive')
1027
1027
1028 def checkformat(mark):
1028 def checkformat(mark):
1029 mark = mark.strip()
1029 mark = mark.strip()
1030 if not mark:
1030 if not mark:
1031 raise error.Abort(_("bookmark names cannot consist entirely of "
1031 raise error.Abort(_("bookmark names cannot consist entirely of "
1032 "whitespace"))
1032 "whitespace"))
1033 scmutil.checknewlabel(repo, mark, 'bookmark')
1033 scmutil.checknewlabel(repo, mark, 'bookmark')
1034 return mark
1034 return mark
1035
1035
1036 def checkconflict(repo, mark, cur, force=False, target=None):
1036 def checkconflict(repo, mark, cur, force=False, target=None):
1037 if mark in marks and not force:
1037 if mark in marks and not force:
1038 if target:
1038 if target:
1039 if marks[mark] == target and target == cur:
1039 if marks[mark] == target and target == cur:
1040 # re-activating a bookmark
1040 # re-activating a bookmark
1041 return
1041 return
1042 anc = repo.changelog.ancestors([repo[target].rev()])
1042 anc = repo.changelog.ancestors([repo[target].rev()])
1043 bmctx = repo[marks[mark]]
1043 bmctx = repo[marks[mark]]
1044 divs = [repo[b].node() for b in marks
1044 divs = [repo[b].node() for b in marks
1045 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1045 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1046
1046
1047 # allow resolving a single divergent bookmark even if moving
1047 # allow resolving a single divergent bookmark even if moving
1048 # the bookmark across branches when a revision is specified
1048 # the bookmark across branches when a revision is specified
1049 # that contains a divergent bookmark
1049 # that contains a divergent bookmark
1050 if bmctx.rev() not in anc and target in divs:
1050 if bmctx.rev() not in anc and target in divs:
1051 bookmarks.deletedivergent(repo, [target], mark)
1051 bookmarks.deletedivergent(repo, [target], mark)
1052 return
1052 return
1053
1053
1054 deletefrom = [b for b in divs
1054 deletefrom = [b for b in divs
1055 if repo[b].rev() in anc or b == target]
1055 if repo[b].rev() in anc or b == target]
1056 bookmarks.deletedivergent(repo, deletefrom, mark)
1056 bookmarks.deletedivergent(repo, deletefrom, mark)
1057 if bookmarks.validdest(repo, bmctx, repo[target]):
1057 if bookmarks.validdest(repo, bmctx, repo[target]):
1058 ui.status(_("moving bookmark '%s' forward from %s\n") %
1058 ui.status(_("moving bookmark '%s' forward from %s\n") %
1059 (mark, short(bmctx.node())))
1059 (mark, short(bmctx.node())))
1060 return
1060 return
1061 raise error.Abort(_("bookmark '%s' already exists "
1061 raise error.Abort(_("bookmark '%s' already exists "
1062 "(use -f to force)") % mark)
1062 "(use -f to force)") % mark)
1063 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1063 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1064 and not force):
1064 and not force):
1065 raise error.Abort(
1065 raise error.Abort(
1066 _("a bookmark cannot have the name of an existing branch"))
1066 _("a bookmark cannot have the name of an existing branch"))
1067
1067
1068 if delete and rename:
1068 if delete and rename:
1069 raise error.Abort(_("--delete and --rename are incompatible"))
1069 raise error.Abort(_("--delete and --rename are incompatible"))
1070 if delete and rev:
1070 if delete and rev:
1071 raise error.Abort(_("--rev is incompatible with --delete"))
1071 raise error.Abort(_("--rev is incompatible with --delete"))
1072 if rename and rev:
1072 if rename and rev:
1073 raise error.Abort(_("--rev is incompatible with --rename"))
1073 raise error.Abort(_("--rev is incompatible with --rename"))
1074 if not names and (delete or rev):
1074 if not names and (delete or rev):
1075 raise error.Abort(_("bookmark name required"))
1075 raise error.Abort(_("bookmark name required"))
1076
1076
1077 if delete or rename or names or inactive:
1077 if delete or rename or names or inactive:
1078 wlock = lock = tr = None
1078 wlock = lock = tr = None
1079 try:
1079 try:
1080 wlock = repo.wlock()
1080 wlock = repo.wlock()
1081 lock = repo.lock()
1081 lock = repo.lock()
1082 cur = repo.changectx('.').node()
1082 cur = repo.changectx('.').node()
1083 marks = repo._bookmarks
1083 marks = repo._bookmarks
1084 if delete:
1084 if delete:
1085 tr = repo.transaction('bookmark')
1085 tr = repo.transaction('bookmark')
1086 for mark in names:
1086 for mark in names:
1087 if mark not in marks:
1087 if mark not in marks:
1088 raise error.Abort(_("bookmark '%s' does not exist") %
1088 raise error.Abort(_("bookmark '%s' does not exist") %
1089 mark)
1089 mark)
1090 if mark == repo._activebookmark:
1090 if mark == repo._activebookmark:
1091 bookmarks.deactivate(repo)
1091 bookmarks.deactivate(repo)
1092 del marks[mark]
1092 del marks[mark]
1093
1093
1094 elif rename:
1094 elif rename:
1095 tr = repo.transaction('bookmark')
1095 tr = repo.transaction('bookmark')
1096 if not names:
1096 if not names:
1097 raise error.Abort(_("new bookmark name required"))
1097 raise error.Abort(_("new bookmark name required"))
1098 elif len(names) > 1:
1098 elif len(names) > 1:
1099 raise error.Abort(_("only one new bookmark name allowed"))
1099 raise error.Abort(_("only one new bookmark name allowed"))
1100 mark = checkformat(names[0])
1100 mark = checkformat(names[0])
1101 if rename not in marks:
1101 if rename not in marks:
1102 raise error.Abort(_("bookmark '%s' does not exist")
1102 raise error.Abort(_("bookmark '%s' does not exist")
1103 % rename)
1103 % rename)
1104 checkconflict(repo, mark, cur, force)
1104 checkconflict(repo, mark, cur, force)
1105 marks[mark] = marks[rename]
1105 marks[mark] = marks[rename]
1106 if repo._activebookmark == rename and not inactive:
1106 if repo._activebookmark == rename and not inactive:
1107 bookmarks.activate(repo, mark)
1107 bookmarks.activate(repo, mark)
1108 del marks[rename]
1108 del marks[rename]
1109 elif names:
1109 elif names:
1110 tr = repo.transaction('bookmark')
1110 tr = repo.transaction('bookmark')
1111 newact = None
1111 newact = None
1112 for mark in names:
1112 for mark in names:
1113 mark = checkformat(mark)
1113 mark = checkformat(mark)
1114 if newact is None:
1114 if newact is None:
1115 newact = mark
1115 newact = mark
1116 if inactive and mark == repo._activebookmark:
1116 if inactive and mark == repo._activebookmark:
1117 bookmarks.deactivate(repo)
1117 bookmarks.deactivate(repo)
1118 return
1118 return
1119 tgt = cur
1119 tgt = cur
1120 if rev:
1120 if rev:
1121 tgt = scmutil.revsingle(repo, rev).node()
1121 tgt = scmutil.revsingle(repo, rev).node()
1122 checkconflict(repo, mark, cur, force, tgt)
1122 checkconflict(repo, mark, cur, force, tgt)
1123 marks[mark] = tgt
1123 marks[mark] = tgt
1124 if not inactive and cur == marks[newact] and not rev:
1124 if not inactive and cur == marks[newact] and not rev:
1125 bookmarks.activate(repo, newact)
1125 bookmarks.activate(repo, newact)
1126 elif cur != tgt and newact == repo._activebookmark:
1126 elif cur != tgt and newact == repo._activebookmark:
1127 bookmarks.deactivate(repo)
1127 bookmarks.deactivate(repo)
1128 elif inactive:
1128 elif inactive:
1129 if len(marks) == 0:
1129 if len(marks) == 0:
1130 ui.status(_("no bookmarks set\n"))
1130 ui.status(_("no bookmarks set\n"))
1131 elif not repo._activebookmark:
1131 elif not repo._activebookmark:
1132 ui.status(_("no active bookmark\n"))
1132 ui.status(_("no active bookmark\n"))
1133 else:
1133 else:
1134 bookmarks.deactivate(repo)
1134 bookmarks.deactivate(repo)
1135 if tr is not None:
1135 if tr is not None:
1136 marks.recordchange(tr)
1136 marks.recordchange(tr)
1137 tr.close()
1137 tr.close()
1138 finally:
1138 finally:
1139 lockmod.release(tr, lock, wlock)
1139 lockmod.release(tr, lock, wlock)
1140 else: # show bookmarks
1140 else: # show bookmarks
1141 fm = ui.formatter('bookmarks', opts)
1141 fm = ui.formatter('bookmarks', opts)
1142 hexfn = fm.hexfunc
1142 hexfn = fm.hexfunc
1143 marks = repo._bookmarks
1143 marks = repo._bookmarks
1144 if len(marks) == 0 and not fm:
1144 if len(marks) == 0 and not fm:
1145 ui.status(_("no bookmarks set\n"))
1145 ui.status(_("no bookmarks set\n"))
1146 for bmark, n in sorted(marks.iteritems()):
1146 for bmark, n in sorted(marks.iteritems()):
1147 active = repo._activebookmark
1147 active = repo._activebookmark
1148 if bmark == active:
1148 if bmark == active:
1149 prefix, label = '*', activebookmarklabel
1149 prefix, label = '*', activebookmarklabel
1150 else:
1150 else:
1151 prefix, label = ' ', ''
1151 prefix, label = ' ', ''
1152
1152
1153 fm.startitem()
1153 fm.startitem()
1154 if not ui.quiet:
1154 if not ui.quiet:
1155 fm.plain(' %s ' % prefix, label=label)
1155 fm.plain(' %s ' % prefix, label=label)
1156 fm.write('bookmark', '%s', bmark, label=label)
1156 fm.write('bookmark', '%s', bmark, label=label)
1157 pad = " " * (25 - encoding.colwidth(bmark))
1157 pad = " " * (25 - encoding.colwidth(bmark))
1158 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1158 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1159 repo.changelog.rev(n), hexfn(n), label=label)
1159 repo.changelog.rev(n), hexfn(n), label=label)
1160 fm.data(active=(bmark == active))
1160 fm.data(active=(bmark == active))
1161 fm.plain('\n')
1161 fm.plain('\n')
1162 fm.end()
1162 fm.end()
1163
1163
1164 @command('branch',
1164 @command('branch',
1165 [('f', 'force', None,
1165 [('f', 'force', None,
1166 _('set branch name even if it shadows an existing branch')),
1166 _('set branch name even if it shadows an existing branch')),
1167 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1167 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1168 _('[-fC] [NAME]'))
1168 _('[-fC] [NAME]'))
1169 def branch(ui, repo, label=None, **opts):
1169 def branch(ui, repo, label=None, **opts):
1170 """set or show the current branch name
1170 """set or show the current branch name
1171
1171
1172 .. note::
1172 .. note::
1173
1173
1174 Branch names are permanent and global. Use :hg:`bookmark` to create a
1174 Branch names are permanent and global. Use :hg:`bookmark` to create a
1175 light-weight bookmark instead. See :hg:`help glossary` for more
1175 light-weight bookmark instead. See :hg:`help glossary` for more
1176 information about named branches and bookmarks.
1176 information about named branches and bookmarks.
1177
1177
1178 With no argument, show the current branch name. With one argument,
1178 With no argument, show the current branch name. With one argument,
1179 set the working directory branch name (the branch will not exist
1179 set the working directory branch name (the branch will not exist
1180 in the repository until the next commit). Standard practice
1180 in the repository until the next commit). Standard practice
1181 recommends that primary development take place on the 'default'
1181 recommends that primary development take place on the 'default'
1182 branch.
1182 branch.
1183
1183
1184 Unless -f/--force is specified, branch will not let you set a
1184 Unless -f/--force is specified, branch will not let you set a
1185 branch name that already exists.
1185 branch name that already exists.
1186
1186
1187 Use -C/--clean to reset the working directory branch to that of
1187 Use -C/--clean to reset the working directory branch to that of
1188 the parent of the working directory, negating a previous branch
1188 the parent of the working directory, negating a previous branch
1189 change.
1189 change.
1190
1190
1191 Use the command :hg:`update` to switch to an existing branch. Use
1191 Use the command :hg:`update` to switch to an existing branch. Use
1192 :hg:`commit --close-branch` to mark this branch head as closed.
1192 :hg:`commit --close-branch` to mark this branch head as closed.
1193 When all heads of a branch are closed, the branch will be
1193 When all heads of a branch are closed, the branch will be
1194 considered closed.
1194 considered closed.
1195
1195
1196 Returns 0 on success.
1196 Returns 0 on success.
1197 """
1197 """
1198 if label:
1198 if label:
1199 label = label.strip()
1199 label = label.strip()
1200
1200
1201 if not opts.get('clean') and not label:
1201 if not opts.get('clean') and not label:
1202 ui.write("%s\n" % repo.dirstate.branch())
1202 ui.write("%s\n" % repo.dirstate.branch())
1203 return
1203 return
1204
1204
1205 with repo.wlock():
1205 with repo.wlock():
1206 if opts.get('clean'):
1206 if opts.get('clean'):
1207 label = repo[None].p1().branch()
1207 label = repo[None].p1().branch()
1208 repo.dirstate.setbranch(label)
1208 repo.dirstate.setbranch(label)
1209 ui.status(_('reset working directory to branch %s\n') % label)
1209 ui.status(_('reset working directory to branch %s\n') % label)
1210 elif label:
1210 elif label:
1211 if not opts.get('force') and label in repo.branchmap():
1211 if not opts.get('force') and label in repo.branchmap():
1212 if label not in [p.branch() for p in repo[None].parents()]:
1212 if label not in [p.branch() for p in repo[None].parents()]:
1213 raise error.Abort(_('a branch of the same name already'
1213 raise error.Abort(_('a branch of the same name already'
1214 ' exists'),
1214 ' exists'),
1215 # i18n: "it" refers to an existing branch
1215 # i18n: "it" refers to an existing branch
1216 hint=_("use 'hg update' to switch to it"))
1216 hint=_("use 'hg update' to switch to it"))
1217 scmutil.checknewlabel(repo, label, 'branch')
1217 scmutil.checknewlabel(repo, label, 'branch')
1218 repo.dirstate.setbranch(label)
1218 repo.dirstate.setbranch(label)
1219 ui.status(_('marked working directory as branch %s\n') % label)
1219 ui.status(_('marked working directory as branch %s\n') % label)
1220
1220
1221 # find any open named branches aside from default
1221 # find any open named branches aside from default
1222 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1222 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1223 if n != "default" and not c]
1223 if n != "default" and not c]
1224 if not others:
1224 if not others:
1225 ui.status(_('(branches are permanent and global, '
1225 ui.status(_('(branches are permanent and global, '
1226 'did you want a bookmark?)\n'))
1226 'did you want a bookmark?)\n'))
1227
1227
1228 @command('branches',
1228 @command('branches',
1229 [('a', 'active', False,
1229 [('a', 'active', False,
1230 _('show only branches that have unmerged heads (DEPRECATED)')),
1230 _('show only branches that have unmerged heads (DEPRECATED)')),
1231 ('c', 'closed', False, _('show normal and closed branches')),
1231 ('c', 'closed', False, _('show normal and closed branches')),
1232 ] + formatteropts,
1232 ] + formatteropts,
1233 _('[-ac]'))
1233 _('[-ac]'))
1234 def branches(ui, repo, active=False, closed=False, **opts):
1234 def branches(ui, repo, active=False, closed=False, **opts):
1235 """list repository named branches
1235 """list repository named branches
1236
1236
1237 List the repository's named branches, indicating which ones are
1237 List the repository's named branches, indicating which ones are
1238 inactive. If -c/--closed is specified, also list branches which have
1238 inactive. If -c/--closed is specified, also list branches which have
1239 been marked closed (see :hg:`commit --close-branch`).
1239 been marked closed (see :hg:`commit --close-branch`).
1240
1240
1241 Use the command :hg:`update` to switch to an existing branch.
1241 Use the command :hg:`update` to switch to an existing branch.
1242
1242
1243 Returns 0.
1243 Returns 0.
1244 """
1244 """
1245
1245
1246 fm = ui.formatter('branches', opts)
1246 fm = ui.formatter('branches', opts)
1247 hexfunc = fm.hexfunc
1247 hexfunc = fm.hexfunc
1248
1248
1249 allheads = set(repo.heads())
1249 allheads = set(repo.heads())
1250 branches = []
1250 branches = []
1251 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1251 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1252 isactive = not isclosed and bool(set(heads) & allheads)
1252 isactive = not isclosed and bool(set(heads) & allheads)
1253 branches.append((tag, repo[tip], isactive, not isclosed))
1253 branches.append((tag, repo[tip], isactive, not isclosed))
1254 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1254 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1255 reverse=True)
1255 reverse=True)
1256
1256
1257 for tag, ctx, isactive, isopen in branches:
1257 for tag, ctx, isactive, isopen in branches:
1258 if active and not isactive:
1258 if active and not isactive:
1259 continue
1259 continue
1260 if isactive:
1260 if isactive:
1261 label = 'branches.active'
1261 label = 'branches.active'
1262 notice = ''
1262 notice = ''
1263 elif not isopen:
1263 elif not isopen:
1264 if not closed:
1264 if not closed:
1265 continue
1265 continue
1266 label = 'branches.closed'
1266 label = 'branches.closed'
1267 notice = _(' (closed)')
1267 notice = _(' (closed)')
1268 else:
1268 else:
1269 label = 'branches.inactive'
1269 label = 'branches.inactive'
1270 notice = _(' (inactive)')
1270 notice = _(' (inactive)')
1271 current = (tag == repo.dirstate.branch())
1271 current = (tag == repo.dirstate.branch())
1272 if current:
1272 if current:
1273 label = 'branches.current'
1273 label = 'branches.current'
1274
1274
1275 fm.startitem()
1275 fm.startitem()
1276 fm.write('branch', '%s', tag, label=label)
1276 fm.write('branch', '%s', tag, label=label)
1277 rev = ctx.rev()
1277 rev = ctx.rev()
1278 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1278 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1279 fmt = ' ' * padsize + ' %d:%s'
1279 fmt = ' ' * padsize + ' %d:%s'
1280 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1280 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1281 label='log.changeset changeset.%s' % ctx.phasestr())
1281 label='log.changeset changeset.%s' % ctx.phasestr())
1282 fm.data(active=isactive, closed=not isopen, current=current)
1282 fm.data(active=isactive, closed=not isopen, current=current)
1283 if not ui.quiet:
1283 if not ui.quiet:
1284 fm.plain(notice)
1284 fm.plain(notice)
1285 fm.plain('\n')
1285 fm.plain('\n')
1286 fm.end()
1286 fm.end()
1287
1287
1288 @command('bundle',
1288 @command('bundle',
1289 [('f', 'force', None, _('run even when the destination is unrelated')),
1289 [('f', 'force', None, _('run even when the destination is unrelated')),
1290 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1290 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1291 _('REV')),
1291 _('REV')),
1292 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1292 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1293 _('BRANCH')),
1293 _('BRANCH')),
1294 ('', 'base', [],
1294 ('', 'base', [],
1295 _('a base changeset assumed to be available at the destination'),
1295 _('a base changeset assumed to be available at the destination'),
1296 _('REV')),
1296 _('REV')),
1297 ('a', 'all', None, _('bundle all changesets in the repository')),
1297 ('a', 'all', None, _('bundle all changesets in the repository')),
1298 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1298 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1299 ] + remoteopts,
1299 ] + remoteopts,
1300 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1300 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1301 def bundle(ui, repo, fname, dest=None, **opts):
1301 def bundle(ui, repo, fname, dest=None, **opts):
1302 """create a changegroup file
1302 """create a changegroup file
1303
1303
1304 Generate a changegroup file collecting changesets to be added
1304 Generate a changegroup file collecting changesets to be added
1305 to a repository.
1305 to a repository.
1306
1306
1307 To create a bundle containing all changesets, use -a/--all
1307 To create a bundle containing all changesets, use -a/--all
1308 (or --base null). Otherwise, hg assumes the destination will have
1308 (or --base null). Otherwise, hg assumes the destination will have
1309 all the nodes you specify with --base parameters. Otherwise, hg
1309 all the nodes you specify with --base parameters. Otherwise, hg
1310 will assume the repository has all the nodes in destination, or
1310 will assume the repository has all the nodes in destination, or
1311 default-push/default if no destination is specified.
1311 default-push/default if no destination is specified.
1312
1312
1313 You can change bundle format with the -t/--type option. You can
1313 You can change bundle format with the -t/--type option. You can
1314 specify a compression, a bundle version or both using a dash
1314 specify a compression, a bundle version or both using a dash
1315 (comp-version). The available compression methods are: none, bzip2,
1315 (comp-version). The available compression methods are: none, bzip2,
1316 and gzip (by default, bundles are compressed using bzip2). The
1316 and gzip (by default, bundles are compressed using bzip2). The
1317 available formats are: v1, v2 (default to most suitable).
1317 available formats are: v1, v2 (default to most suitable).
1318
1318
1319 The bundle file can then be transferred using conventional means
1319 The bundle file can then be transferred using conventional means
1320 and applied to another repository with the unbundle or pull
1320 and applied to another repository with the unbundle or pull
1321 command. This is useful when direct push and pull are not
1321 command. This is useful when direct push and pull are not
1322 available or when exporting an entire repository is undesirable.
1322 available or when exporting an entire repository is undesirable.
1323
1323
1324 Applying bundles preserves all changeset contents including
1324 Applying bundles preserves all changeset contents including
1325 permissions, copy/rename information, and revision history.
1325 permissions, copy/rename information, and revision history.
1326
1326
1327 Returns 0 on success, 1 if no changes found.
1327 Returns 0 on success, 1 if no changes found.
1328 """
1328 """
1329 revs = None
1329 revs = None
1330 if 'rev' in opts:
1330 if 'rev' in opts:
1331 revs = scmutil.revrange(repo, opts['rev'])
1331 revs = scmutil.revrange(repo, opts['rev'])
1332
1332
1333 bundletype = opts.get('type', 'bzip2').lower()
1333 bundletype = opts.get('type', 'bzip2').lower()
1334 try:
1334 try:
1335 bcompression, cgversion, params = exchange.parsebundlespec(
1335 bcompression, cgversion, params = exchange.parsebundlespec(
1336 repo, bundletype, strict=False)
1336 repo, bundletype, strict=False)
1337 except error.UnsupportedBundleSpecification as e:
1337 except error.UnsupportedBundleSpecification as e:
1338 raise error.Abort(str(e),
1338 raise error.Abort(str(e),
1339 hint=_('see "hg help bundle" for supported '
1339 hint=_('see "hg help bundle" for supported '
1340 'values for --type'))
1340 'values for --type'))
1341
1341
1342 # Packed bundles are a pseudo bundle format for now.
1342 # Packed bundles are a pseudo bundle format for now.
1343 if cgversion == 's1':
1343 if cgversion == 's1':
1344 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1344 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1345 hint=_('use "hg debugcreatestreamclonebundle"'))
1345 hint=_('use "hg debugcreatestreamclonebundle"'))
1346
1346
1347 if opts.get('all'):
1347 if opts.get('all'):
1348 if dest:
1348 if dest:
1349 raise error.Abort(_("--all is incompatible with specifying "
1349 raise error.Abort(_("--all is incompatible with specifying "
1350 "a destination"))
1350 "a destination"))
1351 if opts.get('base'):
1351 if opts.get('base'):
1352 ui.warn(_("ignoring --base because --all was specified\n"))
1352 ui.warn(_("ignoring --base because --all was specified\n"))
1353 base = ['null']
1353 base = ['null']
1354 else:
1354 else:
1355 base = scmutil.revrange(repo, opts.get('base'))
1355 base = scmutil.revrange(repo, opts.get('base'))
1356 # TODO: get desired bundlecaps from command line.
1356 # TODO: get desired bundlecaps from command line.
1357 bundlecaps = None
1357 bundlecaps = None
1358 if base:
1358 if base:
1359 if dest:
1359 if dest:
1360 raise error.Abort(_("--base is incompatible with specifying "
1360 raise error.Abort(_("--base is incompatible with specifying "
1361 "a destination"))
1361 "a destination"))
1362 common = [repo.lookup(rev) for rev in base]
1362 common = [repo.lookup(rev) for rev in base]
1363 heads = revs and map(repo.lookup, revs) or revs
1363 heads = revs and map(repo.lookup, revs) or revs
1364 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1364 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1365 common=common, bundlecaps=bundlecaps,
1365 common=common, bundlecaps=bundlecaps,
1366 version=cgversion)
1366 version=cgversion)
1367 outgoing = None
1367 outgoing = None
1368 else:
1368 else:
1369 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1369 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1370 dest, branches = hg.parseurl(dest, opts.get('branch'))
1370 dest, branches = hg.parseurl(dest, opts.get('branch'))
1371 other = hg.peer(repo, opts, dest)
1371 other = hg.peer(repo, opts, dest)
1372 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1372 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1373 heads = revs and map(repo.lookup, revs) or revs
1373 heads = revs and map(repo.lookup, revs) or revs
1374 outgoing = discovery.findcommonoutgoing(repo, other,
1374 outgoing = discovery.findcommonoutgoing(repo, other,
1375 onlyheads=heads,
1375 onlyheads=heads,
1376 force=opts.get('force'),
1376 force=opts.get('force'),
1377 portable=True)
1377 portable=True)
1378 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1378 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1379 bundlecaps, version=cgversion)
1379 bundlecaps, version=cgversion)
1380 if not cg:
1380 if not cg:
1381 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1381 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1382 return 1
1382 return 1
1383
1383
1384 if cgversion == '01': #bundle1
1384 if cgversion == '01': #bundle1
1385 if bcompression is None:
1385 if bcompression is None:
1386 bcompression = 'UN'
1386 bcompression = 'UN'
1387 bversion = 'HG10' + bcompression
1387 bversion = 'HG10' + bcompression
1388 bcompression = None
1388 bcompression = None
1389 else:
1389 else:
1390 assert cgversion == '02'
1390 assert cgversion == '02'
1391 bversion = 'HG20'
1391 bversion = 'HG20'
1392
1392
1393
1393
1394 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1394 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1395
1395
1396 @command('cat',
1396 @command('cat',
1397 [('o', 'output', '',
1397 [('o', 'output', '',
1398 _('print output to file with formatted name'), _('FORMAT')),
1398 _('print output to file with formatted name'), _('FORMAT')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1399 ('r', 'rev', '', _('print the given revision'), _('REV')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1400 ('', 'decode', None, _('apply any matching decode filter')),
1401 ] + walkopts,
1401 ] + walkopts,
1402 _('[OPTION]... FILE...'),
1402 _('[OPTION]... FILE...'),
1403 inferrepo=True)
1403 inferrepo=True)
1404 def cat(ui, repo, file1, *pats, **opts):
1404 def cat(ui, repo, file1, *pats, **opts):
1405 """output the current or given revision of files
1405 """output the current or given revision of files
1406
1406
1407 Print the specified files as they were at the given revision. If
1407 Print the specified files as they were at the given revision. If
1408 no revision is given, the parent of the working directory is used.
1408 no revision is given, the parent of the working directory is used.
1409
1409
1410 Output may be to a file, in which case the name of the file is
1410 Output may be to a file, in which case the name of the file is
1411 given using a format string. The formatting rules as follows:
1411 given using a format string. The formatting rules as follows:
1412
1412
1413 :``%%``: literal "%" character
1413 :``%%``: literal "%" character
1414 :``%s``: basename of file being printed
1414 :``%s``: basename of file being printed
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1415 :``%d``: dirname of file being printed, or '.' if in repository root
1416 :``%p``: root-relative path name of file being printed
1416 :``%p``: root-relative path name of file being printed
1417 :``%H``: changeset hash (40 hexadecimal digits)
1417 :``%H``: changeset hash (40 hexadecimal digits)
1418 :``%R``: changeset revision number
1418 :``%R``: changeset revision number
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1419 :``%h``: short-form changeset hash (12 hexadecimal digits)
1420 :``%r``: zero-padded changeset revision number
1420 :``%r``: zero-padded changeset revision number
1421 :``%b``: basename of the exporting repository
1421 :``%b``: basename of the exporting repository
1422
1422
1423 Returns 0 on success.
1423 Returns 0 on success.
1424 """
1424 """
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1425 ctx = scmutil.revsingle(repo, opts.get('rev'))
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1426 m = scmutil.match(ctx, (file1,) + pats, opts)
1427
1427
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1429
1429
1430 @command('^clone',
1430 @command('^clone',
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1432 'directory (only a repository)')),
1432 'directory (only a repository)')),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1434 _('REV')),
1434 _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1439 ] + remoteopts,
1439 ] + remoteopts,
1440 _('[OPTION]... SOURCE [DEST]'),
1440 _('[OPTION]... SOURCE [DEST]'),
1441 norepo=True)
1441 norepo=True)
1442 def clone(ui, source, dest=None, **opts):
1442 def clone(ui, source, dest=None, **opts):
1443 """make a copy of an existing repository
1443 """make a copy of an existing repository
1444
1444
1445 Create a copy of an existing repository in a new directory.
1445 Create a copy of an existing repository in a new directory.
1446
1446
1447 If no destination directory name is specified, it defaults to the
1447 If no destination directory name is specified, it defaults to the
1448 basename of the source.
1448 basename of the source.
1449
1449
1450 The location of the source is added to the new repository's
1450 The location of the source is added to the new repository's
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1452
1452
1453 Only local paths and ``ssh://`` URLs are supported as
1453 Only local paths and ``ssh://`` URLs are supported as
1454 destinations. For ``ssh://`` destinations, no working directory or
1454 destinations. For ``ssh://`` destinations, no working directory or
1455 ``.hg/hgrc`` will be created on the remote side.
1455 ``.hg/hgrc`` will be created on the remote side.
1456
1456
1457 If the source repository has a bookmark called '@' set, that
1457 If the source repository has a bookmark called '@' set, that
1458 revision will be checked out in the new repository by default.
1458 revision will be checked out in the new repository by default.
1459
1459
1460 To check out a particular version, use -u/--update, or
1460 To check out a particular version, use -u/--update, or
1461 -U/--noupdate to create a clone with no working directory.
1461 -U/--noupdate to create a clone with no working directory.
1462
1462
1463 To pull only a subset of changesets, specify one or more revisions
1463 To pull only a subset of changesets, specify one or more revisions
1464 identifiers with -r/--rev or branches with -b/--branch. The
1464 identifiers with -r/--rev or branches with -b/--branch. The
1465 resulting clone will contain only the specified changesets and
1465 resulting clone will contain only the specified changesets and
1466 their ancestors. These options (or 'clone src#rev dest') imply
1466 their ancestors. These options (or 'clone src#rev dest') imply
1467 --pull, even for local source repositories.
1467 --pull, even for local source repositories.
1468
1468
1469 .. note::
1469 .. note::
1470
1470
1471 Specifying a tag will include the tagged changeset but not the
1471 Specifying a tag will include the tagged changeset but not the
1472 changeset containing the tag.
1472 changeset containing the tag.
1473
1473
1474 .. container:: verbose
1474 .. container:: verbose
1475
1475
1476 For efficiency, hardlinks are used for cloning whenever the
1476 For efficiency, hardlinks are used for cloning whenever the
1477 source and destination are on the same filesystem (note this
1477 source and destination are on the same filesystem (note this
1478 applies only to the repository data, not to the working
1478 applies only to the repository data, not to the working
1479 directory). Some filesystems, such as AFS, implement hardlinking
1479 directory). Some filesystems, such as AFS, implement hardlinking
1480 incorrectly, but do not report errors. In these cases, use the
1480 incorrectly, but do not report errors. In these cases, use the
1481 --pull option to avoid hardlinking.
1481 --pull option to avoid hardlinking.
1482
1482
1483 In some cases, you can clone repositories and the working
1483 In some cases, you can clone repositories and the working
1484 directory using full hardlinks with ::
1484 directory using full hardlinks with ::
1485
1485
1486 $ cp -al REPO REPOCLONE
1486 $ cp -al REPO REPOCLONE
1487
1487
1488 This is the fastest way to clone, but it is not always safe. The
1488 This is the fastest way to clone, but it is not always safe. The
1489 operation is not atomic (making sure REPO is not modified during
1489 operation is not atomic (making sure REPO is not modified during
1490 the operation is up to you) and you have to make sure your
1490 the operation is up to you) and you have to make sure your
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1492 so). Also, this is not compatible with certain extensions that
1492 so). Also, this is not compatible with certain extensions that
1493 place their metadata under the .hg directory, such as mq.
1493 place their metadata under the .hg directory, such as mq.
1494
1494
1495 Mercurial will update the working directory to the first applicable
1495 Mercurial will update the working directory to the first applicable
1496 revision from this list:
1496 revision from this list:
1497
1497
1498 a) null if -U or the source repository has no changesets
1498 a) null if -U or the source repository has no changesets
1499 b) if -u . and the source repository is local, the first parent of
1499 b) if -u . and the source repository is local, the first parent of
1500 the source repository's working directory
1500 the source repository's working directory
1501 c) the changeset specified with -u (if a branch name, this means the
1501 c) the changeset specified with -u (if a branch name, this means the
1502 latest head of that branch)
1502 latest head of that branch)
1503 d) the changeset specified with -r
1503 d) the changeset specified with -r
1504 e) the tipmost head specified with -b
1504 e) the tipmost head specified with -b
1505 f) the tipmost head specified with the url#branch source syntax
1505 f) the tipmost head specified with the url#branch source syntax
1506 g) the revision marked with the '@' bookmark, if present
1506 g) the revision marked with the '@' bookmark, if present
1507 h) the tipmost head of the default branch
1507 h) the tipmost head of the default branch
1508 i) tip
1508 i) tip
1509
1509
1510 When cloning from servers that support it, Mercurial may fetch
1510 When cloning from servers that support it, Mercurial may fetch
1511 pre-generated data from a server-advertised URL. When this is done,
1511 pre-generated data from a server-advertised URL. When this is done,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1513 once for the bundle fetched from the URL and another for any additional
1513 once for the bundle fetched from the URL and another for any additional
1514 data not fetched from this URL. In addition, if an error occurs, the
1514 data not fetched from this URL. In addition, if an error occurs, the
1515 repository may be rolled back to a partial clone. This behavior may
1515 repository may be rolled back to a partial clone. This behavior may
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1517
1517
1518 Examples:
1518 Examples:
1519
1519
1520 - clone a remote repository to a new directory named hg/::
1520 - clone a remote repository to a new directory named hg/::
1521
1521
1522 hg clone http://selenic.com/hg
1522 hg clone http://selenic.com/hg
1523
1523
1524 - create a lightweight local clone::
1524 - create a lightweight local clone::
1525
1525
1526 hg clone project/ project-feature/
1526 hg clone project/ project-feature/
1527
1527
1528 - clone from an absolute path on an ssh server (note double-slash)::
1528 - clone from an absolute path on an ssh server (note double-slash)::
1529
1529
1530 hg clone ssh://user@server//home/projects/alpha/
1530 hg clone ssh://user@server//home/projects/alpha/
1531
1531
1532 - do a high-speed clone over a LAN while checking out a
1532 - do a high-speed clone over a LAN while checking out a
1533 specified version::
1533 specified version::
1534
1534
1535 hg clone --uncompressed http://server/repo -u 1.5
1535 hg clone --uncompressed http://server/repo -u 1.5
1536
1536
1537 - create a repository without changesets after a particular revision::
1537 - create a repository without changesets after a particular revision::
1538
1538
1539 hg clone -r 04e544 experimental/ good/
1539 hg clone -r 04e544 experimental/ good/
1540
1540
1541 - clone (and track) a particular named branch::
1541 - clone (and track) a particular named branch::
1542
1542
1543 hg clone http://selenic.com/hg#stable
1543 hg clone http://selenic.com/hg#stable
1544
1544
1545 See :hg:`help urls` for details on specifying URLs.
1545 See :hg:`help urls` for details on specifying URLs.
1546
1546
1547 Returns 0 on success.
1547 Returns 0 on success.
1548 """
1548 """
1549 if opts.get('noupdate') and opts.get('updaterev'):
1549 if opts.get('noupdate') and opts.get('updaterev'):
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1551
1551
1552 r = hg.clone(ui, opts, source, dest,
1552 r = hg.clone(ui, opts, source, dest,
1553 pull=opts.get('pull'),
1553 pull=opts.get('pull'),
1554 stream=opts.get('uncompressed'),
1554 stream=opts.get('uncompressed'),
1555 rev=opts.get('rev'),
1555 rev=opts.get('rev'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1557 branch=opts.get('branch'),
1557 branch=opts.get('branch'),
1558 shareopts=opts.get('shareopts'))
1558 shareopts=opts.get('shareopts'))
1559
1559
1560 return r is None
1560 return r is None
1561
1561
1562 @command('^commit|ci',
1562 @command('^commit|ci',
1563 [('A', 'addremove', None,
1563 [('A', 'addremove', None,
1564 _('mark new/missing files as added/removed before committing')),
1564 _('mark new/missing files as added/removed before committing')),
1565 ('', 'close-branch', None,
1565 ('', 'close-branch', None,
1566 _('mark a branch head as closed')),
1566 _('mark a branch head as closed')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1572 _('[OPTION]... [FILE]...'),
1572 _('[OPTION]... [FILE]...'),
1573 inferrepo=True)
1573 inferrepo=True)
1574 def commit(ui, repo, *pats, **opts):
1574 def commit(ui, repo, *pats, **opts):
1575 """commit the specified files or all outstanding changes
1575 """commit the specified files or all outstanding changes
1576
1576
1577 Commit changes to the given files into the repository. Unlike a
1577 Commit changes to the given files into the repository. Unlike a
1578 centralized SCM, this operation is a local operation. See
1578 centralized SCM, this operation is a local operation. See
1579 :hg:`push` for a way to actively distribute your changes.
1579 :hg:`push` for a way to actively distribute your changes.
1580
1580
1581 If a list of files is omitted, all changes reported by :hg:`status`
1581 If a list of files is omitted, all changes reported by :hg:`status`
1582 will be committed.
1582 will be committed.
1583
1583
1584 If you are committing the result of a merge, do not provide any
1584 If you are committing the result of a merge, do not provide any
1585 filenames or -I/-X filters.
1585 filenames or -I/-X filters.
1586
1586
1587 If no commit message is specified, Mercurial starts your
1587 If no commit message is specified, Mercurial starts your
1588 configured editor where you can enter a message. In case your
1588 configured editor where you can enter a message. In case your
1589 commit fails, you will find a backup of your message in
1589 commit fails, you will find a backup of your message in
1590 ``.hg/last-message.txt``.
1590 ``.hg/last-message.txt``.
1591
1591
1592 The --close-branch flag can be used to mark the current branch
1592 The --close-branch flag can be used to mark the current branch
1593 head closed. When all heads of a branch are closed, the branch
1593 head closed. When all heads of a branch are closed, the branch
1594 will be considered closed and no longer listed.
1594 will be considered closed and no longer listed.
1595
1595
1596 The --amend flag can be used to amend the parent of the
1596 The --amend flag can be used to amend the parent of the
1597 working directory with a new commit that contains the changes
1597 working directory with a new commit that contains the changes
1598 in the parent in addition to those currently reported by :hg:`status`,
1598 in the parent in addition to those currently reported by :hg:`status`,
1599 if there are any. The old commit is stored in a backup bundle in
1599 if there are any. The old commit is stored in a backup bundle in
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1601 on how to restore it).
1601 on how to restore it).
1602
1602
1603 Message, user and date are taken from the amended commit unless
1603 Message, user and date are taken from the amended commit unless
1604 specified. When a message isn't specified on the command line,
1604 specified. When a message isn't specified on the command line,
1605 the editor will open with the message of the amended commit.
1605 the editor will open with the message of the amended commit.
1606
1606
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1608 or changesets that have children.
1608 or changesets that have children.
1609
1609
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1611
1611
1612 Returns 0 on success, 1 if nothing changed.
1612 Returns 0 on success, 1 if nothing changed.
1613
1613
1614 .. container:: verbose
1614 .. container:: verbose
1615
1615
1616 Examples:
1616 Examples:
1617
1617
1618 - commit all files ending in .py::
1618 - commit all files ending in .py::
1619
1619
1620 hg commit --include "set:**.py"
1620 hg commit --include "set:**.py"
1621
1621
1622 - commit all non-binary files::
1622 - commit all non-binary files::
1623
1623
1624 hg commit --exclude "set:binary()"
1624 hg commit --exclude "set:binary()"
1625
1625
1626 - amend the current commit and set the date to now::
1626 - amend the current commit and set the date to now::
1627
1627
1628 hg commit --amend --date now
1628 hg commit --amend --date now
1629 """
1629 """
1630 wlock = lock = None
1630 wlock = lock = None
1631 try:
1631 try:
1632 wlock = repo.wlock()
1632 wlock = repo.wlock()
1633 lock = repo.lock()
1633 lock = repo.lock()
1634 return _docommit(ui, repo, *pats, **opts)
1634 return _docommit(ui, repo, *pats, **opts)
1635 finally:
1635 finally:
1636 release(lock, wlock)
1636 release(lock, wlock)
1637
1637
1638 def _docommit(ui, repo, *pats, **opts):
1638 def _docommit(ui, repo, *pats, **opts):
1639 if opts.get('interactive'):
1639 if opts.get('interactive'):
1640 opts.pop('interactive')
1640 opts.pop('interactive')
1641 cmdutil.dorecord(ui, repo, commit, None, False,
1641 cmdutil.dorecord(ui, repo, commit, None, False,
1642 cmdutil.recordfilter, *pats, **opts)
1642 cmdutil.recordfilter, *pats, **opts)
1643 return
1643 return
1644
1644
1645 if opts.get('subrepos'):
1645 if opts.get('subrepos'):
1646 if opts.get('amend'):
1646 if opts.get('amend'):
1647 raise error.Abort(_('cannot amend with --subrepos'))
1647 raise error.Abort(_('cannot amend with --subrepos'))
1648 # Let --subrepos on the command line override config setting.
1648 # Let --subrepos on the command line override config setting.
1649 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1649 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1650
1650
1651 cmdutil.checkunfinished(repo, commit=True)
1651 cmdutil.checkunfinished(repo, commit=True)
1652
1652
1653 branch = repo[None].branch()
1653 branch = repo[None].branch()
1654 bheads = repo.branchheads(branch)
1654 bheads = repo.branchheads(branch)
1655
1655
1656 extra = {}
1656 extra = {}
1657 if opts.get('close_branch'):
1657 if opts.get('close_branch'):
1658 extra['close'] = 1
1658 extra['close'] = 1
1659
1659
1660 if not bheads:
1660 if not bheads:
1661 raise error.Abort(_('can only close branch heads'))
1661 raise error.Abort(_('can only close branch heads'))
1662 elif opts.get('amend'):
1662 elif opts.get('amend'):
1663 if repo[None].parents()[0].p1().branch() != branch and \
1663 if repo[None].parents()[0].p1().branch() != branch and \
1664 repo[None].parents()[0].p2().branch() != branch:
1664 repo[None].parents()[0].p2().branch() != branch:
1665 raise error.Abort(_('can only close branch heads'))
1665 raise error.Abort(_('can only close branch heads'))
1666
1666
1667 if opts.get('amend'):
1667 if opts.get('amend'):
1668 if ui.configbool('ui', 'commitsubrepos'):
1668 if ui.configbool('ui', 'commitsubrepos'):
1669 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1669 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1670
1670
1671 old = repo['.']
1671 old = repo['.']
1672 if not old.mutable():
1672 if not old.mutable():
1673 raise error.Abort(_('cannot amend public changesets'))
1673 raise error.Abort(_('cannot amend public changesets'))
1674 if len(repo[None].parents()) > 1:
1674 if len(repo[None].parents()) > 1:
1675 raise error.Abort(_('cannot amend while merging'))
1675 raise error.Abort(_('cannot amend while merging'))
1676 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1676 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1677 if not allowunstable and old.children():
1677 if not allowunstable and old.children():
1678 raise error.Abort(_('cannot amend changeset with children'))
1678 raise error.Abort(_('cannot amend changeset with children'))
1679
1679
1680 newextra = extra.copy()
1680 newextra = extra.copy()
1681 newextra['branch'] = branch
1681 newextra['branch'] = branch
1682 extra = newextra
1682 extra = newextra
1683 # commitfunc is used only for temporary amend commit by cmdutil.amend
1683 # commitfunc is used only for temporary amend commit by cmdutil.amend
1684 def commitfunc(ui, repo, message, match, opts):
1684 def commitfunc(ui, repo, message, match, opts):
1685 return repo.commit(message,
1685 return repo.commit(message,
1686 opts.get('user') or old.user(),
1686 opts.get('user') or old.user(),
1687 opts.get('date') or old.date(),
1687 opts.get('date') or old.date(),
1688 match,
1688 match,
1689 extra=extra)
1689 extra=extra)
1690
1690
1691 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1691 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1692 if node == old.node():
1692 if node == old.node():
1693 ui.status(_("nothing changed\n"))
1693 ui.status(_("nothing changed\n"))
1694 return 1
1694 return 1
1695 else:
1695 else:
1696 def commitfunc(ui, repo, message, match, opts):
1696 def commitfunc(ui, repo, message, match, opts):
1697 backup = ui.backupconfig('phases', 'new-commit')
1697 backup = ui.backupconfig('phases', 'new-commit')
1698 baseui = repo.baseui
1698 baseui = repo.baseui
1699 basebackup = baseui.backupconfig('phases', 'new-commit')
1699 basebackup = baseui.backupconfig('phases', 'new-commit')
1700 try:
1700 try:
1701 if opts.get('secret'):
1701 if opts.get('secret'):
1702 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1702 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703 # Propagate to subrepos
1703 # Propagate to subrepos
1704 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1704 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1705
1705
1706 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1706 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1707 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1707 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1708 return repo.commit(message, opts.get('user'), opts.get('date'),
1708 return repo.commit(message, opts.get('user'), opts.get('date'),
1709 match,
1709 match,
1710 editor=editor,
1710 editor=editor,
1711 extra=extra)
1711 extra=extra)
1712 finally:
1712 finally:
1713 ui.restoreconfig(backup)
1713 ui.restoreconfig(backup)
1714 repo.baseui.restoreconfig(basebackup)
1714 repo.baseui.restoreconfig(basebackup)
1715
1715
1716
1716
1717 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1717 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1718
1718
1719 if not node:
1719 if not node:
1720 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1720 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1721 if stat[3]:
1721 if stat[3]:
1722 ui.status(_("nothing changed (%d missing files, see "
1722 ui.status(_("nothing changed (%d missing files, see "
1723 "'hg status')\n") % len(stat[3]))
1723 "'hg status')\n") % len(stat[3]))
1724 else:
1724 else:
1725 ui.status(_("nothing changed\n"))
1725 ui.status(_("nothing changed\n"))
1726 return 1
1726 return 1
1727
1727
1728 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1728 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1729
1729
1730 @command('config|showconfig|debugconfig',
1730 @command('config|showconfig|debugconfig',
1731 [('u', 'untrusted', None, _('show untrusted configuration options')),
1731 [('u', 'untrusted', None, _('show untrusted configuration options')),
1732 ('e', 'edit', None, _('edit user config')),
1732 ('e', 'edit', None, _('edit user config')),
1733 ('l', 'local', None, _('edit repository config')),
1733 ('l', 'local', None, _('edit repository config')),
1734 ('g', 'global', None, _('edit global config'))],
1734 ('g', 'global', None, _('edit global config'))],
1735 _('[-u] [NAME]...'),
1735 _('[-u] [NAME]...'),
1736 optionalrepo=True)
1736 optionalrepo=True)
1737 def config(ui, repo, *values, **opts):
1737 def config(ui, repo, *values, **opts):
1738 """show combined config settings from all hgrc files
1738 """show combined config settings from all hgrc files
1739
1739
1740 With no arguments, print names and values of all config items.
1740 With no arguments, print names and values of all config items.
1741
1741
1742 With one argument of the form section.name, print just the value
1742 With one argument of the form section.name, print just the value
1743 of that config item.
1743 of that config item.
1744
1744
1745 With multiple arguments, print names and values of all config
1745 With multiple arguments, print names and values of all config
1746 items with matching section names.
1746 items with matching section names.
1747
1747
1748 With --edit, start an editor on the user-level config file. With
1748 With --edit, start an editor on the user-level config file. With
1749 --global, edit the system-wide config file. With --local, edit the
1749 --global, edit the system-wide config file. With --local, edit the
1750 repository-level config file.
1750 repository-level config file.
1751
1751
1752 With --debug, the source (filename and line number) is printed
1752 With --debug, the source (filename and line number) is printed
1753 for each config item.
1753 for each config item.
1754
1754
1755 See :hg:`help config` for more information about config files.
1755 See :hg:`help config` for more information about config files.
1756
1756
1757 Returns 0 on success, 1 if NAME does not exist.
1757 Returns 0 on success, 1 if NAME does not exist.
1758
1758
1759 """
1759 """
1760
1760
1761 if opts.get('edit') or opts.get('local') or opts.get('global'):
1761 if opts.get('edit') or opts.get('local') or opts.get('global'):
1762 if opts.get('local') and opts.get('global'):
1762 if opts.get('local') and opts.get('global'):
1763 raise error.Abort(_("can't use --local and --global together"))
1763 raise error.Abort(_("can't use --local and --global together"))
1764
1764
1765 if opts.get('local'):
1765 if opts.get('local'):
1766 if not repo:
1766 if not repo:
1767 raise error.Abort(_("can't use --local outside a repository"))
1767 raise error.Abort(_("can't use --local outside a repository"))
1768 paths = [repo.join('hgrc')]
1768 paths = [repo.join('hgrc')]
1769 elif opts.get('global'):
1769 elif opts.get('global'):
1770 paths = scmutil.systemrcpath()
1770 paths = scmutil.systemrcpath()
1771 else:
1771 else:
1772 paths = scmutil.userrcpath()
1772 paths = scmutil.userrcpath()
1773
1773
1774 for f in paths:
1774 for f in paths:
1775 if os.path.exists(f):
1775 if os.path.exists(f):
1776 break
1776 break
1777 else:
1777 else:
1778 if opts.get('global'):
1778 if opts.get('global'):
1779 samplehgrc = uimod.samplehgrcs['global']
1779 samplehgrc = uimod.samplehgrcs['global']
1780 elif opts.get('local'):
1780 elif opts.get('local'):
1781 samplehgrc = uimod.samplehgrcs['local']
1781 samplehgrc = uimod.samplehgrcs['local']
1782 else:
1782 else:
1783 samplehgrc = uimod.samplehgrcs['user']
1783 samplehgrc = uimod.samplehgrcs['user']
1784
1784
1785 f = paths[0]
1785 f = paths[0]
1786 fp = open(f, "w")
1786 fp = open(f, "w")
1787 fp.write(samplehgrc)
1787 fp.write(samplehgrc)
1788 fp.close()
1788 fp.close()
1789
1789
1790 editor = ui.geteditor()
1790 editor = ui.geteditor()
1791 ui.system("%s \"%s\"" % (editor, f),
1791 ui.system("%s \"%s\"" % (editor, f),
1792 onerr=error.Abort, errprefix=_("edit failed"))
1792 onerr=error.Abort, errprefix=_("edit failed"))
1793 return
1793 return
1794
1794
1795 for f in scmutil.rcpath():
1795 for f in scmutil.rcpath():
1796 ui.debug('read config from: %s\n' % f)
1796 ui.debug('read config from: %s\n' % f)
1797 untrusted = bool(opts.get('untrusted'))
1797 untrusted = bool(opts.get('untrusted'))
1798 if values:
1798 if values:
1799 sections = [v for v in values if '.' not in v]
1799 sections = [v for v in values if '.' not in v]
1800 items = [v for v in values if '.' in v]
1800 items = [v for v in values if '.' in v]
1801 if len(items) > 1 or items and sections:
1801 if len(items) > 1 or items and sections:
1802 raise error.Abort(_('only one config item permitted'))
1802 raise error.Abort(_('only one config item permitted'))
1803 matched = False
1803 matched = False
1804 for section, name, value in ui.walkconfig(untrusted=untrusted):
1804 for section, name, value in ui.walkconfig(untrusted=untrusted):
1805 value = str(value).replace('\n', '\\n')
1805 value = str(value).replace('\n', '\\n')
1806 sectname = section + '.' + name
1806 sectname = section + '.' + name
1807 if values:
1807 if values:
1808 for v in values:
1808 for v in values:
1809 if v == section:
1809 if v == section:
1810 ui.debug('%s: ' %
1810 ui.debug('%s: ' %
1811 ui.configsource(section, name, untrusted))
1811 ui.configsource(section, name, untrusted))
1812 ui.write('%s=%s\n' % (sectname, value))
1812 ui.write('%s=%s\n' % (sectname, value))
1813 matched = True
1813 matched = True
1814 elif v == sectname:
1814 elif v == sectname:
1815 ui.debug('%s: ' %
1815 ui.debug('%s: ' %
1816 ui.configsource(section, name, untrusted))
1816 ui.configsource(section, name, untrusted))
1817 ui.write(value, '\n')
1817 ui.write(value, '\n')
1818 matched = True
1818 matched = True
1819 else:
1819 else:
1820 ui.debug('%s: ' %
1820 ui.debug('%s: ' %
1821 ui.configsource(section, name, untrusted))
1821 ui.configsource(section, name, untrusted))
1822 ui.write('%s=%s\n' % (sectname, value))
1822 ui.write('%s=%s\n' % (sectname, value))
1823 matched = True
1823 matched = True
1824 if matched:
1824 if matched:
1825 return 0
1825 return 0
1826 return 1
1826 return 1
1827
1827
1828 @command('copy|cp',
1828 @command('copy|cp',
1829 [('A', 'after', None, _('record a copy that has already occurred')),
1829 [('A', 'after', None, _('record a copy that has already occurred')),
1830 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1830 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1831 ] + walkopts + dryrunopts,
1831 ] + walkopts + dryrunopts,
1832 _('[OPTION]... [SOURCE]... DEST'))
1832 _('[OPTION]... [SOURCE]... DEST'))
1833 def copy(ui, repo, *pats, **opts):
1833 def copy(ui, repo, *pats, **opts):
1834 """mark files as copied for the next commit
1834 """mark files as copied for the next commit
1835
1835
1836 Mark dest as having copies of source files. If dest is a
1836 Mark dest as having copies of source files. If dest is a
1837 directory, copies are put in that directory. If dest is a file,
1837 directory, copies are put in that directory. If dest is a file,
1838 the source must be a single file.
1838 the source must be a single file.
1839
1839
1840 By default, this command copies the contents of files as they
1840 By default, this command copies the contents of files as they
1841 exist in the working directory. If invoked with -A/--after, the
1841 exist in the working directory. If invoked with -A/--after, the
1842 operation is recorded, but no copying is performed.
1842 operation is recorded, but no copying is performed.
1843
1843
1844 This command takes effect with the next commit. To undo a copy
1844 This command takes effect with the next commit. To undo a copy
1845 before that, see :hg:`revert`.
1845 before that, see :hg:`revert`.
1846
1846
1847 Returns 0 on success, 1 if errors are encountered.
1847 Returns 0 on success, 1 if errors are encountered.
1848 """
1848 """
1849 with repo.wlock(False):
1849 with repo.wlock(False):
1850 return cmdutil.copy(ui, repo, pats, opts)
1850 return cmdutil.copy(ui, repo, pats, opts)
1851
1851
1852 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1852 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1853 def debugancestor(ui, repo, *args):
1853 def debugancestor(ui, repo, *args):
1854 """find the ancestor revision of two revisions in a given index"""
1854 """find the ancestor revision of two revisions in a given index"""
1855 if len(args) == 3:
1855 if len(args) == 3:
1856 index, rev1, rev2 = args
1856 index, rev1, rev2 = args
1857 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1857 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1858 lookup = r.lookup
1858 lookup = r.lookup
1859 elif len(args) == 2:
1859 elif len(args) == 2:
1860 if not repo:
1860 if not repo:
1861 raise error.Abort(_("there is no Mercurial repository here "
1861 raise error.Abort(_("there is no Mercurial repository here "
1862 "(.hg not found)"))
1862 "(.hg not found)"))
1863 rev1, rev2 = args
1863 rev1, rev2 = args
1864 r = repo.changelog
1864 r = repo.changelog
1865 lookup = repo.lookup
1865 lookup = repo.lookup
1866 else:
1866 else:
1867 raise error.Abort(_('either two or three arguments required'))
1867 raise error.Abort(_('either two or three arguments required'))
1868 a = r.ancestor(lookup(rev1), lookup(rev2))
1868 a = r.ancestor(lookup(rev1), lookup(rev2))
1869 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1869 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1870
1870
1871 @command('debugbuilddag',
1871 @command('debugbuilddag',
1872 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1872 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1873 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1873 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1874 ('n', 'new-file', None, _('add new file at each rev'))],
1874 ('n', 'new-file', None, _('add new file at each rev'))],
1875 _('[OPTION]... [TEXT]'))
1875 _('[OPTION]... [TEXT]'))
1876 def debugbuilddag(ui, repo, text=None,
1876 def debugbuilddag(ui, repo, text=None,
1877 mergeable_file=False,
1877 mergeable_file=False,
1878 overwritten_file=False,
1878 overwritten_file=False,
1879 new_file=False):
1879 new_file=False):
1880 """builds a repo with a given DAG from scratch in the current empty repo
1880 """builds a repo with a given DAG from scratch in the current empty repo
1881
1881
1882 The description of the DAG is read from stdin if not given on the
1882 The description of the DAG is read from stdin if not given on the
1883 command line.
1883 command line.
1884
1884
1885 Elements:
1885 Elements:
1886
1886
1887 - "+n" is a linear run of n nodes based on the current default parent
1887 - "+n" is a linear run of n nodes based on the current default parent
1888 - "." is a single node based on the current default parent
1888 - "." is a single node based on the current default parent
1889 - "$" resets the default parent to null (implied at the start);
1889 - "$" resets the default parent to null (implied at the start);
1890 otherwise the default parent is always the last node created
1890 otherwise the default parent is always the last node created
1891 - "<p" sets the default parent to the backref p
1891 - "<p" sets the default parent to the backref p
1892 - "*p" is a fork at parent p, which is a backref
1892 - "*p" is a fork at parent p, which is a backref
1893 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1893 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1894 - "/p2" is a merge of the preceding node and p2
1894 - "/p2" is a merge of the preceding node and p2
1895 - ":tag" defines a local tag for the preceding node
1895 - ":tag" defines a local tag for the preceding node
1896 - "@branch" sets the named branch for subsequent nodes
1896 - "@branch" sets the named branch for subsequent nodes
1897 - "#...\\n" is a comment up to the end of the line
1897 - "#...\\n" is a comment up to the end of the line
1898
1898
1899 Whitespace between the above elements is ignored.
1899 Whitespace between the above elements is ignored.
1900
1900
1901 A backref is either
1901 A backref is either
1902
1902
1903 - a number n, which references the node curr-n, where curr is the current
1903 - a number n, which references the node curr-n, where curr is the current
1904 node, or
1904 node, or
1905 - the name of a local tag you placed earlier using ":tag", or
1905 - the name of a local tag you placed earlier using ":tag", or
1906 - empty to denote the default parent.
1906 - empty to denote the default parent.
1907
1907
1908 All string valued-elements are either strictly alphanumeric, or must
1908 All string valued-elements are either strictly alphanumeric, or must
1909 be enclosed in double quotes ("..."), with "\\" as escape character.
1909 be enclosed in double quotes ("..."), with "\\" as escape character.
1910 """
1910 """
1911
1911
1912 if text is None:
1912 if text is None:
1913 ui.status(_("reading DAG from stdin\n"))
1913 ui.status(_("reading DAG from stdin\n"))
1914 text = ui.fin.read()
1914 text = ui.fin.read()
1915
1915
1916 cl = repo.changelog
1916 cl = repo.changelog
1917 if len(cl) > 0:
1917 if len(cl) > 0:
1918 raise error.Abort(_('repository is not empty'))
1918 raise error.Abort(_('repository is not empty'))
1919
1919
1920 # determine number of revs in DAG
1920 # determine number of revs in DAG
1921 total = 0
1921 total = 0
1922 for type, data in dagparser.parsedag(text):
1922 for type, data in dagparser.parsedag(text):
1923 if type == 'n':
1923 if type == 'n':
1924 total += 1
1924 total += 1
1925
1925
1926 if mergeable_file:
1926 if mergeable_file:
1927 linesperrev = 2
1927 linesperrev = 2
1928 # make a file with k lines per rev
1928 # make a file with k lines per rev
1929 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1929 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1930 initialmergedlines.append("")
1930 initialmergedlines.append("")
1931
1931
1932 tags = []
1932 tags = []
1933
1933
1934 lock = tr = None
1934 lock = tr = None
1935 try:
1935 try:
1936 lock = repo.lock()
1936 lock = repo.lock()
1937 tr = repo.transaction("builddag")
1937 tr = repo.transaction("builddag")
1938
1938
1939 at = -1
1939 at = -1
1940 atbranch = 'default'
1940 atbranch = 'default'
1941 nodeids = []
1941 nodeids = []
1942 id = 0
1942 id = 0
1943 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1943 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1944 for type, data in dagparser.parsedag(text):
1944 for type, data in dagparser.parsedag(text):
1945 if type == 'n':
1945 if type == 'n':
1946 ui.note(('node %s\n' % str(data)))
1946 ui.note(('node %s\n' % str(data)))
1947 id, ps = data
1947 id, ps = data
1948
1948
1949 files = []
1949 files = []
1950 fctxs = {}
1950 fctxs = {}
1951
1951
1952 p2 = None
1952 p2 = None
1953 if mergeable_file:
1953 if mergeable_file:
1954 fn = "mf"
1954 fn = "mf"
1955 p1 = repo[ps[0]]
1955 p1 = repo[ps[0]]
1956 if len(ps) > 1:
1956 if len(ps) > 1:
1957 p2 = repo[ps[1]]
1957 p2 = repo[ps[1]]
1958 pa = p1.ancestor(p2)
1958 pa = p1.ancestor(p2)
1959 base, local, other = [x[fn].data() for x in (pa, p1,
1959 base, local, other = [x[fn].data() for x in (pa, p1,
1960 p2)]
1960 p2)]
1961 m3 = simplemerge.Merge3Text(base, local, other)
1961 m3 = simplemerge.Merge3Text(base, local, other)
1962 ml = [l.strip() for l in m3.merge_lines()]
1962 ml = [l.strip() for l in m3.merge_lines()]
1963 ml.append("")
1963 ml.append("")
1964 elif at > 0:
1964 elif at > 0:
1965 ml = p1[fn].data().split("\n")
1965 ml = p1[fn].data().split("\n")
1966 else:
1966 else:
1967 ml = initialmergedlines
1967 ml = initialmergedlines
1968 ml[id * linesperrev] += " r%i" % id
1968 ml[id * linesperrev] += " r%i" % id
1969 mergedtext = "\n".join(ml)
1969 mergedtext = "\n".join(ml)
1970 files.append(fn)
1970 files.append(fn)
1971 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1971 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1972
1972
1973 if overwritten_file:
1973 if overwritten_file:
1974 fn = "of"
1974 fn = "of"
1975 files.append(fn)
1975 files.append(fn)
1976 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1976 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1977
1977
1978 if new_file:
1978 if new_file:
1979 fn = "nf%i" % id
1979 fn = "nf%i" % id
1980 files.append(fn)
1980 files.append(fn)
1981 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1981 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1982 if len(ps) > 1:
1982 if len(ps) > 1:
1983 if not p2:
1983 if not p2:
1984 p2 = repo[ps[1]]
1984 p2 = repo[ps[1]]
1985 for fn in p2:
1985 for fn in p2:
1986 if fn.startswith("nf"):
1986 if fn.startswith("nf"):
1987 files.append(fn)
1987 files.append(fn)
1988 fctxs[fn] = p2[fn]
1988 fctxs[fn] = p2[fn]
1989
1989
1990 def fctxfn(repo, cx, path):
1990 def fctxfn(repo, cx, path):
1991 return fctxs.get(path)
1991 return fctxs.get(path)
1992
1992
1993 if len(ps) == 0 or ps[0] < 0:
1993 if len(ps) == 0 or ps[0] < 0:
1994 pars = [None, None]
1994 pars = [None, None]
1995 elif len(ps) == 1:
1995 elif len(ps) == 1:
1996 pars = [nodeids[ps[0]], None]
1996 pars = [nodeids[ps[0]], None]
1997 else:
1997 else:
1998 pars = [nodeids[p] for p in ps]
1998 pars = [nodeids[p] for p in ps]
1999 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1999 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
2000 date=(id, 0),
2000 date=(id, 0),
2001 user="debugbuilddag",
2001 user="debugbuilddag",
2002 extra={'branch': atbranch})
2002 extra={'branch': atbranch})
2003 nodeid = repo.commitctx(cx)
2003 nodeid = repo.commitctx(cx)
2004 nodeids.append(nodeid)
2004 nodeids.append(nodeid)
2005 at = id
2005 at = id
2006 elif type == 'l':
2006 elif type == 'l':
2007 id, name = data
2007 id, name = data
2008 ui.note(('tag %s\n' % name))
2008 ui.note(('tag %s\n' % name))
2009 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2009 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2010 elif type == 'a':
2010 elif type == 'a':
2011 ui.note(('branch %s\n' % data))
2011 ui.note(('branch %s\n' % data))
2012 atbranch = data
2012 atbranch = data
2013 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2013 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2014 tr.close()
2014 tr.close()
2015
2015
2016 if tags:
2016 if tags:
2017 repo.vfs.write("localtags", "".join(tags))
2017 repo.vfs.write("localtags", "".join(tags))
2018 finally:
2018 finally:
2019 ui.progress(_('building'), None)
2019 ui.progress(_('building'), None)
2020 release(tr, lock)
2020 release(tr, lock)
2021
2021
2022 @command('debugbundle',
2022 @command('debugbundle',
2023 [('a', 'all', None, _('show all details')),
2023 [('a', 'all', None, _('show all details')),
2024 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2024 ('', 'spec', None, _('print the bundlespec of the bundle'))],
2025 _('FILE'),
2025 _('FILE'),
2026 norepo=True)
2026 norepo=True)
2027 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2027 def debugbundle(ui, bundlepath, all=None, spec=None, **opts):
2028 """lists the contents of a bundle"""
2028 """lists the contents of a bundle"""
2029 with hg.openpath(ui, bundlepath) as f:
2029 with hg.openpath(ui, bundlepath) as f:
2030 if spec:
2030 if spec:
2031 spec = exchange.getbundlespec(ui, f)
2031 spec = exchange.getbundlespec(ui, f)
2032 ui.write('%s\n' % spec)
2032 ui.write('%s\n' % spec)
2033 return
2033 return
2034
2034
2035 gen = exchange.readbundle(ui, f, bundlepath)
2035 gen = exchange.readbundle(ui, f, bundlepath)
2036 if isinstance(gen, bundle2.unbundle20):
2036 if isinstance(gen, bundle2.unbundle20):
2037 return _debugbundle2(ui, gen, all=all, **opts)
2037 return _debugbundle2(ui, gen, all=all, **opts)
2038 if all:
2038 if all:
2039 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2039 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2040
2040
2041 def showchunks(named):
2041 def showchunks(named):
2042 ui.write("\n%s\n" % named)
2042 ui.write("\n%s\n" % named)
2043 chain = None
2043 chain = None
2044 while True:
2044 while True:
2045 chunkdata = gen.deltachunk(chain)
2045 chunkdata = gen.deltachunk(chain)
2046 if not chunkdata:
2046 if not chunkdata:
2047 break
2047 break
2048 node = chunkdata['node']
2048 node = chunkdata['node']
2049 p1 = chunkdata['p1']
2049 p1 = chunkdata['p1']
2050 p2 = chunkdata['p2']
2050 p2 = chunkdata['p2']
2051 cs = chunkdata['cs']
2051 cs = chunkdata['cs']
2052 deltabase = chunkdata['deltabase']
2052 deltabase = chunkdata['deltabase']
2053 delta = chunkdata['delta']
2053 delta = chunkdata['delta']
2054 ui.write("%s %s %s %s %s %s\n" %
2054 ui.write("%s %s %s %s %s %s\n" %
2055 (hex(node), hex(p1), hex(p2),
2055 (hex(node), hex(p1), hex(p2),
2056 hex(cs), hex(deltabase), len(delta)))
2056 hex(cs), hex(deltabase), len(delta)))
2057 chain = node
2057 chain = node
2058
2058
2059 chunkdata = gen.changelogheader()
2059 chunkdata = gen.changelogheader()
2060 showchunks("changelog")
2060 showchunks("changelog")
2061 chunkdata = gen.manifestheader()
2061 chunkdata = gen.manifestheader()
2062 showchunks("manifest")
2062 showchunks("manifest")
2063 while True:
2063 while True:
2064 chunkdata = gen.filelogheader()
2064 chunkdata = gen.filelogheader()
2065 if not chunkdata:
2065 if not chunkdata:
2066 break
2066 break
2067 fname = chunkdata['filename']
2067 fname = chunkdata['filename']
2068 showchunks(fname)
2068 showchunks(fname)
2069 else:
2069 else:
2070 if isinstance(gen, bundle2.unbundle20):
2070 if isinstance(gen, bundle2.unbundle20):
2071 raise error.Abort(_('use debugbundle2 for this file'))
2071 raise error.Abort(_('use debugbundle2 for this file'))
2072 chunkdata = gen.changelogheader()
2072 chunkdata = gen.changelogheader()
2073 chain = None
2073 chain = None
2074 while True:
2074 while True:
2075 chunkdata = gen.deltachunk(chain)
2075 chunkdata = gen.deltachunk(chain)
2076 if not chunkdata:
2076 if not chunkdata:
2077 break
2077 break
2078 node = chunkdata['node']
2078 node = chunkdata['node']
2079 ui.write("%s\n" % hex(node))
2079 ui.write("%s\n" % hex(node))
2080 chain = node
2080 chain = node
2081
2081
2082 def _debugbundle2(ui, gen, **opts):
2082 def _debugbundle2(ui, gen, **opts):
2083 """lists the contents of a bundle2"""
2083 """lists the contents of a bundle2"""
2084 if not isinstance(gen, bundle2.unbundle20):
2084 if not isinstance(gen, bundle2.unbundle20):
2085 raise error.Abort(_('not a bundle2 file'))
2085 raise error.Abort(_('not a bundle2 file'))
2086 ui.write(('Stream params: %s\n' % repr(gen.params)))
2086 ui.write(('Stream params: %s\n' % repr(gen.params)))
2087 for part in gen.iterparts():
2087 for part in gen.iterparts():
2088 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2088 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2089 if part.type == 'changegroup':
2089 if part.type == 'changegroup':
2090 version = part.params.get('version', '01')
2090 version = part.params.get('version', '01')
2091 cg = changegroup.getunbundler(version, part, 'UN')
2091 cg = changegroup.getunbundler(version, part, 'UN')
2092 chunkdata = cg.changelogheader()
2092 chunkdata = cg.changelogheader()
2093 chain = None
2093 chain = None
2094 while True:
2094 while True:
2095 chunkdata = cg.deltachunk(chain)
2095 chunkdata = cg.deltachunk(chain)
2096 if not chunkdata:
2096 if not chunkdata:
2097 break
2097 break
2098 node = chunkdata['node']
2098 node = chunkdata['node']
2099 ui.write(" %s\n" % hex(node))
2099 ui.write(" %s\n" % hex(node))
2100 chain = node
2100 chain = node
2101
2101
2102 @command('debugcreatestreamclonebundle', [], 'FILE')
2102 @command('debugcreatestreamclonebundle', [], 'FILE')
2103 def debugcreatestreamclonebundle(ui, repo, fname):
2103 def debugcreatestreamclonebundle(ui, repo, fname):
2104 """create a stream clone bundle file
2104 """create a stream clone bundle file
2105
2105
2106 Stream bundles are special bundles that are essentially archives of
2106 Stream bundles are special bundles that are essentially archives of
2107 revlog files. They are commonly used for cloning very quickly.
2107 revlog files. They are commonly used for cloning very quickly.
2108 """
2108 """
2109 requirements, gen = streamclone.generatebundlev1(repo)
2109 requirements, gen = streamclone.generatebundlev1(repo)
2110 changegroup.writechunks(ui, gen, fname)
2110 changegroup.writechunks(ui, gen, fname)
2111
2111
2112 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2112 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2113
2113
2114 @command('debugapplystreamclonebundle', [], 'FILE')
2114 @command('debugapplystreamclonebundle', [], 'FILE')
2115 def debugapplystreamclonebundle(ui, repo, fname):
2115 def debugapplystreamclonebundle(ui, repo, fname):
2116 """apply a stream clone bundle file"""
2116 """apply a stream clone bundle file"""
2117 f = hg.openpath(ui, fname)
2117 f = hg.openpath(ui, fname)
2118 gen = exchange.readbundle(ui, f, fname)
2118 gen = exchange.readbundle(ui, f, fname)
2119 gen.apply(repo)
2119 gen.apply(repo)
2120
2120
2121 @command('debugcheckstate', [], '')
2121 @command('debugcheckstate', [], '')
2122 def debugcheckstate(ui, repo):
2122 def debugcheckstate(ui, repo):
2123 """validate the correctness of the current dirstate"""
2123 """validate the correctness of the current dirstate"""
2124 parent1, parent2 = repo.dirstate.parents()
2124 parent1, parent2 = repo.dirstate.parents()
2125 m1 = repo[parent1].manifest()
2125 m1 = repo[parent1].manifest()
2126 m2 = repo[parent2].manifest()
2126 m2 = repo[parent2].manifest()
2127 errors = 0
2127 errors = 0
2128 for f in repo.dirstate:
2128 for f in repo.dirstate:
2129 state = repo.dirstate[f]
2129 state = repo.dirstate[f]
2130 if state in "nr" and f not in m1:
2130 if state in "nr" and f not in m1:
2131 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2131 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2132 errors += 1
2132 errors += 1
2133 if state in "a" and f in m1:
2133 if state in "a" and f in m1:
2134 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2134 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2135 errors += 1
2135 errors += 1
2136 if state in "m" and f not in m1 and f not in m2:
2136 if state in "m" and f not in m1 and f not in m2:
2137 ui.warn(_("%s in state %s, but not in either manifest\n") %
2137 ui.warn(_("%s in state %s, but not in either manifest\n") %
2138 (f, state))
2138 (f, state))
2139 errors += 1
2139 errors += 1
2140 for f in m1:
2140 for f in m1:
2141 state = repo.dirstate[f]
2141 state = repo.dirstate[f]
2142 if state not in "nrm":
2142 if state not in "nrm":
2143 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2143 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2144 errors += 1
2144 errors += 1
2145 if errors:
2145 if errors:
2146 error = _(".hg/dirstate inconsistent with current parent's manifest")
2146 error = _(".hg/dirstate inconsistent with current parent's manifest")
2147 raise error.Abort(error)
2147 raise error.Abort(error)
2148
2148
2149 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2149 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2150 def debugcommands(ui, cmd='', *args):
2150 def debugcommands(ui, cmd='', *args):
2151 """list all available commands and options"""
2151 """list all available commands and options"""
2152 for cmd, vals in sorted(table.iteritems()):
2152 for cmd, vals in sorted(table.iteritems()):
2153 cmd = cmd.split('|')[0].strip('^')
2153 cmd = cmd.split('|')[0].strip('^')
2154 opts = ', '.join([i[1] for i in vals[1]])
2154 opts = ', '.join([i[1] for i in vals[1]])
2155 ui.write('%s: %s\n' % (cmd, opts))
2155 ui.write('%s: %s\n' % (cmd, opts))
2156
2156
2157 @command('debugcomplete',
2157 @command('debugcomplete',
2158 [('o', 'options', None, _('show the command options'))],
2158 [('o', 'options', None, _('show the command options'))],
2159 _('[-o] CMD'),
2159 _('[-o] CMD'),
2160 norepo=True)
2160 norepo=True)
2161 def debugcomplete(ui, cmd='', **opts):
2161 def debugcomplete(ui, cmd='', **opts):
2162 """returns the completion list associated with the given command"""
2162 """returns the completion list associated with the given command"""
2163
2163
2164 if opts.get('options'):
2164 if opts.get('options'):
2165 options = []
2165 options = []
2166 otables = [globalopts]
2166 otables = [globalopts]
2167 if cmd:
2167 if cmd:
2168 aliases, entry = cmdutil.findcmd(cmd, table, False)
2168 aliases, entry = cmdutil.findcmd(cmd, table, False)
2169 otables.append(entry[1])
2169 otables.append(entry[1])
2170 for t in otables:
2170 for t in otables:
2171 for o in t:
2171 for o in t:
2172 if "(DEPRECATED)" in o[3]:
2172 if "(DEPRECATED)" in o[3]:
2173 continue
2173 continue
2174 if o[0]:
2174 if o[0]:
2175 options.append('-%s' % o[0])
2175 options.append('-%s' % o[0])
2176 options.append('--%s' % o[1])
2176 options.append('--%s' % o[1])
2177 ui.write("%s\n" % "\n".join(options))
2177 ui.write("%s\n" % "\n".join(options))
2178 return
2178 return
2179
2179
2180 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2180 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2181 if ui.verbose:
2181 if ui.verbose:
2182 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2182 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2183 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2183 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2184
2184
2185 @command('debugdag',
2185 @command('debugdag',
2186 [('t', 'tags', None, _('use tags as labels')),
2186 [('t', 'tags', None, _('use tags as labels')),
2187 ('b', 'branches', None, _('annotate with branch names')),
2187 ('b', 'branches', None, _('annotate with branch names')),
2188 ('', 'dots', None, _('use dots for runs')),
2188 ('', 'dots', None, _('use dots for runs')),
2189 ('s', 'spaces', None, _('separate elements by spaces'))],
2189 ('s', 'spaces', None, _('separate elements by spaces'))],
2190 _('[OPTION]... [FILE [REV]...]'),
2190 _('[OPTION]... [FILE [REV]...]'),
2191 optionalrepo=True)
2191 optionalrepo=True)
2192 def debugdag(ui, repo, file_=None, *revs, **opts):
2192 def debugdag(ui, repo, file_=None, *revs, **opts):
2193 """format the changelog or an index DAG as a concise textual description
2193 """format the changelog or an index DAG as a concise textual description
2194
2194
2195 If you pass a revlog index, the revlog's DAG is emitted. If you list
2195 If you pass a revlog index, the revlog's DAG is emitted. If you list
2196 revision numbers, they get labeled in the output as rN.
2196 revision numbers, they get labeled in the output as rN.
2197
2197
2198 Otherwise, the changelog DAG of the current repo is emitted.
2198 Otherwise, the changelog DAG of the current repo is emitted.
2199 """
2199 """
2200 spaces = opts.get('spaces')
2200 spaces = opts.get('spaces')
2201 dots = opts.get('dots')
2201 dots = opts.get('dots')
2202 if file_:
2202 if file_:
2203 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2203 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2204 revs = set((int(r) for r in revs))
2204 revs = set((int(r) for r in revs))
2205 def events():
2205 def events():
2206 for r in rlog:
2206 for r in rlog:
2207 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2207 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2208 if p != -1))
2208 if p != -1))
2209 if r in revs:
2209 if r in revs:
2210 yield 'l', (r, "r%i" % r)
2210 yield 'l', (r, "r%i" % r)
2211 elif repo:
2211 elif repo:
2212 cl = repo.changelog
2212 cl = repo.changelog
2213 tags = opts.get('tags')
2213 tags = opts.get('tags')
2214 branches = opts.get('branches')
2214 branches = opts.get('branches')
2215 if tags:
2215 if tags:
2216 labels = {}
2216 labels = {}
2217 for l, n in repo.tags().items():
2217 for l, n in repo.tags().items():
2218 labels.setdefault(cl.rev(n), []).append(l)
2218 labels.setdefault(cl.rev(n), []).append(l)
2219 def events():
2219 def events():
2220 b = "default"
2220 b = "default"
2221 for r in cl:
2221 for r in cl:
2222 if branches:
2222 if branches:
2223 newb = cl.read(cl.node(r))[5]['branch']
2223 newb = cl.read(cl.node(r))[5]['branch']
2224 if newb != b:
2224 if newb != b:
2225 yield 'a', newb
2225 yield 'a', newb
2226 b = newb
2226 b = newb
2227 yield 'n', (r, list(p for p in cl.parentrevs(r)
2227 yield 'n', (r, list(p for p in cl.parentrevs(r)
2228 if p != -1))
2228 if p != -1))
2229 if tags:
2229 if tags:
2230 ls = labels.get(r)
2230 ls = labels.get(r)
2231 if ls:
2231 if ls:
2232 for l in ls:
2232 for l in ls:
2233 yield 'l', (r, l)
2233 yield 'l', (r, l)
2234 else:
2234 else:
2235 raise error.Abort(_('need repo for changelog dag'))
2235 raise error.Abort(_('need repo for changelog dag'))
2236
2236
2237 for line in dagparser.dagtextlines(events(),
2237 for line in dagparser.dagtextlines(events(),
2238 addspaces=spaces,
2238 addspaces=spaces,
2239 wraplabels=True,
2239 wraplabels=True,
2240 wrapannotations=True,
2240 wrapannotations=True,
2241 wrapnonlinear=dots,
2241 wrapnonlinear=dots,
2242 usedots=dots,
2242 usedots=dots,
2243 maxlinewidth=70):
2243 maxlinewidth=70):
2244 ui.write(line)
2244 ui.write(line)
2245 ui.write("\n")
2245 ui.write("\n")
2246
2246
2247 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2247 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2248 def debugdata(ui, repo, file_, rev=None, **opts):
2248 def debugdata(ui, repo, file_, rev=None, **opts):
2249 """dump the contents of a data file revision"""
2249 """dump the contents of a data file revision"""
2250 if opts.get('changelog') or opts.get('manifest'):
2250 if opts.get('changelog') or opts.get('manifest'):
2251 file_, rev = None, file_
2251 file_, rev = None, file_
2252 elif rev is None:
2252 elif rev is None:
2253 raise error.CommandError('debugdata', _('invalid arguments'))
2253 raise error.CommandError('debugdata', _('invalid arguments'))
2254 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2254 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2255 try:
2255 try:
2256 ui.write(r.revision(r.lookup(rev)))
2256 ui.write(r.revision(r.lookup(rev)))
2257 except KeyError:
2257 except KeyError:
2258 raise error.Abort(_('invalid revision identifier %s') % rev)
2258 raise error.Abort(_('invalid revision identifier %s') % rev)
2259
2259
2260 @command('debugdate',
2260 @command('debugdate',
2261 [('e', 'extended', None, _('try extended date formats'))],
2261 [('e', 'extended', None, _('try extended date formats'))],
2262 _('[-e] DATE [RANGE]'),
2262 _('[-e] DATE [RANGE]'),
2263 norepo=True, optionalrepo=True)
2263 norepo=True, optionalrepo=True)
2264 def debugdate(ui, date, range=None, **opts):
2264 def debugdate(ui, date, range=None, **opts):
2265 """parse and display a date"""
2265 """parse and display a date"""
2266 if opts["extended"]:
2266 if opts["extended"]:
2267 d = util.parsedate(date, util.extendeddateformats)
2267 d = util.parsedate(date, util.extendeddateformats)
2268 else:
2268 else:
2269 d = util.parsedate(date)
2269 d = util.parsedate(date)
2270 ui.write(("internal: %s %s\n") % d)
2270 ui.write(("internal: %s %s\n") % d)
2271 ui.write(("standard: %s\n") % util.datestr(d))
2271 ui.write(("standard: %s\n") % util.datestr(d))
2272 if range:
2272 if range:
2273 m = util.matchdate(range)
2273 m = util.matchdate(range)
2274 ui.write(("match: %s\n") % m(d[0]))
2274 ui.write(("match: %s\n") % m(d[0]))
2275
2275
2276 @command('debugdiscovery',
2276 @command('debugdiscovery',
2277 [('', 'old', None, _('use old-style discovery')),
2277 [('', 'old', None, _('use old-style discovery')),
2278 ('', 'nonheads', None,
2278 ('', 'nonheads', None,
2279 _('use old-style discovery with non-heads included')),
2279 _('use old-style discovery with non-heads included')),
2280 ] + remoteopts,
2280 ] + remoteopts,
2281 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2281 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2282 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2282 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2283 """runs the changeset discovery protocol in isolation"""
2283 """runs the changeset discovery protocol in isolation"""
2284 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2284 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2285 opts.get('branch'))
2285 opts.get('branch'))
2286 remote = hg.peer(repo, opts, remoteurl)
2286 remote = hg.peer(repo, opts, remoteurl)
2287 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2287 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2288
2288
2289 # make sure tests are repeatable
2289 # make sure tests are repeatable
2290 random.seed(12323)
2290 random.seed(12323)
2291
2291
2292 def doit(localheads, remoteheads, remote=remote):
2292 def doit(localheads, remoteheads, remote=remote):
2293 if opts.get('old'):
2293 if opts.get('old'):
2294 if localheads:
2294 if localheads:
2295 raise error.Abort('cannot use localheads with old style '
2295 raise error.Abort('cannot use localheads with old style '
2296 'discovery')
2296 'discovery')
2297 if not util.safehasattr(remote, 'branches'):
2297 if not util.safehasattr(remote, 'branches'):
2298 # enable in-client legacy support
2298 # enable in-client legacy support
2299 remote = localrepo.locallegacypeer(remote.local())
2299 remote = localrepo.locallegacypeer(remote.local())
2300 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2300 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2301 force=True)
2301 force=True)
2302 common = set(common)
2302 common = set(common)
2303 if not opts.get('nonheads'):
2303 if not opts.get('nonheads'):
2304 ui.write(("unpruned common: %s\n") %
2304 ui.write(("unpruned common: %s\n") %
2305 " ".join(sorted(short(n) for n in common)))
2305 " ".join(sorted(short(n) for n in common)))
2306 dag = dagutil.revlogdag(repo.changelog)
2306 dag = dagutil.revlogdag(repo.changelog)
2307 all = dag.ancestorset(dag.internalizeall(common))
2307 all = dag.ancestorset(dag.internalizeall(common))
2308 common = dag.externalizeall(dag.headsetofconnecteds(all))
2308 common = dag.externalizeall(dag.headsetofconnecteds(all))
2309 else:
2309 else:
2310 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2310 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2311 common = set(common)
2311 common = set(common)
2312 rheads = set(hds)
2312 rheads = set(hds)
2313 lheads = set(repo.heads())
2313 lheads = set(repo.heads())
2314 ui.write(("common heads: %s\n") %
2314 ui.write(("common heads: %s\n") %
2315 " ".join(sorted(short(n) for n in common)))
2315 " ".join(sorted(short(n) for n in common)))
2316 if lheads <= common:
2316 if lheads <= common:
2317 ui.write(("local is subset\n"))
2317 ui.write(("local is subset\n"))
2318 elif rheads <= common:
2318 elif rheads <= common:
2319 ui.write(("remote is subset\n"))
2319 ui.write(("remote is subset\n"))
2320
2320
2321 serverlogs = opts.get('serverlog')
2321 serverlogs = opts.get('serverlog')
2322 if serverlogs:
2322 if serverlogs:
2323 for filename in serverlogs:
2323 for filename in serverlogs:
2324 with open(filename, 'r') as logfile:
2324 with open(filename, 'r') as logfile:
2325 line = logfile.readline()
2325 line = logfile.readline()
2326 while line:
2326 while line:
2327 parts = line.strip().split(';')
2327 parts = line.strip().split(';')
2328 op = parts[1]
2328 op = parts[1]
2329 if op == 'cg':
2329 if op == 'cg':
2330 pass
2330 pass
2331 elif op == 'cgss':
2331 elif op == 'cgss':
2332 doit(parts[2].split(' '), parts[3].split(' '))
2332 doit(parts[2].split(' '), parts[3].split(' '))
2333 elif op == 'unb':
2333 elif op == 'unb':
2334 doit(parts[3].split(' '), parts[2].split(' '))
2334 doit(parts[3].split(' '), parts[2].split(' '))
2335 line = logfile.readline()
2335 line = logfile.readline()
2336 else:
2336 else:
2337 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2337 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2338 opts.get('remote_head'))
2338 opts.get('remote_head'))
2339 localrevs = opts.get('local_head')
2339 localrevs = opts.get('local_head')
2340 doit(localrevs, remoterevs)
2340 doit(localrevs, remoterevs)
2341
2341
2342 @command('debugextensions', formatteropts, [], norepo=True)
2342 @command('debugextensions', formatteropts, [], norepo=True)
2343 def debugextensions(ui, **opts):
2343 def debugextensions(ui, **opts):
2344 '''show information about active extensions'''
2344 '''show information about active extensions'''
2345 exts = extensions.extensions(ui)
2345 exts = extensions.extensions(ui)
2346 fm = ui.formatter('debugextensions', opts)
2346 fm = ui.formatter('debugextensions', opts)
2347 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2347 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2348 extsource = extmod.__file__
2348 extsource = extmod.__file__
2349 exttestedwith = getattr(extmod, 'testedwith', None)
2349 exttestedwith = getattr(extmod, 'testedwith', None)
2350 if exttestedwith is not None:
2350 if exttestedwith is not None:
2351 exttestedwith = exttestedwith.split()
2351 exttestedwith = exttestedwith.split()
2352 extbuglink = getattr(extmod, 'buglink', None)
2352 extbuglink = getattr(extmod, 'buglink', None)
2353
2353
2354 fm.startitem()
2354 fm.startitem()
2355
2355
2356 if ui.quiet or ui.verbose:
2356 if ui.quiet or ui.verbose:
2357 fm.write('name', '%s\n', extname)
2357 fm.write('name', '%s\n', extname)
2358 else:
2358 else:
2359 fm.write('name', '%s', extname)
2359 fm.write('name', '%s', extname)
2360 if not exttestedwith:
2360 if not exttestedwith:
2361 fm.plain(_(' (untested!)\n'))
2361 fm.plain(_(' (untested!)\n'))
2362 else:
2362 else:
2363 if exttestedwith == ['internal'] or \
2363 if exttestedwith == ['internal'] or \
2364 util.version() in exttestedwith:
2364 util.version() in exttestedwith:
2365 fm.plain('\n')
2365 fm.plain('\n')
2366 else:
2366 else:
2367 lasttestedversion = exttestedwith[-1]
2367 lasttestedversion = exttestedwith[-1]
2368 fm.plain(' (%s!)\n' % lasttestedversion)
2368 fm.plain(' (%s!)\n' % lasttestedversion)
2369
2369
2370 fm.condwrite(ui.verbose and extsource, 'source',
2370 fm.condwrite(ui.verbose and extsource, 'source',
2371 _(' location: %s\n'), extsource or "")
2371 _(' location: %s\n'), extsource or "")
2372
2372
2373 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2373 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2374 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2374 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2375
2375
2376 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2376 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2377 _(' bug reporting: %s\n'), extbuglink or "")
2377 _(' bug reporting: %s\n'), extbuglink or "")
2378
2378
2379 fm.end()
2379 fm.end()
2380
2380
2381 @command('debugfileset',
2381 @command('debugfileset',
2382 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2382 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2383 _('[-r REV] FILESPEC'))
2383 _('[-r REV] FILESPEC'))
2384 def debugfileset(ui, repo, expr, **opts):
2384 def debugfileset(ui, repo, expr, **opts):
2385 '''parse and apply a fileset specification'''
2385 '''parse and apply a fileset specification'''
2386 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2386 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2387 if ui.verbose:
2387 if ui.verbose:
2388 tree = fileset.parse(expr)
2388 tree = fileset.parse(expr)
2389 ui.note(fileset.prettyformat(tree), "\n")
2389 ui.note(fileset.prettyformat(tree), "\n")
2390
2390
2391 for f in ctx.getfileset(expr):
2391 for f in ctx.getfileset(expr):
2392 ui.write("%s\n" % f)
2392 ui.write("%s\n" % f)
2393
2393
2394 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2394 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2395 def debugfsinfo(ui, path="."):
2395 def debugfsinfo(ui, path="."):
2396 """show information detected about current filesystem"""
2396 """show information detected about current filesystem"""
2397 util.writefile('.debugfsinfo', '')
2397 util.writefile('.debugfsinfo', '')
2398 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2398 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2399 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2399 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2400 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2400 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2401 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2401 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2402 and 'yes' or 'no'))
2402 and 'yes' or 'no'))
2403 os.unlink('.debugfsinfo')
2403 os.unlink('.debugfsinfo')
2404
2404
2405 @command('debuggetbundle',
2405 @command('debuggetbundle',
2406 [('H', 'head', [], _('id of head node'), _('ID')),
2406 [('H', 'head', [], _('id of head node'), _('ID')),
2407 ('C', 'common', [], _('id of common node'), _('ID')),
2407 ('C', 'common', [], _('id of common node'), _('ID')),
2408 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2408 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2409 _('REPO FILE [-H|-C ID]...'),
2409 _('REPO FILE [-H|-C ID]...'),
2410 norepo=True)
2410 norepo=True)
2411 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2411 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2412 """retrieves a bundle from a repo
2412 """retrieves a bundle from a repo
2413
2413
2414 Every ID must be a full-length hex node id string. Saves the bundle to the
2414 Every ID must be a full-length hex node id string. Saves the bundle to the
2415 given file.
2415 given file.
2416 """
2416 """
2417 repo = hg.peer(ui, opts, repopath)
2417 repo = hg.peer(ui, opts, repopath)
2418 if not repo.capable('getbundle'):
2418 if not repo.capable('getbundle'):
2419 raise error.Abort("getbundle() not supported by target repository")
2419 raise error.Abort("getbundle() not supported by target repository")
2420 args = {}
2420 args = {}
2421 if common:
2421 if common:
2422 args['common'] = [bin(s) for s in common]
2422 args['common'] = [bin(s) for s in common]
2423 if head:
2423 if head:
2424 args['heads'] = [bin(s) for s in head]
2424 args['heads'] = [bin(s) for s in head]
2425 # TODO: get desired bundlecaps from command line.
2425 # TODO: get desired bundlecaps from command line.
2426 args['bundlecaps'] = None
2426 args['bundlecaps'] = None
2427 bundle = repo.getbundle('debug', **args)
2427 bundle = repo.getbundle('debug', **args)
2428
2428
2429 bundletype = opts.get('type', 'bzip2').lower()
2429 bundletype = opts.get('type', 'bzip2').lower()
2430 btypes = {'none': 'HG10UN',
2430 btypes = {'none': 'HG10UN',
2431 'bzip2': 'HG10BZ',
2431 'bzip2': 'HG10BZ',
2432 'gzip': 'HG10GZ',
2432 'gzip': 'HG10GZ',
2433 'bundle2': 'HG20'}
2433 'bundle2': 'HG20'}
2434 bundletype = btypes.get(bundletype)
2434 bundletype = btypes.get(bundletype)
2435 if bundletype not in changegroup.bundletypes:
2435 if bundletype not in changegroup.bundletypes:
2436 raise error.Abort(_('unknown bundle type specified with --type'))
2436 raise error.Abort(_('unknown bundle type specified with --type'))
2437 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2437 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2438
2438
2439 @command('debugignore', [], '[FILE]')
2439 @command('debugignore', [], '[FILE]')
2440 def debugignore(ui, repo, *files, **opts):
2440 def debugignore(ui, repo, *files, **opts):
2441 """display the combined ignore pattern and information about ignored files
2441 """display the combined ignore pattern and information about ignored files
2442
2442
2443 With no argument display the combined ignore pattern.
2443 With no argument display the combined ignore pattern.
2444
2444
2445 Given space separated file names, shows if the given file is ignored and
2445 Given space separated file names, shows if the given file is ignored and
2446 if so, show the ignore rule (file and line number) that matched it.
2446 if so, show the ignore rule (file and line number) that matched it.
2447 """
2447 """
2448 ignore = repo.dirstate._ignore
2448 ignore = repo.dirstate._ignore
2449 if not files:
2449 if not files:
2450 # Show all the patterns
2450 # Show all the patterns
2451 includepat = getattr(ignore, 'includepat', None)
2451 includepat = getattr(ignore, 'includepat', None)
2452 if includepat is not None:
2452 if includepat is not None:
2453 ui.write("%s\n" % includepat)
2453 ui.write("%s\n" % includepat)
2454 else:
2454 else:
2455 raise error.Abort(_("no ignore patterns found"))
2455 raise error.Abort(_("no ignore patterns found"))
2456 else:
2456 else:
2457 for f in files:
2457 for f in files:
2458 ignored = None
2458 ignored = None
2459 ignoredata = None
2459 ignoredata = None
2460 if f != '.':
2460 if f != '.':
2461 if ignore(f):
2461 if ignore(f):
2462 ignored = f
2462 ignored = f
2463 ignoredata = repo.dirstate._ignorefileandline(f)
2463 ignoredata = repo.dirstate._ignorefileandline(f)
2464 else:
2464 else:
2465 for p in util.finddirs(f):
2465 for p in util.finddirs(f):
2466 if ignore(p):
2466 if ignore(p):
2467 ignored = p
2467 ignored = p
2468 ignoredata = repo.dirstate._ignorefileandline(p)
2468 ignoredata = repo.dirstate._ignorefileandline(p)
2469 break
2469 break
2470 if ignored:
2470 if ignored:
2471 if ignored == f:
2471 if ignored == f:
2472 ui.write("%s is ignored\n" % f)
2472 ui.write("%s is ignored\n" % f)
2473 else:
2473 else:
2474 ui.write("%s is ignored because of containing folder %s\n"
2474 ui.write("%s is ignored because of containing folder %s\n"
2475 % (f, ignored))
2475 % (f, ignored))
2476 ignorefile, lineno, line = ignoredata
2476 ignorefile, lineno, line = ignoredata
2477 ui.write("(ignore rule in %s, line %d: '%s')\n"
2477 ui.write("(ignore rule in %s, line %d: '%s')\n"
2478 % (ignorefile, lineno, line))
2478 % (ignorefile, lineno, line))
2479 else:
2479 else:
2480 ui.write("%s is not ignored\n" % f)
2480 ui.write("%s is not ignored\n" % f)
2481
2481
2482 @command('debugindex', debugrevlogopts +
2482 @command('debugindex', debugrevlogopts +
2483 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2483 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2484 _('[-f FORMAT] -c|-m|FILE'),
2484 _('[-f FORMAT] -c|-m|FILE'),
2485 optionalrepo=True)
2485 optionalrepo=True)
2486 def debugindex(ui, repo, file_=None, **opts):
2486 def debugindex(ui, repo, file_=None, **opts):
2487 """dump the contents of an index file"""
2487 """dump the contents of an index file"""
2488 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2488 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2489 format = opts.get('format', 0)
2489 format = opts.get('format', 0)
2490 if format not in (0, 1):
2490 if format not in (0, 1):
2491 raise error.Abort(_("unknown format %d") % format)
2491 raise error.Abort(_("unknown format %d") % format)
2492
2492
2493 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2493 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2494 if generaldelta:
2494 if generaldelta:
2495 basehdr = ' delta'
2495 basehdr = ' delta'
2496 else:
2496 else:
2497 basehdr = ' base'
2497 basehdr = ' base'
2498
2498
2499 if ui.debugflag:
2499 if ui.debugflag:
2500 shortfn = hex
2500 shortfn = hex
2501 else:
2501 else:
2502 shortfn = short
2502 shortfn = short
2503
2503
2504 # There might not be anything in r, so have a sane default
2504 # There might not be anything in r, so have a sane default
2505 idlen = 12
2505 idlen = 12
2506 for i in r:
2506 for i in r:
2507 idlen = len(shortfn(r.node(i)))
2507 idlen = len(shortfn(r.node(i)))
2508 break
2508 break
2509
2509
2510 if format == 0:
2510 if format == 0:
2511 ui.write(" rev offset length " + basehdr + " linkrev"
2511 ui.write(" rev offset length " + basehdr + " linkrev"
2512 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2512 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2513 elif format == 1:
2513 elif format == 1:
2514 ui.write(" rev flag offset length"
2514 ui.write(" rev flag offset length"
2515 " size " + basehdr + " link p1 p2"
2515 " size " + basehdr + " link p1 p2"
2516 " %s\n" % "nodeid".rjust(idlen))
2516 " %s\n" % "nodeid".rjust(idlen))
2517
2517
2518 for i in r:
2518 for i in r:
2519 node = r.node(i)
2519 node = r.node(i)
2520 if generaldelta:
2520 if generaldelta:
2521 base = r.deltaparent(i)
2521 base = r.deltaparent(i)
2522 else:
2522 else:
2523 base = r.chainbase(i)
2523 base = r.chainbase(i)
2524 if format == 0:
2524 if format == 0:
2525 try:
2525 try:
2526 pp = r.parents(node)
2526 pp = r.parents(node)
2527 except Exception:
2527 except Exception:
2528 pp = [nullid, nullid]
2528 pp = [nullid, nullid]
2529 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2529 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2530 i, r.start(i), r.length(i), base, r.linkrev(i),
2530 i, r.start(i), r.length(i), base, r.linkrev(i),
2531 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2531 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2532 elif format == 1:
2532 elif format == 1:
2533 pr = r.parentrevs(i)
2533 pr = r.parentrevs(i)
2534 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2534 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2535 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2535 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2536 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2536 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2537
2537
2538 @command('debugindexdot', debugrevlogopts,
2538 @command('debugindexdot', debugrevlogopts,
2539 _('-c|-m|FILE'), optionalrepo=True)
2539 _('-c|-m|FILE'), optionalrepo=True)
2540 def debugindexdot(ui, repo, file_=None, **opts):
2540 def debugindexdot(ui, repo, file_=None, **opts):
2541 """dump an index DAG as a graphviz dot file"""
2541 """dump an index DAG as a graphviz dot file"""
2542 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2542 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2543 ui.write(("digraph G {\n"))
2543 ui.write(("digraph G {\n"))
2544 for i in r:
2544 for i in r:
2545 node = r.node(i)
2545 node = r.node(i)
2546 pp = r.parents(node)
2546 pp = r.parents(node)
2547 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2547 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2548 if pp[1] != nullid:
2548 if pp[1] != nullid:
2549 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2549 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2550 ui.write("}\n")
2550 ui.write("}\n")
2551
2551
2552 @command('debugdeltachain',
2552 @command('debugdeltachain',
2553 debugrevlogopts + formatteropts,
2553 debugrevlogopts + formatteropts,
2554 _('-c|-m|FILE'),
2554 _('-c|-m|FILE'),
2555 optionalrepo=True)
2555 optionalrepo=True)
2556 def debugdeltachain(ui, repo, file_=None, **opts):
2556 def debugdeltachain(ui, repo, file_=None, **opts):
2557 """dump information about delta chains in a revlog
2557 """dump information about delta chains in a revlog
2558
2558
2559 Output can be templatized. Available template keywords are:
2559 Output can be templatized. Available template keywords are:
2560
2560
2561 rev revision number
2561 rev revision number
2562 chainid delta chain identifier (numbered by unique base)
2562 chainid delta chain identifier (numbered by unique base)
2563 chainlen delta chain length to this revision
2563 chainlen delta chain length to this revision
2564 prevrev previous revision in delta chain
2564 prevrev previous revision in delta chain
2565 deltatype role of delta / how it was computed
2565 deltatype role of delta / how it was computed
2566 compsize compressed size of revision
2566 compsize compressed size of revision
2567 uncompsize uncompressed size of revision
2567 uncompsize uncompressed size of revision
2568 chainsize total size of compressed revisions in chain
2568 chainsize total size of compressed revisions in chain
2569 chainratio total chain size divided by uncompressed revision size
2569 chainratio total chain size divided by uncompressed revision size
2570 (new delta chains typically start at ratio 2.00)
2570 (new delta chains typically start at ratio 2.00)
2571 lindist linear distance from base revision in delta chain to end
2571 lindist linear distance from base revision in delta chain to end
2572 of this revision
2572 of this revision
2573 extradist total size of revisions not part of this delta chain from
2573 extradist total size of revisions not part of this delta chain from
2574 base of delta chain to end of this revision; a measurement
2574 base of delta chain to end of this revision; a measurement
2575 of how much extra data we need to read/seek across to read
2575 of how much extra data we need to read/seek across to read
2576 the delta chain for this revision
2576 the delta chain for this revision
2577 extraratio extradist divided by chainsize; another representation of
2577 extraratio extradist divided by chainsize; another representation of
2578 how much unrelated data is needed to load this delta chain
2578 how much unrelated data is needed to load this delta chain
2579 """
2579 """
2580 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2580 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2581 index = r.index
2581 index = r.index
2582 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2582 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2583
2583
2584 def revinfo(rev):
2584 def revinfo(rev):
2585 e = index[rev]
2585 e = index[rev]
2586 compsize = e[1]
2586 compsize = e[1]
2587 uncompsize = e[2]
2587 uncompsize = e[2]
2588 chainsize = 0
2588 chainsize = 0
2589
2589
2590 if generaldelta:
2590 if generaldelta:
2591 if e[3] == e[5]:
2591 if e[3] == e[5]:
2592 deltatype = 'p1'
2592 deltatype = 'p1'
2593 elif e[3] == e[6]:
2593 elif e[3] == e[6]:
2594 deltatype = 'p2'
2594 deltatype = 'p2'
2595 elif e[3] == rev - 1:
2595 elif e[3] == rev - 1:
2596 deltatype = 'prev'
2596 deltatype = 'prev'
2597 elif e[3] == rev:
2597 elif e[3] == rev:
2598 deltatype = 'base'
2598 deltatype = 'base'
2599 else:
2599 else:
2600 deltatype = 'other'
2600 deltatype = 'other'
2601 else:
2601 else:
2602 if e[3] == rev:
2602 if e[3] == rev:
2603 deltatype = 'base'
2603 deltatype = 'base'
2604 else:
2604 else:
2605 deltatype = 'prev'
2605 deltatype = 'prev'
2606
2606
2607 chain = r._deltachain(rev)[0]
2607 chain = r._deltachain(rev)[0]
2608 for iterrev in chain:
2608 for iterrev in chain:
2609 e = index[iterrev]
2609 e = index[iterrev]
2610 chainsize += e[1]
2610 chainsize += e[1]
2611
2611
2612 return compsize, uncompsize, deltatype, chain, chainsize
2612 return compsize, uncompsize, deltatype, chain, chainsize
2613
2613
2614 fm = ui.formatter('debugdeltachain', opts)
2614 fm = ui.formatter('debugdeltachain', opts)
2615
2615
2616 fm.plain(' rev chain# chainlen prev delta '
2616 fm.plain(' rev chain# chainlen prev delta '
2617 'size rawsize chainsize ratio lindist extradist '
2617 'size rawsize chainsize ratio lindist extradist '
2618 'extraratio\n')
2618 'extraratio\n')
2619
2619
2620 chainbases = {}
2620 chainbases = {}
2621 for rev in r:
2621 for rev in r:
2622 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2622 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2623 chainbase = chain[0]
2623 chainbase = chain[0]
2624 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2624 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2625 basestart = r.start(chainbase)
2625 basestart = r.start(chainbase)
2626 revstart = r.start(rev)
2626 revstart = r.start(rev)
2627 lineardist = revstart + comp - basestart
2627 lineardist = revstart + comp - basestart
2628 extradist = lineardist - chainsize
2628 extradist = lineardist - chainsize
2629 try:
2629 try:
2630 prevrev = chain[-2]
2630 prevrev = chain[-2]
2631 except IndexError:
2631 except IndexError:
2632 prevrev = -1
2632 prevrev = -1
2633
2633
2634 chainratio = float(chainsize) / float(uncomp)
2634 chainratio = float(chainsize) / float(uncomp)
2635 extraratio = float(extradist) / float(chainsize)
2635 extraratio = float(extradist) / float(chainsize)
2636
2636
2637 fm.startitem()
2637 fm.startitem()
2638 fm.write('rev chainid chainlen prevrev deltatype compsize '
2638 fm.write('rev chainid chainlen prevrev deltatype compsize '
2639 'uncompsize chainsize chainratio lindist extradist '
2639 'uncompsize chainsize chainratio lindist extradist '
2640 'extraratio',
2640 'extraratio',
2641 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2641 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2642 rev, chainid, len(chain), prevrev, deltatype, comp,
2642 rev, chainid, len(chain), prevrev, deltatype, comp,
2643 uncomp, chainsize, chainratio, lineardist, extradist,
2643 uncomp, chainsize, chainratio, lineardist, extradist,
2644 extraratio,
2644 extraratio,
2645 rev=rev, chainid=chainid, chainlen=len(chain),
2645 rev=rev, chainid=chainid, chainlen=len(chain),
2646 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2646 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2647 uncompsize=uncomp, chainsize=chainsize,
2647 uncompsize=uncomp, chainsize=chainsize,
2648 chainratio=chainratio, lindist=lineardist,
2648 chainratio=chainratio, lindist=lineardist,
2649 extradist=extradist, extraratio=extraratio)
2649 extradist=extradist, extraratio=extraratio)
2650
2650
2651 fm.end()
2651 fm.end()
2652
2652
2653 @command('debuginstall', [], '', norepo=True)
2653 @command('debuginstall', [], '', norepo=True)
2654 def debuginstall(ui):
2654 def debuginstall(ui):
2655 '''test Mercurial installation
2655 '''test Mercurial installation
2656
2656
2657 Returns 0 on success.
2657 Returns 0 on success.
2658 '''
2658 '''
2659
2659
2660 def writetemp(contents):
2660 def writetemp(contents):
2661 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2661 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2662 f = os.fdopen(fd, "wb")
2662 f = os.fdopen(fd, "wb")
2663 f.write(contents)
2663 f.write(contents)
2664 f.close()
2664 f.close()
2665 return name
2665 return name
2666
2666
2667 problems = 0
2667 problems = 0
2668
2668
2669 # encoding
2669 # encoding
2670 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2670 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2671 try:
2671 try:
2672 encoding.fromlocal("test")
2672 encoding.fromlocal("test")
2673 except error.Abort as inst:
2673 except error.Abort as inst:
2674 ui.write(" %s\n" % inst)
2674 ui.write(" %s\n" % inst)
2675 ui.write(_(" (check that your locale is properly set)\n"))
2675 ui.write(_(" (check that your locale is properly set)\n"))
2676 problems += 1
2676 problems += 1
2677
2677
2678 # Python
2678 # Python
2679 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2679 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2680 ui.status(_("checking Python version (%s)\n")
2680 ui.status(_("checking Python version (%s)\n")
2681 % ("%s.%s.%s" % sys.version_info[:3]))
2681 % ("%s.%s.%s" % sys.version_info[:3]))
2682 ui.status(_("checking Python lib (%s)...\n")
2682 ui.status(_("checking Python lib (%s)...\n")
2683 % os.path.dirname(os.__file__))
2683 % os.path.dirname(os.__file__))
2684
2684
2685 # compiled modules
2685 # compiled modules
2686 ui.status(_("checking installed modules (%s)...\n")
2686 ui.status(_("checking installed modules (%s)...\n")
2687 % os.path.dirname(__file__))
2687 % os.path.dirname(__file__))
2688 try:
2688 try:
2689 import bdiff, mpatch, base85, osutil
2689 import bdiff, mpatch, base85, osutil
2690 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2690 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2691 except Exception as inst:
2691 except Exception as inst:
2692 ui.write(" %s\n" % inst)
2692 ui.write(" %s\n" % inst)
2693 ui.write(_(" One or more extensions could not be found"))
2693 ui.write(_(" One or more extensions could not be found"))
2694 ui.write(_(" (check that you compiled the extensions)\n"))
2694 ui.write(_(" (check that you compiled the extensions)\n"))
2695 problems += 1
2695 problems += 1
2696
2696
2697 # templates
2697 # templates
2698 import templater
2698 import templater
2699 p = templater.templatepaths()
2699 p = templater.templatepaths()
2700 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2700 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2701 if p:
2701 if p:
2702 m = templater.templatepath("map-cmdline.default")
2702 m = templater.templatepath("map-cmdline.default")
2703 if m:
2703 if m:
2704 # template found, check if it is working
2704 # template found, check if it is working
2705 try:
2705 try:
2706 templater.templater(m)
2706 templater.templater(m)
2707 except Exception as inst:
2707 except Exception as inst:
2708 ui.write(" %s\n" % inst)
2708 ui.write(" %s\n" % inst)
2709 p = None
2709 p = None
2710 else:
2710 else:
2711 ui.write(_(" template 'default' not found\n"))
2711 ui.write(_(" template 'default' not found\n"))
2712 p = None
2712 p = None
2713 else:
2713 else:
2714 ui.write(_(" no template directories found\n"))
2714 ui.write(_(" no template directories found\n"))
2715 if not p:
2715 if not p:
2716 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2716 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2717 problems += 1
2717 problems += 1
2718
2718
2719 # editor
2719 # editor
2720 ui.status(_("checking commit editor...\n"))
2720 ui.status(_("checking commit editor...\n"))
2721 editor = ui.geteditor()
2721 editor = ui.geteditor()
2722 editor = util.expandpath(editor)
2722 editor = util.expandpath(editor)
2723 cmdpath = util.findexe(shlex.split(editor)[0])
2723 cmdpath = util.findexe(shlex.split(editor)[0])
2724 if not cmdpath:
2724 if not cmdpath:
2725 if editor == 'vi':
2725 if editor == 'vi':
2726 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2726 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2727 ui.write(_(" (specify a commit editor in your configuration"
2727 ui.write(_(" (specify a commit editor in your configuration"
2728 " file)\n"))
2728 " file)\n"))
2729 else:
2729 else:
2730 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2730 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2731 ui.write(_(" (specify a commit editor in your configuration"
2731 ui.write(_(" (specify a commit editor in your configuration"
2732 " file)\n"))
2732 " file)\n"))
2733 problems += 1
2733 problems += 1
2734
2734
2735 # check username
2735 # check username
2736 ui.status(_("checking username...\n"))
2736 ui.status(_("checking username...\n"))
2737 try:
2737 try:
2738 ui.username()
2738 ui.username()
2739 except error.Abort as e:
2739 except error.Abort as e:
2740 ui.write(" %s\n" % e)
2740 ui.write(" %s\n" % e)
2741 ui.write(_(" (specify a username in your configuration file)\n"))
2741 ui.write(_(" (specify a username in your configuration file)\n"))
2742 problems += 1
2742 problems += 1
2743
2743
2744 if not problems:
2744 if not problems:
2745 ui.status(_("no problems detected\n"))
2745 ui.status(_("no problems detected\n"))
2746 else:
2746 else:
2747 ui.write(_("%s problems detected,"
2747 ui.write(_("%s problems detected,"
2748 " please check your install!\n") % problems)
2748 " please check your install!\n") % problems)
2749
2749
2750 return problems
2750 return problems
2751
2751
2752 @command('debugknown', [], _('REPO ID...'), norepo=True)
2752 @command('debugknown', [], _('REPO ID...'), norepo=True)
2753 def debugknown(ui, repopath, *ids, **opts):
2753 def debugknown(ui, repopath, *ids, **opts):
2754 """test whether node ids are known to a repo
2754 """test whether node ids are known to a repo
2755
2755
2756 Every ID must be a full-length hex node id string. Returns a list of 0s
2756 Every ID must be a full-length hex node id string. Returns a list of 0s
2757 and 1s indicating unknown/known.
2757 and 1s indicating unknown/known.
2758 """
2758 """
2759 repo = hg.peer(ui, opts, repopath)
2759 repo = hg.peer(ui, opts, repopath)
2760 if not repo.capable('known'):
2760 if not repo.capable('known'):
2761 raise error.Abort("known() not supported by target repository")
2761 raise error.Abort("known() not supported by target repository")
2762 flags = repo.known([bin(s) for s in ids])
2762 flags = repo.known([bin(s) for s in ids])
2763 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2763 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2764
2764
2765 @command('debuglabelcomplete', [], _('LABEL...'))
2765 @command('debuglabelcomplete', [], _('LABEL...'))
2766 def debuglabelcomplete(ui, repo, *args):
2766 def debuglabelcomplete(ui, repo, *args):
2767 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2767 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2768 debugnamecomplete(ui, repo, *args)
2768 debugnamecomplete(ui, repo, *args)
2769
2769
2770 @command('debugmergestate', [], '')
2770 @command('debugmergestate', [], '')
2771 def debugmergestate(ui, repo, *args):
2771 def debugmergestate(ui, repo, *args):
2772 """print merge state
2772 """print merge state
2773
2773
2774 Use --verbose to print out information about whether v1 or v2 merge state
2774 Use --verbose to print out information about whether v1 or v2 merge state
2775 was chosen."""
2775 was chosen."""
2776 def _hashornull(h):
2776 def _hashornull(h):
2777 if h == nullhex:
2777 if h == nullhex:
2778 return 'null'
2778 return 'null'
2779 else:
2779 else:
2780 return h
2780 return h
2781
2781
2782 def printrecords(version):
2782 def printrecords(version):
2783 ui.write(('* version %s records\n') % version)
2783 ui.write(('* version %s records\n') % version)
2784 if version == 1:
2784 if version == 1:
2785 records = v1records
2785 records = v1records
2786 else:
2786 else:
2787 records = v2records
2787 records = v2records
2788
2788
2789 for rtype, record in records:
2789 for rtype, record in records:
2790 # pretty print some record types
2790 # pretty print some record types
2791 if rtype == 'L':
2791 if rtype == 'L':
2792 ui.write(('local: %s\n') % record)
2792 ui.write(('local: %s\n') % record)
2793 elif rtype == 'O':
2793 elif rtype == 'O':
2794 ui.write(('other: %s\n') % record)
2794 ui.write(('other: %s\n') % record)
2795 elif rtype == 'm':
2795 elif rtype == 'm':
2796 driver, mdstate = record.split('\0', 1)
2796 driver, mdstate = record.split('\0', 1)
2797 ui.write(('merge driver: %s (state "%s")\n')
2797 ui.write(('merge driver: %s (state "%s")\n')
2798 % (driver, mdstate))
2798 % (driver, mdstate))
2799 elif rtype in 'FDC':
2799 elif rtype in 'FDC':
2800 r = record.split('\0')
2800 r = record.split('\0')
2801 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2801 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2802 if version == 1:
2802 if version == 1:
2803 onode = 'not stored in v1 format'
2803 onode = 'not stored in v1 format'
2804 flags = r[7]
2804 flags = r[7]
2805 else:
2805 else:
2806 onode, flags = r[7:9]
2806 onode, flags = r[7:9]
2807 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2807 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2808 % (f, rtype, state, _hashornull(hash)))
2808 % (f, rtype, state, _hashornull(hash)))
2809 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2809 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2810 ui.write((' ancestor path: %s (node %s)\n')
2810 ui.write((' ancestor path: %s (node %s)\n')
2811 % (afile, _hashornull(anode)))
2811 % (afile, _hashornull(anode)))
2812 ui.write((' other path: %s (node %s)\n')
2812 ui.write((' other path: %s (node %s)\n')
2813 % (ofile, _hashornull(onode)))
2813 % (ofile, _hashornull(onode)))
2814 else:
2814 else:
2815 ui.write(('unrecognized entry: %s\t%s\n')
2815 ui.write(('unrecognized entry: %s\t%s\n')
2816 % (rtype, record.replace('\0', '\t')))
2816 % (rtype, record.replace('\0', '\t')))
2817
2817
2818 # Avoid mergestate.read() since it may raise an exception for unsupported
2818 # Avoid mergestate.read() since it may raise an exception for unsupported
2819 # merge state records. We shouldn't be doing this, but this is OK since this
2819 # merge state records. We shouldn't be doing this, but this is OK since this
2820 # command is pretty low-level.
2820 # command is pretty low-level.
2821 ms = mergemod.mergestate(repo)
2821 ms = mergemod.mergestate(repo)
2822
2822
2823 # sort so that reasonable information is on top
2823 # sort so that reasonable information is on top
2824 v1records = ms._readrecordsv1()
2824 v1records = ms._readrecordsv1()
2825 v2records = ms._readrecordsv2()
2825 v2records = ms._readrecordsv2()
2826 order = 'LOm'
2826 order = 'LOm'
2827 def key(r):
2827 def key(r):
2828 idx = order.find(r[0])
2828 idx = order.find(r[0])
2829 if idx == -1:
2829 if idx == -1:
2830 return (1, r[1])
2830 return (1, r[1])
2831 else:
2831 else:
2832 return (0, idx)
2832 return (0, idx)
2833 v1records.sort(key=key)
2833 v1records.sort(key=key)
2834 v2records.sort(key=key)
2834 v2records.sort(key=key)
2835
2835
2836 if not v1records and not v2records:
2836 if not v1records and not v2records:
2837 ui.write(('no merge state found\n'))
2837 ui.write(('no merge state found\n'))
2838 elif not v2records:
2838 elif not v2records:
2839 ui.note(('no version 2 merge state\n'))
2839 ui.note(('no version 2 merge state\n'))
2840 printrecords(1)
2840 printrecords(1)
2841 elif ms._v1v2match(v1records, v2records):
2841 elif ms._v1v2match(v1records, v2records):
2842 ui.note(('v1 and v2 states match: using v2\n'))
2842 ui.note(('v1 and v2 states match: using v2\n'))
2843 printrecords(2)
2843 printrecords(2)
2844 else:
2844 else:
2845 ui.note(('v1 and v2 states mismatch: using v1\n'))
2845 ui.note(('v1 and v2 states mismatch: using v1\n'))
2846 printrecords(1)
2846 printrecords(1)
2847 if ui.verbose:
2847 if ui.verbose:
2848 printrecords(2)
2848 printrecords(2)
2849
2849
2850 @command('debugnamecomplete', [], _('NAME...'))
2850 @command('debugnamecomplete', [], _('NAME...'))
2851 def debugnamecomplete(ui, repo, *args):
2851 def debugnamecomplete(ui, repo, *args):
2852 '''complete "names" - tags, open branch names, bookmark names'''
2852 '''complete "names" - tags, open branch names, bookmark names'''
2853
2853
2854 names = set()
2854 names = set()
2855 # since we previously only listed open branches, we will handle that
2855 # since we previously only listed open branches, we will handle that
2856 # specially (after this for loop)
2856 # specially (after this for loop)
2857 for name, ns in repo.names.iteritems():
2857 for name, ns in repo.names.iteritems():
2858 if name != 'branches':
2858 if name != 'branches':
2859 names.update(ns.listnames(repo))
2859 names.update(ns.listnames(repo))
2860 names.update(tag for (tag, heads, tip, closed)
2860 names.update(tag for (tag, heads, tip, closed)
2861 in repo.branchmap().iterbranches() if not closed)
2861 in repo.branchmap().iterbranches() if not closed)
2862 completions = set()
2862 completions = set()
2863 if not args:
2863 if not args:
2864 args = ['']
2864 args = ['']
2865 for a in args:
2865 for a in args:
2866 completions.update(n for n in names if n.startswith(a))
2866 completions.update(n for n in names if n.startswith(a))
2867 ui.write('\n'.join(sorted(completions)))
2867 ui.write('\n'.join(sorted(completions)))
2868 ui.write('\n')
2868 ui.write('\n')
2869
2869
2870 @command('debuglocks',
2870 @command('debuglocks',
2871 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2871 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2872 ('W', 'force-wlock', None,
2872 ('W', 'force-wlock', None,
2873 _('free the working state lock (DANGEROUS)'))],
2873 _('free the working state lock (DANGEROUS)'))],
2874 _('[OPTION]...'))
2874 _('[OPTION]...'))
2875 def debuglocks(ui, repo, **opts):
2875 def debuglocks(ui, repo, **opts):
2876 """show or modify state of locks
2876 """show or modify state of locks
2877
2877
2878 By default, this command will show which locks are held. This
2878 By default, this command will show which locks are held. This
2879 includes the user and process holding the lock, the amount of time
2879 includes the user and process holding the lock, the amount of time
2880 the lock has been held, and the machine name where the process is
2880 the lock has been held, and the machine name where the process is
2881 running if it's not local.
2881 running if it's not local.
2882
2882
2883 Locks protect the integrity of Mercurial's data, so should be
2883 Locks protect the integrity of Mercurial's data, so should be
2884 treated with care. System crashes or other interruptions may cause
2884 treated with care. System crashes or other interruptions may cause
2885 locks to not be properly released, though Mercurial will usually
2885 locks to not be properly released, though Mercurial will usually
2886 detect and remove such stale locks automatically.
2886 detect and remove such stale locks automatically.
2887
2887
2888 However, detecting stale locks may not always be possible (for
2888 However, detecting stale locks may not always be possible (for
2889 instance, on a shared filesystem). Removing locks may also be
2889 instance, on a shared filesystem). Removing locks may also be
2890 blocked by filesystem permissions.
2890 blocked by filesystem permissions.
2891
2891
2892 Returns 0 if no locks are held.
2892 Returns 0 if no locks are held.
2893
2893
2894 """
2894 """
2895
2895
2896 if opts.get('force_lock'):
2896 if opts.get('force_lock'):
2897 repo.svfs.unlink('lock')
2897 repo.svfs.unlink('lock')
2898 if opts.get('force_wlock'):
2898 if opts.get('force_wlock'):
2899 repo.vfs.unlink('wlock')
2899 repo.vfs.unlink('wlock')
2900 if opts.get('force_lock') or opts.get('force_lock'):
2900 if opts.get('force_lock') or opts.get('force_lock'):
2901 return 0
2901 return 0
2902
2902
2903 now = time.time()
2903 now = time.time()
2904 held = 0
2904 held = 0
2905
2905
2906 def report(vfs, name, method):
2906 def report(vfs, name, method):
2907 # this causes stale locks to get reaped for more accurate reporting
2907 # this causes stale locks to get reaped for more accurate reporting
2908 try:
2908 try:
2909 l = method(False)
2909 l = method(False)
2910 except error.LockHeld:
2910 except error.LockHeld:
2911 l = None
2911 l = None
2912
2912
2913 if l:
2913 if l:
2914 l.release()
2914 l.release()
2915 else:
2915 else:
2916 try:
2916 try:
2917 stat = vfs.lstat(name)
2917 stat = vfs.lstat(name)
2918 age = now - stat.st_mtime
2918 age = now - stat.st_mtime
2919 user = util.username(stat.st_uid)
2919 user = util.username(stat.st_uid)
2920 locker = vfs.readlock(name)
2920 locker = vfs.readlock(name)
2921 if ":" in locker:
2921 if ":" in locker:
2922 host, pid = locker.split(':')
2922 host, pid = locker.split(':')
2923 if host == socket.gethostname():
2923 if host == socket.gethostname():
2924 locker = 'user %s, process %s' % (user, pid)
2924 locker = 'user %s, process %s' % (user, pid)
2925 else:
2925 else:
2926 locker = 'user %s, process %s, host %s' \
2926 locker = 'user %s, process %s, host %s' \
2927 % (user, pid, host)
2927 % (user, pid, host)
2928 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2928 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2929 return 1
2929 return 1
2930 except OSError as e:
2930 except OSError as e:
2931 if e.errno != errno.ENOENT:
2931 if e.errno != errno.ENOENT:
2932 raise
2932 raise
2933
2933
2934 ui.write("%-6s free\n" % (name + ":"))
2934 ui.write("%-6s free\n" % (name + ":"))
2935 return 0
2935 return 0
2936
2936
2937 held += report(repo.svfs, "lock", repo.lock)
2937 held += report(repo.svfs, "lock", repo.lock)
2938 held += report(repo.vfs, "wlock", repo.wlock)
2938 held += report(repo.vfs, "wlock", repo.wlock)
2939
2939
2940 return held
2940 return held
2941
2941
2942 @command('debugobsolete',
2942 @command('debugobsolete',
2943 [('', 'flags', 0, _('markers flag')),
2943 [('', 'flags', 0, _('markers flag')),
2944 ('', 'record-parents', False,
2944 ('', 'record-parents', False,
2945 _('record parent information for the precursor')),
2945 _('record parent information for the precursor')),
2946 ('r', 'rev', [], _('display markers relevant to REV')),
2946 ('r', 'rev', [], _('display markers relevant to REV')),
2947 ] + commitopts2,
2947 ] + commitopts2,
2948 _('[OBSOLETED [REPLACEMENT ...]]'))
2948 _('[OBSOLETED [REPLACEMENT ...]]'))
2949 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2949 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2950 """create arbitrary obsolete marker
2950 """create arbitrary obsolete marker
2951
2951
2952 With no arguments, displays the list of obsolescence markers."""
2952 With no arguments, displays the list of obsolescence markers."""
2953
2953
2954 def parsenodeid(s):
2954 def parsenodeid(s):
2955 try:
2955 try:
2956 # We do not use revsingle/revrange functions here to accept
2956 # We do not use revsingle/revrange functions here to accept
2957 # arbitrary node identifiers, possibly not present in the
2957 # arbitrary node identifiers, possibly not present in the
2958 # local repository.
2958 # local repository.
2959 n = bin(s)
2959 n = bin(s)
2960 if len(n) != len(nullid):
2960 if len(n) != len(nullid):
2961 raise TypeError()
2961 raise TypeError()
2962 return n
2962 return n
2963 except TypeError:
2963 except TypeError:
2964 raise error.Abort('changeset references must be full hexadecimal '
2964 raise error.Abort('changeset references must be full hexadecimal '
2965 'node identifiers')
2965 'node identifiers')
2966
2966
2967 if precursor is not None:
2967 if precursor is not None:
2968 if opts['rev']:
2968 if opts['rev']:
2969 raise error.Abort('cannot select revision when creating marker')
2969 raise error.Abort('cannot select revision when creating marker')
2970 metadata = {}
2970 metadata = {}
2971 metadata['user'] = opts['user'] or ui.username()
2971 metadata['user'] = opts['user'] or ui.username()
2972 succs = tuple(parsenodeid(succ) for succ in successors)
2972 succs = tuple(parsenodeid(succ) for succ in successors)
2973 l = repo.lock()
2973 l = repo.lock()
2974 try:
2974 try:
2975 tr = repo.transaction('debugobsolete')
2975 tr = repo.transaction('debugobsolete')
2976 try:
2976 try:
2977 date = opts.get('date')
2977 date = opts.get('date')
2978 if date:
2978 if date:
2979 date = util.parsedate(date)
2979 date = util.parsedate(date)
2980 else:
2980 else:
2981 date = None
2981 date = None
2982 prec = parsenodeid(precursor)
2982 prec = parsenodeid(precursor)
2983 parents = None
2983 parents = None
2984 if opts['record_parents']:
2984 if opts['record_parents']:
2985 if prec not in repo.unfiltered():
2985 if prec not in repo.unfiltered():
2986 raise error.Abort('cannot used --record-parents on '
2986 raise error.Abort('cannot used --record-parents on '
2987 'unknown changesets')
2987 'unknown changesets')
2988 parents = repo.unfiltered()[prec].parents()
2988 parents = repo.unfiltered()[prec].parents()
2989 parents = tuple(p.node() for p in parents)
2989 parents = tuple(p.node() for p in parents)
2990 repo.obsstore.create(tr, prec, succs, opts['flags'],
2990 repo.obsstore.create(tr, prec, succs, opts['flags'],
2991 parents=parents, date=date,
2991 parents=parents, date=date,
2992 metadata=metadata)
2992 metadata=metadata)
2993 tr.close()
2993 tr.close()
2994 except ValueError as exc:
2994 except ValueError as exc:
2995 raise error.Abort(_('bad obsmarker input: %s') % exc)
2995 raise error.Abort(_('bad obsmarker input: %s') % exc)
2996 finally:
2996 finally:
2997 tr.release()
2997 tr.release()
2998 finally:
2998 finally:
2999 l.release()
2999 l.release()
3000 else:
3000 else:
3001 if opts['rev']:
3001 if opts['rev']:
3002 revs = scmutil.revrange(repo, opts['rev'])
3002 revs = scmutil.revrange(repo, opts['rev'])
3003 nodes = [repo[r].node() for r in revs]
3003 nodes = [repo[r].node() for r in revs]
3004 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3004 markers = list(obsolete.getmarkers(repo, nodes=nodes))
3005 markers.sort(key=lambda x: x._data)
3005 markers.sort(key=lambda x: x._data)
3006 else:
3006 else:
3007 markers = obsolete.getmarkers(repo)
3007 markers = obsolete.getmarkers(repo)
3008
3008
3009 for m in markers:
3009 for m in markers:
3010 cmdutil.showmarker(ui, m)
3010 cmdutil.showmarker(ui, m)
3011
3011
3012 @command('debugpathcomplete',
3012 @command('debugpathcomplete',
3013 [('f', 'full', None, _('complete an entire path')),
3013 [('f', 'full', None, _('complete an entire path')),
3014 ('n', 'normal', None, _('show only normal files')),
3014 ('n', 'normal', None, _('show only normal files')),
3015 ('a', 'added', None, _('show only added files')),
3015 ('a', 'added', None, _('show only added files')),
3016 ('r', 'removed', None, _('show only removed files'))],
3016 ('r', 'removed', None, _('show only removed files'))],
3017 _('FILESPEC...'))
3017 _('FILESPEC...'))
3018 def debugpathcomplete(ui, repo, *specs, **opts):
3018 def debugpathcomplete(ui, repo, *specs, **opts):
3019 '''complete part or all of a tracked path
3019 '''complete part or all of a tracked path
3020
3020
3021 This command supports shells that offer path name completion. It
3021 This command supports shells that offer path name completion. It
3022 currently completes only files already known to the dirstate.
3022 currently completes only files already known to the dirstate.
3023
3023
3024 Completion extends only to the next path segment unless
3024 Completion extends only to the next path segment unless
3025 --full is specified, in which case entire paths are used.'''
3025 --full is specified, in which case entire paths are used.'''
3026
3026
3027 def complete(path, acceptable):
3027 def complete(path, acceptable):
3028 dirstate = repo.dirstate
3028 dirstate = repo.dirstate
3029 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3029 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3030 rootdir = repo.root + os.sep
3030 rootdir = repo.root + os.sep
3031 if spec != repo.root and not spec.startswith(rootdir):
3031 if spec != repo.root and not spec.startswith(rootdir):
3032 return [], []
3032 return [], []
3033 if os.path.isdir(spec):
3033 if os.path.isdir(spec):
3034 spec += '/'
3034 spec += '/'
3035 spec = spec[len(rootdir):]
3035 spec = spec[len(rootdir):]
3036 fixpaths = os.sep != '/'
3036 fixpaths = os.sep != '/'
3037 if fixpaths:
3037 if fixpaths:
3038 spec = spec.replace(os.sep, '/')
3038 spec = spec.replace(os.sep, '/')
3039 speclen = len(spec)
3039 speclen = len(spec)
3040 fullpaths = opts['full']
3040 fullpaths = opts['full']
3041 files, dirs = set(), set()
3041 files, dirs = set(), set()
3042 adddir, addfile = dirs.add, files.add
3042 adddir, addfile = dirs.add, files.add
3043 for f, st in dirstate.iteritems():
3043 for f, st in dirstate.iteritems():
3044 if f.startswith(spec) and st[0] in acceptable:
3044 if f.startswith(spec) and st[0] in acceptable:
3045 if fixpaths:
3045 if fixpaths:
3046 f = f.replace('/', os.sep)
3046 f = f.replace('/', os.sep)
3047 if fullpaths:
3047 if fullpaths:
3048 addfile(f)
3048 addfile(f)
3049 continue
3049 continue
3050 s = f.find(os.sep, speclen)
3050 s = f.find(os.sep, speclen)
3051 if s >= 0:
3051 if s >= 0:
3052 adddir(f[:s])
3052 adddir(f[:s])
3053 else:
3053 else:
3054 addfile(f)
3054 addfile(f)
3055 return files, dirs
3055 return files, dirs
3056
3056
3057 acceptable = ''
3057 acceptable = ''
3058 if opts['normal']:
3058 if opts['normal']:
3059 acceptable += 'nm'
3059 acceptable += 'nm'
3060 if opts['added']:
3060 if opts['added']:
3061 acceptable += 'a'
3061 acceptable += 'a'
3062 if opts['removed']:
3062 if opts['removed']:
3063 acceptable += 'r'
3063 acceptable += 'r'
3064 cwd = repo.getcwd()
3064 cwd = repo.getcwd()
3065 if not specs:
3065 if not specs:
3066 specs = ['.']
3066 specs = ['.']
3067
3067
3068 files, dirs = set(), set()
3068 files, dirs = set(), set()
3069 for spec in specs:
3069 for spec in specs:
3070 f, d = complete(spec, acceptable or 'nmar')
3070 f, d = complete(spec, acceptable or 'nmar')
3071 files.update(f)
3071 files.update(f)
3072 dirs.update(d)
3072 dirs.update(d)
3073 files.update(dirs)
3073 files.update(dirs)
3074 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3074 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3075 ui.write('\n')
3075 ui.write('\n')
3076
3076
3077 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3077 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3078 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3078 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3079 '''access the pushkey key/value protocol
3079 '''access the pushkey key/value protocol
3080
3080
3081 With two args, list the keys in the given namespace.
3081 With two args, list the keys in the given namespace.
3082
3082
3083 With five args, set a key to new if it currently is set to old.
3083 With five args, set a key to new if it currently is set to old.
3084 Reports success or failure.
3084 Reports success or failure.
3085 '''
3085 '''
3086
3086
3087 target = hg.peer(ui, {}, repopath)
3087 target = hg.peer(ui, {}, repopath)
3088 if keyinfo:
3088 if keyinfo:
3089 key, old, new = keyinfo
3089 key, old, new = keyinfo
3090 r = target.pushkey(namespace, key, old, new)
3090 r = target.pushkey(namespace, key, old, new)
3091 ui.status(str(r) + '\n')
3091 ui.status(str(r) + '\n')
3092 return not r
3092 return not r
3093 else:
3093 else:
3094 for k, v in sorted(target.listkeys(namespace).iteritems()):
3094 for k, v in sorted(target.listkeys(namespace).iteritems()):
3095 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3095 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3096 v.encode('string-escape')))
3096 v.encode('string-escape')))
3097
3097
3098 @command('debugpvec', [], _('A B'))
3098 @command('debugpvec', [], _('A B'))
3099 def debugpvec(ui, repo, a, b=None):
3099 def debugpvec(ui, repo, a, b=None):
3100 ca = scmutil.revsingle(repo, a)
3100 ca = scmutil.revsingle(repo, a)
3101 cb = scmutil.revsingle(repo, b)
3101 cb = scmutil.revsingle(repo, b)
3102 pa = pvec.ctxpvec(ca)
3102 pa = pvec.ctxpvec(ca)
3103 pb = pvec.ctxpvec(cb)
3103 pb = pvec.ctxpvec(cb)
3104 if pa == pb:
3104 if pa == pb:
3105 rel = "="
3105 rel = "="
3106 elif pa > pb:
3106 elif pa > pb:
3107 rel = ">"
3107 rel = ">"
3108 elif pa < pb:
3108 elif pa < pb:
3109 rel = "<"
3109 rel = "<"
3110 elif pa | pb:
3110 elif pa | pb:
3111 rel = "|"
3111 rel = "|"
3112 ui.write(_("a: %s\n") % pa)
3112 ui.write(_("a: %s\n") % pa)
3113 ui.write(_("b: %s\n") % pb)
3113 ui.write(_("b: %s\n") % pb)
3114 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3114 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3115 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3115 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3116 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3116 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3117 pa.distance(pb), rel))
3117 pa.distance(pb), rel))
3118
3118
3119 @command('debugrebuilddirstate|debugrebuildstate',
3119 @command('debugrebuilddirstate|debugrebuildstate',
3120 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3120 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3121 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3121 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3122 'the working copy parent')),
3122 'the working copy parent')),
3123 ],
3123 ],
3124 _('[-r REV]'))
3124 _('[-r REV]'))
3125 def debugrebuilddirstate(ui, repo, rev, **opts):
3125 def debugrebuilddirstate(ui, repo, rev, **opts):
3126 """rebuild the dirstate as it would look like for the given revision
3126 """rebuild the dirstate as it would look like for the given revision
3127
3127
3128 If no revision is specified the first current parent will be used.
3128 If no revision is specified the first current parent will be used.
3129
3129
3130 The dirstate will be set to the files of the given revision.
3130 The dirstate will be set to the files of the given revision.
3131 The actual working directory content or existing dirstate
3131 The actual working directory content or existing dirstate
3132 information such as adds or removes is not considered.
3132 information such as adds or removes is not considered.
3133
3133
3134 ``minimal`` will only rebuild the dirstate status for files that claim to be
3134 ``minimal`` will only rebuild the dirstate status for files that claim to be
3135 tracked but are not in the parent manifest, or that exist in the parent
3135 tracked but are not in the parent manifest, or that exist in the parent
3136 manifest but are not in the dirstate. It will not change adds, removes, or
3136 manifest but are not in the dirstate. It will not change adds, removes, or
3137 modified files that are in the working copy parent.
3137 modified files that are in the working copy parent.
3138
3138
3139 One use of this command is to make the next :hg:`status` invocation
3139 One use of this command is to make the next :hg:`status` invocation
3140 check the actual file content.
3140 check the actual file content.
3141 """
3141 """
3142 ctx = scmutil.revsingle(repo, rev)
3142 ctx = scmutil.revsingle(repo, rev)
3143 with repo.wlock():
3143 with repo.wlock():
3144 dirstate = repo.dirstate
3144 dirstate = repo.dirstate
3145 changedfiles = None
3145 changedfiles = None
3146 # See command doc for what minimal does.
3146 # See command doc for what minimal does.
3147 if opts.get('minimal'):
3147 if opts.get('minimal'):
3148 manifestfiles = set(ctx.manifest().keys())
3148 manifestfiles = set(ctx.manifest().keys())
3149 dirstatefiles = set(dirstate)
3149 dirstatefiles = set(dirstate)
3150 manifestonly = manifestfiles - dirstatefiles
3150 manifestonly = manifestfiles - dirstatefiles
3151 dsonly = dirstatefiles - manifestfiles
3151 dsonly = dirstatefiles - manifestfiles
3152 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3152 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3153 changedfiles = manifestonly | dsnotadded
3153 changedfiles = manifestonly | dsnotadded
3154
3154
3155 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3155 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3156
3156
3157 @command('debugrebuildfncache', [], '')
3157 @command('debugrebuildfncache', [], '')
3158 def debugrebuildfncache(ui, repo):
3158 def debugrebuildfncache(ui, repo):
3159 """rebuild the fncache file"""
3159 """rebuild the fncache file"""
3160 repair.rebuildfncache(ui, repo)
3160 repair.rebuildfncache(ui, repo)
3161
3161
3162 @command('debugrename',
3162 @command('debugrename',
3163 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3163 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3164 _('[-r REV] FILE'))
3164 _('[-r REV] FILE'))
3165 def debugrename(ui, repo, file1, *pats, **opts):
3165 def debugrename(ui, repo, file1, *pats, **opts):
3166 """dump rename information"""
3166 """dump rename information"""
3167
3167
3168 ctx = scmutil.revsingle(repo, opts.get('rev'))
3168 ctx = scmutil.revsingle(repo, opts.get('rev'))
3169 m = scmutil.match(ctx, (file1,) + pats, opts)
3169 m = scmutil.match(ctx, (file1,) + pats, opts)
3170 for abs in ctx.walk(m):
3170 for abs in ctx.walk(m):
3171 fctx = ctx[abs]
3171 fctx = ctx[abs]
3172 o = fctx.filelog().renamed(fctx.filenode())
3172 o = fctx.filelog().renamed(fctx.filenode())
3173 rel = m.rel(abs)
3173 rel = m.rel(abs)
3174 if o:
3174 if o:
3175 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3175 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3176 else:
3176 else:
3177 ui.write(_("%s not renamed\n") % rel)
3177 ui.write(_("%s not renamed\n") % rel)
3178
3178
3179 @command('debugrevlog', debugrevlogopts +
3179 @command('debugrevlog', debugrevlogopts +
3180 [('d', 'dump', False, _('dump index data'))],
3180 [('d', 'dump', False, _('dump index data'))],
3181 _('-c|-m|FILE'),
3181 _('-c|-m|FILE'),
3182 optionalrepo=True)
3182 optionalrepo=True)
3183 def debugrevlog(ui, repo, file_=None, **opts):
3183 def debugrevlog(ui, repo, file_=None, **opts):
3184 """show data and statistics about a revlog"""
3184 """show data and statistics about a revlog"""
3185 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3185 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3186
3186
3187 if opts.get("dump"):
3187 if opts.get("dump"):
3188 numrevs = len(r)
3188 numrevs = len(r)
3189 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3189 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3190 " rawsize totalsize compression heads chainlen\n")
3190 " rawsize totalsize compression heads chainlen\n")
3191 ts = 0
3191 ts = 0
3192 heads = set()
3192 heads = set()
3193
3193
3194 for rev in xrange(numrevs):
3194 for rev in xrange(numrevs):
3195 dbase = r.deltaparent(rev)
3195 dbase = r.deltaparent(rev)
3196 if dbase == -1:
3196 if dbase == -1:
3197 dbase = rev
3197 dbase = rev
3198 cbase = r.chainbase(rev)
3198 cbase = r.chainbase(rev)
3199 clen = r.chainlen(rev)
3199 clen = r.chainlen(rev)
3200 p1, p2 = r.parentrevs(rev)
3200 p1, p2 = r.parentrevs(rev)
3201 rs = r.rawsize(rev)
3201 rs = r.rawsize(rev)
3202 ts = ts + rs
3202 ts = ts + rs
3203 heads -= set(r.parentrevs(rev))
3203 heads -= set(r.parentrevs(rev))
3204 heads.add(rev)
3204 heads.add(rev)
3205 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3205 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3206 "%11d %5d %8d\n" %
3206 "%11d %5d %8d\n" %
3207 (rev, p1, p2, r.start(rev), r.end(rev),
3207 (rev, p1, p2, r.start(rev), r.end(rev),
3208 r.start(dbase), r.start(cbase),
3208 r.start(dbase), r.start(cbase),
3209 r.start(p1), r.start(p2),
3209 r.start(p1), r.start(p2),
3210 rs, ts, ts / r.end(rev), len(heads), clen))
3210 rs, ts, ts / r.end(rev), len(heads), clen))
3211 return 0
3211 return 0
3212
3212
3213 v = r.version
3213 v = r.version
3214 format = v & 0xFFFF
3214 format = v & 0xFFFF
3215 flags = []
3215 flags = []
3216 gdelta = False
3216 gdelta = False
3217 if v & revlog.REVLOGNGINLINEDATA:
3217 if v & revlog.REVLOGNGINLINEDATA:
3218 flags.append('inline')
3218 flags.append('inline')
3219 if v & revlog.REVLOGGENERALDELTA:
3219 if v & revlog.REVLOGGENERALDELTA:
3220 gdelta = True
3220 gdelta = True
3221 flags.append('generaldelta')
3221 flags.append('generaldelta')
3222 if not flags:
3222 if not flags:
3223 flags = ['(none)']
3223 flags = ['(none)']
3224
3224
3225 nummerges = 0
3225 nummerges = 0
3226 numfull = 0
3226 numfull = 0
3227 numprev = 0
3227 numprev = 0
3228 nump1 = 0
3228 nump1 = 0
3229 nump2 = 0
3229 nump2 = 0
3230 numother = 0
3230 numother = 0
3231 nump1prev = 0
3231 nump1prev = 0
3232 nump2prev = 0
3232 nump2prev = 0
3233 chainlengths = []
3233 chainlengths = []
3234
3234
3235 datasize = [None, 0, 0L]
3235 datasize = [None, 0, 0L]
3236 fullsize = [None, 0, 0L]
3236 fullsize = [None, 0, 0L]
3237 deltasize = [None, 0, 0L]
3237 deltasize = [None, 0, 0L]
3238
3238
3239 def addsize(size, l):
3239 def addsize(size, l):
3240 if l[0] is None or size < l[0]:
3240 if l[0] is None or size < l[0]:
3241 l[0] = size
3241 l[0] = size
3242 if size > l[1]:
3242 if size > l[1]:
3243 l[1] = size
3243 l[1] = size
3244 l[2] += size
3244 l[2] += size
3245
3245
3246 numrevs = len(r)
3246 numrevs = len(r)
3247 for rev in xrange(numrevs):
3247 for rev in xrange(numrevs):
3248 p1, p2 = r.parentrevs(rev)
3248 p1, p2 = r.parentrevs(rev)
3249 delta = r.deltaparent(rev)
3249 delta = r.deltaparent(rev)
3250 if format > 0:
3250 if format > 0:
3251 addsize(r.rawsize(rev), datasize)
3251 addsize(r.rawsize(rev), datasize)
3252 if p2 != nullrev:
3252 if p2 != nullrev:
3253 nummerges += 1
3253 nummerges += 1
3254 size = r.length(rev)
3254 size = r.length(rev)
3255 if delta == nullrev:
3255 if delta == nullrev:
3256 chainlengths.append(0)
3256 chainlengths.append(0)
3257 numfull += 1
3257 numfull += 1
3258 addsize(size, fullsize)
3258 addsize(size, fullsize)
3259 else:
3259 else:
3260 chainlengths.append(chainlengths[delta] + 1)
3260 chainlengths.append(chainlengths[delta] + 1)
3261 addsize(size, deltasize)
3261 addsize(size, deltasize)
3262 if delta == rev - 1:
3262 if delta == rev - 1:
3263 numprev += 1
3263 numprev += 1
3264 if delta == p1:
3264 if delta == p1:
3265 nump1prev += 1
3265 nump1prev += 1
3266 elif delta == p2:
3266 elif delta == p2:
3267 nump2prev += 1
3267 nump2prev += 1
3268 elif delta == p1:
3268 elif delta == p1:
3269 nump1 += 1
3269 nump1 += 1
3270 elif delta == p2:
3270 elif delta == p2:
3271 nump2 += 1
3271 nump2 += 1
3272 elif delta != nullrev:
3272 elif delta != nullrev:
3273 numother += 1
3273 numother += 1
3274
3274
3275 # Adjust size min value for empty cases
3275 # Adjust size min value for empty cases
3276 for size in (datasize, fullsize, deltasize):
3276 for size in (datasize, fullsize, deltasize):
3277 if size[0] is None:
3277 if size[0] is None:
3278 size[0] = 0
3278 size[0] = 0
3279
3279
3280 numdeltas = numrevs - numfull
3280 numdeltas = numrevs - numfull
3281 numoprev = numprev - nump1prev - nump2prev
3281 numoprev = numprev - nump1prev - nump2prev
3282 totalrawsize = datasize[2]
3282 totalrawsize = datasize[2]
3283 datasize[2] /= numrevs
3283 datasize[2] /= numrevs
3284 fulltotal = fullsize[2]
3284 fulltotal = fullsize[2]
3285 fullsize[2] /= numfull
3285 fullsize[2] /= numfull
3286 deltatotal = deltasize[2]
3286 deltatotal = deltasize[2]
3287 if numrevs - numfull > 0:
3287 if numrevs - numfull > 0:
3288 deltasize[2] /= numrevs - numfull
3288 deltasize[2] /= numrevs - numfull
3289 totalsize = fulltotal + deltatotal
3289 totalsize = fulltotal + deltatotal
3290 avgchainlen = sum(chainlengths) / numrevs
3290 avgchainlen = sum(chainlengths) / numrevs
3291 maxchainlen = max(chainlengths)
3291 maxchainlen = max(chainlengths)
3292 compratio = 1
3292 compratio = 1
3293 if totalsize:
3293 if totalsize:
3294 compratio = totalrawsize / totalsize
3294 compratio = totalrawsize / totalsize
3295
3295
3296 basedfmtstr = '%%%dd\n'
3296 basedfmtstr = '%%%dd\n'
3297 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3297 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3298
3298
3299 def dfmtstr(max):
3299 def dfmtstr(max):
3300 return basedfmtstr % len(str(max))
3300 return basedfmtstr % len(str(max))
3301 def pcfmtstr(max, padding=0):
3301 def pcfmtstr(max, padding=0):
3302 return basepcfmtstr % (len(str(max)), ' ' * padding)
3302 return basepcfmtstr % (len(str(max)), ' ' * padding)
3303
3303
3304 def pcfmt(value, total):
3304 def pcfmt(value, total):
3305 if total:
3305 if total:
3306 return (value, 100 * float(value) / total)
3306 return (value, 100 * float(value) / total)
3307 else:
3307 else:
3308 return value, 100.0
3308 return value, 100.0
3309
3309
3310 ui.write(('format : %d\n') % format)
3310 ui.write(('format : %d\n') % format)
3311 ui.write(('flags : %s\n') % ', '.join(flags))
3311 ui.write(('flags : %s\n') % ', '.join(flags))
3312
3312
3313 ui.write('\n')
3313 ui.write('\n')
3314 fmt = pcfmtstr(totalsize)
3314 fmt = pcfmtstr(totalsize)
3315 fmt2 = dfmtstr(totalsize)
3315 fmt2 = dfmtstr(totalsize)
3316 ui.write(('revisions : ') + fmt2 % numrevs)
3316 ui.write(('revisions : ') + fmt2 % numrevs)
3317 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3317 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3318 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3318 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3319 ui.write(('revisions : ') + fmt2 % numrevs)
3319 ui.write(('revisions : ') + fmt2 % numrevs)
3320 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3320 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3321 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3321 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3322 ui.write(('revision size : ') + fmt2 % totalsize)
3322 ui.write(('revision size : ') + fmt2 % totalsize)
3323 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3323 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3324 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3324 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3325
3325
3326 ui.write('\n')
3326 ui.write('\n')
3327 fmt = dfmtstr(max(avgchainlen, compratio))
3327 fmt = dfmtstr(max(avgchainlen, compratio))
3328 ui.write(('avg chain length : ') + fmt % avgchainlen)
3328 ui.write(('avg chain length : ') + fmt % avgchainlen)
3329 ui.write(('max chain length : ') + fmt % maxchainlen)
3329 ui.write(('max chain length : ') + fmt % maxchainlen)
3330 ui.write(('compression ratio : ') + fmt % compratio)
3330 ui.write(('compression ratio : ') + fmt % compratio)
3331
3331
3332 if format > 0:
3332 if format > 0:
3333 ui.write('\n')
3333 ui.write('\n')
3334 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3334 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3335 % tuple(datasize))
3335 % tuple(datasize))
3336 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3336 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3337 % tuple(fullsize))
3337 % tuple(fullsize))
3338 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3338 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3339 % tuple(deltasize))
3339 % tuple(deltasize))
3340
3340
3341 if numdeltas > 0:
3341 if numdeltas > 0:
3342 ui.write('\n')
3342 ui.write('\n')
3343 fmt = pcfmtstr(numdeltas)
3343 fmt = pcfmtstr(numdeltas)
3344 fmt2 = pcfmtstr(numdeltas, 4)
3344 fmt2 = pcfmtstr(numdeltas, 4)
3345 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3345 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3346 if numprev > 0:
3346 if numprev > 0:
3347 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3347 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3348 numprev))
3348 numprev))
3349 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3349 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3350 numprev))
3350 numprev))
3351 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3351 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3352 numprev))
3352 numprev))
3353 if gdelta:
3353 if gdelta:
3354 ui.write(('deltas against p1 : ')
3354 ui.write(('deltas against p1 : ')
3355 + fmt % pcfmt(nump1, numdeltas))
3355 + fmt % pcfmt(nump1, numdeltas))
3356 ui.write(('deltas against p2 : ')
3356 ui.write(('deltas against p2 : ')
3357 + fmt % pcfmt(nump2, numdeltas))
3357 + fmt % pcfmt(nump2, numdeltas))
3358 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3358 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3359 numdeltas))
3359 numdeltas))
3360
3360
3361 @command('debugrevspec',
3361 @command('debugrevspec',
3362 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3362 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3363 ('REVSPEC'))
3363 ('REVSPEC'))
3364 def debugrevspec(ui, repo, expr, **opts):
3364 def debugrevspec(ui, repo, expr, **opts):
3365 """parse and apply a revision specification
3365 """parse and apply a revision specification
3366
3366
3367 Use --verbose to print the parsed tree before and after aliases
3367 Use --verbose to print the parsed tree before and after aliases
3368 expansion.
3368 expansion.
3369 """
3369 """
3370 if ui.verbose:
3370 if ui.verbose:
3371 tree = revset.parse(expr, lookup=repo.__contains__)
3371 tree = revset.parse(expr, lookup=repo.__contains__)
3372 ui.note(revset.prettyformat(tree), "\n")
3372 ui.note(revset.prettyformat(tree), "\n")
3373 newtree = revset.findaliases(ui, tree)
3373 newtree = revset.findaliases(ui, tree)
3374 if newtree != tree:
3374 if newtree != tree:
3375 ui.note(revset.prettyformat(newtree), "\n")
3375 ui.note(revset.prettyformat(newtree), "\n")
3376 tree = newtree
3376 tree = newtree
3377 newtree = revset.foldconcat(tree)
3377 newtree = revset.foldconcat(tree)
3378 if newtree != tree:
3378 if newtree != tree:
3379 ui.note(revset.prettyformat(newtree), "\n")
3379 ui.note(revset.prettyformat(newtree), "\n")
3380 if opts["optimize"]:
3380 if opts["optimize"]:
3381 weight, optimizedtree = revset.optimize(newtree, True)
3381 weight, optimizedtree = revset.optimize(newtree, True)
3382 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3382 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3383 func = revset.match(ui, expr, repo)
3383 func = revset.match(ui, expr, repo)
3384 revs = func(repo)
3384 revs = func(repo)
3385 if ui.verbose:
3385 if ui.verbose:
3386 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3386 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3387 for c in revs:
3387 for c in revs:
3388 ui.write("%s\n" % c)
3388 ui.write("%s\n" % c)
3389
3389
3390 @command('debugsetparents', [], _('REV1 [REV2]'))
3390 @command('debugsetparents', [], _('REV1 [REV2]'))
3391 def debugsetparents(ui, repo, rev1, rev2=None):
3391 def debugsetparents(ui, repo, rev1, rev2=None):
3392 """manually set the parents of the current working directory
3392 """manually set the parents of the current working directory
3393
3393
3394 This is useful for writing repository conversion tools, but should
3394 This is useful for writing repository conversion tools, but should
3395 be used with care. For example, neither the working directory nor the
3395 be used with care. For example, neither the working directory nor the
3396 dirstate is updated, so file status may be incorrect after running this
3396 dirstate is updated, so file status may be incorrect after running this
3397 command.
3397 command.
3398
3398
3399 Returns 0 on success.
3399 Returns 0 on success.
3400 """
3400 """
3401
3401
3402 r1 = scmutil.revsingle(repo, rev1).node()
3402 r1 = scmutil.revsingle(repo, rev1).node()
3403 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3403 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3404
3404
3405 with repo.wlock():
3405 with repo.wlock():
3406 repo.dirstate.beginparentchange()
3406 repo.dirstate.beginparentchange()
3407 repo.setparents(r1, r2)
3407 repo.setparents(r1, r2)
3408 repo.dirstate.endparentchange()
3408 repo.dirstate.endparentchange()
3409
3409
3410 @command('debugdirstate|debugstate',
3410 @command('debugdirstate|debugstate',
3411 [('', 'nodates', None, _('do not display the saved mtime')),
3411 [('', 'nodates', None, _('do not display the saved mtime')),
3412 ('', 'datesort', None, _('sort by saved mtime'))],
3412 ('', 'datesort', None, _('sort by saved mtime'))],
3413 _('[OPTION]...'))
3413 _('[OPTION]...'))
3414 def debugstate(ui, repo, **opts):
3414 def debugstate(ui, repo, **opts):
3415 """show the contents of the current dirstate"""
3415 """show the contents of the current dirstate"""
3416
3416
3417 nodates = opts.get('nodates')
3417 nodates = opts.get('nodates')
3418 datesort = opts.get('datesort')
3418 datesort = opts.get('datesort')
3419
3419
3420 timestr = ""
3420 timestr = ""
3421 if datesort:
3421 if datesort:
3422 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3422 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3423 else:
3423 else:
3424 keyfunc = None # sort by filename
3424 keyfunc = None # sort by filename
3425 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3425 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3426 if ent[3] == -1:
3426 if ent[3] == -1:
3427 timestr = 'unset '
3427 timestr = 'unset '
3428 elif nodates:
3428 elif nodates:
3429 timestr = 'set '
3429 timestr = 'set '
3430 else:
3430 else:
3431 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3431 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3432 time.localtime(ent[3]))
3432 time.localtime(ent[3]))
3433 if ent[1] & 0o20000:
3433 if ent[1] & 0o20000:
3434 mode = 'lnk'
3434 mode = 'lnk'
3435 else:
3435 else:
3436 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3436 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3437 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3437 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3438 for f in repo.dirstate.copies():
3438 for f in repo.dirstate.copies():
3439 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3439 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3440
3440
3441 @command('debugsub',
3441 @command('debugsub',
3442 [('r', 'rev', '',
3442 [('r', 'rev', '',
3443 _('revision to check'), _('REV'))],
3443 _('revision to check'), _('REV'))],
3444 _('[-r REV] [REV]'))
3444 _('[-r REV] [REV]'))
3445 def debugsub(ui, repo, rev=None):
3445 def debugsub(ui, repo, rev=None):
3446 ctx = scmutil.revsingle(repo, rev, None)
3446 ctx = scmutil.revsingle(repo, rev, None)
3447 for k, v in sorted(ctx.substate.items()):
3447 for k, v in sorted(ctx.substate.items()):
3448 ui.write(('path %s\n') % k)
3448 ui.write(('path %s\n') % k)
3449 ui.write((' source %s\n') % v[0])
3449 ui.write((' source %s\n') % v[0])
3450 ui.write((' revision %s\n') % v[1])
3450 ui.write((' revision %s\n') % v[1])
3451
3451
3452 @command('debugsuccessorssets',
3452 @command('debugsuccessorssets',
3453 [],
3453 [],
3454 _('[REV]'))
3454 _('[REV]'))
3455 def debugsuccessorssets(ui, repo, *revs):
3455 def debugsuccessorssets(ui, repo, *revs):
3456 """show set of successors for revision
3456 """show set of successors for revision
3457
3457
3458 A successors set of changeset A is a consistent group of revisions that
3458 A successors set of changeset A is a consistent group of revisions that
3459 succeed A. It contains non-obsolete changesets only.
3459 succeed A. It contains non-obsolete changesets only.
3460
3460
3461 In most cases a changeset A has a single successors set containing a single
3461 In most cases a changeset A has a single successors set containing a single
3462 successor (changeset A replaced by A').
3462 successor (changeset A replaced by A').
3463
3463
3464 A changeset that is made obsolete with no successors are called "pruned".
3464 A changeset that is made obsolete with no successors are called "pruned".
3465 Such changesets have no successors sets at all.
3465 Such changesets have no successors sets at all.
3466
3466
3467 A changeset that has been "split" will have a successors set containing
3467 A changeset that has been "split" will have a successors set containing
3468 more than one successor.
3468 more than one successor.
3469
3469
3470 A changeset that has been rewritten in multiple different ways is called
3470 A changeset that has been rewritten in multiple different ways is called
3471 "divergent". Such changesets have multiple successor sets (each of which
3471 "divergent". Such changesets have multiple successor sets (each of which
3472 may also be split, i.e. have multiple successors).
3472 may also be split, i.e. have multiple successors).
3473
3473
3474 Results are displayed as follows::
3474 Results are displayed as follows::
3475
3475
3476 <rev1>
3476 <rev1>
3477 <successors-1A>
3477 <successors-1A>
3478 <rev2>
3478 <rev2>
3479 <successors-2A>
3479 <successors-2A>
3480 <successors-2B1> <successors-2B2> <successors-2B3>
3480 <successors-2B1> <successors-2B2> <successors-2B3>
3481
3481
3482 Here rev2 has two possible (i.e. divergent) successors sets. The first
3482 Here rev2 has two possible (i.e. divergent) successors sets. The first
3483 holds one element, whereas the second holds three (i.e. the changeset has
3483 holds one element, whereas the second holds three (i.e. the changeset has
3484 been split).
3484 been split).
3485 """
3485 """
3486 # passed to successorssets caching computation from one call to another
3486 # passed to successorssets caching computation from one call to another
3487 cache = {}
3487 cache = {}
3488 ctx2str = str
3488 ctx2str = str
3489 node2str = short
3489 node2str = short
3490 if ui.debug():
3490 if ui.debug():
3491 def ctx2str(ctx):
3491 def ctx2str(ctx):
3492 return ctx.hex()
3492 return ctx.hex()
3493 node2str = hex
3493 node2str = hex
3494 for rev in scmutil.revrange(repo, revs):
3494 for rev in scmutil.revrange(repo, revs):
3495 ctx = repo[rev]
3495 ctx = repo[rev]
3496 ui.write('%s\n'% ctx2str(ctx))
3496 ui.write('%s\n'% ctx2str(ctx))
3497 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3497 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3498 if succsset:
3498 if succsset:
3499 ui.write(' ')
3499 ui.write(' ')
3500 ui.write(node2str(succsset[0]))
3500 ui.write(node2str(succsset[0]))
3501 for node in succsset[1:]:
3501 for node in succsset[1:]:
3502 ui.write(' ')
3502 ui.write(' ')
3503 ui.write(node2str(node))
3503 ui.write(node2str(node))
3504 ui.write('\n')
3504 ui.write('\n')
3505
3505
3506 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3506 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3507 def debugwalk(ui, repo, *pats, **opts):
3507 def debugwalk(ui, repo, *pats, **opts):
3508 """show how files match on given patterns"""
3508 """show how files match on given patterns"""
3509 m = scmutil.match(repo[None], pats, opts)
3509 m = scmutil.match(repo[None], pats, opts)
3510 items = list(repo.walk(m))
3510 items = list(repo.walk(m))
3511 if not items:
3511 if not items:
3512 return
3512 return
3513 f = lambda fn: fn
3513 f = lambda fn: fn
3514 if ui.configbool('ui', 'slash') and os.sep != '/':
3514 if ui.configbool('ui', 'slash') and os.sep != '/':
3515 f = lambda fn: util.normpath(fn)
3515 f = lambda fn: util.normpath(fn)
3516 fmt = 'f %%-%ds %%-%ds %%s' % (
3516 fmt = 'f %%-%ds %%-%ds %%s' % (
3517 max([len(abs) for abs in items]),
3517 max([len(abs) for abs in items]),
3518 max([len(m.rel(abs)) for abs in items]))
3518 max([len(m.rel(abs)) for abs in items]))
3519 for abs in items:
3519 for abs in items:
3520 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3520 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3521 ui.write("%s\n" % line.rstrip())
3521 ui.write("%s\n" % line.rstrip())
3522
3522
3523 @command('debugwireargs',
3523 @command('debugwireargs',
3524 [('', 'three', '', 'three'),
3524 [('', 'three', '', 'three'),
3525 ('', 'four', '', 'four'),
3525 ('', 'four', '', 'four'),
3526 ('', 'five', '', 'five'),
3526 ('', 'five', '', 'five'),
3527 ] + remoteopts,
3527 ] + remoteopts,
3528 _('REPO [OPTIONS]... [ONE [TWO]]'),
3528 _('REPO [OPTIONS]... [ONE [TWO]]'),
3529 norepo=True)
3529 norepo=True)
3530 def debugwireargs(ui, repopath, *vals, **opts):
3530 def debugwireargs(ui, repopath, *vals, **opts):
3531 repo = hg.peer(ui, opts, repopath)
3531 repo = hg.peer(ui, opts, repopath)
3532 for opt in remoteopts:
3532 for opt in remoteopts:
3533 del opts[opt[1]]
3533 del opts[opt[1]]
3534 args = {}
3534 args = {}
3535 for k, v in opts.iteritems():
3535 for k, v in opts.iteritems():
3536 if v:
3536 if v:
3537 args[k] = v
3537 args[k] = v
3538 # run twice to check that we don't mess up the stream for the next command
3538 # run twice to check that we don't mess up the stream for the next command
3539 res1 = repo.debugwireargs(*vals, **args)
3539 res1 = repo.debugwireargs(*vals, **args)
3540 res2 = repo.debugwireargs(*vals, **args)
3540 res2 = repo.debugwireargs(*vals, **args)
3541 ui.write("%s\n" % res1)
3541 ui.write("%s\n" % res1)
3542 if res1 != res2:
3542 if res1 != res2:
3543 ui.warn("%s\n" % res2)
3543 ui.warn("%s\n" % res2)
3544
3544
3545 @command('^diff',
3545 @command('^diff',
3546 [('r', 'rev', [], _('revision'), _('REV')),
3546 [('r', 'rev', [], _('revision'), _('REV')),
3547 ('c', 'change', '', _('change made by revision'), _('REV'))
3547 ('c', 'change', '', _('change made by revision'), _('REV'))
3548 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3548 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3549 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3549 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3550 inferrepo=True)
3550 inferrepo=True)
3551 def diff(ui, repo, *pats, **opts):
3551 def diff(ui, repo, *pats, **opts):
3552 """diff repository (or selected files)
3552 """diff repository (or selected files)
3553
3553
3554 Show differences between revisions for the specified files.
3554 Show differences between revisions for the specified files.
3555
3555
3556 Differences between files are shown using the unified diff format.
3556 Differences between files are shown using the unified diff format.
3557
3557
3558 .. note::
3558 .. note::
3559
3559
3560 :hg:`diff` may generate unexpected results for merges, as it will
3560 :hg:`diff` may generate unexpected results for merges, as it will
3561 default to comparing against the working directory's first
3561 default to comparing against the working directory's first
3562 parent changeset if no revisions are specified.
3562 parent changeset if no revisions are specified.
3563
3563
3564 When two revision arguments are given, then changes are shown
3564 When two revision arguments are given, then changes are shown
3565 between those revisions. If only one revision is specified then
3565 between those revisions. If only one revision is specified then
3566 that revision is compared to the working directory, and, when no
3566 that revision is compared to the working directory, and, when no
3567 revisions are specified, the working directory files are compared
3567 revisions are specified, the working directory files are compared
3568 to its first parent.
3568 to its first parent.
3569
3569
3570 Alternatively you can specify -c/--change with a revision to see
3570 Alternatively you can specify -c/--change with a revision to see
3571 the changes in that changeset relative to its first parent.
3571 the changes in that changeset relative to its first parent.
3572
3572
3573 Without the -a/--text option, diff will avoid generating diffs of
3573 Without the -a/--text option, diff will avoid generating diffs of
3574 files it detects as binary. With -a, diff will generate a diff
3574 files it detects as binary. With -a, diff will generate a diff
3575 anyway, probably with undesirable results.
3575 anyway, probably with undesirable results.
3576
3576
3577 Use the -g/--git option to generate diffs in the git extended diff
3577 Use the -g/--git option to generate diffs in the git extended diff
3578 format. For more information, read :hg:`help diffs`.
3578 format. For more information, read :hg:`help diffs`.
3579
3579
3580 .. container:: verbose
3580 .. container:: verbose
3581
3581
3582 Examples:
3582 Examples:
3583
3583
3584 - compare a file in the current working directory to its parent::
3584 - compare a file in the current working directory to its parent::
3585
3585
3586 hg diff foo.c
3586 hg diff foo.c
3587
3587
3588 - compare two historical versions of a directory, with rename info::
3588 - compare two historical versions of a directory, with rename info::
3589
3589
3590 hg diff --git -r 1.0:1.2 lib/
3590 hg diff --git -r 1.0:1.2 lib/
3591
3591
3592 - get change stats relative to the last change on some date::
3592 - get change stats relative to the last change on some date::
3593
3593
3594 hg diff --stat -r "date('may 2')"
3594 hg diff --stat -r "date('may 2')"
3595
3595
3596 - diff all newly-added files that contain a keyword::
3596 - diff all newly-added files that contain a keyword::
3597
3597
3598 hg diff "set:added() and grep(GNU)"
3598 hg diff "set:added() and grep(GNU)"
3599
3599
3600 - compare a revision and its parents::
3600 - compare a revision and its parents::
3601
3601
3602 hg diff -c 9353 # compare against first parent
3602 hg diff -c 9353 # compare against first parent
3603 hg diff -r 9353^:9353 # same using revset syntax
3603 hg diff -r 9353^:9353 # same using revset syntax
3604 hg diff -r 9353^2:9353 # compare against the second parent
3604 hg diff -r 9353^2:9353 # compare against the second parent
3605
3605
3606 Returns 0 on success.
3606 Returns 0 on success.
3607 """
3607 """
3608
3608
3609 revs = opts.get('rev')
3609 revs = opts.get('rev')
3610 change = opts.get('change')
3610 change = opts.get('change')
3611 stat = opts.get('stat')
3611 stat = opts.get('stat')
3612 reverse = opts.get('reverse')
3612 reverse = opts.get('reverse')
3613
3613
3614 if revs and change:
3614 if revs and change:
3615 msg = _('cannot specify --rev and --change at the same time')
3615 msg = _('cannot specify --rev and --change at the same time')
3616 raise error.Abort(msg)
3616 raise error.Abort(msg)
3617 elif change:
3617 elif change:
3618 node2 = scmutil.revsingle(repo, change, None).node()
3618 node2 = scmutil.revsingle(repo, change, None).node()
3619 node1 = repo[node2].p1().node()
3619 node1 = repo[node2].p1().node()
3620 else:
3620 else:
3621 node1, node2 = scmutil.revpair(repo, revs)
3621 node1, node2 = scmutil.revpair(repo, revs)
3622
3622
3623 if reverse:
3623 if reverse:
3624 node1, node2 = node2, node1
3624 node1, node2 = node2, node1
3625
3625
3626 diffopts = patch.diffallopts(ui, opts)
3626 diffopts = patch.diffallopts(ui, opts)
3627 m = scmutil.match(repo[node2], pats, opts)
3627 m = scmutil.match(repo[node2], pats, opts)
3628 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3628 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3629 listsubrepos=opts.get('subrepos'),
3629 listsubrepos=opts.get('subrepos'),
3630 root=opts.get('root'))
3630 root=opts.get('root'))
3631
3631
3632 @command('^export',
3632 @command('^export',
3633 [('o', 'output', '',
3633 [('o', 'output', '',
3634 _('print output to file with formatted name'), _('FORMAT')),
3634 _('print output to file with formatted name'), _('FORMAT')),
3635 ('', 'switch-parent', None, _('diff against the second parent')),
3635 ('', 'switch-parent', None, _('diff against the second parent')),
3636 ('r', 'rev', [], _('revisions to export'), _('REV')),
3636 ('r', 'rev', [], _('revisions to export'), _('REV')),
3637 ] + diffopts,
3637 ] + diffopts,
3638 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3638 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3639 def export(ui, repo, *changesets, **opts):
3639 def export(ui, repo, *changesets, **opts):
3640 """dump the header and diffs for one or more changesets
3640 """dump the header and diffs for one or more changesets
3641
3641
3642 Print the changeset header and diffs for one or more revisions.
3642 Print the changeset header and diffs for one or more revisions.
3643 If no revision is given, the parent of the working directory is used.
3643 If no revision is given, the parent of the working directory is used.
3644
3644
3645 The information shown in the changeset header is: author, date,
3645 The information shown in the changeset header is: author, date,
3646 branch name (if non-default), changeset hash, parent(s) and commit
3646 branch name (if non-default), changeset hash, parent(s) and commit
3647 comment.
3647 comment.
3648
3648
3649 .. note::
3649 .. note::
3650
3650
3651 :hg:`export` may generate unexpected diff output for merge
3651 :hg:`export` may generate unexpected diff output for merge
3652 changesets, as it will compare the merge changeset against its
3652 changesets, as it will compare the merge changeset against its
3653 first parent only.
3653 first parent only.
3654
3654
3655 Output may be to a file, in which case the name of the file is
3655 Output may be to a file, in which case the name of the file is
3656 given using a format string. The formatting rules are as follows:
3656 given using a format string. The formatting rules are as follows:
3657
3657
3658 :``%%``: literal "%" character
3658 :``%%``: literal "%" character
3659 :``%H``: changeset hash (40 hexadecimal digits)
3659 :``%H``: changeset hash (40 hexadecimal digits)
3660 :``%N``: number of patches being generated
3660 :``%N``: number of patches being generated
3661 :``%R``: changeset revision number
3661 :``%R``: changeset revision number
3662 :``%b``: basename of the exporting repository
3662 :``%b``: basename of the exporting repository
3663 :``%h``: short-form changeset hash (12 hexadecimal digits)
3663 :``%h``: short-form changeset hash (12 hexadecimal digits)
3664 :``%m``: first line of the commit message (only alphanumeric characters)
3664 :``%m``: first line of the commit message (only alphanumeric characters)
3665 :``%n``: zero-padded sequence number, starting at 1
3665 :``%n``: zero-padded sequence number, starting at 1
3666 :``%r``: zero-padded changeset revision number
3666 :``%r``: zero-padded changeset revision number
3667
3667
3668 Without the -a/--text option, export will avoid generating diffs
3668 Without the -a/--text option, export will avoid generating diffs
3669 of files it detects as binary. With -a, export will generate a
3669 of files it detects as binary. With -a, export will generate a
3670 diff anyway, probably with undesirable results.
3670 diff anyway, probably with undesirable results.
3671
3671
3672 Use the -g/--git option to generate diffs in the git extended diff
3672 Use the -g/--git option to generate diffs in the git extended diff
3673 format. See :hg:`help diffs` for more information.
3673 format. See :hg:`help diffs` for more information.
3674
3674
3675 With the --switch-parent option, the diff will be against the
3675 With the --switch-parent option, the diff will be against the
3676 second parent. It can be useful to review a merge.
3676 second parent. It can be useful to review a merge.
3677
3677
3678 .. container:: verbose
3678 .. container:: verbose
3679
3679
3680 Examples:
3680 Examples:
3681
3681
3682 - use export and import to transplant a bugfix to the current
3682 - use export and import to transplant a bugfix to the current
3683 branch::
3683 branch::
3684
3684
3685 hg export -r 9353 | hg import -
3685 hg export -r 9353 | hg import -
3686
3686
3687 - export all the changesets between two revisions to a file with
3687 - export all the changesets between two revisions to a file with
3688 rename information::
3688 rename information::
3689
3689
3690 hg export --git -r 123:150 > changes.txt
3690 hg export --git -r 123:150 > changes.txt
3691
3691
3692 - split outgoing changes into a series of patches with
3692 - split outgoing changes into a series of patches with
3693 descriptive names::
3693 descriptive names::
3694
3694
3695 hg export -r "outgoing()" -o "%n-%m.patch"
3695 hg export -r "outgoing()" -o "%n-%m.patch"
3696
3696
3697 Returns 0 on success.
3697 Returns 0 on success.
3698 """
3698 """
3699 changesets += tuple(opts.get('rev', []))
3699 changesets += tuple(opts.get('rev', []))
3700 if not changesets:
3700 if not changesets:
3701 changesets = ['.']
3701 changesets = ['.']
3702 revs = scmutil.revrange(repo, changesets)
3702 revs = scmutil.revrange(repo, changesets)
3703 if not revs:
3703 if not revs:
3704 raise error.Abort(_("export requires at least one changeset"))
3704 raise error.Abort(_("export requires at least one changeset"))
3705 if len(revs) > 1:
3705 if len(revs) > 1:
3706 ui.note(_('exporting patches:\n'))
3706 ui.note(_('exporting patches:\n'))
3707 else:
3707 else:
3708 ui.note(_('exporting patch:\n'))
3708 ui.note(_('exporting patch:\n'))
3709 cmdutil.export(repo, revs, template=opts.get('output'),
3709 cmdutil.export(repo, revs, template=opts.get('output'),
3710 switch_parent=opts.get('switch_parent'),
3710 switch_parent=opts.get('switch_parent'),
3711 opts=patch.diffallopts(ui, opts))
3711 opts=patch.diffallopts(ui, opts))
3712
3712
3713 @command('files',
3713 @command('files',
3714 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3714 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3715 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3715 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3716 ] + walkopts + formatteropts + subrepoopts,
3716 ] + walkopts + formatteropts + subrepoopts,
3717 _('[OPTION]... [PATTERN]...'))
3717 _('[OPTION]... [PATTERN]...'))
3718 def files(ui, repo, *pats, **opts):
3718 def files(ui, repo, *pats, **opts):
3719 """list tracked files
3719 """list tracked files
3720
3720
3721 Print files under Mercurial control in the working directory or
3721 Print files under Mercurial control in the working directory or
3722 specified revision whose names match the given patterns (excluding
3722 specified revision whose names match the given patterns (excluding
3723 removed files).
3723 removed files).
3724
3724
3725 If no patterns are given to match, this command prints the names
3725 If no patterns are given to match, this command prints the names
3726 of all files under Mercurial control in the working directory.
3726 of all files under Mercurial control in the working directory.
3727
3727
3728 .. container:: verbose
3728 .. container:: verbose
3729
3729
3730 Examples:
3730 Examples:
3731
3731
3732 - list all files under the current directory::
3732 - list all files under the current directory::
3733
3733
3734 hg files .
3734 hg files .
3735
3735
3736 - shows sizes and flags for current revision::
3736 - shows sizes and flags for current revision::
3737
3737
3738 hg files -vr .
3738 hg files -vr .
3739
3739
3740 - list all files named README::
3740 - list all files named README::
3741
3741
3742 hg files -I "**/README"
3742 hg files -I "**/README"
3743
3743
3744 - list all binary files::
3744 - list all binary files::
3745
3745
3746 hg files "set:binary()"
3746 hg files "set:binary()"
3747
3747
3748 - find files containing a regular expression::
3748 - find files containing a regular expression::
3749
3749
3750 hg files "set:grep('bob')"
3750 hg files "set:grep('bob')"
3751
3751
3752 - search tracked file contents with xargs and grep::
3752 - search tracked file contents with xargs and grep::
3753
3753
3754 hg files -0 | xargs -0 grep foo
3754 hg files -0 | xargs -0 grep foo
3755
3755
3756 See :hg:`help patterns` and :hg:`help filesets` for more information
3756 See :hg:`help patterns` and :hg:`help filesets` for more information
3757 on specifying file patterns.
3757 on specifying file patterns.
3758
3758
3759 Returns 0 if a match is found, 1 otherwise.
3759 Returns 0 if a match is found, 1 otherwise.
3760
3760
3761 """
3761 """
3762 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3762 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3763
3763
3764 end = '\n'
3764 end = '\n'
3765 if opts.get('print0'):
3765 if opts.get('print0'):
3766 end = '\0'
3766 end = '\0'
3767 fm = ui.formatter('files', opts)
3767 fm = ui.formatter('files', opts)
3768 fmt = '%s' + end
3768 fmt = '%s' + end
3769
3769
3770 m = scmutil.match(ctx, pats, opts)
3770 m = scmutil.match(ctx, pats, opts)
3771 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3771 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3772
3772
3773 fm.end()
3773 fm.end()
3774
3774
3775 return ret
3775 return ret
3776
3776
3777 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3777 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3778 def forget(ui, repo, *pats, **opts):
3778 def forget(ui, repo, *pats, **opts):
3779 """forget the specified files on the next commit
3779 """forget the specified files on the next commit
3780
3780
3781 Mark the specified files so they will no longer be tracked
3781 Mark the specified files so they will no longer be tracked
3782 after the next commit.
3782 after the next commit.
3783
3783
3784 This only removes files from the current branch, not from the
3784 This only removes files from the current branch, not from the
3785 entire project history, and it does not delete them from the
3785 entire project history, and it does not delete them from the
3786 working directory.
3786 working directory.
3787
3787
3788 To delete the file from the working directory, see :hg:`remove`.
3788 To delete the file from the working directory, see :hg:`remove`.
3789
3789
3790 To undo a forget before the next commit, see :hg:`add`.
3790 To undo a forget before the next commit, see :hg:`add`.
3791
3791
3792 .. container:: verbose
3792 .. container:: verbose
3793
3793
3794 Examples:
3794 Examples:
3795
3795
3796 - forget newly-added binary files::
3796 - forget newly-added binary files::
3797
3797
3798 hg forget "set:added() and binary()"
3798 hg forget "set:added() and binary()"
3799
3799
3800 - forget files that would be excluded by .hgignore::
3800 - forget files that would be excluded by .hgignore::
3801
3801
3802 hg forget "set:hgignore()"
3802 hg forget "set:hgignore()"
3803
3803
3804 Returns 0 on success.
3804 Returns 0 on success.
3805 """
3805 """
3806
3806
3807 if not pats:
3807 if not pats:
3808 raise error.Abort(_('no files specified'))
3808 raise error.Abort(_('no files specified'))
3809
3809
3810 m = scmutil.match(repo[None], pats, opts)
3810 m = scmutil.match(repo[None], pats, opts)
3811 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3811 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3812 return rejected and 1 or 0
3812 return rejected and 1 or 0
3813
3813
3814 @command(
3814 @command(
3815 'graft',
3815 'graft',
3816 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3816 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3817 ('c', 'continue', False, _('resume interrupted graft')),
3817 ('c', 'continue', False, _('resume interrupted graft')),
3818 ('e', 'edit', False, _('invoke editor on commit messages')),
3818 ('e', 'edit', False, _('invoke editor on commit messages')),
3819 ('', 'log', None, _('append graft info to log message')),
3819 ('', 'log', None, _('append graft info to log message')),
3820 ('f', 'force', False, _('force graft')),
3820 ('f', 'force', False, _('force graft')),
3821 ('D', 'currentdate', False,
3821 ('D', 'currentdate', False,
3822 _('record the current date as commit date')),
3822 _('record the current date as commit date')),
3823 ('U', 'currentuser', False,
3823 ('U', 'currentuser', False,
3824 _('record the current user as committer'), _('DATE'))]
3824 _('record the current user as committer'), _('DATE'))]
3825 + commitopts2 + mergetoolopts + dryrunopts,
3825 + commitopts2 + mergetoolopts + dryrunopts,
3826 _('[OPTION]... [-r REV]... REV...'))
3826 _('[OPTION]... [-r REV]... REV...'))
3827 def graft(ui, repo, *revs, **opts):
3827 def graft(ui, repo, *revs, **opts):
3828 '''copy changes from other branches onto the current branch
3828 '''copy changes from other branches onto the current branch
3829
3829
3830 This command uses Mercurial's merge logic to copy individual
3830 This command uses Mercurial's merge logic to copy individual
3831 changes from other branches without merging branches in the
3831 changes from other branches without merging branches in the
3832 history graph. This is sometimes known as 'backporting' or
3832 history graph. This is sometimes known as 'backporting' or
3833 'cherry-picking'. By default, graft will copy user, date, and
3833 'cherry-picking'. By default, graft will copy user, date, and
3834 description from the source changesets.
3834 description from the source changesets.
3835
3835
3836 Changesets that are ancestors of the current revision, that have
3836 Changesets that are ancestors of the current revision, that have
3837 already been grafted, or that are merges will be skipped.
3837 already been grafted, or that are merges will be skipped.
3838
3838
3839 If --log is specified, log messages will have a comment appended
3839 If --log is specified, log messages will have a comment appended
3840 of the form::
3840 of the form::
3841
3841
3842 (grafted from CHANGESETHASH)
3842 (grafted from CHANGESETHASH)
3843
3843
3844 If --force is specified, revisions will be grafted even if they
3844 If --force is specified, revisions will be grafted even if they
3845 are already ancestors of or have been grafted to the destination.
3845 are already ancestors of or have been grafted to the destination.
3846 This is useful when the revisions have since been backed out.
3846 This is useful when the revisions have since been backed out.
3847
3847
3848 If a graft merge results in conflicts, the graft process is
3848 If a graft merge results in conflicts, the graft process is
3849 interrupted so that the current merge can be manually resolved.
3849 interrupted so that the current merge can be manually resolved.
3850 Once all conflicts are addressed, the graft process can be
3850 Once all conflicts are addressed, the graft process can be
3851 continued with the -c/--continue option.
3851 continued with the -c/--continue option.
3852
3852
3853 .. note::
3853 .. note::
3854
3854
3855 The -c/--continue option does not reapply earlier options, except
3855 The -c/--continue option does not reapply earlier options, except
3856 for --force.
3856 for --force.
3857
3857
3858 .. container:: verbose
3858 .. container:: verbose
3859
3859
3860 Examples:
3860 Examples:
3861
3861
3862 - copy a single change to the stable branch and edit its description::
3862 - copy a single change to the stable branch and edit its description::
3863
3863
3864 hg update stable
3864 hg update stable
3865 hg graft --edit 9393
3865 hg graft --edit 9393
3866
3866
3867 - graft a range of changesets with one exception, updating dates::
3867 - graft a range of changesets with one exception, updating dates::
3868
3868
3869 hg graft -D "2085::2093 and not 2091"
3869 hg graft -D "2085::2093 and not 2091"
3870
3870
3871 - continue a graft after resolving conflicts::
3871 - continue a graft after resolving conflicts::
3872
3872
3873 hg graft -c
3873 hg graft -c
3874
3874
3875 - show the source of a grafted changeset::
3875 - show the source of a grafted changeset::
3876
3876
3877 hg log --debug -r .
3877 hg log --debug -r .
3878
3878
3879 - show revisions sorted by date::
3879 - show revisions sorted by date::
3880
3880
3881 hg log -r 'sort(all(), date)'
3881 hg log -r 'sort(all(), date)'
3882
3882
3883 See :hg:`help revisions` and :hg:`help revsets` for more about
3883 See :hg:`help revisions` and :hg:`help revsets` for more about
3884 specifying revisions.
3884 specifying revisions.
3885
3885
3886 Returns 0 on successful completion.
3886 Returns 0 on successful completion.
3887 '''
3887 '''
3888 with repo.wlock():
3888 with repo.wlock():
3889 return _dograft(ui, repo, *revs, **opts)
3889 return _dograft(ui, repo, *revs, **opts)
3890
3890
3891 def _dograft(ui, repo, *revs, **opts):
3891 def _dograft(ui, repo, *revs, **opts):
3892 if revs and opts['rev']:
3893 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
3894 'revision ordering!\n'))
3895
3892 revs = list(revs)
3896 revs = list(revs)
3893 revs.extend(opts['rev'])
3897 revs.extend(opts['rev'])
3894
3898
3895 if not opts.get('user') and opts.get('currentuser'):
3899 if not opts.get('user') and opts.get('currentuser'):
3896 opts['user'] = ui.username()
3900 opts['user'] = ui.username()
3897 if not opts.get('date') and opts.get('currentdate'):
3901 if not opts.get('date') and opts.get('currentdate'):
3898 opts['date'] = "%d %d" % util.makedate()
3902 opts['date'] = "%d %d" % util.makedate()
3899
3903
3900 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3904 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3901
3905
3902 cont = False
3906 cont = False
3903 if opts['continue']:
3907 if opts['continue']:
3904 cont = True
3908 cont = True
3905 if revs:
3909 if revs:
3906 raise error.Abort(_("can't specify --continue and revisions"))
3910 raise error.Abort(_("can't specify --continue and revisions"))
3907 # read in unfinished revisions
3911 # read in unfinished revisions
3908 try:
3912 try:
3909 nodes = repo.vfs.read('graftstate').splitlines()
3913 nodes = repo.vfs.read('graftstate').splitlines()
3910 revs = [repo[node].rev() for node in nodes]
3914 revs = [repo[node].rev() for node in nodes]
3911 except IOError as inst:
3915 except IOError as inst:
3912 if inst.errno != errno.ENOENT:
3916 if inst.errno != errno.ENOENT:
3913 raise
3917 raise
3914 raise error.Abort(_("no graft state found, can't continue"))
3918 raise error.Abort(_("no graft state found, can't continue"))
3915 else:
3919 else:
3916 cmdutil.checkunfinished(repo)
3920 cmdutil.checkunfinished(repo)
3917 cmdutil.bailifchanged(repo)
3921 cmdutil.bailifchanged(repo)
3918 if not revs:
3922 if not revs:
3919 raise error.Abort(_('no revisions specified'))
3923 raise error.Abort(_('no revisions specified'))
3920 revs = scmutil.revrange(repo, revs)
3924 revs = scmutil.revrange(repo, revs)
3921
3925
3922 skipped = set()
3926 skipped = set()
3923 # check for merges
3927 # check for merges
3924 for rev in repo.revs('%ld and merge()', revs):
3928 for rev in repo.revs('%ld and merge()', revs):
3925 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3929 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3926 skipped.add(rev)
3930 skipped.add(rev)
3927 revs = [r for r in revs if r not in skipped]
3931 revs = [r for r in revs if r not in skipped]
3928 if not revs:
3932 if not revs:
3929 return -1
3933 return -1
3930
3934
3931 # Don't check in the --continue case, in effect retaining --force across
3935 # Don't check in the --continue case, in effect retaining --force across
3932 # --continues. That's because without --force, any revisions we decided to
3936 # --continues. That's because without --force, any revisions we decided to
3933 # skip would have been filtered out here, so they wouldn't have made their
3937 # skip would have been filtered out here, so they wouldn't have made their
3934 # way to the graftstate. With --force, any revisions we would have otherwise
3938 # way to the graftstate. With --force, any revisions we would have otherwise
3935 # skipped would not have been filtered out, and if they hadn't been applied
3939 # skipped would not have been filtered out, and if they hadn't been applied
3936 # already, they'd have been in the graftstate.
3940 # already, they'd have been in the graftstate.
3937 if not (cont or opts.get('force')):
3941 if not (cont or opts.get('force')):
3938 # check for ancestors of dest branch
3942 # check for ancestors of dest branch
3939 crev = repo['.'].rev()
3943 crev = repo['.'].rev()
3940 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3944 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3941 # Cannot use x.remove(y) on smart set, this has to be a list.
3945 # Cannot use x.remove(y) on smart set, this has to be a list.
3942 # XXX make this lazy in the future
3946 # XXX make this lazy in the future
3943 revs = list(revs)
3947 revs = list(revs)
3944 # don't mutate while iterating, create a copy
3948 # don't mutate while iterating, create a copy
3945 for rev in list(revs):
3949 for rev in list(revs):
3946 if rev in ancestors:
3950 if rev in ancestors:
3947 ui.warn(_('skipping ancestor revision %d:%s\n') %
3951 ui.warn(_('skipping ancestor revision %d:%s\n') %
3948 (rev, repo[rev]))
3952 (rev, repo[rev]))
3949 # XXX remove on list is slow
3953 # XXX remove on list is slow
3950 revs.remove(rev)
3954 revs.remove(rev)
3951 if not revs:
3955 if not revs:
3952 return -1
3956 return -1
3953
3957
3954 # analyze revs for earlier grafts
3958 # analyze revs for earlier grafts
3955 ids = {}
3959 ids = {}
3956 for ctx in repo.set("%ld", revs):
3960 for ctx in repo.set("%ld", revs):
3957 ids[ctx.hex()] = ctx.rev()
3961 ids[ctx.hex()] = ctx.rev()
3958 n = ctx.extra().get('source')
3962 n = ctx.extra().get('source')
3959 if n:
3963 if n:
3960 ids[n] = ctx.rev()
3964 ids[n] = ctx.rev()
3961
3965
3962 # check ancestors for earlier grafts
3966 # check ancestors for earlier grafts
3963 ui.debug('scanning for duplicate grafts\n')
3967 ui.debug('scanning for duplicate grafts\n')
3964
3968
3965 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3969 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3966 ctx = repo[rev]
3970 ctx = repo[rev]
3967 n = ctx.extra().get('source')
3971 n = ctx.extra().get('source')
3968 if n in ids:
3972 if n in ids:
3969 try:
3973 try:
3970 r = repo[n].rev()
3974 r = repo[n].rev()
3971 except error.RepoLookupError:
3975 except error.RepoLookupError:
3972 r = None
3976 r = None
3973 if r in revs:
3977 if r in revs:
3974 ui.warn(_('skipping revision %d:%s '
3978 ui.warn(_('skipping revision %d:%s '
3975 '(already grafted to %d:%s)\n')
3979 '(already grafted to %d:%s)\n')
3976 % (r, repo[r], rev, ctx))
3980 % (r, repo[r], rev, ctx))
3977 revs.remove(r)
3981 revs.remove(r)
3978 elif ids[n] in revs:
3982 elif ids[n] in revs:
3979 if r is None:
3983 if r is None:
3980 ui.warn(_('skipping already grafted revision %d:%s '
3984 ui.warn(_('skipping already grafted revision %d:%s '
3981 '(%d:%s also has unknown origin %s)\n')
3985 '(%d:%s also has unknown origin %s)\n')
3982 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3986 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3983 else:
3987 else:
3984 ui.warn(_('skipping already grafted revision %d:%s '
3988 ui.warn(_('skipping already grafted revision %d:%s '
3985 '(%d:%s also has origin %d:%s)\n')
3989 '(%d:%s also has origin %d:%s)\n')
3986 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3990 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3987 revs.remove(ids[n])
3991 revs.remove(ids[n])
3988 elif ctx.hex() in ids:
3992 elif ctx.hex() in ids:
3989 r = ids[ctx.hex()]
3993 r = ids[ctx.hex()]
3990 ui.warn(_('skipping already grafted revision %d:%s '
3994 ui.warn(_('skipping already grafted revision %d:%s '
3991 '(was grafted from %d:%s)\n') %
3995 '(was grafted from %d:%s)\n') %
3992 (r, repo[r], rev, ctx))
3996 (r, repo[r], rev, ctx))
3993 revs.remove(r)
3997 revs.remove(r)
3994 if not revs:
3998 if not revs:
3995 return -1
3999 return -1
3996
4000
3997 for pos, ctx in enumerate(repo.set("%ld", revs)):
4001 for pos, ctx in enumerate(repo.set("%ld", revs)):
3998 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4002 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3999 ctx.description().split('\n', 1)[0])
4003 ctx.description().split('\n', 1)[0])
4000 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4004 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4001 if names:
4005 if names:
4002 desc += ' (%s)' % ' '.join(names)
4006 desc += ' (%s)' % ' '.join(names)
4003 ui.status(_('grafting %s\n') % desc)
4007 ui.status(_('grafting %s\n') % desc)
4004 if opts.get('dry_run'):
4008 if opts.get('dry_run'):
4005 continue
4009 continue
4006
4010
4007 extra = ctx.extra().copy()
4011 extra = ctx.extra().copy()
4008 del extra['branch']
4012 del extra['branch']
4009 source = extra.get('source')
4013 source = extra.get('source')
4010 if source:
4014 if source:
4011 extra['intermediate-source'] = ctx.hex()
4015 extra['intermediate-source'] = ctx.hex()
4012 else:
4016 else:
4013 extra['source'] = ctx.hex()
4017 extra['source'] = ctx.hex()
4014 user = ctx.user()
4018 user = ctx.user()
4015 if opts.get('user'):
4019 if opts.get('user'):
4016 user = opts['user']
4020 user = opts['user']
4017 date = ctx.date()
4021 date = ctx.date()
4018 if opts.get('date'):
4022 if opts.get('date'):
4019 date = opts['date']
4023 date = opts['date']
4020 message = ctx.description()
4024 message = ctx.description()
4021 if opts.get('log'):
4025 if opts.get('log'):
4022 message += '\n(grafted from %s)' % ctx.hex()
4026 message += '\n(grafted from %s)' % ctx.hex()
4023
4027
4024 # we don't merge the first commit when continuing
4028 # we don't merge the first commit when continuing
4025 if not cont:
4029 if not cont:
4026 # perform the graft merge with p1(rev) as 'ancestor'
4030 # perform the graft merge with p1(rev) as 'ancestor'
4027 try:
4031 try:
4028 # ui.forcemerge is an internal variable, do not document
4032 # ui.forcemerge is an internal variable, do not document
4029 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4033 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4030 'graft')
4034 'graft')
4031 stats = mergemod.graft(repo, ctx, ctx.p1(),
4035 stats = mergemod.graft(repo, ctx, ctx.p1(),
4032 ['local', 'graft'])
4036 ['local', 'graft'])
4033 finally:
4037 finally:
4034 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4038 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4035 # report any conflicts
4039 # report any conflicts
4036 if stats and stats[3] > 0:
4040 if stats and stats[3] > 0:
4037 # write out state for --continue
4041 # write out state for --continue
4038 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4042 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4039 repo.vfs.write('graftstate', ''.join(nodelines))
4043 repo.vfs.write('graftstate', ''.join(nodelines))
4040 extra = ''
4044 extra = ''
4041 if opts.get('user'):
4045 if opts.get('user'):
4042 extra += ' --user %s' % opts['user']
4046 extra += ' --user %s' % opts['user']
4043 if opts.get('date'):
4047 if opts.get('date'):
4044 extra += ' --date %s' % opts['date']
4048 extra += ' --date %s' % opts['date']
4045 if opts.get('log'):
4049 if opts.get('log'):
4046 extra += ' --log'
4050 extra += ' --log'
4047 hint=_('use hg resolve and hg graft --continue%s') % extra
4051 hint=_('use hg resolve and hg graft --continue%s') % extra
4048 raise error.Abort(
4052 raise error.Abort(
4049 _("unresolved conflicts, can't continue"),
4053 _("unresolved conflicts, can't continue"),
4050 hint=hint)
4054 hint=hint)
4051 else:
4055 else:
4052 cont = False
4056 cont = False
4053
4057
4054 # commit
4058 # commit
4055 node = repo.commit(text=message, user=user,
4059 node = repo.commit(text=message, user=user,
4056 date=date, extra=extra, editor=editor)
4060 date=date, extra=extra, editor=editor)
4057 if node is None:
4061 if node is None:
4058 ui.warn(
4062 ui.warn(
4059 _('note: graft of %d:%s created no changes to commit\n') %
4063 _('note: graft of %d:%s created no changes to commit\n') %
4060 (ctx.rev(), ctx))
4064 (ctx.rev(), ctx))
4061
4065
4062 # remove state when we complete successfully
4066 # remove state when we complete successfully
4063 if not opts.get('dry_run'):
4067 if not opts.get('dry_run'):
4064 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4068 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4065
4069
4066 return 0
4070 return 0
4067
4071
4068 @command('grep',
4072 @command('grep',
4069 [('0', 'print0', None, _('end fields with NUL')),
4073 [('0', 'print0', None, _('end fields with NUL')),
4070 ('', 'all', None, _('print all revisions that match')),
4074 ('', 'all', None, _('print all revisions that match')),
4071 ('a', 'text', None, _('treat all files as text')),
4075 ('a', 'text', None, _('treat all files as text')),
4072 ('f', 'follow', None,
4076 ('f', 'follow', None,
4073 _('follow changeset history,'
4077 _('follow changeset history,'
4074 ' or file history across copies and renames')),
4078 ' or file history across copies and renames')),
4075 ('i', 'ignore-case', None, _('ignore case when matching')),
4079 ('i', 'ignore-case', None, _('ignore case when matching')),
4076 ('l', 'files-with-matches', None,
4080 ('l', 'files-with-matches', None,
4077 _('print only filenames and revisions that match')),
4081 _('print only filenames and revisions that match')),
4078 ('n', 'line-number', None, _('print matching line numbers')),
4082 ('n', 'line-number', None, _('print matching line numbers')),
4079 ('r', 'rev', [],
4083 ('r', 'rev', [],
4080 _('only search files changed within revision range'), _('REV')),
4084 _('only search files changed within revision range'), _('REV')),
4081 ('u', 'user', None, _('list the author (long with -v)')),
4085 ('u', 'user', None, _('list the author (long with -v)')),
4082 ('d', 'date', None, _('list the date (short with -q)')),
4086 ('d', 'date', None, _('list the date (short with -q)')),
4083 ] + walkopts,
4087 ] + walkopts,
4084 _('[OPTION]... PATTERN [FILE]...'),
4088 _('[OPTION]... PATTERN [FILE]...'),
4085 inferrepo=True)
4089 inferrepo=True)
4086 def grep(ui, repo, pattern, *pats, **opts):
4090 def grep(ui, repo, pattern, *pats, **opts):
4087 """search for a pattern in specified files and revisions
4091 """search for a pattern in specified files and revisions
4088
4092
4089 Search revisions of files for a regular expression.
4093 Search revisions of files for a regular expression.
4090
4094
4091 This command behaves differently than Unix grep. It only accepts
4095 This command behaves differently than Unix grep. It only accepts
4092 Python/Perl regexps. It searches repository history, not the
4096 Python/Perl regexps. It searches repository history, not the
4093 working directory. It always prints the revision number in which a
4097 working directory. It always prints the revision number in which a
4094 match appears.
4098 match appears.
4095
4099
4096 By default, grep only prints output for the first revision of a
4100 By default, grep only prints output for the first revision of a
4097 file in which it finds a match. To get it to print every revision
4101 file in which it finds a match. To get it to print every revision
4098 that contains a change in match status ("-" for a match that
4102 that contains a change in match status ("-" for a match that
4099 becomes a non-match, or "+" for a non-match that becomes a match),
4103 becomes a non-match, or "+" for a non-match that becomes a match),
4100 use the --all flag.
4104 use the --all flag.
4101
4105
4102 Returns 0 if a match is found, 1 otherwise.
4106 Returns 0 if a match is found, 1 otherwise.
4103 """
4107 """
4104 reflags = re.M
4108 reflags = re.M
4105 if opts.get('ignore_case'):
4109 if opts.get('ignore_case'):
4106 reflags |= re.I
4110 reflags |= re.I
4107 try:
4111 try:
4108 regexp = util.re.compile(pattern, reflags)
4112 regexp = util.re.compile(pattern, reflags)
4109 except re.error as inst:
4113 except re.error as inst:
4110 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4114 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4111 return 1
4115 return 1
4112 sep, eol = ':', '\n'
4116 sep, eol = ':', '\n'
4113 if opts.get('print0'):
4117 if opts.get('print0'):
4114 sep = eol = '\0'
4118 sep = eol = '\0'
4115
4119
4116 getfile = util.lrucachefunc(repo.file)
4120 getfile = util.lrucachefunc(repo.file)
4117
4121
4118 def matchlines(body):
4122 def matchlines(body):
4119 begin = 0
4123 begin = 0
4120 linenum = 0
4124 linenum = 0
4121 while begin < len(body):
4125 while begin < len(body):
4122 match = regexp.search(body, begin)
4126 match = regexp.search(body, begin)
4123 if not match:
4127 if not match:
4124 break
4128 break
4125 mstart, mend = match.span()
4129 mstart, mend = match.span()
4126 linenum += body.count('\n', begin, mstart) + 1
4130 linenum += body.count('\n', begin, mstart) + 1
4127 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4131 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4128 begin = body.find('\n', mend) + 1 or len(body) + 1
4132 begin = body.find('\n', mend) + 1 or len(body) + 1
4129 lend = begin - 1
4133 lend = begin - 1
4130 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4134 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4131
4135
4132 class linestate(object):
4136 class linestate(object):
4133 def __init__(self, line, linenum, colstart, colend):
4137 def __init__(self, line, linenum, colstart, colend):
4134 self.line = line
4138 self.line = line
4135 self.linenum = linenum
4139 self.linenum = linenum
4136 self.colstart = colstart
4140 self.colstart = colstart
4137 self.colend = colend
4141 self.colend = colend
4138
4142
4139 def __hash__(self):
4143 def __hash__(self):
4140 return hash((self.linenum, self.line))
4144 return hash((self.linenum, self.line))
4141
4145
4142 def __eq__(self, other):
4146 def __eq__(self, other):
4143 return self.line == other.line
4147 return self.line == other.line
4144
4148
4145 def __iter__(self):
4149 def __iter__(self):
4146 yield (self.line[:self.colstart], '')
4150 yield (self.line[:self.colstart], '')
4147 yield (self.line[self.colstart:self.colend], 'grep.match')
4151 yield (self.line[self.colstart:self.colend], 'grep.match')
4148 rest = self.line[self.colend:]
4152 rest = self.line[self.colend:]
4149 while rest != '':
4153 while rest != '':
4150 match = regexp.search(rest)
4154 match = regexp.search(rest)
4151 if not match:
4155 if not match:
4152 yield (rest, '')
4156 yield (rest, '')
4153 break
4157 break
4154 mstart, mend = match.span()
4158 mstart, mend = match.span()
4155 yield (rest[:mstart], '')
4159 yield (rest[:mstart], '')
4156 yield (rest[mstart:mend], 'grep.match')
4160 yield (rest[mstart:mend], 'grep.match')
4157 rest = rest[mend:]
4161 rest = rest[mend:]
4158
4162
4159 matches = {}
4163 matches = {}
4160 copies = {}
4164 copies = {}
4161 def grepbody(fn, rev, body):
4165 def grepbody(fn, rev, body):
4162 matches[rev].setdefault(fn, [])
4166 matches[rev].setdefault(fn, [])
4163 m = matches[rev][fn]
4167 m = matches[rev][fn]
4164 for lnum, cstart, cend, line in matchlines(body):
4168 for lnum, cstart, cend, line in matchlines(body):
4165 s = linestate(line, lnum, cstart, cend)
4169 s = linestate(line, lnum, cstart, cend)
4166 m.append(s)
4170 m.append(s)
4167
4171
4168 def difflinestates(a, b):
4172 def difflinestates(a, b):
4169 sm = difflib.SequenceMatcher(None, a, b)
4173 sm = difflib.SequenceMatcher(None, a, b)
4170 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4174 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4171 if tag == 'insert':
4175 if tag == 'insert':
4172 for i in xrange(blo, bhi):
4176 for i in xrange(blo, bhi):
4173 yield ('+', b[i])
4177 yield ('+', b[i])
4174 elif tag == 'delete':
4178 elif tag == 'delete':
4175 for i in xrange(alo, ahi):
4179 for i in xrange(alo, ahi):
4176 yield ('-', a[i])
4180 yield ('-', a[i])
4177 elif tag == 'replace':
4181 elif tag == 'replace':
4178 for i in xrange(alo, ahi):
4182 for i in xrange(alo, ahi):
4179 yield ('-', a[i])
4183 yield ('-', a[i])
4180 for i in xrange(blo, bhi):
4184 for i in xrange(blo, bhi):
4181 yield ('+', b[i])
4185 yield ('+', b[i])
4182
4186
4183 def display(fn, ctx, pstates, states):
4187 def display(fn, ctx, pstates, states):
4184 rev = ctx.rev()
4188 rev = ctx.rev()
4185 if ui.quiet:
4189 if ui.quiet:
4186 datefunc = util.shortdate
4190 datefunc = util.shortdate
4187 else:
4191 else:
4188 datefunc = util.datestr
4192 datefunc = util.datestr
4189 found = False
4193 found = False
4190 @util.cachefunc
4194 @util.cachefunc
4191 def binary():
4195 def binary():
4192 flog = getfile(fn)
4196 flog = getfile(fn)
4193 return util.binary(flog.read(ctx.filenode(fn)))
4197 return util.binary(flog.read(ctx.filenode(fn)))
4194
4198
4195 if opts.get('all'):
4199 if opts.get('all'):
4196 iter = difflinestates(pstates, states)
4200 iter = difflinestates(pstates, states)
4197 else:
4201 else:
4198 iter = [('', l) for l in states]
4202 iter = [('', l) for l in states]
4199 for change, l in iter:
4203 for change, l in iter:
4200 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4204 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4201
4205
4202 if opts.get('line_number'):
4206 if opts.get('line_number'):
4203 cols.append((str(l.linenum), 'grep.linenumber'))
4207 cols.append((str(l.linenum), 'grep.linenumber'))
4204 if opts.get('all'):
4208 if opts.get('all'):
4205 cols.append((change, 'grep.change'))
4209 cols.append((change, 'grep.change'))
4206 if opts.get('user'):
4210 if opts.get('user'):
4207 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4211 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4208 if opts.get('date'):
4212 if opts.get('date'):
4209 cols.append((datefunc(ctx.date()), 'grep.date'))
4213 cols.append((datefunc(ctx.date()), 'grep.date'))
4210 for col, label in cols[:-1]:
4214 for col, label in cols[:-1]:
4211 ui.write(col, label=label)
4215 ui.write(col, label=label)
4212 ui.write(sep, label='grep.sep')
4216 ui.write(sep, label='grep.sep')
4213 ui.write(cols[-1][0], label=cols[-1][1])
4217 ui.write(cols[-1][0], label=cols[-1][1])
4214 if not opts.get('files_with_matches'):
4218 if not opts.get('files_with_matches'):
4215 ui.write(sep, label='grep.sep')
4219 ui.write(sep, label='grep.sep')
4216 if not opts.get('text') and binary():
4220 if not opts.get('text') and binary():
4217 ui.write(" Binary file matches")
4221 ui.write(" Binary file matches")
4218 else:
4222 else:
4219 for s, label in l:
4223 for s, label in l:
4220 ui.write(s, label=label)
4224 ui.write(s, label=label)
4221 ui.write(eol)
4225 ui.write(eol)
4222 found = True
4226 found = True
4223 if opts.get('files_with_matches'):
4227 if opts.get('files_with_matches'):
4224 break
4228 break
4225 return found
4229 return found
4226
4230
4227 skip = {}
4231 skip = {}
4228 revfiles = {}
4232 revfiles = {}
4229 matchfn = scmutil.match(repo[None], pats, opts)
4233 matchfn = scmutil.match(repo[None], pats, opts)
4230 found = False
4234 found = False
4231 follow = opts.get('follow')
4235 follow = opts.get('follow')
4232
4236
4233 def prep(ctx, fns):
4237 def prep(ctx, fns):
4234 rev = ctx.rev()
4238 rev = ctx.rev()
4235 pctx = ctx.p1()
4239 pctx = ctx.p1()
4236 parent = pctx.rev()
4240 parent = pctx.rev()
4237 matches.setdefault(rev, {})
4241 matches.setdefault(rev, {})
4238 matches.setdefault(parent, {})
4242 matches.setdefault(parent, {})
4239 files = revfiles.setdefault(rev, [])
4243 files = revfiles.setdefault(rev, [])
4240 for fn in fns:
4244 for fn in fns:
4241 flog = getfile(fn)
4245 flog = getfile(fn)
4242 try:
4246 try:
4243 fnode = ctx.filenode(fn)
4247 fnode = ctx.filenode(fn)
4244 except error.LookupError:
4248 except error.LookupError:
4245 continue
4249 continue
4246
4250
4247 copied = flog.renamed(fnode)
4251 copied = flog.renamed(fnode)
4248 copy = follow and copied and copied[0]
4252 copy = follow and copied and copied[0]
4249 if copy:
4253 if copy:
4250 copies.setdefault(rev, {})[fn] = copy
4254 copies.setdefault(rev, {})[fn] = copy
4251 if fn in skip:
4255 if fn in skip:
4252 if copy:
4256 if copy:
4253 skip[copy] = True
4257 skip[copy] = True
4254 continue
4258 continue
4255 files.append(fn)
4259 files.append(fn)
4256
4260
4257 if fn not in matches[rev]:
4261 if fn not in matches[rev]:
4258 grepbody(fn, rev, flog.read(fnode))
4262 grepbody(fn, rev, flog.read(fnode))
4259
4263
4260 pfn = copy or fn
4264 pfn = copy or fn
4261 if pfn not in matches[parent]:
4265 if pfn not in matches[parent]:
4262 try:
4266 try:
4263 fnode = pctx.filenode(pfn)
4267 fnode = pctx.filenode(pfn)
4264 grepbody(pfn, parent, flog.read(fnode))
4268 grepbody(pfn, parent, flog.read(fnode))
4265 except error.LookupError:
4269 except error.LookupError:
4266 pass
4270 pass
4267
4271
4268 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4272 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4269 rev = ctx.rev()
4273 rev = ctx.rev()
4270 parent = ctx.p1().rev()
4274 parent = ctx.p1().rev()
4271 for fn in sorted(revfiles.get(rev, [])):
4275 for fn in sorted(revfiles.get(rev, [])):
4272 states = matches[rev][fn]
4276 states = matches[rev][fn]
4273 copy = copies.get(rev, {}).get(fn)
4277 copy = copies.get(rev, {}).get(fn)
4274 if fn in skip:
4278 if fn in skip:
4275 if copy:
4279 if copy:
4276 skip[copy] = True
4280 skip[copy] = True
4277 continue
4281 continue
4278 pstates = matches.get(parent, {}).get(copy or fn, [])
4282 pstates = matches.get(parent, {}).get(copy or fn, [])
4279 if pstates or states:
4283 if pstates or states:
4280 r = display(fn, ctx, pstates, states)
4284 r = display(fn, ctx, pstates, states)
4281 found = found or r
4285 found = found or r
4282 if r and not opts.get('all'):
4286 if r and not opts.get('all'):
4283 skip[fn] = True
4287 skip[fn] = True
4284 if copy:
4288 if copy:
4285 skip[copy] = True
4289 skip[copy] = True
4286 del matches[rev]
4290 del matches[rev]
4287 del revfiles[rev]
4291 del revfiles[rev]
4288
4292
4289 return not found
4293 return not found
4290
4294
4291 @command('heads',
4295 @command('heads',
4292 [('r', 'rev', '',
4296 [('r', 'rev', '',
4293 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4297 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4294 ('t', 'topo', False, _('show topological heads only')),
4298 ('t', 'topo', False, _('show topological heads only')),
4295 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4299 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4296 ('c', 'closed', False, _('show normal and closed branch heads')),
4300 ('c', 'closed', False, _('show normal and closed branch heads')),
4297 ] + templateopts,
4301 ] + templateopts,
4298 _('[-ct] [-r STARTREV] [REV]...'))
4302 _('[-ct] [-r STARTREV] [REV]...'))
4299 def heads(ui, repo, *branchrevs, **opts):
4303 def heads(ui, repo, *branchrevs, **opts):
4300 """show branch heads
4304 """show branch heads
4301
4305
4302 With no arguments, show all open branch heads in the repository.
4306 With no arguments, show all open branch heads in the repository.
4303 Branch heads are changesets that have no descendants on the
4307 Branch heads are changesets that have no descendants on the
4304 same branch. They are where development generally takes place and
4308 same branch. They are where development generally takes place and
4305 are the usual targets for update and merge operations.
4309 are the usual targets for update and merge operations.
4306
4310
4307 If one or more REVs are given, only open branch heads on the
4311 If one or more REVs are given, only open branch heads on the
4308 branches associated with the specified changesets are shown. This
4312 branches associated with the specified changesets are shown. This
4309 means that you can use :hg:`heads .` to see the heads on the
4313 means that you can use :hg:`heads .` to see the heads on the
4310 currently checked-out branch.
4314 currently checked-out branch.
4311
4315
4312 If -c/--closed is specified, also show branch heads marked closed
4316 If -c/--closed is specified, also show branch heads marked closed
4313 (see :hg:`commit --close-branch`).
4317 (see :hg:`commit --close-branch`).
4314
4318
4315 If STARTREV is specified, only those heads that are descendants of
4319 If STARTREV is specified, only those heads that are descendants of
4316 STARTREV will be displayed.
4320 STARTREV will be displayed.
4317
4321
4318 If -t/--topo is specified, named branch mechanics will be ignored and only
4322 If -t/--topo is specified, named branch mechanics will be ignored and only
4319 topological heads (changesets with no children) will be shown.
4323 topological heads (changesets with no children) will be shown.
4320
4324
4321 Returns 0 if matching heads are found, 1 if not.
4325 Returns 0 if matching heads are found, 1 if not.
4322 """
4326 """
4323
4327
4324 start = None
4328 start = None
4325 if 'rev' in opts:
4329 if 'rev' in opts:
4326 start = scmutil.revsingle(repo, opts['rev'], None).node()
4330 start = scmutil.revsingle(repo, opts['rev'], None).node()
4327
4331
4328 if opts.get('topo'):
4332 if opts.get('topo'):
4329 heads = [repo[h] for h in repo.heads(start)]
4333 heads = [repo[h] for h in repo.heads(start)]
4330 else:
4334 else:
4331 heads = []
4335 heads = []
4332 for branch in repo.branchmap():
4336 for branch in repo.branchmap():
4333 heads += repo.branchheads(branch, start, opts.get('closed'))
4337 heads += repo.branchheads(branch, start, opts.get('closed'))
4334 heads = [repo[h] for h in heads]
4338 heads = [repo[h] for h in heads]
4335
4339
4336 if branchrevs:
4340 if branchrevs:
4337 branches = set(repo[br].branch() for br in branchrevs)
4341 branches = set(repo[br].branch() for br in branchrevs)
4338 heads = [h for h in heads if h.branch() in branches]
4342 heads = [h for h in heads if h.branch() in branches]
4339
4343
4340 if opts.get('active') and branchrevs:
4344 if opts.get('active') and branchrevs:
4341 dagheads = repo.heads(start)
4345 dagheads = repo.heads(start)
4342 heads = [h for h in heads if h.node() in dagheads]
4346 heads = [h for h in heads if h.node() in dagheads]
4343
4347
4344 if branchrevs:
4348 if branchrevs:
4345 haveheads = set(h.branch() for h in heads)
4349 haveheads = set(h.branch() for h in heads)
4346 if branches - haveheads:
4350 if branches - haveheads:
4347 headless = ', '.join(b for b in branches - haveheads)
4351 headless = ', '.join(b for b in branches - haveheads)
4348 msg = _('no open branch heads found on branches %s')
4352 msg = _('no open branch heads found on branches %s')
4349 if opts.get('rev'):
4353 if opts.get('rev'):
4350 msg += _(' (started at %s)') % opts['rev']
4354 msg += _(' (started at %s)') % opts['rev']
4351 ui.warn((msg + '\n') % headless)
4355 ui.warn((msg + '\n') % headless)
4352
4356
4353 if not heads:
4357 if not heads:
4354 return 1
4358 return 1
4355
4359
4356 heads = sorted(heads, key=lambda x: -x.rev())
4360 heads = sorted(heads, key=lambda x: -x.rev())
4357 displayer = cmdutil.show_changeset(ui, repo, opts)
4361 displayer = cmdutil.show_changeset(ui, repo, opts)
4358 for ctx in heads:
4362 for ctx in heads:
4359 displayer.show(ctx)
4363 displayer.show(ctx)
4360 displayer.close()
4364 displayer.close()
4361
4365
4362 @command('help',
4366 @command('help',
4363 [('e', 'extension', None, _('show only help for extensions')),
4367 [('e', 'extension', None, _('show only help for extensions')),
4364 ('c', 'command', None, _('show only help for commands')),
4368 ('c', 'command', None, _('show only help for commands')),
4365 ('k', 'keyword', None, _('show topics matching keyword')),
4369 ('k', 'keyword', None, _('show topics matching keyword')),
4366 ('s', 'system', [], _('show help for specific platform(s)')),
4370 ('s', 'system', [], _('show help for specific platform(s)')),
4367 ],
4371 ],
4368 _('[-ecks] [TOPIC]'),
4372 _('[-ecks] [TOPIC]'),
4369 norepo=True)
4373 norepo=True)
4370 def help_(ui, name=None, **opts):
4374 def help_(ui, name=None, **opts):
4371 """show help for a given topic or a help overview
4375 """show help for a given topic or a help overview
4372
4376
4373 With no arguments, print a list of commands with short help messages.
4377 With no arguments, print a list of commands with short help messages.
4374
4378
4375 Given a topic, extension, or command name, print help for that
4379 Given a topic, extension, or command name, print help for that
4376 topic.
4380 topic.
4377
4381
4378 Returns 0 if successful.
4382 Returns 0 if successful.
4379 """
4383 """
4380
4384
4381 textwidth = min(ui.termwidth(), 80) - 2
4385 textwidth = min(ui.termwidth(), 80) - 2
4382
4386
4383 keep = opts.get('system') or []
4387 keep = opts.get('system') or []
4384 if len(keep) == 0:
4388 if len(keep) == 0:
4385 if sys.platform.startswith('win'):
4389 if sys.platform.startswith('win'):
4386 keep.append('windows')
4390 keep.append('windows')
4387 elif sys.platform == 'OpenVMS':
4391 elif sys.platform == 'OpenVMS':
4388 keep.append('vms')
4392 keep.append('vms')
4389 elif sys.platform == 'plan9':
4393 elif sys.platform == 'plan9':
4390 keep.append('plan9')
4394 keep.append('plan9')
4391 else:
4395 else:
4392 keep.append('unix')
4396 keep.append('unix')
4393 keep.append(sys.platform.lower())
4397 keep.append(sys.platform.lower())
4394 if ui.verbose:
4398 if ui.verbose:
4395 keep.append('verbose')
4399 keep.append('verbose')
4396
4400
4397 section = None
4401 section = None
4398 subtopic = None
4402 subtopic = None
4399 if name and '.' in name:
4403 if name and '.' in name:
4400 name, section = name.split('.', 1)
4404 name, section = name.split('.', 1)
4401 section = section.lower()
4405 section = section.lower()
4402 if '.' in section:
4406 if '.' in section:
4403 subtopic, section = section.split('.', 1)
4407 subtopic, section = section.split('.', 1)
4404 else:
4408 else:
4405 subtopic = section
4409 subtopic = section
4406
4410
4407 text = help.help_(ui, name, subtopic=subtopic, **opts)
4411 text = help.help_(ui, name, subtopic=subtopic, **opts)
4408
4412
4409 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4413 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4410 section=section)
4414 section=section)
4411
4415
4412 # We could have been given a weird ".foo" section without a name
4416 # We could have been given a weird ".foo" section without a name
4413 # to look for, or we could have simply failed to found "foo.bar"
4417 # to look for, or we could have simply failed to found "foo.bar"
4414 # because bar isn't a section of foo
4418 # because bar isn't a section of foo
4415 if section and not (formatted and name):
4419 if section and not (formatted and name):
4416 raise error.Abort(_("help section not found"))
4420 raise error.Abort(_("help section not found"))
4417
4421
4418 if 'verbose' in pruned:
4422 if 'verbose' in pruned:
4419 keep.append('omitted')
4423 keep.append('omitted')
4420 else:
4424 else:
4421 keep.append('notomitted')
4425 keep.append('notomitted')
4422 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4426 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4423 section=section)
4427 section=section)
4424 ui.write(formatted)
4428 ui.write(formatted)
4425
4429
4426
4430
4427 @command('identify|id',
4431 @command('identify|id',
4428 [('r', 'rev', '',
4432 [('r', 'rev', '',
4429 _('identify the specified revision'), _('REV')),
4433 _('identify the specified revision'), _('REV')),
4430 ('n', 'num', None, _('show local revision number')),
4434 ('n', 'num', None, _('show local revision number')),
4431 ('i', 'id', None, _('show global revision id')),
4435 ('i', 'id', None, _('show global revision id')),
4432 ('b', 'branch', None, _('show branch')),
4436 ('b', 'branch', None, _('show branch')),
4433 ('t', 'tags', None, _('show tags')),
4437 ('t', 'tags', None, _('show tags')),
4434 ('B', 'bookmarks', None, _('show bookmarks')),
4438 ('B', 'bookmarks', None, _('show bookmarks')),
4435 ] + remoteopts,
4439 ] + remoteopts,
4436 _('[-nibtB] [-r REV] [SOURCE]'),
4440 _('[-nibtB] [-r REV] [SOURCE]'),
4437 optionalrepo=True)
4441 optionalrepo=True)
4438 def identify(ui, repo, source=None, rev=None,
4442 def identify(ui, repo, source=None, rev=None,
4439 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4443 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4440 """identify the working directory or specified revision
4444 """identify the working directory or specified revision
4441
4445
4442 Print a summary identifying the repository state at REV using one or
4446 Print a summary identifying the repository state at REV using one or
4443 two parent hash identifiers, followed by a "+" if the working
4447 two parent hash identifiers, followed by a "+" if the working
4444 directory has uncommitted changes, the branch name (if not default),
4448 directory has uncommitted changes, the branch name (if not default),
4445 a list of tags, and a list of bookmarks.
4449 a list of tags, and a list of bookmarks.
4446
4450
4447 When REV is not given, print a summary of the current state of the
4451 When REV is not given, print a summary of the current state of the
4448 repository.
4452 repository.
4449
4453
4450 Specifying a path to a repository root or Mercurial bundle will
4454 Specifying a path to a repository root or Mercurial bundle will
4451 cause lookup to operate on that repository/bundle.
4455 cause lookup to operate on that repository/bundle.
4452
4456
4453 .. container:: verbose
4457 .. container:: verbose
4454
4458
4455 Examples:
4459 Examples:
4456
4460
4457 - generate a build identifier for the working directory::
4461 - generate a build identifier for the working directory::
4458
4462
4459 hg id --id > build-id.dat
4463 hg id --id > build-id.dat
4460
4464
4461 - find the revision corresponding to a tag::
4465 - find the revision corresponding to a tag::
4462
4466
4463 hg id -n -r 1.3
4467 hg id -n -r 1.3
4464
4468
4465 - check the most recent revision of a remote repository::
4469 - check the most recent revision of a remote repository::
4466
4470
4467 hg id -r tip http://selenic.com/hg/
4471 hg id -r tip http://selenic.com/hg/
4468
4472
4469 See :hg:`log` for generating more information about specific revisions,
4473 See :hg:`log` for generating more information about specific revisions,
4470 including full hash identifiers.
4474 including full hash identifiers.
4471
4475
4472 Returns 0 if successful.
4476 Returns 0 if successful.
4473 """
4477 """
4474
4478
4475 if not repo and not source:
4479 if not repo and not source:
4476 raise error.Abort(_("there is no Mercurial repository here "
4480 raise error.Abort(_("there is no Mercurial repository here "
4477 "(.hg not found)"))
4481 "(.hg not found)"))
4478
4482
4479 if ui.debugflag:
4483 if ui.debugflag:
4480 hexfunc = hex
4484 hexfunc = hex
4481 else:
4485 else:
4482 hexfunc = short
4486 hexfunc = short
4483 default = not (num or id or branch or tags or bookmarks)
4487 default = not (num or id or branch or tags or bookmarks)
4484 output = []
4488 output = []
4485 revs = []
4489 revs = []
4486
4490
4487 if source:
4491 if source:
4488 source, branches = hg.parseurl(ui.expandpath(source))
4492 source, branches = hg.parseurl(ui.expandpath(source))
4489 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4493 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4490 repo = peer.local()
4494 repo = peer.local()
4491 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4495 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4492
4496
4493 if not repo:
4497 if not repo:
4494 if num or branch or tags:
4498 if num or branch or tags:
4495 raise error.Abort(
4499 raise error.Abort(
4496 _("can't query remote revision number, branch, or tags"))
4500 _("can't query remote revision number, branch, or tags"))
4497 if not rev and revs:
4501 if not rev and revs:
4498 rev = revs[0]
4502 rev = revs[0]
4499 if not rev:
4503 if not rev:
4500 rev = "tip"
4504 rev = "tip"
4501
4505
4502 remoterev = peer.lookup(rev)
4506 remoterev = peer.lookup(rev)
4503 if default or id:
4507 if default or id:
4504 output = [hexfunc(remoterev)]
4508 output = [hexfunc(remoterev)]
4505
4509
4506 def getbms():
4510 def getbms():
4507 bms = []
4511 bms = []
4508
4512
4509 if 'bookmarks' in peer.listkeys('namespaces'):
4513 if 'bookmarks' in peer.listkeys('namespaces'):
4510 hexremoterev = hex(remoterev)
4514 hexremoterev = hex(remoterev)
4511 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4515 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4512 if bmr == hexremoterev]
4516 if bmr == hexremoterev]
4513
4517
4514 return sorted(bms)
4518 return sorted(bms)
4515
4519
4516 if bookmarks:
4520 if bookmarks:
4517 output.extend(getbms())
4521 output.extend(getbms())
4518 elif default and not ui.quiet:
4522 elif default and not ui.quiet:
4519 # multiple bookmarks for a single parent separated by '/'
4523 # multiple bookmarks for a single parent separated by '/'
4520 bm = '/'.join(getbms())
4524 bm = '/'.join(getbms())
4521 if bm:
4525 if bm:
4522 output.append(bm)
4526 output.append(bm)
4523 else:
4527 else:
4524 ctx = scmutil.revsingle(repo, rev, None)
4528 ctx = scmutil.revsingle(repo, rev, None)
4525
4529
4526 if ctx.rev() is None:
4530 if ctx.rev() is None:
4527 ctx = repo[None]
4531 ctx = repo[None]
4528 parents = ctx.parents()
4532 parents = ctx.parents()
4529 taglist = []
4533 taglist = []
4530 for p in parents:
4534 for p in parents:
4531 taglist.extend(p.tags())
4535 taglist.extend(p.tags())
4532
4536
4533 changed = ""
4537 changed = ""
4534 if default or id or num:
4538 if default or id or num:
4535 if (any(repo.status())
4539 if (any(repo.status())
4536 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4540 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4537 changed = '+'
4541 changed = '+'
4538 if default or id:
4542 if default or id:
4539 output = ["%s%s" %
4543 output = ["%s%s" %
4540 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4544 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4541 if num:
4545 if num:
4542 output.append("%s%s" %
4546 output.append("%s%s" %
4543 ('+'.join([str(p.rev()) for p in parents]), changed))
4547 ('+'.join([str(p.rev()) for p in parents]), changed))
4544 else:
4548 else:
4545 if default or id:
4549 if default or id:
4546 output = [hexfunc(ctx.node())]
4550 output = [hexfunc(ctx.node())]
4547 if num:
4551 if num:
4548 output.append(str(ctx.rev()))
4552 output.append(str(ctx.rev()))
4549 taglist = ctx.tags()
4553 taglist = ctx.tags()
4550
4554
4551 if default and not ui.quiet:
4555 if default and not ui.quiet:
4552 b = ctx.branch()
4556 b = ctx.branch()
4553 if b != 'default':
4557 if b != 'default':
4554 output.append("(%s)" % b)
4558 output.append("(%s)" % b)
4555
4559
4556 # multiple tags for a single parent separated by '/'
4560 # multiple tags for a single parent separated by '/'
4557 t = '/'.join(taglist)
4561 t = '/'.join(taglist)
4558 if t:
4562 if t:
4559 output.append(t)
4563 output.append(t)
4560
4564
4561 # multiple bookmarks for a single parent separated by '/'
4565 # multiple bookmarks for a single parent separated by '/'
4562 bm = '/'.join(ctx.bookmarks())
4566 bm = '/'.join(ctx.bookmarks())
4563 if bm:
4567 if bm:
4564 output.append(bm)
4568 output.append(bm)
4565 else:
4569 else:
4566 if branch:
4570 if branch:
4567 output.append(ctx.branch())
4571 output.append(ctx.branch())
4568
4572
4569 if tags:
4573 if tags:
4570 output.extend(taglist)
4574 output.extend(taglist)
4571
4575
4572 if bookmarks:
4576 if bookmarks:
4573 output.extend(ctx.bookmarks())
4577 output.extend(ctx.bookmarks())
4574
4578
4575 ui.write("%s\n" % ' '.join(output))
4579 ui.write("%s\n" % ' '.join(output))
4576
4580
4577 @command('import|patch',
4581 @command('import|patch',
4578 [('p', 'strip', 1,
4582 [('p', 'strip', 1,
4579 _('directory strip option for patch. This has the same '
4583 _('directory strip option for patch. This has the same '
4580 'meaning as the corresponding patch option'), _('NUM')),
4584 'meaning as the corresponding patch option'), _('NUM')),
4581 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4585 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4582 ('e', 'edit', False, _('invoke editor on commit messages')),
4586 ('e', 'edit', False, _('invoke editor on commit messages')),
4583 ('f', 'force', None,
4587 ('f', 'force', None,
4584 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4588 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4585 ('', 'no-commit', None,
4589 ('', 'no-commit', None,
4586 _("don't commit, just update the working directory")),
4590 _("don't commit, just update the working directory")),
4587 ('', 'bypass', None,
4591 ('', 'bypass', None,
4588 _("apply patch without touching the working directory")),
4592 _("apply patch without touching the working directory")),
4589 ('', 'partial', None,
4593 ('', 'partial', None,
4590 _('commit even if some hunks fail')),
4594 _('commit even if some hunks fail')),
4591 ('', 'exact', None,
4595 ('', 'exact', None,
4592 _('apply patch to the nodes from which it was generated')),
4596 _('apply patch to the nodes from which it was generated')),
4593 ('', 'prefix', '',
4597 ('', 'prefix', '',
4594 _('apply patch to subdirectory'), _('DIR')),
4598 _('apply patch to subdirectory'), _('DIR')),
4595 ('', 'import-branch', None,
4599 ('', 'import-branch', None,
4596 _('use any branch information in patch (implied by --exact)'))] +
4600 _('use any branch information in patch (implied by --exact)'))] +
4597 commitopts + commitopts2 + similarityopts,
4601 commitopts + commitopts2 + similarityopts,
4598 _('[OPTION]... PATCH...'))
4602 _('[OPTION]... PATCH...'))
4599 def import_(ui, repo, patch1=None, *patches, **opts):
4603 def import_(ui, repo, patch1=None, *patches, **opts):
4600 """import an ordered set of patches
4604 """import an ordered set of patches
4601
4605
4602 Import a list of patches and commit them individually (unless
4606 Import a list of patches and commit them individually (unless
4603 --no-commit is specified).
4607 --no-commit is specified).
4604
4608
4605 To read a patch from standard input, use "-" as the patch name. If
4609 To read a patch from standard input, use "-" as the patch name. If
4606 a URL is specified, the patch will be downloaded from there.
4610 a URL is specified, the patch will be downloaded from there.
4607
4611
4608 Import first applies changes to the working directory (unless
4612 Import first applies changes to the working directory (unless
4609 --bypass is specified), import will abort if there are outstanding
4613 --bypass is specified), import will abort if there are outstanding
4610 changes.
4614 changes.
4611
4615
4612 Use --bypass to apply and commit patches directly to the
4616 Use --bypass to apply and commit patches directly to the
4613 repository, without affecting the working directory. Without
4617 repository, without affecting the working directory. Without
4614 --exact, patches will be applied on top of the working directory
4618 --exact, patches will be applied on top of the working directory
4615 parent revision.
4619 parent revision.
4616
4620
4617 You can import a patch straight from a mail message. Even patches
4621 You can import a patch straight from a mail message. Even patches
4618 as attachments work (to use the body part, it must have type
4622 as attachments work (to use the body part, it must have type
4619 text/plain or text/x-patch). From and Subject headers of email
4623 text/plain or text/x-patch). From and Subject headers of email
4620 message are used as default committer and commit message. All
4624 message are used as default committer and commit message. All
4621 text/plain body parts before first diff are added to the commit
4625 text/plain body parts before first diff are added to the commit
4622 message.
4626 message.
4623
4627
4624 If the imported patch was generated by :hg:`export`, user and
4628 If the imported patch was generated by :hg:`export`, user and
4625 description from patch override values from message headers and
4629 description from patch override values from message headers and
4626 body. Values given on command line with -m/--message and -u/--user
4630 body. Values given on command line with -m/--message and -u/--user
4627 override these.
4631 override these.
4628
4632
4629 If --exact is specified, import will set the working directory to
4633 If --exact is specified, import will set the working directory to
4630 the parent of each patch before applying it, and will abort if the
4634 the parent of each patch before applying it, and will abort if the
4631 resulting changeset has a different ID than the one recorded in
4635 resulting changeset has a different ID than the one recorded in
4632 the patch. This may happen due to character set problems or other
4636 the patch. This may happen due to character set problems or other
4633 deficiencies in the text patch format.
4637 deficiencies in the text patch format.
4634
4638
4635 Use --partial to ensure a changeset will be created from the patch
4639 Use --partial to ensure a changeset will be created from the patch
4636 even if some hunks fail to apply. Hunks that fail to apply will be
4640 even if some hunks fail to apply. Hunks that fail to apply will be
4637 written to a <target-file>.rej file. Conflicts can then be resolved
4641 written to a <target-file>.rej file. Conflicts can then be resolved
4638 by hand before :hg:`commit --amend` is run to update the created
4642 by hand before :hg:`commit --amend` is run to update the created
4639 changeset. This flag exists to let people import patches that
4643 changeset. This flag exists to let people import patches that
4640 partially apply without losing the associated metadata (author,
4644 partially apply without losing the associated metadata (author,
4641 date, description, ...).
4645 date, description, ...).
4642
4646
4643 .. note::
4647 .. note::
4644
4648
4645 When no hunks apply cleanly, :hg:`import --partial` will create
4649 When no hunks apply cleanly, :hg:`import --partial` will create
4646 an empty changeset, importing only the patch metadata.
4650 an empty changeset, importing only the patch metadata.
4647
4651
4648 With -s/--similarity, hg will attempt to discover renames and
4652 With -s/--similarity, hg will attempt to discover renames and
4649 copies in the patch in the same way as :hg:`addremove`.
4653 copies in the patch in the same way as :hg:`addremove`.
4650
4654
4651 It is possible to use external patch programs to perform the patch
4655 It is possible to use external patch programs to perform the patch
4652 by setting the ``ui.patch`` configuration option. For the default
4656 by setting the ``ui.patch`` configuration option. For the default
4653 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4657 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4654 See :hg:`help config` for more information about configuration
4658 See :hg:`help config` for more information about configuration
4655 files and how to use these options.
4659 files and how to use these options.
4656
4660
4657 See :hg:`help dates` for a list of formats valid for -d/--date.
4661 See :hg:`help dates` for a list of formats valid for -d/--date.
4658
4662
4659 .. container:: verbose
4663 .. container:: verbose
4660
4664
4661 Examples:
4665 Examples:
4662
4666
4663 - import a traditional patch from a website and detect renames::
4667 - import a traditional patch from a website and detect renames::
4664
4668
4665 hg import -s 80 http://example.com/bugfix.patch
4669 hg import -s 80 http://example.com/bugfix.patch
4666
4670
4667 - import a changeset from an hgweb server::
4671 - import a changeset from an hgweb server::
4668
4672
4669 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4673 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4670
4674
4671 - import all the patches in an Unix-style mbox::
4675 - import all the patches in an Unix-style mbox::
4672
4676
4673 hg import incoming-patches.mbox
4677 hg import incoming-patches.mbox
4674
4678
4675 - attempt to exactly restore an exported changeset (not always
4679 - attempt to exactly restore an exported changeset (not always
4676 possible)::
4680 possible)::
4677
4681
4678 hg import --exact proposed-fix.patch
4682 hg import --exact proposed-fix.patch
4679
4683
4680 - use an external tool to apply a patch which is too fuzzy for
4684 - use an external tool to apply a patch which is too fuzzy for
4681 the default internal tool.
4685 the default internal tool.
4682
4686
4683 hg import --config ui.patch="patch --merge" fuzzy.patch
4687 hg import --config ui.patch="patch --merge" fuzzy.patch
4684
4688
4685 - change the default fuzzing from 2 to a less strict 7
4689 - change the default fuzzing from 2 to a less strict 7
4686
4690
4687 hg import --config ui.fuzz=7 fuzz.patch
4691 hg import --config ui.fuzz=7 fuzz.patch
4688
4692
4689 Returns 0 on success, 1 on partial success (see --partial).
4693 Returns 0 on success, 1 on partial success (see --partial).
4690 """
4694 """
4691
4695
4692 if not patch1:
4696 if not patch1:
4693 raise error.Abort(_('need at least one patch to import'))
4697 raise error.Abort(_('need at least one patch to import'))
4694
4698
4695 patches = (patch1,) + patches
4699 patches = (patch1,) + patches
4696
4700
4697 date = opts.get('date')
4701 date = opts.get('date')
4698 if date:
4702 if date:
4699 opts['date'] = util.parsedate(date)
4703 opts['date'] = util.parsedate(date)
4700
4704
4701 exact = opts.get('exact')
4705 exact = opts.get('exact')
4702 update = not opts.get('bypass')
4706 update = not opts.get('bypass')
4703 if not update and opts.get('no_commit'):
4707 if not update and opts.get('no_commit'):
4704 raise error.Abort(_('cannot use --no-commit with --bypass'))
4708 raise error.Abort(_('cannot use --no-commit with --bypass'))
4705 try:
4709 try:
4706 sim = float(opts.get('similarity') or 0)
4710 sim = float(opts.get('similarity') or 0)
4707 except ValueError:
4711 except ValueError:
4708 raise error.Abort(_('similarity must be a number'))
4712 raise error.Abort(_('similarity must be a number'))
4709 if sim < 0 or sim > 100:
4713 if sim < 0 or sim > 100:
4710 raise error.Abort(_('similarity must be between 0 and 100'))
4714 raise error.Abort(_('similarity must be between 0 and 100'))
4711 if sim and not update:
4715 if sim and not update:
4712 raise error.Abort(_('cannot use --similarity with --bypass'))
4716 raise error.Abort(_('cannot use --similarity with --bypass'))
4713 if exact:
4717 if exact:
4714 if opts.get('edit'):
4718 if opts.get('edit'):
4715 raise error.Abort(_('cannot use --exact with --edit'))
4719 raise error.Abort(_('cannot use --exact with --edit'))
4716 if opts.get('prefix'):
4720 if opts.get('prefix'):
4717 raise error.Abort(_('cannot use --exact with --prefix'))
4721 raise error.Abort(_('cannot use --exact with --prefix'))
4718
4722
4719 base = opts["base"]
4723 base = opts["base"]
4720 wlock = dsguard = lock = tr = None
4724 wlock = dsguard = lock = tr = None
4721 msgs = []
4725 msgs = []
4722 ret = 0
4726 ret = 0
4723
4727
4724
4728
4725 try:
4729 try:
4726 wlock = repo.wlock()
4730 wlock = repo.wlock()
4727
4731
4728 if update:
4732 if update:
4729 cmdutil.checkunfinished(repo)
4733 cmdutil.checkunfinished(repo)
4730 if (exact or not opts.get('force')):
4734 if (exact or not opts.get('force')):
4731 cmdutil.bailifchanged(repo)
4735 cmdutil.bailifchanged(repo)
4732
4736
4733 if not opts.get('no_commit'):
4737 if not opts.get('no_commit'):
4734 lock = repo.lock()
4738 lock = repo.lock()
4735 tr = repo.transaction('import')
4739 tr = repo.transaction('import')
4736 else:
4740 else:
4737 dsguard = cmdutil.dirstateguard(repo, 'import')
4741 dsguard = cmdutil.dirstateguard(repo, 'import')
4738 parents = repo[None].parents()
4742 parents = repo[None].parents()
4739 for patchurl in patches:
4743 for patchurl in patches:
4740 if patchurl == '-':
4744 if patchurl == '-':
4741 ui.status(_('applying patch from stdin\n'))
4745 ui.status(_('applying patch from stdin\n'))
4742 patchfile = ui.fin
4746 patchfile = ui.fin
4743 patchurl = 'stdin' # for error message
4747 patchurl = 'stdin' # for error message
4744 else:
4748 else:
4745 patchurl = os.path.join(base, patchurl)
4749 patchurl = os.path.join(base, patchurl)
4746 ui.status(_('applying %s\n') % patchurl)
4750 ui.status(_('applying %s\n') % patchurl)
4747 patchfile = hg.openpath(ui, patchurl)
4751 patchfile = hg.openpath(ui, patchurl)
4748
4752
4749 haspatch = False
4753 haspatch = False
4750 for hunk in patch.split(patchfile):
4754 for hunk in patch.split(patchfile):
4751 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4755 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4752 parents, opts,
4756 parents, opts,
4753 msgs, hg.clean)
4757 msgs, hg.clean)
4754 if msg:
4758 if msg:
4755 haspatch = True
4759 haspatch = True
4756 ui.note(msg + '\n')
4760 ui.note(msg + '\n')
4757 if update or exact:
4761 if update or exact:
4758 parents = repo[None].parents()
4762 parents = repo[None].parents()
4759 else:
4763 else:
4760 parents = [repo[node]]
4764 parents = [repo[node]]
4761 if rej:
4765 if rej:
4762 ui.write_err(_("patch applied partially\n"))
4766 ui.write_err(_("patch applied partially\n"))
4763 ui.write_err(_("(fix the .rej files and run "
4767 ui.write_err(_("(fix the .rej files and run "
4764 "`hg commit --amend`)\n"))
4768 "`hg commit --amend`)\n"))
4765 ret = 1
4769 ret = 1
4766 break
4770 break
4767
4771
4768 if not haspatch:
4772 if not haspatch:
4769 raise error.Abort(_('%s: no diffs found') % patchurl)
4773 raise error.Abort(_('%s: no diffs found') % patchurl)
4770
4774
4771 if tr:
4775 if tr:
4772 tr.close()
4776 tr.close()
4773 if msgs:
4777 if msgs:
4774 repo.savecommitmessage('\n* * *\n'.join(msgs))
4778 repo.savecommitmessage('\n* * *\n'.join(msgs))
4775 if dsguard:
4779 if dsguard:
4776 dsguard.close()
4780 dsguard.close()
4777 return ret
4781 return ret
4778 finally:
4782 finally:
4779 if tr:
4783 if tr:
4780 tr.release()
4784 tr.release()
4781 release(lock, dsguard, wlock)
4785 release(lock, dsguard, wlock)
4782
4786
4783 @command('incoming|in',
4787 @command('incoming|in',
4784 [('f', 'force', None,
4788 [('f', 'force', None,
4785 _('run even if remote repository is unrelated')),
4789 _('run even if remote repository is unrelated')),
4786 ('n', 'newest-first', None, _('show newest record first')),
4790 ('n', 'newest-first', None, _('show newest record first')),
4787 ('', 'bundle', '',
4791 ('', 'bundle', '',
4788 _('file to store the bundles into'), _('FILE')),
4792 _('file to store the bundles into'), _('FILE')),
4789 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4793 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4790 ('B', 'bookmarks', False, _("compare bookmarks")),
4794 ('B', 'bookmarks', False, _("compare bookmarks")),
4791 ('b', 'branch', [],
4795 ('b', 'branch', [],
4792 _('a specific branch you would like to pull'), _('BRANCH')),
4796 _('a specific branch you would like to pull'), _('BRANCH')),
4793 ] + logopts + remoteopts + subrepoopts,
4797 ] + logopts + remoteopts + subrepoopts,
4794 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4798 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4795 def incoming(ui, repo, source="default", **opts):
4799 def incoming(ui, repo, source="default", **opts):
4796 """show new changesets found in source
4800 """show new changesets found in source
4797
4801
4798 Show new changesets found in the specified path/URL or the default
4802 Show new changesets found in the specified path/URL or the default
4799 pull location. These are the changesets that would have been pulled
4803 pull location. These are the changesets that would have been pulled
4800 if a pull at the time you issued this command.
4804 if a pull at the time you issued this command.
4801
4805
4802 See pull for valid source format details.
4806 See pull for valid source format details.
4803
4807
4804 .. container:: verbose
4808 .. container:: verbose
4805
4809
4806 With -B/--bookmarks, the result of bookmark comparison between
4810 With -B/--bookmarks, the result of bookmark comparison between
4807 local and remote repositories is displayed. With -v/--verbose,
4811 local and remote repositories is displayed. With -v/--verbose,
4808 status is also displayed for each bookmark like below::
4812 status is also displayed for each bookmark like below::
4809
4813
4810 BM1 01234567890a added
4814 BM1 01234567890a added
4811 BM2 1234567890ab advanced
4815 BM2 1234567890ab advanced
4812 BM3 234567890abc diverged
4816 BM3 234567890abc diverged
4813 BM4 34567890abcd changed
4817 BM4 34567890abcd changed
4814
4818
4815 The action taken locally when pulling depends on the
4819 The action taken locally when pulling depends on the
4816 status of each bookmark:
4820 status of each bookmark:
4817
4821
4818 :``added``: pull will create it
4822 :``added``: pull will create it
4819 :``advanced``: pull will update it
4823 :``advanced``: pull will update it
4820 :``diverged``: pull will create a divergent bookmark
4824 :``diverged``: pull will create a divergent bookmark
4821 :``changed``: result depends on remote changesets
4825 :``changed``: result depends on remote changesets
4822
4826
4823 From the point of view of pulling behavior, bookmark
4827 From the point of view of pulling behavior, bookmark
4824 existing only in the remote repository are treated as ``added``,
4828 existing only in the remote repository are treated as ``added``,
4825 even if it is in fact locally deleted.
4829 even if it is in fact locally deleted.
4826
4830
4827 .. container:: verbose
4831 .. container:: verbose
4828
4832
4829 For remote repository, using --bundle avoids downloading the
4833 For remote repository, using --bundle avoids downloading the
4830 changesets twice if the incoming is followed by a pull.
4834 changesets twice if the incoming is followed by a pull.
4831
4835
4832 Examples:
4836 Examples:
4833
4837
4834 - show incoming changes with patches and full description::
4838 - show incoming changes with patches and full description::
4835
4839
4836 hg incoming -vp
4840 hg incoming -vp
4837
4841
4838 - show incoming changes excluding merges, store a bundle::
4842 - show incoming changes excluding merges, store a bundle::
4839
4843
4840 hg in -vpM --bundle incoming.hg
4844 hg in -vpM --bundle incoming.hg
4841 hg pull incoming.hg
4845 hg pull incoming.hg
4842
4846
4843 - briefly list changes inside a bundle::
4847 - briefly list changes inside a bundle::
4844
4848
4845 hg in changes.hg -T "{desc|firstline}\\n"
4849 hg in changes.hg -T "{desc|firstline}\\n"
4846
4850
4847 Returns 0 if there are incoming changes, 1 otherwise.
4851 Returns 0 if there are incoming changes, 1 otherwise.
4848 """
4852 """
4849 if opts.get('graph'):
4853 if opts.get('graph'):
4850 cmdutil.checkunsupportedgraphflags([], opts)
4854 cmdutil.checkunsupportedgraphflags([], opts)
4851 def display(other, chlist, displayer):
4855 def display(other, chlist, displayer):
4852 revdag = cmdutil.graphrevs(other, chlist, opts)
4856 revdag = cmdutil.graphrevs(other, chlist, opts)
4853 cmdutil.displaygraph(ui, repo, revdag, displayer,
4857 cmdutil.displaygraph(ui, repo, revdag, displayer,
4854 graphmod.asciiedges)
4858 graphmod.asciiedges)
4855
4859
4856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4860 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4857 return 0
4861 return 0
4858
4862
4859 if opts.get('bundle') and opts.get('subrepos'):
4863 if opts.get('bundle') and opts.get('subrepos'):
4860 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4864 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4861
4865
4862 if opts.get('bookmarks'):
4866 if opts.get('bookmarks'):
4863 source, branches = hg.parseurl(ui.expandpath(source),
4867 source, branches = hg.parseurl(ui.expandpath(source),
4864 opts.get('branch'))
4868 opts.get('branch'))
4865 other = hg.peer(repo, opts, source)
4869 other = hg.peer(repo, opts, source)
4866 if 'bookmarks' not in other.listkeys('namespaces'):
4870 if 'bookmarks' not in other.listkeys('namespaces'):
4867 ui.warn(_("remote doesn't support bookmarks\n"))
4871 ui.warn(_("remote doesn't support bookmarks\n"))
4868 return 0
4872 return 0
4869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4873 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4870 return bookmarks.incoming(ui, repo, other)
4874 return bookmarks.incoming(ui, repo, other)
4871
4875
4872 repo._subtoppath = ui.expandpath(source)
4876 repo._subtoppath = ui.expandpath(source)
4873 try:
4877 try:
4874 return hg.incoming(ui, repo, source, opts)
4878 return hg.incoming(ui, repo, source, opts)
4875 finally:
4879 finally:
4876 del repo._subtoppath
4880 del repo._subtoppath
4877
4881
4878
4882
4879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4883 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4880 norepo=True)
4884 norepo=True)
4881 def init(ui, dest=".", **opts):
4885 def init(ui, dest=".", **opts):
4882 """create a new repository in the given directory
4886 """create a new repository in the given directory
4883
4887
4884 Initialize a new repository in the given directory. If the given
4888 Initialize a new repository in the given directory. If the given
4885 directory does not exist, it will be created.
4889 directory does not exist, it will be created.
4886
4890
4887 If no directory is given, the current directory is used.
4891 If no directory is given, the current directory is used.
4888
4892
4889 It is possible to specify an ``ssh://`` URL as the destination.
4893 It is possible to specify an ``ssh://`` URL as the destination.
4890 See :hg:`help urls` for more information.
4894 See :hg:`help urls` for more information.
4891
4895
4892 Returns 0 on success.
4896 Returns 0 on success.
4893 """
4897 """
4894 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4898 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4895
4899
4896 @command('locate',
4900 @command('locate',
4897 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4901 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4898 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4902 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4899 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4903 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4900 ] + walkopts,
4904 ] + walkopts,
4901 _('[OPTION]... [PATTERN]...'))
4905 _('[OPTION]... [PATTERN]...'))
4902 def locate(ui, repo, *pats, **opts):
4906 def locate(ui, repo, *pats, **opts):
4903 """locate files matching specific patterns (DEPRECATED)
4907 """locate files matching specific patterns (DEPRECATED)
4904
4908
4905 Print files under Mercurial control in the working directory whose
4909 Print files under Mercurial control in the working directory whose
4906 names match the given patterns.
4910 names match the given patterns.
4907
4911
4908 By default, this command searches all directories in the working
4912 By default, this command searches all directories in the working
4909 directory. To search just the current directory and its
4913 directory. To search just the current directory and its
4910 subdirectories, use "--include .".
4914 subdirectories, use "--include .".
4911
4915
4912 If no patterns are given to match, this command prints the names
4916 If no patterns are given to match, this command prints the names
4913 of all files under Mercurial control in the working directory.
4917 of all files under Mercurial control in the working directory.
4914
4918
4915 If you want to feed the output of this command into the "xargs"
4919 If you want to feed the output of this command into the "xargs"
4916 command, use the -0 option to both this command and "xargs". This
4920 command, use the -0 option to both this command and "xargs". This
4917 will avoid the problem of "xargs" treating single filenames that
4921 will avoid the problem of "xargs" treating single filenames that
4918 contain whitespace as multiple filenames.
4922 contain whitespace as multiple filenames.
4919
4923
4920 See :hg:`help files` for a more versatile command.
4924 See :hg:`help files` for a more versatile command.
4921
4925
4922 Returns 0 if a match is found, 1 otherwise.
4926 Returns 0 if a match is found, 1 otherwise.
4923 """
4927 """
4924 if opts.get('print0'):
4928 if opts.get('print0'):
4925 end = '\0'
4929 end = '\0'
4926 else:
4930 else:
4927 end = '\n'
4931 end = '\n'
4928 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4932 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4929
4933
4930 ret = 1
4934 ret = 1
4931 ctx = repo[rev]
4935 ctx = repo[rev]
4932 m = scmutil.match(ctx, pats, opts, default='relglob',
4936 m = scmutil.match(ctx, pats, opts, default='relglob',
4933 badfn=lambda x, y: False)
4937 badfn=lambda x, y: False)
4934
4938
4935 for abs in ctx.matches(m):
4939 for abs in ctx.matches(m):
4936 if opts.get('fullpath'):
4940 if opts.get('fullpath'):
4937 ui.write(repo.wjoin(abs), end)
4941 ui.write(repo.wjoin(abs), end)
4938 else:
4942 else:
4939 ui.write(((pats and m.rel(abs)) or abs), end)
4943 ui.write(((pats and m.rel(abs)) or abs), end)
4940 ret = 0
4944 ret = 0
4941
4945
4942 return ret
4946 return ret
4943
4947
4944 @command('^log|history',
4948 @command('^log|history',
4945 [('f', 'follow', None,
4949 [('f', 'follow', None,
4946 _('follow changeset history, or file history across copies and renames')),
4950 _('follow changeset history, or file history across copies and renames')),
4947 ('', 'follow-first', None,
4951 ('', 'follow-first', None,
4948 _('only follow the first parent of merge changesets (DEPRECATED)')),
4952 _('only follow the first parent of merge changesets (DEPRECATED)')),
4949 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4953 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4950 ('C', 'copies', None, _('show copied files')),
4954 ('C', 'copies', None, _('show copied files')),
4951 ('k', 'keyword', [],
4955 ('k', 'keyword', [],
4952 _('do case-insensitive search for a given text'), _('TEXT')),
4956 _('do case-insensitive search for a given text'), _('TEXT')),
4953 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4957 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4954 ('', 'removed', None, _('include revisions where files were removed')),
4958 ('', 'removed', None, _('include revisions where files were removed')),
4955 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4959 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4956 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4960 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4957 ('', 'only-branch', [],
4961 ('', 'only-branch', [],
4958 _('show only changesets within the given named branch (DEPRECATED)'),
4962 _('show only changesets within the given named branch (DEPRECATED)'),
4959 _('BRANCH')),
4963 _('BRANCH')),
4960 ('b', 'branch', [],
4964 ('b', 'branch', [],
4961 _('show changesets within the given named branch'), _('BRANCH')),
4965 _('show changesets within the given named branch'), _('BRANCH')),
4962 ('P', 'prune', [],
4966 ('P', 'prune', [],
4963 _('do not display revision or any of its ancestors'), _('REV')),
4967 _('do not display revision or any of its ancestors'), _('REV')),
4964 ] + logopts + walkopts,
4968 ] + logopts + walkopts,
4965 _('[OPTION]... [FILE]'),
4969 _('[OPTION]... [FILE]'),
4966 inferrepo=True)
4970 inferrepo=True)
4967 def log(ui, repo, *pats, **opts):
4971 def log(ui, repo, *pats, **opts):
4968 """show revision history of entire repository or files
4972 """show revision history of entire repository or files
4969
4973
4970 Print the revision history of the specified files or the entire
4974 Print the revision history of the specified files or the entire
4971 project.
4975 project.
4972
4976
4973 If no revision range is specified, the default is ``tip:0`` unless
4977 If no revision range is specified, the default is ``tip:0`` unless
4974 --follow is set, in which case the working directory parent is
4978 --follow is set, in which case the working directory parent is
4975 used as the starting revision.
4979 used as the starting revision.
4976
4980
4977 File history is shown without following rename or copy history of
4981 File history is shown without following rename or copy history of
4978 files. Use -f/--follow with a filename to follow history across
4982 files. Use -f/--follow with a filename to follow history across
4979 renames and copies. --follow without a filename will only show
4983 renames and copies. --follow without a filename will only show
4980 ancestors or descendants of the starting revision.
4984 ancestors or descendants of the starting revision.
4981
4985
4982 By default this command prints revision number and changeset id,
4986 By default this command prints revision number and changeset id,
4983 tags, non-trivial parents, user, date and time, and a summary for
4987 tags, non-trivial parents, user, date and time, and a summary for
4984 each commit. When the -v/--verbose switch is used, the list of
4988 each commit. When the -v/--verbose switch is used, the list of
4985 changed files and full commit message are shown.
4989 changed files and full commit message are shown.
4986
4990
4987 With --graph the revisions are shown as an ASCII art DAG with the most
4991 With --graph the revisions are shown as an ASCII art DAG with the most
4988 recent changeset at the top.
4992 recent changeset at the top.
4989 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4993 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4990 and '+' represents a fork where the changeset from the lines below is a
4994 and '+' represents a fork where the changeset from the lines below is a
4991 parent of the 'o' merge on the same line.
4995 parent of the 'o' merge on the same line.
4992
4996
4993 .. note::
4997 .. note::
4994
4998
4995 :hg:`log --patch` may generate unexpected diff output for merge
4999 :hg:`log --patch` may generate unexpected diff output for merge
4996 changesets, as it will only compare the merge changeset against
5000 changesets, as it will only compare the merge changeset against
4997 its first parent. Also, only files different from BOTH parents
5001 its first parent. Also, only files different from BOTH parents
4998 will appear in files:.
5002 will appear in files:.
4999
5003
5000 .. note::
5004 .. note::
5001
5005
5002 For performance reasons, :hg:`log FILE` may omit duplicate changes
5006 For performance reasons, :hg:`log FILE` may omit duplicate changes
5003 made on branches and will not show removals or mode changes. To
5007 made on branches and will not show removals or mode changes. To
5004 see all such changes, use the --removed switch.
5008 see all such changes, use the --removed switch.
5005
5009
5006 .. container:: verbose
5010 .. container:: verbose
5007
5011
5008 Some examples:
5012 Some examples:
5009
5013
5010 - changesets with full descriptions and file lists::
5014 - changesets with full descriptions and file lists::
5011
5015
5012 hg log -v
5016 hg log -v
5013
5017
5014 - changesets ancestral to the working directory::
5018 - changesets ancestral to the working directory::
5015
5019
5016 hg log -f
5020 hg log -f
5017
5021
5018 - last 10 commits on the current branch::
5022 - last 10 commits on the current branch::
5019
5023
5020 hg log -l 10 -b .
5024 hg log -l 10 -b .
5021
5025
5022 - changesets showing all modifications of a file, including removals::
5026 - changesets showing all modifications of a file, including removals::
5023
5027
5024 hg log --removed file.c
5028 hg log --removed file.c
5025
5029
5026 - all changesets that touch a directory, with diffs, excluding merges::
5030 - all changesets that touch a directory, with diffs, excluding merges::
5027
5031
5028 hg log -Mp lib/
5032 hg log -Mp lib/
5029
5033
5030 - all revision numbers that match a keyword::
5034 - all revision numbers that match a keyword::
5031
5035
5032 hg log -k bug --template "{rev}\\n"
5036 hg log -k bug --template "{rev}\\n"
5033
5037
5034 - the full hash identifier of the working directory parent::
5038 - the full hash identifier of the working directory parent::
5035
5039
5036 hg log -r . --template "{node}\\n"
5040 hg log -r . --template "{node}\\n"
5037
5041
5038 - list available log templates::
5042 - list available log templates::
5039
5043
5040 hg log -T list
5044 hg log -T list
5041
5045
5042 - check if a given changeset is included in a tagged release::
5046 - check if a given changeset is included in a tagged release::
5043
5047
5044 hg log -r "a21ccf and ancestor(1.9)"
5048 hg log -r "a21ccf and ancestor(1.9)"
5045
5049
5046 - find all changesets by some user in a date range::
5050 - find all changesets by some user in a date range::
5047
5051
5048 hg log -k alice -d "may 2008 to jul 2008"
5052 hg log -k alice -d "may 2008 to jul 2008"
5049
5053
5050 - summary of all changesets after the last tag::
5054 - summary of all changesets after the last tag::
5051
5055
5052 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5056 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5053
5057
5054 See :hg:`help dates` for a list of formats valid for -d/--date.
5058 See :hg:`help dates` for a list of formats valid for -d/--date.
5055
5059
5056 See :hg:`help revisions` and :hg:`help revsets` for more about
5060 See :hg:`help revisions` and :hg:`help revsets` for more about
5057 specifying and ordering revisions.
5061 specifying and ordering revisions.
5058
5062
5059 See :hg:`help templates` for more about pre-packaged styles and
5063 See :hg:`help templates` for more about pre-packaged styles and
5060 specifying custom templates.
5064 specifying custom templates.
5061
5065
5062 Returns 0 on success.
5066 Returns 0 on success.
5063
5067
5064 """
5068 """
5065 if opts.get('follow') and opts.get('rev'):
5069 if opts.get('follow') and opts.get('rev'):
5066 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5070 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5067 del opts['follow']
5071 del opts['follow']
5068
5072
5069 if opts.get('graph'):
5073 if opts.get('graph'):
5070 return cmdutil.graphlog(ui, repo, *pats, **opts)
5074 return cmdutil.graphlog(ui, repo, *pats, **opts)
5071
5075
5072 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5076 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5073 limit = cmdutil.loglimit(opts)
5077 limit = cmdutil.loglimit(opts)
5074 count = 0
5078 count = 0
5075
5079
5076 getrenamed = None
5080 getrenamed = None
5077 if opts.get('copies'):
5081 if opts.get('copies'):
5078 endrev = None
5082 endrev = None
5079 if opts.get('rev'):
5083 if opts.get('rev'):
5080 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5084 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5081 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5085 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5082
5086
5083 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5087 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5084 for rev in revs:
5088 for rev in revs:
5085 if count == limit:
5089 if count == limit:
5086 break
5090 break
5087 ctx = repo[rev]
5091 ctx = repo[rev]
5088 copies = None
5092 copies = None
5089 if getrenamed is not None and rev:
5093 if getrenamed is not None and rev:
5090 copies = []
5094 copies = []
5091 for fn in ctx.files():
5095 for fn in ctx.files():
5092 rename = getrenamed(fn, rev)
5096 rename = getrenamed(fn, rev)
5093 if rename:
5097 if rename:
5094 copies.append((fn, rename[0]))
5098 copies.append((fn, rename[0]))
5095 if filematcher:
5099 if filematcher:
5096 revmatchfn = filematcher(ctx.rev())
5100 revmatchfn = filematcher(ctx.rev())
5097 else:
5101 else:
5098 revmatchfn = None
5102 revmatchfn = None
5099 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5103 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5100 if displayer.flush(ctx):
5104 if displayer.flush(ctx):
5101 count += 1
5105 count += 1
5102
5106
5103 displayer.close()
5107 displayer.close()
5104
5108
5105 @command('manifest',
5109 @command('manifest',
5106 [('r', 'rev', '', _('revision to display'), _('REV')),
5110 [('r', 'rev', '', _('revision to display'), _('REV')),
5107 ('', 'all', False, _("list files from all revisions"))]
5111 ('', 'all', False, _("list files from all revisions"))]
5108 + formatteropts,
5112 + formatteropts,
5109 _('[-r REV]'))
5113 _('[-r REV]'))
5110 def manifest(ui, repo, node=None, rev=None, **opts):
5114 def manifest(ui, repo, node=None, rev=None, **opts):
5111 """output the current or given revision of the project manifest
5115 """output the current or given revision of the project manifest
5112
5116
5113 Print a list of version controlled files for the given revision.
5117 Print a list of version controlled files for the given revision.
5114 If no revision is given, the first parent of the working directory
5118 If no revision is given, the first parent of the working directory
5115 is used, or the null revision if no revision is checked out.
5119 is used, or the null revision if no revision is checked out.
5116
5120
5117 With -v, print file permissions, symlink and executable bits.
5121 With -v, print file permissions, symlink and executable bits.
5118 With --debug, print file revision hashes.
5122 With --debug, print file revision hashes.
5119
5123
5120 If option --all is specified, the list of all files from all revisions
5124 If option --all is specified, the list of all files from all revisions
5121 is printed. This includes deleted and renamed files.
5125 is printed. This includes deleted and renamed files.
5122
5126
5123 Returns 0 on success.
5127 Returns 0 on success.
5124 """
5128 """
5125
5129
5126 fm = ui.formatter('manifest', opts)
5130 fm = ui.formatter('manifest', opts)
5127
5131
5128 if opts.get('all'):
5132 if opts.get('all'):
5129 if rev or node:
5133 if rev or node:
5130 raise error.Abort(_("can't specify a revision with --all"))
5134 raise error.Abort(_("can't specify a revision with --all"))
5131
5135
5132 res = []
5136 res = []
5133 prefix = "data/"
5137 prefix = "data/"
5134 suffix = ".i"
5138 suffix = ".i"
5135 plen = len(prefix)
5139 plen = len(prefix)
5136 slen = len(suffix)
5140 slen = len(suffix)
5137 with repo.lock():
5141 with repo.lock():
5138 for fn, b, size in repo.store.datafiles():
5142 for fn, b, size in repo.store.datafiles():
5139 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5143 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5140 res.append(fn[plen:-slen])
5144 res.append(fn[plen:-slen])
5141 for f in res:
5145 for f in res:
5142 fm.startitem()
5146 fm.startitem()
5143 fm.write("path", '%s\n', f)
5147 fm.write("path", '%s\n', f)
5144 fm.end()
5148 fm.end()
5145 return
5149 return
5146
5150
5147 if rev and node:
5151 if rev and node:
5148 raise error.Abort(_("please specify just one revision"))
5152 raise error.Abort(_("please specify just one revision"))
5149
5153
5150 if not node:
5154 if not node:
5151 node = rev
5155 node = rev
5152
5156
5153 char = {'l': '@', 'x': '*', '': ''}
5157 char = {'l': '@', 'x': '*', '': ''}
5154 mode = {'l': '644', 'x': '755', '': '644'}
5158 mode = {'l': '644', 'x': '755', '': '644'}
5155 ctx = scmutil.revsingle(repo, node)
5159 ctx = scmutil.revsingle(repo, node)
5156 mf = ctx.manifest()
5160 mf = ctx.manifest()
5157 for f in ctx:
5161 for f in ctx:
5158 fm.startitem()
5162 fm.startitem()
5159 fl = ctx[f].flags()
5163 fl = ctx[f].flags()
5160 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5164 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5161 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5165 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5162 fm.write('path', '%s\n', f)
5166 fm.write('path', '%s\n', f)
5163 fm.end()
5167 fm.end()
5164
5168
5165 @command('^merge',
5169 @command('^merge',
5166 [('f', 'force', None,
5170 [('f', 'force', None,
5167 _('force a merge including outstanding changes (DEPRECATED)')),
5171 _('force a merge including outstanding changes (DEPRECATED)')),
5168 ('r', 'rev', '', _('revision to merge'), _('REV')),
5172 ('r', 'rev', '', _('revision to merge'), _('REV')),
5169 ('P', 'preview', None,
5173 ('P', 'preview', None,
5170 _('review revisions to merge (no merge is performed)'))
5174 _('review revisions to merge (no merge is performed)'))
5171 ] + mergetoolopts,
5175 ] + mergetoolopts,
5172 _('[-P] [-f] [[-r] REV]'))
5176 _('[-P] [-f] [[-r] REV]'))
5173 def merge(ui, repo, node=None, **opts):
5177 def merge(ui, repo, node=None, **opts):
5174 """merge another revision into working directory
5178 """merge another revision into working directory
5175
5179
5176 The current working directory is updated with all changes made in
5180 The current working directory is updated with all changes made in
5177 the requested revision since the last common predecessor revision.
5181 the requested revision since the last common predecessor revision.
5178
5182
5179 Files that changed between either parent are marked as changed for
5183 Files that changed between either parent are marked as changed for
5180 the next commit and a commit must be performed before any further
5184 the next commit and a commit must be performed before any further
5181 updates to the repository are allowed. The next commit will have
5185 updates to the repository are allowed. The next commit will have
5182 two parents.
5186 two parents.
5183
5187
5184 ``--tool`` can be used to specify the merge tool used for file
5188 ``--tool`` can be used to specify the merge tool used for file
5185 merges. It overrides the HGMERGE environment variable and your
5189 merges. It overrides the HGMERGE environment variable and your
5186 configuration files. See :hg:`help merge-tools` for options.
5190 configuration files. See :hg:`help merge-tools` for options.
5187
5191
5188 If no revision is specified, the working directory's parent is a
5192 If no revision is specified, the working directory's parent is a
5189 head revision, and the current branch contains exactly one other
5193 head revision, and the current branch contains exactly one other
5190 head, the other head is merged with by default. Otherwise, an
5194 head, the other head is merged with by default. Otherwise, an
5191 explicit revision with which to merge with must be provided.
5195 explicit revision with which to merge with must be provided.
5192
5196
5193 See :hg:`help resolve` for information on handling file conflicts.
5197 See :hg:`help resolve` for information on handling file conflicts.
5194
5198
5195 To undo an uncommitted merge, use :hg:`update --clean .` which
5199 To undo an uncommitted merge, use :hg:`update --clean .` which
5196 will check out a clean copy of the original merge parent, losing
5200 will check out a clean copy of the original merge parent, losing
5197 all changes.
5201 all changes.
5198
5202
5199 Returns 0 on success, 1 if there are unresolved files.
5203 Returns 0 on success, 1 if there are unresolved files.
5200 """
5204 """
5201
5205
5202 if opts.get('rev') and node:
5206 if opts.get('rev') and node:
5203 raise error.Abort(_("please specify just one revision"))
5207 raise error.Abort(_("please specify just one revision"))
5204 if not node:
5208 if not node:
5205 node = opts.get('rev')
5209 node = opts.get('rev')
5206
5210
5207 if node:
5211 if node:
5208 node = scmutil.revsingle(repo, node).node()
5212 node = scmutil.revsingle(repo, node).node()
5209
5213
5210 if not node:
5214 if not node:
5211 node = repo[destutil.destmerge(repo)].node()
5215 node = repo[destutil.destmerge(repo)].node()
5212
5216
5213 if opts.get('preview'):
5217 if opts.get('preview'):
5214 # find nodes that are ancestors of p2 but not of p1
5218 # find nodes that are ancestors of p2 but not of p1
5215 p1 = repo.lookup('.')
5219 p1 = repo.lookup('.')
5216 p2 = repo.lookup(node)
5220 p2 = repo.lookup(node)
5217 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5221 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5218
5222
5219 displayer = cmdutil.show_changeset(ui, repo, opts)
5223 displayer = cmdutil.show_changeset(ui, repo, opts)
5220 for node in nodes:
5224 for node in nodes:
5221 displayer.show(repo[node])
5225 displayer.show(repo[node])
5222 displayer.close()
5226 displayer.close()
5223 return 0
5227 return 0
5224
5228
5225 try:
5229 try:
5226 # ui.forcemerge is an internal variable, do not document
5230 # ui.forcemerge is an internal variable, do not document
5227 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5231 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5228 return hg.merge(repo, node, force=opts.get('force'))
5232 return hg.merge(repo, node, force=opts.get('force'))
5229 finally:
5233 finally:
5230 ui.setconfig('ui', 'forcemerge', '', 'merge')
5234 ui.setconfig('ui', 'forcemerge', '', 'merge')
5231
5235
5232 @command('outgoing|out',
5236 @command('outgoing|out',
5233 [('f', 'force', None, _('run even when the destination is unrelated')),
5237 [('f', 'force', None, _('run even when the destination is unrelated')),
5234 ('r', 'rev', [],
5238 ('r', 'rev', [],
5235 _('a changeset intended to be included in the destination'), _('REV')),
5239 _('a changeset intended to be included in the destination'), _('REV')),
5236 ('n', 'newest-first', None, _('show newest record first')),
5240 ('n', 'newest-first', None, _('show newest record first')),
5237 ('B', 'bookmarks', False, _('compare bookmarks')),
5241 ('B', 'bookmarks', False, _('compare bookmarks')),
5238 ('b', 'branch', [], _('a specific branch you would like to push'),
5242 ('b', 'branch', [], _('a specific branch you would like to push'),
5239 _('BRANCH')),
5243 _('BRANCH')),
5240 ] + logopts + remoteopts + subrepoopts,
5244 ] + logopts + remoteopts + subrepoopts,
5241 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5245 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5242 def outgoing(ui, repo, dest=None, **opts):
5246 def outgoing(ui, repo, dest=None, **opts):
5243 """show changesets not found in the destination
5247 """show changesets not found in the destination
5244
5248
5245 Show changesets not found in the specified destination repository
5249 Show changesets not found in the specified destination repository
5246 or the default push location. These are the changesets that would
5250 or the default push location. These are the changesets that would
5247 be pushed if a push was requested.
5251 be pushed if a push was requested.
5248
5252
5249 See pull for details of valid destination formats.
5253 See pull for details of valid destination formats.
5250
5254
5251 .. container:: verbose
5255 .. container:: verbose
5252
5256
5253 With -B/--bookmarks, the result of bookmark comparison between
5257 With -B/--bookmarks, the result of bookmark comparison between
5254 local and remote repositories is displayed. With -v/--verbose,
5258 local and remote repositories is displayed. With -v/--verbose,
5255 status is also displayed for each bookmark like below::
5259 status is also displayed for each bookmark like below::
5256
5260
5257 BM1 01234567890a added
5261 BM1 01234567890a added
5258 BM2 deleted
5262 BM2 deleted
5259 BM3 234567890abc advanced
5263 BM3 234567890abc advanced
5260 BM4 34567890abcd diverged
5264 BM4 34567890abcd diverged
5261 BM5 4567890abcde changed
5265 BM5 4567890abcde changed
5262
5266
5263 The action taken when pushing depends on the
5267 The action taken when pushing depends on the
5264 status of each bookmark:
5268 status of each bookmark:
5265
5269
5266 :``added``: push with ``-B`` will create it
5270 :``added``: push with ``-B`` will create it
5267 :``deleted``: push with ``-B`` will delete it
5271 :``deleted``: push with ``-B`` will delete it
5268 :``advanced``: push will update it
5272 :``advanced``: push will update it
5269 :``diverged``: push with ``-B`` will update it
5273 :``diverged``: push with ``-B`` will update it
5270 :``changed``: push with ``-B`` will update it
5274 :``changed``: push with ``-B`` will update it
5271
5275
5272 From the point of view of pushing behavior, bookmarks
5276 From the point of view of pushing behavior, bookmarks
5273 existing only in the remote repository are treated as
5277 existing only in the remote repository are treated as
5274 ``deleted``, even if it is in fact added remotely.
5278 ``deleted``, even if it is in fact added remotely.
5275
5279
5276 Returns 0 if there are outgoing changes, 1 otherwise.
5280 Returns 0 if there are outgoing changes, 1 otherwise.
5277 """
5281 """
5278 if opts.get('graph'):
5282 if opts.get('graph'):
5279 cmdutil.checkunsupportedgraphflags([], opts)
5283 cmdutil.checkunsupportedgraphflags([], opts)
5280 o, other = hg._outgoing(ui, repo, dest, opts)
5284 o, other = hg._outgoing(ui, repo, dest, opts)
5281 if not o:
5285 if not o:
5282 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5286 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5283 return
5287 return
5284
5288
5285 revdag = cmdutil.graphrevs(repo, o, opts)
5289 revdag = cmdutil.graphrevs(repo, o, opts)
5286 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5290 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5287 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5291 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5288 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5292 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5289 return 0
5293 return 0
5290
5294
5291 if opts.get('bookmarks'):
5295 if opts.get('bookmarks'):
5292 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5296 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5293 dest, branches = hg.parseurl(dest, opts.get('branch'))
5297 dest, branches = hg.parseurl(dest, opts.get('branch'))
5294 other = hg.peer(repo, opts, dest)
5298 other = hg.peer(repo, opts, dest)
5295 if 'bookmarks' not in other.listkeys('namespaces'):
5299 if 'bookmarks' not in other.listkeys('namespaces'):
5296 ui.warn(_("remote doesn't support bookmarks\n"))
5300 ui.warn(_("remote doesn't support bookmarks\n"))
5297 return 0
5301 return 0
5298 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5302 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5299 return bookmarks.outgoing(ui, repo, other)
5303 return bookmarks.outgoing(ui, repo, other)
5300
5304
5301 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5305 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5302 try:
5306 try:
5303 return hg.outgoing(ui, repo, dest, opts)
5307 return hg.outgoing(ui, repo, dest, opts)
5304 finally:
5308 finally:
5305 del repo._subtoppath
5309 del repo._subtoppath
5306
5310
5307 @command('parents',
5311 @command('parents',
5308 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5312 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5309 ] + templateopts,
5313 ] + templateopts,
5310 _('[-r REV] [FILE]'),
5314 _('[-r REV] [FILE]'),
5311 inferrepo=True)
5315 inferrepo=True)
5312 def parents(ui, repo, file_=None, **opts):
5316 def parents(ui, repo, file_=None, **opts):
5313 """show the parents of the working directory or revision (DEPRECATED)
5317 """show the parents of the working directory or revision (DEPRECATED)
5314
5318
5315 Print the working directory's parent revisions. If a revision is
5319 Print the working directory's parent revisions. If a revision is
5316 given via -r/--rev, the parent of that revision will be printed.
5320 given via -r/--rev, the parent of that revision will be printed.
5317 If a file argument is given, the revision in which the file was
5321 If a file argument is given, the revision in which the file was
5318 last changed (before the working directory revision or the
5322 last changed (before the working directory revision or the
5319 argument to --rev if given) is printed.
5323 argument to --rev if given) is printed.
5320
5324
5321 This command is equivalent to::
5325 This command is equivalent to::
5322
5326
5323 hg log -r "p1()+p2()" or
5327 hg log -r "p1()+p2()" or
5324 hg log -r "p1(REV)+p2(REV)" or
5328 hg log -r "p1(REV)+p2(REV)" or
5325 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5329 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5326 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5330 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5327
5331
5328 See :hg:`summary` and :hg:`help revsets` for related information.
5332 See :hg:`summary` and :hg:`help revsets` for related information.
5329
5333
5330 Returns 0 on success.
5334 Returns 0 on success.
5331 """
5335 """
5332
5336
5333 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5337 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5334
5338
5335 if file_:
5339 if file_:
5336 m = scmutil.match(ctx, (file_,), opts)
5340 m = scmutil.match(ctx, (file_,), opts)
5337 if m.anypats() or len(m.files()) != 1:
5341 if m.anypats() or len(m.files()) != 1:
5338 raise error.Abort(_('can only specify an explicit filename'))
5342 raise error.Abort(_('can only specify an explicit filename'))
5339 file_ = m.files()[0]
5343 file_ = m.files()[0]
5340 filenodes = []
5344 filenodes = []
5341 for cp in ctx.parents():
5345 for cp in ctx.parents():
5342 if not cp:
5346 if not cp:
5343 continue
5347 continue
5344 try:
5348 try:
5345 filenodes.append(cp.filenode(file_))
5349 filenodes.append(cp.filenode(file_))
5346 except error.LookupError:
5350 except error.LookupError:
5347 pass
5351 pass
5348 if not filenodes:
5352 if not filenodes:
5349 raise error.Abort(_("'%s' not found in manifest!") % file_)
5353 raise error.Abort(_("'%s' not found in manifest!") % file_)
5350 p = []
5354 p = []
5351 for fn in filenodes:
5355 for fn in filenodes:
5352 fctx = repo.filectx(file_, fileid=fn)
5356 fctx = repo.filectx(file_, fileid=fn)
5353 p.append(fctx.node())
5357 p.append(fctx.node())
5354 else:
5358 else:
5355 p = [cp.node() for cp in ctx.parents()]
5359 p = [cp.node() for cp in ctx.parents()]
5356
5360
5357 displayer = cmdutil.show_changeset(ui, repo, opts)
5361 displayer = cmdutil.show_changeset(ui, repo, opts)
5358 for n in p:
5362 for n in p:
5359 if n != nullid:
5363 if n != nullid:
5360 displayer.show(repo[n])
5364 displayer.show(repo[n])
5361 displayer.close()
5365 displayer.close()
5362
5366
5363 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5367 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5364 def paths(ui, repo, search=None, **opts):
5368 def paths(ui, repo, search=None, **opts):
5365 """show aliases for remote repositories
5369 """show aliases for remote repositories
5366
5370
5367 Show definition of symbolic path name NAME. If no name is given,
5371 Show definition of symbolic path name NAME. If no name is given,
5368 show definition of all available names.
5372 show definition of all available names.
5369
5373
5370 Option -q/--quiet suppresses all output when searching for NAME
5374 Option -q/--quiet suppresses all output when searching for NAME
5371 and shows only the path names when listing all definitions.
5375 and shows only the path names when listing all definitions.
5372
5376
5373 Path names are defined in the [paths] section of your
5377 Path names are defined in the [paths] section of your
5374 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5378 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5375 repository, ``.hg/hgrc`` is used, too.
5379 repository, ``.hg/hgrc`` is used, too.
5376
5380
5377 The path names ``default`` and ``default-push`` have a special
5381 The path names ``default`` and ``default-push`` have a special
5378 meaning. When performing a push or pull operation, they are used
5382 meaning. When performing a push or pull operation, they are used
5379 as fallbacks if no location is specified on the command-line.
5383 as fallbacks if no location is specified on the command-line.
5380 When ``default-push`` is set, it will be used for push and
5384 When ``default-push`` is set, it will be used for push and
5381 ``default`` will be used for pull; otherwise ``default`` is used
5385 ``default`` will be used for pull; otherwise ``default`` is used
5382 as the fallback for both. When cloning a repository, the clone
5386 as the fallback for both. When cloning a repository, the clone
5383 source is written as ``default`` in ``.hg/hgrc``.
5387 source is written as ``default`` in ``.hg/hgrc``.
5384
5388
5385 .. note::
5389 .. note::
5386
5390
5387 ``default`` and ``default-push`` apply to all inbound (e.g.
5391 ``default`` and ``default-push`` apply to all inbound (e.g.
5388 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5392 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5389 and :hg:`bundle`) operations.
5393 and :hg:`bundle`) operations.
5390
5394
5391 See :hg:`help urls` for more information.
5395 See :hg:`help urls` for more information.
5392
5396
5393 Returns 0 on success.
5397 Returns 0 on success.
5394 """
5398 """
5395 if search:
5399 if search:
5396 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5400 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5397 if name == search]
5401 if name == search]
5398 else:
5402 else:
5399 pathitems = sorted(ui.paths.iteritems())
5403 pathitems = sorted(ui.paths.iteritems())
5400
5404
5401 fm = ui.formatter('paths', opts)
5405 fm = ui.formatter('paths', opts)
5402 if fm:
5406 if fm:
5403 hidepassword = str
5407 hidepassword = str
5404 else:
5408 else:
5405 hidepassword = util.hidepassword
5409 hidepassword = util.hidepassword
5406 if ui.quiet:
5410 if ui.quiet:
5407 namefmt = '%s\n'
5411 namefmt = '%s\n'
5408 else:
5412 else:
5409 namefmt = '%s = '
5413 namefmt = '%s = '
5410 showsubopts = not search and not ui.quiet
5414 showsubopts = not search and not ui.quiet
5411
5415
5412 for name, path in pathitems:
5416 for name, path in pathitems:
5413 fm.startitem()
5417 fm.startitem()
5414 fm.condwrite(not search, 'name', namefmt, name)
5418 fm.condwrite(not search, 'name', namefmt, name)
5415 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5419 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5416 for subopt, value in sorted(path.suboptions.items()):
5420 for subopt, value in sorted(path.suboptions.items()):
5417 assert subopt not in ('name', 'url')
5421 assert subopt not in ('name', 'url')
5418 if showsubopts:
5422 if showsubopts:
5419 fm.plain('%s:%s = ' % (name, subopt))
5423 fm.plain('%s:%s = ' % (name, subopt))
5420 fm.condwrite(showsubopts, subopt, '%s\n', value)
5424 fm.condwrite(showsubopts, subopt, '%s\n', value)
5421
5425
5422 fm.end()
5426 fm.end()
5423
5427
5424 if search and not pathitems:
5428 if search and not pathitems:
5425 if not ui.quiet:
5429 if not ui.quiet:
5426 ui.warn(_("not found!\n"))
5430 ui.warn(_("not found!\n"))
5427 return 1
5431 return 1
5428 else:
5432 else:
5429 return 0
5433 return 0
5430
5434
5431 @command('phase',
5435 @command('phase',
5432 [('p', 'public', False, _('set changeset phase to public')),
5436 [('p', 'public', False, _('set changeset phase to public')),
5433 ('d', 'draft', False, _('set changeset phase to draft')),
5437 ('d', 'draft', False, _('set changeset phase to draft')),
5434 ('s', 'secret', False, _('set changeset phase to secret')),
5438 ('s', 'secret', False, _('set changeset phase to secret')),
5435 ('f', 'force', False, _('allow to move boundary backward')),
5439 ('f', 'force', False, _('allow to move boundary backward')),
5436 ('r', 'rev', [], _('target revision'), _('REV')),
5440 ('r', 'rev', [], _('target revision'), _('REV')),
5437 ],
5441 ],
5438 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5442 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5439 def phase(ui, repo, *revs, **opts):
5443 def phase(ui, repo, *revs, **opts):
5440 """set or show the current phase name
5444 """set or show the current phase name
5441
5445
5442 With no argument, show the phase name of the current revision(s).
5446 With no argument, show the phase name of the current revision(s).
5443
5447
5444 With one of -p/--public, -d/--draft or -s/--secret, change the
5448 With one of -p/--public, -d/--draft or -s/--secret, change the
5445 phase value of the specified revisions.
5449 phase value of the specified revisions.
5446
5450
5447 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5451 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5448 lower phase to an higher phase. Phases are ordered as follows::
5452 lower phase to an higher phase. Phases are ordered as follows::
5449
5453
5450 public < draft < secret
5454 public < draft < secret
5451
5455
5452 Returns 0 on success, 1 if some phases could not be changed.
5456 Returns 0 on success, 1 if some phases could not be changed.
5453
5457
5454 (For more information about the phases concept, see :hg:`help phases`.)
5458 (For more information about the phases concept, see :hg:`help phases`.)
5455 """
5459 """
5456 # search for a unique phase argument
5460 # search for a unique phase argument
5457 targetphase = None
5461 targetphase = None
5458 for idx, name in enumerate(phases.phasenames):
5462 for idx, name in enumerate(phases.phasenames):
5459 if opts[name]:
5463 if opts[name]:
5460 if targetphase is not None:
5464 if targetphase is not None:
5461 raise error.Abort(_('only one phase can be specified'))
5465 raise error.Abort(_('only one phase can be specified'))
5462 targetphase = idx
5466 targetphase = idx
5463
5467
5464 # look for specified revision
5468 # look for specified revision
5465 revs = list(revs)
5469 revs = list(revs)
5466 revs.extend(opts['rev'])
5470 revs.extend(opts['rev'])
5467 if not revs:
5471 if not revs:
5468 # display both parents as the second parent phase can influence
5472 # display both parents as the second parent phase can influence
5469 # the phase of a merge commit
5473 # the phase of a merge commit
5470 revs = [c.rev() for c in repo[None].parents()]
5474 revs = [c.rev() for c in repo[None].parents()]
5471
5475
5472 revs = scmutil.revrange(repo, revs)
5476 revs = scmutil.revrange(repo, revs)
5473
5477
5474 lock = None
5478 lock = None
5475 ret = 0
5479 ret = 0
5476 if targetphase is None:
5480 if targetphase is None:
5477 # display
5481 # display
5478 for r in revs:
5482 for r in revs:
5479 ctx = repo[r]
5483 ctx = repo[r]
5480 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5484 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5481 else:
5485 else:
5482 tr = None
5486 tr = None
5483 lock = repo.lock()
5487 lock = repo.lock()
5484 try:
5488 try:
5485 tr = repo.transaction("phase")
5489 tr = repo.transaction("phase")
5486 # set phase
5490 # set phase
5487 if not revs:
5491 if not revs:
5488 raise error.Abort(_('empty revision set'))
5492 raise error.Abort(_('empty revision set'))
5489 nodes = [repo[r].node() for r in revs]
5493 nodes = [repo[r].node() for r in revs]
5490 # moving revision from public to draft may hide them
5494 # moving revision from public to draft may hide them
5491 # We have to check result on an unfiltered repository
5495 # We have to check result on an unfiltered repository
5492 unfi = repo.unfiltered()
5496 unfi = repo.unfiltered()
5493 getphase = unfi._phasecache.phase
5497 getphase = unfi._phasecache.phase
5494 olddata = [getphase(unfi, r) for r in unfi]
5498 olddata = [getphase(unfi, r) for r in unfi]
5495 phases.advanceboundary(repo, tr, targetphase, nodes)
5499 phases.advanceboundary(repo, tr, targetphase, nodes)
5496 if opts['force']:
5500 if opts['force']:
5497 phases.retractboundary(repo, tr, targetphase, nodes)
5501 phases.retractboundary(repo, tr, targetphase, nodes)
5498 tr.close()
5502 tr.close()
5499 finally:
5503 finally:
5500 if tr is not None:
5504 if tr is not None:
5501 tr.release()
5505 tr.release()
5502 lock.release()
5506 lock.release()
5503 getphase = unfi._phasecache.phase
5507 getphase = unfi._phasecache.phase
5504 newdata = [getphase(unfi, r) for r in unfi]
5508 newdata = [getphase(unfi, r) for r in unfi]
5505 changes = sum(newdata[r] != olddata[r] for r in unfi)
5509 changes = sum(newdata[r] != olddata[r] for r in unfi)
5506 cl = unfi.changelog
5510 cl = unfi.changelog
5507 rejected = [n for n in nodes
5511 rejected = [n for n in nodes
5508 if newdata[cl.rev(n)] < targetphase]
5512 if newdata[cl.rev(n)] < targetphase]
5509 if rejected:
5513 if rejected:
5510 ui.warn(_('cannot move %i changesets to a higher '
5514 ui.warn(_('cannot move %i changesets to a higher '
5511 'phase, use --force\n') % len(rejected))
5515 'phase, use --force\n') % len(rejected))
5512 ret = 1
5516 ret = 1
5513 if changes:
5517 if changes:
5514 msg = _('phase changed for %i changesets\n') % changes
5518 msg = _('phase changed for %i changesets\n') % changes
5515 if ret:
5519 if ret:
5516 ui.status(msg)
5520 ui.status(msg)
5517 else:
5521 else:
5518 ui.note(msg)
5522 ui.note(msg)
5519 else:
5523 else:
5520 ui.warn(_('no phases changed\n'))
5524 ui.warn(_('no phases changed\n'))
5521 return ret
5525 return ret
5522
5526
5523 def postincoming(ui, repo, modheads, optupdate, checkout):
5527 def postincoming(ui, repo, modheads, optupdate, checkout):
5524 if modheads == 0:
5528 if modheads == 0:
5525 return
5529 return
5526 if optupdate:
5530 if optupdate:
5527 try:
5531 try:
5528 brev = checkout
5532 brev = checkout
5529 movemarkfrom = None
5533 movemarkfrom = None
5530 if not checkout:
5534 if not checkout:
5531 updata = destutil.destupdate(repo)
5535 updata = destutil.destupdate(repo)
5532 checkout, movemarkfrom, brev = updata
5536 checkout, movemarkfrom, brev = updata
5533 ret = hg.update(repo, checkout)
5537 ret = hg.update(repo, checkout)
5534 except error.UpdateAbort as inst:
5538 except error.UpdateAbort as inst:
5535 msg = _("not updating: %s") % str(inst)
5539 msg = _("not updating: %s") % str(inst)
5536 hint = inst.hint
5540 hint = inst.hint
5537 raise error.UpdateAbort(msg, hint=hint)
5541 raise error.UpdateAbort(msg, hint=hint)
5538 if not ret and not checkout:
5542 if not ret and not checkout:
5539 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5543 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5540 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5544 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5541 return ret
5545 return ret
5542 if modheads > 1:
5546 if modheads > 1:
5543 currentbranchheads = len(repo.branchheads())
5547 currentbranchheads = len(repo.branchheads())
5544 if currentbranchheads == modheads:
5548 if currentbranchheads == modheads:
5545 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5549 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5546 elif currentbranchheads > 1:
5550 elif currentbranchheads > 1:
5547 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5551 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5548 "merge)\n"))
5552 "merge)\n"))
5549 else:
5553 else:
5550 ui.status(_("(run 'hg heads' to see heads)\n"))
5554 ui.status(_("(run 'hg heads' to see heads)\n"))
5551 else:
5555 else:
5552 ui.status(_("(run 'hg update' to get a working copy)\n"))
5556 ui.status(_("(run 'hg update' to get a working copy)\n"))
5553
5557
5554 @command('^pull',
5558 @command('^pull',
5555 [('u', 'update', None,
5559 [('u', 'update', None,
5556 _('update to new branch head if changesets were pulled')),
5560 _('update to new branch head if changesets were pulled')),
5557 ('f', 'force', None, _('run even when remote repository is unrelated')),
5561 ('f', 'force', None, _('run even when remote repository is unrelated')),
5558 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5562 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5559 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5563 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5560 ('b', 'branch', [], _('a specific branch you would like to pull'),
5564 ('b', 'branch', [], _('a specific branch you would like to pull'),
5561 _('BRANCH')),
5565 _('BRANCH')),
5562 ] + remoteopts,
5566 ] + remoteopts,
5563 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5567 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5564 def pull(ui, repo, source="default", **opts):
5568 def pull(ui, repo, source="default", **opts):
5565 """pull changes from the specified source
5569 """pull changes from the specified source
5566
5570
5567 Pull changes from a remote repository to a local one.
5571 Pull changes from a remote repository to a local one.
5568
5572
5569 This finds all changes from the repository at the specified path
5573 This finds all changes from the repository at the specified path
5570 or URL and adds them to a local repository (the current one unless
5574 or URL and adds them to a local repository (the current one unless
5571 -R is specified). By default, this does not update the copy of the
5575 -R is specified). By default, this does not update the copy of the
5572 project in the working directory.
5576 project in the working directory.
5573
5577
5574 Use :hg:`incoming` if you want to see what would have been added
5578 Use :hg:`incoming` if you want to see what would have been added
5575 by a pull at the time you issued this command. If you then decide
5579 by a pull at the time you issued this command. If you then decide
5576 to add those changes to the repository, you should use :hg:`pull
5580 to add those changes to the repository, you should use :hg:`pull
5577 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5581 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5578
5582
5579 If SOURCE is omitted, the 'default' path will be used.
5583 If SOURCE is omitted, the 'default' path will be used.
5580 See :hg:`help urls` for more information.
5584 See :hg:`help urls` for more information.
5581
5585
5582 Returns 0 on success, 1 if an update had unresolved files.
5586 Returns 0 on success, 1 if an update had unresolved files.
5583 """
5587 """
5584 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5588 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5585 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5589 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5586 other = hg.peer(repo, opts, source)
5590 other = hg.peer(repo, opts, source)
5587 try:
5591 try:
5588 revs, checkout = hg.addbranchrevs(repo, other, branches,
5592 revs, checkout = hg.addbranchrevs(repo, other, branches,
5589 opts.get('rev'))
5593 opts.get('rev'))
5590
5594
5591
5595
5592 pullopargs = {}
5596 pullopargs = {}
5593 if opts.get('bookmark'):
5597 if opts.get('bookmark'):
5594 if not revs:
5598 if not revs:
5595 revs = []
5599 revs = []
5596 # The list of bookmark used here is not the one used to actually
5600 # The list of bookmark used here is not the one used to actually
5597 # update the bookmark name. This can result in the revision pulled
5601 # update the bookmark name. This can result in the revision pulled
5598 # not ending up with the name of the bookmark because of a race
5602 # not ending up with the name of the bookmark because of a race
5599 # condition on the server. (See issue 4689 for details)
5603 # condition on the server. (See issue 4689 for details)
5600 remotebookmarks = other.listkeys('bookmarks')
5604 remotebookmarks = other.listkeys('bookmarks')
5601 pullopargs['remotebookmarks'] = remotebookmarks
5605 pullopargs['remotebookmarks'] = remotebookmarks
5602 for b in opts['bookmark']:
5606 for b in opts['bookmark']:
5603 if b not in remotebookmarks:
5607 if b not in remotebookmarks:
5604 raise error.Abort(_('remote bookmark %s not found!') % b)
5608 raise error.Abort(_('remote bookmark %s not found!') % b)
5605 revs.append(remotebookmarks[b])
5609 revs.append(remotebookmarks[b])
5606
5610
5607 if revs:
5611 if revs:
5608 try:
5612 try:
5609 # When 'rev' is a bookmark name, we cannot guarantee that it
5613 # When 'rev' is a bookmark name, we cannot guarantee that it
5610 # will be updated with that name because of a race condition
5614 # will be updated with that name because of a race condition
5611 # server side. (See issue 4689 for details)
5615 # server side. (See issue 4689 for details)
5612 oldrevs = revs
5616 oldrevs = revs
5613 revs = [] # actually, nodes
5617 revs = [] # actually, nodes
5614 for r in oldrevs:
5618 for r in oldrevs:
5615 node = other.lookup(r)
5619 node = other.lookup(r)
5616 revs.append(node)
5620 revs.append(node)
5617 if r == checkout:
5621 if r == checkout:
5618 checkout = node
5622 checkout = node
5619 except error.CapabilityError:
5623 except error.CapabilityError:
5620 err = _("other repository doesn't support revision lookup, "
5624 err = _("other repository doesn't support revision lookup, "
5621 "so a rev cannot be specified.")
5625 "so a rev cannot be specified.")
5622 raise error.Abort(err)
5626 raise error.Abort(err)
5623
5627
5624 pullopargs.update(opts.get('opargs', {}))
5628 pullopargs.update(opts.get('opargs', {}))
5625 modheads = exchange.pull(repo, other, heads=revs,
5629 modheads = exchange.pull(repo, other, heads=revs,
5626 force=opts.get('force'),
5630 force=opts.get('force'),
5627 bookmarks=opts.get('bookmark', ()),
5631 bookmarks=opts.get('bookmark', ()),
5628 opargs=pullopargs).cgresult
5632 opargs=pullopargs).cgresult
5629 if checkout:
5633 if checkout:
5630 checkout = str(repo.changelog.rev(checkout))
5634 checkout = str(repo.changelog.rev(checkout))
5631 repo._subtoppath = source
5635 repo._subtoppath = source
5632 try:
5636 try:
5633 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5637 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5634
5638
5635 finally:
5639 finally:
5636 del repo._subtoppath
5640 del repo._subtoppath
5637
5641
5638 finally:
5642 finally:
5639 other.close()
5643 other.close()
5640 return ret
5644 return ret
5641
5645
5642 @command('^push',
5646 @command('^push',
5643 [('f', 'force', None, _('force push')),
5647 [('f', 'force', None, _('force push')),
5644 ('r', 'rev', [],
5648 ('r', 'rev', [],
5645 _('a changeset intended to be included in the destination'),
5649 _('a changeset intended to be included in the destination'),
5646 _('REV')),
5650 _('REV')),
5647 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5651 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5648 ('b', 'branch', [],
5652 ('b', 'branch', [],
5649 _('a specific branch you would like to push'), _('BRANCH')),
5653 _('a specific branch you would like to push'), _('BRANCH')),
5650 ('', 'new-branch', False, _('allow pushing a new branch')),
5654 ('', 'new-branch', False, _('allow pushing a new branch')),
5651 ] + remoteopts,
5655 ] + remoteopts,
5652 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5656 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5653 def push(ui, repo, dest=None, **opts):
5657 def push(ui, repo, dest=None, **opts):
5654 """push changes to the specified destination
5658 """push changes to the specified destination
5655
5659
5656 Push changesets from the local repository to the specified
5660 Push changesets from the local repository to the specified
5657 destination.
5661 destination.
5658
5662
5659 This operation is symmetrical to pull: it is identical to a pull
5663 This operation is symmetrical to pull: it is identical to a pull
5660 in the destination repository from the current one.
5664 in the destination repository from the current one.
5661
5665
5662 By default, push will not allow creation of new heads at the
5666 By default, push will not allow creation of new heads at the
5663 destination, since multiple heads would make it unclear which head
5667 destination, since multiple heads would make it unclear which head
5664 to use. In this situation, it is recommended to pull and merge
5668 to use. In this situation, it is recommended to pull and merge
5665 before pushing.
5669 before pushing.
5666
5670
5667 Use --new-branch if you want to allow push to create a new named
5671 Use --new-branch if you want to allow push to create a new named
5668 branch that is not present at the destination. This allows you to
5672 branch that is not present at the destination. This allows you to
5669 only create a new branch without forcing other changes.
5673 only create a new branch without forcing other changes.
5670
5674
5671 .. note::
5675 .. note::
5672
5676
5673 Extra care should be taken with the -f/--force option,
5677 Extra care should be taken with the -f/--force option,
5674 which will push all new heads on all branches, an action which will
5678 which will push all new heads on all branches, an action which will
5675 almost always cause confusion for collaborators.
5679 almost always cause confusion for collaborators.
5676
5680
5677 If -r/--rev is used, the specified revision and all its ancestors
5681 If -r/--rev is used, the specified revision and all its ancestors
5678 will be pushed to the remote repository.
5682 will be pushed to the remote repository.
5679
5683
5680 If -B/--bookmark is used, the specified bookmarked revision, its
5684 If -B/--bookmark is used, the specified bookmarked revision, its
5681 ancestors, and the bookmark will be pushed to the remote
5685 ancestors, and the bookmark will be pushed to the remote
5682 repository.
5686 repository.
5683
5687
5684 Please see :hg:`help urls` for important details about ``ssh://``
5688 Please see :hg:`help urls` for important details about ``ssh://``
5685 URLs. If DESTINATION is omitted, a default path will be used.
5689 URLs. If DESTINATION is omitted, a default path will be used.
5686
5690
5687 Returns 0 if push was successful, 1 if nothing to push.
5691 Returns 0 if push was successful, 1 if nothing to push.
5688 """
5692 """
5689
5693
5690 if opts.get('bookmark'):
5694 if opts.get('bookmark'):
5691 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5695 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5692 for b in opts['bookmark']:
5696 for b in opts['bookmark']:
5693 # translate -B options to -r so changesets get pushed
5697 # translate -B options to -r so changesets get pushed
5694 if b in repo._bookmarks:
5698 if b in repo._bookmarks:
5695 opts.setdefault('rev', []).append(b)
5699 opts.setdefault('rev', []).append(b)
5696 else:
5700 else:
5697 # if we try to push a deleted bookmark, translate it to null
5701 # if we try to push a deleted bookmark, translate it to null
5698 # this lets simultaneous -r, -b options continue working
5702 # this lets simultaneous -r, -b options continue working
5699 opts.setdefault('rev', []).append("null")
5703 opts.setdefault('rev', []).append("null")
5700
5704
5701 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5705 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5702 if not path:
5706 if not path:
5703 raise error.Abort(_('default repository not configured!'),
5707 raise error.Abort(_('default repository not configured!'),
5704 hint=_('see the "path" section in "hg help config"'))
5708 hint=_('see the "path" section in "hg help config"'))
5705 dest = path.pushloc or path.loc
5709 dest = path.pushloc or path.loc
5706 branches = (path.branch, opts.get('branch') or [])
5710 branches = (path.branch, opts.get('branch') or [])
5707 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5711 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5708 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5712 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5709 other = hg.peer(repo, opts, dest)
5713 other = hg.peer(repo, opts, dest)
5710
5714
5711 if revs:
5715 if revs:
5712 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5716 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5713 if not revs:
5717 if not revs:
5714 raise error.Abort(_("specified revisions evaluate to an empty set"),
5718 raise error.Abort(_("specified revisions evaluate to an empty set"),
5715 hint=_("use different revision arguments"))
5719 hint=_("use different revision arguments"))
5716
5720
5717 repo._subtoppath = dest
5721 repo._subtoppath = dest
5718 try:
5722 try:
5719 # push subrepos depth-first for coherent ordering
5723 # push subrepos depth-first for coherent ordering
5720 c = repo['']
5724 c = repo['']
5721 subs = c.substate # only repos that are committed
5725 subs = c.substate # only repos that are committed
5722 for s in sorted(subs):
5726 for s in sorted(subs):
5723 result = c.sub(s).push(opts)
5727 result = c.sub(s).push(opts)
5724 if result == 0:
5728 if result == 0:
5725 return not result
5729 return not result
5726 finally:
5730 finally:
5727 del repo._subtoppath
5731 del repo._subtoppath
5728 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5732 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5729 newbranch=opts.get('new_branch'),
5733 newbranch=opts.get('new_branch'),
5730 bookmarks=opts.get('bookmark', ()),
5734 bookmarks=opts.get('bookmark', ()),
5731 opargs=opts.get('opargs'))
5735 opargs=opts.get('opargs'))
5732
5736
5733 result = not pushop.cgresult
5737 result = not pushop.cgresult
5734
5738
5735 if pushop.bkresult is not None:
5739 if pushop.bkresult is not None:
5736 if pushop.bkresult == 2:
5740 if pushop.bkresult == 2:
5737 result = 2
5741 result = 2
5738 elif not result and pushop.bkresult:
5742 elif not result and pushop.bkresult:
5739 result = 2
5743 result = 2
5740
5744
5741 return result
5745 return result
5742
5746
5743 @command('recover', [])
5747 @command('recover', [])
5744 def recover(ui, repo):
5748 def recover(ui, repo):
5745 """roll back an interrupted transaction
5749 """roll back an interrupted transaction
5746
5750
5747 Recover from an interrupted commit or pull.
5751 Recover from an interrupted commit or pull.
5748
5752
5749 This command tries to fix the repository status after an
5753 This command tries to fix the repository status after an
5750 interrupted operation. It should only be necessary when Mercurial
5754 interrupted operation. It should only be necessary when Mercurial
5751 suggests it.
5755 suggests it.
5752
5756
5753 Returns 0 if successful, 1 if nothing to recover or verify fails.
5757 Returns 0 if successful, 1 if nothing to recover or verify fails.
5754 """
5758 """
5755 if repo.recover():
5759 if repo.recover():
5756 return hg.verify(repo)
5760 return hg.verify(repo)
5757 return 1
5761 return 1
5758
5762
5759 @command('^remove|rm',
5763 @command('^remove|rm',
5760 [('A', 'after', None, _('record delete for missing files')),
5764 [('A', 'after', None, _('record delete for missing files')),
5761 ('f', 'force', None,
5765 ('f', 'force', None,
5762 _('remove (and delete) file even if added or modified')),
5766 _('remove (and delete) file even if added or modified')),
5763 ] + subrepoopts + walkopts,
5767 ] + subrepoopts + walkopts,
5764 _('[OPTION]... FILE...'),
5768 _('[OPTION]... FILE...'),
5765 inferrepo=True)
5769 inferrepo=True)
5766 def remove(ui, repo, *pats, **opts):
5770 def remove(ui, repo, *pats, **opts):
5767 """remove the specified files on the next commit
5771 """remove the specified files on the next commit
5768
5772
5769 Schedule the indicated files for removal from the current branch.
5773 Schedule the indicated files for removal from the current branch.
5770
5774
5771 This command schedules the files to be removed at the next commit.
5775 This command schedules the files to be removed at the next commit.
5772 To undo a remove before that, see :hg:`revert`. To undo added
5776 To undo a remove before that, see :hg:`revert`. To undo added
5773 files, see :hg:`forget`.
5777 files, see :hg:`forget`.
5774
5778
5775 .. container:: verbose
5779 .. container:: verbose
5776
5780
5777 -A/--after can be used to remove only files that have already
5781 -A/--after can be used to remove only files that have already
5778 been deleted, -f/--force can be used to force deletion, and -Af
5782 been deleted, -f/--force can be used to force deletion, and -Af
5779 can be used to remove files from the next revision without
5783 can be used to remove files from the next revision without
5780 deleting them from the working directory.
5784 deleting them from the working directory.
5781
5785
5782 The following table details the behavior of remove for different
5786 The following table details the behavior of remove for different
5783 file states (columns) and option combinations (rows). The file
5787 file states (columns) and option combinations (rows). The file
5784 states are Added [A], Clean [C], Modified [M] and Missing [!]
5788 states are Added [A], Clean [C], Modified [M] and Missing [!]
5785 (as reported by :hg:`status`). The actions are Warn, Remove
5789 (as reported by :hg:`status`). The actions are Warn, Remove
5786 (from branch) and Delete (from disk):
5790 (from branch) and Delete (from disk):
5787
5791
5788 ========= == == == ==
5792 ========= == == == ==
5789 opt/state A C M !
5793 opt/state A C M !
5790 ========= == == == ==
5794 ========= == == == ==
5791 none W RD W R
5795 none W RD W R
5792 -f R RD RD R
5796 -f R RD RD R
5793 -A W W W R
5797 -A W W W R
5794 -Af R R R R
5798 -Af R R R R
5795 ========= == == == ==
5799 ========= == == == ==
5796
5800
5797 .. note::
5801 .. note::
5798
5802
5799 :hg:`remove` never deletes files in Added [A] state from the
5803 :hg:`remove` never deletes files in Added [A] state from the
5800 working directory, not even if ``--force`` is specified.
5804 working directory, not even if ``--force`` is specified.
5801
5805
5802 Returns 0 on success, 1 if any warnings encountered.
5806 Returns 0 on success, 1 if any warnings encountered.
5803 """
5807 """
5804
5808
5805 after, force = opts.get('after'), opts.get('force')
5809 after, force = opts.get('after'), opts.get('force')
5806 if not pats and not after:
5810 if not pats and not after:
5807 raise error.Abort(_('no files specified'))
5811 raise error.Abort(_('no files specified'))
5808
5812
5809 m = scmutil.match(repo[None], pats, opts)
5813 m = scmutil.match(repo[None], pats, opts)
5810 subrepos = opts.get('subrepos')
5814 subrepos = opts.get('subrepos')
5811 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5815 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5812
5816
5813 @command('rename|move|mv',
5817 @command('rename|move|mv',
5814 [('A', 'after', None, _('record a rename that has already occurred')),
5818 [('A', 'after', None, _('record a rename that has already occurred')),
5815 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5819 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5816 ] + walkopts + dryrunopts,
5820 ] + walkopts + dryrunopts,
5817 _('[OPTION]... SOURCE... DEST'))
5821 _('[OPTION]... SOURCE... DEST'))
5818 def rename(ui, repo, *pats, **opts):
5822 def rename(ui, repo, *pats, **opts):
5819 """rename files; equivalent of copy + remove
5823 """rename files; equivalent of copy + remove
5820
5824
5821 Mark dest as copies of sources; mark sources for deletion. If dest
5825 Mark dest as copies of sources; mark sources for deletion. If dest
5822 is a directory, copies are put in that directory. If dest is a
5826 is a directory, copies are put in that directory. If dest is a
5823 file, there can only be one source.
5827 file, there can only be one source.
5824
5828
5825 By default, this command copies the contents of files as they
5829 By default, this command copies the contents of files as they
5826 exist in the working directory. If invoked with -A/--after, the
5830 exist in the working directory. If invoked with -A/--after, the
5827 operation is recorded, but no copying is performed.
5831 operation is recorded, but no copying is performed.
5828
5832
5829 This command takes effect at the next commit. To undo a rename
5833 This command takes effect at the next commit. To undo a rename
5830 before that, see :hg:`revert`.
5834 before that, see :hg:`revert`.
5831
5835
5832 Returns 0 on success, 1 if errors are encountered.
5836 Returns 0 on success, 1 if errors are encountered.
5833 """
5837 """
5834 with repo.wlock(False):
5838 with repo.wlock(False):
5835 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5839 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5836
5840
5837 @command('resolve',
5841 @command('resolve',
5838 [('a', 'all', None, _('select all unresolved files')),
5842 [('a', 'all', None, _('select all unresolved files')),
5839 ('l', 'list', None, _('list state of files needing merge')),
5843 ('l', 'list', None, _('list state of files needing merge')),
5840 ('m', 'mark', None, _('mark files as resolved')),
5844 ('m', 'mark', None, _('mark files as resolved')),
5841 ('u', 'unmark', None, _('mark files as unresolved')),
5845 ('u', 'unmark', None, _('mark files as unresolved')),
5842 ('n', 'no-status', None, _('hide status prefix'))]
5846 ('n', 'no-status', None, _('hide status prefix'))]
5843 + mergetoolopts + walkopts + formatteropts,
5847 + mergetoolopts + walkopts + formatteropts,
5844 _('[OPTION]... [FILE]...'),
5848 _('[OPTION]... [FILE]...'),
5845 inferrepo=True)
5849 inferrepo=True)
5846 def resolve(ui, repo, *pats, **opts):
5850 def resolve(ui, repo, *pats, **opts):
5847 """redo merges or set/view the merge status of files
5851 """redo merges or set/view the merge status of files
5848
5852
5849 Merges with unresolved conflicts are often the result of
5853 Merges with unresolved conflicts are often the result of
5850 non-interactive merging using the ``internal:merge`` configuration
5854 non-interactive merging using the ``internal:merge`` configuration
5851 setting, or a command-line merge tool like ``diff3``. The resolve
5855 setting, or a command-line merge tool like ``diff3``. The resolve
5852 command is used to manage the files involved in a merge, after
5856 command is used to manage the files involved in a merge, after
5853 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5857 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5854 working directory must have two parents). See :hg:`help
5858 working directory must have two parents). See :hg:`help
5855 merge-tools` for information on configuring merge tools.
5859 merge-tools` for information on configuring merge tools.
5856
5860
5857 The resolve command can be used in the following ways:
5861 The resolve command can be used in the following ways:
5858
5862
5859 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5863 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5860 files, discarding any previous merge attempts. Re-merging is not
5864 files, discarding any previous merge attempts. Re-merging is not
5861 performed for files already marked as resolved. Use ``--all/-a``
5865 performed for files already marked as resolved. Use ``--all/-a``
5862 to select all unresolved files. ``--tool`` can be used to specify
5866 to select all unresolved files. ``--tool`` can be used to specify
5863 the merge tool used for the given files. It overrides the HGMERGE
5867 the merge tool used for the given files. It overrides the HGMERGE
5864 environment variable and your configuration files. Previous file
5868 environment variable and your configuration files. Previous file
5865 contents are saved with a ``.orig`` suffix.
5869 contents are saved with a ``.orig`` suffix.
5866
5870
5867 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5871 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5868 (e.g. after having manually fixed-up the files). The default is
5872 (e.g. after having manually fixed-up the files). The default is
5869 to mark all unresolved files.
5873 to mark all unresolved files.
5870
5874
5871 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5875 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5872 default is to mark all resolved files.
5876 default is to mark all resolved files.
5873
5877
5874 - :hg:`resolve -l`: list files which had or still have conflicts.
5878 - :hg:`resolve -l`: list files which had or still have conflicts.
5875 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5879 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5876
5880
5877 .. note::
5881 .. note::
5878
5882
5879 Mercurial will not let you commit files with unresolved merge
5883 Mercurial will not let you commit files with unresolved merge
5880 conflicts. You must use :hg:`resolve -m ...` before you can
5884 conflicts. You must use :hg:`resolve -m ...` before you can
5881 commit after a conflicting merge.
5885 commit after a conflicting merge.
5882
5886
5883 Returns 0 on success, 1 if any files fail a resolve attempt.
5887 Returns 0 on success, 1 if any files fail a resolve attempt.
5884 """
5888 """
5885
5889
5886 all, mark, unmark, show, nostatus = \
5890 all, mark, unmark, show, nostatus = \
5887 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5891 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5888
5892
5889 if (show and (mark or unmark)) or (mark and unmark):
5893 if (show and (mark or unmark)) or (mark and unmark):
5890 raise error.Abort(_("too many options specified"))
5894 raise error.Abort(_("too many options specified"))
5891 if pats and all:
5895 if pats and all:
5892 raise error.Abort(_("can't specify --all and patterns"))
5896 raise error.Abort(_("can't specify --all and patterns"))
5893 if not (all or pats or show or mark or unmark):
5897 if not (all or pats or show or mark or unmark):
5894 raise error.Abort(_('no files or directories specified'),
5898 raise error.Abort(_('no files or directories specified'),
5895 hint=('use --all to re-merge all unresolved files'))
5899 hint=('use --all to re-merge all unresolved files'))
5896
5900
5897 if show:
5901 if show:
5898 fm = ui.formatter('resolve', opts)
5902 fm = ui.formatter('resolve', opts)
5899 ms = mergemod.mergestate.read(repo)
5903 ms = mergemod.mergestate.read(repo)
5900 m = scmutil.match(repo[None], pats, opts)
5904 m = scmutil.match(repo[None], pats, opts)
5901 for f in ms:
5905 for f in ms:
5902 if not m(f):
5906 if not m(f):
5903 continue
5907 continue
5904 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5908 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5905 'd': 'driverresolved'}[ms[f]]
5909 'd': 'driverresolved'}[ms[f]]
5906 fm.startitem()
5910 fm.startitem()
5907 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5911 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5908 fm.write('path', '%s\n', f, label=l)
5912 fm.write('path', '%s\n', f, label=l)
5909 fm.end()
5913 fm.end()
5910 return 0
5914 return 0
5911
5915
5912 with repo.wlock():
5916 with repo.wlock():
5913 ms = mergemod.mergestate.read(repo)
5917 ms = mergemod.mergestate.read(repo)
5914
5918
5915 if not (ms.active() or repo.dirstate.p2() != nullid):
5919 if not (ms.active() or repo.dirstate.p2() != nullid):
5916 raise error.Abort(
5920 raise error.Abort(
5917 _('resolve command not applicable when not merging'))
5921 _('resolve command not applicable when not merging'))
5918
5922
5919 wctx = repo[None]
5923 wctx = repo[None]
5920
5924
5921 if ms.mergedriver and ms.mdstate() == 'u':
5925 if ms.mergedriver and ms.mdstate() == 'u':
5922 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5926 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5923 ms.commit()
5927 ms.commit()
5924 # allow mark and unmark to go through
5928 # allow mark and unmark to go through
5925 if not mark and not unmark and not proceed:
5929 if not mark and not unmark and not proceed:
5926 return 1
5930 return 1
5927
5931
5928 m = scmutil.match(wctx, pats, opts)
5932 m = scmutil.match(wctx, pats, opts)
5929 ret = 0
5933 ret = 0
5930 didwork = False
5934 didwork = False
5931 runconclude = False
5935 runconclude = False
5932
5936
5933 tocomplete = []
5937 tocomplete = []
5934 for f in ms:
5938 for f in ms:
5935 if not m(f):
5939 if not m(f):
5936 continue
5940 continue
5937
5941
5938 didwork = True
5942 didwork = True
5939
5943
5940 # don't let driver-resolved files be marked, and run the conclude
5944 # don't let driver-resolved files be marked, and run the conclude
5941 # step if asked to resolve
5945 # step if asked to resolve
5942 if ms[f] == "d":
5946 if ms[f] == "d":
5943 exact = m.exact(f)
5947 exact = m.exact(f)
5944 if mark:
5948 if mark:
5945 if exact:
5949 if exact:
5946 ui.warn(_('not marking %s as it is driver-resolved\n')
5950 ui.warn(_('not marking %s as it is driver-resolved\n')
5947 % f)
5951 % f)
5948 elif unmark:
5952 elif unmark:
5949 if exact:
5953 if exact:
5950 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5954 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5951 % f)
5955 % f)
5952 else:
5956 else:
5953 runconclude = True
5957 runconclude = True
5954 continue
5958 continue
5955
5959
5956 if mark:
5960 if mark:
5957 ms.mark(f, "r")
5961 ms.mark(f, "r")
5958 elif unmark:
5962 elif unmark:
5959 ms.mark(f, "u")
5963 ms.mark(f, "u")
5960 else:
5964 else:
5961 # backup pre-resolve (merge uses .orig for its own purposes)
5965 # backup pre-resolve (merge uses .orig for its own purposes)
5962 a = repo.wjoin(f)
5966 a = repo.wjoin(f)
5963 try:
5967 try:
5964 util.copyfile(a, a + ".resolve")
5968 util.copyfile(a, a + ".resolve")
5965 except (IOError, OSError) as inst:
5969 except (IOError, OSError) as inst:
5966 if inst.errno != errno.ENOENT:
5970 if inst.errno != errno.ENOENT:
5967 raise
5971 raise
5968
5972
5969 try:
5973 try:
5970 # preresolve file
5974 # preresolve file
5971 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5975 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5972 'resolve')
5976 'resolve')
5973 complete, r = ms.preresolve(f, wctx)
5977 complete, r = ms.preresolve(f, wctx)
5974 if not complete:
5978 if not complete:
5975 tocomplete.append(f)
5979 tocomplete.append(f)
5976 elif r:
5980 elif r:
5977 ret = 1
5981 ret = 1
5978 finally:
5982 finally:
5979 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5983 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5980 ms.commit()
5984 ms.commit()
5981
5985
5982 # replace filemerge's .orig file with our resolve file, but only
5986 # replace filemerge's .orig file with our resolve file, but only
5983 # for merges that are complete
5987 # for merges that are complete
5984 if complete:
5988 if complete:
5985 try:
5989 try:
5986 util.rename(a + ".resolve",
5990 util.rename(a + ".resolve",
5987 scmutil.origpath(ui, repo, a))
5991 scmutil.origpath(ui, repo, a))
5988 except OSError as inst:
5992 except OSError as inst:
5989 if inst.errno != errno.ENOENT:
5993 if inst.errno != errno.ENOENT:
5990 raise
5994 raise
5991
5995
5992 for f in tocomplete:
5996 for f in tocomplete:
5993 try:
5997 try:
5994 # resolve file
5998 # resolve file
5995 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5999 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5996 'resolve')
6000 'resolve')
5997 r = ms.resolve(f, wctx)
6001 r = ms.resolve(f, wctx)
5998 if r:
6002 if r:
5999 ret = 1
6003 ret = 1
6000 finally:
6004 finally:
6001 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6005 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6002 ms.commit()
6006 ms.commit()
6003
6007
6004 # replace filemerge's .orig file with our resolve file
6008 # replace filemerge's .orig file with our resolve file
6005 a = repo.wjoin(f)
6009 a = repo.wjoin(f)
6006 try:
6010 try:
6007 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6011 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6008 except OSError as inst:
6012 except OSError as inst:
6009 if inst.errno != errno.ENOENT:
6013 if inst.errno != errno.ENOENT:
6010 raise
6014 raise
6011
6015
6012 ms.commit()
6016 ms.commit()
6013 ms.recordactions()
6017 ms.recordactions()
6014
6018
6015 if not didwork and pats:
6019 if not didwork and pats:
6016 ui.warn(_("arguments do not match paths that need resolving\n"))
6020 ui.warn(_("arguments do not match paths that need resolving\n"))
6017 elif ms.mergedriver and ms.mdstate() != 's':
6021 elif ms.mergedriver and ms.mdstate() != 's':
6018 # run conclude step when either a driver-resolved file is requested
6022 # run conclude step when either a driver-resolved file is requested
6019 # or there are no driver-resolved files
6023 # or there are no driver-resolved files
6020 # we can't use 'ret' to determine whether any files are unresolved
6024 # we can't use 'ret' to determine whether any files are unresolved
6021 # because we might not have tried to resolve some
6025 # because we might not have tried to resolve some
6022 if ((runconclude or not list(ms.driverresolved()))
6026 if ((runconclude or not list(ms.driverresolved()))
6023 and not list(ms.unresolved())):
6027 and not list(ms.unresolved())):
6024 proceed = mergemod.driverconclude(repo, ms, wctx)
6028 proceed = mergemod.driverconclude(repo, ms, wctx)
6025 ms.commit()
6029 ms.commit()
6026 if not proceed:
6030 if not proceed:
6027 return 1
6031 return 1
6028
6032
6029 # Nudge users into finishing an unfinished operation
6033 # Nudge users into finishing an unfinished operation
6030 unresolvedf = list(ms.unresolved())
6034 unresolvedf = list(ms.unresolved())
6031 driverresolvedf = list(ms.driverresolved())
6035 driverresolvedf = list(ms.driverresolved())
6032 if not unresolvedf and not driverresolvedf:
6036 if not unresolvedf and not driverresolvedf:
6033 ui.status(_('(no more unresolved files)\n'))
6037 ui.status(_('(no more unresolved files)\n'))
6034 cmdutil.checkafterresolved(repo)
6038 cmdutil.checkafterresolved(repo)
6035 elif not unresolvedf:
6039 elif not unresolvedf:
6036 ui.status(_('(no more unresolved files -- '
6040 ui.status(_('(no more unresolved files -- '
6037 'run "hg resolve --all" to conclude)\n'))
6041 'run "hg resolve --all" to conclude)\n'))
6038
6042
6039 return ret
6043 return ret
6040
6044
6041 @command('revert',
6045 @command('revert',
6042 [('a', 'all', None, _('revert all changes when no arguments given')),
6046 [('a', 'all', None, _('revert all changes when no arguments given')),
6043 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6047 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6044 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6048 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6045 ('C', 'no-backup', None, _('do not save backup copies of files')),
6049 ('C', 'no-backup', None, _('do not save backup copies of files')),
6046 ('i', 'interactive', None,
6050 ('i', 'interactive', None,
6047 _('interactively select the changes (EXPERIMENTAL)')),
6051 _('interactively select the changes (EXPERIMENTAL)')),
6048 ] + walkopts + dryrunopts,
6052 ] + walkopts + dryrunopts,
6049 _('[OPTION]... [-r REV] [NAME]...'))
6053 _('[OPTION]... [-r REV] [NAME]...'))
6050 def revert(ui, repo, *pats, **opts):
6054 def revert(ui, repo, *pats, **opts):
6051 """restore files to their checkout state
6055 """restore files to their checkout state
6052
6056
6053 .. note::
6057 .. note::
6054
6058
6055 To check out earlier revisions, you should use :hg:`update REV`.
6059 To check out earlier revisions, you should use :hg:`update REV`.
6056 To cancel an uncommitted merge (and lose your changes),
6060 To cancel an uncommitted merge (and lose your changes),
6057 use :hg:`update --clean .`.
6061 use :hg:`update --clean .`.
6058
6062
6059 With no revision specified, revert the specified files or directories
6063 With no revision specified, revert the specified files or directories
6060 to the contents they had in the parent of the working directory.
6064 to the contents they had in the parent of the working directory.
6061 This restores the contents of files to an unmodified
6065 This restores the contents of files to an unmodified
6062 state and unschedules adds, removes, copies, and renames. If the
6066 state and unschedules adds, removes, copies, and renames. If the
6063 working directory has two parents, you must explicitly specify a
6067 working directory has two parents, you must explicitly specify a
6064 revision.
6068 revision.
6065
6069
6066 Using the -r/--rev or -d/--date options, revert the given files or
6070 Using the -r/--rev or -d/--date options, revert the given files or
6067 directories to their states as of a specific revision. Because
6071 directories to their states as of a specific revision. Because
6068 revert does not change the working directory parents, this will
6072 revert does not change the working directory parents, this will
6069 cause these files to appear modified. This can be helpful to "back
6073 cause these files to appear modified. This can be helpful to "back
6070 out" some or all of an earlier change. See :hg:`backout` for a
6074 out" some or all of an earlier change. See :hg:`backout` for a
6071 related method.
6075 related method.
6072
6076
6073 Modified files are saved with a .orig suffix before reverting.
6077 Modified files are saved with a .orig suffix before reverting.
6074 To disable these backups, use --no-backup.
6078 To disable these backups, use --no-backup.
6075
6079
6076 See :hg:`help dates` for a list of formats valid for -d/--date.
6080 See :hg:`help dates` for a list of formats valid for -d/--date.
6077
6081
6078 See :hg:`help backout` for a way to reverse the effect of an
6082 See :hg:`help backout` for a way to reverse the effect of an
6079 earlier changeset.
6083 earlier changeset.
6080
6084
6081 Returns 0 on success.
6085 Returns 0 on success.
6082 """
6086 """
6083
6087
6084 if opts.get("date"):
6088 if opts.get("date"):
6085 if opts.get("rev"):
6089 if opts.get("rev"):
6086 raise error.Abort(_("you can't specify a revision and a date"))
6090 raise error.Abort(_("you can't specify a revision and a date"))
6087 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6091 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6088
6092
6089 parent, p2 = repo.dirstate.parents()
6093 parent, p2 = repo.dirstate.parents()
6090 if not opts.get('rev') and p2 != nullid:
6094 if not opts.get('rev') and p2 != nullid:
6091 # revert after merge is a trap for new users (issue2915)
6095 # revert after merge is a trap for new users (issue2915)
6092 raise error.Abort(_('uncommitted merge with no revision specified'),
6096 raise error.Abort(_('uncommitted merge with no revision specified'),
6093 hint=_('use "hg update" or see "hg help revert"'))
6097 hint=_('use "hg update" or see "hg help revert"'))
6094
6098
6095 ctx = scmutil.revsingle(repo, opts.get('rev'))
6099 ctx = scmutil.revsingle(repo, opts.get('rev'))
6096
6100
6097 if (not (pats or opts.get('include') or opts.get('exclude') or
6101 if (not (pats or opts.get('include') or opts.get('exclude') or
6098 opts.get('all') or opts.get('interactive'))):
6102 opts.get('all') or opts.get('interactive'))):
6099 msg = _("no files or directories specified")
6103 msg = _("no files or directories specified")
6100 if p2 != nullid:
6104 if p2 != nullid:
6101 hint = _("uncommitted merge, use --all to discard all changes,"
6105 hint = _("uncommitted merge, use --all to discard all changes,"
6102 " or 'hg update -C .' to abort the merge")
6106 " or 'hg update -C .' to abort the merge")
6103 raise error.Abort(msg, hint=hint)
6107 raise error.Abort(msg, hint=hint)
6104 dirty = any(repo.status())
6108 dirty = any(repo.status())
6105 node = ctx.node()
6109 node = ctx.node()
6106 if node != parent:
6110 if node != parent:
6107 if dirty:
6111 if dirty:
6108 hint = _("uncommitted changes, use --all to discard all"
6112 hint = _("uncommitted changes, use --all to discard all"
6109 " changes, or 'hg update %s' to update") % ctx.rev()
6113 " changes, or 'hg update %s' to update") % ctx.rev()
6110 else:
6114 else:
6111 hint = _("use --all to revert all files,"
6115 hint = _("use --all to revert all files,"
6112 " or 'hg update %s' to update") % ctx.rev()
6116 " or 'hg update %s' to update") % ctx.rev()
6113 elif dirty:
6117 elif dirty:
6114 hint = _("uncommitted changes, use --all to discard all changes")
6118 hint = _("uncommitted changes, use --all to discard all changes")
6115 else:
6119 else:
6116 hint = _("use --all to revert all files")
6120 hint = _("use --all to revert all files")
6117 raise error.Abort(msg, hint=hint)
6121 raise error.Abort(msg, hint=hint)
6118
6122
6119 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6123 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6120
6124
6121 @command('rollback', dryrunopts +
6125 @command('rollback', dryrunopts +
6122 [('f', 'force', False, _('ignore safety measures'))])
6126 [('f', 'force', False, _('ignore safety measures'))])
6123 def rollback(ui, repo, **opts):
6127 def rollback(ui, repo, **opts):
6124 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6128 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6125
6129
6126 Please use :hg:`commit --amend` instead of rollback to correct
6130 Please use :hg:`commit --amend` instead of rollback to correct
6127 mistakes in the last commit.
6131 mistakes in the last commit.
6128
6132
6129 This command should be used with care. There is only one level of
6133 This command should be used with care. There is only one level of
6130 rollback, and there is no way to undo a rollback. It will also
6134 rollback, and there is no way to undo a rollback. It will also
6131 restore the dirstate at the time of the last transaction, losing
6135 restore the dirstate at the time of the last transaction, losing
6132 any dirstate changes since that time. This command does not alter
6136 any dirstate changes since that time. This command does not alter
6133 the working directory.
6137 the working directory.
6134
6138
6135 Transactions are used to encapsulate the effects of all commands
6139 Transactions are used to encapsulate the effects of all commands
6136 that create new changesets or propagate existing changesets into a
6140 that create new changesets or propagate existing changesets into a
6137 repository.
6141 repository.
6138
6142
6139 .. container:: verbose
6143 .. container:: verbose
6140
6144
6141 For example, the following commands are transactional, and their
6145 For example, the following commands are transactional, and their
6142 effects can be rolled back:
6146 effects can be rolled back:
6143
6147
6144 - commit
6148 - commit
6145 - import
6149 - import
6146 - pull
6150 - pull
6147 - push (with this repository as the destination)
6151 - push (with this repository as the destination)
6148 - unbundle
6152 - unbundle
6149
6153
6150 To avoid permanent data loss, rollback will refuse to rollback a
6154 To avoid permanent data loss, rollback will refuse to rollback a
6151 commit transaction if it isn't checked out. Use --force to
6155 commit transaction if it isn't checked out. Use --force to
6152 override this protection.
6156 override this protection.
6153
6157
6154 This command is not intended for use on public repositories. Once
6158 This command is not intended for use on public repositories. Once
6155 changes are visible for pull by other users, rolling a transaction
6159 changes are visible for pull by other users, rolling a transaction
6156 back locally is ineffective (someone else may already have pulled
6160 back locally is ineffective (someone else may already have pulled
6157 the changes). Furthermore, a race is possible with readers of the
6161 the changes). Furthermore, a race is possible with readers of the
6158 repository; for example an in-progress pull from the repository
6162 repository; for example an in-progress pull from the repository
6159 may fail if a rollback is performed.
6163 may fail if a rollback is performed.
6160
6164
6161 Returns 0 on success, 1 if no rollback data is available.
6165 Returns 0 on success, 1 if no rollback data is available.
6162 """
6166 """
6163 return repo.rollback(dryrun=opts.get('dry_run'),
6167 return repo.rollback(dryrun=opts.get('dry_run'),
6164 force=opts.get('force'))
6168 force=opts.get('force'))
6165
6169
6166 @command('root', [])
6170 @command('root', [])
6167 def root(ui, repo):
6171 def root(ui, repo):
6168 """print the root (top) of the current working directory
6172 """print the root (top) of the current working directory
6169
6173
6170 Print the root directory of the current repository.
6174 Print the root directory of the current repository.
6171
6175
6172 Returns 0 on success.
6176 Returns 0 on success.
6173 """
6177 """
6174 ui.write(repo.root + "\n")
6178 ui.write(repo.root + "\n")
6175
6179
6176 @command('^serve',
6180 @command('^serve',
6177 [('A', 'accesslog', '', _('name of access log file to write to'),
6181 [('A', 'accesslog', '', _('name of access log file to write to'),
6178 _('FILE')),
6182 _('FILE')),
6179 ('d', 'daemon', None, _('run server in background')),
6183 ('d', 'daemon', None, _('run server in background')),
6180 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6184 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6181 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6185 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6182 # use string type, then we can check if something was passed
6186 # use string type, then we can check if something was passed
6183 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6187 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6184 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6188 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6185 _('ADDR')),
6189 _('ADDR')),
6186 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6190 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6187 _('PREFIX')),
6191 _('PREFIX')),
6188 ('n', 'name', '',
6192 ('n', 'name', '',
6189 _('name to show in web pages (default: working directory)'), _('NAME')),
6193 _('name to show in web pages (default: working directory)'), _('NAME')),
6190 ('', 'web-conf', '',
6194 ('', 'web-conf', '',
6191 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6195 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6192 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6196 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6193 _('FILE')),
6197 _('FILE')),
6194 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6198 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6195 ('', 'stdio', None, _('for remote clients')),
6199 ('', 'stdio', None, _('for remote clients')),
6196 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6200 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6197 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6201 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6198 ('', 'style', '', _('template style to use'), _('STYLE')),
6202 ('', 'style', '', _('template style to use'), _('STYLE')),
6199 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6203 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6200 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6204 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6201 _('[OPTION]...'),
6205 _('[OPTION]...'),
6202 optionalrepo=True)
6206 optionalrepo=True)
6203 def serve(ui, repo, **opts):
6207 def serve(ui, repo, **opts):
6204 """start stand-alone webserver
6208 """start stand-alone webserver
6205
6209
6206 Start a local HTTP repository browser and pull server. You can use
6210 Start a local HTTP repository browser and pull server. You can use
6207 this for ad-hoc sharing and browsing of repositories. It is
6211 this for ad-hoc sharing and browsing of repositories. It is
6208 recommended to use a real web server to serve a repository for
6212 recommended to use a real web server to serve a repository for
6209 longer periods of time.
6213 longer periods of time.
6210
6214
6211 Please note that the server does not implement access control.
6215 Please note that the server does not implement access control.
6212 This means that, by default, anybody can read from the server and
6216 This means that, by default, anybody can read from the server and
6213 nobody can write to it by default. Set the ``web.allow_push``
6217 nobody can write to it by default. Set the ``web.allow_push``
6214 option to ``*`` to allow everybody to push to the server. You
6218 option to ``*`` to allow everybody to push to the server. You
6215 should use a real web server if you need to authenticate users.
6219 should use a real web server if you need to authenticate users.
6216
6220
6217 By default, the server logs accesses to stdout and errors to
6221 By default, the server logs accesses to stdout and errors to
6218 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6222 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6219 files.
6223 files.
6220
6224
6221 To have the server choose a free port number to listen on, specify
6225 To have the server choose a free port number to listen on, specify
6222 a port number of 0; in this case, the server will print the port
6226 a port number of 0; in this case, the server will print the port
6223 number it uses.
6227 number it uses.
6224
6228
6225 Returns 0 on success.
6229 Returns 0 on success.
6226 """
6230 """
6227
6231
6228 if opts["stdio"] and opts["cmdserver"]:
6232 if opts["stdio"] and opts["cmdserver"]:
6229 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6233 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6230
6234
6231 if opts["stdio"]:
6235 if opts["stdio"]:
6232 if repo is None:
6236 if repo is None:
6233 raise error.RepoError(_("there is no Mercurial repository here"
6237 raise error.RepoError(_("there is no Mercurial repository here"
6234 " (.hg not found)"))
6238 " (.hg not found)"))
6235 s = sshserver.sshserver(ui, repo)
6239 s = sshserver.sshserver(ui, repo)
6236 s.serve_forever()
6240 s.serve_forever()
6237
6241
6238 if opts["cmdserver"]:
6242 if opts["cmdserver"]:
6239 service = commandserver.createservice(ui, repo, opts)
6243 service = commandserver.createservice(ui, repo, opts)
6240 else:
6244 else:
6241 service = hgweb.createservice(ui, repo, opts)
6245 service = hgweb.createservice(ui, repo, opts)
6242 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6246 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6243
6247
6244 @command('^status|st',
6248 @command('^status|st',
6245 [('A', 'all', None, _('show status of all files')),
6249 [('A', 'all', None, _('show status of all files')),
6246 ('m', 'modified', None, _('show only modified files')),
6250 ('m', 'modified', None, _('show only modified files')),
6247 ('a', 'added', None, _('show only added files')),
6251 ('a', 'added', None, _('show only added files')),
6248 ('r', 'removed', None, _('show only removed files')),
6252 ('r', 'removed', None, _('show only removed files')),
6249 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6253 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6250 ('c', 'clean', None, _('show only files without changes')),
6254 ('c', 'clean', None, _('show only files without changes')),
6251 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6255 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6252 ('i', 'ignored', None, _('show only ignored files')),
6256 ('i', 'ignored', None, _('show only ignored files')),
6253 ('n', 'no-status', None, _('hide status prefix')),
6257 ('n', 'no-status', None, _('hide status prefix')),
6254 ('C', 'copies', None, _('show source of copied files')),
6258 ('C', 'copies', None, _('show source of copied files')),
6255 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6259 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6256 ('', 'rev', [], _('show difference from revision'), _('REV')),
6260 ('', 'rev', [], _('show difference from revision'), _('REV')),
6257 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6261 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6258 ] + walkopts + subrepoopts + formatteropts,
6262 ] + walkopts + subrepoopts + formatteropts,
6259 _('[OPTION]... [FILE]...'),
6263 _('[OPTION]... [FILE]...'),
6260 inferrepo=True)
6264 inferrepo=True)
6261 def status(ui, repo, *pats, **opts):
6265 def status(ui, repo, *pats, **opts):
6262 """show changed files in the working directory
6266 """show changed files in the working directory
6263
6267
6264 Show status of files in the repository. If names are given, only
6268 Show status of files in the repository. If names are given, only
6265 files that match are shown. Files that are clean or ignored or
6269 files that match are shown. Files that are clean or ignored or
6266 the source of a copy/move operation, are not listed unless
6270 the source of a copy/move operation, are not listed unless
6267 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6271 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6268 Unless options described with "show only ..." are given, the
6272 Unless options described with "show only ..." are given, the
6269 options -mardu are used.
6273 options -mardu are used.
6270
6274
6271 Option -q/--quiet hides untracked (unknown and ignored) files
6275 Option -q/--quiet hides untracked (unknown and ignored) files
6272 unless explicitly requested with -u/--unknown or -i/--ignored.
6276 unless explicitly requested with -u/--unknown or -i/--ignored.
6273
6277
6274 .. note::
6278 .. note::
6275
6279
6276 :hg:`status` may appear to disagree with diff if permissions have
6280 :hg:`status` may appear to disagree with diff if permissions have
6277 changed or a merge has occurred. The standard diff format does
6281 changed or a merge has occurred. The standard diff format does
6278 not report permission changes and diff only reports changes
6282 not report permission changes and diff only reports changes
6279 relative to one merge parent.
6283 relative to one merge parent.
6280
6284
6281 If one revision is given, it is used as the base revision.
6285 If one revision is given, it is used as the base revision.
6282 If two revisions are given, the differences between them are
6286 If two revisions are given, the differences between them are
6283 shown. The --change option can also be used as a shortcut to list
6287 shown. The --change option can also be used as a shortcut to list
6284 the changed files of a revision from its first parent.
6288 the changed files of a revision from its first parent.
6285
6289
6286 The codes used to show the status of files are::
6290 The codes used to show the status of files are::
6287
6291
6288 M = modified
6292 M = modified
6289 A = added
6293 A = added
6290 R = removed
6294 R = removed
6291 C = clean
6295 C = clean
6292 ! = missing (deleted by non-hg command, but still tracked)
6296 ! = missing (deleted by non-hg command, but still tracked)
6293 ? = not tracked
6297 ? = not tracked
6294 I = ignored
6298 I = ignored
6295 = origin of the previous file (with --copies)
6299 = origin of the previous file (with --copies)
6296
6300
6297 .. container:: verbose
6301 .. container:: verbose
6298
6302
6299 Examples:
6303 Examples:
6300
6304
6301 - show changes in the working directory relative to a
6305 - show changes in the working directory relative to a
6302 changeset::
6306 changeset::
6303
6307
6304 hg status --rev 9353
6308 hg status --rev 9353
6305
6309
6306 - show changes in the working directory relative to the
6310 - show changes in the working directory relative to the
6307 current directory (see :hg:`help patterns` for more information)::
6311 current directory (see :hg:`help patterns` for more information)::
6308
6312
6309 hg status re:
6313 hg status re:
6310
6314
6311 - show all changes including copies in an existing changeset::
6315 - show all changes including copies in an existing changeset::
6312
6316
6313 hg status --copies --change 9353
6317 hg status --copies --change 9353
6314
6318
6315 - get a NUL separated list of added files, suitable for xargs::
6319 - get a NUL separated list of added files, suitable for xargs::
6316
6320
6317 hg status -an0
6321 hg status -an0
6318
6322
6319 Returns 0 on success.
6323 Returns 0 on success.
6320 """
6324 """
6321
6325
6322 revs = opts.get('rev')
6326 revs = opts.get('rev')
6323 change = opts.get('change')
6327 change = opts.get('change')
6324
6328
6325 if revs and change:
6329 if revs and change:
6326 msg = _('cannot specify --rev and --change at the same time')
6330 msg = _('cannot specify --rev and --change at the same time')
6327 raise error.Abort(msg)
6331 raise error.Abort(msg)
6328 elif change:
6332 elif change:
6329 node2 = scmutil.revsingle(repo, change, None).node()
6333 node2 = scmutil.revsingle(repo, change, None).node()
6330 node1 = repo[node2].p1().node()
6334 node1 = repo[node2].p1().node()
6331 else:
6335 else:
6332 node1, node2 = scmutil.revpair(repo, revs)
6336 node1, node2 = scmutil.revpair(repo, revs)
6333
6337
6334 if pats:
6338 if pats:
6335 cwd = repo.getcwd()
6339 cwd = repo.getcwd()
6336 else:
6340 else:
6337 cwd = ''
6341 cwd = ''
6338
6342
6339 if opts.get('print0'):
6343 if opts.get('print0'):
6340 end = '\0'
6344 end = '\0'
6341 else:
6345 else:
6342 end = '\n'
6346 end = '\n'
6343 copy = {}
6347 copy = {}
6344 states = 'modified added removed deleted unknown ignored clean'.split()
6348 states = 'modified added removed deleted unknown ignored clean'.split()
6345 show = [k for k in states if opts.get(k)]
6349 show = [k for k in states if opts.get(k)]
6346 if opts.get('all'):
6350 if opts.get('all'):
6347 show += ui.quiet and (states[:4] + ['clean']) or states
6351 show += ui.quiet and (states[:4] + ['clean']) or states
6348 if not show:
6352 if not show:
6349 if ui.quiet:
6353 if ui.quiet:
6350 show = states[:4]
6354 show = states[:4]
6351 else:
6355 else:
6352 show = states[:5]
6356 show = states[:5]
6353
6357
6354 m = scmutil.match(repo[node2], pats, opts)
6358 m = scmutil.match(repo[node2], pats, opts)
6355 stat = repo.status(node1, node2, m,
6359 stat = repo.status(node1, node2, m,
6356 'ignored' in show, 'clean' in show, 'unknown' in show,
6360 'ignored' in show, 'clean' in show, 'unknown' in show,
6357 opts.get('subrepos'))
6361 opts.get('subrepos'))
6358 changestates = zip(states, 'MAR!?IC', stat)
6362 changestates = zip(states, 'MAR!?IC', stat)
6359
6363
6360 if (opts.get('all') or opts.get('copies')
6364 if (opts.get('all') or opts.get('copies')
6361 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6365 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6362 copy = copies.pathcopies(repo[node1], repo[node2], m)
6366 copy = copies.pathcopies(repo[node1], repo[node2], m)
6363
6367
6364 fm = ui.formatter('status', opts)
6368 fm = ui.formatter('status', opts)
6365 fmt = '%s' + end
6369 fmt = '%s' + end
6366 showchar = not opts.get('no_status')
6370 showchar = not opts.get('no_status')
6367
6371
6368 for state, char, files in changestates:
6372 for state, char, files in changestates:
6369 if state in show:
6373 if state in show:
6370 label = 'status.' + state
6374 label = 'status.' + state
6371 for f in files:
6375 for f in files:
6372 fm.startitem()
6376 fm.startitem()
6373 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6377 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6374 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6378 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6375 if f in copy:
6379 if f in copy:
6376 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6380 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6377 label='status.copied')
6381 label='status.copied')
6378 fm.end()
6382 fm.end()
6379
6383
6380 @command('^summary|sum',
6384 @command('^summary|sum',
6381 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6385 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6382 def summary(ui, repo, **opts):
6386 def summary(ui, repo, **opts):
6383 """summarize working directory state
6387 """summarize working directory state
6384
6388
6385 This generates a brief summary of the working directory state,
6389 This generates a brief summary of the working directory state,
6386 including parents, branch, commit status, phase and available updates.
6390 including parents, branch, commit status, phase and available updates.
6387
6391
6388 With the --remote option, this will check the default paths for
6392 With the --remote option, this will check the default paths for
6389 incoming and outgoing changes. This can be time-consuming.
6393 incoming and outgoing changes. This can be time-consuming.
6390
6394
6391 Returns 0 on success.
6395 Returns 0 on success.
6392 """
6396 """
6393
6397
6394 ctx = repo[None]
6398 ctx = repo[None]
6395 parents = ctx.parents()
6399 parents = ctx.parents()
6396 pnode = parents[0].node()
6400 pnode = parents[0].node()
6397 marks = []
6401 marks = []
6398
6402
6399 for p in parents:
6403 for p in parents:
6400 # label with log.changeset (instead of log.parent) since this
6404 # label with log.changeset (instead of log.parent) since this
6401 # shows a working directory parent *changeset*:
6405 # shows a working directory parent *changeset*:
6402 # i18n: column positioning for "hg summary"
6406 # i18n: column positioning for "hg summary"
6403 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6407 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6404 label='log.changeset changeset.%s' % p.phasestr())
6408 label='log.changeset changeset.%s' % p.phasestr())
6405 ui.write(' '.join(p.tags()), label='log.tag')
6409 ui.write(' '.join(p.tags()), label='log.tag')
6406 if p.bookmarks():
6410 if p.bookmarks():
6407 marks.extend(p.bookmarks())
6411 marks.extend(p.bookmarks())
6408 if p.rev() == -1:
6412 if p.rev() == -1:
6409 if not len(repo):
6413 if not len(repo):
6410 ui.write(_(' (empty repository)'))
6414 ui.write(_(' (empty repository)'))
6411 else:
6415 else:
6412 ui.write(_(' (no revision checked out)'))
6416 ui.write(_(' (no revision checked out)'))
6413 ui.write('\n')
6417 ui.write('\n')
6414 if p.description():
6418 if p.description():
6415 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6419 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6416 label='log.summary')
6420 label='log.summary')
6417
6421
6418 branch = ctx.branch()
6422 branch = ctx.branch()
6419 bheads = repo.branchheads(branch)
6423 bheads = repo.branchheads(branch)
6420 # i18n: column positioning for "hg summary"
6424 # i18n: column positioning for "hg summary"
6421 m = _('branch: %s\n') % branch
6425 m = _('branch: %s\n') % branch
6422 if branch != 'default':
6426 if branch != 'default':
6423 ui.write(m, label='log.branch')
6427 ui.write(m, label='log.branch')
6424 else:
6428 else:
6425 ui.status(m, label='log.branch')
6429 ui.status(m, label='log.branch')
6426
6430
6427 if marks:
6431 if marks:
6428 active = repo._activebookmark
6432 active = repo._activebookmark
6429 # i18n: column positioning for "hg summary"
6433 # i18n: column positioning for "hg summary"
6430 ui.write(_('bookmarks:'), label='log.bookmark')
6434 ui.write(_('bookmarks:'), label='log.bookmark')
6431 if active is not None:
6435 if active is not None:
6432 if active in marks:
6436 if active in marks:
6433 ui.write(' *' + active, label=activebookmarklabel)
6437 ui.write(' *' + active, label=activebookmarklabel)
6434 marks.remove(active)
6438 marks.remove(active)
6435 else:
6439 else:
6436 ui.write(' [%s]' % active, label=activebookmarklabel)
6440 ui.write(' [%s]' % active, label=activebookmarklabel)
6437 for m in marks:
6441 for m in marks:
6438 ui.write(' ' + m, label='log.bookmark')
6442 ui.write(' ' + m, label='log.bookmark')
6439 ui.write('\n', label='log.bookmark')
6443 ui.write('\n', label='log.bookmark')
6440
6444
6441 status = repo.status(unknown=True)
6445 status = repo.status(unknown=True)
6442
6446
6443 c = repo.dirstate.copies()
6447 c = repo.dirstate.copies()
6444 copied, renamed = [], []
6448 copied, renamed = [], []
6445 for d, s in c.iteritems():
6449 for d, s in c.iteritems():
6446 if s in status.removed:
6450 if s in status.removed:
6447 status.removed.remove(s)
6451 status.removed.remove(s)
6448 renamed.append(d)
6452 renamed.append(d)
6449 else:
6453 else:
6450 copied.append(d)
6454 copied.append(d)
6451 if d in status.added:
6455 if d in status.added:
6452 status.added.remove(d)
6456 status.added.remove(d)
6453
6457
6454 try:
6458 try:
6455 ms = mergemod.mergestate.read(repo)
6459 ms = mergemod.mergestate.read(repo)
6456 except error.UnsupportedMergeRecords as e:
6460 except error.UnsupportedMergeRecords as e:
6457 s = ' '.join(e.recordtypes)
6461 s = ' '.join(e.recordtypes)
6458 ui.warn(
6462 ui.warn(
6459 _('warning: merge state has unsupported record types: %s\n') % s)
6463 _('warning: merge state has unsupported record types: %s\n') % s)
6460 unresolved = 0
6464 unresolved = 0
6461 else:
6465 else:
6462 unresolved = [f for f in ms if ms[f] == 'u']
6466 unresolved = [f for f in ms if ms[f] == 'u']
6463
6467
6464 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6468 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6465
6469
6466 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6470 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6467 (ui.label(_('%d added'), 'status.added'), status.added),
6471 (ui.label(_('%d added'), 'status.added'), status.added),
6468 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6472 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6469 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6473 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6470 (ui.label(_('%d copied'), 'status.copied'), copied),
6474 (ui.label(_('%d copied'), 'status.copied'), copied),
6471 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6475 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6472 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6476 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6473 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6477 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6474 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6478 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6475 t = []
6479 t = []
6476 for l, s in labels:
6480 for l, s in labels:
6477 if s:
6481 if s:
6478 t.append(l % len(s))
6482 t.append(l % len(s))
6479
6483
6480 t = ', '.join(t)
6484 t = ', '.join(t)
6481 cleanworkdir = False
6485 cleanworkdir = False
6482
6486
6483 if repo.vfs.exists('graftstate'):
6487 if repo.vfs.exists('graftstate'):
6484 t += _(' (graft in progress)')
6488 t += _(' (graft in progress)')
6485 if repo.vfs.exists('updatestate'):
6489 if repo.vfs.exists('updatestate'):
6486 t += _(' (interrupted update)')
6490 t += _(' (interrupted update)')
6487 elif len(parents) > 1:
6491 elif len(parents) > 1:
6488 t += _(' (merge)')
6492 t += _(' (merge)')
6489 elif branch != parents[0].branch():
6493 elif branch != parents[0].branch():
6490 t += _(' (new branch)')
6494 t += _(' (new branch)')
6491 elif (parents[0].closesbranch() and
6495 elif (parents[0].closesbranch() and
6492 pnode in repo.branchheads(branch, closed=True)):
6496 pnode in repo.branchheads(branch, closed=True)):
6493 t += _(' (head closed)')
6497 t += _(' (head closed)')
6494 elif not (status.modified or status.added or status.removed or renamed or
6498 elif not (status.modified or status.added or status.removed or renamed or
6495 copied or subs):
6499 copied or subs):
6496 t += _(' (clean)')
6500 t += _(' (clean)')
6497 cleanworkdir = True
6501 cleanworkdir = True
6498 elif pnode not in bheads:
6502 elif pnode not in bheads:
6499 t += _(' (new branch head)')
6503 t += _(' (new branch head)')
6500
6504
6501 if parents:
6505 if parents:
6502 pendingphase = max(p.phase() for p in parents)
6506 pendingphase = max(p.phase() for p in parents)
6503 else:
6507 else:
6504 pendingphase = phases.public
6508 pendingphase = phases.public
6505
6509
6506 if pendingphase > phases.newcommitphase(ui):
6510 if pendingphase > phases.newcommitphase(ui):
6507 t += ' (%s)' % phases.phasenames[pendingphase]
6511 t += ' (%s)' % phases.phasenames[pendingphase]
6508
6512
6509 if cleanworkdir:
6513 if cleanworkdir:
6510 # i18n: column positioning for "hg summary"
6514 # i18n: column positioning for "hg summary"
6511 ui.status(_('commit: %s\n') % t.strip())
6515 ui.status(_('commit: %s\n') % t.strip())
6512 else:
6516 else:
6513 # i18n: column positioning for "hg summary"
6517 # i18n: column positioning for "hg summary"
6514 ui.write(_('commit: %s\n') % t.strip())
6518 ui.write(_('commit: %s\n') % t.strip())
6515
6519
6516 # all ancestors of branch heads - all ancestors of parent = new csets
6520 # all ancestors of branch heads - all ancestors of parent = new csets
6517 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6521 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6518 bheads))
6522 bheads))
6519
6523
6520 if new == 0:
6524 if new == 0:
6521 # i18n: column positioning for "hg summary"
6525 # i18n: column positioning for "hg summary"
6522 ui.status(_('update: (current)\n'))
6526 ui.status(_('update: (current)\n'))
6523 elif pnode not in bheads:
6527 elif pnode not in bheads:
6524 # i18n: column positioning for "hg summary"
6528 # i18n: column positioning for "hg summary"
6525 ui.write(_('update: %d new changesets (update)\n') % new)
6529 ui.write(_('update: %d new changesets (update)\n') % new)
6526 else:
6530 else:
6527 # i18n: column positioning for "hg summary"
6531 # i18n: column positioning for "hg summary"
6528 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6532 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6529 (new, len(bheads)))
6533 (new, len(bheads)))
6530
6534
6531 t = []
6535 t = []
6532 draft = len(repo.revs('draft()'))
6536 draft = len(repo.revs('draft()'))
6533 if draft:
6537 if draft:
6534 t.append(_('%d draft') % draft)
6538 t.append(_('%d draft') % draft)
6535 secret = len(repo.revs('secret()'))
6539 secret = len(repo.revs('secret()'))
6536 if secret:
6540 if secret:
6537 t.append(_('%d secret') % secret)
6541 t.append(_('%d secret') % secret)
6538
6542
6539 if draft or secret:
6543 if draft or secret:
6540 ui.status(_('phases: %s\n') % ', '.join(t))
6544 ui.status(_('phases: %s\n') % ', '.join(t))
6541
6545
6542 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6546 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6543 for trouble in ("unstable", "divergent", "bumped"):
6547 for trouble in ("unstable", "divergent", "bumped"):
6544 numtrouble = len(repo.revs(trouble + "()"))
6548 numtrouble = len(repo.revs(trouble + "()"))
6545 # We write all the possibilities to ease translation
6549 # We write all the possibilities to ease translation
6546 troublemsg = {
6550 troublemsg = {
6547 "unstable": _("unstable: %d changesets"),
6551 "unstable": _("unstable: %d changesets"),
6548 "divergent": _("divergent: %d changesets"),
6552 "divergent": _("divergent: %d changesets"),
6549 "bumped": _("bumped: %d changesets"),
6553 "bumped": _("bumped: %d changesets"),
6550 }
6554 }
6551 if numtrouble > 0:
6555 if numtrouble > 0:
6552 ui.status(troublemsg[trouble] % numtrouble + "\n")
6556 ui.status(troublemsg[trouble] % numtrouble + "\n")
6553
6557
6554 cmdutil.summaryhooks(ui, repo)
6558 cmdutil.summaryhooks(ui, repo)
6555
6559
6556 if opts.get('remote'):
6560 if opts.get('remote'):
6557 needsincoming, needsoutgoing = True, True
6561 needsincoming, needsoutgoing = True, True
6558 else:
6562 else:
6559 needsincoming, needsoutgoing = False, False
6563 needsincoming, needsoutgoing = False, False
6560 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6564 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6561 if i:
6565 if i:
6562 needsincoming = True
6566 needsincoming = True
6563 if o:
6567 if o:
6564 needsoutgoing = True
6568 needsoutgoing = True
6565 if not needsincoming and not needsoutgoing:
6569 if not needsincoming and not needsoutgoing:
6566 return
6570 return
6567
6571
6568 def getincoming():
6572 def getincoming():
6569 source, branches = hg.parseurl(ui.expandpath('default'))
6573 source, branches = hg.parseurl(ui.expandpath('default'))
6570 sbranch = branches[0]
6574 sbranch = branches[0]
6571 try:
6575 try:
6572 other = hg.peer(repo, {}, source)
6576 other = hg.peer(repo, {}, source)
6573 except error.RepoError:
6577 except error.RepoError:
6574 if opts.get('remote'):
6578 if opts.get('remote'):
6575 raise
6579 raise
6576 return source, sbranch, None, None, None
6580 return source, sbranch, None, None, None
6577 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6581 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6578 if revs:
6582 if revs:
6579 revs = [other.lookup(rev) for rev in revs]
6583 revs = [other.lookup(rev) for rev in revs]
6580 ui.debug('comparing with %s\n' % util.hidepassword(source))
6584 ui.debug('comparing with %s\n' % util.hidepassword(source))
6581 repo.ui.pushbuffer()
6585 repo.ui.pushbuffer()
6582 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6586 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6583 repo.ui.popbuffer()
6587 repo.ui.popbuffer()
6584 return source, sbranch, other, commoninc, commoninc[1]
6588 return source, sbranch, other, commoninc, commoninc[1]
6585
6589
6586 if needsincoming:
6590 if needsincoming:
6587 source, sbranch, sother, commoninc, incoming = getincoming()
6591 source, sbranch, sother, commoninc, incoming = getincoming()
6588 else:
6592 else:
6589 source = sbranch = sother = commoninc = incoming = None
6593 source = sbranch = sother = commoninc = incoming = None
6590
6594
6591 def getoutgoing():
6595 def getoutgoing():
6592 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6596 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6593 dbranch = branches[0]
6597 dbranch = branches[0]
6594 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6598 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6595 if source != dest:
6599 if source != dest:
6596 try:
6600 try:
6597 dother = hg.peer(repo, {}, dest)
6601 dother = hg.peer(repo, {}, dest)
6598 except error.RepoError:
6602 except error.RepoError:
6599 if opts.get('remote'):
6603 if opts.get('remote'):
6600 raise
6604 raise
6601 return dest, dbranch, None, None
6605 return dest, dbranch, None, None
6602 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6606 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6603 elif sother is None:
6607 elif sother is None:
6604 # there is no explicit destination peer, but source one is invalid
6608 # there is no explicit destination peer, but source one is invalid
6605 return dest, dbranch, None, None
6609 return dest, dbranch, None, None
6606 else:
6610 else:
6607 dother = sother
6611 dother = sother
6608 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6612 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6609 common = None
6613 common = None
6610 else:
6614 else:
6611 common = commoninc
6615 common = commoninc
6612 if revs:
6616 if revs:
6613 revs = [repo.lookup(rev) for rev in revs]
6617 revs = [repo.lookup(rev) for rev in revs]
6614 repo.ui.pushbuffer()
6618 repo.ui.pushbuffer()
6615 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6619 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6616 commoninc=common)
6620 commoninc=common)
6617 repo.ui.popbuffer()
6621 repo.ui.popbuffer()
6618 return dest, dbranch, dother, outgoing
6622 return dest, dbranch, dother, outgoing
6619
6623
6620 if needsoutgoing:
6624 if needsoutgoing:
6621 dest, dbranch, dother, outgoing = getoutgoing()
6625 dest, dbranch, dother, outgoing = getoutgoing()
6622 else:
6626 else:
6623 dest = dbranch = dother = outgoing = None
6627 dest = dbranch = dother = outgoing = None
6624
6628
6625 if opts.get('remote'):
6629 if opts.get('remote'):
6626 t = []
6630 t = []
6627 if incoming:
6631 if incoming:
6628 t.append(_('1 or more incoming'))
6632 t.append(_('1 or more incoming'))
6629 o = outgoing.missing
6633 o = outgoing.missing
6630 if o:
6634 if o:
6631 t.append(_('%d outgoing') % len(o))
6635 t.append(_('%d outgoing') % len(o))
6632 other = dother or sother
6636 other = dother or sother
6633 if 'bookmarks' in other.listkeys('namespaces'):
6637 if 'bookmarks' in other.listkeys('namespaces'):
6634 counts = bookmarks.summary(repo, other)
6638 counts = bookmarks.summary(repo, other)
6635 if counts[0] > 0:
6639 if counts[0] > 0:
6636 t.append(_('%d incoming bookmarks') % counts[0])
6640 t.append(_('%d incoming bookmarks') % counts[0])
6637 if counts[1] > 0:
6641 if counts[1] > 0:
6638 t.append(_('%d outgoing bookmarks') % counts[1])
6642 t.append(_('%d outgoing bookmarks') % counts[1])
6639
6643
6640 if t:
6644 if t:
6641 # i18n: column positioning for "hg summary"
6645 # i18n: column positioning for "hg summary"
6642 ui.write(_('remote: %s\n') % (', '.join(t)))
6646 ui.write(_('remote: %s\n') % (', '.join(t)))
6643 else:
6647 else:
6644 # i18n: column positioning for "hg summary"
6648 # i18n: column positioning for "hg summary"
6645 ui.status(_('remote: (synced)\n'))
6649 ui.status(_('remote: (synced)\n'))
6646
6650
6647 cmdutil.summaryremotehooks(ui, repo, opts,
6651 cmdutil.summaryremotehooks(ui, repo, opts,
6648 ((source, sbranch, sother, commoninc),
6652 ((source, sbranch, sother, commoninc),
6649 (dest, dbranch, dother, outgoing)))
6653 (dest, dbranch, dother, outgoing)))
6650
6654
6651 @command('tag',
6655 @command('tag',
6652 [('f', 'force', None, _('force tag')),
6656 [('f', 'force', None, _('force tag')),
6653 ('l', 'local', None, _('make the tag local')),
6657 ('l', 'local', None, _('make the tag local')),
6654 ('r', 'rev', '', _('revision to tag'), _('REV')),
6658 ('r', 'rev', '', _('revision to tag'), _('REV')),
6655 ('', 'remove', None, _('remove a tag')),
6659 ('', 'remove', None, _('remove a tag')),
6656 # -l/--local is already there, commitopts cannot be used
6660 # -l/--local is already there, commitopts cannot be used
6657 ('e', 'edit', None, _('invoke editor on commit messages')),
6661 ('e', 'edit', None, _('invoke editor on commit messages')),
6658 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6662 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6659 ] + commitopts2,
6663 ] + commitopts2,
6660 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6664 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6661 def tag(ui, repo, name1, *names, **opts):
6665 def tag(ui, repo, name1, *names, **opts):
6662 """add one or more tags for the current or given revision
6666 """add one or more tags for the current or given revision
6663
6667
6664 Name a particular revision using <name>.
6668 Name a particular revision using <name>.
6665
6669
6666 Tags are used to name particular revisions of the repository and are
6670 Tags are used to name particular revisions of the repository and are
6667 very useful to compare different revisions, to go back to significant
6671 very useful to compare different revisions, to go back to significant
6668 earlier versions or to mark branch points as releases, etc. Changing
6672 earlier versions or to mark branch points as releases, etc. Changing
6669 an existing tag is normally disallowed; use -f/--force to override.
6673 an existing tag is normally disallowed; use -f/--force to override.
6670
6674
6671 If no revision is given, the parent of the working directory is
6675 If no revision is given, the parent of the working directory is
6672 used.
6676 used.
6673
6677
6674 To facilitate version control, distribution, and merging of tags,
6678 To facilitate version control, distribution, and merging of tags,
6675 they are stored as a file named ".hgtags" which is managed similarly
6679 they are stored as a file named ".hgtags" which is managed similarly
6676 to other project files and can be hand-edited if necessary. This
6680 to other project files and can be hand-edited if necessary. This
6677 also means that tagging creates a new commit. The file
6681 also means that tagging creates a new commit. The file
6678 ".hg/localtags" is used for local tags (not shared among
6682 ".hg/localtags" is used for local tags (not shared among
6679 repositories).
6683 repositories).
6680
6684
6681 Tag commits are usually made at the head of a branch. If the parent
6685 Tag commits are usually made at the head of a branch. If the parent
6682 of the working directory is not a branch head, :hg:`tag` aborts; use
6686 of the working directory is not a branch head, :hg:`tag` aborts; use
6683 -f/--force to force the tag commit to be based on a non-head
6687 -f/--force to force the tag commit to be based on a non-head
6684 changeset.
6688 changeset.
6685
6689
6686 See :hg:`help dates` for a list of formats valid for -d/--date.
6690 See :hg:`help dates` for a list of formats valid for -d/--date.
6687
6691
6688 Since tag names have priority over branch names during revision
6692 Since tag names have priority over branch names during revision
6689 lookup, using an existing branch name as a tag name is discouraged.
6693 lookup, using an existing branch name as a tag name is discouraged.
6690
6694
6691 Returns 0 on success.
6695 Returns 0 on success.
6692 """
6696 """
6693 wlock = lock = None
6697 wlock = lock = None
6694 try:
6698 try:
6695 wlock = repo.wlock()
6699 wlock = repo.wlock()
6696 lock = repo.lock()
6700 lock = repo.lock()
6697 rev_ = "."
6701 rev_ = "."
6698 names = [t.strip() for t in (name1,) + names]
6702 names = [t.strip() for t in (name1,) + names]
6699 if len(names) != len(set(names)):
6703 if len(names) != len(set(names)):
6700 raise error.Abort(_('tag names must be unique'))
6704 raise error.Abort(_('tag names must be unique'))
6701 for n in names:
6705 for n in names:
6702 scmutil.checknewlabel(repo, n, 'tag')
6706 scmutil.checknewlabel(repo, n, 'tag')
6703 if not n:
6707 if not n:
6704 raise error.Abort(_('tag names cannot consist entirely of '
6708 raise error.Abort(_('tag names cannot consist entirely of '
6705 'whitespace'))
6709 'whitespace'))
6706 if opts.get('rev') and opts.get('remove'):
6710 if opts.get('rev') and opts.get('remove'):
6707 raise error.Abort(_("--rev and --remove are incompatible"))
6711 raise error.Abort(_("--rev and --remove are incompatible"))
6708 if opts.get('rev'):
6712 if opts.get('rev'):
6709 rev_ = opts['rev']
6713 rev_ = opts['rev']
6710 message = opts.get('message')
6714 message = opts.get('message')
6711 if opts.get('remove'):
6715 if opts.get('remove'):
6712 if opts.get('local'):
6716 if opts.get('local'):
6713 expectedtype = 'local'
6717 expectedtype = 'local'
6714 else:
6718 else:
6715 expectedtype = 'global'
6719 expectedtype = 'global'
6716
6720
6717 for n in names:
6721 for n in names:
6718 if not repo.tagtype(n):
6722 if not repo.tagtype(n):
6719 raise error.Abort(_("tag '%s' does not exist") % n)
6723 raise error.Abort(_("tag '%s' does not exist") % n)
6720 if repo.tagtype(n) != expectedtype:
6724 if repo.tagtype(n) != expectedtype:
6721 if expectedtype == 'global':
6725 if expectedtype == 'global':
6722 raise error.Abort(_("tag '%s' is not a global tag") % n)
6726 raise error.Abort(_("tag '%s' is not a global tag") % n)
6723 else:
6727 else:
6724 raise error.Abort(_("tag '%s' is not a local tag") % n)
6728 raise error.Abort(_("tag '%s' is not a local tag") % n)
6725 rev_ = 'null'
6729 rev_ = 'null'
6726 if not message:
6730 if not message:
6727 # we don't translate commit messages
6731 # we don't translate commit messages
6728 message = 'Removed tag %s' % ', '.join(names)
6732 message = 'Removed tag %s' % ', '.join(names)
6729 elif not opts.get('force'):
6733 elif not opts.get('force'):
6730 for n in names:
6734 for n in names:
6731 if n in repo.tags():
6735 if n in repo.tags():
6732 raise error.Abort(_("tag '%s' already exists "
6736 raise error.Abort(_("tag '%s' already exists "
6733 "(use -f to force)") % n)
6737 "(use -f to force)") % n)
6734 if not opts.get('local'):
6738 if not opts.get('local'):
6735 p1, p2 = repo.dirstate.parents()
6739 p1, p2 = repo.dirstate.parents()
6736 if p2 != nullid:
6740 if p2 != nullid:
6737 raise error.Abort(_('uncommitted merge'))
6741 raise error.Abort(_('uncommitted merge'))
6738 bheads = repo.branchheads()
6742 bheads = repo.branchheads()
6739 if not opts.get('force') and bheads and p1 not in bheads:
6743 if not opts.get('force') and bheads and p1 not in bheads:
6740 raise error.Abort(_('not at a branch head (use -f to force)'))
6744 raise error.Abort(_('not at a branch head (use -f to force)'))
6741 r = scmutil.revsingle(repo, rev_).node()
6745 r = scmutil.revsingle(repo, rev_).node()
6742
6746
6743 if not message:
6747 if not message:
6744 # we don't translate commit messages
6748 # we don't translate commit messages
6745 message = ('Added tag %s for changeset %s' %
6749 message = ('Added tag %s for changeset %s' %
6746 (', '.join(names), short(r)))
6750 (', '.join(names), short(r)))
6747
6751
6748 date = opts.get('date')
6752 date = opts.get('date')
6749 if date:
6753 if date:
6750 date = util.parsedate(date)
6754 date = util.parsedate(date)
6751
6755
6752 if opts.get('remove'):
6756 if opts.get('remove'):
6753 editform = 'tag.remove'
6757 editform = 'tag.remove'
6754 else:
6758 else:
6755 editform = 'tag.add'
6759 editform = 'tag.add'
6756 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6760 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6757
6761
6758 # don't allow tagging the null rev
6762 # don't allow tagging the null rev
6759 if (not opts.get('remove') and
6763 if (not opts.get('remove') and
6760 scmutil.revsingle(repo, rev_).rev() == nullrev):
6764 scmutil.revsingle(repo, rev_).rev() == nullrev):
6761 raise error.Abort(_("cannot tag null revision"))
6765 raise error.Abort(_("cannot tag null revision"))
6762
6766
6763 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6767 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6764 editor=editor)
6768 editor=editor)
6765 finally:
6769 finally:
6766 release(lock, wlock)
6770 release(lock, wlock)
6767
6771
6768 @command('tags', formatteropts, '')
6772 @command('tags', formatteropts, '')
6769 def tags(ui, repo, **opts):
6773 def tags(ui, repo, **opts):
6770 """list repository tags
6774 """list repository tags
6771
6775
6772 This lists both regular and local tags. When the -v/--verbose
6776 This lists both regular and local tags. When the -v/--verbose
6773 switch is used, a third column "local" is printed for local tags.
6777 switch is used, a third column "local" is printed for local tags.
6774 When the -q/--quiet switch is used, only the tag name is printed.
6778 When the -q/--quiet switch is used, only the tag name is printed.
6775
6779
6776 Returns 0 on success.
6780 Returns 0 on success.
6777 """
6781 """
6778
6782
6779 fm = ui.formatter('tags', opts)
6783 fm = ui.formatter('tags', opts)
6780 hexfunc = fm.hexfunc
6784 hexfunc = fm.hexfunc
6781 tagtype = ""
6785 tagtype = ""
6782
6786
6783 for t, n in reversed(repo.tagslist()):
6787 for t, n in reversed(repo.tagslist()):
6784 hn = hexfunc(n)
6788 hn = hexfunc(n)
6785 label = 'tags.normal'
6789 label = 'tags.normal'
6786 tagtype = ''
6790 tagtype = ''
6787 if repo.tagtype(t) == 'local':
6791 if repo.tagtype(t) == 'local':
6788 label = 'tags.local'
6792 label = 'tags.local'
6789 tagtype = 'local'
6793 tagtype = 'local'
6790
6794
6791 fm.startitem()
6795 fm.startitem()
6792 fm.write('tag', '%s', t, label=label)
6796 fm.write('tag', '%s', t, label=label)
6793 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6797 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6794 fm.condwrite(not ui.quiet, 'rev node', fmt,
6798 fm.condwrite(not ui.quiet, 'rev node', fmt,
6795 repo.changelog.rev(n), hn, label=label)
6799 repo.changelog.rev(n), hn, label=label)
6796 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6800 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6797 tagtype, label=label)
6801 tagtype, label=label)
6798 fm.plain('\n')
6802 fm.plain('\n')
6799 fm.end()
6803 fm.end()
6800
6804
6801 @command('tip',
6805 @command('tip',
6802 [('p', 'patch', None, _('show patch')),
6806 [('p', 'patch', None, _('show patch')),
6803 ('g', 'git', None, _('use git extended diff format')),
6807 ('g', 'git', None, _('use git extended diff format')),
6804 ] + templateopts,
6808 ] + templateopts,
6805 _('[-p] [-g]'))
6809 _('[-p] [-g]'))
6806 def tip(ui, repo, **opts):
6810 def tip(ui, repo, **opts):
6807 """show the tip revision (DEPRECATED)
6811 """show the tip revision (DEPRECATED)
6808
6812
6809 The tip revision (usually just called the tip) is the changeset
6813 The tip revision (usually just called the tip) is the changeset
6810 most recently added to the repository (and therefore the most
6814 most recently added to the repository (and therefore the most
6811 recently changed head).
6815 recently changed head).
6812
6816
6813 If you have just made a commit, that commit will be the tip. If
6817 If you have just made a commit, that commit will be the tip. If
6814 you have just pulled changes from another repository, the tip of
6818 you have just pulled changes from another repository, the tip of
6815 that repository becomes the current tip. The "tip" tag is special
6819 that repository becomes the current tip. The "tip" tag is special
6816 and cannot be renamed or assigned to a different changeset.
6820 and cannot be renamed or assigned to a different changeset.
6817
6821
6818 This command is deprecated, please use :hg:`heads` instead.
6822 This command is deprecated, please use :hg:`heads` instead.
6819
6823
6820 Returns 0 on success.
6824 Returns 0 on success.
6821 """
6825 """
6822 displayer = cmdutil.show_changeset(ui, repo, opts)
6826 displayer = cmdutil.show_changeset(ui, repo, opts)
6823 displayer.show(repo['tip'])
6827 displayer.show(repo['tip'])
6824 displayer.close()
6828 displayer.close()
6825
6829
6826 @command('unbundle',
6830 @command('unbundle',
6827 [('u', 'update', None,
6831 [('u', 'update', None,
6828 _('update to new branch head if changesets were unbundled'))],
6832 _('update to new branch head if changesets were unbundled'))],
6829 _('[-u] FILE...'))
6833 _('[-u] FILE...'))
6830 def unbundle(ui, repo, fname1, *fnames, **opts):
6834 def unbundle(ui, repo, fname1, *fnames, **opts):
6831 """apply one or more changegroup files
6835 """apply one or more changegroup files
6832
6836
6833 Apply one or more compressed changegroup files generated by the
6837 Apply one or more compressed changegroup files generated by the
6834 bundle command.
6838 bundle command.
6835
6839
6836 Returns 0 on success, 1 if an update has unresolved files.
6840 Returns 0 on success, 1 if an update has unresolved files.
6837 """
6841 """
6838 fnames = (fname1,) + fnames
6842 fnames = (fname1,) + fnames
6839
6843
6840 with repo.lock():
6844 with repo.lock():
6841 for fname in fnames:
6845 for fname in fnames:
6842 f = hg.openpath(ui, fname)
6846 f = hg.openpath(ui, fname)
6843 gen = exchange.readbundle(ui, f, fname)
6847 gen = exchange.readbundle(ui, f, fname)
6844 if isinstance(gen, bundle2.unbundle20):
6848 if isinstance(gen, bundle2.unbundle20):
6845 tr = repo.transaction('unbundle')
6849 tr = repo.transaction('unbundle')
6846 try:
6850 try:
6847 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6851 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6848 url='bundle:' + fname)
6852 url='bundle:' + fname)
6849 tr.close()
6853 tr.close()
6850 except error.BundleUnknownFeatureError as exc:
6854 except error.BundleUnknownFeatureError as exc:
6851 raise error.Abort(_('%s: unknown bundle feature, %s')
6855 raise error.Abort(_('%s: unknown bundle feature, %s')
6852 % (fname, exc),
6856 % (fname, exc),
6853 hint=_("see https://mercurial-scm.org/"
6857 hint=_("see https://mercurial-scm.org/"
6854 "wiki/BundleFeature for more "
6858 "wiki/BundleFeature for more "
6855 "information"))
6859 "information"))
6856 finally:
6860 finally:
6857 if tr:
6861 if tr:
6858 tr.release()
6862 tr.release()
6859 changes = [r.get('return', 0)
6863 changes = [r.get('return', 0)
6860 for r in op.records['changegroup']]
6864 for r in op.records['changegroup']]
6861 modheads = changegroup.combineresults(changes)
6865 modheads = changegroup.combineresults(changes)
6862 elif isinstance(gen, streamclone.streamcloneapplier):
6866 elif isinstance(gen, streamclone.streamcloneapplier):
6863 raise error.Abort(
6867 raise error.Abort(
6864 _('packed bundles cannot be applied with '
6868 _('packed bundles cannot be applied with '
6865 '"hg unbundle"'),
6869 '"hg unbundle"'),
6866 hint=_('use "hg debugapplystreamclonebundle"'))
6870 hint=_('use "hg debugapplystreamclonebundle"'))
6867 else:
6871 else:
6868 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6872 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6869
6873
6870 return postincoming(ui, repo, modheads, opts.get('update'), None)
6874 return postincoming(ui, repo, modheads, opts.get('update'), None)
6871
6875
6872 @command('^update|up|checkout|co',
6876 @command('^update|up|checkout|co',
6873 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6877 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6874 ('c', 'check', None,
6878 ('c', 'check', None,
6875 _('update across branches if no uncommitted changes')),
6879 _('update across branches if no uncommitted changes')),
6876 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6880 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6877 ('r', 'rev', '', _('revision'), _('REV'))
6881 ('r', 'rev', '', _('revision'), _('REV'))
6878 ] + mergetoolopts,
6882 ] + mergetoolopts,
6879 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6883 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6880 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6884 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6881 tool=None):
6885 tool=None):
6882 """update working directory (or switch revisions)
6886 """update working directory (or switch revisions)
6883
6887
6884 Update the repository's working directory to the specified
6888 Update the repository's working directory to the specified
6885 changeset. If no changeset is specified, update to the tip of the
6889 changeset. If no changeset is specified, update to the tip of the
6886 current named branch and move the active bookmark (see :hg:`help
6890 current named branch and move the active bookmark (see :hg:`help
6887 bookmarks`).
6891 bookmarks`).
6888
6892
6889 Update sets the working directory's parent revision to the specified
6893 Update sets the working directory's parent revision to the specified
6890 changeset (see :hg:`help parents`).
6894 changeset (see :hg:`help parents`).
6891
6895
6892 If the changeset is not a descendant or ancestor of the working
6896 If the changeset is not a descendant or ancestor of the working
6893 directory's parent, the update is aborted. With the -c/--check
6897 directory's parent, the update is aborted. With the -c/--check
6894 option, the working directory is checked for uncommitted changes; if
6898 option, the working directory is checked for uncommitted changes; if
6895 none are found, the working directory is updated to the specified
6899 none are found, the working directory is updated to the specified
6896 changeset.
6900 changeset.
6897
6901
6898 .. container:: verbose
6902 .. container:: verbose
6899
6903
6900 The following rules apply when the working directory contains
6904 The following rules apply when the working directory contains
6901 uncommitted changes:
6905 uncommitted changes:
6902
6906
6903 1. If neither -c/--check nor -C/--clean is specified, and if
6907 1. If neither -c/--check nor -C/--clean is specified, and if
6904 the requested changeset is an ancestor or descendant of
6908 the requested changeset is an ancestor or descendant of
6905 the working directory's parent, the uncommitted changes
6909 the working directory's parent, the uncommitted changes
6906 are merged into the requested changeset and the merged
6910 are merged into the requested changeset and the merged
6907 result is left uncommitted. If the requested changeset is
6911 result is left uncommitted. If the requested changeset is
6908 not an ancestor or descendant (that is, it is on another
6912 not an ancestor or descendant (that is, it is on another
6909 branch), the update is aborted and the uncommitted changes
6913 branch), the update is aborted and the uncommitted changes
6910 are preserved.
6914 are preserved.
6911
6915
6912 2. With the -c/--check option, the update is aborted and the
6916 2. With the -c/--check option, the update is aborted and the
6913 uncommitted changes are preserved.
6917 uncommitted changes are preserved.
6914
6918
6915 3. With the -C/--clean option, uncommitted changes are discarded and
6919 3. With the -C/--clean option, uncommitted changes are discarded and
6916 the working directory is updated to the requested changeset.
6920 the working directory is updated to the requested changeset.
6917
6921
6918 To cancel an uncommitted merge (and lose your changes), use
6922 To cancel an uncommitted merge (and lose your changes), use
6919 :hg:`update --clean .`.
6923 :hg:`update --clean .`.
6920
6924
6921 Use null as the changeset to remove the working directory (like
6925 Use null as the changeset to remove the working directory (like
6922 :hg:`clone -U`).
6926 :hg:`clone -U`).
6923
6927
6924 If you want to revert just one file to an older revision, use
6928 If you want to revert just one file to an older revision, use
6925 :hg:`revert [-r REV] NAME`.
6929 :hg:`revert [-r REV] NAME`.
6926
6930
6927 See :hg:`help dates` for a list of formats valid for -d/--date.
6931 See :hg:`help dates` for a list of formats valid for -d/--date.
6928
6932
6929 Returns 0 on success, 1 if there are unresolved files.
6933 Returns 0 on success, 1 if there are unresolved files.
6930 """
6934 """
6931 movemarkfrom = None
6935 movemarkfrom = None
6932 if rev and node:
6936 if rev and node:
6933 raise error.Abort(_("please specify just one revision"))
6937 raise error.Abort(_("please specify just one revision"))
6934
6938
6935 if rev is None or rev == '':
6939 if rev is None or rev == '':
6936 rev = node
6940 rev = node
6937
6941
6938 with repo.wlock():
6942 with repo.wlock():
6939 cmdutil.clearunfinished(repo)
6943 cmdutil.clearunfinished(repo)
6940
6944
6941 if date:
6945 if date:
6942 if rev is not None:
6946 if rev is not None:
6943 raise error.Abort(_("you can't specify a revision and a date"))
6947 raise error.Abort(_("you can't specify a revision and a date"))
6944 rev = cmdutil.finddate(ui, repo, date)
6948 rev = cmdutil.finddate(ui, repo, date)
6945
6949
6946 # if we defined a bookmark, we have to remember the original name
6950 # if we defined a bookmark, we have to remember the original name
6947 brev = rev
6951 brev = rev
6948 rev = scmutil.revsingle(repo, rev, rev).rev()
6952 rev = scmutil.revsingle(repo, rev, rev).rev()
6949
6953
6950 if check and clean:
6954 if check and clean:
6951 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6955 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6952 )
6956 )
6953
6957
6954 if check:
6958 if check:
6955 cmdutil.bailifchanged(repo, merge=False)
6959 cmdutil.bailifchanged(repo, merge=False)
6956 if rev is None:
6960 if rev is None:
6957 updata = destutil.destupdate(repo, clean=clean, check=check)
6961 updata = destutil.destupdate(repo, clean=clean, check=check)
6958 rev, movemarkfrom, brev = updata
6962 rev, movemarkfrom, brev = updata
6959
6963
6960 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6964 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6961
6965
6962 if clean:
6966 if clean:
6963 ret = hg.clean(repo, rev)
6967 ret = hg.clean(repo, rev)
6964 else:
6968 else:
6965 ret = hg.update(repo, rev)
6969 ret = hg.update(repo, rev)
6966
6970
6967 if not ret and movemarkfrom:
6971 if not ret and movemarkfrom:
6968 if movemarkfrom == repo['.'].node():
6972 if movemarkfrom == repo['.'].node():
6969 pass # no-op update
6973 pass # no-op update
6970 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6974 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6971 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6975 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6972 else:
6976 else:
6973 # this can happen with a non-linear update
6977 # this can happen with a non-linear update
6974 ui.status(_("(leaving bookmark %s)\n") %
6978 ui.status(_("(leaving bookmark %s)\n") %
6975 repo._activebookmark)
6979 repo._activebookmark)
6976 bookmarks.deactivate(repo)
6980 bookmarks.deactivate(repo)
6977 elif brev in repo._bookmarks:
6981 elif brev in repo._bookmarks:
6978 bookmarks.activate(repo, brev)
6982 bookmarks.activate(repo, brev)
6979 ui.status(_("(activating bookmark %s)\n") % brev)
6983 ui.status(_("(activating bookmark %s)\n") % brev)
6980 elif brev:
6984 elif brev:
6981 if repo._activebookmark:
6985 if repo._activebookmark:
6982 ui.status(_("(leaving bookmark %s)\n") %
6986 ui.status(_("(leaving bookmark %s)\n") %
6983 repo._activebookmark)
6987 repo._activebookmark)
6984 bookmarks.deactivate(repo)
6988 bookmarks.deactivate(repo)
6985
6989
6986 return ret
6990 return ret
6987
6991
6988 @command('verify', [])
6992 @command('verify', [])
6989 def verify(ui, repo):
6993 def verify(ui, repo):
6990 """verify the integrity of the repository
6994 """verify the integrity of the repository
6991
6995
6992 Verify the integrity of the current repository.
6996 Verify the integrity of the current repository.
6993
6997
6994 This will perform an extensive check of the repository's
6998 This will perform an extensive check of the repository's
6995 integrity, validating the hashes and checksums of each entry in
6999 integrity, validating the hashes and checksums of each entry in
6996 the changelog, manifest, and tracked files, as well as the
7000 the changelog, manifest, and tracked files, as well as the
6997 integrity of their crosslinks and indices.
7001 integrity of their crosslinks and indices.
6998
7002
6999 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7003 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7000 for more information about recovery from corruption of the
7004 for more information about recovery from corruption of the
7001 repository.
7005 repository.
7002
7006
7003 Returns 0 on success, 1 if errors are encountered.
7007 Returns 0 on success, 1 if errors are encountered.
7004 """
7008 """
7005 return hg.verify(repo)
7009 return hg.verify(repo)
7006
7010
7007 @command('version', [], norepo=True)
7011 @command('version', [], norepo=True)
7008 def version_(ui):
7012 def version_(ui):
7009 """output version and copyright information"""
7013 """output version and copyright information"""
7010 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7014 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7011 % util.version())
7015 % util.version())
7012 ui.status(_(
7016 ui.status(_(
7013 "(see https://mercurial-scm.org for more information)\n"
7017 "(see https://mercurial-scm.org for more information)\n"
7014 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7018 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7015 "This is free software; see the source for copying conditions. "
7019 "This is free software; see the source for copying conditions. "
7016 "There is NO\nwarranty; "
7020 "There is NO\nwarranty; "
7017 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7021 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7018 ))
7022 ))
7019
7023
7020 ui.note(_("\nEnabled extensions:\n\n"))
7024 ui.note(_("\nEnabled extensions:\n\n"))
7021 if ui.verbose:
7025 if ui.verbose:
7022 # format names and versions into columns
7026 # format names and versions into columns
7023 names = []
7027 names = []
7024 vers = []
7028 vers = []
7025 for name, module in extensions.extensions():
7029 for name, module in extensions.extensions():
7026 names.append(name)
7030 names.append(name)
7027 vers.append(extensions.moduleversion(module))
7031 vers.append(extensions.moduleversion(module))
7028 if names:
7032 if names:
7029 maxnamelen = max(len(n) for n in names)
7033 maxnamelen = max(len(n) for n in names)
7030 for i, name in enumerate(names):
7034 for i, name in enumerate(names):
7031 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7035 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,829 +1,830
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1:5d205f8b35b6
53 skipping ancestor revision 1:5d205f8b35b6
54 skipping ancestor revision 2:5c095ad7e90f
54 skipping ancestor revision 2:5c095ad7e90f
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1:5d205f8b35b6
60 skipping ancestor revision 1:5d205f8b35b6
61 skipping ancestor revision 2:5c095ad7e90f
61 skipping ancestor revision 2:5c095ad7e90f
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 warning: inconsistent use of --rev might give unexpected revision ordering!
65 skipping ancestor revision 2:5c095ad7e90f
66 skipping ancestor revision 2:5c095ad7e90f
66 skipping ancestor revision 1:5d205f8b35b6
67 skipping ancestor revision 1:5d205f8b35b6
67 [255]
68 [255]
68
69
69 Can't graft with dirty wd:
70 Can't graft with dirty wd:
70
71
71 $ hg up -q 0
72 $ hg up -q 0
72 $ echo foo > a
73 $ echo foo > a
73 $ hg graft 1
74 $ hg graft 1
74 abort: uncommitted changes
75 abort: uncommitted changes
75 [255]
76 [255]
76 $ hg revert a
77 $ hg revert a
77
78
78 Graft a rename:
79 Graft a rename:
79 (this also tests that editor is invoked if '--edit' is specified)
80 (this also tests that editor is invoked if '--edit' is specified)
80
81
81 $ hg status --rev "2^1" --rev 2
82 $ hg status --rev "2^1" --rev 2
82 A b
83 A b
83 R a
84 R a
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
85 $ HGEDITOR=cat hg graft 2 -u foo --edit
85 grafting 2:5c095ad7e90f "2"
86 grafting 2:5c095ad7e90f "2"
86 merging a and b to b
87 merging a and b to b
87 2
88 2
88
89
89
90
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
91 HG: Enter commit message. Lines beginning with 'HG:' are removed.
91 HG: Leave message empty to abort commit.
92 HG: Leave message empty to abort commit.
92 HG: --
93 HG: --
93 HG: user: foo
94 HG: user: foo
94 HG: branch 'default'
95 HG: branch 'default'
95 HG: added b
96 HG: added b
96 HG: removed a
97 HG: removed a
97 $ hg export tip --git
98 $ hg export tip --git
98 # HG changeset patch
99 # HG changeset patch
99 # User foo
100 # User foo
100 # Date 0 0
101 # Date 0 0
101 # Thu Jan 01 00:00:00 1970 +0000
102 # Thu Jan 01 00:00:00 1970 +0000
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
103 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
104 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
104 2
105 2
105
106
106 diff --git a/a b/b
107 diff --git a/a b/b
107 rename from a
108 rename from a
108 rename to b
109 rename to b
109
110
110 Look for extra:source
111 Look for extra:source
111
112
112 $ hg log --debug -r tip
113 $ hg log --debug -r tip
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
114 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
114 tag: tip
115 tag: tip
115 phase: draft
116 phase: draft
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
117 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
117 parent: -1:0000000000000000000000000000000000000000
118 parent: -1:0000000000000000000000000000000000000000
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
119 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
119 user: foo
120 user: foo
120 date: Thu Jan 01 00:00:00 1970 +0000
121 date: Thu Jan 01 00:00:00 1970 +0000
121 files+: b
122 files+: b
122 files-: a
123 files-: a
123 extra: branch=default
124 extra: branch=default
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
125 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
125 description:
126 description:
126 2
127 2
127
128
128
129
129
130
130 Graft out of order, skipping a merge and a duplicate
131 Graft out of order, skipping a merge and a duplicate
131 (this also tests that editor is not invoked if '--edit' is not specified)
132 (this also tests that editor is not invoked if '--edit' is not specified)
132
133
133 $ hg graft 1 5 4 3 'merge()' 2 -n
134 $ hg graft 1 5 4 3 'merge()' 2 -n
134 skipping ungraftable merge revision 6
135 skipping ungraftable merge revision 6
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
136 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
136 grafting 1:5d205f8b35b6 "1"
137 grafting 1:5d205f8b35b6 "1"
137 grafting 5:97f8bfe72746 "5"
138 grafting 5:97f8bfe72746 "5"
138 grafting 4:9c233e8e184d "4"
139 grafting 4:9c233e8e184d "4"
139 grafting 3:4c60f11aa304 "3"
140 grafting 3:4c60f11aa304 "3"
140
141
141 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
142 $ HGEDITOR=cat hg graft 1 5 'merge()' 2 --debug
142 skipping ungraftable merge revision 6
143 skipping ungraftable merge revision 6
143 scanning for duplicate grafts
144 scanning for duplicate grafts
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
145 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
145 grafting 1:5d205f8b35b6 "1"
146 grafting 1:5d205f8b35b6 "1"
146 searching for copies back to rev 1
147 searching for copies back to rev 1
147 unmatched files in local:
148 unmatched files in local:
148 b
149 b
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
150 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
150 src: 'a' -> dst: 'b' *
151 src: 'a' -> dst: 'b' *
151 checking for directory renames
152 checking for directory renames
152 resolving manifests
153 resolving manifests
153 branchmerge: True, force: True, partial: False
154 branchmerge: True, force: True, partial: False
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
155 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
155 preserving b for resolve of b
156 preserving b for resolve of b
156 b: local copied/moved from a -> m (premerge)
157 b: local copied/moved from a -> m (premerge)
157 picked tool ':merge' for b (binary False symlink False changedelete False)
158 picked tool ':merge' for b (binary False symlink False changedelete False)
158 merging b and a to b
159 merging b and a to b
159 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
160 premerge successful
161 premerge successful
161 committing files:
162 committing files:
162 b
163 b
163 committing manifest
164 committing manifest
164 committing changelog
165 committing changelog
165 grafting 5:97f8bfe72746 "5"
166 grafting 5:97f8bfe72746 "5"
166 searching for copies back to rev 1
167 searching for copies back to rev 1
167 resolving manifests
168 resolving manifests
168 branchmerge: True, force: True, partial: False
169 branchmerge: True, force: True, partial: False
169 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
170 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
170 e: remote is newer -> g
171 e: remote is newer -> g
171 getting e
172 getting e
172 b: remote unchanged -> k
173 b: remote unchanged -> k
173 committing files:
174 committing files:
174 e
175 e
175 committing manifest
176 committing manifest
176 committing changelog
177 committing changelog
177 $ HGEDITOR=cat hg graft 4 3 --log --debug
178 $ HGEDITOR=cat hg graft 4 3 --log --debug
178 scanning for duplicate grafts
179 scanning for duplicate grafts
179 grafting 4:9c233e8e184d "4"
180 grafting 4:9c233e8e184d "4"
180 searching for copies back to rev 1
181 searching for copies back to rev 1
181 resolving manifests
182 resolving manifests
182 branchmerge: True, force: True, partial: False
183 branchmerge: True, force: True, partial: False
183 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
184 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
184 preserving e for resolve of e
185 preserving e for resolve of e
185 d: remote is newer -> g
186 d: remote is newer -> g
186 getting d
187 getting d
187 b: remote unchanged -> k
188 b: remote unchanged -> k
188 e: versions differ -> m (premerge)
189 e: versions differ -> m (premerge)
189 picked tool ':merge' for e (binary False symlink False changedelete False)
190 picked tool ':merge' for e (binary False symlink False changedelete False)
190 merging e
191 merging e
191 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
192 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
192 e: versions differ -> m (merge)
193 e: versions differ -> m (merge)
193 picked tool ':merge' for e (binary False symlink False changedelete False)
194 picked tool ':merge' for e (binary False symlink False changedelete False)
194 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
195 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
195 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
196 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
196 abort: unresolved conflicts, can't continue
197 abort: unresolved conflicts, can't continue
197 (use hg resolve and hg graft --continue --log)
198 (use hg resolve and hg graft --continue --log)
198 [255]
199 [255]
199
200
200 Summary should mention graft:
201 Summary should mention graft:
201
202
202 $ hg summary |grep graft
203 $ hg summary |grep graft
203 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
204 commit: 2 modified, 2 unknown, 1 unresolved (graft in progress)
204
205
205 Commit while interrupted should fail:
206 Commit while interrupted should fail:
206
207
207 $ hg ci -m 'commit interrupted graft'
208 $ hg ci -m 'commit interrupted graft'
208 abort: graft in progress
209 abort: graft in progress
209 (use 'hg graft --continue' or 'hg update' to abort)
210 (use 'hg graft --continue' or 'hg update' to abort)
210 [255]
211 [255]
211
212
212 Abort the graft and try committing:
213 Abort the graft and try committing:
213
214
214 $ hg up -C .
215 $ hg up -C .
215 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 $ echo c >> e
217 $ echo c >> e
217 $ hg ci -mtest
218 $ hg ci -mtest
218
219
219 $ hg strip . --config extensions.strip=
220 $ hg strip . --config extensions.strip=
220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
222 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
222
223
223 Graft again:
224 Graft again:
224
225
225 $ hg graft 1 5 4 3 'merge()' 2
226 $ hg graft 1 5 4 3 'merge()' 2
226 skipping ungraftable merge revision 6
227 skipping ungraftable merge revision 6
227 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
228 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
228 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
229 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
229 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
230 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
230 grafting 4:9c233e8e184d "4"
231 grafting 4:9c233e8e184d "4"
231 merging e
232 merging e
232 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
233 warning: conflicts while merging e! (edit, then use 'hg resolve --mark')
233 abort: unresolved conflicts, can't continue
234 abort: unresolved conflicts, can't continue
234 (use hg resolve and hg graft --continue)
235 (use hg resolve and hg graft --continue)
235 [255]
236 [255]
236
237
237 Continue without resolve should fail:
238 Continue without resolve should fail:
238
239
239 $ hg graft -c
240 $ hg graft -c
240 grafting 4:9c233e8e184d "4"
241 grafting 4:9c233e8e184d "4"
241 abort: unresolved merge conflicts (see "hg help resolve")
242 abort: unresolved merge conflicts (see "hg help resolve")
242 [255]
243 [255]
243
244
244 Fix up:
245 Fix up:
245
246
246 $ echo b > e
247 $ echo b > e
247 $ hg resolve -m e
248 $ hg resolve -m e
248 (no more unresolved files)
249 (no more unresolved files)
249 continue: hg graft --continue
250 continue: hg graft --continue
250
251
251 Continue with a revision should fail:
252 Continue with a revision should fail:
252
253
253 $ hg graft -c 6
254 $ hg graft -c 6
254 abort: can't specify --continue and revisions
255 abort: can't specify --continue and revisions
255 [255]
256 [255]
256
257
257 $ hg graft -c -r 6
258 $ hg graft -c -r 6
258 abort: can't specify --continue and revisions
259 abort: can't specify --continue and revisions
259 [255]
260 [255]
260
261
261 Continue for real, clobber usernames
262 Continue for real, clobber usernames
262
263
263 $ hg graft -c -U
264 $ hg graft -c -U
264 grafting 4:9c233e8e184d "4"
265 grafting 4:9c233e8e184d "4"
265 grafting 3:4c60f11aa304 "3"
266 grafting 3:4c60f11aa304 "3"
266
267
267 Compare with original:
268 Compare with original:
268
269
269 $ hg diff -r 6
270 $ hg diff -r 6
270 $ hg status --rev 0:. -C
271 $ hg status --rev 0:. -C
271 M d
272 M d
272 M e
273 M e
273 A b
274 A b
274 a
275 a
275 A c
276 A c
276 a
277 a
277 R a
278 R a
278
279
279 View graph:
280 View graph:
280
281
281 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
282 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
282 @ test@11.draft: 3
283 @ test@11.draft: 3
283 |
284 |
284 o test@10.draft: 4
285 o test@10.draft: 4
285 |
286 |
286 o test@9.draft: 5
287 o test@9.draft: 5
287 |
288 |
288 o bar@8.draft: 1
289 o bar@8.draft: 1
289 |
290 |
290 o foo@7.draft: 2
291 o foo@7.draft: 2
291 |
292 |
292 | o test@6.secret: 6
293 | o test@6.secret: 6
293 | |\
294 | |\
294 | | o test@5.draft: 5
295 | | o test@5.draft: 5
295 | | |
296 | | |
296 | o | test@4.draft: 4
297 | o | test@4.draft: 4
297 | |/
298 | |/
298 | o baz@3.public: 3
299 | o baz@3.public: 3
299 | |
300 | |
300 | o test@2.public: 2
301 | o test@2.public: 2
301 | |
302 | |
302 | o bar@1.public: 1
303 | o bar@1.public: 1
303 |/
304 |/
304 o test@0.public: 0
305 o test@0.public: 0
305
306
306 Graft again onto another branch should preserve the original source
307 Graft again onto another branch should preserve the original source
307 $ hg up -q 0
308 $ hg up -q 0
308 $ echo 'g'>g
309 $ echo 'g'>g
309 $ hg add g
310 $ hg add g
310 $ hg ci -m 7
311 $ hg ci -m 7
311 created new head
312 created new head
312 $ hg graft 7
313 $ hg graft 7
313 grafting 7:ef0ef43d49e7 "2"
314 grafting 7:ef0ef43d49e7 "2"
314
315
315 $ hg log -r 7 --template '{rev}:{node}\n'
316 $ hg log -r 7 --template '{rev}:{node}\n'
316 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
317 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
317 $ hg log -r 2 --template '{rev}:{node}\n'
318 $ hg log -r 2 --template '{rev}:{node}\n'
318 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
319 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
319
320
320 $ hg log --debug -r tip
321 $ hg log --debug -r tip
321 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
322 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
322 tag: tip
323 tag: tip
323 phase: draft
324 phase: draft
324 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
325 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
325 parent: -1:0000000000000000000000000000000000000000
326 parent: -1:0000000000000000000000000000000000000000
326 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
327 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
327 user: foo
328 user: foo
328 date: Thu Jan 01 00:00:00 1970 +0000
329 date: Thu Jan 01 00:00:00 1970 +0000
329 files+: b
330 files+: b
330 files-: a
331 files-: a
331 extra: branch=default
332 extra: branch=default
332 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
333 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
333 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
334 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
334 description:
335 description:
335 2
336 2
336
337
337
338
338 Disallow grafting an already grafted cset onto its original branch
339 Disallow grafting an already grafted cset onto its original branch
339 $ hg up -q 6
340 $ hg up -q 6
340 $ hg graft 7
341 $ hg graft 7
341 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
342 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
342 [255]
343 [255]
343
344
344 $ hg extdiff --config extensions.extdiff= --patch -r 2 -r 13
345 $ hg extdiff --config extensions.extdiff= --patch -r 2 -r 13
345 --- */hg-5c095ad7e90f.patch * +0000 (glob)
346 --- */hg-5c095ad7e90f.patch * +0000 (glob)
346 +++ */hg-7a4785234d87.patch * +0000 (glob)
347 +++ */hg-7a4785234d87.patch * +0000 (glob)
347 @@ -1,18 +1,18 @@
348 @@ -1,18 +1,18 @@
348 # HG changeset patch
349 # HG changeset patch
349 -# User test
350 -# User test
350 +# User foo
351 +# User foo
351 # Date 0 0
352 # Date 0 0
352 # Thu Jan 01 00:00:00 1970 +0000
353 # Thu Jan 01 00:00:00 1970 +0000
353 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
354 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
354 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
355 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
355 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
356 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
356 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
357 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
357 2
358 2
358
359
359 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
360 -diff -r 5d205f8b35b6 -r 5c095ad7e90f a
360 +diff -r b592ea63bb0c -r 7a4785234d87 a
361 +diff -r b592ea63bb0c -r 7a4785234d87 a
361 --- a/a Thu Jan 01 00:00:00 1970 +0000
362 --- a/a Thu Jan 01 00:00:00 1970 +0000
362 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
363 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
363 @@ -1,1 +0,0 @@
364 @@ -1,1 +0,0 @@
364 --b
365 --b
365 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
366 -diff -r 5d205f8b35b6 -r 5c095ad7e90f b
366 +-a
367 +-a
367 +diff -r b592ea63bb0c -r 7a4785234d87 b
368 +diff -r b592ea63bb0c -r 7a4785234d87 b
368 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
369 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
369 +++ b/b Thu Jan 01 00:00:00 1970 +0000
370 +++ b/b Thu Jan 01 00:00:00 1970 +0000
370 @@ -0,0 +1,1 @@
371 @@ -0,0 +1,1 @@
371 -+b
372 -+b
372 ++a
373 ++a
373 [1]
374 [1]
374
375
375 $ hg extdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
376 $ hg extdiff --config extensions.extdiff= --patch -r 2 -r 13 -X .
376 --- */hg-5c095ad7e90f.patch * +0000 (glob)
377 --- */hg-5c095ad7e90f.patch * +0000 (glob)
377 +++ */hg-7a4785234d87.patch * +0000 (glob)
378 +++ */hg-7a4785234d87.patch * +0000 (glob)
378 @@ -1,8 +1,8 @@
379 @@ -1,8 +1,8 @@
379 # HG changeset patch
380 # HG changeset patch
380 -# User test
381 -# User test
381 +# User foo
382 +# User foo
382 # Date 0 0
383 # Date 0 0
383 # Thu Jan 01 00:00:00 1970 +0000
384 # Thu Jan 01 00:00:00 1970 +0000
384 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
385 -# Node ID 5c095ad7e90f871700f02dd1fa5012cb4498a2d4
385 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
386 -# Parent 5d205f8b35b66bc36375c9534ffd3237730e8f04
386 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
387 +# Node ID 7a4785234d87ec1aa420ed6b11afe40fa73e12a9
387 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
388 +# Parent b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
388 2
389 2
389
390
390 [1]
391 [1]
391
392
392 Disallow grafting already grafted csets with the same origin onto each other
393 Disallow grafting already grafted csets with the same origin onto each other
393 $ hg up -q 13
394 $ hg up -q 13
394 $ hg graft 2
395 $ hg graft 2
395 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
396 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
396 [255]
397 [255]
397 $ hg graft 7
398 $ hg graft 7
398 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
399 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
399 [255]
400 [255]
400
401
401 $ hg up -q 7
402 $ hg up -q 7
402 $ hg graft 2
403 $ hg graft 2
403 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
404 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
404 [255]
405 [255]
405 $ hg graft tip
406 $ hg graft tip
406 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
407 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
407 [255]
408 [255]
408
409
409 Graft with --log
410 Graft with --log
410
411
411 $ hg up -Cq 1
412 $ hg up -Cq 1
412 $ hg graft 3 --log -u foo
413 $ hg graft 3 --log -u foo
413 grafting 3:4c60f11aa304 "3"
414 grafting 3:4c60f11aa304 "3"
414 warning: can't find ancestor for 'c' copied from 'b'!
415 warning: can't find ancestor for 'c' copied from 'b'!
415 $ hg log --template '{rev} {parents} {desc}\n' -r tip
416 $ hg log --template '{rev} {parents} {desc}\n' -r tip
416 14 1:5d205f8b35b6 3
417 14 1:5d205f8b35b6 3
417 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
418 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
418
419
419 Resolve conflicted graft
420 Resolve conflicted graft
420 $ hg up -q 0
421 $ hg up -q 0
421 $ echo b > a
422 $ echo b > a
422 $ hg ci -m 8
423 $ hg ci -m 8
423 created new head
424 created new head
424 $ echo c > a
425 $ echo c > a
425 $ hg ci -m 9
426 $ hg ci -m 9
426 $ hg graft 1 --tool internal:fail
427 $ hg graft 1 --tool internal:fail
427 grafting 1:5d205f8b35b6 "1"
428 grafting 1:5d205f8b35b6 "1"
428 abort: unresolved conflicts, can't continue
429 abort: unresolved conflicts, can't continue
429 (use hg resolve and hg graft --continue)
430 (use hg resolve and hg graft --continue)
430 [255]
431 [255]
431 $ hg resolve --all
432 $ hg resolve --all
432 merging a
433 merging a
433 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
434 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
434 [1]
435 [1]
435 $ cat a
436 $ cat a
436 <<<<<<< local: aaa4406d4f0a - test: 9
437 <<<<<<< local: aaa4406d4f0a - test: 9
437 c
438 c
438 =======
439 =======
439 b
440 b
440 >>>>>>> other: 5d205f8b35b6 - bar: 1
441 >>>>>>> other: 5d205f8b35b6 - bar: 1
441 $ echo b > a
442 $ echo b > a
442 $ hg resolve -m a
443 $ hg resolve -m a
443 (no more unresolved files)
444 (no more unresolved files)
444 continue: hg graft --continue
445 continue: hg graft --continue
445 $ hg graft -c
446 $ hg graft -c
446 grafting 1:5d205f8b35b6 "1"
447 grafting 1:5d205f8b35b6 "1"
447 $ hg export tip --git
448 $ hg export tip --git
448 # HG changeset patch
449 # HG changeset patch
449 # User bar
450 # User bar
450 # Date 0 0
451 # Date 0 0
451 # Thu Jan 01 00:00:00 1970 +0000
452 # Thu Jan 01 00:00:00 1970 +0000
452 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
453 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
453 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
454 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
454 1
455 1
455
456
456 diff --git a/a b/a
457 diff --git a/a b/a
457 --- a/a
458 --- a/a
458 +++ b/a
459 +++ b/a
459 @@ -1,1 +1,1 @@
460 @@ -1,1 +1,1 @@
460 -c
461 -c
461 +b
462 +b
462
463
463 Resolve conflicted graft with rename
464 Resolve conflicted graft with rename
464 $ echo c > a
465 $ echo c > a
465 $ hg ci -m 10
466 $ hg ci -m 10
466 $ hg graft 2 --tool internal:fail
467 $ hg graft 2 --tool internal:fail
467 grafting 2:5c095ad7e90f "2"
468 grafting 2:5c095ad7e90f "2"
468 abort: unresolved conflicts, can't continue
469 abort: unresolved conflicts, can't continue
469 (use hg resolve and hg graft --continue)
470 (use hg resolve and hg graft --continue)
470 [255]
471 [255]
471 $ hg resolve --all
472 $ hg resolve --all
472 merging a and b to b
473 merging a and b to b
473 (no more unresolved files)
474 (no more unresolved files)
474 continue: hg graft --continue
475 continue: hg graft --continue
475 $ hg graft -c
476 $ hg graft -c
476 grafting 2:5c095ad7e90f "2"
477 grafting 2:5c095ad7e90f "2"
477 $ hg export tip --git
478 $ hg export tip --git
478 # HG changeset patch
479 # HG changeset patch
479 # User test
480 # User test
480 # Date 0 0
481 # Date 0 0
481 # Thu Jan 01 00:00:00 1970 +0000
482 # Thu Jan 01 00:00:00 1970 +0000
482 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
483 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
483 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
484 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
484 2
485 2
485
486
486 diff --git a/a b/b
487 diff --git a/a b/b
487 rename from a
488 rename from a
488 rename to b
489 rename to b
489
490
490 Test simple origin(), with and without args
491 Test simple origin(), with and without args
491 $ hg log -r 'origin()'
492 $ hg log -r 'origin()'
492 changeset: 1:5d205f8b35b6
493 changeset: 1:5d205f8b35b6
493 user: bar
494 user: bar
494 date: Thu Jan 01 00:00:00 1970 +0000
495 date: Thu Jan 01 00:00:00 1970 +0000
495 summary: 1
496 summary: 1
496
497
497 changeset: 2:5c095ad7e90f
498 changeset: 2:5c095ad7e90f
498 user: test
499 user: test
499 date: Thu Jan 01 00:00:00 1970 +0000
500 date: Thu Jan 01 00:00:00 1970 +0000
500 summary: 2
501 summary: 2
501
502
502 changeset: 3:4c60f11aa304
503 changeset: 3:4c60f11aa304
503 user: baz
504 user: baz
504 date: Thu Jan 01 00:00:00 1970 +0000
505 date: Thu Jan 01 00:00:00 1970 +0000
505 summary: 3
506 summary: 3
506
507
507 changeset: 4:9c233e8e184d
508 changeset: 4:9c233e8e184d
508 user: test
509 user: test
509 date: Thu Jan 01 00:00:00 1970 +0000
510 date: Thu Jan 01 00:00:00 1970 +0000
510 summary: 4
511 summary: 4
511
512
512 changeset: 5:97f8bfe72746
513 changeset: 5:97f8bfe72746
513 branch: stable
514 branch: stable
514 parent: 3:4c60f11aa304
515 parent: 3:4c60f11aa304
515 user: test
516 user: test
516 date: Thu Jan 01 00:00:00 1970 +0000
517 date: Thu Jan 01 00:00:00 1970 +0000
517 summary: 5
518 summary: 5
518
519
519 $ hg log -r 'origin(7)'
520 $ hg log -r 'origin(7)'
520 changeset: 2:5c095ad7e90f
521 changeset: 2:5c095ad7e90f
521 user: test
522 user: test
522 date: Thu Jan 01 00:00:00 1970 +0000
523 date: Thu Jan 01 00:00:00 1970 +0000
523 summary: 2
524 summary: 2
524
525
525 Now transplant a graft to test following through copies
526 Now transplant a graft to test following through copies
526 $ hg up -q 0
527 $ hg up -q 0
527 $ hg branch -q dev
528 $ hg branch -q dev
528 $ hg ci -qm "dev branch"
529 $ hg ci -qm "dev branch"
529 $ hg --config extensions.transplant= transplant -q 7
530 $ hg --config extensions.transplant= transplant -q 7
530 $ hg log -r 'origin(.)'
531 $ hg log -r 'origin(.)'
531 changeset: 2:5c095ad7e90f
532 changeset: 2:5c095ad7e90f
532 user: test
533 user: test
533 date: Thu Jan 01 00:00:00 1970 +0000
534 date: Thu Jan 01 00:00:00 1970 +0000
534 summary: 2
535 summary: 2
535
536
536 Test that the graft and transplant markers in extra are converted, allowing
537 Test that the graft and transplant markers in extra are converted, allowing
537 origin() to still work. Note that these recheck the immediately preceeding two
538 origin() to still work. Note that these recheck the immediately preceeding two
538 tests.
539 tests.
539 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
540 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
540
541
541 The graft case
542 The graft case
542 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
543 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
543 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
544 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
544 branch=default
545 branch=default
545 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
546 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
546 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
547 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
547 $ hg -R ../converted log -r 'origin(7)'
548 $ hg -R ../converted log -r 'origin(7)'
548 changeset: 2:e0213322b2c1
549 changeset: 2:e0213322b2c1
549 user: test
550 user: test
550 date: Thu Jan 01 00:00:00 1970 +0000
551 date: Thu Jan 01 00:00:00 1970 +0000
551 summary: 2
552 summary: 2
552
553
553 Test that template correctly expands more than one 'extra' (issue4362), and that
554 Test that template correctly expands more than one 'extra' (issue4362), and that
554 'intermediate-source' is converted.
555 'intermediate-source' is converted.
555 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
556 $ hg -R ../converted log -r 13 --template "{extras % ' Extra: {extra}\n'}"
556 Extra: branch=default
557 Extra: branch=default
557 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
558 Extra: convert_revision=7a4785234d87ec1aa420ed6b11afe40fa73e12a9
558 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
559 Extra: intermediate-source=7ae846e9111fc8f57745634250c7b9ac0a60689b
559 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
560 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
560
561
561 The transplant case
562 The transplant case
562 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
563 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
563 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
564 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
564 branch=dev
565 branch=dev
565 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
566 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
566 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
567 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
567 `h\x9b (esc)
568 `h\x9b (esc)
568 $ hg -R ../converted log -r 'origin(tip)'
569 $ hg -R ../converted log -r 'origin(tip)'
569 changeset: 2:e0213322b2c1
570 changeset: 2:e0213322b2c1
570 user: test
571 user: test
571 date: Thu Jan 01 00:00:00 1970 +0000
572 date: Thu Jan 01 00:00:00 1970 +0000
572 summary: 2
573 summary: 2
573
574
574
575
575 Test simple destination
576 Test simple destination
576 $ hg log -r 'destination()'
577 $ hg log -r 'destination()'
577 changeset: 7:ef0ef43d49e7
578 changeset: 7:ef0ef43d49e7
578 parent: 0:68795b066622
579 parent: 0:68795b066622
579 user: foo
580 user: foo
580 date: Thu Jan 01 00:00:00 1970 +0000
581 date: Thu Jan 01 00:00:00 1970 +0000
581 summary: 2
582 summary: 2
582
583
583 changeset: 8:6b9e5368ca4e
584 changeset: 8:6b9e5368ca4e
584 user: bar
585 user: bar
585 date: Thu Jan 01 00:00:00 1970 +0000
586 date: Thu Jan 01 00:00:00 1970 +0000
586 summary: 1
587 summary: 1
587
588
588 changeset: 9:1905859650ec
589 changeset: 9:1905859650ec
589 user: test
590 user: test
590 date: Thu Jan 01 00:00:00 1970 +0000
591 date: Thu Jan 01 00:00:00 1970 +0000
591 summary: 5
592 summary: 5
592
593
593 changeset: 10:52dc0b4c6907
594 changeset: 10:52dc0b4c6907
594 user: test
595 user: test
595 date: Thu Jan 01 00:00:00 1970 +0000
596 date: Thu Jan 01 00:00:00 1970 +0000
596 summary: 4
597 summary: 4
597
598
598 changeset: 11:882b35362a6b
599 changeset: 11:882b35362a6b
599 user: test
600 user: test
600 date: Thu Jan 01 00:00:00 1970 +0000
601 date: Thu Jan 01 00:00:00 1970 +0000
601 summary: 3
602 summary: 3
602
603
603 changeset: 13:7a4785234d87
604 changeset: 13:7a4785234d87
604 user: foo
605 user: foo
605 date: Thu Jan 01 00:00:00 1970 +0000
606 date: Thu Jan 01 00:00:00 1970 +0000
606 summary: 2
607 summary: 2
607
608
608 changeset: 14:f64defefacee
609 changeset: 14:f64defefacee
609 parent: 1:5d205f8b35b6
610 parent: 1:5d205f8b35b6
610 user: foo
611 user: foo
611 date: Thu Jan 01 00:00:00 1970 +0000
612 date: Thu Jan 01 00:00:00 1970 +0000
612 summary: 3
613 summary: 3
613
614
614 changeset: 17:f67661df0c48
615 changeset: 17:f67661df0c48
615 user: bar
616 user: bar
616 date: Thu Jan 01 00:00:00 1970 +0000
617 date: Thu Jan 01 00:00:00 1970 +0000
617 summary: 1
618 summary: 1
618
619
619 changeset: 19:9627f653b421
620 changeset: 19:9627f653b421
620 user: test
621 user: test
621 date: Thu Jan 01 00:00:00 1970 +0000
622 date: Thu Jan 01 00:00:00 1970 +0000
622 summary: 2
623 summary: 2
623
624
624 changeset: 21:7e61b508e709
625 changeset: 21:7e61b508e709
625 branch: dev
626 branch: dev
626 tag: tip
627 tag: tip
627 user: foo
628 user: foo
628 date: Thu Jan 01 00:00:00 1970 +0000
629 date: Thu Jan 01 00:00:00 1970 +0000
629 summary: 2
630 summary: 2
630
631
631 $ hg log -r 'destination(2)'
632 $ hg log -r 'destination(2)'
632 changeset: 7:ef0ef43d49e7
633 changeset: 7:ef0ef43d49e7
633 parent: 0:68795b066622
634 parent: 0:68795b066622
634 user: foo
635 user: foo
635 date: Thu Jan 01 00:00:00 1970 +0000
636 date: Thu Jan 01 00:00:00 1970 +0000
636 summary: 2
637 summary: 2
637
638
638 changeset: 13:7a4785234d87
639 changeset: 13:7a4785234d87
639 user: foo
640 user: foo
640 date: Thu Jan 01 00:00:00 1970 +0000
641 date: Thu Jan 01 00:00:00 1970 +0000
641 summary: 2
642 summary: 2
642
643
643 changeset: 19:9627f653b421
644 changeset: 19:9627f653b421
644 user: test
645 user: test
645 date: Thu Jan 01 00:00:00 1970 +0000
646 date: Thu Jan 01 00:00:00 1970 +0000
646 summary: 2
647 summary: 2
647
648
648 changeset: 21:7e61b508e709
649 changeset: 21:7e61b508e709
649 branch: dev
650 branch: dev
650 tag: tip
651 tag: tip
651 user: foo
652 user: foo
652 date: Thu Jan 01 00:00:00 1970 +0000
653 date: Thu Jan 01 00:00:00 1970 +0000
653 summary: 2
654 summary: 2
654
655
655 Transplants of grafts can find a destination...
656 Transplants of grafts can find a destination...
656 $ hg log -r 'destination(7)'
657 $ hg log -r 'destination(7)'
657 changeset: 21:7e61b508e709
658 changeset: 21:7e61b508e709
658 branch: dev
659 branch: dev
659 tag: tip
660 tag: tip
660 user: foo
661 user: foo
661 date: Thu Jan 01 00:00:00 1970 +0000
662 date: Thu Jan 01 00:00:00 1970 +0000
662 summary: 2
663 summary: 2
663
664
664 ... grafts of grafts unfortunately can't
665 ... grafts of grafts unfortunately can't
665 $ hg graft -q 13
666 $ hg graft -q 13
666 warning: can't find ancestor for 'b' copied from 'a'!
667 warning: can't find ancestor for 'b' copied from 'a'!
667 $ hg log -r 'destination(13)'
668 $ hg log -r 'destination(13)'
668 All copies of a cset
669 All copies of a cset
669 $ hg log -r 'origin(13) or destination(origin(13))'
670 $ hg log -r 'origin(13) or destination(origin(13))'
670 changeset: 2:5c095ad7e90f
671 changeset: 2:5c095ad7e90f
671 user: test
672 user: test
672 date: Thu Jan 01 00:00:00 1970 +0000
673 date: Thu Jan 01 00:00:00 1970 +0000
673 summary: 2
674 summary: 2
674
675
675 changeset: 7:ef0ef43d49e7
676 changeset: 7:ef0ef43d49e7
676 parent: 0:68795b066622
677 parent: 0:68795b066622
677 user: foo
678 user: foo
678 date: Thu Jan 01 00:00:00 1970 +0000
679 date: Thu Jan 01 00:00:00 1970 +0000
679 summary: 2
680 summary: 2
680
681
681 changeset: 13:7a4785234d87
682 changeset: 13:7a4785234d87
682 user: foo
683 user: foo
683 date: Thu Jan 01 00:00:00 1970 +0000
684 date: Thu Jan 01 00:00:00 1970 +0000
684 summary: 2
685 summary: 2
685
686
686 changeset: 19:9627f653b421
687 changeset: 19:9627f653b421
687 user: test
688 user: test
688 date: Thu Jan 01 00:00:00 1970 +0000
689 date: Thu Jan 01 00:00:00 1970 +0000
689 summary: 2
690 summary: 2
690
691
691 changeset: 21:7e61b508e709
692 changeset: 21:7e61b508e709
692 branch: dev
693 branch: dev
693 user: foo
694 user: foo
694 date: Thu Jan 01 00:00:00 1970 +0000
695 date: Thu Jan 01 00:00:00 1970 +0000
695 summary: 2
696 summary: 2
696
697
697 changeset: 22:d1cb6591fa4b
698 changeset: 22:d1cb6591fa4b
698 branch: dev
699 branch: dev
699 tag: tip
700 tag: tip
700 user: foo
701 user: foo
701 date: Thu Jan 01 00:00:00 1970 +0000
702 date: Thu Jan 01 00:00:00 1970 +0000
702 summary: 2
703 summary: 2
703
704
704
705
705 graft works on complex revset
706 graft works on complex revset
706
707
707 $ hg graft 'origin(13) or destination(origin(13))'
708 $ hg graft 'origin(13) or destination(origin(13))'
708 skipping ancestor revision 21:7e61b508e709
709 skipping ancestor revision 21:7e61b508e709
709 skipping ancestor revision 22:d1cb6591fa4b
710 skipping ancestor revision 22:d1cb6591fa4b
710 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
711 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
711 grafting 7:ef0ef43d49e7 "2"
712 grafting 7:ef0ef43d49e7 "2"
712 warning: can't find ancestor for 'b' copied from 'a'!
713 warning: can't find ancestor for 'b' copied from 'a'!
713 grafting 13:7a4785234d87 "2"
714 grafting 13:7a4785234d87 "2"
714 warning: can't find ancestor for 'b' copied from 'a'!
715 warning: can't find ancestor for 'b' copied from 'a'!
715 grafting 19:9627f653b421 "2"
716 grafting 19:9627f653b421 "2"
716 merging b
717 merging b
717 warning: can't find ancestor for 'b' copied from 'a'!
718 warning: can't find ancestor for 'b' copied from 'a'!
718
719
719 graft with --force (still doesn't graft merges)
720 graft with --force (still doesn't graft merges)
720
721
721 $ hg graft 19 0 6
722 $ hg graft 19 0 6
722 skipping ungraftable merge revision 6
723 skipping ungraftable merge revision 6
723 skipping ancestor revision 0:68795b066622
724 skipping ancestor revision 0:68795b066622
724 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
725 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
725 [255]
726 [255]
726 $ hg graft 19 0 6 --force
727 $ hg graft 19 0 6 --force
727 skipping ungraftable merge revision 6
728 skipping ungraftable merge revision 6
728 grafting 19:9627f653b421 "2"
729 grafting 19:9627f653b421 "2"
729 merging b
730 merging b
730 warning: can't find ancestor for 'b' copied from 'a'!
731 warning: can't find ancestor for 'b' copied from 'a'!
731 grafting 0:68795b066622 "0"
732 grafting 0:68795b066622 "0"
732
733
733 graft --force after backout
734 graft --force after backout
734
735
735 $ echo abc > a
736 $ echo abc > a
736 $ hg ci -m 28
737 $ hg ci -m 28
737 $ hg backout 28
738 $ hg backout 28
738 reverting a
739 reverting a
739 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
740 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
740 $ hg graft 28
741 $ hg graft 28
741 skipping ancestor revision 28:50a516bb8b57
742 skipping ancestor revision 28:50a516bb8b57
742 [255]
743 [255]
743 $ hg graft 28 --force
744 $ hg graft 28 --force
744 grafting 28:50a516bb8b57 "28"
745 grafting 28:50a516bb8b57 "28"
745 merging a
746 merging a
746 $ cat a
747 $ cat a
747 abc
748 abc
748
749
749 graft --continue after --force
750 graft --continue after --force
750
751
751 $ echo def > a
752 $ echo def > a
752 $ hg ci -m 31
753 $ hg ci -m 31
753 $ hg graft 28 --force --tool internal:fail
754 $ hg graft 28 --force --tool internal:fail
754 grafting 28:50a516bb8b57 "28"
755 grafting 28:50a516bb8b57 "28"
755 abort: unresolved conflicts, can't continue
756 abort: unresolved conflicts, can't continue
756 (use hg resolve and hg graft --continue)
757 (use hg resolve and hg graft --continue)
757 [255]
758 [255]
758 $ hg resolve --all
759 $ hg resolve --all
759 merging a
760 merging a
760 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
761 warning: conflicts while merging a! (edit, then use 'hg resolve --mark')
761 [1]
762 [1]
762 $ echo abc > a
763 $ echo abc > a
763 $ hg resolve -m a
764 $ hg resolve -m a
764 (no more unresolved files)
765 (no more unresolved files)
765 continue: hg graft --continue
766 continue: hg graft --continue
766 $ hg graft -c
767 $ hg graft -c
767 grafting 28:50a516bb8b57 "28"
768 grafting 28:50a516bb8b57 "28"
768 $ cat a
769 $ cat a
769 abc
770 abc
770
771
771 Continue testing same origin policy, using revision numbers from test above
772 Continue testing same origin policy, using revision numbers from test above
772 but do some destructive editing of the repo:
773 but do some destructive editing of the repo:
773
774
774 $ hg up -qC 7
775 $ hg up -qC 7
775 $ hg tag -l -r 13 tmp
776 $ hg tag -l -r 13 tmp
776 $ hg --config extensions.strip= strip 2
777 $ hg --config extensions.strip= strip 2
777 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
778 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
778 $ hg graft tmp
779 $ hg graft tmp
779 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
780 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
780 [255]
781 [255]
781
782
782 Empty graft
783 Empty graft
783
784
784 $ hg up -qr 26
785 $ hg up -qr 26
785 $ hg tag -f something
786 $ hg tag -f something
786 $ hg graft -qr 27
787 $ hg graft -qr 27
787 $ hg graft -f 27
788 $ hg graft -f 27
788 grafting 27:ed6c7e54e319 "28"
789 grafting 27:ed6c7e54e319 "28"
789 note: graft of 27:ed6c7e54e319 created no changes to commit
790 note: graft of 27:ed6c7e54e319 created no changes to commit
790
791
791 $ cd ..
792 $ cd ..
792
793
793 Graft to duplicate a commit
794 Graft to duplicate a commit
794
795
795 $ hg init graftsibling
796 $ hg init graftsibling
796 $ cd graftsibling
797 $ cd graftsibling
797 $ touch a
798 $ touch a
798 $ hg commit -qAm a
799 $ hg commit -qAm a
799 $ touch b
800 $ touch b
800 $ hg commit -qAm b
801 $ hg commit -qAm b
801 $ hg log -G -T '{rev}\n'
802 $ hg log -G -T '{rev}\n'
802 @ 1
803 @ 1
803 |
804 |
804 o 0
805 o 0
805
806
806 $ hg up -q 0
807 $ hg up -q 0
807 $ hg graft -r 1
808 $ hg graft -r 1
808 grafting 1:0e067c57feba "b" (tip)
809 grafting 1:0e067c57feba "b" (tip)
809 $ hg log -G -T '{rev}\n'
810 $ hg log -G -T '{rev}\n'
810 @ 2
811 @ 2
811 |
812 |
812 | o 1
813 | o 1
813 |/
814 |/
814 o 0
815 o 0
815
816
816 Graft to duplicate a commit twice
817 Graft to duplicate a commit twice
817
818
818 $ hg up -q 0
819 $ hg up -q 0
819 $ hg graft -r 2
820 $ hg graft -r 2
820 grafting 2:044ec77f6389 "b" (tip)
821 grafting 2:044ec77f6389 "b" (tip)
821 $ hg log -G -T '{rev}\n'
822 $ hg log -G -T '{rev}\n'
822 @ 3
823 @ 3
823 |
824 |
824 | o 2
825 | o 2
825 |/
826 |/
826 | o 1
827 | o 1
827 |/
828 |/
828 o 0
829 o 0
829
830
General Comments 0
You need to be logged in to leave comments. Login now