##// END OF EJS Templates
import: simplify status reporting logic (and make it more I18N-friendly)...
Greg Ward -
r15194:0705f2ac default
parent child Browse files
Show More
@@ -1,5446 +1,5443 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil
19 import random, setdiscovery, treediscovery, dagutil
20
20
21 table = {}
21 table = {}
22
22
23 command = cmdutil.command(table)
23 command = cmdutil.command(table)
24
24
25 # common command options
25 # common command options
26
26
27 globalopts = [
27 globalopts = [
28 ('R', 'repository', '',
28 ('R', 'repository', '',
29 _('repository root directory or name of overlay bundle file'),
29 _('repository root directory or name of overlay bundle file'),
30 _('REPO')),
30 _('REPO')),
31 ('', 'cwd', '',
31 ('', 'cwd', '',
32 _('change working directory'), _('DIR')),
32 _('change working directory'), _('DIR')),
33 ('y', 'noninteractive', None,
33 ('y', 'noninteractive', None,
34 _('do not prompt, automatically pick the first choice for all prompts')),
34 _('do not prompt, automatically pick the first choice for all prompts')),
35 ('q', 'quiet', None, _('suppress output')),
35 ('q', 'quiet', None, _('suppress output')),
36 ('v', 'verbose', None, _('enable additional output')),
36 ('v', 'verbose', None, _('enable additional output')),
37 ('', 'config', [],
37 ('', 'config', [],
38 _('set/override config option (use \'section.name=value\')'),
38 _('set/override config option (use \'section.name=value\')'),
39 _('CONFIG')),
39 _('CONFIG')),
40 ('', 'debug', None, _('enable debugging output')),
40 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debugger', None, _('start debugger')),
41 ('', 'debugger', None, _('start debugger')),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 _('ENCODE')),
43 _('ENCODE')),
44 ('', 'encodingmode', encoding.encodingmode,
44 ('', 'encodingmode', encoding.encodingmode,
45 _('set the charset encoding mode'), _('MODE')),
45 _('set the charset encoding mode'), _('MODE')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
46 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'time', None, _('time how long the command takes')),
47 ('', 'time', None, _('time how long the command takes')),
48 ('', 'profile', None, _('print command execution profile')),
48 ('', 'profile', None, _('print command execution profile')),
49 ('', 'version', None, _('output version information and exit')),
49 ('', 'version', None, _('output version information and exit')),
50 ('h', 'help', None, _('display help and exit')),
50 ('h', 'help', None, _('display help and exit')),
51 ]
51 ]
52
52
53 dryrunopts = [('n', 'dry-run', None,
53 dryrunopts = [('n', 'dry-run', None,
54 _('do not perform actions, just print output'))]
54 _('do not perform actions, just print output'))]
55
55
56 remoteopts = [
56 remoteopts = [
57 ('e', 'ssh', '',
57 ('e', 'ssh', '',
58 _('specify ssh command to use'), _('CMD')),
58 _('specify ssh command to use'), _('CMD')),
59 ('', 'remotecmd', '',
59 ('', 'remotecmd', '',
60 _('specify hg command to run on the remote side'), _('CMD')),
60 _('specify hg command to run on the remote side'), _('CMD')),
61 ('', 'insecure', None,
61 ('', 'insecure', None,
62 _('do not verify server certificate (ignoring web.cacerts config)')),
62 _('do not verify server certificate (ignoring web.cacerts config)')),
63 ]
63 ]
64
64
65 walkopts = [
65 walkopts = [
66 ('I', 'include', [],
66 ('I', 'include', [],
67 _('include names matching the given patterns'), _('PATTERN')),
67 _('include names matching the given patterns'), _('PATTERN')),
68 ('X', 'exclude', [],
68 ('X', 'exclude', [],
69 _('exclude names matching the given patterns'), _('PATTERN')),
69 _('exclude names matching the given patterns'), _('PATTERN')),
70 ]
70 ]
71
71
72 commitopts = [
72 commitopts = [
73 ('m', 'message', '',
73 ('m', 'message', '',
74 _('use text as commit message'), _('TEXT')),
74 _('use text as commit message'), _('TEXT')),
75 ('l', 'logfile', '',
75 ('l', 'logfile', '',
76 _('read commit message from file'), _('FILE')),
76 _('read commit message from file'), _('FILE')),
77 ]
77 ]
78
78
79 commitopts2 = [
79 commitopts2 = [
80 ('d', 'date', '',
80 ('d', 'date', '',
81 _('record the specified date as commit date'), _('DATE')),
81 _('record the specified date as commit date'), _('DATE')),
82 ('u', 'user', '',
82 ('u', 'user', '',
83 _('record the specified user as committer'), _('USER')),
83 _('record the specified user as committer'), _('USER')),
84 ]
84 ]
85
85
86 templateopts = [
86 templateopts = [
87 ('', 'style', '',
87 ('', 'style', '',
88 _('display using template map file'), _('STYLE')),
88 _('display using template map file'), _('STYLE')),
89 ('', 'template', '',
89 ('', 'template', '',
90 _('display with template'), _('TEMPLATE')),
90 _('display with template'), _('TEMPLATE')),
91 ]
91 ]
92
92
93 logopts = [
93 logopts = [
94 ('p', 'patch', None, _('show patch')),
94 ('p', 'patch', None, _('show patch')),
95 ('g', 'git', None, _('use git extended diff format')),
95 ('g', 'git', None, _('use git extended diff format')),
96 ('l', 'limit', '',
96 ('l', 'limit', '',
97 _('limit number of changes displayed'), _('NUM')),
97 _('limit number of changes displayed'), _('NUM')),
98 ('M', 'no-merges', None, _('do not show merges')),
98 ('M', 'no-merges', None, _('do not show merges')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
99 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ] + templateopts
100 ] + templateopts
101
101
102 diffopts = [
102 diffopts = [
103 ('a', 'text', None, _('treat all files as text')),
103 ('a', 'text', None, _('treat all files as text')),
104 ('g', 'git', None, _('use git extended diff format')),
104 ('g', 'git', None, _('use git extended diff format')),
105 ('', 'nodates', None, _('omit dates from diff headers'))
105 ('', 'nodates', None, _('omit dates from diff headers'))
106 ]
106 ]
107
107
108 diffopts2 = [
108 diffopts2 = [
109 ('p', 'show-function', None, _('show which function each change is in')),
109 ('p', 'show-function', None, _('show which function each change is in')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
111 ('w', 'ignore-all-space', None,
111 ('w', 'ignore-all-space', None,
112 _('ignore white space when comparing lines')),
112 _('ignore white space when comparing lines')),
113 ('b', 'ignore-space-change', None,
113 ('b', 'ignore-space-change', None,
114 _('ignore changes in the amount of white space')),
114 _('ignore changes in the amount of white space')),
115 ('B', 'ignore-blank-lines', None,
115 ('B', 'ignore-blank-lines', None,
116 _('ignore changes whose lines are all blank')),
116 _('ignore changes whose lines are all blank')),
117 ('U', 'unified', '',
117 ('U', 'unified', '',
118 _('number of lines of context to show'), _('NUM')),
118 _('number of lines of context to show'), _('NUM')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
119 ('', 'stat', None, _('output diffstat-style summary of changes')),
120 ]
120 ]
121
121
122 mergetoolopts = [
122 mergetoolopts = [
123 ('t', 'tool', '', _('specify merge tool')),
123 ('t', 'tool', '', _('specify merge tool')),
124 ]
124 ]
125
125
126 similarityopts = [
126 similarityopts = [
127 ('s', 'similarity', '',
127 ('s', 'similarity', '',
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
129 ]
129 ]
130
130
131 subrepoopts = [
131 subrepoopts = [
132 ('S', 'subrepos', None,
132 ('S', 'subrepos', None,
133 _('recurse into subrepositories'))
133 _('recurse into subrepositories'))
134 ]
134 ]
135
135
136 # Commands start here, listed alphabetically
136 # Commands start here, listed alphabetically
137
137
138 @command('^add',
138 @command('^add',
139 walkopts + subrepoopts + dryrunopts,
139 walkopts + subrepoopts + dryrunopts,
140 _('[OPTION]... [FILE]...'))
140 _('[OPTION]... [FILE]...'))
141 def add(ui, repo, *pats, **opts):
141 def add(ui, repo, *pats, **opts):
142 """add the specified files on the next commit
142 """add the specified files on the next commit
143
143
144 Schedule files to be version controlled and added to the
144 Schedule files to be version controlled and added to the
145 repository.
145 repository.
146
146
147 The files will be added to the repository at the next commit. To
147 The files will be added to the repository at the next commit. To
148 undo an add before that, see :hg:`forget`.
148 undo an add before that, see :hg:`forget`.
149
149
150 If no names are given, add all files to the repository.
150 If no names are given, add all files to the repository.
151
151
152 .. container:: verbose
152 .. container:: verbose
153
153
154 An example showing how new (unknown) files are added
154 An example showing how new (unknown) files are added
155 automatically by :hg:`add`::
155 automatically by :hg:`add`::
156
156
157 $ ls
157 $ ls
158 foo.c
158 foo.c
159 $ hg status
159 $ hg status
160 ? foo.c
160 ? foo.c
161 $ hg add
161 $ hg add
162 adding foo.c
162 adding foo.c
163 $ hg status
163 $ hg status
164 A foo.c
164 A foo.c
165
165
166 Returns 0 if all files are successfully added.
166 Returns 0 if all files are successfully added.
167 """
167 """
168
168
169 m = scmutil.match(repo[None], pats, opts)
169 m = scmutil.match(repo[None], pats, opts)
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
171 opts.get('subrepos'), prefix="")
171 opts.get('subrepos'), prefix="")
172 return rejected and 1 or 0
172 return rejected and 1 or 0
173
173
174 @command('addremove',
174 @command('addremove',
175 similarityopts + walkopts + dryrunopts,
175 similarityopts + walkopts + dryrunopts,
176 _('[OPTION]... [FILE]...'))
176 _('[OPTION]... [FILE]...'))
177 def addremove(ui, repo, *pats, **opts):
177 def addremove(ui, repo, *pats, **opts):
178 """add all new files, delete all missing files
178 """add all new files, delete all missing files
179
179
180 Add all new files and remove all missing files from the
180 Add all new files and remove all missing files from the
181 repository.
181 repository.
182
182
183 New files are ignored if they match any of the patterns in
183 New files are ignored if they match any of the patterns in
184 ``.hgignore``. As with add, these changes take effect at the next
184 ``.hgignore``. As with add, these changes take effect at the next
185 commit.
185 commit.
186
186
187 Use the -s/--similarity option to detect renamed files. With a
187 Use the -s/--similarity option to detect renamed files. With a
188 parameter greater than 0, this compares every removed file with
188 parameter greater than 0, this compares every removed file with
189 every added file and records those similar enough as renames. This
189 every added file and records those similar enough as renames. This
190 option takes a percentage between 0 (disabled) and 100 (files must
190 option takes a percentage between 0 (disabled) and 100 (files must
191 be identical) as its parameter. Detecting renamed files this way
191 be identical) as its parameter. Detecting renamed files this way
192 can be expensive. After using this option, :hg:`status -C` can be
192 can be expensive. After using this option, :hg:`status -C` can be
193 used to check which files were identified as moved or renamed.
193 used to check which files were identified as moved or renamed.
194
194
195 Returns 0 if all files are successfully added.
195 Returns 0 if all files are successfully added.
196 """
196 """
197 try:
197 try:
198 sim = float(opts.get('similarity') or 100)
198 sim = float(opts.get('similarity') or 100)
199 except ValueError:
199 except ValueError:
200 raise util.Abort(_('similarity must be a number'))
200 raise util.Abort(_('similarity must be a number'))
201 if sim < 0 or sim > 100:
201 if sim < 0 or sim > 100:
202 raise util.Abort(_('similarity must be between 0 and 100'))
202 raise util.Abort(_('similarity must be between 0 and 100'))
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
204
204
205 @command('^annotate|blame',
205 @command('^annotate|blame',
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
207 ('', 'follow', None,
207 ('', 'follow', None,
208 _('follow copies/renames and list the filename (DEPRECATED)')),
208 _('follow copies/renames and list the filename (DEPRECATED)')),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
209 ('', 'no-follow', None, _("don't follow copies and renames")),
210 ('a', 'text', None, _('treat all files as text')),
210 ('a', 'text', None, _('treat all files as text')),
211 ('u', 'user', None, _('list the author (long with -v)')),
211 ('u', 'user', None, _('list the author (long with -v)')),
212 ('f', 'file', None, _('list the filename')),
212 ('f', 'file', None, _('list the filename')),
213 ('d', 'date', None, _('list the date (short with -q)')),
213 ('d', 'date', None, _('list the date (short with -q)')),
214 ('n', 'number', None, _('list the revision number (default)')),
214 ('n', 'number', None, _('list the revision number (default)')),
215 ('c', 'changeset', None, _('list the changeset')),
215 ('c', 'changeset', None, _('list the changeset')),
216 ('l', 'line-number', None, _('show line number at the first appearance'))
216 ('l', 'line-number', None, _('show line number at the first appearance'))
217 ] + walkopts,
217 ] + walkopts,
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
219 def annotate(ui, repo, *pats, **opts):
219 def annotate(ui, repo, *pats, **opts):
220 """show changeset information by line for each file
220 """show changeset information by line for each file
221
221
222 List changes in files, showing the revision id responsible for
222 List changes in files, showing the revision id responsible for
223 each line
223 each line
224
224
225 This command is useful for discovering when a change was made and
225 This command is useful for discovering when a change was made and
226 by whom.
226 by whom.
227
227
228 Without the -a/--text option, annotate will avoid processing files
228 Without the -a/--text option, annotate will avoid processing files
229 it detects as binary. With -a, annotate will annotate the file
229 it detects as binary. With -a, annotate will annotate the file
230 anyway, although the results will probably be neither useful
230 anyway, although the results will probably be neither useful
231 nor desirable.
231 nor desirable.
232
232
233 Returns 0 on success.
233 Returns 0 on success.
234 """
234 """
235 if opts.get('follow'):
235 if opts.get('follow'):
236 # --follow is deprecated and now just an alias for -f/--file
236 # --follow is deprecated and now just an alias for -f/--file
237 # to mimic the behavior of Mercurial before version 1.5
237 # to mimic the behavior of Mercurial before version 1.5
238 opts['file'] = True
238 opts['file'] = True
239
239
240 datefunc = ui.quiet and util.shortdate or util.datestr
240 datefunc = ui.quiet and util.shortdate or util.datestr
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
242
242
243 if not pats:
243 if not pats:
244 raise util.Abort(_('at least one filename or pattern is required'))
244 raise util.Abort(_('at least one filename or pattern is required'))
245
245
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
247 ('number', ' ', lambda x: str(x[0].rev())),
247 ('number', ' ', lambda x: str(x[0].rev())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
248 ('changeset', ' ', lambda x: short(x[0].node())),
249 ('date', ' ', getdate),
249 ('date', ' ', getdate),
250 ('file', ' ', lambda x: x[0].path()),
250 ('file', ' ', lambda x: x[0].path()),
251 ('line_number', ':', lambda x: str(x[1])),
251 ('line_number', ':', lambda x: str(x[1])),
252 ]
252 ]
253
253
254 if (not opts.get('user') and not opts.get('changeset')
254 if (not opts.get('user') and not opts.get('changeset')
255 and not opts.get('date') and not opts.get('file')):
255 and not opts.get('date') and not opts.get('file')):
256 opts['number'] = True
256 opts['number'] = True
257
257
258 linenumber = opts.get('line_number') is not None
258 linenumber = opts.get('line_number') is not None
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
260 raise util.Abort(_('at least one of -n/-c is required for -l'))
261
261
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
264
264
265 def bad(x, y):
265 def bad(x, y):
266 raise util.Abort("%s: %s" % (x, y))
266 raise util.Abort("%s: %s" % (x, y))
267
267
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
268 ctx = scmutil.revsingle(repo, opts.get('rev'))
269 m = scmutil.match(ctx, pats, opts)
269 m = scmutil.match(ctx, pats, opts)
270 m.bad = bad
270 m.bad = bad
271 follow = not opts.get('no_follow')
271 follow = not opts.get('no_follow')
272 for abs in ctx.walk(m):
272 for abs in ctx.walk(m):
273 fctx = ctx[abs]
273 fctx = ctx[abs]
274 if not opts.get('text') and util.binary(fctx.data()):
274 if not opts.get('text') and util.binary(fctx.data()):
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
276 continue
276 continue
277
277
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
279 pieces = []
279 pieces = []
280
280
281 for f, sep in funcmap:
281 for f, sep in funcmap:
282 l = [f(n) for n, dummy in lines]
282 l = [f(n) for n, dummy in lines]
283 if l:
283 if l:
284 sized = [(x, encoding.colwidth(x)) for x in l]
284 sized = [(x, encoding.colwidth(x)) for x in l]
285 ml = max([w for x, w in sized])
285 ml = max([w for x, w in sized])
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
287 for x, w in sized])
287 for x, w in sized])
288
288
289 if pieces:
289 if pieces:
290 for p, l in zip(zip(*pieces), lines):
290 for p, l in zip(zip(*pieces), lines):
291 ui.write("%s: %s" % ("".join(p), l[1]))
291 ui.write("%s: %s" % ("".join(p), l[1]))
292
292
293 @command('archive',
293 @command('archive',
294 [('', 'no-decode', None, _('do not pass files through decoders')),
294 [('', 'no-decode', None, _('do not pass files through decoders')),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
295 ('p', 'prefix', '', _('directory prefix for files in archive'),
296 _('PREFIX')),
296 _('PREFIX')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
299 ] + subrepoopts + walkopts,
299 ] + subrepoopts + walkopts,
300 _('[OPTION]... DEST'))
300 _('[OPTION]... DEST'))
301 def archive(ui, repo, dest, **opts):
301 def archive(ui, repo, dest, **opts):
302 '''create an unversioned archive of a repository revision
302 '''create an unversioned archive of a repository revision
303
303
304 By default, the revision used is the parent of the working
304 By default, the revision used is the parent of the working
305 directory; use -r/--rev to specify a different revision.
305 directory; use -r/--rev to specify a different revision.
306
306
307 The archive type is automatically detected based on file
307 The archive type is automatically detected based on file
308 extension (or override using -t/--type).
308 extension (or override using -t/--type).
309
309
310 .. container:: verbose
310 .. container:: verbose
311
311
312 Examples:
312 Examples:
313
313
314 - create a zip file containing the 1.0 release::
314 - create a zip file containing the 1.0 release::
315
315
316 hg archive -r 1.0 project-1.0.zip
316 hg archive -r 1.0 project-1.0.zip
317
317
318 - create a tarball excluding .hg files::
318 - create a tarball excluding .hg files::
319
319
320 hg archive project.tar.gz -X ".hg*"
320 hg archive project.tar.gz -X ".hg*"
321
321
322 Valid types are:
322 Valid types are:
323
323
324 :``files``: a directory full of files (default)
324 :``files``: a directory full of files (default)
325 :``tar``: tar archive, uncompressed
325 :``tar``: tar archive, uncompressed
326 :``tbz2``: tar archive, compressed using bzip2
326 :``tbz2``: tar archive, compressed using bzip2
327 :``tgz``: tar archive, compressed using gzip
327 :``tgz``: tar archive, compressed using gzip
328 :``uzip``: zip archive, uncompressed
328 :``uzip``: zip archive, uncompressed
329 :``zip``: zip archive, compressed using deflate
329 :``zip``: zip archive, compressed using deflate
330
330
331 The exact name of the destination archive or directory is given
331 The exact name of the destination archive or directory is given
332 using a format string; see :hg:`help export` for details.
332 using a format string; see :hg:`help export` for details.
333
333
334 Each member added to an archive file has a directory prefix
334 Each member added to an archive file has a directory prefix
335 prepended. Use -p/--prefix to specify a format string for the
335 prepended. Use -p/--prefix to specify a format string for the
336 prefix. The default is the basename of the archive, with suffixes
336 prefix. The default is the basename of the archive, with suffixes
337 removed.
337 removed.
338
338
339 Returns 0 on success.
339 Returns 0 on success.
340 '''
340 '''
341
341
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
342 ctx = scmutil.revsingle(repo, opts.get('rev'))
343 if not ctx:
343 if not ctx:
344 raise util.Abort(_('no working directory: please specify a revision'))
344 raise util.Abort(_('no working directory: please specify a revision'))
345 node = ctx.node()
345 node = ctx.node()
346 dest = cmdutil.makefilename(repo, dest, node)
346 dest = cmdutil.makefilename(repo, dest, node)
347 if os.path.realpath(dest) == repo.root:
347 if os.path.realpath(dest) == repo.root:
348 raise util.Abort(_('repository root cannot be destination'))
348 raise util.Abort(_('repository root cannot be destination'))
349
349
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
351 prefix = opts.get('prefix')
351 prefix = opts.get('prefix')
352
352
353 if dest == '-':
353 if dest == '-':
354 if kind == 'files':
354 if kind == 'files':
355 raise util.Abort(_('cannot archive plain files to stdout'))
355 raise util.Abort(_('cannot archive plain files to stdout'))
356 dest = cmdutil.makefileobj(repo, dest)
356 dest = cmdutil.makefileobj(repo, dest)
357 if not prefix:
357 if not prefix:
358 prefix = os.path.basename(repo.root) + '-%h'
358 prefix = os.path.basename(repo.root) + '-%h'
359
359
360 prefix = cmdutil.makefilename(repo, prefix, node)
360 prefix = cmdutil.makefilename(repo, prefix, node)
361 matchfn = scmutil.match(ctx, [], opts)
361 matchfn = scmutil.match(ctx, [], opts)
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
363 matchfn, prefix, subrepos=opts.get('subrepos'))
363 matchfn, prefix, subrepos=opts.get('subrepos'))
364
364
365 @command('backout',
365 @command('backout',
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
367 ('', 'parent', '', _('parent to choose when backing out merge'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
368 ('r', 'rev', '', _('revision to backout'), _('REV')),
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
369 ] + mergetoolopts + walkopts + commitopts + commitopts2,
370 _('[OPTION]... [-r] REV'))
370 _('[OPTION]... [-r] REV'))
371 def backout(ui, repo, node=None, rev=None, **opts):
371 def backout(ui, repo, node=None, rev=None, **opts):
372 '''reverse effect of earlier changeset
372 '''reverse effect of earlier changeset
373
373
374 Prepare a new changeset with the effect of REV undone in the
374 Prepare a new changeset with the effect of REV undone in the
375 current working directory.
375 current working directory.
376
376
377 If REV is the parent of the working directory, then this new changeset
377 If REV is the parent of the working directory, then this new changeset
378 is committed automatically. Otherwise, hg needs to merge the
378 is committed automatically. Otherwise, hg needs to merge the
379 changes and the merged result is left uncommitted.
379 changes and the merged result is left uncommitted.
380
380
381 By default, the pending changeset will have one parent,
381 By default, the pending changeset will have one parent,
382 maintaining a linear history. With --merge, the pending changeset
382 maintaining a linear history. With --merge, the pending changeset
383 will instead have two parents: the old parent of the working
383 will instead have two parents: the old parent of the working
384 directory and a new child of REV that simply undoes REV.
384 directory and a new child of REV that simply undoes REV.
385
385
386 Before version 1.7, the behavior without --merge was equivalent to
386 Before version 1.7, the behavior without --merge was equivalent to
387 specifying --merge followed by :hg:`update --clean .` to cancel
387 specifying --merge followed by :hg:`update --clean .` to cancel
388 the merge and leave the child of REV as a head to be merged
388 the merge and leave the child of REV as a head to be merged
389 separately.
389 separately.
390
390
391 See :hg:`help dates` for a list of formats valid for -d/--date.
391 See :hg:`help dates` for a list of formats valid for -d/--date.
392
392
393 Returns 0 on success.
393 Returns 0 on success.
394 '''
394 '''
395 if rev and node:
395 if rev and node:
396 raise util.Abort(_("please specify just one revision"))
396 raise util.Abort(_("please specify just one revision"))
397
397
398 if not rev:
398 if not rev:
399 rev = node
399 rev = node
400
400
401 if not rev:
401 if not rev:
402 raise util.Abort(_("please specify a revision to backout"))
402 raise util.Abort(_("please specify a revision to backout"))
403
403
404 date = opts.get('date')
404 date = opts.get('date')
405 if date:
405 if date:
406 opts['date'] = util.parsedate(date)
406 opts['date'] = util.parsedate(date)
407
407
408 cmdutil.bailifchanged(repo)
408 cmdutil.bailifchanged(repo)
409 node = scmutil.revsingle(repo, rev).node()
409 node = scmutil.revsingle(repo, rev).node()
410
410
411 op1, op2 = repo.dirstate.parents()
411 op1, op2 = repo.dirstate.parents()
412 a = repo.changelog.ancestor(op1, node)
412 a = repo.changelog.ancestor(op1, node)
413 if a != node:
413 if a != node:
414 raise util.Abort(_('cannot backout change on a different branch'))
414 raise util.Abort(_('cannot backout change on a different branch'))
415
415
416 p1, p2 = repo.changelog.parents(node)
416 p1, p2 = repo.changelog.parents(node)
417 if p1 == nullid:
417 if p1 == nullid:
418 raise util.Abort(_('cannot backout a change with no parents'))
418 raise util.Abort(_('cannot backout a change with no parents'))
419 if p2 != nullid:
419 if p2 != nullid:
420 if not opts.get('parent'):
420 if not opts.get('parent'):
421 raise util.Abort(_('cannot backout a merge changeset without '
421 raise util.Abort(_('cannot backout a merge changeset without '
422 '--parent'))
422 '--parent'))
423 p = repo.lookup(opts['parent'])
423 p = repo.lookup(opts['parent'])
424 if p not in (p1, p2):
424 if p not in (p1, p2):
425 raise util.Abort(_('%s is not a parent of %s') %
425 raise util.Abort(_('%s is not a parent of %s') %
426 (short(p), short(node)))
426 (short(p), short(node)))
427 parent = p
427 parent = p
428 else:
428 else:
429 if opts.get('parent'):
429 if opts.get('parent'):
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
430 raise util.Abort(_('cannot use --parent on non-merge changeset'))
431 parent = p1
431 parent = p1
432
432
433 # the backout should appear on the same branch
433 # the backout should appear on the same branch
434 branch = repo.dirstate.branch()
434 branch = repo.dirstate.branch()
435 hg.clean(repo, node, show_stats=False)
435 hg.clean(repo, node, show_stats=False)
436 repo.dirstate.setbranch(branch)
436 repo.dirstate.setbranch(branch)
437 revert_opts = opts.copy()
437 revert_opts = opts.copy()
438 revert_opts['date'] = None
438 revert_opts['date'] = None
439 revert_opts['all'] = True
439 revert_opts['all'] = True
440 revert_opts['rev'] = hex(parent)
440 revert_opts['rev'] = hex(parent)
441 revert_opts['no_backup'] = None
441 revert_opts['no_backup'] = None
442 revert(ui, repo, **revert_opts)
442 revert(ui, repo, **revert_opts)
443 if not opts.get('merge') and op1 != node:
443 if not opts.get('merge') and op1 != node:
444 try:
444 try:
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
446 return hg.update(repo, op1)
446 return hg.update(repo, op1)
447 finally:
447 finally:
448 ui.setconfig('ui', 'forcemerge', '')
448 ui.setconfig('ui', 'forcemerge', '')
449
449
450 commit_opts = opts.copy()
450 commit_opts = opts.copy()
451 commit_opts['addremove'] = False
451 commit_opts['addremove'] = False
452 if not commit_opts['message'] and not commit_opts['logfile']:
452 if not commit_opts['message'] and not commit_opts['logfile']:
453 # we don't translate commit messages
453 # we don't translate commit messages
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
454 commit_opts['message'] = "Backed out changeset %s" % short(node)
455 commit_opts['force_editor'] = True
455 commit_opts['force_editor'] = True
456 commit(ui, repo, **commit_opts)
456 commit(ui, repo, **commit_opts)
457 def nice(node):
457 def nice(node):
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
458 return '%d:%s' % (repo.changelog.rev(node), short(node))
459 ui.status(_('changeset %s backs out changeset %s\n') %
459 ui.status(_('changeset %s backs out changeset %s\n') %
460 (nice(repo.changelog.tip()), nice(node)))
460 (nice(repo.changelog.tip()), nice(node)))
461 if opts.get('merge') and op1 != node:
461 if opts.get('merge') and op1 != node:
462 hg.clean(repo, op1, show_stats=False)
462 hg.clean(repo, op1, show_stats=False)
463 ui.status(_('merging with changeset %s\n')
463 ui.status(_('merging with changeset %s\n')
464 % nice(repo.changelog.tip()))
464 % nice(repo.changelog.tip()))
465 try:
465 try:
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
466 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 return hg.merge(repo, hex(repo.changelog.tip()))
467 return hg.merge(repo, hex(repo.changelog.tip()))
468 finally:
468 finally:
469 ui.setconfig('ui', 'forcemerge', '')
469 ui.setconfig('ui', 'forcemerge', '')
470 return 0
470 return 0
471
471
472 @command('bisect',
472 @command('bisect',
473 [('r', 'reset', False, _('reset bisect state')),
473 [('r', 'reset', False, _('reset bisect state')),
474 ('g', 'good', False, _('mark changeset good')),
474 ('g', 'good', False, _('mark changeset good')),
475 ('b', 'bad', False, _('mark changeset bad')),
475 ('b', 'bad', False, _('mark changeset bad')),
476 ('s', 'skip', False, _('skip testing changeset')),
476 ('s', 'skip', False, _('skip testing changeset')),
477 ('e', 'extend', False, _('extend the bisect range')),
477 ('e', 'extend', False, _('extend the bisect range')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
478 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
479 ('U', 'noupdate', False, _('do not update to target'))],
479 ('U', 'noupdate', False, _('do not update to target'))],
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
480 _("[-gbsr] [-U] [-c CMD] [REV]"))
481 def bisect(ui, repo, rev=None, extra=None, command=None,
481 def bisect(ui, repo, rev=None, extra=None, command=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
482 reset=None, good=None, bad=None, skip=None, extend=None,
483 noupdate=None):
483 noupdate=None):
484 """subdivision search of changesets
484 """subdivision search of changesets
485
485
486 This command helps to find changesets which introduce problems. To
486 This command helps to find changesets which introduce problems. To
487 use, mark the earliest changeset you know exhibits the problem as
487 use, mark the earliest changeset you know exhibits the problem as
488 bad, then mark the latest changeset which is free from the problem
488 bad, then mark the latest changeset which is free from the problem
489 as good. Bisect will update your working directory to a revision
489 as good. Bisect will update your working directory to a revision
490 for testing (unless the -U/--noupdate option is specified). Once
490 for testing (unless the -U/--noupdate option is specified). Once
491 you have performed tests, mark the working directory as good or
491 you have performed tests, mark the working directory as good or
492 bad, and bisect will either update to another candidate changeset
492 bad, and bisect will either update to another candidate changeset
493 or announce that it has found the bad revision.
493 or announce that it has found the bad revision.
494
494
495 As a shortcut, you can also use the revision argument to mark a
495 As a shortcut, you can also use the revision argument to mark a
496 revision as good or bad without checking it out first.
496 revision as good or bad without checking it out first.
497
497
498 If you supply a command, it will be used for automatic bisection.
498 If you supply a command, it will be used for automatic bisection.
499 Its exit status will be used to mark revisions as good or bad:
499 Its exit status will be used to mark revisions as good or bad:
500 status 0 means good, 125 means to skip the revision, 127
500 status 0 means good, 125 means to skip the revision, 127
501 (command not found) will abort the bisection, and any other
501 (command not found) will abort the bisection, and any other
502 non-zero exit status means the revision is bad.
502 non-zero exit status means the revision is bad.
503
503
504 .. container:: verbose
504 .. container:: verbose
505
505
506 Some examples:
506 Some examples:
507
507
508 - start a bisection with known bad revision 12, and good revision 34::
508 - start a bisection with known bad revision 12, and good revision 34::
509
509
510 hg bisect --bad 34
510 hg bisect --bad 34
511 hg bisect --good 12
511 hg bisect --good 12
512
512
513 - advance the current bisection by marking current revision as good or
513 - advance the current bisection by marking current revision as good or
514 bad::
514 bad::
515
515
516 hg bisect --good
516 hg bisect --good
517 hg bisect --bad
517 hg bisect --bad
518
518
519 - mark the current revision, or a known revision, to be skipped (eg. if
519 - mark the current revision, or a known revision, to be skipped (eg. if
520 that revision is not usable because of another issue)::
520 that revision is not usable because of another issue)::
521
521
522 hg bisect --skip
522 hg bisect --skip
523 hg bisect --skip 23
523 hg bisect --skip 23
524
524
525 - forget the current bisection::
525 - forget the current bisection::
526
526
527 hg bisect --reset
527 hg bisect --reset
528
528
529 - use 'make && make tests' to automatically find the first broken
529 - use 'make && make tests' to automatically find the first broken
530 revision::
530 revision::
531
531
532 hg bisect --reset
532 hg bisect --reset
533 hg bisect --bad 34
533 hg bisect --bad 34
534 hg bisect --good 12
534 hg bisect --good 12
535 hg bisect --command 'make && make tests'
535 hg bisect --command 'make && make tests'
536
536
537 - see all changesets whose states are already known in the current
537 - see all changesets whose states are already known in the current
538 bisection::
538 bisection::
539
539
540 hg log -r "bisect(pruned)"
540 hg log -r "bisect(pruned)"
541
541
542 - see all changesets that took part in the current bisection::
542 - see all changesets that took part in the current bisection::
543
543
544 hg log -r "bisect(range)"
544 hg log -r "bisect(range)"
545
545
546 - with the graphlog extension, you can even get a nice graph::
546 - with the graphlog extension, you can even get a nice graph::
547
547
548 hg log --graph -r "bisect(range)"
548 hg log --graph -r "bisect(range)"
549
549
550 See :hg:`help revsets` for more about the `bisect()` keyword.
550 See :hg:`help revsets` for more about the `bisect()` keyword.
551
551
552 Returns 0 on success.
552 Returns 0 on success.
553 """
553 """
554 def extendbisectrange(nodes, good):
554 def extendbisectrange(nodes, good):
555 # bisect is incomplete when it ends on a merge node and
555 # bisect is incomplete when it ends on a merge node and
556 # one of the parent was not checked.
556 # one of the parent was not checked.
557 parents = repo[nodes[0]].parents()
557 parents = repo[nodes[0]].parents()
558 if len(parents) > 1:
558 if len(parents) > 1:
559 side = good and state['bad'] or state['good']
559 side = good and state['bad'] or state['good']
560 num = len(set(i.node() for i in parents) & set(side))
560 num = len(set(i.node() for i in parents) & set(side))
561 if num == 1:
561 if num == 1:
562 return parents[0].ancestor(parents[1])
562 return parents[0].ancestor(parents[1])
563 return None
563 return None
564
564
565 def print_result(nodes, good):
565 def print_result(nodes, good):
566 displayer = cmdutil.show_changeset(ui, repo, {})
566 displayer = cmdutil.show_changeset(ui, repo, {})
567 if len(nodes) == 1:
567 if len(nodes) == 1:
568 # narrowed it down to a single revision
568 # narrowed it down to a single revision
569 if good:
569 if good:
570 ui.write(_("The first good revision is:\n"))
570 ui.write(_("The first good revision is:\n"))
571 else:
571 else:
572 ui.write(_("The first bad revision is:\n"))
572 ui.write(_("The first bad revision is:\n"))
573 displayer.show(repo[nodes[0]])
573 displayer.show(repo[nodes[0]])
574 extendnode = extendbisectrange(nodes, good)
574 extendnode = extendbisectrange(nodes, good)
575 if extendnode is not None:
575 if extendnode is not None:
576 ui.write(_('Not all ancestors of this changeset have been'
576 ui.write(_('Not all ancestors of this changeset have been'
577 ' checked.\nUse bisect --extend to continue the '
577 ' checked.\nUse bisect --extend to continue the '
578 'bisection from\nthe common ancestor, %s.\n')
578 'bisection from\nthe common ancestor, %s.\n')
579 % extendnode)
579 % extendnode)
580 else:
580 else:
581 # multiple possible revisions
581 # multiple possible revisions
582 if good:
582 if good:
583 ui.write(_("Due to skipped revisions, the first "
583 ui.write(_("Due to skipped revisions, the first "
584 "good revision could be any of:\n"))
584 "good revision could be any of:\n"))
585 else:
585 else:
586 ui.write(_("Due to skipped revisions, the first "
586 ui.write(_("Due to skipped revisions, the first "
587 "bad revision could be any of:\n"))
587 "bad revision could be any of:\n"))
588 for n in nodes:
588 for n in nodes:
589 displayer.show(repo[n])
589 displayer.show(repo[n])
590 displayer.close()
590 displayer.close()
591
591
592 def check_state(state, interactive=True):
592 def check_state(state, interactive=True):
593 if not state['good'] or not state['bad']:
593 if not state['good'] or not state['bad']:
594 if (good or bad or skip or reset) and interactive:
594 if (good or bad or skip or reset) and interactive:
595 return
595 return
596 if not state['good']:
596 if not state['good']:
597 raise util.Abort(_('cannot bisect (no known good revisions)'))
597 raise util.Abort(_('cannot bisect (no known good revisions)'))
598 else:
598 else:
599 raise util.Abort(_('cannot bisect (no known bad revisions)'))
599 raise util.Abort(_('cannot bisect (no known bad revisions)'))
600 return True
600 return True
601
601
602 # backward compatibility
602 # backward compatibility
603 if rev in "good bad reset init".split():
603 if rev in "good bad reset init".split():
604 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
604 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
605 cmd, rev, extra = rev, extra, None
605 cmd, rev, extra = rev, extra, None
606 if cmd == "good":
606 if cmd == "good":
607 good = True
607 good = True
608 elif cmd == "bad":
608 elif cmd == "bad":
609 bad = True
609 bad = True
610 else:
610 else:
611 reset = True
611 reset = True
612 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
612 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
613 raise util.Abort(_('incompatible arguments'))
613 raise util.Abort(_('incompatible arguments'))
614
614
615 if reset:
615 if reset:
616 p = repo.join("bisect.state")
616 p = repo.join("bisect.state")
617 if os.path.exists(p):
617 if os.path.exists(p):
618 os.unlink(p)
618 os.unlink(p)
619 return
619 return
620
620
621 state = hbisect.load_state(repo)
621 state = hbisect.load_state(repo)
622
622
623 if command:
623 if command:
624 changesets = 1
624 changesets = 1
625 try:
625 try:
626 while changesets:
626 while changesets:
627 # update state
627 # update state
628 status = util.system(command, out=ui.fout)
628 status = util.system(command, out=ui.fout)
629 if status == 125:
629 if status == 125:
630 transition = "skip"
630 transition = "skip"
631 elif status == 0:
631 elif status == 0:
632 transition = "good"
632 transition = "good"
633 # status < 0 means process was killed
633 # status < 0 means process was killed
634 elif status == 127:
634 elif status == 127:
635 raise util.Abort(_("failed to execute %s") % command)
635 raise util.Abort(_("failed to execute %s") % command)
636 elif status < 0:
636 elif status < 0:
637 raise util.Abort(_("%s killed") % command)
637 raise util.Abort(_("%s killed") % command)
638 else:
638 else:
639 transition = "bad"
639 transition = "bad"
640 ctx = scmutil.revsingle(repo, rev)
640 ctx = scmutil.revsingle(repo, rev)
641 rev = None # clear for future iterations
641 rev = None # clear for future iterations
642 state[transition].append(ctx.node())
642 state[transition].append(ctx.node())
643 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
643 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
644 check_state(state, interactive=False)
644 check_state(state, interactive=False)
645 # bisect
645 # bisect
646 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
646 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
647 # update to next check
647 # update to next check
648 cmdutil.bailifchanged(repo)
648 cmdutil.bailifchanged(repo)
649 hg.clean(repo, nodes[0], show_stats=False)
649 hg.clean(repo, nodes[0], show_stats=False)
650 finally:
650 finally:
651 hbisect.save_state(repo, state)
651 hbisect.save_state(repo, state)
652 print_result(nodes, good)
652 print_result(nodes, good)
653 return
653 return
654
654
655 # update state
655 # update state
656
656
657 if rev:
657 if rev:
658 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
658 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
659 else:
659 else:
660 nodes = [repo.lookup('.')]
660 nodes = [repo.lookup('.')]
661
661
662 if good or bad or skip:
662 if good or bad or skip:
663 if good:
663 if good:
664 state['good'] += nodes
664 state['good'] += nodes
665 elif bad:
665 elif bad:
666 state['bad'] += nodes
666 state['bad'] += nodes
667 elif skip:
667 elif skip:
668 state['skip'] += nodes
668 state['skip'] += nodes
669 hbisect.save_state(repo, state)
669 hbisect.save_state(repo, state)
670
670
671 if not check_state(state):
671 if not check_state(state):
672 return
672 return
673
673
674 # actually bisect
674 # actually bisect
675 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
675 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
676 if extend:
676 if extend:
677 if not changesets:
677 if not changesets:
678 extendnode = extendbisectrange(nodes, good)
678 extendnode = extendbisectrange(nodes, good)
679 if extendnode is not None:
679 if extendnode is not None:
680 ui.write(_("Extending search to changeset %d:%s\n"
680 ui.write(_("Extending search to changeset %d:%s\n"
681 % (extendnode.rev(), extendnode)))
681 % (extendnode.rev(), extendnode)))
682 if noupdate:
682 if noupdate:
683 return
683 return
684 cmdutil.bailifchanged(repo)
684 cmdutil.bailifchanged(repo)
685 return hg.clean(repo, extendnode.node())
685 return hg.clean(repo, extendnode.node())
686 raise util.Abort(_("nothing to extend"))
686 raise util.Abort(_("nothing to extend"))
687
687
688 if changesets == 0:
688 if changesets == 0:
689 print_result(nodes, good)
689 print_result(nodes, good)
690 else:
690 else:
691 assert len(nodes) == 1 # only a single node can be tested next
691 assert len(nodes) == 1 # only a single node can be tested next
692 node = nodes[0]
692 node = nodes[0]
693 # compute the approximate number of remaining tests
693 # compute the approximate number of remaining tests
694 tests, size = 0, 2
694 tests, size = 0, 2
695 while size <= changesets:
695 while size <= changesets:
696 tests, size = tests + 1, size * 2
696 tests, size = tests + 1, size * 2
697 rev = repo.changelog.rev(node)
697 rev = repo.changelog.rev(node)
698 ui.write(_("Testing changeset %d:%s "
698 ui.write(_("Testing changeset %d:%s "
699 "(%d changesets remaining, ~%d tests)\n")
699 "(%d changesets remaining, ~%d tests)\n")
700 % (rev, short(node), changesets, tests))
700 % (rev, short(node), changesets, tests))
701 if not noupdate:
701 if not noupdate:
702 cmdutil.bailifchanged(repo)
702 cmdutil.bailifchanged(repo)
703 return hg.clean(repo, node)
703 return hg.clean(repo, node)
704
704
705 @command('bookmarks',
705 @command('bookmarks',
706 [('f', 'force', False, _('force')),
706 [('f', 'force', False, _('force')),
707 ('r', 'rev', '', _('revision'), _('REV')),
707 ('r', 'rev', '', _('revision'), _('REV')),
708 ('d', 'delete', False, _('delete a given bookmark')),
708 ('d', 'delete', False, _('delete a given bookmark')),
709 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
709 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
710 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
710 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
711 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
711 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
712 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
712 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
713 rename=None, inactive=False):
713 rename=None, inactive=False):
714 '''track a line of development with movable markers
714 '''track a line of development with movable markers
715
715
716 Bookmarks are pointers to certain commits that move when
716 Bookmarks are pointers to certain commits that move when
717 committing. Bookmarks are local. They can be renamed, copied and
717 committing. Bookmarks are local. They can be renamed, copied and
718 deleted. It is possible to use bookmark names in :hg:`merge` and
718 deleted. It is possible to use bookmark names in :hg:`merge` and
719 :hg:`update` to merge and update respectively to a given bookmark.
719 :hg:`update` to merge and update respectively to a given bookmark.
720
720
721 You can use :hg:`bookmark NAME` to set a bookmark on the working
721 You can use :hg:`bookmark NAME` to set a bookmark on the working
722 directory's parent revision with the given name. If you specify
722 directory's parent revision with the given name. If you specify
723 a revision using -r REV (where REV may be an existing bookmark),
723 a revision using -r REV (where REV may be an existing bookmark),
724 the bookmark is assigned to that revision.
724 the bookmark is assigned to that revision.
725
725
726 Bookmarks can be pushed and pulled between repositories (see :hg:`help
726 Bookmarks can be pushed and pulled between repositories (see :hg:`help
727 push` and :hg:`help pull`). This requires both the local and remote
727 push` and :hg:`help pull`). This requires both the local and remote
728 repositories to support bookmarks. For versions prior to 1.8, this means
728 repositories to support bookmarks. For versions prior to 1.8, this means
729 the bookmarks extension must be enabled.
729 the bookmarks extension must be enabled.
730 '''
730 '''
731 hexfn = ui.debugflag and hex or short
731 hexfn = ui.debugflag and hex or short
732 marks = repo._bookmarks
732 marks = repo._bookmarks
733 cur = repo.changectx('.').node()
733 cur = repo.changectx('.').node()
734
734
735 if rename:
735 if rename:
736 if rename not in marks:
736 if rename not in marks:
737 raise util.Abort(_("bookmark '%s' does not exist") % rename)
737 raise util.Abort(_("bookmark '%s' does not exist") % rename)
738 if mark in marks and not force:
738 if mark in marks and not force:
739 raise util.Abort(_("bookmark '%s' already exists "
739 raise util.Abort(_("bookmark '%s' already exists "
740 "(use -f to force)") % mark)
740 "(use -f to force)") % mark)
741 if mark is None:
741 if mark is None:
742 raise util.Abort(_("new bookmark name required"))
742 raise util.Abort(_("new bookmark name required"))
743 marks[mark] = marks[rename]
743 marks[mark] = marks[rename]
744 if repo._bookmarkcurrent == rename and not inactive:
744 if repo._bookmarkcurrent == rename and not inactive:
745 bookmarks.setcurrent(repo, mark)
745 bookmarks.setcurrent(repo, mark)
746 del marks[rename]
746 del marks[rename]
747 bookmarks.write(repo)
747 bookmarks.write(repo)
748 return
748 return
749
749
750 if delete:
750 if delete:
751 if mark is None:
751 if mark is None:
752 raise util.Abort(_("bookmark name required"))
752 raise util.Abort(_("bookmark name required"))
753 if mark not in marks:
753 if mark not in marks:
754 raise util.Abort(_("bookmark '%s' does not exist") % mark)
754 raise util.Abort(_("bookmark '%s' does not exist") % mark)
755 if mark == repo._bookmarkcurrent:
755 if mark == repo._bookmarkcurrent:
756 bookmarks.setcurrent(repo, None)
756 bookmarks.setcurrent(repo, None)
757 del marks[mark]
757 del marks[mark]
758 bookmarks.write(repo)
758 bookmarks.write(repo)
759 return
759 return
760
760
761 if mark is not None:
761 if mark is not None:
762 if "\n" in mark:
762 if "\n" in mark:
763 raise util.Abort(_("bookmark name cannot contain newlines"))
763 raise util.Abort(_("bookmark name cannot contain newlines"))
764 mark = mark.strip()
764 mark = mark.strip()
765 if not mark:
765 if not mark:
766 raise util.Abort(_("bookmark names cannot consist entirely of "
766 raise util.Abort(_("bookmark names cannot consist entirely of "
767 "whitespace"))
767 "whitespace"))
768 if inactive and mark == repo._bookmarkcurrent:
768 if inactive and mark == repo._bookmarkcurrent:
769 bookmarks.setcurrent(repo, None)
769 bookmarks.setcurrent(repo, None)
770 return
770 return
771 if mark in marks and not force:
771 if mark in marks and not force:
772 raise util.Abort(_("bookmark '%s' already exists "
772 raise util.Abort(_("bookmark '%s' already exists "
773 "(use -f to force)") % mark)
773 "(use -f to force)") % mark)
774 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
774 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
775 and not force):
775 and not force):
776 raise util.Abort(
776 raise util.Abort(
777 _("a bookmark cannot have the name of an existing branch"))
777 _("a bookmark cannot have the name of an existing branch"))
778 if rev:
778 if rev:
779 marks[mark] = repo.lookup(rev)
779 marks[mark] = repo.lookup(rev)
780 else:
780 else:
781 marks[mark] = repo.changectx('.').node()
781 marks[mark] = repo.changectx('.').node()
782 if not inactive and repo.changectx('.').node() == marks[mark]:
782 if not inactive and repo.changectx('.').node() == marks[mark]:
783 bookmarks.setcurrent(repo, mark)
783 bookmarks.setcurrent(repo, mark)
784 bookmarks.write(repo)
784 bookmarks.write(repo)
785 return
785 return
786
786
787 if mark is None:
787 if mark is None:
788 if rev:
788 if rev:
789 raise util.Abort(_("bookmark name required"))
789 raise util.Abort(_("bookmark name required"))
790 if len(marks) == 0:
790 if len(marks) == 0:
791 ui.status(_("no bookmarks set\n"))
791 ui.status(_("no bookmarks set\n"))
792 else:
792 else:
793 for bmark, n in sorted(marks.iteritems()):
793 for bmark, n in sorted(marks.iteritems()):
794 current = repo._bookmarkcurrent
794 current = repo._bookmarkcurrent
795 if bmark == current and n == cur:
795 if bmark == current and n == cur:
796 prefix, label = '*', 'bookmarks.current'
796 prefix, label = '*', 'bookmarks.current'
797 else:
797 else:
798 prefix, label = ' ', ''
798 prefix, label = ' ', ''
799
799
800 if ui.quiet:
800 if ui.quiet:
801 ui.write("%s\n" % bmark, label=label)
801 ui.write("%s\n" % bmark, label=label)
802 else:
802 else:
803 ui.write(" %s %-25s %d:%s\n" % (
803 ui.write(" %s %-25s %d:%s\n" % (
804 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
804 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
805 label=label)
805 label=label)
806 return
806 return
807
807
808 @command('branch',
808 @command('branch',
809 [('f', 'force', None,
809 [('f', 'force', None,
810 _('set branch name even if it shadows an existing branch')),
810 _('set branch name even if it shadows an existing branch')),
811 ('C', 'clean', None, _('reset branch name to parent branch name'))],
811 ('C', 'clean', None, _('reset branch name to parent branch name'))],
812 _('[-fC] [NAME]'))
812 _('[-fC] [NAME]'))
813 def branch(ui, repo, label=None, **opts):
813 def branch(ui, repo, label=None, **opts):
814 """set or show the current branch name
814 """set or show the current branch name
815
815
816 With no argument, show the current branch name. With one argument,
816 With no argument, show the current branch name. With one argument,
817 set the working directory branch name (the branch will not exist
817 set the working directory branch name (the branch will not exist
818 in the repository until the next commit). Standard practice
818 in the repository until the next commit). Standard practice
819 recommends that primary development take place on the 'default'
819 recommends that primary development take place on the 'default'
820 branch.
820 branch.
821
821
822 Unless -f/--force is specified, branch will not let you set a
822 Unless -f/--force is specified, branch will not let you set a
823 branch name that already exists, even if it's inactive.
823 branch name that already exists, even if it's inactive.
824
824
825 Use -C/--clean to reset the working directory branch to that of
825 Use -C/--clean to reset the working directory branch to that of
826 the parent of the working directory, negating a previous branch
826 the parent of the working directory, negating a previous branch
827 change.
827 change.
828
828
829 Use the command :hg:`update` to switch to an existing branch. Use
829 Use the command :hg:`update` to switch to an existing branch. Use
830 :hg:`commit --close-branch` to mark this branch as closed.
830 :hg:`commit --close-branch` to mark this branch as closed.
831
831
832 .. note::
832 .. note::
833
833
834 Branch names are permanent. Use :hg:`bookmark` to create a
834 Branch names are permanent. Use :hg:`bookmark` to create a
835 light-weight bookmark instead. See :hg:`help glossary` for more
835 light-weight bookmark instead. See :hg:`help glossary` for more
836 information about named branches and bookmarks.
836 information about named branches and bookmarks.
837
837
838 Returns 0 on success.
838 Returns 0 on success.
839 """
839 """
840
840
841 if opts.get('clean'):
841 if opts.get('clean'):
842 label = repo[None].p1().branch()
842 label = repo[None].p1().branch()
843 repo.dirstate.setbranch(label)
843 repo.dirstate.setbranch(label)
844 ui.status(_('reset working directory to branch %s\n') % label)
844 ui.status(_('reset working directory to branch %s\n') % label)
845 elif label:
845 elif label:
846 if not opts.get('force') and label in repo.branchtags():
846 if not opts.get('force') and label in repo.branchtags():
847 if label not in [p.branch() for p in repo.parents()]:
847 if label not in [p.branch() for p in repo.parents()]:
848 raise util.Abort(_('a branch of the same name already exists'),
848 raise util.Abort(_('a branch of the same name already exists'),
849 # i18n: "it" refers to an existing branch
849 # i18n: "it" refers to an existing branch
850 hint=_("use 'hg update' to switch to it"))
850 hint=_("use 'hg update' to switch to it"))
851 repo.dirstate.setbranch(label)
851 repo.dirstate.setbranch(label)
852 ui.status(_('marked working directory as branch %s\n') % label)
852 ui.status(_('marked working directory as branch %s\n') % label)
853 else:
853 else:
854 ui.write("%s\n" % repo.dirstate.branch())
854 ui.write("%s\n" % repo.dirstate.branch())
855
855
856 @command('branches',
856 @command('branches',
857 [('a', 'active', False, _('show only branches that have unmerged heads')),
857 [('a', 'active', False, _('show only branches that have unmerged heads')),
858 ('c', 'closed', False, _('show normal and closed branches'))],
858 ('c', 'closed', False, _('show normal and closed branches'))],
859 _('[-ac]'))
859 _('[-ac]'))
860 def branches(ui, repo, active=False, closed=False):
860 def branches(ui, repo, active=False, closed=False):
861 """list repository named branches
861 """list repository named branches
862
862
863 List the repository's named branches, indicating which ones are
863 List the repository's named branches, indicating which ones are
864 inactive. If -c/--closed is specified, also list branches which have
864 inactive. If -c/--closed is specified, also list branches which have
865 been marked closed (see :hg:`commit --close-branch`).
865 been marked closed (see :hg:`commit --close-branch`).
866
866
867 If -a/--active is specified, only show active branches. A branch
867 If -a/--active is specified, only show active branches. A branch
868 is considered active if it contains repository heads.
868 is considered active if it contains repository heads.
869
869
870 Use the command :hg:`update` to switch to an existing branch.
870 Use the command :hg:`update` to switch to an existing branch.
871
871
872 Returns 0.
872 Returns 0.
873 """
873 """
874
874
875 hexfunc = ui.debugflag and hex or short
875 hexfunc = ui.debugflag and hex or short
876 activebranches = [repo[n].branch() for n in repo.heads()]
876 activebranches = [repo[n].branch() for n in repo.heads()]
877 def testactive(tag, node):
877 def testactive(tag, node):
878 realhead = tag in activebranches
878 realhead = tag in activebranches
879 open = node in repo.branchheads(tag, closed=False)
879 open = node in repo.branchheads(tag, closed=False)
880 return realhead and open
880 return realhead and open
881 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
881 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
882 for tag, node in repo.branchtags().items()],
882 for tag, node in repo.branchtags().items()],
883 reverse=True)
883 reverse=True)
884
884
885 for isactive, node, tag in branches:
885 for isactive, node, tag in branches:
886 if (not active) or isactive:
886 if (not active) or isactive:
887 if ui.quiet:
887 if ui.quiet:
888 ui.write("%s\n" % tag)
888 ui.write("%s\n" % tag)
889 else:
889 else:
890 hn = repo.lookup(node)
890 hn = repo.lookup(node)
891 if isactive:
891 if isactive:
892 label = 'branches.active'
892 label = 'branches.active'
893 notice = ''
893 notice = ''
894 elif hn not in repo.branchheads(tag, closed=False):
894 elif hn not in repo.branchheads(tag, closed=False):
895 if not closed:
895 if not closed:
896 continue
896 continue
897 label = 'branches.closed'
897 label = 'branches.closed'
898 notice = _(' (closed)')
898 notice = _(' (closed)')
899 else:
899 else:
900 label = 'branches.inactive'
900 label = 'branches.inactive'
901 notice = _(' (inactive)')
901 notice = _(' (inactive)')
902 if tag == repo.dirstate.branch():
902 if tag == repo.dirstate.branch():
903 label = 'branches.current'
903 label = 'branches.current'
904 rev = str(node).rjust(31 - encoding.colwidth(tag))
904 rev = str(node).rjust(31 - encoding.colwidth(tag))
905 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
905 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
906 tag = ui.label(tag, label)
906 tag = ui.label(tag, label)
907 ui.write("%s %s%s\n" % (tag, rev, notice))
907 ui.write("%s %s%s\n" % (tag, rev, notice))
908
908
909 @command('bundle',
909 @command('bundle',
910 [('f', 'force', None, _('run even when the destination is unrelated')),
910 [('f', 'force', None, _('run even when the destination is unrelated')),
911 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
911 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
912 _('REV')),
912 _('REV')),
913 ('b', 'branch', [], _('a specific branch you would like to bundle'),
913 ('b', 'branch', [], _('a specific branch you would like to bundle'),
914 _('BRANCH')),
914 _('BRANCH')),
915 ('', 'base', [],
915 ('', 'base', [],
916 _('a base changeset assumed to be available at the destination'),
916 _('a base changeset assumed to be available at the destination'),
917 _('REV')),
917 _('REV')),
918 ('a', 'all', None, _('bundle all changesets in the repository')),
918 ('a', 'all', None, _('bundle all changesets in the repository')),
919 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
919 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
920 ] + remoteopts,
920 ] + remoteopts,
921 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
921 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
922 def bundle(ui, repo, fname, dest=None, **opts):
922 def bundle(ui, repo, fname, dest=None, **opts):
923 """create a changegroup file
923 """create a changegroup file
924
924
925 Generate a compressed changegroup file collecting changesets not
925 Generate a compressed changegroup file collecting changesets not
926 known to be in another repository.
926 known to be in another repository.
927
927
928 If you omit the destination repository, then hg assumes the
928 If you omit the destination repository, then hg assumes the
929 destination will have all the nodes you specify with --base
929 destination will have all the nodes you specify with --base
930 parameters. To create a bundle containing all changesets, use
930 parameters. To create a bundle containing all changesets, use
931 -a/--all (or --base null).
931 -a/--all (or --base null).
932
932
933 You can change compression method with the -t/--type option.
933 You can change compression method with the -t/--type option.
934 The available compression methods are: none, bzip2, and
934 The available compression methods are: none, bzip2, and
935 gzip (by default, bundles are compressed using bzip2).
935 gzip (by default, bundles are compressed using bzip2).
936
936
937 The bundle file can then be transferred using conventional means
937 The bundle file can then be transferred using conventional means
938 and applied to another repository with the unbundle or pull
938 and applied to another repository with the unbundle or pull
939 command. This is useful when direct push and pull are not
939 command. This is useful when direct push and pull are not
940 available or when exporting an entire repository is undesirable.
940 available or when exporting an entire repository is undesirable.
941
941
942 Applying bundles preserves all changeset contents including
942 Applying bundles preserves all changeset contents including
943 permissions, copy/rename information, and revision history.
943 permissions, copy/rename information, and revision history.
944
944
945 Returns 0 on success, 1 if no changes found.
945 Returns 0 on success, 1 if no changes found.
946 """
946 """
947 revs = None
947 revs = None
948 if 'rev' in opts:
948 if 'rev' in opts:
949 revs = scmutil.revrange(repo, opts['rev'])
949 revs = scmutil.revrange(repo, opts['rev'])
950
950
951 if opts.get('all'):
951 if opts.get('all'):
952 base = ['null']
952 base = ['null']
953 else:
953 else:
954 base = scmutil.revrange(repo, opts.get('base'))
954 base = scmutil.revrange(repo, opts.get('base'))
955 if base:
955 if base:
956 if dest:
956 if dest:
957 raise util.Abort(_("--base is incompatible with specifying "
957 raise util.Abort(_("--base is incompatible with specifying "
958 "a destination"))
958 "a destination"))
959 common = [repo.lookup(rev) for rev in base]
959 common = [repo.lookup(rev) for rev in base]
960 heads = revs and map(repo.lookup, revs) or revs
960 heads = revs and map(repo.lookup, revs) or revs
961 else:
961 else:
962 dest = ui.expandpath(dest or 'default-push', dest or 'default')
962 dest = ui.expandpath(dest or 'default-push', dest or 'default')
963 dest, branches = hg.parseurl(dest, opts.get('branch'))
963 dest, branches = hg.parseurl(dest, opts.get('branch'))
964 other = hg.peer(repo, opts, dest)
964 other = hg.peer(repo, opts, dest)
965 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
965 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
966 heads = revs and map(repo.lookup, revs) or revs
966 heads = revs and map(repo.lookup, revs) or revs
967 common, outheads = discovery.findcommonoutgoing(repo, other,
967 common, outheads = discovery.findcommonoutgoing(repo, other,
968 onlyheads=heads,
968 onlyheads=heads,
969 force=opts.get('force'))
969 force=opts.get('force'))
970
970
971 cg = repo.getbundle('bundle', common=common, heads=heads)
971 cg = repo.getbundle('bundle', common=common, heads=heads)
972 if not cg:
972 if not cg:
973 ui.status(_("no changes found\n"))
973 ui.status(_("no changes found\n"))
974 return 1
974 return 1
975
975
976 bundletype = opts.get('type', 'bzip2').lower()
976 bundletype = opts.get('type', 'bzip2').lower()
977 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
977 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
978 bundletype = btypes.get(bundletype)
978 bundletype = btypes.get(bundletype)
979 if bundletype not in changegroup.bundletypes:
979 if bundletype not in changegroup.bundletypes:
980 raise util.Abort(_('unknown bundle type specified with --type'))
980 raise util.Abort(_('unknown bundle type specified with --type'))
981
981
982 changegroup.writebundle(cg, fname, bundletype)
982 changegroup.writebundle(cg, fname, bundletype)
983
983
984 @command('cat',
984 @command('cat',
985 [('o', 'output', '',
985 [('o', 'output', '',
986 _('print output to file with formatted name'), _('FORMAT')),
986 _('print output to file with formatted name'), _('FORMAT')),
987 ('r', 'rev', '', _('print the given revision'), _('REV')),
987 ('r', 'rev', '', _('print the given revision'), _('REV')),
988 ('', 'decode', None, _('apply any matching decode filter')),
988 ('', 'decode', None, _('apply any matching decode filter')),
989 ] + walkopts,
989 ] + walkopts,
990 _('[OPTION]... FILE...'))
990 _('[OPTION]... FILE...'))
991 def cat(ui, repo, file1, *pats, **opts):
991 def cat(ui, repo, file1, *pats, **opts):
992 """output the current or given revision of files
992 """output the current or given revision of files
993
993
994 Print the specified files as they were at the given revision. If
994 Print the specified files as they were at the given revision. If
995 no revision is given, the parent of the working directory is used,
995 no revision is given, the parent of the working directory is used,
996 or tip if no revision is checked out.
996 or tip if no revision is checked out.
997
997
998 Output may be to a file, in which case the name of the file is
998 Output may be to a file, in which case the name of the file is
999 given using a format string. The formatting rules are the same as
999 given using a format string. The formatting rules are the same as
1000 for the export command, with the following additions:
1000 for the export command, with the following additions:
1001
1001
1002 :``%s``: basename of file being printed
1002 :``%s``: basename of file being printed
1003 :``%d``: dirname of file being printed, or '.' if in repository root
1003 :``%d``: dirname of file being printed, or '.' if in repository root
1004 :``%p``: root-relative path name of file being printed
1004 :``%p``: root-relative path name of file being printed
1005
1005
1006 Returns 0 on success.
1006 Returns 0 on success.
1007 """
1007 """
1008 ctx = scmutil.revsingle(repo, opts.get('rev'))
1008 ctx = scmutil.revsingle(repo, opts.get('rev'))
1009 err = 1
1009 err = 1
1010 m = scmutil.match(ctx, (file1,) + pats, opts)
1010 m = scmutil.match(ctx, (file1,) + pats, opts)
1011 for abs in ctx.walk(m):
1011 for abs in ctx.walk(m):
1012 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1012 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1013 pathname=abs)
1013 pathname=abs)
1014 data = ctx[abs].data()
1014 data = ctx[abs].data()
1015 if opts.get('decode'):
1015 if opts.get('decode'):
1016 data = repo.wwritedata(abs, data)
1016 data = repo.wwritedata(abs, data)
1017 fp.write(data)
1017 fp.write(data)
1018 fp.close()
1018 fp.close()
1019 err = 0
1019 err = 0
1020 return err
1020 return err
1021
1021
1022 @command('^clone',
1022 @command('^clone',
1023 [('U', 'noupdate', None,
1023 [('U', 'noupdate', None,
1024 _('the clone will include an empty working copy (only a repository)')),
1024 _('the clone will include an empty working copy (only a repository)')),
1025 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1025 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1026 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1026 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1027 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1027 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1028 ('', 'pull', None, _('use pull protocol to copy metadata')),
1028 ('', 'pull', None, _('use pull protocol to copy metadata')),
1029 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1029 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1030 ] + remoteopts,
1030 ] + remoteopts,
1031 _('[OPTION]... SOURCE [DEST]'))
1031 _('[OPTION]... SOURCE [DEST]'))
1032 def clone(ui, source, dest=None, **opts):
1032 def clone(ui, source, dest=None, **opts):
1033 """make a copy of an existing repository
1033 """make a copy of an existing repository
1034
1034
1035 Create a copy of an existing repository in a new directory.
1035 Create a copy of an existing repository in a new directory.
1036
1036
1037 If no destination directory name is specified, it defaults to the
1037 If no destination directory name is specified, it defaults to the
1038 basename of the source.
1038 basename of the source.
1039
1039
1040 The location of the source is added to the new repository's
1040 The location of the source is added to the new repository's
1041 ``.hg/hgrc`` file, as the default to be used for future pulls.
1041 ``.hg/hgrc`` file, as the default to be used for future pulls.
1042
1042
1043 Only local paths and ``ssh://`` URLs are supported as
1043 Only local paths and ``ssh://`` URLs are supported as
1044 destinations. For ``ssh://`` destinations, no working directory or
1044 destinations. For ``ssh://`` destinations, no working directory or
1045 ``.hg/hgrc`` will be created on the remote side.
1045 ``.hg/hgrc`` will be created on the remote side.
1046
1046
1047 To pull only a subset of changesets, specify one or more revisions
1047 To pull only a subset of changesets, specify one or more revisions
1048 identifiers with -r/--rev or branches with -b/--branch. The
1048 identifiers with -r/--rev or branches with -b/--branch. The
1049 resulting clone will contain only the specified changesets and
1049 resulting clone will contain only the specified changesets and
1050 their ancestors. These options (or 'clone src#rev dest') imply
1050 their ancestors. These options (or 'clone src#rev dest') imply
1051 --pull, even for local source repositories. Note that specifying a
1051 --pull, even for local source repositories. Note that specifying a
1052 tag will include the tagged changeset but not the changeset
1052 tag will include the tagged changeset but not the changeset
1053 containing the tag.
1053 containing the tag.
1054
1054
1055 To check out a particular version, use -u/--update, or
1055 To check out a particular version, use -u/--update, or
1056 -U/--noupdate to create a clone with no working directory.
1056 -U/--noupdate to create a clone with no working directory.
1057
1057
1058 .. container:: verbose
1058 .. container:: verbose
1059
1059
1060 For efficiency, hardlinks are used for cloning whenever the
1060 For efficiency, hardlinks are used for cloning whenever the
1061 source and destination are on the same filesystem (note this
1061 source and destination are on the same filesystem (note this
1062 applies only to the repository data, not to the working
1062 applies only to the repository data, not to the working
1063 directory). Some filesystems, such as AFS, implement hardlinking
1063 directory). Some filesystems, such as AFS, implement hardlinking
1064 incorrectly, but do not report errors. In these cases, use the
1064 incorrectly, but do not report errors. In these cases, use the
1065 --pull option to avoid hardlinking.
1065 --pull option to avoid hardlinking.
1066
1066
1067 In some cases, you can clone repositories and the working
1067 In some cases, you can clone repositories and the working
1068 directory using full hardlinks with ::
1068 directory using full hardlinks with ::
1069
1069
1070 $ cp -al REPO REPOCLONE
1070 $ cp -al REPO REPOCLONE
1071
1071
1072 This is the fastest way to clone, but it is not always safe. The
1072 This is the fastest way to clone, but it is not always safe. The
1073 operation is not atomic (making sure REPO is not modified during
1073 operation is not atomic (making sure REPO is not modified during
1074 the operation is up to you) and you have to make sure your
1074 the operation is up to you) and you have to make sure your
1075 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1075 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1076 so). Also, this is not compatible with certain extensions that
1076 so). Also, this is not compatible with certain extensions that
1077 place their metadata under the .hg directory, such as mq.
1077 place their metadata under the .hg directory, such as mq.
1078
1078
1079 Mercurial will update the working directory to the first applicable
1079 Mercurial will update the working directory to the first applicable
1080 revision from this list:
1080 revision from this list:
1081
1081
1082 a) null if -U or the source repository has no changesets
1082 a) null if -U or the source repository has no changesets
1083 b) if -u . and the source repository is local, the first parent of
1083 b) if -u . and the source repository is local, the first parent of
1084 the source repository's working directory
1084 the source repository's working directory
1085 c) the changeset specified with -u (if a branch name, this means the
1085 c) the changeset specified with -u (if a branch name, this means the
1086 latest head of that branch)
1086 latest head of that branch)
1087 d) the changeset specified with -r
1087 d) the changeset specified with -r
1088 e) the tipmost head specified with -b
1088 e) the tipmost head specified with -b
1089 f) the tipmost head specified with the url#branch source syntax
1089 f) the tipmost head specified with the url#branch source syntax
1090 g) the tipmost head of the default branch
1090 g) the tipmost head of the default branch
1091 h) tip
1091 h) tip
1092
1092
1093 Examples:
1093 Examples:
1094
1094
1095 - clone a remote repository to a new directory named hg/::
1095 - clone a remote repository to a new directory named hg/::
1096
1096
1097 hg clone http://selenic.com/hg
1097 hg clone http://selenic.com/hg
1098
1098
1099 - create a lightweight local clone::
1099 - create a lightweight local clone::
1100
1100
1101 hg clone project/ project-feature/
1101 hg clone project/ project-feature/
1102
1102
1103 - clone from an absolute path on an ssh server (note double-slash)::
1103 - clone from an absolute path on an ssh server (note double-slash)::
1104
1104
1105 hg clone ssh://user@server//home/projects/alpha/
1105 hg clone ssh://user@server//home/projects/alpha/
1106
1106
1107 - do a high-speed clone over a LAN while checking out a
1107 - do a high-speed clone over a LAN while checking out a
1108 specified version::
1108 specified version::
1109
1109
1110 hg clone --uncompressed http://server/repo -u 1.5
1110 hg clone --uncompressed http://server/repo -u 1.5
1111
1111
1112 - create a repository without changesets after a particular revision::
1112 - create a repository without changesets after a particular revision::
1113
1113
1114 hg clone -r 04e544 experimental/ good/
1114 hg clone -r 04e544 experimental/ good/
1115
1115
1116 - clone (and track) a particular named branch::
1116 - clone (and track) a particular named branch::
1117
1117
1118 hg clone http://selenic.com/hg#stable
1118 hg clone http://selenic.com/hg#stable
1119
1119
1120 See :hg:`help urls` for details on specifying URLs.
1120 See :hg:`help urls` for details on specifying URLs.
1121
1121
1122 Returns 0 on success.
1122 Returns 0 on success.
1123 """
1123 """
1124 if opts.get('noupdate') and opts.get('updaterev'):
1124 if opts.get('noupdate') and opts.get('updaterev'):
1125 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1125 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1126
1126
1127 r = hg.clone(ui, opts, source, dest,
1127 r = hg.clone(ui, opts, source, dest,
1128 pull=opts.get('pull'),
1128 pull=opts.get('pull'),
1129 stream=opts.get('uncompressed'),
1129 stream=opts.get('uncompressed'),
1130 rev=opts.get('rev'),
1130 rev=opts.get('rev'),
1131 update=opts.get('updaterev') or not opts.get('noupdate'),
1131 update=opts.get('updaterev') or not opts.get('noupdate'),
1132 branch=opts.get('branch'))
1132 branch=opts.get('branch'))
1133
1133
1134 return r is None
1134 return r is None
1135
1135
1136 @command('^commit|ci',
1136 @command('^commit|ci',
1137 [('A', 'addremove', None,
1137 [('A', 'addremove', None,
1138 _('mark new/missing files as added/removed before committing')),
1138 _('mark new/missing files as added/removed before committing')),
1139 ('', 'close-branch', None,
1139 ('', 'close-branch', None,
1140 _('mark a branch as closed, hiding it from the branch list')),
1140 _('mark a branch as closed, hiding it from the branch list')),
1141 ] + walkopts + commitopts + commitopts2,
1141 ] + walkopts + commitopts + commitopts2,
1142 _('[OPTION]... [FILE]...'))
1142 _('[OPTION]... [FILE]...'))
1143 def commit(ui, repo, *pats, **opts):
1143 def commit(ui, repo, *pats, **opts):
1144 """commit the specified files or all outstanding changes
1144 """commit the specified files or all outstanding changes
1145
1145
1146 Commit changes to the given files into the repository. Unlike a
1146 Commit changes to the given files into the repository. Unlike a
1147 centralized SCM, this operation is a local operation. See
1147 centralized SCM, this operation is a local operation. See
1148 :hg:`push` for a way to actively distribute your changes.
1148 :hg:`push` for a way to actively distribute your changes.
1149
1149
1150 If a list of files is omitted, all changes reported by :hg:`status`
1150 If a list of files is omitted, all changes reported by :hg:`status`
1151 will be committed.
1151 will be committed.
1152
1152
1153 If you are committing the result of a merge, do not provide any
1153 If you are committing the result of a merge, do not provide any
1154 filenames or -I/-X filters.
1154 filenames or -I/-X filters.
1155
1155
1156 If no commit message is specified, Mercurial starts your
1156 If no commit message is specified, Mercurial starts your
1157 configured editor where you can enter a message. In case your
1157 configured editor where you can enter a message. In case your
1158 commit fails, you will find a backup of your message in
1158 commit fails, you will find a backup of your message in
1159 ``.hg/last-message.txt``.
1159 ``.hg/last-message.txt``.
1160
1160
1161 See :hg:`help dates` for a list of formats valid for -d/--date.
1161 See :hg:`help dates` for a list of formats valid for -d/--date.
1162
1162
1163 Returns 0 on success, 1 if nothing changed.
1163 Returns 0 on success, 1 if nothing changed.
1164 """
1164 """
1165 extra = {}
1165 extra = {}
1166 if opts.get('close_branch'):
1166 if opts.get('close_branch'):
1167 if repo['.'].node() not in repo.branchheads():
1167 if repo['.'].node() not in repo.branchheads():
1168 # The topo heads set is included in the branch heads set of the
1168 # The topo heads set is included in the branch heads set of the
1169 # current branch, so it's sufficient to test branchheads
1169 # current branch, so it's sufficient to test branchheads
1170 raise util.Abort(_('can only close branch heads'))
1170 raise util.Abort(_('can only close branch heads'))
1171 extra['close'] = 1
1171 extra['close'] = 1
1172 e = cmdutil.commiteditor
1172 e = cmdutil.commiteditor
1173 if opts.get('force_editor'):
1173 if opts.get('force_editor'):
1174 e = cmdutil.commitforceeditor
1174 e = cmdutil.commitforceeditor
1175
1175
1176 def commitfunc(ui, repo, message, match, opts):
1176 def commitfunc(ui, repo, message, match, opts):
1177 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1177 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1178 editor=e, extra=extra)
1178 editor=e, extra=extra)
1179
1179
1180 branch = repo[None].branch()
1180 branch = repo[None].branch()
1181 bheads = repo.branchheads(branch)
1181 bheads = repo.branchheads(branch)
1182
1182
1183 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1183 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1184 if not node:
1184 if not node:
1185 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1185 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1186 if stat[3]:
1186 if stat[3]:
1187 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1187 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1188 % len(stat[3]))
1188 % len(stat[3]))
1189 else:
1189 else:
1190 ui.status(_("nothing changed\n"))
1190 ui.status(_("nothing changed\n"))
1191 return 1
1191 return 1
1192
1192
1193 ctx = repo[node]
1193 ctx = repo[node]
1194 parents = ctx.parents()
1194 parents = ctx.parents()
1195
1195
1196 if (bheads and node not in bheads and not
1196 if (bheads and node not in bheads and not
1197 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1197 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1198 ui.status(_('created new head\n'))
1198 ui.status(_('created new head\n'))
1199 # The message is not printed for initial roots. For the other
1199 # The message is not printed for initial roots. For the other
1200 # changesets, it is printed in the following situations:
1200 # changesets, it is printed in the following situations:
1201 #
1201 #
1202 # Par column: for the 2 parents with ...
1202 # Par column: for the 2 parents with ...
1203 # N: null or no parent
1203 # N: null or no parent
1204 # B: parent is on another named branch
1204 # B: parent is on another named branch
1205 # C: parent is a regular non head changeset
1205 # C: parent is a regular non head changeset
1206 # H: parent was a branch head of the current branch
1206 # H: parent was a branch head of the current branch
1207 # Msg column: whether we print "created new head" message
1207 # Msg column: whether we print "created new head" message
1208 # In the following, it is assumed that there already exists some
1208 # In the following, it is assumed that there already exists some
1209 # initial branch heads of the current branch, otherwise nothing is
1209 # initial branch heads of the current branch, otherwise nothing is
1210 # printed anyway.
1210 # printed anyway.
1211 #
1211 #
1212 # Par Msg Comment
1212 # Par Msg Comment
1213 # NN y additional topo root
1213 # NN y additional topo root
1214 #
1214 #
1215 # BN y additional branch root
1215 # BN y additional branch root
1216 # CN y additional topo head
1216 # CN y additional topo head
1217 # HN n usual case
1217 # HN n usual case
1218 #
1218 #
1219 # BB y weird additional branch root
1219 # BB y weird additional branch root
1220 # CB y branch merge
1220 # CB y branch merge
1221 # HB n merge with named branch
1221 # HB n merge with named branch
1222 #
1222 #
1223 # CC y additional head from merge
1223 # CC y additional head from merge
1224 # CH n merge with a head
1224 # CH n merge with a head
1225 #
1225 #
1226 # HH n head merge: head count decreases
1226 # HH n head merge: head count decreases
1227
1227
1228 if not opts.get('close_branch'):
1228 if not opts.get('close_branch'):
1229 for r in parents:
1229 for r in parents:
1230 if r.extra().get('close') and r.branch() == branch:
1230 if r.extra().get('close') and r.branch() == branch:
1231 ui.status(_('reopening closed branch head %d\n') % r)
1231 ui.status(_('reopening closed branch head %d\n') % r)
1232
1232
1233 if ui.debugflag:
1233 if ui.debugflag:
1234 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1234 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1235 elif ui.verbose:
1235 elif ui.verbose:
1236 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1236 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1237
1237
1238 @command('copy|cp',
1238 @command('copy|cp',
1239 [('A', 'after', None, _('record a copy that has already occurred')),
1239 [('A', 'after', None, _('record a copy that has already occurred')),
1240 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1240 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1241 ] + walkopts + dryrunopts,
1241 ] + walkopts + dryrunopts,
1242 _('[OPTION]... [SOURCE]... DEST'))
1242 _('[OPTION]... [SOURCE]... DEST'))
1243 def copy(ui, repo, *pats, **opts):
1243 def copy(ui, repo, *pats, **opts):
1244 """mark files as copied for the next commit
1244 """mark files as copied for the next commit
1245
1245
1246 Mark dest as having copies of source files. If dest is a
1246 Mark dest as having copies of source files. If dest is a
1247 directory, copies are put in that directory. If dest is a file,
1247 directory, copies are put in that directory. If dest is a file,
1248 the source must be a single file.
1248 the source must be a single file.
1249
1249
1250 By default, this command copies the contents of files as they
1250 By default, this command copies the contents of files as they
1251 exist in the working directory. If invoked with -A/--after, the
1251 exist in the working directory. If invoked with -A/--after, the
1252 operation is recorded, but no copying is performed.
1252 operation is recorded, but no copying is performed.
1253
1253
1254 This command takes effect with the next commit. To undo a copy
1254 This command takes effect with the next commit. To undo a copy
1255 before that, see :hg:`revert`.
1255 before that, see :hg:`revert`.
1256
1256
1257 Returns 0 on success, 1 if errors are encountered.
1257 Returns 0 on success, 1 if errors are encountered.
1258 """
1258 """
1259 wlock = repo.wlock(False)
1259 wlock = repo.wlock(False)
1260 try:
1260 try:
1261 return cmdutil.copy(ui, repo, pats, opts)
1261 return cmdutil.copy(ui, repo, pats, opts)
1262 finally:
1262 finally:
1263 wlock.release()
1263 wlock.release()
1264
1264
1265 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1265 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1266 def debugancestor(ui, repo, *args):
1266 def debugancestor(ui, repo, *args):
1267 """find the ancestor revision of two revisions in a given index"""
1267 """find the ancestor revision of two revisions in a given index"""
1268 if len(args) == 3:
1268 if len(args) == 3:
1269 index, rev1, rev2 = args
1269 index, rev1, rev2 = args
1270 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1270 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1271 lookup = r.lookup
1271 lookup = r.lookup
1272 elif len(args) == 2:
1272 elif len(args) == 2:
1273 if not repo:
1273 if not repo:
1274 raise util.Abort(_("there is no Mercurial repository here "
1274 raise util.Abort(_("there is no Mercurial repository here "
1275 "(.hg not found)"))
1275 "(.hg not found)"))
1276 rev1, rev2 = args
1276 rev1, rev2 = args
1277 r = repo.changelog
1277 r = repo.changelog
1278 lookup = repo.lookup
1278 lookup = repo.lookup
1279 else:
1279 else:
1280 raise util.Abort(_('either two or three arguments required'))
1280 raise util.Abort(_('either two or three arguments required'))
1281 a = r.ancestor(lookup(rev1), lookup(rev2))
1281 a = r.ancestor(lookup(rev1), lookup(rev2))
1282 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1282 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1283
1283
1284 @command('debugbuilddag',
1284 @command('debugbuilddag',
1285 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1285 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1286 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1286 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1287 ('n', 'new-file', None, _('add new file at each rev'))],
1287 ('n', 'new-file', None, _('add new file at each rev'))],
1288 _('[OPTION]... [TEXT]'))
1288 _('[OPTION]... [TEXT]'))
1289 def debugbuilddag(ui, repo, text=None,
1289 def debugbuilddag(ui, repo, text=None,
1290 mergeable_file=False,
1290 mergeable_file=False,
1291 overwritten_file=False,
1291 overwritten_file=False,
1292 new_file=False):
1292 new_file=False):
1293 """builds a repo with a given DAG from scratch in the current empty repo
1293 """builds a repo with a given DAG from scratch in the current empty repo
1294
1294
1295 The description of the DAG is read from stdin if not given on the
1295 The description of the DAG is read from stdin if not given on the
1296 command line.
1296 command line.
1297
1297
1298 Elements:
1298 Elements:
1299
1299
1300 - "+n" is a linear run of n nodes based on the current default parent
1300 - "+n" is a linear run of n nodes based on the current default parent
1301 - "." is a single node based on the current default parent
1301 - "." is a single node based on the current default parent
1302 - "$" resets the default parent to null (implied at the start);
1302 - "$" resets the default parent to null (implied at the start);
1303 otherwise the default parent is always the last node created
1303 otherwise the default parent is always the last node created
1304 - "<p" sets the default parent to the backref p
1304 - "<p" sets the default parent to the backref p
1305 - "*p" is a fork at parent p, which is a backref
1305 - "*p" is a fork at parent p, which is a backref
1306 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1306 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1307 - "/p2" is a merge of the preceding node and p2
1307 - "/p2" is a merge of the preceding node and p2
1308 - ":tag" defines a local tag for the preceding node
1308 - ":tag" defines a local tag for the preceding node
1309 - "@branch" sets the named branch for subsequent nodes
1309 - "@branch" sets the named branch for subsequent nodes
1310 - "#...\\n" is a comment up to the end of the line
1310 - "#...\\n" is a comment up to the end of the line
1311
1311
1312 Whitespace between the above elements is ignored.
1312 Whitespace between the above elements is ignored.
1313
1313
1314 A backref is either
1314 A backref is either
1315
1315
1316 - a number n, which references the node curr-n, where curr is the current
1316 - a number n, which references the node curr-n, where curr is the current
1317 node, or
1317 node, or
1318 - the name of a local tag you placed earlier using ":tag", or
1318 - the name of a local tag you placed earlier using ":tag", or
1319 - empty to denote the default parent.
1319 - empty to denote the default parent.
1320
1320
1321 All string valued-elements are either strictly alphanumeric, or must
1321 All string valued-elements are either strictly alphanumeric, or must
1322 be enclosed in double quotes ("..."), with "\\" as escape character.
1322 be enclosed in double quotes ("..."), with "\\" as escape character.
1323 """
1323 """
1324
1324
1325 if text is None:
1325 if text is None:
1326 ui.status(_("reading DAG from stdin\n"))
1326 ui.status(_("reading DAG from stdin\n"))
1327 text = ui.fin.read()
1327 text = ui.fin.read()
1328
1328
1329 cl = repo.changelog
1329 cl = repo.changelog
1330 if len(cl) > 0:
1330 if len(cl) > 0:
1331 raise util.Abort(_('repository is not empty'))
1331 raise util.Abort(_('repository is not empty'))
1332
1332
1333 # determine number of revs in DAG
1333 # determine number of revs in DAG
1334 total = 0
1334 total = 0
1335 for type, data in dagparser.parsedag(text):
1335 for type, data in dagparser.parsedag(text):
1336 if type == 'n':
1336 if type == 'n':
1337 total += 1
1337 total += 1
1338
1338
1339 if mergeable_file:
1339 if mergeable_file:
1340 linesperrev = 2
1340 linesperrev = 2
1341 # make a file with k lines per rev
1341 # make a file with k lines per rev
1342 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1342 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1343 initialmergedlines.append("")
1343 initialmergedlines.append("")
1344
1344
1345 tags = []
1345 tags = []
1346
1346
1347 tr = repo.transaction("builddag")
1347 tr = repo.transaction("builddag")
1348 try:
1348 try:
1349
1349
1350 at = -1
1350 at = -1
1351 atbranch = 'default'
1351 atbranch = 'default'
1352 nodeids = []
1352 nodeids = []
1353 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1353 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1354 for type, data in dagparser.parsedag(text):
1354 for type, data in dagparser.parsedag(text):
1355 if type == 'n':
1355 if type == 'n':
1356 ui.note('node %s\n' % str(data))
1356 ui.note('node %s\n' % str(data))
1357 id, ps = data
1357 id, ps = data
1358
1358
1359 files = []
1359 files = []
1360 fctxs = {}
1360 fctxs = {}
1361
1361
1362 p2 = None
1362 p2 = None
1363 if mergeable_file:
1363 if mergeable_file:
1364 fn = "mf"
1364 fn = "mf"
1365 p1 = repo[ps[0]]
1365 p1 = repo[ps[0]]
1366 if len(ps) > 1:
1366 if len(ps) > 1:
1367 p2 = repo[ps[1]]
1367 p2 = repo[ps[1]]
1368 pa = p1.ancestor(p2)
1368 pa = p1.ancestor(p2)
1369 base, local, other = [x[fn].data() for x in pa, p1, p2]
1369 base, local, other = [x[fn].data() for x in pa, p1, p2]
1370 m3 = simplemerge.Merge3Text(base, local, other)
1370 m3 = simplemerge.Merge3Text(base, local, other)
1371 ml = [l.strip() for l in m3.merge_lines()]
1371 ml = [l.strip() for l in m3.merge_lines()]
1372 ml.append("")
1372 ml.append("")
1373 elif at > 0:
1373 elif at > 0:
1374 ml = p1[fn].data().split("\n")
1374 ml = p1[fn].data().split("\n")
1375 else:
1375 else:
1376 ml = initialmergedlines
1376 ml = initialmergedlines
1377 ml[id * linesperrev] += " r%i" % id
1377 ml[id * linesperrev] += " r%i" % id
1378 mergedtext = "\n".join(ml)
1378 mergedtext = "\n".join(ml)
1379 files.append(fn)
1379 files.append(fn)
1380 fctxs[fn] = context.memfilectx(fn, mergedtext)
1380 fctxs[fn] = context.memfilectx(fn, mergedtext)
1381
1381
1382 if overwritten_file:
1382 if overwritten_file:
1383 fn = "of"
1383 fn = "of"
1384 files.append(fn)
1384 files.append(fn)
1385 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1385 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1386
1386
1387 if new_file:
1387 if new_file:
1388 fn = "nf%i" % id
1388 fn = "nf%i" % id
1389 files.append(fn)
1389 files.append(fn)
1390 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1390 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1391 if len(ps) > 1:
1391 if len(ps) > 1:
1392 if not p2:
1392 if not p2:
1393 p2 = repo[ps[1]]
1393 p2 = repo[ps[1]]
1394 for fn in p2:
1394 for fn in p2:
1395 if fn.startswith("nf"):
1395 if fn.startswith("nf"):
1396 files.append(fn)
1396 files.append(fn)
1397 fctxs[fn] = p2[fn]
1397 fctxs[fn] = p2[fn]
1398
1398
1399 def fctxfn(repo, cx, path):
1399 def fctxfn(repo, cx, path):
1400 return fctxs.get(path)
1400 return fctxs.get(path)
1401
1401
1402 if len(ps) == 0 or ps[0] < 0:
1402 if len(ps) == 0 or ps[0] < 0:
1403 pars = [None, None]
1403 pars = [None, None]
1404 elif len(ps) == 1:
1404 elif len(ps) == 1:
1405 pars = [nodeids[ps[0]], None]
1405 pars = [nodeids[ps[0]], None]
1406 else:
1406 else:
1407 pars = [nodeids[p] for p in ps]
1407 pars = [nodeids[p] for p in ps]
1408 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1408 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1409 date=(id, 0),
1409 date=(id, 0),
1410 user="debugbuilddag",
1410 user="debugbuilddag",
1411 extra={'branch': atbranch})
1411 extra={'branch': atbranch})
1412 nodeid = repo.commitctx(cx)
1412 nodeid = repo.commitctx(cx)
1413 nodeids.append(nodeid)
1413 nodeids.append(nodeid)
1414 at = id
1414 at = id
1415 elif type == 'l':
1415 elif type == 'l':
1416 id, name = data
1416 id, name = data
1417 ui.note('tag %s\n' % name)
1417 ui.note('tag %s\n' % name)
1418 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1418 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1419 elif type == 'a':
1419 elif type == 'a':
1420 ui.note('branch %s\n' % data)
1420 ui.note('branch %s\n' % data)
1421 atbranch = data
1421 atbranch = data
1422 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1422 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1423 tr.close()
1423 tr.close()
1424 finally:
1424 finally:
1425 ui.progress(_('building'), None)
1425 ui.progress(_('building'), None)
1426 tr.release()
1426 tr.release()
1427
1427
1428 if tags:
1428 if tags:
1429 repo.opener.write("localtags", "".join(tags))
1429 repo.opener.write("localtags", "".join(tags))
1430
1430
1431 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1431 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1432 def debugbundle(ui, bundlepath, all=None, **opts):
1432 def debugbundle(ui, bundlepath, all=None, **opts):
1433 """lists the contents of a bundle"""
1433 """lists the contents of a bundle"""
1434 f = url.open(ui, bundlepath)
1434 f = url.open(ui, bundlepath)
1435 try:
1435 try:
1436 gen = changegroup.readbundle(f, bundlepath)
1436 gen = changegroup.readbundle(f, bundlepath)
1437 if all:
1437 if all:
1438 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1438 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1439
1439
1440 def showchunks(named):
1440 def showchunks(named):
1441 ui.write("\n%s\n" % named)
1441 ui.write("\n%s\n" % named)
1442 chain = None
1442 chain = None
1443 while True:
1443 while True:
1444 chunkdata = gen.deltachunk(chain)
1444 chunkdata = gen.deltachunk(chain)
1445 if not chunkdata:
1445 if not chunkdata:
1446 break
1446 break
1447 node = chunkdata['node']
1447 node = chunkdata['node']
1448 p1 = chunkdata['p1']
1448 p1 = chunkdata['p1']
1449 p2 = chunkdata['p2']
1449 p2 = chunkdata['p2']
1450 cs = chunkdata['cs']
1450 cs = chunkdata['cs']
1451 deltabase = chunkdata['deltabase']
1451 deltabase = chunkdata['deltabase']
1452 delta = chunkdata['delta']
1452 delta = chunkdata['delta']
1453 ui.write("%s %s %s %s %s %s\n" %
1453 ui.write("%s %s %s %s %s %s\n" %
1454 (hex(node), hex(p1), hex(p2),
1454 (hex(node), hex(p1), hex(p2),
1455 hex(cs), hex(deltabase), len(delta)))
1455 hex(cs), hex(deltabase), len(delta)))
1456 chain = node
1456 chain = node
1457
1457
1458 chunkdata = gen.changelogheader()
1458 chunkdata = gen.changelogheader()
1459 showchunks("changelog")
1459 showchunks("changelog")
1460 chunkdata = gen.manifestheader()
1460 chunkdata = gen.manifestheader()
1461 showchunks("manifest")
1461 showchunks("manifest")
1462 while True:
1462 while True:
1463 chunkdata = gen.filelogheader()
1463 chunkdata = gen.filelogheader()
1464 if not chunkdata:
1464 if not chunkdata:
1465 break
1465 break
1466 fname = chunkdata['filename']
1466 fname = chunkdata['filename']
1467 showchunks(fname)
1467 showchunks(fname)
1468 else:
1468 else:
1469 chunkdata = gen.changelogheader()
1469 chunkdata = gen.changelogheader()
1470 chain = None
1470 chain = None
1471 while True:
1471 while True:
1472 chunkdata = gen.deltachunk(chain)
1472 chunkdata = gen.deltachunk(chain)
1473 if not chunkdata:
1473 if not chunkdata:
1474 break
1474 break
1475 node = chunkdata['node']
1475 node = chunkdata['node']
1476 ui.write("%s\n" % hex(node))
1476 ui.write("%s\n" % hex(node))
1477 chain = node
1477 chain = node
1478 finally:
1478 finally:
1479 f.close()
1479 f.close()
1480
1480
1481 @command('debugcheckstate', [], '')
1481 @command('debugcheckstate', [], '')
1482 def debugcheckstate(ui, repo):
1482 def debugcheckstate(ui, repo):
1483 """validate the correctness of the current dirstate"""
1483 """validate the correctness of the current dirstate"""
1484 parent1, parent2 = repo.dirstate.parents()
1484 parent1, parent2 = repo.dirstate.parents()
1485 m1 = repo[parent1].manifest()
1485 m1 = repo[parent1].manifest()
1486 m2 = repo[parent2].manifest()
1486 m2 = repo[parent2].manifest()
1487 errors = 0
1487 errors = 0
1488 for f in repo.dirstate:
1488 for f in repo.dirstate:
1489 state = repo.dirstate[f]
1489 state = repo.dirstate[f]
1490 if state in "nr" and f not in m1:
1490 if state in "nr" and f not in m1:
1491 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1491 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1492 errors += 1
1492 errors += 1
1493 if state in "a" and f in m1:
1493 if state in "a" and f in m1:
1494 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1494 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1495 errors += 1
1495 errors += 1
1496 if state in "m" and f not in m1 and f not in m2:
1496 if state in "m" and f not in m1 and f not in m2:
1497 ui.warn(_("%s in state %s, but not in either manifest\n") %
1497 ui.warn(_("%s in state %s, but not in either manifest\n") %
1498 (f, state))
1498 (f, state))
1499 errors += 1
1499 errors += 1
1500 for f in m1:
1500 for f in m1:
1501 state = repo.dirstate[f]
1501 state = repo.dirstate[f]
1502 if state not in "nrm":
1502 if state not in "nrm":
1503 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1503 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1504 errors += 1
1504 errors += 1
1505 if errors:
1505 if errors:
1506 error = _(".hg/dirstate inconsistent with current parent's manifest")
1506 error = _(".hg/dirstate inconsistent with current parent's manifest")
1507 raise util.Abort(error)
1507 raise util.Abort(error)
1508
1508
1509 @command('debugcommands', [], _('[COMMAND]'))
1509 @command('debugcommands', [], _('[COMMAND]'))
1510 def debugcommands(ui, cmd='', *args):
1510 def debugcommands(ui, cmd='', *args):
1511 """list all available commands and options"""
1511 """list all available commands and options"""
1512 for cmd, vals in sorted(table.iteritems()):
1512 for cmd, vals in sorted(table.iteritems()):
1513 cmd = cmd.split('|')[0].strip('^')
1513 cmd = cmd.split('|')[0].strip('^')
1514 opts = ', '.join([i[1] for i in vals[1]])
1514 opts = ', '.join([i[1] for i in vals[1]])
1515 ui.write('%s: %s\n' % (cmd, opts))
1515 ui.write('%s: %s\n' % (cmd, opts))
1516
1516
1517 @command('debugcomplete',
1517 @command('debugcomplete',
1518 [('o', 'options', None, _('show the command options'))],
1518 [('o', 'options', None, _('show the command options'))],
1519 _('[-o] CMD'))
1519 _('[-o] CMD'))
1520 def debugcomplete(ui, cmd='', **opts):
1520 def debugcomplete(ui, cmd='', **opts):
1521 """returns the completion list associated with the given command"""
1521 """returns the completion list associated with the given command"""
1522
1522
1523 if opts.get('options'):
1523 if opts.get('options'):
1524 options = []
1524 options = []
1525 otables = [globalopts]
1525 otables = [globalopts]
1526 if cmd:
1526 if cmd:
1527 aliases, entry = cmdutil.findcmd(cmd, table, False)
1527 aliases, entry = cmdutil.findcmd(cmd, table, False)
1528 otables.append(entry[1])
1528 otables.append(entry[1])
1529 for t in otables:
1529 for t in otables:
1530 for o in t:
1530 for o in t:
1531 if "(DEPRECATED)" in o[3]:
1531 if "(DEPRECATED)" in o[3]:
1532 continue
1532 continue
1533 if o[0]:
1533 if o[0]:
1534 options.append('-%s' % o[0])
1534 options.append('-%s' % o[0])
1535 options.append('--%s' % o[1])
1535 options.append('--%s' % o[1])
1536 ui.write("%s\n" % "\n".join(options))
1536 ui.write("%s\n" % "\n".join(options))
1537 return
1537 return
1538
1538
1539 cmdlist = cmdutil.findpossible(cmd, table)
1539 cmdlist = cmdutil.findpossible(cmd, table)
1540 if ui.verbose:
1540 if ui.verbose:
1541 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1541 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1542 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1542 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1543
1543
1544 @command('debugdag',
1544 @command('debugdag',
1545 [('t', 'tags', None, _('use tags as labels')),
1545 [('t', 'tags', None, _('use tags as labels')),
1546 ('b', 'branches', None, _('annotate with branch names')),
1546 ('b', 'branches', None, _('annotate with branch names')),
1547 ('', 'dots', None, _('use dots for runs')),
1547 ('', 'dots', None, _('use dots for runs')),
1548 ('s', 'spaces', None, _('separate elements by spaces'))],
1548 ('s', 'spaces', None, _('separate elements by spaces'))],
1549 _('[OPTION]... [FILE [REV]...]'))
1549 _('[OPTION]... [FILE [REV]...]'))
1550 def debugdag(ui, repo, file_=None, *revs, **opts):
1550 def debugdag(ui, repo, file_=None, *revs, **opts):
1551 """format the changelog or an index DAG as a concise textual description
1551 """format the changelog or an index DAG as a concise textual description
1552
1552
1553 If you pass a revlog index, the revlog's DAG is emitted. If you list
1553 If you pass a revlog index, the revlog's DAG is emitted. If you list
1554 revision numbers, they get labelled in the output as rN.
1554 revision numbers, they get labelled in the output as rN.
1555
1555
1556 Otherwise, the changelog DAG of the current repo is emitted.
1556 Otherwise, the changelog DAG of the current repo is emitted.
1557 """
1557 """
1558 spaces = opts.get('spaces')
1558 spaces = opts.get('spaces')
1559 dots = opts.get('dots')
1559 dots = opts.get('dots')
1560 if file_:
1560 if file_:
1561 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1561 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1562 revs = set((int(r) for r in revs))
1562 revs = set((int(r) for r in revs))
1563 def events():
1563 def events():
1564 for r in rlog:
1564 for r in rlog:
1565 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1565 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1566 if r in revs:
1566 if r in revs:
1567 yield 'l', (r, "r%i" % r)
1567 yield 'l', (r, "r%i" % r)
1568 elif repo:
1568 elif repo:
1569 cl = repo.changelog
1569 cl = repo.changelog
1570 tags = opts.get('tags')
1570 tags = opts.get('tags')
1571 branches = opts.get('branches')
1571 branches = opts.get('branches')
1572 if tags:
1572 if tags:
1573 labels = {}
1573 labels = {}
1574 for l, n in repo.tags().items():
1574 for l, n in repo.tags().items():
1575 labels.setdefault(cl.rev(n), []).append(l)
1575 labels.setdefault(cl.rev(n), []).append(l)
1576 def events():
1576 def events():
1577 b = "default"
1577 b = "default"
1578 for r in cl:
1578 for r in cl:
1579 if branches:
1579 if branches:
1580 newb = cl.read(cl.node(r))[5]['branch']
1580 newb = cl.read(cl.node(r))[5]['branch']
1581 if newb != b:
1581 if newb != b:
1582 yield 'a', newb
1582 yield 'a', newb
1583 b = newb
1583 b = newb
1584 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1584 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1585 if tags:
1585 if tags:
1586 ls = labels.get(r)
1586 ls = labels.get(r)
1587 if ls:
1587 if ls:
1588 for l in ls:
1588 for l in ls:
1589 yield 'l', (r, l)
1589 yield 'l', (r, l)
1590 else:
1590 else:
1591 raise util.Abort(_('need repo for changelog dag'))
1591 raise util.Abort(_('need repo for changelog dag'))
1592
1592
1593 for line in dagparser.dagtextlines(events(),
1593 for line in dagparser.dagtextlines(events(),
1594 addspaces=spaces,
1594 addspaces=spaces,
1595 wraplabels=True,
1595 wraplabels=True,
1596 wrapannotations=True,
1596 wrapannotations=True,
1597 wrapnonlinear=dots,
1597 wrapnonlinear=dots,
1598 usedots=dots,
1598 usedots=dots,
1599 maxlinewidth=70):
1599 maxlinewidth=70):
1600 ui.write(line)
1600 ui.write(line)
1601 ui.write("\n")
1601 ui.write("\n")
1602
1602
1603 @command('debugdata',
1603 @command('debugdata',
1604 [('c', 'changelog', False, _('open changelog')),
1604 [('c', 'changelog', False, _('open changelog')),
1605 ('m', 'manifest', False, _('open manifest'))],
1605 ('m', 'manifest', False, _('open manifest'))],
1606 _('-c|-m|FILE REV'))
1606 _('-c|-m|FILE REV'))
1607 def debugdata(ui, repo, file_, rev = None, **opts):
1607 def debugdata(ui, repo, file_, rev = None, **opts):
1608 """dump the contents of a data file revision"""
1608 """dump the contents of a data file revision"""
1609 if opts.get('changelog') or opts.get('manifest'):
1609 if opts.get('changelog') or opts.get('manifest'):
1610 file_, rev = None, file_
1610 file_, rev = None, file_
1611 elif rev is None:
1611 elif rev is None:
1612 raise error.CommandError('debugdata', _('invalid arguments'))
1612 raise error.CommandError('debugdata', _('invalid arguments'))
1613 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1613 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1614 try:
1614 try:
1615 ui.write(r.revision(r.lookup(rev)))
1615 ui.write(r.revision(r.lookup(rev)))
1616 except KeyError:
1616 except KeyError:
1617 raise util.Abort(_('invalid revision identifier %s') % rev)
1617 raise util.Abort(_('invalid revision identifier %s') % rev)
1618
1618
1619 @command('debugdate',
1619 @command('debugdate',
1620 [('e', 'extended', None, _('try extended date formats'))],
1620 [('e', 'extended', None, _('try extended date formats'))],
1621 _('[-e] DATE [RANGE]'))
1621 _('[-e] DATE [RANGE]'))
1622 def debugdate(ui, date, range=None, **opts):
1622 def debugdate(ui, date, range=None, **opts):
1623 """parse and display a date"""
1623 """parse and display a date"""
1624 if opts["extended"]:
1624 if opts["extended"]:
1625 d = util.parsedate(date, util.extendeddateformats)
1625 d = util.parsedate(date, util.extendeddateformats)
1626 else:
1626 else:
1627 d = util.parsedate(date)
1627 d = util.parsedate(date)
1628 ui.write("internal: %s %s\n" % d)
1628 ui.write("internal: %s %s\n" % d)
1629 ui.write("standard: %s\n" % util.datestr(d))
1629 ui.write("standard: %s\n" % util.datestr(d))
1630 if range:
1630 if range:
1631 m = util.matchdate(range)
1631 m = util.matchdate(range)
1632 ui.write("match: %s\n" % m(d[0]))
1632 ui.write("match: %s\n" % m(d[0]))
1633
1633
1634 @command('debugdiscovery',
1634 @command('debugdiscovery',
1635 [('', 'old', None, _('use old-style discovery')),
1635 [('', 'old', None, _('use old-style discovery')),
1636 ('', 'nonheads', None,
1636 ('', 'nonheads', None,
1637 _('use old-style discovery with non-heads included')),
1637 _('use old-style discovery with non-heads included')),
1638 ] + remoteopts,
1638 ] + remoteopts,
1639 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1639 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1640 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1640 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1641 """runs the changeset discovery protocol in isolation"""
1641 """runs the changeset discovery protocol in isolation"""
1642 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1642 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1643 remote = hg.peer(repo, opts, remoteurl)
1643 remote = hg.peer(repo, opts, remoteurl)
1644 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1644 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1645
1645
1646 # make sure tests are repeatable
1646 # make sure tests are repeatable
1647 random.seed(12323)
1647 random.seed(12323)
1648
1648
1649 def doit(localheads, remoteheads):
1649 def doit(localheads, remoteheads):
1650 if opts.get('old'):
1650 if opts.get('old'):
1651 if localheads:
1651 if localheads:
1652 raise util.Abort('cannot use localheads with old style discovery')
1652 raise util.Abort('cannot use localheads with old style discovery')
1653 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1653 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1654 force=True)
1654 force=True)
1655 common = set(common)
1655 common = set(common)
1656 if not opts.get('nonheads'):
1656 if not opts.get('nonheads'):
1657 ui.write("unpruned common: %s\n" % " ".join([short(n)
1657 ui.write("unpruned common: %s\n" % " ".join([short(n)
1658 for n in common]))
1658 for n in common]))
1659 dag = dagutil.revlogdag(repo.changelog)
1659 dag = dagutil.revlogdag(repo.changelog)
1660 all = dag.ancestorset(dag.internalizeall(common))
1660 all = dag.ancestorset(dag.internalizeall(common))
1661 common = dag.externalizeall(dag.headsetofconnecteds(all))
1661 common = dag.externalizeall(dag.headsetofconnecteds(all))
1662 else:
1662 else:
1663 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1663 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1664 common = set(common)
1664 common = set(common)
1665 rheads = set(hds)
1665 rheads = set(hds)
1666 lheads = set(repo.heads())
1666 lheads = set(repo.heads())
1667 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1667 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1668 if lheads <= common:
1668 if lheads <= common:
1669 ui.write("local is subset\n")
1669 ui.write("local is subset\n")
1670 elif rheads <= common:
1670 elif rheads <= common:
1671 ui.write("remote is subset\n")
1671 ui.write("remote is subset\n")
1672
1672
1673 serverlogs = opts.get('serverlog')
1673 serverlogs = opts.get('serverlog')
1674 if serverlogs:
1674 if serverlogs:
1675 for filename in serverlogs:
1675 for filename in serverlogs:
1676 logfile = open(filename, 'r')
1676 logfile = open(filename, 'r')
1677 try:
1677 try:
1678 line = logfile.readline()
1678 line = logfile.readline()
1679 while line:
1679 while line:
1680 parts = line.strip().split(';')
1680 parts = line.strip().split(';')
1681 op = parts[1]
1681 op = parts[1]
1682 if op == 'cg':
1682 if op == 'cg':
1683 pass
1683 pass
1684 elif op == 'cgss':
1684 elif op == 'cgss':
1685 doit(parts[2].split(' '), parts[3].split(' '))
1685 doit(parts[2].split(' '), parts[3].split(' '))
1686 elif op == 'unb':
1686 elif op == 'unb':
1687 doit(parts[3].split(' '), parts[2].split(' '))
1687 doit(parts[3].split(' '), parts[2].split(' '))
1688 line = logfile.readline()
1688 line = logfile.readline()
1689 finally:
1689 finally:
1690 logfile.close()
1690 logfile.close()
1691
1691
1692 else:
1692 else:
1693 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1693 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1694 opts.get('remote_head'))
1694 opts.get('remote_head'))
1695 localrevs = opts.get('local_head')
1695 localrevs = opts.get('local_head')
1696 doit(localrevs, remoterevs)
1696 doit(localrevs, remoterevs)
1697
1697
1698 @command('debugfileset', [], ('REVSPEC'))
1698 @command('debugfileset', [], ('REVSPEC'))
1699 def debugfileset(ui, repo, expr):
1699 def debugfileset(ui, repo, expr):
1700 '''parse and apply a fileset specification'''
1700 '''parse and apply a fileset specification'''
1701 if ui.verbose:
1701 if ui.verbose:
1702 tree = fileset.parse(expr)[0]
1702 tree = fileset.parse(expr)[0]
1703 ui.note(tree, "\n")
1703 ui.note(tree, "\n")
1704
1704
1705 for f in fileset.getfileset(repo[None], expr):
1705 for f in fileset.getfileset(repo[None], expr):
1706 ui.write("%s\n" % f)
1706 ui.write("%s\n" % f)
1707
1707
1708 @command('debugfsinfo', [], _('[PATH]'))
1708 @command('debugfsinfo', [], _('[PATH]'))
1709 def debugfsinfo(ui, path = "."):
1709 def debugfsinfo(ui, path = "."):
1710 """show information detected about current filesystem"""
1710 """show information detected about current filesystem"""
1711 util.writefile('.debugfsinfo', '')
1711 util.writefile('.debugfsinfo', '')
1712 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1712 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1713 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1713 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1714 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1714 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1715 and 'yes' or 'no'))
1715 and 'yes' or 'no'))
1716 os.unlink('.debugfsinfo')
1716 os.unlink('.debugfsinfo')
1717
1717
1718 @command('debuggetbundle',
1718 @command('debuggetbundle',
1719 [('H', 'head', [], _('id of head node'), _('ID')),
1719 [('H', 'head', [], _('id of head node'), _('ID')),
1720 ('C', 'common', [], _('id of common node'), _('ID')),
1720 ('C', 'common', [], _('id of common node'), _('ID')),
1721 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1721 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1722 _('REPO FILE [-H|-C ID]...'))
1722 _('REPO FILE [-H|-C ID]...'))
1723 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1723 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1724 """retrieves a bundle from a repo
1724 """retrieves a bundle from a repo
1725
1725
1726 Every ID must be a full-length hex node id string. Saves the bundle to the
1726 Every ID must be a full-length hex node id string. Saves the bundle to the
1727 given file.
1727 given file.
1728 """
1728 """
1729 repo = hg.peer(ui, opts, repopath)
1729 repo = hg.peer(ui, opts, repopath)
1730 if not repo.capable('getbundle'):
1730 if not repo.capable('getbundle'):
1731 raise util.Abort("getbundle() not supported by target repository")
1731 raise util.Abort("getbundle() not supported by target repository")
1732 args = {}
1732 args = {}
1733 if common:
1733 if common:
1734 args['common'] = [bin(s) for s in common]
1734 args['common'] = [bin(s) for s in common]
1735 if head:
1735 if head:
1736 args['heads'] = [bin(s) for s in head]
1736 args['heads'] = [bin(s) for s in head]
1737 bundle = repo.getbundle('debug', **args)
1737 bundle = repo.getbundle('debug', **args)
1738
1738
1739 bundletype = opts.get('type', 'bzip2').lower()
1739 bundletype = opts.get('type', 'bzip2').lower()
1740 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1740 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1741 bundletype = btypes.get(bundletype)
1741 bundletype = btypes.get(bundletype)
1742 if bundletype not in changegroup.bundletypes:
1742 if bundletype not in changegroup.bundletypes:
1743 raise util.Abort(_('unknown bundle type specified with --type'))
1743 raise util.Abort(_('unknown bundle type specified with --type'))
1744 changegroup.writebundle(bundle, bundlepath, bundletype)
1744 changegroup.writebundle(bundle, bundlepath, bundletype)
1745
1745
1746 @command('debugignore', [], '')
1746 @command('debugignore', [], '')
1747 def debugignore(ui, repo, *values, **opts):
1747 def debugignore(ui, repo, *values, **opts):
1748 """display the combined ignore pattern"""
1748 """display the combined ignore pattern"""
1749 ignore = repo.dirstate._ignore
1749 ignore = repo.dirstate._ignore
1750 includepat = getattr(ignore, 'includepat', None)
1750 includepat = getattr(ignore, 'includepat', None)
1751 if includepat is not None:
1751 if includepat is not None:
1752 ui.write("%s\n" % includepat)
1752 ui.write("%s\n" % includepat)
1753 else:
1753 else:
1754 raise util.Abort(_("no ignore patterns found"))
1754 raise util.Abort(_("no ignore patterns found"))
1755
1755
1756 @command('debugindex',
1756 @command('debugindex',
1757 [('c', 'changelog', False, _('open changelog')),
1757 [('c', 'changelog', False, _('open changelog')),
1758 ('m', 'manifest', False, _('open manifest')),
1758 ('m', 'manifest', False, _('open manifest')),
1759 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1759 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1760 _('[-f FORMAT] -c|-m|FILE'))
1760 _('[-f FORMAT] -c|-m|FILE'))
1761 def debugindex(ui, repo, file_ = None, **opts):
1761 def debugindex(ui, repo, file_ = None, **opts):
1762 """dump the contents of an index file"""
1762 """dump the contents of an index file"""
1763 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1763 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1764 format = opts.get('format', 0)
1764 format = opts.get('format', 0)
1765 if format not in (0, 1):
1765 if format not in (0, 1):
1766 raise util.Abort(_("unknown format %d") % format)
1766 raise util.Abort(_("unknown format %d") % format)
1767
1767
1768 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1768 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1769 if generaldelta:
1769 if generaldelta:
1770 basehdr = ' delta'
1770 basehdr = ' delta'
1771 else:
1771 else:
1772 basehdr = ' base'
1772 basehdr = ' base'
1773
1773
1774 if format == 0:
1774 if format == 0:
1775 ui.write(" rev offset length " + basehdr + " linkrev"
1775 ui.write(" rev offset length " + basehdr + " linkrev"
1776 " nodeid p1 p2\n")
1776 " nodeid p1 p2\n")
1777 elif format == 1:
1777 elif format == 1:
1778 ui.write(" rev flag offset length"
1778 ui.write(" rev flag offset length"
1779 " size " + basehdr + " link p1 p2 nodeid\n")
1779 " size " + basehdr + " link p1 p2 nodeid\n")
1780
1780
1781 for i in r:
1781 for i in r:
1782 node = r.node(i)
1782 node = r.node(i)
1783 if generaldelta:
1783 if generaldelta:
1784 base = r.deltaparent(i)
1784 base = r.deltaparent(i)
1785 else:
1785 else:
1786 base = r.chainbase(i)
1786 base = r.chainbase(i)
1787 if format == 0:
1787 if format == 0:
1788 try:
1788 try:
1789 pp = r.parents(node)
1789 pp = r.parents(node)
1790 except:
1790 except:
1791 pp = [nullid, nullid]
1791 pp = [nullid, nullid]
1792 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1792 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1793 i, r.start(i), r.length(i), base, r.linkrev(i),
1793 i, r.start(i), r.length(i), base, r.linkrev(i),
1794 short(node), short(pp[0]), short(pp[1])))
1794 short(node), short(pp[0]), short(pp[1])))
1795 elif format == 1:
1795 elif format == 1:
1796 pr = r.parentrevs(i)
1796 pr = r.parentrevs(i)
1797 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1797 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1798 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1798 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1799 base, r.linkrev(i), pr[0], pr[1], short(node)))
1799 base, r.linkrev(i), pr[0], pr[1], short(node)))
1800
1800
1801 @command('debugindexdot', [], _('FILE'))
1801 @command('debugindexdot', [], _('FILE'))
1802 def debugindexdot(ui, repo, file_):
1802 def debugindexdot(ui, repo, file_):
1803 """dump an index DAG as a graphviz dot file"""
1803 """dump an index DAG as a graphviz dot file"""
1804 r = None
1804 r = None
1805 if repo:
1805 if repo:
1806 filelog = repo.file(file_)
1806 filelog = repo.file(file_)
1807 if len(filelog):
1807 if len(filelog):
1808 r = filelog
1808 r = filelog
1809 if not r:
1809 if not r:
1810 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1810 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1811 ui.write("digraph G {\n")
1811 ui.write("digraph G {\n")
1812 for i in r:
1812 for i in r:
1813 node = r.node(i)
1813 node = r.node(i)
1814 pp = r.parents(node)
1814 pp = r.parents(node)
1815 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1815 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1816 if pp[1] != nullid:
1816 if pp[1] != nullid:
1817 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1817 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1818 ui.write("}\n")
1818 ui.write("}\n")
1819
1819
1820 @command('debuginstall', [], '')
1820 @command('debuginstall', [], '')
1821 def debuginstall(ui):
1821 def debuginstall(ui):
1822 '''test Mercurial installation
1822 '''test Mercurial installation
1823
1823
1824 Returns 0 on success.
1824 Returns 0 on success.
1825 '''
1825 '''
1826
1826
1827 def writetemp(contents):
1827 def writetemp(contents):
1828 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1828 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1829 f = os.fdopen(fd, "wb")
1829 f = os.fdopen(fd, "wb")
1830 f.write(contents)
1830 f.write(contents)
1831 f.close()
1831 f.close()
1832 return name
1832 return name
1833
1833
1834 problems = 0
1834 problems = 0
1835
1835
1836 # encoding
1836 # encoding
1837 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1837 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1838 try:
1838 try:
1839 encoding.fromlocal("test")
1839 encoding.fromlocal("test")
1840 except util.Abort, inst:
1840 except util.Abort, inst:
1841 ui.write(" %s\n" % inst)
1841 ui.write(" %s\n" % inst)
1842 ui.write(_(" (check that your locale is properly set)\n"))
1842 ui.write(_(" (check that your locale is properly set)\n"))
1843 problems += 1
1843 problems += 1
1844
1844
1845 # compiled modules
1845 # compiled modules
1846 ui.status(_("Checking installed modules (%s)...\n")
1846 ui.status(_("Checking installed modules (%s)...\n")
1847 % os.path.dirname(__file__))
1847 % os.path.dirname(__file__))
1848 try:
1848 try:
1849 import bdiff, mpatch, base85, osutil
1849 import bdiff, mpatch, base85, osutil
1850 except Exception, inst:
1850 except Exception, inst:
1851 ui.write(" %s\n" % inst)
1851 ui.write(" %s\n" % inst)
1852 ui.write(_(" One or more extensions could not be found"))
1852 ui.write(_(" One or more extensions could not be found"))
1853 ui.write(_(" (check that you compiled the extensions)\n"))
1853 ui.write(_(" (check that you compiled the extensions)\n"))
1854 problems += 1
1854 problems += 1
1855
1855
1856 # templates
1856 # templates
1857 ui.status(_("Checking templates...\n"))
1857 ui.status(_("Checking templates...\n"))
1858 try:
1858 try:
1859 import templater
1859 import templater
1860 templater.templater(templater.templatepath("map-cmdline.default"))
1860 templater.templater(templater.templatepath("map-cmdline.default"))
1861 except Exception, inst:
1861 except Exception, inst:
1862 ui.write(" %s\n" % inst)
1862 ui.write(" %s\n" % inst)
1863 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1863 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1864 problems += 1
1864 problems += 1
1865
1865
1866 # editor
1866 # editor
1867 ui.status(_("Checking commit editor...\n"))
1867 ui.status(_("Checking commit editor...\n"))
1868 editor = ui.geteditor()
1868 editor = ui.geteditor()
1869 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1869 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1870 if not cmdpath:
1870 if not cmdpath:
1871 if editor == 'vi':
1871 if editor == 'vi':
1872 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1872 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1873 ui.write(_(" (specify a commit editor in your configuration"
1873 ui.write(_(" (specify a commit editor in your configuration"
1874 " file)\n"))
1874 " file)\n"))
1875 else:
1875 else:
1876 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1876 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1877 ui.write(_(" (specify a commit editor in your configuration"
1877 ui.write(_(" (specify a commit editor in your configuration"
1878 " file)\n"))
1878 " file)\n"))
1879 problems += 1
1879 problems += 1
1880
1880
1881 # check username
1881 # check username
1882 ui.status(_("Checking username...\n"))
1882 ui.status(_("Checking username...\n"))
1883 try:
1883 try:
1884 ui.username()
1884 ui.username()
1885 except util.Abort, e:
1885 except util.Abort, e:
1886 ui.write(" %s\n" % e)
1886 ui.write(" %s\n" % e)
1887 ui.write(_(" (specify a username in your configuration file)\n"))
1887 ui.write(_(" (specify a username in your configuration file)\n"))
1888 problems += 1
1888 problems += 1
1889
1889
1890 if not problems:
1890 if not problems:
1891 ui.status(_("No problems detected\n"))
1891 ui.status(_("No problems detected\n"))
1892 else:
1892 else:
1893 ui.write(_("%s problems detected,"
1893 ui.write(_("%s problems detected,"
1894 " please check your install!\n") % problems)
1894 " please check your install!\n") % problems)
1895
1895
1896 return problems
1896 return problems
1897
1897
1898 @command('debugknown', [], _('REPO ID...'))
1898 @command('debugknown', [], _('REPO ID...'))
1899 def debugknown(ui, repopath, *ids, **opts):
1899 def debugknown(ui, repopath, *ids, **opts):
1900 """test whether node ids are known to a repo
1900 """test whether node ids are known to a repo
1901
1901
1902 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1902 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1903 indicating unknown/known.
1903 indicating unknown/known.
1904 """
1904 """
1905 repo = hg.peer(ui, opts, repopath)
1905 repo = hg.peer(ui, opts, repopath)
1906 if not repo.capable('known'):
1906 if not repo.capable('known'):
1907 raise util.Abort("known() not supported by target repository")
1907 raise util.Abort("known() not supported by target repository")
1908 flags = repo.known([bin(s) for s in ids])
1908 flags = repo.known([bin(s) for s in ids])
1909 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1909 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1910
1910
1911 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1911 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1912 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1912 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1913 '''access the pushkey key/value protocol
1913 '''access the pushkey key/value protocol
1914
1914
1915 With two args, list the keys in the given namespace.
1915 With two args, list the keys in the given namespace.
1916
1916
1917 With five args, set a key to new if it currently is set to old.
1917 With five args, set a key to new if it currently is set to old.
1918 Reports success or failure.
1918 Reports success or failure.
1919 '''
1919 '''
1920
1920
1921 target = hg.peer(ui, {}, repopath)
1921 target = hg.peer(ui, {}, repopath)
1922 if keyinfo:
1922 if keyinfo:
1923 key, old, new = keyinfo
1923 key, old, new = keyinfo
1924 r = target.pushkey(namespace, key, old, new)
1924 r = target.pushkey(namespace, key, old, new)
1925 ui.status(str(r) + '\n')
1925 ui.status(str(r) + '\n')
1926 return not r
1926 return not r
1927 else:
1927 else:
1928 for k, v in target.listkeys(namespace).iteritems():
1928 for k, v in target.listkeys(namespace).iteritems():
1929 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1929 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1930 v.encode('string-escape')))
1930 v.encode('string-escape')))
1931
1931
1932 @command('debugrebuildstate',
1932 @command('debugrebuildstate',
1933 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1933 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1934 _('[-r REV] [REV]'))
1934 _('[-r REV] [REV]'))
1935 def debugrebuildstate(ui, repo, rev="tip"):
1935 def debugrebuildstate(ui, repo, rev="tip"):
1936 """rebuild the dirstate as it would look like for the given revision"""
1936 """rebuild the dirstate as it would look like for the given revision"""
1937 ctx = scmutil.revsingle(repo, rev)
1937 ctx = scmutil.revsingle(repo, rev)
1938 wlock = repo.wlock()
1938 wlock = repo.wlock()
1939 try:
1939 try:
1940 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1940 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1941 finally:
1941 finally:
1942 wlock.release()
1942 wlock.release()
1943
1943
1944 @command('debugrename',
1944 @command('debugrename',
1945 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1945 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1946 _('[-r REV] FILE'))
1946 _('[-r REV] FILE'))
1947 def debugrename(ui, repo, file1, *pats, **opts):
1947 def debugrename(ui, repo, file1, *pats, **opts):
1948 """dump rename information"""
1948 """dump rename information"""
1949
1949
1950 ctx = scmutil.revsingle(repo, opts.get('rev'))
1950 ctx = scmutil.revsingle(repo, opts.get('rev'))
1951 m = scmutil.match(ctx, (file1,) + pats, opts)
1951 m = scmutil.match(ctx, (file1,) + pats, opts)
1952 for abs in ctx.walk(m):
1952 for abs in ctx.walk(m):
1953 fctx = ctx[abs]
1953 fctx = ctx[abs]
1954 o = fctx.filelog().renamed(fctx.filenode())
1954 o = fctx.filelog().renamed(fctx.filenode())
1955 rel = m.rel(abs)
1955 rel = m.rel(abs)
1956 if o:
1956 if o:
1957 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1957 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1958 else:
1958 else:
1959 ui.write(_("%s not renamed\n") % rel)
1959 ui.write(_("%s not renamed\n") % rel)
1960
1960
1961 @command('debugrevlog',
1961 @command('debugrevlog',
1962 [('c', 'changelog', False, _('open changelog')),
1962 [('c', 'changelog', False, _('open changelog')),
1963 ('m', 'manifest', False, _('open manifest')),
1963 ('m', 'manifest', False, _('open manifest')),
1964 ('d', 'dump', False, _('dump index data'))],
1964 ('d', 'dump', False, _('dump index data'))],
1965 _('-c|-m|FILE'))
1965 _('-c|-m|FILE'))
1966 def debugrevlog(ui, repo, file_ = None, **opts):
1966 def debugrevlog(ui, repo, file_ = None, **opts):
1967 """show data and statistics about a revlog"""
1967 """show data and statistics about a revlog"""
1968 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1968 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1969
1969
1970 if opts.get("dump"):
1970 if opts.get("dump"):
1971 numrevs = len(r)
1971 numrevs = len(r)
1972 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1972 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1973 " rawsize totalsize compression heads\n")
1973 " rawsize totalsize compression heads\n")
1974 ts = 0
1974 ts = 0
1975 heads = set()
1975 heads = set()
1976 for rev in xrange(numrevs):
1976 for rev in xrange(numrevs):
1977 dbase = r.deltaparent(rev)
1977 dbase = r.deltaparent(rev)
1978 if dbase == -1:
1978 if dbase == -1:
1979 dbase = rev
1979 dbase = rev
1980 cbase = r.chainbase(rev)
1980 cbase = r.chainbase(rev)
1981 p1, p2 = r.parentrevs(rev)
1981 p1, p2 = r.parentrevs(rev)
1982 rs = r.rawsize(rev)
1982 rs = r.rawsize(rev)
1983 ts = ts + rs
1983 ts = ts + rs
1984 heads -= set(r.parentrevs(rev))
1984 heads -= set(r.parentrevs(rev))
1985 heads.add(rev)
1985 heads.add(rev)
1986 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1986 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1987 (rev, p1, p2, r.start(rev), r.end(rev),
1987 (rev, p1, p2, r.start(rev), r.end(rev),
1988 r.start(dbase), r.start(cbase),
1988 r.start(dbase), r.start(cbase),
1989 r.start(p1), r.start(p2),
1989 r.start(p1), r.start(p2),
1990 rs, ts, ts / r.end(rev), len(heads)))
1990 rs, ts, ts / r.end(rev), len(heads)))
1991 return 0
1991 return 0
1992
1992
1993 v = r.version
1993 v = r.version
1994 format = v & 0xFFFF
1994 format = v & 0xFFFF
1995 flags = []
1995 flags = []
1996 gdelta = False
1996 gdelta = False
1997 if v & revlog.REVLOGNGINLINEDATA:
1997 if v & revlog.REVLOGNGINLINEDATA:
1998 flags.append('inline')
1998 flags.append('inline')
1999 if v & revlog.REVLOGGENERALDELTA:
1999 if v & revlog.REVLOGGENERALDELTA:
2000 gdelta = True
2000 gdelta = True
2001 flags.append('generaldelta')
2001 flags.append('generaldelta')
2002 if not flags:
2002 if not flags:
2003 flags = ['(none)']
2003 flags = ['(none)']
2004
2004
2005 nummerges = 0
2005 nummerges = 0
2006 numfull = 0
2006 numfull = 0
2007 numprev = 0
2007 numprev = 0
2008 nump1 = 0
2008 nump1 = 0
2009 nump2 = 0
2009 nump2 = 0
2010 numother = 0
2010 numother = 0
2011 nump1prev = 0
2011 nump1prev = 0
2012 nump2prev = 0
2012 nump2prev = 0
2013 chainlengths = []
2013 chainlengths = []
2014
2014
2015 datasize = [None, 0, 0L]
2015 datasize = [None, 0, 0L]
2016 fullsize = [None, 0, 0L]
2016 fullsize = [None, 0, 0L]
2017 deltasize = [None, 0, 0L]
2017 deltasize = [None, 0, 0L]
2018
2018
2019 def addsize(size, l):
2019 def addsize(size, l):
2020 if l[0] is None or size < l[0]:
2020 if l[0] is None or size < l[0]:
2021 l[0] = size
2021 l[0] = size
2022 if size > l[1]:
2022 if size > l[1]:
2023 l[1] = size
2023 l[1] = size
2024 l[2] += size
2024 l[2] += size
2025
2025
2026 numrevs = len(r)
2026 numrevs = len(r)
2027 for rev in xrange(numrevs):
2027 for rev in xrange(numrevs):
2028 p1, p2 = r.parentrevs(rev)
2028 p1, p2 = r.parentrevs(rev)
2029 delta = r.deltaparent(rev)
2029 delta = r.deltaparent(rev)
2030 if format > 0:
2030 if format > 0:
2031 addsize(r.rawsize(rev), datasize)
2031 addsize(r.rawsize(rev), datasize)
2032 if p2 != nullrev:
2032 if p2 != nullrev:
2033 nummerges += 1
2033 nummerges += 1
2034 size = r.length(rev)
2034 size = r.length(rev)
2035 if delta == nullrev:
2035 if delta == nullrev:
2036 chainlengths.append(0)
2036 chainlengths.append(0)
2037 numfull += 1
2037 numfull += 1
2038 addsize(size, fullsize)
2038 addsize(size, fullsize)
2039 else:
2039 else:
2040 chainlengths.append(chainlengths[delta] + 1)
2040 chainlengths.append(chainlengths[delta] + 1)
2041 addsize(size, deltasize)
2041 addsize(size, deltasize)
2042 if delta == rev - 1:
2042 if delta == rev - 1:
2043 numprev += 1
2043 numprev += 1
2044 if delta == p1:
2044 if delta == p1:
2045 nump1prev += 1
2045 nump1prev += 1
2046 elif delta == p2:
2046 elif delta == p2:
2047 nump2prev += 1
2047 nump2prev += 1
2048 elif delta == p1:
2048 elif delta == p1:
2049 nump1 += 1
2049 nump1 += 1
2050 elif delta == p2:
2050 elif delta == p2:
2051 nump2 += 1
2051 nump2 += 1
2052 elif delta != nullrev:
2052 elif delta != nullrev:
2053 numother += 1
2053 numother += 1
2054
2054
2055 numdeltas = numrevs - numfull
2055 numdeltas = numrevs - numfull
2056 numoprev = numprev - nump1prev - nump2prev
2056 numoprev = numprev - nump1prev - nump2prev
2057 totalrawsize = datasize[2]
2057 totalrawsize = datasize[2]
2058 datasize[2] /= numrevs
2058 datasize[2] /= numrevs
2059 fulltotal = fullsize[2]
2059 fulltotal = fullsize[2]
2060 fullsize[2] /= numfull
2060 fullsize[2] /= numfull
2061 deltatotal = deltasize[2]
2061 deltatotal = deltasize[2]
2062 deltasize[2] /= numrevs - numfull
2062 deltasize[2] /= numrevs - numfull
2063 totalsize = fulltotal + deltatotal
2063 totalsize = fulltotal + deltatotal
2064 avgchainlen = sum(chainlengths) / numrevs
2064 avgchainlen = sum(chainlengths) / numrevs
2065 compratio = totalrawsize / totalsize
2065 compratio = totalrawsize / totalsize
2066
2066
2067 basedfmtstr = '%%%dd\n'
2067 basedfmtstr = '%%%dd\n'
2068 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2068 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2069
2069
2070 def dfmtstr(max):
2070 def dfmtstr(max):
2071 return basedfmtstr % len(str(max))
2071 return basedfmtstr % len(str(max))
2072 def pcfmtstr(max, padding=0):
2072 def pcfmtstr(max, padding=0):
2073 return basepcfmtstr % (len(str(max)), ' ' * padding)
2073 return basepcfmtstr % (len(str(max)), ' ' * padding)
2074
2074
2075 def pcfmt(value, total):
2075 def pcfmt(value, total):
2076 return (value, 100 * float(value) / total)
2076 return (value, 100 * float(value) / total)
2077
2077
2078 ui.write('format : %d\n' % format)
2078 ui.write('format : %d\n' % format)
2079 ui.write('flags : %s\n' % ', '.join(flags))
2079 ui.write('flags : %s\n' % ', '.join(flags))
2080
2080
2081 ui.write('\n')
2081 ui.write('\n')
2082 fmt = pcfmtstr(totalsize)
2082 fmt = pcfmtstr(totalsize)
2083 fmt2 = dfmtstr(totalsize)
2083 fmt2 = dfmtstr(totalsize)
2084 ui.write('revisions : ' + fmt2 % numrevs)
2084 ui.write('revisions : ' + fmt2 % numrevs)
2085 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2085 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2086 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2086 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2087 ui.write('revisions : ' + fmt2 % numrevs)
2087 ui.write('revisions : ' + fmt2 % numrevs)
2088 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2088 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2089 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2089 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2090 ui.write('revision size : ' + fmt2 % totalsize)
2090 ui.write('revision size : ' + fmt2 % totalsize)
2091 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2091 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2092 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2092 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2093
2093
2094 ui.write('\n')
2094 ui.write('\n')
2095 fmt = dfmtstr(max(avgchainlen, compratio))
2095 fmt = dfmtstr(max(avgchainlen, compratio))
2096 ui.write('avg chain length : ' + fmt % avgchainlen)
2096 ui.write('avg chain length : ' + fmt % avgchainlen)
2097 ui.write('compression ratio : ' + fmt % compratio)
2097 ui.write('compression ratio : ' + fmt % compratio)
2098
2098
2099 if format > 0:
2099 if format > 0:
2100 ui.write('\n')
2100 ui.write('\n')
2101 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2101 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2102 % tuple(datasize))
2102 % tuple(datasize))
2103 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2103 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2104 % tuple(fullsize))
2104 % tuple(fullsize))
2105 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2105 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2106 % tuple(deltasize))
2106 % tuple(deltasize))
2107
2107
2108 if numdeltas > 0:
2108 if numdeltas > 0:
2109 ui.write('\n')
2109 ui.write('\n')
2110 fmt = pcfmtstr(numdeltas)
2110 fmt = pcfmtstr(numdeltas)
2111 fmt2 = pcfmtstr(numdeltas, 4)
2111 fmt2 = pcfmtstr(numdeltas, 4)
2112 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2112 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2113 if numprev > 0:
2113 if numprev > 0:
2114 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2114 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2115 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2115 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2116 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2116 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2117 if gdelta:
2117 if gdelta:
2118 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2118 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2119 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2119 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2120 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2120 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2121
2121
2122 @command('debugrevspec', [], ('REVSPEC'))
2122 @command('debugrevspec', [], ('REVSPEC'))
2123 def debugrevspec(ui, repo, expr):
2123 def debugrevspec(ui, repo, expr):
2124 '''parse and apply a revision specification'''
2124 '''parse and apply a revision specification'''
2125 if ui.verbose:
2125 if ui.verbose:
2126 tree = revset.parse(expr)[0]
2126 tree = revset.parse(expr)[0]
2127 ui.note(tree, "\n")
2127 ui.note(tree, "\n")
2128 newtree = revset.findaliases(ui, tree)
2128 newtree = revset.findaliases(ui, tree)
2129 if newtree != tree:
2129 if newtree != tree:
2130 ui.note(newtree, "\n")
2130 ui.note(newtree, "\n")
2131 func = revset.match(ui, expr)
2131 func = revset.match(ui, expr)
2132 for c in func(repo, range(len(repo))):
2132 for c in func(repo, range(len(repo))):
2133 ui.write("%s\n" % c)
2133 ui.write("%s\n" % c)
2134
2134
2135 @command('debugsetparents', [], _('REV1 [REV2]'))
2135 @command('debugsetparents', [], _('REV1 [REV2]'))
2136 def debugsetparents(ui, repo, rev1, rev2=None):
2136 def debugsetparents(ui, repo, rev1, rev2=None):
2137 """manually set the parents of the current working directory
2137 """manually set the parents of the current working directory
2138
2138
2139 This is useful for writing repository conversion tools, but should
2139 This is useful for writing repository conversion tools, but should
2140 be used with care.
2140 be used with care.
2141
2141
2142 Returns 0 on success.
2142 Returns 0 on success.
2143 """
2143 """
2144
2144
2145 r1 = scmutil.revsingle(repo, rev1).node()
2145 r1 = scmutil.revsingle(repo, rev1).node()
2146 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2146 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2147
2147
2148 wlock = repo.wlock()
2148 wlock = repo.wlock()
2149 try:
2149 try:
2150 repo.dirstate.setparents(r1, r2)
2150 repo.dirstate.setparents(r1, r2)
2151 finally:
2151 finally:
2152 wlock.release()
2152 wlock.release()
2153
2153
2154 @command('debugstate',
2154 @command('debugstate',
2155 [('', 'nodates', None, _('do not display the saved mtime')),
2155 [('', 'nodates', None, _('do not display the saved mtime')),
2156 ('', 'datesort', None, _('sort by saved mtime'))],
2156 ('', 'datesort', None, _('sort by saved mtime'))],
2157 _('[OPTION]...'))
2157 _('[OPTION]...'))
2158 def debugstate(ui, repo, nodates=None, datesort=None):
2158 def debugstate(ui, repo, nodates=None, datesort=None):
2159 """show the contents of the current dirstate"""
2159 """show the contents of the current dirstate"""
2160 timestr = ""
2160 timestr = ""
2161 showdate = not nodates
2161 showdate = not nodates
2162 if datesort:
2162 if datesort:
2163 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2163 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2164 else:
2164 else:
2165 keyfunc = None # sort by filename
2165 keyfunc = None # sort by filename
2166 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2166 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2167 if showdate:
2167 if showdate:
2168 if ent[3] == -1:
2168 if ent[3] == -1:
2169 # Pad or slice to locale representation
2169 # Pad or slice to locale representation
2170 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2170 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2171 time.localtime(0)))
2171 time.localtime(0)))
2172 timestr = 'unset'
2172 timestr = 'unset'
2173 timestr = (timestr[:locale_len] +
2173 timestr = (timestr[:locale_len] +
2174 ' ' * (locale_len - len(timestr)))
2174 ' ' * (locale_len - len(timestr)))
2175 else:
2175 else:
2176 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2176 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2177 time.localtime(ent[3]))
2177 time.localtime(ent[3]))
2178 if ent[1] & 020000:
2178 if ent[1] & 020000:
2179 mode = 'lnk'
2179 mode = 'lnk'
2180 else:
2180 else:
2181 mode = '%3o' % (ent[1] & 0777)
2181 mode = '%3o' % (ent[1] & 0777)
2182 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2182 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2183 for f in repo.dirstate.copies():
2183 for f in repo.dirstate.copies():
2184 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2184 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2185
2185
2186 @command('debugsub',
2186 @command('debugsub',
2187 [('r', 'rev', '',
2187 [('r', 'rev', '',
2188 _('revision to check'), _('REV'))],
2188 _('revision to check'), _('REV'))],
2189 _('[-r REV] [REV]'))
2189 _('[-r REV] [REV]'))
2190 def debugsub(ui, repo, rev=None):
2190 def debugsub(ui, repo, rev=None):
2191 ctx = scmutil.revsingle(repo, rev, None)
2191 ctx = scmutil.revsingle(repo, rev, None)
2192 for k, v in sorted(ctx.substate.items()):
2192 for k, v in sorted(ctx.substate.items()):
2193 ui.write('path %s\n' % k)
2193 ui.write('path %s\n' % k)
2194 ui.write(' source %s\n' % v[0])
2194 ui.write(' source %s\n' % v[0])
2195 ui.write(' revision %s\n' % v[1])
2195 ui.write(' revision %s\n' % v[1])
2196
2196
2197 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2197 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2198 def debugwalk(ui, repo, *pats, **opts):
2198 def debugwalk(ui, repo, *pats, **opts):
2199 """show how files match on given patterns"""
2199 """show how files match on given patterns"""
2200 m = scmutil.match(repo[None], pats, opts)
2200 m = scmutil.match(repo[None], pats, opts)
2201 items = list(repo.walk(m))
2201 items = list(repo.walk(m))
2202 if not items:
2202 if not items:
2203 return
2203 return
2204 fmt = 'f %%-%ds %%-%ds %%s' % (
2204 fmt = 'f %%-%ds %%-%ds %%s' % (
2205 max([len(abs) for abs in items]),
2205 max([len(abs) for abs in items]),
2206 max([len(m.rel(abs)) for abs in items]))
2206 max([len(m.rel(abs)) for abs in items]))
2207 for abs in items:
2207 for abs in items:
2208 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2208 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2209 ui.write("%s\n" % line.rstrip())
2209 ui.write("%s\n" % line.rstrip())
2210
2210
2211 @command('debugwireargs',
2211 @command('debugwireargs',
2212 [('', 'three', '', 'three'),
2212 [('', 'three', '', 'three'),
2213 ('', 'four', '', 'four'),
2213 ('', 'four', '', 'four'),
2214 ('', 'five', '', 'five'),
2214 ('', 'five', '', 'five'),
2215 ] + remoteopts,
2215 ] + remoteopts,
2216 _('REPO [OPTIONS]... [ONE [TWO]]'))
2216 _('REPO [OPTIONS]... [ONE [TWO]]'))
2217 def debugwireargs(ui, repopath, *vals, **opts):
2217 def debugwireargs(ui, repopath, *vals, **opts):
2218 repo = hg.peer(ui, opts, repopath)
2218 repo = hg.peer(ui, opts, repopath)
2219 for opt in remoteopts:
2219 for opt in remoteopts:
2220 del opts[opt[1]]
2220 del opts[opt[1]]
2221 args = {}
2221 args = {}
2222 for k, v in opts.iteritems():
2222 for k, v in opts.iteritems():
2223 if v:
2223 if v:
2224 args[k] = v
2224 args[k] = v
2225 # run twice to check that we don't mess up the stream for the next command
2225 # run twice to check that we don't mess up the stream for the next command
2226 res1 = repo.debugwireargs(*vals, **args)
2226 res1 = repo.debugwireargs(*vals, **args)
2227 res2 = repo.debugwireargs(*vals, **args)
2227 res2 = repo.debugwireargs(*vals, **args)
2228 ui.write("%s\n" % res1)
2228 ui.write("%s\n" % res1)
2229 if res1 != res2:
2229 if res1 != res2:
2230 ui.warn("%s\n" % res2)
2230 ui.warn("%s\n" % res2)
2231
2231
2232 @command('^diff',
2232 @command('^diff',
2233 [('r', 'rev', [], _('revision'), _('REV')),
2233 [('r', 'rev', [], _('revision'), _('REV')),
2234 ('c', 'change', '', _('change made by revision'), _('REV'))
2234 ('c', 'change', '', _('change made by revision'), _('REV'))
2235 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2235 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2236 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2236 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2237 def diff(ui, repo, *pats, **opts):
2237 def diff(ui, repo, *pats, **opts):
2238 """diff repository (or selected files)
2238 """diff repository (or selected files)
2239
2239
2240 Show differences between revisions for the specified files.
2240 Show differences between revisions for the specified files.
2241
2241
2242 Differences between files are shown using the unified diff format.
2242 Differences between files are shown using the unified diff format.
2243
2243
2244 .. note::
2244 .. note::
2245 diff may generate unexpected results for merges, as it will
2245 diff may generate unexpected results for merges, as it will
2246 default to comparing against the working directory's first
2246 default to comparing against the working directory's first
2247 parent changeset if no revisions are specified.
2247 parent changeset if no revisions are specified.
2248
2248
2249 When two revision arguments are given, then changes are shown
2249 When two revision arguments are given, then changes are shown
2250 between those revisions. If only one revision is specified then
2250 between those revisions. If only one revision is specified then
2251 that revision is compared to the working directory, and, when no
2251 that revision is compared to the working directory, and, when no
2252 revisions are specified, the working directory files are compared
2252 revisions are specified, the working directory files are compared
2253 to its parent.
2253 to its parent.
2254
2254
2255 Alternatively you can specify -c/--change with a revision to see
2255 Alternatively you can specify -c/--change with a revision to see
2256 the changes in that changeset relative to its first parent.
2256 the changes in that changeset relative to its first parent.
2257
2257
2258 Without the -a/--text option, diff will avoid generating diffs of
2258 Without the -a/--text option, diff will avoid generating diffs of
2259 files it detects as binary. With -a, diff will generate a diff
2259 files it detects as binary. With -a, diff will generate a diff
2260 anyway, probably with undesirable results.
2260 anyway, probably with undesirable results.
2261
2261
2262 Use the -g/--git option to generate diffs in the git extended diff
2262 Use the -g/--git option to generate diffs in the git extended diff
2263 format. For more information, read :hg:`help diffs`.
2263 format. For more information, read :hg:`help diffs`.
2264
2264
2265 .. container:: verbose
2265 .. container:: verbose
2266
2266
2267 Examples:
2267 Examples:
2268
2268
2269 - compare a file in the current working directory to its parent::
2269 - compare a file in the current working directory to its parent::
2270
2270
2271 hg diff foo.c
2271 hg diff foo.c
2272
2272
2273 - compare two historical versions of a directory, with rename info::
2273 - compare two historical versions of a directory, with rename info::
2274
2274
2275 hg diff --git -r 1.0:1.2 lib/
2275 hg diff --git -r 1.0:1.2 lib/
2276
2276
2277 - get change stats relative to the last change on some date::
2277 - get change stats relative to the last change on some date::
2278
2278
2279 hg diff --stat -r "date('may 2')"
2279 hg diff --stat -r "date('may 2')"
2280
2280
2281 - diff all newly-added files that contain a keyword::
2281 - diff all newly-added files that contain a keyword::
2282
2282
2283 hg diff "set:added() and grep(GNU)"
2283 hg diff "set:added() and grep(GNU)"
2284
2284
2285 - compare a revision and its parents::
2285 - compare a revision and its parents::
2286
2286
2287 hg diff -c 9353 # compare against first parent
2287 hg diff -c 9353 # compare against first parent
2288 hg diff -r 9353^:9353 # same using revset syntax
2288 hg diff -r 9353^:9353 # same using revset syntax
2289 hg diff -r 9353^2:9353 # compare against the second parent
2289 hg diff -r 9353^2:9353 # compare against the second parent
2290
2290
2291 Returns 0 on success.
2291 Returns 0 on success.
2292 """
2292 """
2293
2293
2294 revs = opts.get('rev')
2294 revs = opts.get('rev')
2295 change = opts.get('change')
2295 change = opts.get('change')
2296 stat = opts.get('stat')
2296 stat = opts.get('stat')
2297 reverse = opts.get('reverse')
2297 reverse = opts.get('reverse')
2298
2298
2299 if revs and change:
2299 if revs and change:
2300 msg = _('cannot specify --rev and --change at the same time')
2300 msg = _('cannot specify --rev and --change at the same time')
2301 raise util.Abort(msg)
2301 raise util.Abort(msg)
2302 elif change:
2302 elif change:
2303 node2 = scmutil.revsingle(repo, change, None).node()
2303 node2 = scmutil.revsingle(repo, change, None).node()
2304 node1 = repo[node2].p1().node()
2304 node1 = repo[node2].p1().node()
2305 else:
2305 else:
2306 node1, node2 = scmutil.revpair(repo, revs)
2306 node1, node2 = scmutil.revpair(repo, revs)
2307
2307
2308 if reverse:
2308 if reverse:
2309 node1, node2 = node2, node1
2309 node1, node2 = node2, node1
2310
2310
2311 diffopts = patch.diffopts(ui, opts)
2311 diffopts = patch.diffopts(ui, opts)
2312 m = scmutil.match(repo[node2], pats, opts)
2312 m = scmutil.match(repo[node2], pats, opts)
2313 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2313 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2314 listsubrepos=opts.get('subrepos'))
2314 listsubrepos=opts.get('subrepos'))
2315
2315
2316 @command('^export',
2316 @command('^export',
2317 [('o', 'output', '',
2317 [('o', 'output', '',
2318 _('print output to file with formatted name'), _('FORMAT')),
2318 _('print output to file with formatted name'), _('FORMAT')),
2319 ('', 'switch-parent', None, _('diff against the second parent')),
2319 ('', 'switch-parent', None, _('diff against the second parent')),
2320 ('r', 'rev', [], _('revisions to export'), _('REV')),
2320 ('r', 'rev', [], _('revisions to export'), _('REV')),
2321 ] + diffopts,
2321 ] + diffopts,
2322 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2322 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2323 def export(ui, repo, *changesets, **opts):
2323 def export(ui, repo, *changesets, **opts):
2324 """dump the header and diffs for one or more changesets
2324 """dump the header and diffs for one or more changesets
2325
2325
2326 Print the changeset header and diffs for one or more revisions.
2326 Print the changeset header and diffs for one or more revisions.
2327
2327
2328 The information shown in the changeset header is: author, date,
2328 The information shown in the changeset header is: author, date,
2329 branch name (if non-default), changeset hash, parent(s) and commit
2329 branch name (if non-default), changeset hash, parent(s) and commit
2330 comment.
2330 comment.
2331
2331
2332 .. note::
2332 .. note::
2333 export may generate unexpected diff output for merge
2333 export may generate unexpected diff output for merge
2334 changesets, as it will compare the merge changeset against its
2334 changesets, as it will compare the merge changeset against its
2335 first parent only.
2335 first parent only.
2336
2336
2337 Output may be to a file, in which case the name of the file is
2337 Output may be to a file, in which case the name of the file is
2338 given using a format string. The formatting rules are as follows:
2338 given using a format string. The formatting rules are as follows:
2339
2339
2340 :``%%``: literal "%" character
2340 :``%%``: literal "%" character
2341 :``%H``: changeset hash (40 hexadecimal digits)
2341 :``%H``: changeset hash (40 hexadecimal digits)
2342 :``%N``: number of patches being generated
2342 :``%N``: number of patches being generated
2343 :``%R``: changeset revision number
2343 :``%R``: changeset revision number
2344 :``%b``: basename of the exporting repository
2344 :``%b``: basename of the exporting repository
2345 :``%h``: short-form changeset hash (12 hexadecimal digits)
2345 :``%h``: short-form changeset hash (12 hexadecimal digits)
2346 :``%m``: first line of the commit message (only alphanumeric characters)
2346 :``%m``: first line of the commit message (only alphanumeric characters)
2347 :``%n``: zero-padded sequence number, starting at 1
2347 :``%n``: zero-padded sequence number, starting at 1
2348 :``%r``: zero-padded changeset revision number
2348 :``%r``: zero-padded changeset revision number
2349
2349
2350 Without the -a/--text option, export will avoid generating diffs
2350 Without the -a/--text option, export will avoid generating diffs
2351 of files it detects as binary. With -a, export will generate a
2351 of files it detects as binary. With -a, export will generate a
2352 diff anyway, probably with undesirable results.
2352 diff anyway, probably with undesirable results.
2353
2353
2354 Use the -g/--git option to generate diffs in the git extended diff
2354 Use the -g/--git option to generate diffs in the git extended diff
2355 format. See :hg:`help diffs` for more information.
2355 format. See :hg:`help diffs` for more information.
2356
2356
2357 With the --switch-parent option, the diff will be against the
2357 With the --switch-parent option, the diff will be against the
2358 second parent. It can be useful to review a merge.
2358 second parent. It can be useful to review a merge.
2359
2359
2360 .. container:: verbose
2360 .. container:: verbose
2361
2361
2362 Examples:
2362 Examples:
2363
2363
2364 - use export and import to transplant a bugfix to the current
2364 - use export and import to transplant a bugfix to the current
2365 branch::
2365 branch::
2366
2366
2367 hg export -r 9353 | hg import -
2367 hg export -r 9353 | hg import -
2368
2368
2369 - export all the changesets between two revisions to a file with
2369 - export all the changesets between two revisions to a file with
2370 rename information::
2370 rename information::
2371
2371
2372 hg export --git -r 123:150 > changes.txt
2372 hg export --git -r 123:150 > changes.txt
2373
2373
2374 - split outgoing changes into a series of patches with
2374 - split outgoing changes into a series of patches with
2375 descriptive names::
2375 descriptive names::
2376
2376
2377 hg export -r "outgoing()" -o "%n-%m.patch"
2377 hg export -r "outgoing()" -o "%n-%m.patch"
2378
2378
2379 Returns 0 on success.
2379 Returns 0 on success.
2380 """
2380 """
2381 changesets += tuple(opts.get('rev', []))
2381 changesets += tuple(opts.get('rev', []))
2382 if not changesets:
2382 if not changesets:
2383 raise util.Abort(_("export requires at least one changeset"))
2383 raise util.Abort(_("export requires at least one changeset"))
2384 revs = scmutil.revrange(repo, changesets)
2384 revs = scmutil.revrange(repo, changesets)
2385 if len(revs) > 1:
2385 if len(revs) > 1:
2386 ui.note(_('exporting patches:\n'))
2386 ui.note(_('exporting patches:\n'))
2387 else:
2387 else:
2388 ui.note(_('exporting patch:\n'))
2388 ui.note(_('exporting patch:\n'))
2389 cmdutil.export(repo, revs, template=opts.get('output'),
2389 cmdutil.export(repo, revs, template=opts.get('output'),
2390 switch_parent=opts.get('switch_parent'),
2390 switch_parent=opts.get('switch_parent'),
2391 opts=patch.diffopts(ui, opts))
2391 opts=patch.diffopts(ui, opts))
2392
2392
2393 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2393 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2394 def forget(ui, repo, *pats, **opts):
2394 def forget(ui, repo, *pats, **opts):
2395 """forget the specified files on the next commit
2395 """forget the specified files on the next commit
2396
2396
2397 Mark the specified files so they will no longer be tracked
2397 Mark the specified files so they will no longer be tracked
2398 after the next commit.
2398 after the next commit.
2399
2399
2400 This only removes files from the current branch, not from the
2400 This only removes files from the current branch, not from the
2401 entire project history, and it does not delete them from the
2401 entire project history, and it does not delete them from the
2402 working directory.
2402 working directory.
2403
2403
2404 To undo a forget before the next commit, see :hg:`add`.
2404 To undo a forget before the next commit, see :hg:`add`.
2405
2405
2406 .. container:: verbose
2406 .. container:: verbose
2407
2407
2408 Examples:
2408 Examples:
2409
2409
2410 - forget newly-added binary files::
2410 - forget newly-added binary files::
2411
2411
2412 hg forget "set:added() and binary()"
2412 hg forget "set:added() and binary()"
2413
2413
2414 - forget files that would be excluded by .hgignore::
2414 - forget files that would be excluded by .hgignore::
2415
2415
2416 hg forget "set:hgignore()"
2416 hg forget "set:hgignore()"
2417
2417
2418 Returns 0 on success.
2418 Returns 0 on success.
2419 """
2419 """
2420
2420
2421 if not pats:
2421 if not pats:
2422 raise util.Abort(_('no files specified'))
2422 raise util.Abort(_('no files specified'))
2423
2423
2424 m = scmutil.match(repo[None], pats, opts)
2424 m = scmutil.match(repo[None], pats, opts)
2425 s = repo.status(match=m, clean=True)
2425 s = repo.status(match=m, clean=True)
2426 forget = sorted(s[0] + s[1] + s[3] + s[6])
2426 forget = sorted(s[0] + s[1] + s[3] + s[6])
2427 errs = 0
2427 errs = 0
2428
2428
2429 for f in m.files():
2429 for f in m.files():
2430 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2430 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2431 if os.path.exists(m.rel(f)):
2431 if os.path.exists(m.rel(f)):
2432 ui.warn(_('not removing %s: file is already untracked\n')
2432 ui.warn(_('not removing %s: file is already untracked\n')
2433 % m.rel(f))
2433 % m.rel(f))
2434 errs = 1
2434 errs = 1
2435
2435
2436 for f in forget:
2436 for f in forget:
2437 if ui.verbose or not m.exact(f):
2437 if ui.verbose or not m.exact(f):
2438 ui.status(_('removing %s\n') % m.rel(f))
2438 ui.status(_('removing %s\n') % m.rel(f))
2439
2439
2440 repo[None].forget(forget)
2440 repo[None].forget(forget)
2441 return errs
2441 return errs
2442
2442
2443 @command('grep',
2443 @command('grep',
2444 [('0', 'print0', None, _('end fields with NUL')),
2444 [('0', 'print0', None, _('end fields with NUL')),
2445 ('', 'all', None, _('print all revisions that match')),
2445 ('', 'all', None, _('print all revisions that match')),
2446 ('a', 'text', None, _('treat all files as text')),
2446 ('a', 'text', None, _('treat all files as text')),
2447 ('f', 'follow', None,
2447 ('f', 'follow', None,
2448 _('follow changeset history,'
2448 _('follow changeset history,'
2449 ' or file history across copies and renames')),
2449 ' or file history across copies and renames')),
2450 ('i', 'ignore-case', None, _('ignore case when matching')),
2450 ('i', 'ignore-case', None, _('ignore case when matching')),
2451 ('l', 'files-with-matches', None,
2451 ('l', 'files-with-matches', None,
2452 _('print only filenames and revisions that match')),
2452 _('print only filenames and revisions that match')),
2453 ('n', 'line-number', None, _('print matching line numbers')),
2453 ('n', 'line-number', None, _('print matching line numbers')),
2454 ('r', 'rev', [],
2454 ('r', 'rev', [],
2455 _('only search files changed within revision range'), _('REV')),
2455 _('only search files changed within revision range'), _('REV')),
2456 ('u', 'user', None, _('list the author (long with -v)')),
2456 ('u', 'user', None, _('list the author (long with -v)')),
2457 ('d', 'date', None, _('list the date (short with -q)')),
2457 ('d', 'date', None, _('list the date (short with -q)')),
2458 ] + walkopts,
2458 ] + walkopts,
2459 _('[OPTION]... PATTERN [FILE]...'))
2459 _('[OPTION]... PATTERN [FILE]...'))
2460 def grep(ui, repo, pattern, *pats, **opts):
2460 def grep(ui, repo, pattern, *pats, **opts):
2461 """search for a pattern in specified files and revisions
2461 """search for a pattern in specified files and revisions
2462
2462
2463 Search revisions of files for a regular expression.
2463 Search revisions of files for a regular expression.
2464
2464
2465 This command behaves differently than Unix grep. It only accepts
2465 This command behaves differently than Unix grep. It only accepts
2466 Python/Perl regexps. It searches repository history, not the
2466 Python/Perl regexps. It searches repository history, not the
2467 working directory. It always prints the revision number in which a
2467 working directory. It always prints the revision number in which a
2468 match appears.
2468 match appears.
2469
2469
2470 By default, grep only prints output for the first revision of a
2470 By default, grep only prints output for the first revision of a
2471 file in which it finds a match. To get it to print every revision
2471 file in which it finds a match. To get it to print every revision
2472 that contains a change in match status ("-" for a match that
2472 that contains a change in match status ("-" for a match that
2473 becomes a non-match, or "+" for a non-match that becomes a match),
2473 becomes a non-match, or "+" for a non-match that becomes a match),
2474 use the --all flag.
2474 use the --all flag.
2475
2475
2476 Returns 0 if a match is found, 1 otherwise.
2476 Returns 0 if a match is found, 1 otherwise.
2477 """
2477 """
2478 reflags = 0
2478 reflags = 0
2479 if opts.get('ignore_case'):
2479 if opts.get('ignore_case'):
2480 reflags |= re.I
2480 reflags |= re.I
2481 try:
2481 try:
2482 regexp = re.compile(pattern, reflags)
2482 regexp = re.compile(pattern, reflags)
2483 except re.error, inst:
2483 except re.error, inst:
2484 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2484 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2485 return 1
2485 return 1
2486 sep, eol = ':', '\n'
2486 sep, eol = ':', '\n'
2487 if opts.get('print0'):
2487 if opts.get('print0'):
2488 sep = eol = '\0'
2488 sep = eol = '\0'
2489
2489
2490 getfile = util.lrucachefunc(repo.file)
2490 getfile = util.lrucachefunc(repo.file)
2491
2491
2492 def matchlines(body):
2492 def matchlines(body):
2493 begin = 0
2493 begin = 0
2494 linenum = 0
2494 linenum = 0
2495 while True:
2495 while True:
2496 match = regexp.search(body, begin)
2496 match = regexp.search(body, begin)
2497 if not match:
2497 if not match:
2498 break
2498 break
2499 mstart, mend = match.span()
2499 mstart, mend = match.span()
2500 linenum += body.count('\n', begin, mstart) + 1
2500 linenum += body.count('\n', begin, mstart) + 1
2501 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2501 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2502 begin = body.find('\n', mend) + 1 or len(body)
2502 begin = body.find('\n', mend) + 1 or len(body)
2503 lend = begin - 1
2503 lend = begin - 1
2504 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2504 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2505
2505
2506 class linestate(object):
2506 class linestate(object):
2507 def __init__(self, line, linenum, colstart, colend):
2507 def __init__(self, line, linenum, colstart, colend):
2508 self.line = line
2508 self.line = line
2509 self.linenum = linenum
2509 self.linenum = linenum
2510 self.colstart = colstart
2510 self.colstart = colstart
2511 self.colend = colend
2511 self.colend = colend
2512
2512
2513 def __hash__(self):
2513 def __hash__(self):
2514 return hash((self.linenum, self.line))
2514 return hash((self.linenum, self.line))
2515
2515
2516 def __eq__(self, other):
2516 def __eq__(self, other):
2517 return self.line == other.line
2517 return self.line == other.line
2518
2518
2519 matches = {}
2519 matches = {}
2520 copies = {}
2520 copies = {}
2521 def grepbody(fn, rev, body):
2521 def grepbody(fn, rev, body):
2522 matches[rev].setdefault(fn, [])
2522 matches[rev].setdefault(fn, [])
2523 m = matches[rev][fn]
2523 m = matches[rev][fn]
2524 for lnum, cstart, cend, line in matchlines(body):
2524 for lnum, cstart, cend, line in matchlines(body):
2525 s = linestate(line, lnum, cstart, cend)
2525 s = linestate(line, lnum, cstart, cend)
2526 m.append(s)
2526 m.append(s)
2527
2527
2528 def difflinestates(a, b):
2528 def difflinestates(a, b):
2529 sm = difflib.SequenceMatcher(None, a, b)
2529 sm = difflib.SequenceMatcher(None, a, b)
2530 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2530 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2531 if tag == 'insert':
2531 if tag == 'insert':
2532 for i in xrange(blo, bhi):
2532 for i in xrange(blo, bhi):
2533 yield ('+', b[i])
2533 yield ('+', b[i])
2534 elif tag == 'delete':
2534 elif tag == 'delete':
2535 for i in xrange(alo, ahi):
2535 for i in xrange(alo, ahi):
2536 yield ('-', a[i])
2536 yield ('-', a[i])
2537 elif tag == 'replace':
2537 elif tag == 'replace':
2538 for i in xrange(alo, ahi):
2538 for i in xrange(alo, ahi):
2539 yield ('-', a[i])
2539 yield ('-', a[i])
2540 for i in xrange(blo, bhi):
2540 for i in xrange(blo, bhi):
2541 yield ('+', b[i])
2541 yield ('+', b[i])
2542
2542
2543 def display(fn, ctx, pstates, states):
2543 def display(fn, ctx, pstates, states):
2544 rev = ctx.rev()
2544 rev = ctx.rev()
2545 datefunc = ui.quiet and util.shortdate or util.datestr
2545 datefunc = ui.quiet and util.shortdate or util.datestr
2546 found = False
2546 found = False
2547 filerevmatches = {}
2547 filerevmatches = {}
2548 def binary():
2548 def binary():
2549 flog = getfile(fn)
2549 flog = getfile(fn)
2550 return util.binary(flog.read(ctx.filenode(fn)))
2550 return util.binary(flog.read(ctx.filenode(fn)))
2551
2551
2552 if opts.get('all'):
2552 if opts.get('all'):
2553 iter = difflinestates(pstates, states)
2553 iter = difflinestates(pstates, states)
2554 else:
2554 else:
2555 iter = [('', l) for l in states]
2555 iter = [('', l) for l in states]
2556 for change, l in iter:
2556 for change, l in iter:
2557 cols = [fn, str(rev)]
2557 cols = [fn, str(rev)]
2558 before, match, after = None, None, None
2558 before, match, after = None, None, None
2559 if opts.get('line_number'):
2559 if opts.get('line_number'):
2560 cols.append(str(l.linenum))
2560 cols.append(str(l.linenum))
2561 if opts.get('all'):
2561 if opts.get('all'):
2562 cols.append(change)
2562 cols.append(change)
2563 if opts.get('user'):
2563 if opts.get('user'):
2564 cols.append(ui.shortuser(ctx.user()))
2564 cols.append(ui.shortuser(ctx.user()))
2565 if opts.get('date'):
2565 if opts.get('date'):
2566 cols.append(datefunc(ctx.date()))
2566 cols.append(datefunc(ctx.date()))
2567 if opts.get('files_with_matches'):
2567 if opts.get('files_with_matches'):
2568 c = (fn, rev)
2568 c = (fn, rev)
2569 if c in filerevmatches:
2569 if c in filerevmatches:
2570 continue
2570 continue
2571 filerevmatches[c] = 1
2571 filerevmatches[c] = 1
2572 else:
2572 else:
2573 before = l.line[:l.colstart]
2573 before = l.line[:l.colstart]
2574 match = l.line[l.colstart:l.colend]
2574 match = l.line[l.colstart:l.colend]
2575 after = l.line[l.colend:]
2575 after = l.line[l.colend:]
2576 ui.write(sep.join(cols))
2576 ui.write(sep.join(cols))
2577 if before is not None:
2577 if before is not None:
2578 if not opts.get('text') and binary():
2578 if not opts.get('text') and binary():
2579 ui.write(sep + " Binary file matches")
2579 ui.write(sep + " Binary file matches")
2580 else:
2580 else:
2581 ui.write(sep + before)
2581 ui.write(sep + before)
2582 ui.write(match, label='grep.match')
2582 ui.write(match, label='grep.match')
2583 ui.write(after)
2583 ui.write(after)
2584 ui.write(eol)
2584 ui.write(eol)
2585 found = True
2585 found = True
2586 return found
2586 return found
2587
2587
2588 skip = {}
2588 skip = {}
2589 revfiles = {}
2589 revfiles = {}
2590 matchfn = scmutil.match(repo[None], pats, opts)
2590 matchfn = scmutil.match(repo[None], pats, opts)
2591 found = False
2591 found = False
2592 follow = opts.get('follow')
2592 follow = opts.get('follow')
2593
2593
2594 def prep(ctx, fns):
2594 def prep(ctx, fns):
2595 rev = ctx.rev()
2595 rev = ctx.rev()
2596 pctx = ctx.p1()
2596 pctx = ctx.p1()
2597 parent = pctx.rev()
2597 parent = pctx.rev()
2598 matches.setdefault(rev, {})
2598 matches.setdefault(rev, {})
2599 matches.setdefault(parent, {})
2599 matches.setdefault(parent, {})
2600 files = revfiles.setdefault(rev, [])
2600 files = revfiles.setdefault(rev, [])
2601 for fn in fns:
2601 for fn in fns:
2602 flog = getfile(fn)
2602 flog = getfile(fn)
2603 try:
2603 try:
2604 fnode = ctx.filenode(fn)
2604 fnode = ctx.filenode(fn)
2605 except error.LookupError:
2605 except error.LookupError:
2606 continue
2606 continue
2607
2607
2608 copied = flog.renamed(fnode)
2608 copied = flog.renamed(fnode)
2609 copy = follow and copied and copied[0]
2609 copy = follow and copied and copied[0]
2610 if copy:
2610 if copy:
2611 copies.setdefault(rev, {})[fn] = copy
2611 copies.setdefault(rev, {})[fn] = copy
2612 if fn in skip:
2612 if fn in skip:
2613 if copy:
2613 if copy:
2614 skip[copy] = True
2614 skip[copy] = True
2615 continue
2615 continue
2616 files.append(fn)
2616 files.append(fn)
2617
2617
2618 if fn not in matches[rev]:
2618 if fn not in matches[rev]:
2619 grepbody(fn, rev, flog.read(fnode))
2619 grepbody(fn, rev, flog.read(fnode))
2620
2620
2621 pfn = copy or fn
2621 pfn = copy or fn
2622 if pfn not in matches[parent]:
2622 if pfn not in matches[parent]:
2623 try:
2623 try:
2624 fnode = pctx.filenode(pfn)
2624 fnode = pctx.filenode(pfn)
2625 grepbody(pfn, parent, flog.read(fnode))
2625 grepbody(pfn, parent, flog.read(fnode))
2626 except error.LookupError:
2626 except error.LookupError:
2627 pass
2627 pass
2628
2628
2629 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2629 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2630 rev = ctx.rev()
2630 rev = ctx.rev()
2631 parent = ctx.p1().rev()
2631 parent = ctx.p1().rev()
2632 for fn in sorted(revfiles.get(rev, [])):
2632 for fn in sorted(revfiles.get(rev, [])):
2633 states = matches[rev][fn]
2633 states = matches[rev][fn]
2634 copy = copies.get(rev, {}).get(fn)
2634 copy = copies.get(rev, {}).get(fn)
2635 if fn in skip:
2635 if fn in skip:
2636 if copy:
2636 if copy:
2637 skip[copy] = True
2637 skip[copy] = True
2638 continue
2638 continue
2639 pstates = matches.get(parent, {}).get(copy or fn, [])
2639 pstates = matches.get(parent, {}).get(copy or fn, [])
2640 if pstates or states:
2640 if pstates or states:
2641 r = display(fn, ctx, pstates, states)
2641 r = display(fn, ctx, pstates, states)
2642 found = found or r
2642 found = found or r
2643 if r and not opts.get('all'):
2643 if r and not opts.get('all'):
2644 skip[fn] = True
2644 skip[fn] = True
2645 if copy:
2645 if copy:
2646 skip[copy] = True
2646 skip[copy] = True
2647 del matches[rev]
2647 del matches[rev]
2648 del revfiles[rev]
2648 del revfiles[rev]
2649
2649
2650 return not found
2650 return not found
2651
2651
2652 @command('heads',
2652 @command('heads',
2653 [('r', 'rev', '',
2653 [('r', 'rev', '',
2654 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2654 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2655 ('t', 'topo', False, _('show topological heads only')),
2655 ('t', 'topo', False, _('show topological heads only')),
2656 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2656 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2657 ('c', 'closed', False, _('show normal and closed branch heads')),
2657 ('c', 'closed', False, _('show normal and closed branch heads')),
2658 ] + templateopts,
2658 ] + templateopts,
2659 _('[-ac] [-r STARTREV] [REV]...'))
2659 _('[-ac] [-r STARTREV] [REV]...'))
2660 def heads(ui, repo, *branchrevs, **opts):
2660 def heads(ui, repo, *branchrevs, **opts):
2661 """show current repository heads or show branch heads
2661 """show current repository heads or show branch heads
2662
2662
2663 With no arguments, show all repository branch heads.
2663 With no arguments, show all repository branch heads.
2664
2664
2665 Repository "heads" are changesets with no child changesets. They are
2665 Repository "heads" are changesets with no child changesets. They are
2666 where development generally takes place and are the usual targets
2666 where development generally takes place and are the usual targets
2667 for update and merge operations. Branch heads are changesets that have
2667 for update and merge operations. Branch heads are changesets that have
2668 no child changeset on the same branch.
2668 no child changeset on the same branch.
2669
2669
2670 If one or more REVs are given, only branch heads on the branches
2670 If one or more REVs are given, only branch heads on the branches
2671 associated with the specified changesets are shown. This means
2671 associated with the specified changesets are shown. This means
2672 that you can use :hg:`heads foo` to see the heads on a branch
2672 that you can use :hg:`heads foo` to see the heads on a branch
2673 named ``foo``.
2673 named ``foo``.
2674
2674
2675 If -c/--closed is specified, also show branch heads marked closed
2675 If -c/--closed is specified, also show branch heads marked closed
2676 (see :hg:`commit --close-branch`).
2676 (see :hg:`commit --close-branch`).
2677
2677
2678 If STARTREV is specified, only those heads that are descendants of
2678 If STARTREV is specified, only those heads that are descendants of
2679 STARTREV will be displayed.
2679 STARTREV will be displayed.
2680
2680
2681 If -t/--topo is specified, named branch mechanics will be ignored and only
2681 If -t/--topo is specified, named branch mechanics will be ignored and only
2682 changesets without children will be shown.
2682 changesets without children will be shown.
2683
2683
2684 Returns 0 if matching heads are found, 1 if not.
2684 Returns 0 if matching heads are found, 1 if not.
2685 """
2685 """
2686
2686
2687 start = None
2687 start = None
2688 if 'rev' in opts:
2688 if 'rev' in opts:
2689 start = scmutil.revsingle(repo, opts['rev'], None).node()
2689 start = scmutil.revsingle(repo, opts['rev'], None).node()
2690
2690
2691 if opts.get('topo'):
2691 if opts.get('topo'):
2692 heads = [repo[h] for h in repo.heads(start)]
2692 heads = [repo[h] for h in repo.heads(start)]
2693 else:
2693 else:
2694 heads = []
2694 heads = []
2695 for branch in repo.branchmap():
2695 for branch in repo.branchmap():
2696 heads += repo.branchheads(branch, start, opts.get('closed'))
2696 heads += repo.branchheads(branch, start, opts.get('closed'))
2697 heads = [repo[h] for h in heads]
2697 heads = [repo[h] for h in heads]
2698
2698
2699 if branchrevs:
2699 if branchrevs:
2700 branches = set(repo[br].branch() for br in branchrevs)
2700 branches = set(repo[br].branch() for br in branchrevs)
2701 heads = [h for h in heads if h.branch() in branches]
2701 heads = [h for h in heads if h.branch() in branches]
2702
2702
2703 if opts.get('active') and branchrevs:
2703 if opts.get('active') and branchrevs:
2704 dagheads = repo.heads(start)
2704 dagheads = repo.heads(start)
2705 heads = [h for h in heads if h.node() in dagheads]
2705 heads = [h for h in heads if h.node() in dagheads]
2706
2706
2707 if branchrevs:
2707 if branchrevs:
2708 haveheads = set(h.branch() for h in heads)
2708 haveheads = set(h.branch() for h in heads)
2709 if branches - haveheads:
2709 if branches - haveheads:
2710 headless = ', '.join(b for b in branches - haveheads)
2710 headless = ', '.join(b for b in branches - haveheads)
2711 msg = _('no open branch heads found on branches %s')
2711 msg = _('no open branch heads found on branches %s')
2712 if opts.get('rev'):
2712 if opts.get('rev'):
2713 msg += _(' (started at %s)' % opts['rev'])
2713 msg += _(' (started at %s)' % opts['rev'])
2714 ui.warn((msg + '\n') % headless)
2714 ui.warn((msg + '\n') % headless)
2715
2715
2716 if not heads:
2716 if not heads:
2717 return 1
2717 return 1
2718
2718
2719 heads = sorted(heads, key=lambda x: -x.rev())
2719 heads = sorted(heads, key=lambda x: -x.rev())
2720 displayer = cmdutil.show_changeset(ui, repo, opts)
2720 displayer = cmdutil.show_changeset(ui, repo, opts)
2721 for ctx in heads:
2721 for ctx in heads:
2722 displayer.show(ctx)
2722 displayer.show(ctx)
2723 displayer.close()
2723 displayer.close()
2724
2724
2725 @command('help',
2725 @command('help',
2726 [('e', 'extension', None, _('show only help for extensions')),
2726 [('e', 'extension', None, _('show only help for extensions')),
2727 ('c', 'command', None, _('show only help for commands'))],
2727 ('c', 'command', None, _('show only help for commands'))],
2728 _('[-ec] [TOPIC]'))
2728 _('[-ec] [TOPIC]'))
2729 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2729 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2730 """show help for a given topic or a help overview
2730 """show help for a given topic or a help overview
2731
2731
2732 With no arguments, print a list of commands with short help messages.
2732 With no arguments, print a list of commands with short help messages.
2733
2733
2734 Given a topic, extension, or command name, print help for that
2734 Given a topic, extension, or command name, print help for that
2735 topic.
2735 topic.
2736
2736
2737 Returns 0 if successful.
2737 Returns 0 if successful.
2738 """
2738 """
2739
2739
2740 textwidth = min(ui.termwidth(), 80) - 2
2740 textwidth = min(ui.termwidth(), 80) - 2
2741
2741
2742 def optrst(options):
2742 def optrst(options):
2743 data = []
2743 data = []
2744 multioccur = False
2744 multioccur = False
2745 for option in options:
2745 for option in options:
2746 if len(option) == 5:
2746 if len(option) == 5:
2747 shortopt, longopt, default, desc, optlabel = option
2747 shortopt, longopt, default, desc, optlabel = option
2748 else:
2748 else:
2749 shortopt, longopt, default, desc = option
2749 shortopt, longopt, default, desc = option
2750 optlabel = _("VALUE") # default label
2750 optlabel = _("VALUE") # default label
2751
2751
2752 if _("DEPRECATED") in desc and not ui.verbose:
2752 if _("DEPRECATED") in desc and not ui.verbose:
2753 continue
2753 continue
2754
2754
2755 so = ''
2755 so = ''
2756 if shortopt:
2756 if shortopt:
2757 so = '-' + shortopt
2757 so = '-' + shortopt
2758 lo = '--' + longopt
2758 lo = '--' + longopt
2759 if default:
2759 if default:
2760 desc += _(" (default: %s)") % default
2760 desc += _(" (default: %s)") % default
2761
2761
2762 if isinstance(default, list):
2762 if isinstance(default, list):
2763 lo += " %s [+]" % optlabel
2763 lo += " %s [+]" % optlabel
2764 multioccur = True
2764 multioccur = True
2765 elif (default is not None) and not isinstance(default, bool):
2765 elif (default is not None) and not isinstance(default, bool):
2766 lo += " %s" % optlabel
2766 lo += " %s" % optlabel
2767
2767
2768 data.append((so, lo, desc))
2768 data.append((so, lo, desc))
2769
2769
2770 rst = minirst.maketable(data, 1)
2770 rst = minirst.maketable(data, 1)
2771
2771
2772 if multioccur:
2772 if multioccur:
2773 rst += _("\n[+] marked option can be specified multiple times")
2773 rst += _("\n[+] marked option can be specified multiple times")
2774
2774
2775 return rst
2775 return rst
2776
2776
2777 # list all option lists
2777 # list all option lists
2778 def opttext(optlist, width):
2778 def opttext(optlist, width):
2779 rst = ''
2779 rst = ''
2780 if not optlist:
2780 if not optlist:
2781 return ''
2781 return ''
2782
2782
2783 for title, options in optlist:
2783 for title, options in optlist:
2784 rst += '\n%s\n\n' % title
2784 rst += '\n%s\n\n' % title
2785 rst += optrst(options)
2785 rst += optrst(options)
2786 rst += '\n'
2786 rst += '\n'
2787
2787
2788 return '\n' + minirst.format(rst, width)
2788 return '\n' + minirst.format(rst, width)
2789
2789
2790 def addglobalopts(optlist, aliases):
2790 def addglobalopts(optlist, aliases):
2791 if ui.quiet:
2791 if ui.quiet:
2792 return []
2792 return []
2793
2793
2794 if ui.verbose:
2794 if ui.verbose:
2795 optlist.append((_("global options:"), globalopts))
2795 optlist.append((_("global options:"), globalopts))
2796 if name == 'shortlist':
2796 if name == 'shortlist':
2797 optlist.append((_('use "hg help" for the full list '
2797 optlist.append((_('use "hg help" for the full list '
2798 'of commands'), ()))
2798 'of commands'), ()))
2799 else:
2799 else:
2800 if name == 'shortlist':
2800 if name == 'shortlist':
2801 msg = _('use "hg help" for the full list of commands '
2801 msg = _('use "hg help" for the full list of commands '
2802 'or "hg -v" for details')
2802 'or "hg -v" for details')
2803 elif name and not full:
2803 elif name and not full:
2804 msg = _('use "hg help %s" to show the full help text' % name)
2804 msg = _('use "hg help %s" to show the full help text' % name)
2805 elif aliases:
2805 elif aliases:
2806 msg = _('use "hg -v help%s" to show builtin aliases and '
2806 msg = _('use "hg -v help%s" to show builtin aliases and '
2807 'global options') % (name and " " + name or "")
2807 'global options') % (name and " " + name or "")
2808 else:
2808 else:
2809 msg = _('use "hg -v help %s" to show global options') % name
2809 msg = _('use "hg -v help %s" to show global options') % name
2810 optlist.append((msg, ()))
2810 optlist.append((msg, ()))
2811
2811
2812 def helpcmd(name):
2812 def helpcmd(name):
2813 optlist = []
2813 optlist = []
2814 try:
2814 try:
2815 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2815 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2816 except error.AmbiguousCommand, inst:
2816 except error.AmbiguousCommand, inst:
2817 # py3k fix: except vars can't be used outside the scope of the
2817 # py3k fix: except vars can't be used outside the scope of the
2818 # except block, nor can be used inside a lambda. python issue4617
2818 # except block, nor can be used inside a lambda. python issue4617
2819 prefix = inst.args[0]
2819 prefix = inst.args[0]
2820 select = lambda c: c.lstrip('^').startswith(prefix)
2820 select = lambda c: c.lstrip('^').startswith(prefix)
2821 helplist(select)
2821 helplist(select)
2822 return
2822 return
2823
2823
2824 # check if it's an invalid alias and display its error if it is
2824 # check if it's an invalid alias and display its error if it is
2825 if getattr(entry[0], 'badalias', False):
2825 if getattr(entry[0], 'badalias', False):
2826 if not unknowncmd:
2826 if not unknowncmd:
2827 entry[0](ui)
2827 entry[0](ui)
2828 return
2828 return
2829
2829
2830 # synopsis
2830 # synopsis
2831 if len(entry) > 2:
2831 if len(entry) > 2:
2832 if entry[2].startswith('hg'):
2832 if entry[2].startswith('hg'):
2833 ui.write("%s\n" % entry[2])
2833 ui.write("%s\n" % entry[2])
2834 else:
2834 else:
2835 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2835 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2836 else:
2836 else:
2837 ui.write('hg %s\n' % aliases[0])
2837 ui.write('hg %s\n' % aliases[0])
2838
2838
2839 # aliases
2839 # aliases
2840 if full and not ui.quiet and len(aliases) > 1:
2840 if full and not ui.quiet and len(aliases) > 1:
2841 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2841 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2842
2842
2843 # description
2843 # description
2844 doc = gettext(entry[0].__doc__)
2844 doc = gettext(entry[0].__doc__)
2845 if not doc:
2845 if not doc:
2846 doc = _("(no help text available)")
2846 doc = _("(no help text available)")
2847 if util.safehasattr(entry[0], 'definition'): # aliased command
2847 if util.safehasattr(entry[0], 'definition'): # aliased command
2848 if entry[0].definition.startswith('!'): # shell alias
2848 if entry[0].definition.startswith('!'): # shell alias
2849 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2849 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2850 else:
2850 else:
2851 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2851 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2852 if ui.quiet or not full:
2852 if ui.quiet or not full:
2853 doc = doc.splitlines()[0]
2853 doc = doc.splitlines()[0]
2854 keep = ui.verbose and ['verbose'] or []
2854 keep = ui.verbose and ['verbose'] or []
2855 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2855 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2856 ui.write("\n%s" % formatted)
2856 ui.write("\n%s" % formatted)
2857 if pruned:
2857 if pruned:
2858 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2858 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2859
2859
2860 if not ui.quiet:
2860 if not ui.quiet:
2861 # options
2861 # options
2862 if entry[1]:
2862 if entry[1]:
2863 optlist.append((_("options:\n"), entry[1]))
2863 optlist.append((_("options:\n"), entry[1]))
2864
2864
2865 # check if this command shadows a non-trivial (multi-line)
2865 # check if this command shadows a non-trivial (multi-line)
2866 # extension help text
2866 # extension help text
2867 try:
2867 try:
2868 mod = extensions.find(name)
2868 mod = extensions.find(name)
2869 doc = gettext(mod.__doc__) or ''
2869 doc = gettext(mod.__doc__) or ''
2870 if '\n' in doc.strip():
2870 if '\n' in doc.strip():
2871 msg = _('use "hg help -e %s" to show help for '
2871 msg = _('use "hg help -e %s" to show help for '
2872 'the %s extension') % (name, name)
2872 'the %s extension') % (name, name)
2873 ui.write('\n%s\n' % msg)
2873 ui.write('\n%s\n' % msg)
2874 except KeyError:
2874 except KeyError:
2875 pass
2875 pass
2876
2876
2877 addglobalopts(optlist, False)
2877 addglobalopts(optlist, False)
2878 ui.write(opttext(optlist, textwidth))
2878 ui.write(opttext(optlist, textwidth))
2879
2879
2880 def helplist(select=None):
2880 def helplist(select=None):
2881 # list of commands
2881 # list of commands
2882 if name == "shortlist":
2882 if name == "shortlist":
2883 header = _('basic commands:\n\n')
2883 header = _('basic commands:\n\n')
2884 else:
2884 else:
2885 header = _('list of commands:\n\n')
2885 header = _('list of commands:\n\n')
2886
2886
2887 h = {}
2887 h = {}
2888 cmds = {}
2888 cmds = {}
2889 for c, e in table.iteritems():
2889 for c, e in table.iteritems():
2890 f = c.split("|", 1)[0]
2890 f = c.split("|", 1)[0]
2891 if select and not select(f):
2891 if select and not select(f):
2892 continue
2892 continue
2893 if (not select and name != 'shortlist' and
2893 if (not select and name != 'shortlist' and
2894 e[0].__module__ != __name__):
2894 e[0].__module__ != __name__):
2895 continue
2895 continue
2896 if name == "shortlist" and not f.startswith("^"):
2896 if name == "shortlist" and not f.startswith("^"):
2897 continue
2897 continue
2898 f = f.lstrip("^")
2898 f = f.lstrip("^")
2899 if not ui.debugflag and f.startswith("debug"):
2899 if not ui.debugflag and f.startswith("debug"):
2900 continue
2900 continue
2901 doc = e[0].__doc__
2901 doc = e[0].__doc__
2902 if doc and 'DEPRECATED' in doc and not ui.verbose:
2902 if doc and 'DEPRECATED' in doc and not ui.verbose:
2903 continue
2903 continue
2904 doc = gettext(doc)
2904 doc = gettext(doc)
2905 if not doc:
2905 if not doc:
2906 doc = _("(no help text available)")
2906 doc = _("(no help text available)")
2907 h[f] = doc.splitlines()[0].rstrip()
2907 h[f] = doc.splitlines()[0].rstrip()
2908 cmds[f] = c.lstrip("^")
2908 cmds[f] = c.lstrip("^")
2909
2909
2910 if not h:
2910 if not h:
2911 ui.status(_('no commands defined\n'))
2911 ui.status(_('no commands defined\n'))
2912 return
2912 return
2913
2913
2914 ui.status(header)
2914 ui.status(header)
2915 fns = sorted(h)
2915 fns = sorted(h)
2916 m = max(map(len, fns))
2916 m = max(map(len, fns))
2917 for f in fns:
2917 for f in fns:
2918 if ui.verbose:
2918 if ui.verbose:
2919 commands = cmds[f].replace("|",", ")
2919 commands = cmds[f].replace("|",", ")
2920 ui.write(" %s:\n %s\n"%(commands, h[f]))
2920 ui.write(" %s:\n %s\n"%(commands, h[f]))
2921 else:
2921 else:
2922 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2922 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2923 initindent=' %-*s ' % (m, f),
2923 initindent=' %-*s ' % (m, f),
2924 hangindent=' ' * (m + 4))))
2924 hangindent=' ' * (m + 4))))
2925
2925
2926 if not name:
2926 if not name:
2927 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2927 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2928 if text:
2928 if text:
2929 ui.write("\n%s" % minirst.format(text, textwidth))
2929 ui.write("\n%s" % minirst.format(text, textwidth))
2930
2930
2931 ui.write(_("\nadditional help topics:\n\n"))
2931 ui.write(_("\nadditional help topics:\n\n"))
2932 topics = []
2932 topics = []
2933 for names, header, doc in help.helptable:
2933 for names, header, doc in help.helptable:
2934 topics.append((sorted(names, key=len, reverse=True)[0], header))
2934 topics.append((sorted(names, key=len, reverse=True)[0], header))
2935 topics_len = max([len(s[0]) for s in topics])
2935 topics_len = max([len(s[0]) for s in topics])
2936 for t, desc in topics:
2936 for t, desc in topics:
2937 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2937 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2938
2938
2939 optlist = []
2939 optlist = []
2940 addglobalopts(optlist, True)
2940 addglobalopts(optlist, True)
2941 ui.write(opttext(optlist, textwidth))
2941 ui.write(opttext(optlist, textwidth))
2942
2942
2943 def helptopic(name):
2943 def helptopic(name):
2944 for names, header, doc in help.helptable:
2944 for names, header, doc in help.helptable:
2945 if name in names:
2945 if name in names:
2946 break
2946 break
2947 else:
2947 else:
2948 raise error.UnknownCommand(name)
2948 raise error.UnknownCommand(name)
2949
2949
2950 # description
2950 # description
2951 if not doc:
2951 if not doc:
2952 doc = _("(no help text available)")
2952 doc = _("(no help text available)")
2953 if util.safehasattr(doc, '__call__'):
2953 if util.safehasattr(doc, '__call__'):
2954 doc = doc()
2954 doc = doc()
2955
2955
2956 ui.write("%s\n\n" % header)
2956 ui.write("%s\n\n" % header)
2957 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2957 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2958 try:
2958 try:
2959 cmdutil.findcmd(name, table)
2959 cmdutil.findcmd(name, table)
2960 ui.write(_('\nuse "hg help -c %s" to see help for '
2960 ui.write(_('\nuse "hg help -c %s" to see help for '
2961 'the %s command\n') % (name, name))
2961 'the %s command\n') % (name, name))
2962 except error.UnknownCommand:
2962 except error.UnknownCommand:
2963 pass
2963 pass
2964
2964
2965 def helpext(name):
2965 def helpext(name):
2966 try:
2966 try:
2967 mod = extensions.find(name)
2967 mod = extensions.find(name)
2968 doc = gettext(mod.__doc__) or _('no help text available')
2968 doc = gettext(mod.__doc__) or _('no help text available')
2969 except KeyError:
2969 except KeyError:
2970 mod = None
2970 mod = None
2971 doc = extensions.disabledext(name)
2971 doc = extensions.disabledext(name)
2972 if not doc:
2972 if not doc:
2973 raise error.UnknownCommand(name)
2973 raise error.UnknownCommand(name)
2974
2974
2975 if '\n' not in doc:
2975 if '\n' not in doc:
2976 head, tail = doc, ""
2976 head, tail = doc, ""
2977 else:
2977 else:
2978 head, tail = doc.split('\n', 1)
2978 head, tail = doc.split('\n', 1)
2979 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2979 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2980 if tail:
2980 if tail:
2981 ui.write(minirst.format(tail, textwidth))
2981 ui.write(minirst.format(tail, textwidth))
2982 ui.status('\n')
2982 ui.status('\n')
2983
2983
2984 if mod:
2984 if mod:
2985 try:
2985 try:
2986 ct = mod.cmdtable
2986 ct = mod.cmdtable
2987 except AttributeError:
2987 except AttributeError:
2988 ct = {}
2988 ct = {}
2989 modcmds = set([c.split('|', 1)[0] for c in ct])
2989 modcmds = set([c.split('|', 1)[0] for c in ct])
2990 helplist(modcmds.__contains__)
2990 helplist(modcmds.__contains__)
2991 else:
2991 else:
2992 ui.write(_('use "hg help extensions" for information on enabling '
2992 ui.write(_('use "hg help extensions" for information on enabling '
2993 'extensions\n'))
2993 'extensions\n'))
2994
2994
2995 def helpextcmd(name):
2995 def helpextcmd(name):
2996 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2996 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2997 doc = gettext(mod.__doc__).splitlines()[0]
2997 doc = gettext(mod.__doc__).splitlines()[0]
2998
2998
2999 msg = help.listexts(_("'%s' is provided by the following "
2999 msg = help.listexts(_("'%s' is provided by the following "
3000 "extension:") % cmd, {ext: doc}, indent=4)
3000 "extension:") % cmd, {ext: doc}, indent=4)
3001 ui.write(minirst.format(msg, textwidth))
3001 ui.write(minirst.format(msg, textwidth))
3002 ui.write('\n')
3002 ui.write('\n')
3003 ui.write(_('use "hg help extensions" for information on enabling '
3003 ui.write(_('use "hg help extensions" for information on enabling '
3004 'extensions\n'))
3004 'extensions\n'))
3005
3005
3006 if name and name != 'shortlist':
3006 if name and name != 'shortlist':
3007 i = None
3007 i = None
3008 if unknowncmd:
3008 if unknowncmd:
3009 queries = (helpextcmd,)
3009 queries = (helpextcmd,)
3010 elif opts.get('extension'):
3010 elif opts.get('extension'):
3011 queries = (helpext,)
3011 queries = (helpext,)
3012 elif opts.get('command'):
3012 elif opts.get('command'):
3013 queries = (helpcmd,)
3013 queries = (helpcmd,)
3014 else:
3014 else:
3015 queries = (helptopic, helpcmd, helpext, helpextcmd)
3015 queries = (helptopic, helpcmd, helpext, helpextcmd)
3016 for f in queries:
3016 for f in queries:
3017 try:
3017 try:
3018 f(name)
3018 f(name)
3019 i = None
3019 i = None
3020 break
3020 break
3021 except error.UnknownCommand, inst:
3021 except error.UnknownCommand, inst:
3022 i = inst
3022 i = inst
3023 if i:
3023 if i:
3024 raise i
3024 raise i
3025 else:
3025 else:
3026 # program name
3026 # program name
3027 ui.status(_("Mercurial Distributed SCM\n"))
3027 ui.status(_("Mercurial Distributed SCM\n"))
3028 ui.status('\n')
3028 ui.status('\n')
3029 helplist()
3029 helplist()
3030
3030
3031
3031
3032 @command('identify|id',
3032 @command('identify|id',
3033 [('r', 'rev', '',
3033 [('r', 'rev', '',
3034 _('identify the specified revision'), _('REV')),
3034 _('identify the specified revision'), _('REV')),
3035 ('n', 'num', None, _('show local revision number')),
3035 ('n', 'num', None, _('show local revision number')),
3036 ('i', 'id', None, _('show global revision id')),
3036 ('i', 'id', None, _('show global revision id')),
3037 ('b', 'branch', None, _('show branch')),
3037 ('b', 'branch', None, _('show branch')),
3038 ('t', 'tags', None, _('show tags')),
3038 ('t', 'tags', None, _('show tags')),
3039 ('B', 'bookmarks', None, _('show bookmarks'))],
3039 ('B', 'bookmarks', None, _('show bookmarks'))],
3040 _('[-nibtB] [-r REV] [SOURCE]'))
3040 _('[-nibtB] [-r REV] [SOURCE]'))
3041 def identify(ui, repo, source=None, rev=None,
3041 def identify(ui, repo, source=None, rev=None,
3042 num=None, id=None, branch=None, tags=None, bookmarks=None):
3042 num=None, id=None, branch=None, tags=None, bookmarks=None):
3043 """identify the working copy or specified revision
3043 """identify the working copy or specified revision
3044
3044
3045 Print a summary identifying the repository state at REV using one or
3045 Print a summary identifying the repository state at REV using one or
3046 two parent hash identifiers, followed by a "+" if the working
3046 two parent hash identifiers, followed by a "+" if the working
3047 directory has uncommitted changes, the branch name (if not default),
3047 directory has uncommitted changes, the branch name (if not default),
3048 a list of tags, and a list of bookmarks.
3048 a list of tags, and a list of bookmarks.
3049
3049
3050 When REV is not given, print a summary of the current state of the
3050 When REV is not given, print a summary of the current state of the
3051 repository.
3051 repository.
3052
3052
3053 Specifying a path to a repository root or Mercurial bundle will
3053 Specifying a path to a repository root or Mercurial bundle will
3054 cause lookup to operate on that repository/bundle.
3054 cause lookup to operate on that repository/bundle.
3055
3055
3056 .. container:: verbose
3056 .. container:: verbose
3057
3057
3058 Examples:
3058 Examples:
3059
3059
3060 - generate a build identifier for the working directory::
3060 - generate a build identifier for the working directory::
3061
3061
3062 hg id --id > build-id.dat
3062 hg id --id > build-id.dat
3063
3063
3064 - find the revision corresponding to a tag::
3064 - find the revision corresponding to a tag::
3065
3065
3066 hg id -n -r 1.3
3066 hg id -n -r 1.3
3067
3067
3068 - check the most recent revision of a remote repository::
3068 - check the most recent revision of a remote repository::
3069
3069
3070 hg id -r tip http://selenic.com/hg/
3070 hg id -r tip http://selenic.com/hg/
3071
3071
3072 Returns 0 if successful.
3072 Returns 0 if successful.
3073 """
3073 """
3074
3074
3075 if not repo and not source:
3075 if not repo and not source:
3076 raise util.Abort(_("there is no Mercurial repository here "
3076 raise util.Abort(_("there is no Mercurial repository here "
3077 "(.hg not found)"))
3077 "(.hg not found)"))
3078
3078
3079 hexfunc = ui.debugflag and hex or short
3079 hexfunc = ui.debugflag and hex or short
3080 default = not (num or id or branch or tags or bookmarks)
3080 default = not (num or id or branch or tags or bookmarks)
3081 output = []
3081 output = []
3082 revs = []
3082 revs = []
3083
3083
3084 if source:
3084 if source:
3085 source, branches = hg.parseurl(ui.expandpath(source))
3085 source, branches = hg.parseurl(ui.expandpath(source))
3086 repo = hg.peer(ui, {}, source)
3086 repo = hg.peer(ui, {}, source)
3087 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3087 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3088
3088
3089 if not repo.local():
3089 if not repo.local():
3090 if num or branch or tags:
3090 if num or branch or tags:
3091 raise util.Abort(
3091 raise util.Abort(
3092 _("can't query remote revision number, branch, or tags"))
3092 _("can't query remote revision number, branch, or tags"))
3093 if not rev and revs:
3093 if not rev and revs:
3094 rev = revs[0]
3094 rev = revs[0]
3095 if not rev:
3095 if not rev:
3096 rev = "tip"
3096 rev = "tip"
3097
3097
3098 remoterev = repo.lookup(rev)
3098 remoterev = repo.lookup(rev)
3099 if default or id:
3099 if default or id:
3100 output = [hexfunc(remoterev)]
3100 output = [hexfunc(remoterev)]
3101
3101
3102 def getbms():
3102 def getbms():
3103 bms = []
3103 bms = []
3104
3104
3105 if 'bookmarks' in repo.listkeys('namespaces'):
3105 if 'bookmarks' in repo.listkeys('namespaces'):
3106 hexremoterev = hex(remoterev)
3106 hexremoterev = hex(remoterev)
3107 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3107 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3108 if bmr == hexremoterev]
3108 if bmr == hexremoterev]
3109
3109
3110 return bms
3110 return bms
3111
3111
3112 if bookmarks:
3112 if bookmarks:
3113 output.extend(getbms())
3113 output.extend(getbms())
3114 elif default and not ui.quiet:
3114 elif default and not ui.quiet:
3115 # multiple bookmarks for a single parent separated by '/'
3115 # multiple bookmarks for a single parent separated by '/'
3116 bm = '/'.join(getbms())
3116 bm = '/'.join(getbms())
3117 if bm:
3117 if bm:
3118 output.append(bm)
3118 output.append(bm)
3119 else:
3119 else:
3120 if not rev:
3120 if not rev:
3121 ctx = repo[None]
3121 ctx = repo[None]
3122 parents = ctx.parents()
3122 parents = ctx.parents()
3123 changed = ""
3123 changed = ""
3124 if default or id or num:
3124 if default or id or num:
3125 changed = util.any(repo.status()) and "+" or ""
3125 changed = util.any(repo.status()) and "+" or ""
3126 if default or id:
3126 if default or id:
3127 output = ["%s%s" %
3127 output = ["%s%s" %
3128 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3128 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3129 if num:
3129 if num:
3130 output.append("%s%s" %
3130 output.append("%s%s" %
3131 ('+'.join([str(p.rev()) for p in parents]), changed))
3131 ('+'.join([str(p.rev()) for p in parents]), changed))
3132 else:
3132 else:
3133 ctx = scmutil.revsingle(repo, rev)
3133 ctx = scmutil.revsingle(repo, rev)
3134 if default or id:
3134 if default or id:
3135 output = [hexfunc(ctx.node())]
3135 output = [hexfunc(ctx.node())]
3136 if num:
3136 if num:
3137 output.append(str(ctx.rev()))
3137 output.append(str(ctx.rev()))
3138
3138
3139 if default and not ui.quiet:
3139 if default and not ui.quiet:
3140 b = ctx.branch()
3140 b = ctx.branch()
3141 if b != 'default':
3141 if b != 'default':
3142 output.append("(%s)" % b)
3142 output.append("(%s)" % b)
3143
3143
3144 # multiple tags for a single parent separated by '/'
3144 # multiple tags for a single parent separated by '/'
3145 t = '/'.join(ctx.tags())
3145 t = '/'.join(ctx.tags())
3146 if t:
3146 if t:
3147 output.append(t)
3147 output.append(t)
3148
3148
3149 # multiple bookmarks for a single parent separated by '/'
3149 # multiple bookmarks for a single parent separated by '/'
3150 bm = '/'.join(ctx.bookmarks())
3150 bm = '/'.join(ctx.bookmarks())
3151 if bm:
3151 if bm:
3152 output.append(bm)
3152 output.append(bm)
3153 else:
3153 else:
3154 if branch:
3154 if branch:
3155 output.append(ctx.branch())
3155 output.append(ctx.branch())
3156
3156
3157 if tags:
3157 if tags:
3158 output.extend(ctx.tags())
3158 output.extend(ctx.tags())
3159
3159
3160 if bookmarks:
3160 if bookmarks:
3161 output.extend(ctx.bookmarks())
3161 output.extend(ctx.bookmarks())
3162
3162
3163 ui.write("%s\n" % ' '.join(output))
3163 ui.write("%s\n" % ' '.join(output))
3164
3164
3165 @command('import|patch',
3165 @command('import|patch',
3166 [('p', 'strip', 1,
3166 [('p', 'strip', 1,
3167 _('directory strip option for patch. This has the same '
3167 _('directory strip option for patch. This has the same '
3168 'meaning as the corresponding patch option'), _('NUM')),
3168 'meaning as the corresponding patch option'), _('NUM')),
3169 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3169 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3170 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3170 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3171 ('', 'no-commit', None,
3171 ('', 'no-commit', None,
3172 _("don't commit, just update the working directory")),
3172 _("don't commit, just update the working directory")),
3173 ('', 'bypass', None,
3173 ('', 'bypass', None,
3174 _("apply patch without touching the working directory")),
3174 _("apply patch without touching the working directory")),
3175 ('', 'exact', None,
3175 ('', 'exact', None,
3176 _('apply patch to the nodes from which it was generated')),
3176 _('apply patch to the nodes from which it was generated')),
3177 ('', 'import-branch', None,
3177 ('', 'import-branch', None,
3178 _('use any branch information in patch (implied by --exact)'))] +
3178 _('use any branch information in patch (implied by --exact)'))] +
3179 commitopts + commitopts2 + similarityopts,
3179 commitopts + commitopts2 + similarityopts,
3180 _('[OPTION]... PATCH...'))
3180 _('[OPTION]... PATCH...'))
3181 def import_(ui, repo, patch1, *patches, **opts):
3181 def import_(ui, repo, patch1, *patches, **opts):
3182 """import an ordered set of patches
3182 """import an ordered set of patches
3183
3183
3184 Import a list of patches and commit them individually (unless
3184 Import a list of patches and commit them individually (unless
3185 --no-commit is specified).
3185 --no-commit is specified).
3186
3186
3187 If there are outstanding changes in the working directory, import
3187 If there are outstanding changes in the working directory, import
3188 will abort unless given the -f/--force flag.
3188 will abort unless given the -f/--force flag.
3189
3189
3190 You can import a patch straight from a mail message. Even patches
3190 You can import a patch straight from a mail message. Even patches
3191 as attachments work (to use the body part, it must have type
3191 as attachments work (to use the body part, it must have type
3192 text/plain or text/x-patch). From and Subject headers of email
3192 text/plain or text/x-patch). From and Subject headers of email
3193 message are used as default committer and commit message. All
3193 message are used as default committer and commit message. All
3194 text/plain body parts before first diff are added to commit
3194 text/plain body parts before first diff are added to commit
3195 message.
3195 message.
3196
3196
3197 If the imported patch was generated by :hg:`export`, user and
3197 If the imported patch was generated by :hg:`export`, user and
3198 description from patch override values from message headers and
3198 description from patch override values from message headers and
3199 body. Values given on command line with -m/--message and -u/--user
3199 body. Values given on command line with -m/--message and -u/--user
3200 override these.
3200 override these.
3201
3201
3202 If --exact is specified, import will set the working directory to
3202 If --exact is specified, import will set the working directory to
3203 the parent of each patch before applying it, and will abort if the
3203 the parent of each patch before applying it, and will abort if the
3204 resulting changeset has a different ID than the one recorded in
3204 resulting changeset has a different ID than the one recorded in
3205 the patch. This may happen due to character set problems or other
3205 the patch. This may happen due to character set problems or other
3206 deficiencies in the text patch format.
3206 deficiencies in the text patch format.
3207
3207
3208 Use --bypass to apply and commit patches directly to the
3208 Use --bypass to apply and commit patches directly to the
3209 repository, not touching the working directory. Without --exact,
3209 repository, not touching the working directory. Without --exact,
3210 patches will be applied on top of the working directory parent
3210 patches will be applied on top of the working directory parent
3211 revision.
3211 revision.
3212
3212
3213 With -s/--similarity, hg will attempt to discover renames and
3213 With -s/--similarity, hg will attempt to discover renames and
3214 copies in the patch in the same way as 'addremove'.
3214 copies in the patch in the same way as 'addremove'.
3215
3215
3216 To read a patch from standard input, use "-" as the patch name. If
3216 To read a patch from standard input, use "-" as the patch name. If
3217 a URL is specified, the patch will be downloaded from it.
3217 a URL is specified, the patch will be downloaded from it.
3218 See :hg:`help dates` for a list of formats valid for -d/--date.
3218 See :hg:`help dates` for a list of formats valid for -d/--date.
3219
3219
3220 .. container:: verbose
3220 .. container:: verbose
3221
3221
3222 Examples:
3222 Examples:
3223
3223
3224 - import a traditional patch from a website and detect renames::
3224 - import a traditional patch from a website and detect renames::
3225
3225
3226 hg import -s 80 http://example.com/bugfix.patch
3226 hg import -s 80 http://example.com/bugfix.patch
3227
3227
3228 - import a changeset from an hgweb server::
3228 - import a changeset from an hgweb server::
3229
3229
3230 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3230 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3231
3231
3232 - import all the patches in an Unix-style mbox::
3232 - import all the patches in an Unix-style mbox::
3233
3233
3234 hg import incoming-patches.mbox
3234 hg import incoming-patches.mbox
3235
3235
3236 - attempt to exactly restore an exported changeset (not always
3236 - attempt to exactly restore an exported changeset (not always
3237 possible)::
3237 possible)::
3238
3238
3239 hg import --exact proposed-fix.patch
3239 hg import --exact proposed-fix.patch
3240
3240
3241 Returns 0 on success.
3241 Returns 0 on success.
3242 """
3242 """
3243 patches = (patch1,) + patches
3243 patches = (patch1,) + patches
3244
3244
3245 date = opts.get('date')
3245 date = opts.get('date')
3246 if date:
3246 if date:
3247 opts['date'] = util.parsedate(date)
3247 opts['date'] = util.parsedate(date)
3248
3248
3249 update = not opts.get('bypass')
3249 update = not opts.get('bypass')
3250 if not update and opts.get('no_commit'):
3250 if not update and opts.get('no_commit'):
3251 raise util.Abort(_('cannot use --no-commit with --bypass'))
3251 raise util.Abort(_('cannot use --no-commit with --bypass'))
3252 try:
3252 try:
3253 sim = float(opts.get('similarity') or 0)
3253 sim = float(opts.get('similarity') or 0)
3254 except ValueError:
3254 except ValueError:
3255 raise util.Abort(_('similarity must be a number'))
3255 raise util.Abort(_('similarity must be a number'))
3256 if sim < 0 or sim > 100:
3256 if sim < 0 or sim > 100:
3257 raise util.Abort(_('similarity must be between 0 and 100'))
3257 raise util.Abort(_('similarity must be between 0 and 100'))
3258 if sim and not update:
3258 if sim and not update:
3259 raise util.Abort(_('cannot use --similarity with --bypass'))
3259 raise util.Abort(_('cannot use --similarity with --bypass'))
3260
3260
3261 if (opts.get('exact') or not opts.get('force')) and update:
3261 if (opts.get('exact') or not opts.get('force')) and update:
3262 cmdutil.bailifchanged(repo)
3262 cmdutil.bailifchanged(repo)
3263
3263
3264 d = opts["base"]
3264 d = opts["base"]
3265 strip = opts["strip"]
3265 strip = opts["strip"]
3266 wlock = lock = None
3266 wlock = lock = None
3267 msgs = []
3267 msgs = []
3268
3268
3269 def checkexact(repo, n, nodeid):
3269 def checkexact(repo, n, nodeid):
3270 if opts.get('exact') and hex(n) != nodeid:
3270 if opts.get('exact') and hex(n) != nodeid:
3271 repo.rollback()
3271 repo.rollback()
3272 raise util.Abort(_('patch is damaged or loses information'))
3272 raise util.Abort(_('patch is damaged or loses information'))
3273
3273
3274 def tryone(ui, hunk, parents):
3274 def tryone(ui, hunk, parents):
3275 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3275 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3276 patch.extract(ui, hunk)
3276 patch.extract(ui, hunk)
3277
3277
3278 if not tmpname:
3278 if not tmpname:
3279 return None
3279 return (None, None)
3280 commitid = _('to working directory')
3280 msg = _('applied to working directory')
3281
3281
3282 try:
3282 try:
3283 cmdline_message = cmdutil.logmessage(ui, opts)
3283 cmdline_message = cmdutil.logmessage(ui, opts)
3284 if cmdline_message:
3284 if cmdline_message:
3285 # pickup the cmdline msg
3285 # pickup the cmdline msg
3286 message = cmdline_message
3286 message = cmdline_message
3287 elif message:
3287 elif message:
3288 # pickup the patch msg
3288 # pickup the patch msg
3289 message = message.strip()
3289 message = message.strip()
3290 else:
3290 else:
3291 # launch the editor
3291 # launch the editor
3292 message = None
3292 message = None
3293 ui.debug('message:\n%s\n' % message)
3293 ui.debug('message:\n%s\n' % message)
3294
3294
3295 if len(parents) == 1:
3295 if len(parents) == 1:
3296 parents.append(repo[nullid])
3296 parents.append(repo[nullid])
3297 if opts.get('exact'):
3297 if opts.get('exact'):
3298 if not nodeid or not p1:
3298 if not nodeid or not p1:
3299 raise util.Abort(_('not a Mercurial patch'))
3299 raise util.Abort(_('not a Mercurial patch'))
3300 p1 = repo[p1]
3300 p1 = repo[p1]
3301 p2 = repo[p2 or nullid]
3301 p2 = repo[p2 or nullid]
3302 elif p2:
3302 elif p2:
3303 try:
3303 try:
3304 p1 = repo[p1]
3304 p1 = repo[p1]
3305 p2 = repo[p2]
3305 p2 = repo[p2]
3306 except error.RepoError:
3306 except error.RepoError:
3307 p1, p2 = parents
3307 p1, p2 = parents
3308 else:
3308 else:
3309 p1, p2 = parents
3309 p1, p2 = parents
3310
3310
3311 n = None
3311 n = None
3312 if update:
3312 if update:
3313 if opts.get('exact') and p1 != parents[0]:
3313 if opts.get('exact') and p1 != parents[0]:
3314 hg.clean(repo, p1.node())
3314 hg.clean(repo, p1.node())
3315 if p1 != parents[0] and p2 != parents[1]:
3315 if p1 != parents[0] and p2 != parents[1]:
3316 repo.dirstate.setparents(p1.node(), p2.node())
3316 repo.dirstate.setparents(p1.node(), p2.node())
3317
3317
3318 if opts.get('exact') or opts.get('import_branch'):
3318 if opts.get('exact') or opts.get('import_branch'):
3319 repo.dirstate.setbranch(branch or 'default')
3319 repo.dirstate.setbranch(branch or 'default')
3320
3320
3321 files = set()
3321 files = set()
3322 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3322 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3323 eolmode=None, similarity=sim / 100.0)
3323 eolmode=None, similarity=sim / 100.0)
3324 files = list(files)
3324 files = list(files)
3325 if opts.get('no_commit'):
3325 if opts.get('no_commit'):
3326 if message:
3326 if message:
3327 msgs.append(message)
3327 msgs.append(message)
3328 else:
3328 else:
3329 if opts.get('exact'):
3329 if opts.get('exact'):
3330 m = None
3330 m = None
3331 else:
3331 else:
3332 m = scmutil.matchfiles(repo, files or [])
3332 m = scmutil.matchfiles(repo, files or [])
3333 n = repo.commit(message, opts.get('user') or user,
3333 n = repo.commit(message, opts.get('user') or user,
3334 opts.get('date') or date, match=m,
3334 opts.get('date') or date, match=m,
3335 editor=cmdutil.commiteditor)
3335 editor=cmdutil.commiteditor)
3336 checkexact(repo, n, nodeid)
3336 checkexact(repo, n, nodeid)
3337 # Force a dirstate write so that the next transaction
3337 # Force a dirstate write so that the next transaction
3338 # backups an up-to-date file.
3338 # backups an up-to-date file.
3339 repo.dirstate.write()
3339 repo.dirstate.write()
3340 else:
3340 else:
3341 if opts.get('exact') or opts.get('import_branch'):
3341 if opts.get('exact') or opts.get('import_branch'):
3342 branch = branch or 'default'
3342 branch = branch or 'default'
3343 else:
3343 else:
3344 branch = p1.branch()
3344 branch = p1.branch()
3345 store = patch.filestore()
3345 store = patch.filestore()
3346 try:
3346 try:
3347 files = set()
3347 files = set()
3348 try:
3348 try:
3349 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3349 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3350 files, eolmode=None)
3350 files, eolmode=None)
3351 except patch.PatchError, e:
3351 except patch.PatchError, e:
3352 raise util.Abort(str(e))
3352 raise util.Abort(str(e))
3353 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3353 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3354 message,
3354 message,
3355 opts.get('user') or user,
3355 opts.get('user') or user,
3356 opts.get('date') or date,
3356 opts.get('date') or date,
3357 branch, files, store,
3357 branch, files, store,
3358 editor=cmdutil.commiteditor)
3358 editor=cmdutil.commiteditor)
3359 repo.savecommitmessage(memctx.description())
3359 repo.savecommitmessage(memctx.description())
3360 n = memctx.commit()
3360 n = memctx.commit()
3361 checkexact(repo, n, nodeid)
3361 checkexact(repo, n, nodeid)
3362 finally:
3362 finally:
3363 store.close()
3363 store.close()
3364 if n:
3364 if n:
3365 commitid = short(n)
3365 msg = _('created %s') % short(n)
3366 return commitid
3366 return (msg, n)
3367 finally:
3367 finally:
3368 os.unlink(tmpname)
3368 os.unlink(tmpname)
3369
3369
3370 try:
3370 try:
3371 wlock = repo.wlock()
3371 wlock = repo.wlock()
3372 lock = repo.lock()
3372 lock = repo.lock()
3373 parents = repo.parents()
3373 parents = repo.parents()
3374 lastcommit = None
3375 for p in patches:
3374 for p in patches:
3376 pf = os.path.join(d, p)
3375 pf = os.path.join(d, p)
3377
3376
3378 if pf == '-':
3377 if pf == '-':
3379 ui.status(_("applying patch from stdin\n"))
3378 ui.status(_("applying patch from stdin\n"))
3380 pf = ui.fin
3379 pf = ui.fin
3381 else:
3380 else:
3382 ui.status(_("applying %s\n") % p)
3381 ui.status(_("applying %s\n") % p)
3383 pf = url.open(ui, pf)
3382 pf = url.open(ui, pf)
3384
3383
3385 haspatch = False
3384 haspatch = False
3386 for hunk in patch.split(pf):
3385 for hunk in patch.split(pf):
3387 commitid = tryone(ui, hunk, parents)
3386 (msg, node) = tryone(ui, hunk, parents)
3388 if commitid:
3387 if msg:
3389 haspatch = True
3388 haspatch = True
3390 if lastcommit:
3389 ui.note(msg + '\n')
3391 ui.status(_('applied %s\n') % lastcommit)
3392 lastcommit = commitid
3393 if update or opts.get('exact'):
3390 if update or opts.get('exact'):
3394 parents = repo.parents()
3391 parents = repo.parents()
3395 else:
3392 else:
3396 parents = [repo[commitid]]
3393 parents = [repo[node]]
3397
3394
3398 if not haspatch:
3395 if not haspatch:
3399 raise util.Abort(_('no diffs found'))
3396 raise util.Abort(_('no diffs found'))
3400
3397
3401 if msgs:
3398 if msgs:
3402 repo.savecommitmessage('\n* * *\n'.join(msgs))
3399 repo.savecommitmessage('\n* * *\n'.join(msgs))
3403 finally:
3400 finally:
3404 release(lock, wlock)
3401 release(lock, wlock)
3405
3402
3406 @command('incoming|in',
3403 @command('incoming|in',
3407 [('f', 'force', None,
3404 [('f', 'force', None,
3408 _('run even if remote repository is unrelated')),
3405 _('run even if remote repository is unrelated')),
3409 ('n', 'newest-first', None, _('show newest record first')),
3406 ('n', 'newest-first', None, _('show newest record first')),
3410 ('', 'bundle', '',
3407 ('', 'bundle', '',
3411 _('file to store the bundles into'), _('FILE')),
3408 _('file to store the bundles into'), _('FILE')),
3412 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3409 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3413 ('B', 'bookmarks', False, _("compare bookmarks")),
3410 ('B', 'bookmarks', False, _("compare bookmarks")),
3414 ('b', 'branch', [],
3411 ('b', 'branch', [],
3415 _('a specific branch you would like to pull'), _('BRANCH')),
3412 _('a specific branch you would like to pull'), _('BRANCH')),
3416 ] + logopts + remoteopts + subrepoopts,
3413 ] + logopts + remoteopts + subrepoopts,
3417 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3414 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3418 def incoming(ui, repo, source="default", **opts):
3415 def incoming(ui, repo, source="default", **opts):
3419 """show new changesets found in source
3416 """show new changesets found in source
3420
3417
3421 Show new changesets found in the specified path/URL or the default
3418 Show new changesets found in the specified path/URL or the default
3422 pull location. These are the changesets that would have been pulled
3419 pull location. These are the changesets that would have been pulled
3423 if a pull at the time you issued this command.
3420 if a pull at the time you issued this command.
3424
3421
3425 For remote repository, using --bundle avoids downloading the
3422 For remote repository, using --bundle avoids downloading the
3426 changesets twice if the incoming is followed by a pull.
3423 changesets twice if the incoming is followed by a pull.
3427
3424
3428 See pull for valid source format details.
3425 See pull for valid source format details.
3429
3426
3430 Returns 0 if there are incoming changes, 1 otherwise.
3427 Returns 0 if there are incoming changes, 1 otherwise.
3431 """
3428 """
3432 if opts.get('bundle') and opts.get('subrepos'):
3429 if opts.get('bundle') and opts.get('subrepos'):
3433 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3430 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3434
3431
3435 if opts.get('bookmarks'):
3432 if opts.get('bookmarks'):
3436 source, branches = hg.parseurl(ui.expandpath(source),
3433 source, branches = hg.parseurl(ui.expandpath(source),
3437 opts.get('branch'))
3434 opts.get('branch'))
3438 other = hg.peer(repo, opts, source)
3435 other = hg.peer(repo, opts, source)
3439 if 'bookmarks' not in other.listkeys('namespaces'):
3436 if 'bookmarks' not in other.listkeys('namespaces'):
3440 ui.warn(_("remote doesn't support bookmarks\n"))
3437 ui.warn(_("remote doesn't support bookmarks\n"))
3441 return 0
3438 return 0
3442 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3439 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3443 return bookmarks.diff(ui, repo, other)
3440 return bookmarks.diff(ui, repo, other)
3444
3441
3445 repo._subtoppath = ui.expandpath(source)
3442 repo._subtoppath = ui.expandpath(source)
3446 try:
3443 try:
3447 return hg.incoming(ui, repo, source, opts)
3444 return hg.incoming(ui, repo, source, opts)
3448 finally:
3445 finally:
3449 del repo._subtoppath
3446 del repo._subtoppath
3450
3447
3451
3448
3452 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3449 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3453 def init(ui, dest=".", **opts):
3450 def init(ui, dest=".", **opts):
3454 """create a new repository in the given directory
3451 """create a new repository in the given directory
3455
3452
3456 Initialize a new repository in the given directory. If the given
3453 Initialize a new repository in the given directory. If the given
3457 directory does not exist, it will be created.
3454 directory does not exist, it will be created.
3458
3455
3459 If no directory is given, the current directory is used.
3456 If no directory is given, the current directory is used.
3460
3457
3461 It is possible to specify an ``ssh://`` URL as the destination.
3458 It is possible to specify an ``ssh://`` URL as the destination.
3462 See :hg:`help urls` for more information.
3459 See :hg:`help urls` for more information.
3463
3460
3464 Returns 0 on success.
3461 Returns 0 on success.
3465 """
3462 """
3466 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3463 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3467
3464
3468 @command('locate',
3465 @command('locate',
3469 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3466 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3470 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3467 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3471 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3468 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3472 ] + walkopts,
3469 ] + walkopts,
3473 _('[OPTION]... [PATTERN]...'))
3470 _('[OPTION]... [PATTERN]...'))
3474 def locate(ui, repo, *pats, **opts):
3471 def locate(ui, repo, *pats, **opts):
3475 """locate files matching specific patterns
3472 """locate files matching specific patterns
3476
3473
3477 Print files under Mercurial control in the working directory whose
3474 Print files under Mercurial control in the working directory whose
3478 names match the given patterns.
3475 names match the given patterns.
3479
3476
3480 By default, this command searches all directories in the working
3477 By default, this command searches all directories in the working
3481 directory. To search just the current directory and its
3478 directory. To search just the current directory and its
3482 subdirectories, use "--include .".
3479 subdirectories, use "--include .".
3483
3480
3484 If no patterns are given to match, this command prints the names
3481 If no patterns are given to match, this command prints the names
3485 of all files under Mercurial control in the working directory.
3482 of all files under Mercurial control in the working directory.
3486
3483
3487 If you want to feed the output of this command into the "xargs"
3484 If you want to feed the output of this command into the "xargs"
3488 command, use the -0 option to both this command and "xargs". This
3485 command, use the -0 option to both this command and "xargs". This
3489 will avoid the problem of "xargs" treating single filenames that
3486 will avoid the problem of "xargs" treating single filenames that
3490 contain whitespace as multiple filenames.
3487 contain whitespace as multiple filenames.
3491
3488
3492 Returns 0 if a match is found, 1 otherwise.
3489 Returns 0 if a match is found, 1 otherwise.
3493 """
3490 """
3494 end = opts.get('print0') and '\0' or '\n'
3491 end = opts.get('print0') and '\0' or '\n'
3495 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3492 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3496
3493
3497 ret = 1
3494 ret = 1
3498 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3495 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3499 m.bad = lambda x, y: False
3496 m.bad = lambda x, y: False
3500 for abs in repo[rev].walk(m):
3497 for abs in repo[rev].walk(m):
3501 if not rev and abs not in repo.dirstate:
3498 if not rev and abs not in repo.dirstate:
3502 continue
3499 continue
3503 if opts.get('fullpath'):
3500 if opts.get('fullpath'):
3504 ui.write(repo.wjoin(abs), end)
3501 ui.write(repo.wjoin(abs), end)
3505 else:
3502 else:
3506 ui.write(((pats and m.rel(abs)) or abs), end)
3503 ui.write(((pats and m.rel(abs)) or abs), end)
3507 ret = 0
3504 ret = 0
3508
3505
3509 return ret
3506 return ret
3510
3507
3511 @command('^log|history',
3508 @command('^log|history',
3512 [('f', 'follow', None,
3509 [('f', 'follow', None,
3513 _('follow changeset history, or file history across copies and renames')),
3510 _('follow changeset history, or file history across copies and renames')),
3514 ('', 'follow-first', None,
3511 ('', 'follow-first', None,
3515 _('only follow the first parent of merge changesets')),
3512 _('only follow the first parent of merge changesets')),
3516 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3513 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3517 ('C', 'copies', None, _('show copied files')),
3514 ('C', 'copies', None, _('show copied files')),
3518 ('k', 'keyword', [],
3515 ('k', 'keyword', [],
3519 _('do case-insensitive search for a given text'), _('TEXT')),
3516 _('do case-insensitive search for a given text'), _('TEXT')),
3520 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3517 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3521 ('', 'removed', None, _('include revisions where files were removed')),
3518 ('', 'removed', None, _('include revisions where files were removed')),
3522 ('m', 'only-merges', None, _('show only merges')),
3519 ('m', 'only-merges', None, _('show only merges')),
3523 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3520 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3524 ('', 'only-branch', [],
3521 ('', 'only-branch', [],
3525 _('show only changesets within the given named branch (DEPRECATED)'),
3522 _('show only changesets within the given named branch (DEPRECATED)'),
3526 _('BRANCH')),
3523 _('BRANCH')),
3527 ('b', 'branch', [],
3524 ('b', 'branch', [],
3528 _('show changesets within the given named branch'), _('BRANCH')),
3525 _('show changesets within the given named branch'), _('BRANCH')),
3529 ('P', 'prune', [],
3526 ('P', 'prune', [],
3530 _('do not display revision or any of its ancestors'), _('REV')),
3527 _('do not display revision or any of its ancestors'), _('REV')),
3531 ('', 'hidden', False, _('show hidden changesets')),
3528 ('', 'hidden', False, _('show hidden changesets')),
3532 ] + logopts + walkopts,
3529 ] + logopts + walkopts,
3533 _('[OPTION]... [FILE]'))
3530 _('[OPTION]... [FILE]'))
3534 def log(ui, repo, *pats, **opts):
3531 def log(ui, repo, *pats, **opts):
3535 """show revision history of entire repository or files
3532 """show revision history of entire repository or files
3536
3533
3537 Print the revision history of the specified files or the entire
3534 Print the revision history of the specified files or the entire
3538 project.
3535 project.
3539
3536
3540 If no revision range is specified, the default is ``tip:0`` unless
3537 If no revision range is specified, the default is ``tip:0`` unless
3541 --follow is set, in which case the working directory parent is
3538 --follow is set, in which case the working directory parent is
3542 used as the starting revision.
3539 used as the starting revision.
3543
3540
3544 File history is shown without following rename or copy history of
3541 File history is shown without following rename or copy history of
3545 files. Use -f/--follow with a filename to follow history across
3542 files. Use -f/--follow with a filename to follow history across
3546 renames and copies. --follow without a filename will only show
3543 renames and copies. --follow without a filename will only show
3547 ancestors or descendants of the starting revision.
3544 ancestors or descendants of the starting revision.
3548
3545
3549 By default this command prints revision number and changeset id,
3546 By default this command prints revision number and changeset id,
3550 tags, non-trivial parents, user, date and time, and a summary for
3547 tags, non-trivial parents, user, date and time, and a summary for
3551 each commit. When the -v/--verbose switch is used, the list of
3548 each commit. When the -v/--verbose switch is used, the list of
3552 changed files and full commit message are shown.
3549 changed files and full commit message are shown.
3553
3550
3554 .. note::
3551 .. note::
3555 log -p/--patch may generate unexpected diff output for merge
3552 log -p/--patch may generate unexpected diff output for merge
3556 changesets, as it will only compare the merge changeset against
3553 changesets, as it will only compare the merge changeset against
3557 its first parent. Also, only files different from BOTH parents
3554 its first parent. Also, only files different from BOTH parents
3558 will appear in files:.
3555 will appear in files:.
3559
3556
3560 .. note::
3557 .. note::
3561 for performance reasons, log FILE may omit duplicate changes
3558 for performance reasons, log FILE may omit duplicate changes
3562 made on branches and will not show deletions. To see all
3559 made on branches and will not show deletions. To see all
3563 changes including duplicates and deletions, use the --removed
3560 changes including duplicates and deletions, use the --removed
3564 switch.
3561 switch.
3565
3562
3566 .. container:: verbose
3563 .. container:: verbose
3567
3564
3568 Some examples:
3565 Some examples:
3569
3566
3570 - changesets with full descriptions and file lists::
3567 - changesets with full descriptions and file lists::
3571
3568
3572 hg log -v
3569 hg log -v
3573
3570
3574 - changesets ancestral to the working directory::
3571 - changesets ancestral to the working directory::
3575
3572
3576 hg log -f
3573 hg log -f
3577
3574
3578 - last 10 commits on the current branch::
3575 - last 10 commits on the current branch::
3579
3576
3580 hg log -l 10 -b .
3577 hg log -l 10 -b .
3581
3578
3582 - changesets showing all modifications of a file, including removals::
3579 - changesets showing all modifications of a file, including removals::
3583
3580
3584 hg log --removed file.c
3581 hg log --removed file.c
3585
3582
3586 - all changesets that touch a directory, with diffs, excluding merges::
3583 - all changesets that touch a directory, with diffs, excluding merges::
3587
3584
3588 hg log -Mp lib/
3585 hg log -Mp lib/
3589
3586
3590 - all revision numbers that match a keyword::
3587 - all revision numbers that match a keyword::
3591
3588
3592 hg log -k bug --template "{rev}\\n"
3589 hg log -k bug --template "{rev}\\n"
3593
3590
3594 - check if a given changeset is included is a tagged release::
3591 - check if a given changeset is included is a tagged release::
3595
3592
3596 hg log -r "a21ccf and ancestor(1.9)"
3593 hg log -r "a21ccf and ancestor(1.9)"
3597
3594
3598 - find all changesets by some user in a date range::
3595 - find all changesets by some user in a date range::
3599
3596
3600 hg log -k alice -d "may 2008 to jul 2008"
3597 hg log -k alice -d "may 2008 to jul 2008"
3601
3598
3602 - summary of all changesets after the last tag::
3599 - summary of all changesets after the last tag::
3603
3600
3604 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3601 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3605
3602
3606 See :hg:`help dates` for a list of formats valid for -d/--date.
3603 See :hg:`help dates` for a list of formats valid for -d/--date.
3607
3604
3608 See :hg:`help revisions` and :hg:`help revsets` for more about
3605 See :hg:`help revisions` and :hg:`help revsets` for more about
3609 specifying revisions.
3606 specifying revisions.
3610
3607
3611 Returns 0 on success.
3608 Returns 0 on success.
3612 """
3609 """
3613
3610
3614 matchfn = scmutil.match(repo[None], pats, opts)
3611 matchfn = scmutil.match(repo[None], pats, opts)
3615 limit = cmdutil.loglimit(opts)
3612 limit = cmdutil.loglimit(opts)
3616 count = 0
3613 count = 0
3617
3614
3618 endrev = None
3615 endrev = None
3619 if opts.get('copies') and opts.get('rev'):
3616 if opts.get('copies') and opts.get('rev'):
3620 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3617 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3621
3618
3622 df = False
3619 df = False
3623 if opts["date"]:
3620 if opts["date"]:
3624 df = util.matchdate(opts["date"])
3621 df = util.matchdate(opts["date"])
3625
3622
3626 branches = opts.get('branch', []) + opts.get('only_branch', [])
3623 branches = opts.get('branch', []) + opts.get('only_branch', [])
3627 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3624 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3628
3625
3629 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3626 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3630 def prep(ctx, fns):
3627 def prep(ctx, fns):
3631 rev = ctx.rev()
3628 rev = ctx.rev()
3632 parents = [p for p in repo.changelog.parentrevs(rev)
3629 parents = [p for p in repo.changelog.parentrevs(rev)
3633 if p != nullrev]
3630 if p != nullrev]
3634 if opts.get('no_merges') and len(parents) == 2:
3631 if opts.get('no_merges') and len(parents) == 2:
3635 return
3632 return
3636 if opts.get('only_merges') and len(parents) != 2:
3633 if opts.get('only_merges') and len(parents) != 2:
3637 return
3634 return
3638 if opts.get('branch') and ctx.branch() not in opts['branch']:
3635 if opts.get('branch') and ctx.branch() not in opts['branch']:
3639 return
3636 return
3640 if not opts.get('hidden') and ctx.hidden():
3637 if not opts.get('hidden') and ctx.hidden():
3641 return
3638 return
3642 if df and not df(ctx.date()[0]):
3639 if df and not df(ctx.date()[0]):
3643 return
3640 return
3644 if opts['user'] and not [k for k in opts['user']
3641 if opts['user'] and not [k for k in opts['user']
3645 if k.lower() in ctx.user().lower()]:
3642 if k.lower() in ctx.user().lower()]:
3646 return
3643 return
3647 if opts.get('keyword'):
3644 if opts.get('keyword'):
3648 for k in [kw.lower() for kw in opts['keyword']]:
3645 for k in [kw.lower() for kw in opts['keyword']]:
3649 if (k in ctx.user().lower() or
3646 if (k in ctx.user().lower() or
3650 k in ctx.description().lower() or
3647 k in ctx.description().lower() or
3651 k in " ".join(ctx.files()).lower()):
3648 k in " ".join(ctx.files()).lower()):
3652 break
3649 break
3653 else:
3650 else:
3654 return
3651 return
3655
3652
3656 copies = None
3653 copies = None
3657 if opts.get('copies') and rev:
3654 if opts.get('copies') and rev:
3658 copies = []
3655 copies = []
3659 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3656 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3660 for fn in ctx.files():
3657 for fn in ctx.files():
3661 rename = getrenamed(fn, rev)
3658 rename = getrenamed(fn, rev)
3662 if rename:
3659 if rename:
3663 copies.append((fn, rename[0]))
3660 copies.append((fn, rename[0]))
3664
3661
3665 revmatchfn = None
3662 revmatchfn = None
3666 if opts.get('patch') or opts.get('stat'):
3663 if opts.get('patch') or opts.get('stat'):
3667 if opts.get('follow') or opts.get('follow_first'):
3664 if opts.get('follow') or opts.get('follow_first'):
3668 # note: this might be wrong when following through merges
3665 # note: this might be wrong when following through merges
3669 revmatchfn = scmutil.match(repo[None], fns, default='path')
3666 revmatchfn = scmutil.match(repo[None], fns, default='path')
3670 else:
3667 else:
3671 revmatchfn = matchfn
3668 revmatchfn = matchfn
3672
3669
3673 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3670 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3674
3671
3675 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3672 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3676 if count == limit:
3673 if count == limit:
3677 break
3674 break
3678 if displayer.flush(ctx.rev()):
3675 if displayer.flush(ctx.rev()):
3679 count += 1
3676 count += 1
3680 displayer.close()
3677 displayer.close()
3681
3678
3682 @command('manifest',
3679 @command('manifest',
3683 [('r', 'rev', '', _('revision to display'), _('REV')),
3680 [('r', 'rev', '', _('revision to display'), _('REV')),
3684 ('', 'all', False, _("list files from all revisions"))],
3681 ('', 'all', False, _("list files from all revisions"))],
3685 _('[-r REV]'))
3682 _('[-r REV]'))
3686 def manifest(ui, repo, node=None, rev=None, **opts):
3683 def manifest(ui, repo, node=None, rev=None, **opts):
3687 """output the current or given revision of the project manifest
3684 """output the current or given revision of the project manifest
3688
3685
3689 Print a list of version controlled files for the given revision.
3686 Print a list of version controlled files for the given revision.
3690 If no revision is given, the first parent of the working directory
3687 If no revision is given, the first parent of the working directory
3691 is used, or the null revision if no revision is checked out.
3688 is used, or the null revision if no revision is checked out.
3692
3689
3693 With -v, print file permissions, symlink and executable bits.
3690 With -v, print file permissions, symlink and executable bits.
3694 With --debug, print file revision hashes.
3691 With --debug, print file revision hashes.
3695
3692
3696 If option --all is specified, the list of all files from all revisions
3693 If option --all is specified, the list of all files from all revisions
3697 is printed. This includes deleted and renamed files.
3694 is printed. This includes deleted and renamed files.
3698
3695
3699 Returns 0 on success.
3696 Returns 0 on success.
3700 """
3697 """
3701 if opts.get('all'):
3698 if opts.get('all'):
3702 if rev or node:
3699 if rev or node:
3703 raise util.Abort(_("can't specify a revision with --all"))
3700 raise util.Abort(_("can't specify a revision with --all"))
3704
3701
3705 res = []
3702 res = []
3706 prefix = "data/"
3703 prefix = "data/"
3707 suffix = ".i"
3704 suffix = ".i"
3708 plen = len(prefix)
3705 plen = len(prefix)
3709 slen = len(suffix)
3706 slen = len(suffix)
3710 lock = repo.lock()
3707 lock = repo.lock()
3711 try:
3708 try:
3712 for fn, b, size in repo.store.datafiles():
3709 for fn, b, size in repo.store.datafiles():
3713 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3710 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3714 res.append(fn[plen:-slen])
3711 res.append(fn[plen:-slen])
3715 finally:
3712 finally:
3716 lock.release()
3713 lock.release()
3717 for f in sorted(res):
3714 for f in sorted(res):
3718 ui.write("%s\n" % f)
3715 ui.write("%s\n" % f)
3719 return
3716 return
3720
3717
3721 if rev and node:
3718 if rev and node:
3722 raise util.Abort(_("please specify just one revision"))
3719 raise util.Abort(_("please specify just one revision"))
3723
3720
3724 if not node:
3721 if not node:
3725 node = rev
3722 node = rev
3726
3723
3727 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3724 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3728 ctx = scmutil.revsingle(repo, node)
3725 ctx = scmutil.revsingle(repo, node)
3729 for f in ctx:
3726 for f in ctx:
3730 if ui.debugflag:
3727 if ui.debugflag:
3731 ui.write("%40s " % hex(ctx.manifest()[f]))
3728 ui.write("%40s " % hex(ctx.manifest()[f]))
3732 if ui.verbose:
3729 if ui.verbose:
3733 ui.write(decor[ctx.flags(f)])
3730 ui.write(decor[ctx.flags(f)])
3734 ui.write("%s\n" % f)
3731 ui.write("%s\n" % f)
3735
3732
3736 @command('^merge',
3733 @command('^merge',
3737 [('f', 'force', None, _('force a merge with outstanding changes')),
3734 [('f', 'force', None, _('force a merge with outstanding changes')),
3738 ('r', 'rev', '', _('revision to merge'), _('REV')),
3735 ('r', 'rev', '', _('revision to merge'), _('REV')),
3739 ('P', 'preview', None,
3736 ('P', 'preview', None,
3740 _('review revisions to merge (no merge is performed)'))
3737 _('review revisions to merge (no merge is performed)'))
3741 ] + mergetoolopts,
3738 ] + mergetoolopts,
3742 _('[-P] [-f] [[-r] REV]'))
3739 _('[-P] [-f] [[-r] REV]'))
3743 def merge(ui, repo, node=None, **opts):
3740 def merge(ui, repo, node=None, **opts):
3744 """merge working directory with another revision
3741 """merge working directory with another revision
3745
3742
3746 The current working directory is updated with all changes made in
3743 The current working directory is updated with all changes made in
3747 the requested revision since the last common predecessor revision.
3744 the requested revision since the last common predecessor revision.
3748
3745
3749 Files that changed between either parent are marked as changed for
3746 Files that changed between either parent are marked as changed for
3750 the next commit and a commit must be performed before any further
3747 the next commit and a commit must be performed before any further
3751 updates to the repository are allowed. The next commit will have
3748 updates to the repository are allowed. The next commit will have
3752 two parents.
3749 two parents.
3753
3750
3754 ``--tool`` can be used to specify the merge tool used for file
3751 ``--tool`` can be used to specify the merge tool used for file
3755 merges. It overrides the HGMERGE environment variable and your
3752 merges. It overrides the HGMERGE environment variable and your
3756 configuration files. See :hg:`help merge-tools` for options.
3753 configuration files. See :hg:`help merge-tools` for options.
3757
3754
3758 If no revision is specified, the working directory's parent is a
3755 If no revision is specified, the working directory's parent is a
3759 head revision, and the current branch contains exactly one other
3756 head revision, and the current branch contains exactly one other
3760 head, the other head is merged with by default. Otherwise, an
3757 head, the other head is merged with by default. Otherwise, an
3761 explicit revision with which to merge with must be provided.
3758 explicit revision with which to merge with must be provided.
3762
3759
3763 :hg:`resolve` must be used to resolve unresolved files.
3760 :hg:`resolve` must be used to resolve unresolved files.
3764
3761
3765 To undo an uncommitted merge, use :hg:`update --clean .` which
3762 To undo an uncommitted merge, use :hg:`update --clean .` which
3766 will check out a clean copy of the original merge parent, losing
3763 will check out a clean copy of the original merge parent, losing
3767 all changes.
3764 all changes.
3768
3765
3769 Returns 0 on success, 1 if there are unresolved files.
3766 Returns 0 on success, 1 if there are unresolved files.
3770 """
3767 """
3771
3768
3772 if opts.get('rev') and node:
3769 if opts.get('rev') and node:
3773 raise util.Abort(_("please specify just one revision"))
3770 raise util.Abort(_("please specify just one revision"))
3774 if not node:
3771 if not node:
3775 node = opts.get('rev')
3772 node = opts.get('rev')
3776
3773
3777 if not node:
3774 if not node:
3778 branch = repo[None].branch()
3775 branch = repo[None].branch()
3779 bheads = repo.branchheads(branch)
3776 bheads = repo.branchheads(branch)
3780 if len(bheads) > 2:
3777 if len(bheads) > 2:
3781 raise util.Abort(_("branch '%s' has %d heads - "
3778 raise util.Abort(_("branch '%s' has %d heads - "
3782 "please merge with an explicit rev")
3779 "please merge with an explicit rev")
3783 % (branch, len(bheads)),
3780 % (branch, len(bheads)),
3784 hint=_("run 'hg heads .' to see heads"))
3781 hint=_("run 'hg heads .' to see heads"))
3785
3782
3786 parent = repo.dirstate.p1()
3783 parent = repo.dirstate.p1()
3787 if len(bheads) == 1:
3784 if len(bheads) == 1:
3788 if len(repo.heads()) > 1:
3785 if len(repo.heads()) > 1:
3789 raise util.Abort(_("branch '%s' has one head - "
3786 raise util.Abort(_("branch '%s' has one head - "
3790 "please merge with an explicit rev")
3787 "please merge with an explicit rev")
3791 % branch,
3788 % branch,
3792 hint=_("run 'hg heads' to see all heads"))
3789 hint=_("run 'hg heads' to see all heads"))
3793 msg = _('there is nothing to merge')
3790 msg = _('there is nothing to merge')
3794 if parent != repo.lookup(repo[None].branch()):
3791 if parent != repo.lookup(repo[None].branch()):
3795 msg = _('%s - use "hg update" instead') % msg
3792 msg = _('%s - use "hg update" instead') % msg
3796 raise util.Abort(msg)
3793 raise util.Abort(msg)
3797
3794
3798 if parent not in bheads:
3795 if parent not in bheads:
3799 raise util.Abort(_('working directory not at a head revision'),
3796 raise util.Abort(_('working directory not at a head revision'),
3800 hint=_("use 'hg update' or merge with an "
3797 hint=_("use 'hg update' or merge with an "
3801 "explicit revision"))
3798 "explicit revision"))
3802 node = parent == bheads[0] and bheads[-1] or bheads[0]
3799 node = parent == bheads[0] and bheads[-1] or bheads[0]
3803 else:
3800 else:
3804 node = scmutil.revsingle(repo, node).node()
3801 node = scmutil.revsingle(repo, node).node()
3805
3802
3806 if opts.get('preview'):
3803 if opts.get('preview'):
3807 # find nodes that are ancestors of p2 but not of p1
3804 # find nodes that are ancestors of p2 but not of p1
3808 p1 = repo.lookup('.')
3805 p1 = repo.lookup('.')
3809 p2 = repo.lookup(node)
3806 p2 = repo.lookup(node)
3810 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3807 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3811
3808
3812 displayer = cmdutil.show_changeset(ui, repo, opts)
3809 displayer = cmdutil.show_changeset(ui, repo, opts)
3813 for node in nodes:
3810 for node in nodes:
3814 displayer.show(repo[node])
3811 displayer.show(repo[node])
3815 displayer.close()
3812 displayer.close()
3816 return 0
3813 return 0
3817
3814
3818 try:
3815 try:
3819 # ui.forcemerge is an internal variable, do not document
3816 # ui.forcemerge is an internal variable, do not document
3820 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3817 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3821 return hg.merge(repo, node, force=opts.get('force'))
3818 return hg.merge(repo, node, force=opts.get('force'))
3822 finally:
3819 finally:
3823 ui.setconfig('ui', 'forcemerge', '')
3820 ui.setconfig('ui', 'forcemerge', '')
3824
3821
3825 @command('outgoing|out',
3822 @command('outgoing|out',
3826 [('f', 'force', None, _('run even when the destination is unrelated')),
3823 [('f', 'force', None, _('run even when the destination is unrelated')),
3827 ('r', 'rev', [],
3824 ('r', 'rev', [],
3828 _('a changeset intended to be included in the destination'), _('REV')),
3825 _('a changeset intended to be included in the destination'), _('REV')),
3829 ('n', 'newest-first', None, _('show newest record first')),
3826 ('n', 'newest-first', None, _('show newest record first')),
3830 ('B', 'bookmarks', False, _('compare bookmarks')),
3827 ('B', 'bookmarks', False, _('compare bookmarks')),
3831 ('b', 'branch', [], _('a specific branch you would like to push'),
3828 ('b', 'branch', [], _('a specific branch you would like to push'),
3832 _('BRANCH')),
3829 _('BRANCH')),
3833 ] + logopts + remoteopts + subrepoopts,
3830 ] + logopts + remoteopts + subrepoopts,
3834 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3831 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3835 def outgoing(ui, repo, dest=None, **opts):
3832 def outgoing(ui, repo, dest=None, **opts):
3836 """show changesets not found in the destination
3833 """show changesets not found in the destination
3837
3834
3838 Show changesets not found in the specified destination repository
3835 Show changesets not found in the specified destination repository
3839 or the default push location. These are the changesets that would
3836 or the default push location. These are the changesets that would
3840 be pushed if a push was requested.
3837 be pushed if a push was requested.
3841
3838
3842 See pull for details of valid destination formats.
3839 See pull for details of valid destination formats.
3843
3840
3844 Returns 0 if there are outgoing changes, 1 otherwise.
3841 Returns 0 if there are outgoing changes, 1 otherwise.
3845 """
3842 """
3846
3843
3847 if opts.get('bookmarks'):
3844 if opts.get('bookmarks'):
3848 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3845 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3849 dest, branches = hg.parseurl(dest, opts.get('branch'))
3846 dest, branches = hg.parseurl(dest, opts.get('branch'))
3850 other = hg.peer(repo, opts, dest)
3847 other = hg.peer(repo, opts, dest)
3851 if 'bookmarks' not in other.listkeys('namespaces'):
3848 if 'bookmarks' not in other.listkeys('namespaces'):
3852 ui.warn(_("remote doesn't support bookmarks\n"))
3849 ui.warn(_("remote doesn't support bookmarks\n"))
3853 return 0
3850 return 0
3854 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3851 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3855 return bookmarks.diff(ui, other, repo)
3852 return bookmarks.diff(ui, other, repo)
3856
3853
3857 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3854 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3858 try:
3855 try:
3859 return hg.outgoing(ui, repo, dest, opts)
3856 return hg.outgoing(ui, repo, dest, opts)
3860 finally:
3857 finally:
3861 del repo._subtoppath
3858 del repo._subtoppath
3862
3859
3863 @command('parents',
3860 @command('parents',
3864 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3861 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3865 ] + templateopts,
3862 ] + templateopts,
3866 _('[-r REV] [FILE]'))
3863 _('[-r REV] [FILE]'))
3867 def parents(ui, repo, file_=None, **opts):
3864 def parents(ui, repo, file_=None, **opts):
3868 """show the parents of the working directory or revision
3865 """show the parents of the working directory or revision
3869
3866
3870 Print the working directory's parent revisions. If a revision is
3867 Print the working directory's parent revisions. If a revision is
3871 given via -r/--rev, the parent of that revision will be printed.
3868 given via -r/--rev, the parent of that revision will be printed.
3872 If a file argument is given, the revision in which the file was
3869 If a file argument is given, the revision in which the file was
3873 last changed (before the working directory revision or the
3870 last changed (before the working directory revision or the
3874 argument to --rev if given) is printed.
3871 argument to --rev if given) is printed.
3875
3872
3876 Returns 0 on success.
3873 Returns 0 on success.
3877 """
3874 """
3878
3875
3879 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3876 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3880
3877
3881 if file_:
3878 if file_:
3882 m = scmutil.match(ctx, (file_,), opts)
3879 m = scmutil.match(ctx, (file_,), opts)
3883 if m.anypats() or len(m.files()) != 1:
3880 if m.anypats() or len(m.files()) != 1:
3884 raise util.Abort(_('can only specify an explicit filename'))
3881 raise util.Abort(_('can only specify an explicit filename'))
3885 file_ = m.files()[0]
3882 file_ = m.files()[0]
3886 filenodes = []
3883 filenodes = []
3887 for cp in ctx.parents():
3884 for cp in ctx.parents():
3888 if not cp:
3885 if not cp:
3889 continue
3886 continue
3890 try:
3887 try:
3891 filenodes.append(cp.filenode(file_))
3888 filenodes.append(cp.filenode(file_))
3892 except error.LookupError:
3889 except error.LookupError:
3893 pass
3890 pass
3894 if not filenodes:
3891 if not filenodes:
3895 raise util.Abort(_("'%s' not found in manifest!") % file_)
3892 raise util.Abort(_("'%s' not found in manifest!") % file_)
3896 fl = repo.file(file_)
3893 fl = repo.file(file_)
3897 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3894 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3898 else:
3895 else:
3899 p = [cp.node() for cp in ctx.parents()]
3896 p = [cp.node() for cp in ctx.parents()]
3900
3897
3901 displayer = cmdutil.show_changeset(ui, repo, opts)
3898 displayer = cmdutil.show_changeset(ui, repo, opts)
3902 for n in p:
3899 for n in p:
3903 if n != nullid:
3900 if n != nullid:
3904 displayer.show(repo[n])
3901 displayer.show(repo[n])
3905 displayer.close()
3902 displayer.close()
3906
3903
3907 @command('paths', [], _('[NAME]'))
3904 @command('paths', [], _('[NAME]'))
3908 def paths(ui, repo, search=None):
3905 def paths(ui, repo, search=None):
3909 """show aliases for remote repositories
3906 """show aliases for remote repositories
3910
3907
3911 Show definition of symbolic path name NAME. If no name is given,
3908 Show definition of symbolic path name NAME. If no name is given,
3912 show definition of all available names.
3909 show definition of all available names.
3913
3910
3914 Option -q/--quiet suppresses all output when searching for NAME
3911 Option -q/--quiet suppresses all output when searching for NAME
3915 and shows only the path names when listing all definitions.
3912 and shows only the path names when listing all definitions.
3916
3913
3917 Path names are defined in the [paths] section of your
3914 Path names are defined in the [paths] section of your
3918 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3915 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3919 repository, ``.hg/hgrc`` is used, too.
3916 repository, ``.hg/hgrc`` is used, too.
3920
3917
3921 The path names ``default`` and ``default-push`` have a special
3918 The path names ``default`` and ``default-push`` have a special
3922 meaning. When performing a push or pull operation, they are used
3919 meaning. When performing a push or pull operation, they are used
3923 as fallbacks if no location is specified on the command-line.
3920 as fallbacks if no location is specified on the command-line.
3924 When ``default-push`` is set, it will be used for push and
3921 When ``default-push`` is set, it will be used for push and
3925 ``default`` will be used for pull; otherwise ``default`` is used
3922 ``default`` will be used for pull; otherwise ``default`` is used
3926 as the fallback for both. When cloning a repository, the clone
3923 as the fallback for both. When cloning a repository, the clone
3927 source is written as ``default`` in ``.hg/hgrc``. Note that
3924 source is written as ``default`` in ``.hg/hgrc``. Note that
3928 ``default`` and ``default-push`` apply to all inbound (e.g.
3925 ``default`` and ``default-push`` apply to all inbound (e.g.
3929 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3926 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3930 :hg:`bundle`) operations.
3927 :hg:`bundle`) operations.
3931
3928
3932 See :hg:`help urls` for more information.
3929 See :hg:`help urls` for more information.
3933
3930
3934 Returns 0 on success.
3931 Returns 0 on success.
3935 """
3932 """
3936 if search:
3933 if search:
3937 for name, path in ui.configitems("paths"):
3934 for name, path in ui.configitems("paths"):
3938 if name == search:
3935 if name == search:
3939 ui.status("%s\n" % util.hidepassword(path))
3936 ui.status("%s\n" % util.hidepassword(path))
3940 return
3937 return
3941 if not ui.quiet:
3938 if not ui.quiet:
3942 ui.warn(_("not found!\n"))
3939 ui.warn(_("not found!\n"))
3943 return 1
3940 return 1
3944 else:
3941 else:
3945 for name, path in ui.configitems("paths"):
3942 for name, path in ui.configitems("paths"):
3946 if ui.quiet:
3943 if ui.quiet:
3947 ui.write("%s\n" % name)
3944 ui.write("%s\n" % name)
3948 else:
3945 else:
3949 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3946 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3950
3947
3951 def postincoming(ui, repo, modheads, optupdate, checkout):
3948 def postincoming(ui, repo, modheads, optupdate, checkout):
3952 if modheads == 0:
3949 if modheads == 0:
3953 return
3950 return
3954 if optupdate:
3951 if optupdate:
3955 try:
3952 try:
3956 return hg.update(repo, checkout)
3953 return hg.update(repo, checkout)
3957 except util.Abort, inst:
3954 except util.Abort, inst:
3958 ui.warn(_("not updating: %s\n" % str(inst)))
3955 ui.warn(_("not updating: %s\n" % str(inst)))
3959 return 0
3956 return 0
3960 if modheads > 1:
3957 if modheads > 1:
3961 currentbranchheads = len(repo.branchheads())
3958 currentbranchheads = len(repo.branchheads())
3962 if currentbranchheads == modheads:
3959 if currentbranchheads == modheads:
3963 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3960 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3964 elif currentbranchheads > 1:
3961 elif currentbranchheads > 1:
3965 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3962 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3966 else:
3963 else:
3967 ui.status(_("(run 'hg heads' to see heads)\n"))
3964 ui.status(_("(run 'hg heads' to see heads)\n"))
3968 else:
3965 else:
3969 ui.status(_("(run 'hg update' to get a working copy)\n"))
3966 ui.status(_("(run 'hg update' to get a working copy)\n"))
3970
3967
3971 @command('^pull',
3968 @command('^pull',
3972 [('u', 'update', None,
3969 [('u', 'update', None,
3973 _('update to new branch head if changesets were pulled')),
3970 _('update to new branch head if changesets were pulled')),
3974 ('f', 'force', None, _('run even when remote repository is unrelated')),
3971 ('f', 'force', None, _('run even when remote repository is unrelated')),
3975 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3972 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3976 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3973 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3977 ('b', 'branch', [], _('a specific branch you would like to pull'),
3974 ('b', 'branch', [], _('a specific branch you would like to pull'),
3978 _('BRANCH')),
3975 _('BRANCH')),
3979 ] + remoteopts,
3976 ] + remoteopts,
3980 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3977 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3981 def pull(ui, repo, source="default", **opts):
3978 def pull(ui, repo, source="default", **opts):
3982 """pull changes from the specified source
3979 """pull changes from the specified source
3983
3980
3984 Pull changes from a remote repository to a local one.
3981 Pull changes from a remote repository to a local one.
3985
3982
3986 This finds all changes from the repository at the specified path
3983 This finds all changes from the repository at the specified path
3987 or URL and adds them to a local repository (the current one unless
3984 or URL and adds them to a local repository (the current one unless
3988 -R is specified). By default, this does not update the copy of the
3985 -R is specified). By default, this does not update the copy of the
3989 project in the working directory.
3986 project in the working directory.
3990
3987
3991 Use :hg:`incoming` if you want to see what would have been added
3988 Use :hg:`incoming` if you want to see what would have been added
3992 by a pull at the time you issued this command. If you then decide
3989 by a pull at the time you issued this command. If you then decide
3993 to add those changes to the repository, you should use :hg:`pull
3990 to add those changes to the repository, you should use :hg:`pull
3994 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3991 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3995
3992
3996 If SOURCE is omitted, the 'default' path will be used.
3993 If SOURCE is omitted, the 'default' path will be used.
3997 See :hg:`help urls` for more information.
3994 See :hg:`help urls` for more information.
3998
3995
3999 Returns 0 on success, 1 if an update had unresolved files.
3996 Returns 0 on success, 1 if an update had unresolved files.
4000 """
3997 """
4001 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3998 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4002 other = hg.peer(repo, opts, source)
3999 other = hg.peer(repo, opts, source)
4003 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4000 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4004 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4001 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4005
4002
4006 if opts.get('bookmark'):
4003 if opts.get('bookmark'):
4007 if not revs:
4004 if not revs:
4008 revs = []
4005 revs = []
4009 rb = other.listkeys('bookmarks')
4006 rb = other.listkeys('bookmarks')
4010 for b in opts['bookmark']:
4007 for b in opts['bookmark']:
4011 if b not in rb:
4008 if b not in rb:
4012 raise util.Abort(_('remote bookmark %s not found!') % b)
4009 raise util.Abort(_('remote bookmark %s not found!') % b)
4013 revs.append(rb[b])
4010 revs.append(rb[b])
4014
4011
4015 if revs:
4012 if revs:
4016 try:
4013 try:
4017 revs = [other.lookup(rev) for rev in revs]
4014 revs = [other.lookup(rev) for rev in revs]
4018 except error.CapabilityError:
4015 except error.CapabilityError:
4019 err = _("other repository doesn't support revision lookup, "
4016 err = _("other repository doesn't support revision lookup, "
4020 "so a rev cannot be specified.")
4017 "so a rev cannot be specified.")
4021 raise util.Abort(err)
4018 raise util.Abort(err)
4022
4019
4023 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4020 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4024 bookmarks.updatefromremote(ui, repo, other)
4021 bookmarks.updatefromremote(ui, repo, other)
4025 if checkout:
4022 if checkout:
4026 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4023 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4027 repo._subtoppath = source
4024 repo._subtoppath = source
4028 try:
4025 try:
4029 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4026 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4030
4027
4031 finally:
4028 finally:
4032 del repo._subtoppath
4029 del repo._subtoppath
4033
4030
4034 # update specified bookmarks
4031 # update specified bookmarks
4035 if opts.get('bookmark'):
4032 if opts.get('bookmark'):
4036 for b in opts['bookmark']:
4033 for b in opts['bookmark']:
4037 # explicit pull overrides local bookmark if any
4034 # explicit pull overrides local bookmark if any
4038 ui.status(_("importing bookmark %s\n") % b)
4035 ui.status(_("importing bookmark %s\n") % b)
4039 repo._bookmarks[b] = repo[rb[b]].node()
4036 repo._bookmarks[b] = repo[rb[b]].node()
4040 bookmarks.write(repo)
4037 bookmarks.write(repo)
4041
4038
4042 return ret
4039 return ret
4043
4040
4044 @command('^push',
4041 @command('^push',
4045 [('f', 'force', None, _('force push')),
4042 [('f', 'force', None, _('force push')),
4046 ('r', 'rev', [],
4043 ('r', 'rev', [],
4047 _('a changeset intended to be included in the destination'),
4044 _('a changeset intended to be included in the destination'),
4048 _('REV')),
4045 _('REV')),
4049 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4046 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4050 ('b', 'branch', [],
4047 ('b', 'branch', [],
4051 _('a specific branch you would like to push'), _('BRANCH')),
4048 _('a specific branch you would like to push'), _('BRANCH')),
4052 ('', 'new-branch', False, _('allow pushing a new branch')),
4049 ('', 'new-branch', False, _('allow pushing a new branch')),
4053 ] + remoteopts,
4050 ] + remoteopts,
4054 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4051 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4055 def push(ui, repo, dest=None, **opts):
4052 def push(ui, repo, dest=None, **opts):
4056 """push changes to the specified destination
4053 """push changes to the specified destination
4057
4054
4058 Push changesets from the local repository to the specified
4055 Push changesets from the local repository to the specified
4059 destination.
4056 destination.
4060
4057
4061 This operation is symmetrical to pull: it is identical to a pull
4058 This operation is symmetrical to pull: it is identical to a pull
4062 in the destination repository from the current one.
4059 in the destination repository from the current one.
4063
4060
4064 By default, push will not allow creation of new heads at the
4061 By default, push will not allow creation of new heads at the
4065 destination, since multiple heads would make it unclear which head
4062 destination, since multiple heads would make it unclear which head
4066 to use. In this situation, it is recommended to pull and merge
4063 to use. In this situation, it is recommended to pull and merge
4067 before pushing.
4064 before pushing.
4068
4065
4069 Use --new-branch if you want to allow push to create a new named
4066 Use --new-branch if you want to allow push to create a new named
4070 branch that is not present at the destination. This allows you to
4067 branch that is not present at the destination. This allows you to
4071 only create a new branch without forcing other changes.
4068 only create a new branch without forcing other changes.
4072
4069
4073 Use -f/--force to override the default behavior and push all
4070 Use -f/--force to override the default behavior and push all
4074 changesets on all branches.
4071 changesets on all branches.
4075
4072
4076 If -r/--rev is used, the specified revision and all its ancestors
4073 If -r/--rev is used, the specified revision and all its ancestors
4077 will be pushed to the remote repository.
4074 will be pushed to the remote repository.
4078
4075
4079 Please see :hg:`help urls` for important details about ``ssh://``
4076 Please see :hg:`help urls` for important details about ``ssh://``
4080 URLs. If DESTINATION is omitted, a default path will be used.
4077 URLs. If DESTINATION is omitted, a default path will be used.
4081
4078
4082 Returns 0 if push was successful, 1 if nothing to push.
4079 Returns 0 if push was successful, 1 if nothing to push.
4083 """
4080 """
4084
4081
4085 if opts.get('bookmark'):
4082 if opts.get('bookmark'):
4086 for b in opts['bookmark']:
4083 for b in opts['bookmark']:
4087 # translate -B options to -r so changesets get pushed
4084 # translate -B options to -r so changesets get pushed
4088 if b in repo._bookmarks:
4085 if b in repo._bookmarks:
4089 opts.setdefault('rev', []).append(b)
4086 opts.setdefault('rev', []).append(b)
4090 else:
4087 else:
4091 # if we try to push a deleted bookmark, translate it to null
4088 # if we try to push a deleted bookmark, translate it to null
4092 # this lets simultaneous -r, -b options continue working
4089 # this lets simultaneous -r, -b options continue working
4093 opts.setdefault('rev', []).append("null")
4090 opts.setdefault('rev', []).append("null")
4094
4091
4095 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4092 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4096 dest, branches = hg.parseurl(dest, opts.get('branch'))
4093 dest, branches = hg.parseurl(dest, opts.get('branch'))
4097 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4094 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4098 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4095 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4099 other = hg.peer(repo, opts, dest)
4096 other = hg.peer(repo, opts, dest)
4100 if revs:
4097 if revs:
4101 revs = [repo.lookup(rev) for rev in revs]
4098 revs = [repo.lookup(rev) for rev in revs]
4102
4099
4103 repo._subtoppath = dest
4100 repo._subtoppath = dest
4104 try:
4101 try:
4105 # push subrepos depth-first for coherent ordering
4102 # push subrepos depth-first for coherent ordering
4106 c = repo['']
4103 c = repo['']
4107 subs = c.substate # only repos that are committed
4104 subs = c.substate # only repos that are committed
4108 for s in sorted(subs):
4105 for s in sorted(subs):
4109 if not c.sub(s).push(opts.get('force')):
4106 if not c.sub(s).push(opts.get('force')):
4110 return False
4107 return False
4111 finally:
4108 finally:
4112 del repo._subtoppath
4109 del repo._subtoppath
4113 result = repo.push(other, opts.get('force'), revs=revs,
4110 result = repo.push(other, opts.get('force'), revs=revs,
4114 newbranch=opts.get('new_branch'))
4111 newbranch=opts.get('new_branch'))
4115
4112
4116 result = (result == 0)
4113 result = (result == 0)
4117
4114
4118 if opts.get('bookmark'):
4115 if opts.get('bookmark'):
4119 rb = other.listkeys('bookmarks')
4116 rb = other.listkeys('bookmarks')
4120 for b in opts['bookmark']:
4117 for b in opts['bookmark']:
4121 # explicit push overrides remote bookmark if any
4118 # explicit push overrides remote bookmark if any
4122 if b in repo._bookmarks:
4119 if b in repo._bookmarks:
4123 ui.status(_("exporting bookmark %s\n") % b)
4120 ui.status(_("exporting bookmark %s\n") % b)
4124 new = repo[b].hex()
4121 new = repo[b].hex()
4125 elif b in rb:
4122 elif b in rb:
4126 ui.status(_("deleting remote bookmark %s\n") % b)
4123 ui.status(_("deleting remote bookmark %s\n") % b)
4127 new = '' # delete
4124 new = '' # delete
4128 else:
4125 else:
4129 ui.warn(_('bookmark %s does not exist on the local '
4126 ui.warn(_('bookmark %s does not exist on the local '
4130 'or remote repository!\n') % b)
4127 'or remote repository!\n') % b)
4131 return 2
4128 return 2
4132 old = rb.get(b, '')
4129 old = rb.get(b, '')
4133 r = other.pushkey('bookmarks', b, old, new)
4130 r = other.pushkey('bookmarks', b, old, new)
4134 if not r:
4131 if not r:
4135 ui.warn(_('updating bookmark %s failed!\n') % b)
4132 ui.warn(_('updating bookmark %s failed!\n') % b)
4136 if not result:
4133 if not result:
4137 result = 2
4134 result = 2
4138
4135
4139 return result
4136 return result
4140
4137
4141 @command('recover', [])
4138 @command('recover', [])
4142 def recover(ui, repo):
4139 def recover(ui, repo):
4143 """roll back an interrupted transaction
4140 """roll back an interrupted transaction
4144
4141
4145 Recover from an interrupted commit or pull.
4142 Recover from an interrupted commit or pull.
4146
4143
4147 This command tries to fix the repository status after an
4144 This command tries to fix the repository status after an
4148 interrupted operation. It should only be necessary when Mercurial
4145 interrupted operation. It should only be necessary when Mercurial
4149 suggests it.
4146 suggests it.
4150
4147
4151 Returns 0 if successful, 1 if nothing to recover or verify fails.
4148 Returns 0 if successful, 1 if nothing to recover or verify fails.
4152 """
4149 """
4153 if repo.recover():
4150 if repo.recover():
4154 return hg.verify(repo)
4151 return hg.verify(repo)
4155 return 1
4152 return 1
4156
4153
4157 @command('^remove|rm',
4154 @command('^remove|rm',
4158 [('A', 'after', None, _('record delete for missing files')),
4155 [('A', 'after', None, _('record delete for missing files')),
4159 ('f', 'force', None,
4156 ('f', 'force', None,
4160 _('remove (and delete) file even if added or modified')),
4157 _('remove (and delete) file even if added or modified')),
4161 ] + walkopts,
4158 ] + walkopts,
4162 _('[OPTION]... FILE...'))
4159 _('[OPTION]... FILE...'))
4163 def remove(ui, repo, *pats, **opts):
4160 def remove(ui, repo, *pats, **opts):
4164 """remove the specified files on the next commit
4161 """remove the specified files on the next commit
4165
4162
4166 Schedule the indicated files for removal from the current branch.
4163 Schedule the indicated files for removal from the current branch.
4167
4164
4168 This command schedules the files to be removed at the next commit.
4165 This command schedules the files to be removed at the next commit.
4169 To undo a remove before that, see :hg:`revert`. To undo added
4166 To undo a remove before that, see :hg:`revert`. To undo added
4170 files, see :hg:`forget`.
4167 files, see :hg:`forget`.
4171
4168
4172 .. container:: verbose
4169 .. container:: verbose
4173
4170
4174 -A/--after can be used to remove only files that have already
4171 -A/--after can be used to remove only files that have already
4175 been deleted, -f/--force can be used to force deletion, and -Af
4172 been deleted, -f/--force can be used to force deletion, and -Af
4176 can be used to remove files from the next revision without
4173 can be used to remove files from the next revision without
4177 deleting them from the working directory.
4174 deleting them from the working directory.
4178
4175
4179 The following table details the behavior of remove for different
4176 The following table details the behavior of remove for different
4180 file states (columns) and option combinations (rows). The file
4177 file states (columns) and option combinations (rows). The file
4181 states are Added [A], Clean [C], Modified [M] and Missing [!]
4178 states are Added [A], Clean [C], Modified [M] and Missing [!]
4182 (as reported by :hg:`status`). The actions are Warn, Remove
4179 (as reported by :hg:`status`). The actions are Warn, Remove
4183 (from branch) and Delete (from disk):
4180 (from branch) and Delete (from disk):
4184
4181
4185 ======= == == == ==
4182 ======= == == == ==
4186 A C M !
4183 A C M !
4187 ======= == == == ==
4184 ======= == == == ==
4188 none W RD W R
4185 none W RD W R
4189 -f R RD RD R
4186 -f R RD RD R
4190 -A W W W R
4187 -A W W W R
4191 -Af R R R R
4188 -Af R R R R
4192 ======= == == == ==
4189 ======= == == == ==
4193
4190
4194 Note that remove never deletes files in Added [A] state from the
4191 Note that remove never deletes files in Added [A] state from the
4195 working directory, not even if option --force is specified.
4192 working directory, not even if option --force is specified.
4196
4193
4197 Returns 0 on success, 1 if any warnings encountered.
4194 Returns 0 on success, 1 if any warnings encountered.
4198 """
4195 """
4199
4196
4200 ret = 0
4197 ret = 0
4201 after, force = opts.get('after'), opts.get('force')
4198 after, force = opts.get('after'), opts.get('force')
4202 if not pats and not after:
4199 if not pats and not after:
4203 raise util.Abort(_('no files specified'))
4200 raise util.Abort(_('no files specified'))
4204
4201
4205 m = scmutil.match(repo[None], pats, opts)
4202 m = scmutil.match(repo[None], pats, opts)
4206 s = repo.status(match=m, clean=True)
4203 s = repo.status(match=m, clean=True)
4207 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4204 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4208
4205
4209 for f in m.files():
4206 for f in m.files():
4210 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4207 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4211 if os.path.exists(m.rel(f)):
4208 if os.path.exists(m.rel(f)):
4212 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4209 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4213 ret = 1
4210 ret = 1
4214
4211
4215 if force:
4212 if force:
4216 list = modified + deleted + clean + added
4213 list = modified + deleted + clean + added
4217 elif after:
4214 elif after:
4218 list = deleted
4215 list = deleted
4219 for f in modified + added + clean:
4216 for f in modified + added + clean:
4220 ui.warn(_('not removing %s: file still exists (use -f'
4217 ui.warn(_('not removing %s: file still exists (use -f'
4221 ' to force removal)\n') % m.rel(f))
4218 ' to force removal)\n') % m.rel(f))
4222 ret = 1
4219 ret = 1
4223 else:
4220 else:
4224 list = deleted + clean
4221 list = deleted + clean
4225 for f in modified:
4222 for f in modified:
4226 ui.warn(_('not removing %s: file is modified (use -f'
4223 ui.warn(_('not removing %s: file is modified (use -f'
4227 ' to force removal)\n') % m.rel(f))
4224 ' to force removal)\n') % m.rel(f))
4228 ret = 1
4225 ret = 1
4229 for f in added:
4226 for f in added:
4230 ui.warn(_('not removing %s: file has been marked for add'
4227 ui.warn(_('not removing %s: file has been marked for add'
4231 ' (use forget to undo)\n') % m.rel(f))
4228 ' (use forget to undo)\n') % m.rel(f))
4232 ret = 1
4229 ret = 1
4233
4230
4234 for f in sorted(list):
4231 for f in sorted(list):
4235 if ui.verbose or not m.exact(f):
4232 if ui.verbose or not m.exact(f):
4236 ui.status(_('removing %s\n') % m.rel(f))
4233 ui.status(_('removing %s\n') % m.rel(f))
4237
4234
4238 wlock = repo.wlock()
4235 wlock = repo.wlock()
4239 try:
4236 try:
4240 if not after:
4237 if not after:
4241 for f in list:
4238 for f in list:
4242 if f in added:
4239 if f in added:
4243 continue # we never unlink added files on remove
4240 continue # we never unlink added files on remove
4244 try:
4241 try:
4245 util.unlinkpath(repo.wjoin(f))
4242 util.unlinkpath(repo.wjoin(f))
4246 except OSError, inst:
4243 except OSError, inst:
4247 if inst.errno != errno.ENOENT:
4244 if inst.errno != errno.ENOENT:
4248 raise
4245 raise
4249 repo[None].forget(list)
4246 repo[None].forget(list)
4250 finally:
4247 finally:
4251 wlock.release()
4248 wlock.release()
4252
4249
4253 return ret
4250 return ret
4254
4251
4255 @command('rename|move|mv',
4252 @command('rename|move|mv',
4256 [('A', 'after', None, _('record a rename that has already occurred')),
4253 [('A', 'after', None, _('record a rename that has already occurred')),
4257 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4254 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4258 ] + walkopts + dryrunopts,
4255 ] + walkopts + dryrunopts,
4259 _('[OPTION]... SOURCE... DEST'))
4256 _('[OPTION]... SOURCE... DEST'))
4260 def rename(ui, repo, *pats, **opts):
4257 def rename(ui, repo, *pats, **opts):
4261 """rename files; equivalent of copy + remove
4258 """rename files; equivalent of copy + remove
4262
4259
4263 Mark dest as copies of sources; mark sources for deletion. If dest
4260 Mark dest as copies of sources; mark sources for deletion. If dest
4264 is a directory, copies are put in that directory. If dest is a
4261 is a directory, copies are put in that directory. If dest is a
4265 file, there can only be one source.
4262 file, there can only be one source.
4266
4263
4267 By default, this command copies the contents of files as they
4264 By default, this command copies the contents of files as they
4268 exist in the working directory. If invoked with -A/--after, the
4265 exist in the working directory. If invoked with -A/--after, the
4269 operation is recorded, but no copying is performed.
4266 operation is recorded, but no copying is performed.
4270
4267
4271 This command takes effect at the next commit. To undo a rename
4268 This command takes effect at the next commit. To undo a rename
4272 before that, see :hg:`revert`.
4269 before that, see :hg:`revert`.
4273
4270
4274 Returns 0 on success, 1 if errors are encountered.
4271 Returns 0 on success, 1 if errors are encountered.
4275 """
4272 """
4276 wlock = repo.wlock(False)
4273 wlock = repo.wlock(False)
4277 try:
4274 try:
4278 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4275 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4279 finally:
4276 finally:
4280 wlock.release()
4277 wlock.release()
4281
4278
4282 @command('resolve',
4279 @command('resolve',
4283 [('a', 'all', None, _('select all unresolved files')),
4280 [('a', 'all', None, _('select all unresolved files')),
4284 ('l', 'list', None, _('list state of files needing merge')),
4281 ('l', 'list', None, _('list state of files needing merge')),
4285 ('m', 'mark', None, _('mark files as resolved')),
4282 ('m', 'mark', None, _('mark files as resolved')),
4286 ('u', 'unmark', None, _('mark files as unresolved')),
4283 ('u', 'unmark', None, _('mark files as unresolved')),
4287 ('n', 'no-status', None, _('hide status prefix'))]
4284 ('n', 'no-status', None, _('hide status prefix'))]
4288 + mergetoolopts + walkopts,
4285 + mergetoolopts + walkopts,
4289 _('[OPTION]... [FILE]...'))
4286 _('[OPTION]... [FILE]...'))
4290 def resolve(ui, repo, *pats, **opts):
4287 def resolve(ui, repo, *pats, **opts):
4291 """redo merges or set/view the merge status of files
4288 """redo merges or set/view the merge status of files
4292
4289
4293 Merges with unresolved conflicts are often the result of
4290 Merges with unresolved conflicts are often the result of
4294 non-interactive merging using the ``internal:merge`` configuration
4291 non-interactive merging using the ``internal:merge`` configuration
4295 setting, or a command-line merge tool like ``diff3``. The resolve
4292 setting, or a command-line merge tool like ``diff3``. The resolve
4296 command is used to manage the files involved in a merge, after
4293 command is used to manage the files involved in a merge, after
4297 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4294 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4298 working directory must have two parents).
4295 working directory must have two parents).
4299
4296
4300 The resolve command can be used in the following ways:
4297 The resolve command can be used in the following ways:
4301
4298
4302 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4299 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4303 files, discarding any previous merge attempts. Re-merging is not
4300 files, discarding any previous merge attempts. Re-merging is not
4304 performed for files already marked as resolved. Use ``--all/-a``
4301 performed for files already marked as resolved. Use ``--all/-a``
4305 to select all unresolved files. ``--tool`` can be used to specify
4302 to select all unresolved files. ``--tool`` can be used to specify
4306 the merge tool used for the given files. It overrides the HGMERGE
4303 the merge tool used for the given files. It overrides the HGMERGE
4307 environment variable and your configuration files.
4304 environment variable and your configuration files.
4308
4305
4309 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4306 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4310 (e.g. after having manually fixed-up the files). The default is
4307 (e.g. after having manually fixed-up the files). The default is
4311 to mark all unresolved files.
4308 to mark all unresolved files.
4312
4309
4313 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4310 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4314 default is to mark all resolved files.
4311 default is to mark all resolved files.
4315
4312
4316 - :hg:`resolve -l`: list files which had or still have conflicts.
4313 - :hg:`resolve -l`: list files which had or still have conflicts.
4317 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4314 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4318
4315
4319 Note that Mercurial will not let you commit files with unresolved
4316 Note that Mercurial will not let you commit files with unresolved
4320 merge conflicts. You must use :hg:`resolve -m ...` before you can
4317 merge conflicts. You must use :hg:`resolve -m ...` before you can
4321 commit after a conflicting merge.
4318 commit after a conflicting merge.
4322
4319
4323 Returns 0 on success, 1 if any files fail a resolve attempt.
4320 Returns 0 on success, 1 if any files fail a resolve attempt.
4324 """
4321 """
4325
4322
4326 all, mark, unmark, show, nostatus = \
4323 all, mark, unmark, show, nostatus = \
4327 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4324 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4328
4325
4329 if (show and (mark or unmark)) or (mark and unmark):
4326 if (show and (mark or unmark)) or (mark and unmark):
4330 raise util.Abort(_("too many options specified"))
4327 raise util.Abort(_("too many options specified"))
4331 if pats and all:
4328 if pats and all:
4332 raise util.Abort(_("can't specify --all and patterns"))
4329 raise util.Abort(_("can't specify --all and patterns"))
4333 if not (all or pats or show or mark or unmark):
4330 if not (all or pats or show or mark or unmark):
4334 raise util.Abort(_('no files or directories specified; '
4331 raise util.Abort(_('no files or directories specified; '
4335 'use --all to remerge all files'))
4332 'use --all to remerge all files'))
4336
4333
4337 ms = mergemod.mergestate(repo)
4334 ms = mergemod.mergestate(repo)
4338 m = scmutil.match(repo[None], pats, opts)
4335 m = scmutil.match(repo[None], pats, opts)
4339 ret = 0
4336 ret = 0
4340
4337
4341 for f in ms:
4338 for f in ms:
4342 if m(f):
4339 if m(f):
4343 if show:
4340 if show:
4344 if nostatus:
4341 if nostatus:
4345 ui.write("%s\n" % f)
4342 ui.write("%s\n" % f)
4346 else:
4343 else:
4347 ui.write("%s %s\n" % (ms[f].upper(), f),
4344 ui.write("%s %s\n" % (ms[f].upper(), f),
4348 label='resolve.' +
4345 label='resolve.' +
4349 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4346 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4350 elif mark:
4347 elif mark:
4351 ms.mark(f, "r")
4348 ms.mark(f, "r")
4352 elif unmark:
4349 elif unmark:
4353 ms.mark(f, "u")
4350 ms.mark(f, "u")
4354 else:
4351 else:
4355 wctx = repo[None]
4352 wctx = repo[None]
4356 mctx = wctx.parents()[-1]
4353 mctx = wctx.parents()[-1]
4357
4354
4358 # backup pre-resolve (merge uses .orig for its own purposes)
4355 # backup pre-resolve (merge uses .orig for its own purposes)
4359 a = repo.wjoin(f)
4356 a = repo.wjoin(f)
4360 util.copyfile(a, a + ".resolve")
4357 util.copyfile(a, a + ".resolve")
4361
4358
4362 try:
4359 try:
4363 # resolve file
4360 # resolve file
4364 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4361 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4365 if ms.resolve(f, wctx, mctx):
4362 if ms.resolve(f, wctx, mctx):
4366 ret = 1
4363 ret = 1
4367 finally:
4364 finally:
4368 ui.setconfig('ui', 'forcemerge', '')
4365 ui.setconfig('ui', 'forcemerge', '')
4369
4366
4370 # replace filemerge's .orig file with our resolve file
4367 # replace filemerge's .orig file with our resolve file
4371 util.rename(a + ".resolve", a + ".orig")
4368 util.rename(a + ".resolve", a + ".orig")
4372
4369
4373 ms.commit()
4370 ms.commit()
4374 return ret
4371 return ret
4375
4372
4376 @command('revert',
4373 @command('revert',
4377 [('a', 'all', None, _('revert all changes when no arguments given')),
4374 [('a', 'all', None, _('revert all changes when no arguments given')),
4378 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4375 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4379 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4376 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4380 ('C', 'no-backup', None, _('do not save backup copies of files')),
4377 ('C', 'no-backup', None, _('do not save backup copies of files')),
4381 ] + walkopts + dryrunopts,
4378 ] + walkopts + dryrunopts,
4382 _('[OPTION]... [-r REV] [NAME]...'))
4379 _('[OPTION]... [-r REV] [NAME]...'))
4383 def revert(ui, repo, *pats, **opts):
4380 def revert(ui, repo, *pats, **opts):
4384 """restore files to their checkout state
4381 """restore files to their checkout state
4385
4382
4386 .. note::
4383 .. note::
4387 To check out earlier revisions, you should use :hg:`update REV`.
4384 To check out earlier revisions, you should use :hg:`update REV`.
4388 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4385 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4389
4386
4390 With no revision specified, revert the specified files or directories
4387 With no revision specified, revert the specified files or directories
4391 to the contents they had in the parent of the working directory.
4388 to the contents they had in the parent of the working directory.
4392 This restores the contents of files to an unmodified
4389 This restores the contents of files to an unmodified
4393 state and unschedules adds, removes, copies, and renames. If the
4390 state and unschedules adds, removes, copies, and renames. If the
4394 working directory has two parents, you must explicitly specify a
4391 working directory has two parents, you must explicitly specify a
4395 revision.
4392 revision.
4396
4393
4397 Using the -r/--rev or -d/--date options, revert the given files or
4394 Using the -r/--rev or -d/--date options, revert the given files or
4398 directories to their states as of a specific revision. Because
4395 directories to their states as of a specific revision. Because
4399 revert does not change the working directory parents, this will
4396 revert does not change the working directory parents, this will
4400 cause these files to appear modified. This can be helpful to "back
4397 cause these files to appear modified. This can be helpful to "back
4401 out" some or all of an earlier change. See :hg:`backout` for a
4398 out" some or all of an earlier change. See :hg:`backout` for a
4402 related method.
4399 related method.
4403
4400
4404 Modified files are saved with a .orig suffix before reverting.
4401 Modified files are saved with a .orig suffix before reverting.
4405 To disable these backups, use --no-backup.
4402 To disable these backups, use --no-backup.
4406
4403
4407 See :hg:`help dates` for a list of formats valid for -d/--date.
4404 See :hg:`help dates` for a list of formats valid for -d/--date.
4408
4405
4409 Returns 0 on success.
4406 Returns 0 on success.
4410 """
4407 """
4411
4408
4412 if opts.get("date"):
4409 if opts.get("date"):
4413 if opts.get("rev"):
4410 if opts.get("rev"):
4414 raise util.Abort(_("you can't specify a revision and a date"))
4411 raise util.Abort(_("you can't specify a revision and a date"))
4415 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4412 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4416
4413
4417 parent, p2 = repo.dirstate.parents()
4414 parent, p2 = repo.dirstate.parents()
4418 if not opts.get('rev') and p2 != nullid:
4415 if not opts.get('rev') and p2 != nullid:
4419 # revert after merge is a trap for new users (issue2915)
4416 # revert after merge is a trap for new users (issue2915)
4420 raise util.Abort(_('uncommitted merge with no revision specified'),
4417 raise util.Abort(_('uncommitted merge with no revision specified'),
4421 hint=_('use "hg update" or see "hg help revert"'))
4418 hint=_('use "hg update" or see "hg help revert"'))
4422
4419
4423 ctx = scmutil.revsingle(repo, opts.get('rev'))
4420 ctx = scmutil.revsingle(repo, opts.get('rev'))
4424 node = ctx.node()
4421 node = ctx.node()
4425
4422
4426 if not pats and not opts.get('all'):
4423 if not pats and not opts.get('all'):
4427 msg = _("no files or directories specified")
4424 msg = _("no files or directories specified")
4428 if p2 != nullid:
4425 if p2 != nullid:
4429 hint = _("uncommitted merge, use --all to discard all changes,"
4426 hint = _("uncommitted merge, use --all to discard all changes,"
4430 " or 'hg update -C .' to abort the merge")
4427 " or 'hg update -C .' to abort the merge")
4431 raise util.Abort(msg, hint=hint)
4428 raise util.Abort(msg, hint=hint)
4432 dirty = util.any(repo.status())
4429 dirty = util.any(repo.status())
4433 if node != parent:
4430 if node != parent:
4434 if dirty:
4431 if dirty:
4435 hint = _("uncommitted changes, use --all to discard all"
4432 hint = _("uncommitted changes, use --all to discard all"
4436 " changes, or 'hg update %s' to update") % ctx.rev()
4433 " changes, or 'hg update %s' to update") % ctx.rev()
4437 else:
4434 else:
4438 hint = _("use --all to revert all files,"
4435 hint = _("use --all to revert all files,"
4439 " or 'hg update %s' to update") % ctx.rev()
4436 " or 'hg update %s' to update") % ctx.rev()
4440 elif dirty:
4437 elif dirty:
4441 hint = _("uncommitted changes, use --all to discard all changes")
4438 hint = _("uncommitted changes, use --all to discard all changes")
4442 else:
4439 else:
4443 hint = _("use --all to revert all files")
4440 hint = _("use --all to revert all files")
4444 raise util.Abort(msg, hint=hint)
4441 raise util.Abort(msg, hint=hint)
4445
4442
4446 mf = ctx.manifest()
4443 mf = ctx.manifest()
4447 if node == parent:
4444 if node == parent:
4448 pmf = mf
4445 pmf = mf
4449 else:
4446 else:
4450 pmf = None
4447 pmf = None
4451
4448
4452 # need all matching names in dirstate and manifest of target rev,
4449 # need all matching names in dirstate and manifest of target rev,
4453 # so have to walk both. do not print errors if files exist in one
4450 # so have to walk both. do not print errors if files exist in one
4454 # but not other.
4451 # but not other.
4455
4452
4456 names = {}
4453 names = {}
4457
4454
4458 wlock = repo.wlock()
4455 wlock = repo.wlock()
4459 try:
4456 try:
4460 # walk dirstate.
4457 # walk dirstate.
4461
4458
4462 m = scmutil.match(repo[None], pats, opts)
4459 m = scmutil.match(repo[None], pats, opts)
4463 m.bad = lambda x, y: False
4460 m.bad = lambda x, y: False
4464 for abs in repo.walk(m):
4461 for abs in repo.walk(m):
4465 names[abs] = m.rel(abs), m.exact(abs)
4462 names[abs] = m.rel(abs), m.exact(abs)
4466
4463
4467 # walk target manifest.
4464 # walk target manifest.
4468
4465
4469 def badfn(path, msg):
4466 def badfn(path, msg):
4470 if path in names:
4467 if path in names:
4471 return
4468 return
4472 path_ = path + '/'
4469 path_ = path + '/'
4473 for f in names:
4470 for f in names:
4474 if f.startswith(path_):
4471 if f.startswith(path_):
4475 return
4472 return
4476 ui.warn("%s: %s\n" % (m.rel(path), msg))
4473 ui.warn("%s: %s\n" % (m.rel(path), msg))
4477
4474
4478 m = scmutil.match(repo[node], pats, opts)
4475 m = scmutil.match(repo[node], pats, opts)
4479 m.bad = badfn
4476 m.bad = badfn
4480 for abs in repo[node].walk(m):
4477 for abs in repo[node].walk(m):
4481 if abs not in names:
4478 if abs not in names:
4482 names[abs] = m.rel(abs), m.exact(abs)
4479 names[abs] = m.rel(abs), m.exact(abs)
4483
4480
4484 m = scmutil.matchfiles(repo, names)
4481 m = scmutil.matchfiles(repo, names)
4485 changes = repo.status(match=m)[:4]
4482 changes = repo.status(match=m)[:4]
4486 modified, added, removed, deleted = map(set, changes)
4483 modified, added, removed, deleted = map(set, changes)
4487
4484
4488 # if f is a rename, also revert the source
4485 # if f is a rename, also revert the source
4489 cwd = repo.getcwd()
4486 cwd = repo.getcwd()
4490 for f in added:
4487 for f in added:
4491 src = repo.dirstate.copied(f)
4488 src = repo.dirstate.copied(f)
4492 if src and src not in names and repo.dirstate[src] == 'r':
4489 if src and src not in names and repo.dirstate[src] == 'r':
4493 removed.add(src)
4490 removed.add(src)
4494 names[src] = (repo.pathto(src, cwd), True)
4491 names[src] = (repo.pathto(src, cwd), True)
4495
4492
4496 def removeforget(abs):
4493 def removeforget(abs):
4497 if repo.dirstate[abs] == 'a':
4494 if repo.dirstate[abs] == 'a':
4498 return _('forgetting %s\n')
4495 return _('forgetting %s\n')
4499 return _('removing %s\n')
4496 return _('removing %s\n')
4500
4497
4501 revert = ([], _('reverting %s\n'))
4498 revert = ([], _('reverting %s\n'))
4502 add = ([], _('adding %s\n'))
4499 add = ([], _('adding %s\n'))
4503 remove = ([], removeforget)
4500 remove = ([], removeforget)
4504 undelete = ([], _('undeleting %s\n'))
4501 undelete = ([], _('undeleting %s\n'))
4505
4502
4506 disptable = (
4503 disptable = (
4507 # dispatch table:
4504 # dispatch table:
4508 # file state
4505 # file state
4509 # action if in target manifest
4506 # action if in target manifest
4510 # action if not in target manifest
4507 # action if not in target manifest
4511 # make backup if in target manifest
4508 # make backup if in target manifest
4512 # make backup if not in target manifest
4509 # make backup if not in target manifest
4513 (modified, revert, remove, True, True),
4510 (modified, revert, remove, True, True),
4514 (added, revert, remove, True, False),
4511 (added, revert, remove, True, False),
4515 (removed, undelete, None, False, False),
4512 (removed, undelete, None, False, False),
4516 (deleted, revert, remove, False, False),
4513 (deleted, revert, remove, False, False),
4517 )
4514 )
4518
4515
4519 for abs, (rel, exact) in sorted(names.items()):
4516 for abs, (rel, exact) in sorted(names.items()):
4520 mfentry = mf.get(abs)
4517 mfentry = mf.get(abs)
4521 target = repo.wjoin(abs)
4518 target = repo.wjoin(abs)
4522 def handle(xlist, dobackup):
4519 def handle(xlist, dobackup):
4523 xlist[0].append(abs)
4520 xlist[0].append(abs)
4524 if (dobackup and not opts.get('no_backup') and
4521 if (dobackup and not opts.get('no_backup') and
4525 os.path.lexists(target)):
4522 os.path.lexists(target)):
4526 bakname = "%s.orig" % rel
4523 bakname = "%s.orig" % rel
4527 ui.note(_('saving current version of %s as %s\n') %
4524 ui.note(_('saving current version of %s as %s\n') %
4528 (rel, bakname))
4525 (rel, bakname))
4529 if not opts.get('dry_run'):
4526 if not opts.get('dry_run'):
4530 util.rename(target, bakname)
4527 util.rename(target, bakname)
4531 if ui.verbose or not exact:
4528 if ui.verbose or not exact:
4532 msg = xlist[1]
4529 msg = xlist[1]
4533 if not isinstance(msg, basestring):
4530 if not isinstance(msg, basestring):
4534 msg = msg(abs)
4531 msg = msg(abs)
4535 ui.status(msg % rel)
4532 ui.status(msg % rel)
4536 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4533 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4537 if abs not in table:
4534 if abs not in table:
4538 continue
4535 continue
4539 # file has changed in dirstate
4536 # file has changed in dirstate
4540 if mfentry:
4537 if mfentry:
4541 handle(hitlist, backuphit)
4538 handle(hitlist, backuphit)
4542 elif misslist is not None:
4539 elif misslist is not None:
4543 handle(misslist, backupmiss)
4540 handle(misslist, backupmiss)
4544 break
4541 break
4545 else:
4542 else:
4546 if abs not in repo.dirstate:
4543 if abs not in repo.dirstate:
4547 if mfentry:
4544 if mfentry:
4548 handle(add, True)
4545 handle(add, True)
4549 elif exact:
4546 elif exact:
4550 ui.warn(_('file not managed: %s\n') % rel)
4547 ui.warn(_('file not managed: %s\n') % rel)
4551 continue
4548 continue
4552 # file has not changed in dirstate
4549 # file has not changed in dirstate
4553 if node == parent:
4550 if node == parent:
4554 if exact:
4551 if exact:
4555 ui.warn(_('no changes needed to %s\n') % rel)
4552 ui.warn(_('no changes needed to %s\n') % rel)
4556 continue
4553 continue
4557 if pmf is None:
4554 if pmf is None:
4558 # only need parent manifest in this unlikely case,
4555 # only need parent manifest in this unlikely case,
4559 # so do not read by default
4556 # so do not read by default
4560 pmf = repo[parent].manifest()
4557 pmf = repo[parent].manifest()
4561 if abs in pmf:
4558 if abs in pmf:
4562 if mfentry:
4559 if mfentry:
4563 # if version of file is same in parent and target
4560 # if version of file is same in parent and target
4564 # manifests, do nothing
4561 # manifests, do nothing
4565 if (pmf[abs] != mfentry or
4562 if (pmf[abs] != mfentry or
4566 pmf.flags(abs) != mf.flags(abs)):
4563 pmf.flags(abs) != mf.flags(abs)):
4567 handle(revert, False)
4564 handle(revert, False)
4568 else:
4565 else:
4569 handle(remove, False)
4566 handle(remove, False)
4570
4567
4571 if not opts.get('dry_run'):
4568 if not opts.get('dry_run'):
4572 def checkout(f):
4569 def checkout(f):
4573 fc = ctx[f]
4570 fc = ctx[f]
4574 repo.wwrite(f, fc.data(), fc.flags())
4571 repo.wwrite(f, fc.data(), fc.flags())
4575
4572
4576 audit_path = scmutil.pathauditor(repo.root)
4573 audit_path = scmutil.pathauditor(repo.root)
4577 for f in remove[0]:
4574 for f in remove[0]:
4578 if repo.dirstate[f] == 'a':
4575 if repo.dirstate[f] == 'a':
4579 repo.dirstate.drop(f)
4576 repo.dirstate.drop(f)
4580 continue
4577 continue
4581 audit_path(f)
4578 audit_path(f)
4582 try:
4579 try:
4583 util.unlinkpath(repo.wjoin(f))
4580 util.unlinkpath(repo.wjoin(f))
4584 except OSError:
4581 except OSError:
4585 pass
4582 pass
4586 repo.dirstate.remove(f)
4583 repo.dirstate.remove(f)
4587
4584
4588 normal = None
4585 normal = None
4589 if node == parent:
4586 if node == parent:
4590 # We're reverting to our parent. If possible, we'd like status
4587 # We're reverting to our parent. If possible, we'd like status
4591 # to report the file as clean. We have to use normallookup for
4588 # to report the file as clean. We have to use normallookup for
4592 # merges to avoid losing information about merged/dirty files.
4589 # merges to avoid losing information about merged/dirty files.
4593 if p2 != nullid:
4590 if p2 != nullid:
4594 normal = repo.dirstate.normallookup
4591 normal = repo.dirstate.normallookup
4595 else:
4592 else:
4596 normal = repo.dirstate.normal
4593 normal = repo.dirstate.normal
4597 for f in revert[0]:
4594 for f in revert[0]:
4598 checkout(f)
4595 checkout(f)
4599 if normal:
4596 if normal:
4600 normal(f)
4597 normal(f)
4601
4598
4602 for f in add[0]:
4599 for f in add[0]:
4603 checkout(f)
4600 checkout(f)
4604 repo.dirstate.add(f)
4601 repo.dirstate.add(f)
4605
4602
4606 normal = repo.dirstate.normallookup
4603 normal = repo.dirstate.normallookup
4607 if node == parent and p2 == nullid:
4604 if node == parent and p2 == nullid:
4608 normal = repo.dirstate.normal
4605 normal = repo.dirstate.normal
4609 for f in undelete[0]:
4606 for f in undelete[0]:
4610 checkout(f)
4607 checkout(f)
4611 normal(f)
4608 normal(f)
4612
4609
4613 finally:
4610 finally:
4614 wlock.release()
4611 wlock.release()
4615
4612
4616 @command('rollback', dryrunopts +
4613 @command('rollback', dryrunopts +
4617 [('f', 'force', False, _('ignore safety measures'))])
4614 [('f', 'force', False, _('ignore safety measures'))])
4618 def rollback(ui, repo, **opts):
4615 def rollback(ui, repo, **opts):
4619 """roll back the last transaction (dangerous)
4616 """roll back the last transaction (dangerous)
4620
4617
4621 This command should be used with care. There is only one level of
4618 This command should be used with care. There is only one level of
4622 rollback, and there is no way to undo a rollback. It will also
4619 rollback, and there is no way to undo a rollback. It will also
4623 restore the dirstate at the time of the last transaction, losing
4620 restore the dirstate at the time of the last transaction, losing
4624 any dirstate changes since that time. This command does not alter
4621 any dirstate changes since that time. This command does not alter
4625 the working directory.
4622 the working directory.
4626
4623
4627 Transactions are used to encapsulate the effects of all commands
4624 Transactions are used to encapsulate the effects of all commands
4628 that create new changesets or propagate existing changesets into a
4625 that create new changesets or propagate existing changesets into a
4629 repository. For example, the following commands are transactional,
4626 repository. For example, the following commands are transactional,
4630 and their effects can be rolled back:
4627 and their effects can be rolled back:
4631
4628
4632 - commit
4629 - commit
4633 - import
4630 - import
4634 - pull
4631 - pull
4635 - push (with this repository as the destination)
4632 - push (with this repository as the destination)
4636 - unbundle
4633 - unbundle
4637
4634
4638 It's possible to lose data with rollback: commit, update back to
4635 It's possible to lose data with rollback: commit, update back to
4639 an older changeset, and then rollback. The update removes the
4636 an older changeset, and then rollback. The update removes the
4640 changes you committed from the working directory, and rollback
4637 changes you committed from the working directory, and rollback
4641 removes them from history. To avoid data loss, you must pass
4638 removes them from history. To avoid data loss, you must pass
4642 --force in this case.
4639 --force in this case.
4643
4640
4644 This command is not intended for use on public repositories. Once
4641 This command is not intended for use on public repositories. Once
4645 changes are visible for pull by other users, rolling a transaction
4642 changes are visible for pull by other users, rolling a transaction
4646 back locally is ineffective (someone else may already have pulled
4643 back locally is ineffective (someone else may already have pulled
4647 the changes). Furthermore, a race is possible with readers of the
4644 the changes). Furthermore, a race is possible with readers of the
4648 repository; for example an in-progress pull from the repository
4645 repository; for example an in-progress pull from the repository
4649 may fail if a rollback is performed.
4646 may fail if a rollback is performed.
4650
4647
4651 Returns 0 on success, 1 if no rollback data is available.
4648 Returns 0 on success, 1 if no rollback data is available.
4652 """
4649 """
4653 return repo.rollback(dryrun=opts.get('dry_run'),
4650 return repo.rollback(dryrun=opts.get('dry_run'),
4654 force=opts.get('force'))
4651 force=opts.get('force'))
4655
4652
4656 @command('root', [])
4653 @command('root', [])
4657 def root(ui, repo):
4654 def root(ui, repo):
4658 """print the root (top) of the current working directory
4655 """print the root (top) of the current working directory
4659
4656
4660 Print the root directory of the current repository.
4657 Print the root directory of the current repository.
4661
4658
4662 Returns 0 on success.
4659 Returns 0 on success.
4663 """
4660 """
4664 ui.write(repo.root + "\n")
4661 ui.write(repo.root + "\n")
4665
4662
4666 @command('^serve',
4663 @command('^serve',
4667 [('A', 'accesslog', '', _('name of access log file to write to'),
4664 [('A', 'accesslog', '', _('name of access log file to write to'),
4668 _('FILE')),
4665 _('FILE')),
4669 ('d', 'daemon', None, _('run server in background')),
4666 ('d', 'daemon', None, _('run server in background')),
4670 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4667 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4671 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4668 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4672 # use string type, then we can check if something was passed
4669 # use string type, then we can check if something was passed
4673 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4670 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4674 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4671 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4675 _('ADDR')),
4672 _('ADDR')),
4676 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4673 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4677 _('PREFIX')),
4674 _('PREFIX')),
4678 ('n', 'name', '',
4675 ('n', 'name', '',
4679 _('name to show in web pages (default: working directory)'), _('NAME')),
4676 _('name to show in web pages (default: working directory)'), _('NAME')),
4680 ('', 'web-conf', '',
4677 ('', 'web-conf', '',
4681 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4678 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4682 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4679 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4683 _('FILE')),
4680 _('FILE')),
4684 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4681 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4685 ('', 'stdio', None, _('for remote clients')),
4682 ('', 'stdio', None, _('for remote clients')),
4686 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4683 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4687 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4684 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4688 ('', 'style', '', _('template style to use'), _('STYLE')),
4685 ('', 'style', '', _('template style to use'), _('STYLE')),
4689 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4686 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4690 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4687 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4691 _('[OPTION]...'))
4688 _('[OPTION]...'))
4692 def serve(ui, repo, **opts):
4689 def serve(ui, repo, **opts):
4693 """start stand-alone webserver
4690 """start stand-alone webserver
4694
4691
4695 Start a local HTTP repository browser and pull server. You can use
4692 Start a local HTTP repository browser and pull server. You can use
4696 this for ad-hoc sharing and browsing of repositories. It is
4693 this for ad-hoc sharing and browsing of repositories. It is
4697 recommended to use a real web server to serve a repository for
4694 recommended to use a real web server to serve a repository for
4698 longer periods of time.
4695 longer periods of time.
4699
4696
4700 Please note that the server does not implement access control.
4697 Please note that the server does not implement access control.
4701 This means that, by default, anybody can read from the server and
4698 This means that, by default, anybody can read from the server and
4702 nobody can write to it by default. Set the ``web.allow_push``
4699 nobody can write to it by default. Set the ``web.allow_push``
4703 option to ``*`` to allow everybody to push to the server. You
4700 option to ``*`` to allow everybody to push to the server. You
4704 should use a real web server if you need to authenticate users.
4701 should use a real web server if you need to authenticate users.
4705
4702
4706 By default, the server logs accesses to stdout and errors to
4703 By default, the server logs accesses to stdout and errors to
4707 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4704 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4708 files.
4705 files.
4709
4706
4710 To have the server choose a free port number to listen on, specify
4707 To have the server choose a free port number to listen on, specify
4711 a port number of 0; in this case, the server will print the port
4708 a port number of 0; in this case, the server will print the port
4712 number it uses.
4709 number it uses.
4713
4710
4714 Returns 0 on success.
4711 Returns 0 on success.
4715 """
4712 """
4716
4713
4717 if opts["stdio"] and opts["cmdserver"]:
4714 if opts["stdio"] and opts["cmdserver"]:
4718 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4715 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4719
4716
4720 def checkrepo():
4717 def checkrepo():
4721 if repo is None:
4718 if repo is None:
4722 raise error.RepoError(_("There is no Mercurial repository here"
4719 raise error.RepoError(_("There is no Mercurial repository here"
4723 " (.hg not found)"))
4720 " (.hg not found)"))
4724
4721
4725 if opts["stdio"]:
4722 if opts["stdio"]:
4726 checkrepo()
4723 checkrepo()
4727 s = sshserver.sshserver(ui, repo)
4724 s = sshserver.sshserver(ui, repo)
4728 s.serve_forever()
4725 s.serve_forever()
4729
4726
4730 if opts["cmdserver"]:
4727 if opts["cmdserver"]:
4731 checkrepo()
4728 checkrepo()
4732 s = commandserver.server(ui, repo, opts["cmdserver"])
4729 s = commandserver.server(ui, repo, opts["cmdserver"])
4733 return s.serve()
4730 return s.serve()
4734
4731
4735 # this way we can check if something was given in the command-line
4732 # this way we can check if something was given in the command-line
4736 if opts.get('port'):
4733 if opts.get('port'):
4737 opts['port'] = util.getport(opts.get('port'))
4734 opts['port'] = util.getport(opts.get('port'))
4738
4735
4739 baseui = repo and repo.baseui or ui
4736 baseui = repo and repo.baseui or ui
4740 optlist = ("name templates style address port prefix ipv6"
4737 optlist = ("name templates style address port prefix ipv6"
4741 " accesslog errorlog certificate encoding")
4738 " accesslog errorlog certificate encoding")
4742 for o in optlist.split():
4739 for o in optlist.split():
4743 val = opts.get(o, '')
4740 val = opts.get(o, '')
4744 if val in (None, ''): # should check against default options instead
4741 if val in (None, ''): # should check against default options instead
4745 continue
4742 continue
4746 baseui.setconfig("web", o, val)
4743 baseui.setconfig("web", o, val)
4747 if repo and repo.ui != baseui:
4744 if repo and repo.ui != baseui:
4748 repo.ui.setconfig("web", o, val)
4745 repo.ui.setconfig("web", o, val)
4749
4746
4750 o = opts.get('web_conf') or opts.get('webdir_conf')
4747 o = opts.get('web_conf') or opts.get('webdir_conf')
4751 if not o:
4748 if not o:
4752 if not repo:
4749 if not repo:
4753 raise error.RepoError(_("There is no Mercurial repository"
4750 raise error.RepoError(_("There is no Mercurial repository"
4754 " here (.hg not found)"))
4751 " here (.hg not found)"))
4755 o = repo.root
4752 o = repo.root
4756
4753
4757 app = hgweb.hgweb(o, baseui=ui)
4754 app = hgweb.hgweb(o, baseui=ui)
4758
4755
4759 class service(object):
4756 class service(object):
4760 def init(self):
4757 def init(self):
4761 util.setsignalhandler()
4758 util.setsignalhandler()
4762 self.httpd = hgweb.server.create_server(ui, app)
4759 self.httpd = hgweb.server.create_server(ui, app)
4763
4760
4764 if opts['port'] and not ui.verbose:
4761 if opts['port'] and not ui.verbose:
4765 return
4762 return
4766
4763
4767 if self.httpd.prefix:
4764 if self.httpd.prefix:
4768 prefix = self.httpd.prefix.strip('/') + '/'
4765 prefix = self.httpd.prefix.strip('/') + '/'
4769 else:
4766 else:
4770 prefix = ''
4767 prefix = ''
4771
4768
4772 port = ':%d' % self.httpd.port
4769 port = ':%d' % self.httpd.port
4773 if port == ':80':
4770 if port == ':80':
4774 port = ''
4771 port = ''
4775
4772
4776 bindaddr = self.httpd.addr
4773 bindaddr = self.httpd.addr
4777 if bindaddr == '0.0.0.0':
4774 if bindaddr == '0.0.0.0':
4778 bindaddr = '*'
4775 bindaddr = '*'
4779 elif ':' in bindaddr: # IPv6
4776 elif ':' in bindaddr: # IPv6
4780 bindaddr = '[%s]' % bindaddr
4777 bindaddr = '[%s]' % bindaddr
4781
4778
4782 fqaddr = self.httpd.fqaddr
4779 fqaddr = self.httpd.fqaddr
4783 if ':' in fqaddr:
4780 if ':' in fqaddr:
4784 fqaddr = '[%s]' % fqaddr
4781 fqaddr = '[%s]' % fqaddr
4785 if opts['port']:
4782 if opts['port']:
4786 write = ui.status
4783 write = ui.status
4787 else:
4784 else:
4788 write = ui.write
4785 write = ui.write
4789 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4786 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4790 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4787 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4791
4788
4792 def run(self):
4789 def run(self):
4793 self.httpd.serve_forever()
4790 self.httpd.serve_forever()
4794
4791
4795 service = service()
4792 service = service()
4796
4793
4797 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4794 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4798
4795
4799 @command('showconfig|debugconfig',
4796 @command('showconfig|debugconfig',
4800 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4797 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4801 _('[-u] [NAME]...'))
4798 _('[-u] [NAME]...'))
4802 def showconfig(ui, repo, *values, **opts):
4799 def showconfig(ui, repo, *values, **opts):
4803 """show combined config settings from all hgrc files
4800 """show combined config settings from all hgrc files
4804
4801
4805 With no arguments, print names and values of all config items.
4802 With no arguments, print names and values of all config items.
4806
4803
4807 With one argument of the form section.name, print just the value
4804 With one argument of the form section.name, print just the value
4808 of that config item.
4805 of that config item.
4809
4806
4810 With multiple arguments, print names and values of all config
4807 With multiple arguments, print names and values of all config
4811 items with matching section names.
4808 items with matching section names.
4812
4809
4813 With --debug, the source (filename and line number) is printed
4810 With --debug, the source (filename and line number) is printed
4814 for each config item.
4811 for each config item.
4815
4812
4816 Returns 0 on success.
4813 Returns 0 on success.
4817 """
4814 """
4818
4815
4819 for f in scmutil.rcpath():
4816 for f in scmutil.rcpath():
4820 ui.debug('read config from: %s\n' % f)
4817 ui.debug('read config from: %s\n' % f)
4821 untrusted = bool(opts.get('untrusted'))
4818 untrusted = bool(opts.get('untrusted'))
4822 if values:
4819 if values:
4823 sections = [v for v in values if '.' not in v]
4820 sections = [v for v in values if '.' not in v]
4824 items = [v for v in values if '.' in v]
4821 items = [v for v in values if '.' in v]
4825 if len(items) > 1 or items and sections:
4822 if len(items) > 1 or items and sections:
4826 raise util.Abort(_('only one config item permitted'))
4823 raise util.Abort(_('only one config item permitted'))
4827 for section, name, value in ui.walkconfig(untrusted=untrusted):
4824 for section, name, value in ui.walkconfig(untrusted=untrusted):
4828 value = str(value).replace('\n', '\\n')
4825 value = str(value).replace('\n', '\\n')
4829 sectname = section + '.' + name
4826 sectname = section + '.' + name
4830 if values:
4827 if values:
4831 for v in values:
4828 for v in values:
4832 if v == section:
4829 if v == section:
4833 ui.debug('%s: ' %
4830 ui.debug('%s: ' %
4834 ui.configsource(section, name, untrusted))
4831 ui.configsource(section, name, untrusted))
4835 ui.write('%s=%s\n' % (sectname, value))
4832 ui.write('%s=%s\n' % (sectname, value))
4836 elif v == sectname:
4833 elif v == sectname:
4837 ui.debug('%s: ' %
4834 ui.debug('%s: ' %
4838 ui.configsource(section, name, untrusted))
4835 ui.configsource(section, name, untrusted))
4839 ui.write(value, '\n')
4836 ui.write(value, '\n')
4840 else:
4837 else:
4841 ui.debug('%s: ' %
4838 ui.debug('%s: ' %
4842 ui.configsource(section, name, untrusted))
4839 ui.configsource(section, name, untrusted))
4843 ui.write('%s=%s\n' % (sectname, value))
4840 ui.write('%s=%s\n' % (sectname, value))
4844
4841
4845 @command('^status|st',
4842 @command('^status|st',
4846 [('A', 'all', None, _('show status of all files')),
4843 [('A', 'all', None, _('show status of all files')),
4847 ('m', 'modified', None, _('show only modified files')),
4844 ('m', 'modified', None, _('show only modified files')),
4848 ('a', 'added', None, _('show only added files')),
4845 ('a', 'added', None, _('show only added files')),
4849 ('r', 'removed', None, _('show only removed files')),
4846 ('r', 'removed', None, _('show only removed files')),
4850 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4847 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4851 ('c', 'clean', None, _('show only files without changes')),
4848 ('c', 'clean', None, _('show only files without changes')),
4852 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4849 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4853 ('i', 'ignored', None, _('show only ignored files')),
4850 ('i', 'ignored', None, _('show only ignored files')),
4854 ('n', 'no-status', None, _('hide status prefix')),
4851 ('n', 'no-status', None, _('hide status prefix')),
4855 ('C', 'copies', None, _('show source of copied files')),
4852 ('C', 'copies', None, _('show source of copied files')),
4856 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4853 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4857 ('', 'rev', [], _('show difference from revision'), _('REV')),
4854 ('', 'rev', [], _('show difference from revision'), _('REV')),
4858 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4855 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4859 ] + walkopts + subrepoopts,
4856 ] + walkopts + subrepoopts,
4860 _('[OPTION]... [FILE]...'))
4857 _('[OPTION]... [FILE]...'))
4861 def status(ui, repo, *pats, **opts):
4858 def status(ui, repo, *pats, **opts):
4862 """show changed files in the working directory
4859 """show changed files in the working directory
4863
4860
4864 Show status of files in the repository. If names are given, only
4861 Show status of files in the repository. If names are given, only
4865 files that match are shown. Files that are clean or ignored or
4862 files that match are shown. Files that are clean or ignored or
4866 the source of a copy/move operation, are not listed unless
4863 the source of a copy/move operation, are not listed unless
4867 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4864 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4868 Unless options described with "show only ..." are given, the
4865 Unless options described with "show only ..." are given, the
4869 options -mardu are used.
4866 options -mardu are used.
4870
4867
4871 Option -q/--quiet hides untracked (unknown and ignored) files
4868 Option -q/--quiet hides untracked (unknown and ignored) files
4872 unless explicitly requested with -u/--unknown or -i/--ignored.
4869 unless explicitly requested with -u/--unknown or -i/--ignored.
4873
4870
4874 .. note::
4871 .. note::
4875 status may appear to disagree with diff if permissions have
4872 status may appear to disagree with diff if permissions have
4876 changed or a merge has occurred. The standard diff format does
4873 changed or a merge has occurred. The standard diff format does
4877 not report permission changes and diff only reports changes
4874 not report permission changes and diff only reports changes
4878 relative to one merge parent.
4875 relative to one merge parent.
4879
4876
4880 If one revision is given, it is used as the base revision.
4877 If one revision is given, it is used as the base revision.
4881 If two revisions are given, the differences between them are
4878 If two revisions are given, the differences between them are
4882 shown. The --change option can also be used as a shortcut to list
4879 shown. The --change option can also be used as a shortcut to list
4883 the changed files of a revision from its first parent.
4880 the changed files of a revision from its first parent.
4884
4881
4885 The codes used to show the status of files are::
4882 The codes used to show the status of files are::
4886
4883
4887 M = modified
4884 M = modified
4888 A = added
4885 A = added
4889 R = removed
4886 R = removed
4890 C = clean
4887 C = clean
4891 ! = missing (deleted by non-hg command, but still tracked)
4888 ! = missing (deleted by non-hg command, but still tracked)
4892 ? = not tracked
4889 ? = not tracked
4893 I = ignored
4890 I = ignored
4894 = origin of the previous file listed as A (added)
4891 = origin of the previous file listed as A (added)
4895
4892
4896 .. container:: verbose
4893 .. container:: verbose
4897
4894
4898 Examples:
4895 Examples:
4899
4896
4900 - show changes in the working directory relative to a changeset:
4897 - show changes in the working directory relative to a changeset:
4901
4898
4902 hg status --rev 9353
4899 hg status --rev 9353
4903
4900
4904 - show all changes including copies in an existing changeset::
4901 - show all changes including copies in an existing changeset::
4905
4902
4906 hg status --copies --change 9353
4903 hg status --copies --change 9353
4907
4904
4908 - get a NUL separated list of added files, suitable for xargs::
4905 - get a NUL separated list of added files, suitable for xargs::
4909
4906
4910 hg status -an0
4907 hg status -an0
4911
4908
4912 Returns 0 on success.
4909 Returns 0 on success.
4913 """
4910 """
4914
4911
4915 revs = opts.get('rev')
4912 revs = opts.get('rev')
4916 change = opts.get('change')
4913 change = opts.get('change')
4917
4914
4918 if revs and change:
4915 if revs and change:
4919 msg = _('cannot specify --rev and --change at the same time')
4916 msg = _('cannot specify --rev and --change at the same time')
4920 raise util.Abort(msg)
4917 raise util.Abort(msg)
4921 elif change:
4918 elif change:
4922 node2 = repo.lookup(change)
4919 node2 = repo.lookup(change)
4923 node1 = repo[node2].p1().node()
4920 node1 = repo[node2].p1().node()
4924 else:
4921 else:
4925 node1, node2 = scmutil.revpair(repo, revs)
4922 node1, node2 = scmutil.revpair(repo, revs)
4926
4923
4927 cwd = (pats and repo.getcwd()) or ''
4924 cwd = (pats and repo.getcwd()) or ''
4928 end = opts.get('print0') and '\0' or '\n'
4925 end = opts.get('print0') and '\0' or '\n'
4929 copy = {}
4926 copy = {}
4930 states = 'modified added removed deleted unknown ignored clean'.split()
4927 states = 'modified added removed deleted unknown ignored clean'.split()
4931 show = [k for k in states if opts.get(k)]
4928 show = [k for k in states if opts.get(k)]
4932 if opts.get('all'):
4929 if opts.get('all'):
4933 show += ui.quiet and (states[:4] + ['clean']) or states
4930 show += ui.quiet and (states[:4] + ['clean']) or states
4934 if not show:
4931 if not show:
4935 show = ui.quiet and states[:4] or states[:5]
4932 show = ui.quiet and states[:4] or states[:5]
4936
4933
4937 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4934 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4938 'ignored' in show, 'clean' in show, 'unknown' in show,
4935 'ignored' in show, 'clean' in show, 'unknown' in show,
4939 opts.get('subrepos'))
4936 opts.get('subrepos'))
4940 changestates = zip(states, 'MAR!?IC', stat)
4937 changestates = zip(states, 'MAR!?IC', stat)
4941
4938
4942 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4939 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4943 ctxn = repo[nullid]
4940 ctxn = repo[nullid]
4944 ctx1 = repo[node1]
4941 ctx1 = repo[node1]
4945 ctx2 = repo[node2]
4942 ctx2 = repo[node2]
4946 added = stat[1]
4943 added = stat[1]
4947 if node2 is None:
4944 if node2 is None:
4948 added = stat[0] + stat[1] # merged?
4945 added = stat[0] + stat[1] # merged?
4949
4946
4950 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4947 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4951 if k in added:
4948 if k in added:
4952 copy[k] = v
4949 copy[k] = v
4953 elif v in added:
4950 elif v in added:
4954 copy[v] = k
4951 copy[v] = k
4955
4952
4956 for state, char, files in changestates:
4953 for state, char, files in changestates:
4957 if state in show:
4954 if state in show:
4958 format = "%s %%s%s" % (char, end)
4955 format = "%s %%s%s" % (char, end)
4959 if opts.get('no_status'):
4956 if opts.get('no_status'):
4960 format = "%%s%s" % end
4957 format = "%%s%s" % end
4961
4958
4962 for f in files:
4959 for f in files:
4963 ui.write(format % repo.pathto(f, cwd),
4960 ui.write(format % repo.pathto(f, cwd),
4964 label='status.' + state)
4961 label='status.' + state)
4965 if f in copy:
4962 if f in copy:
4966 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4963 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4967 label='status.copied')
4964 label='status.copied')
4968
4965
4969 @command('^summary|sum',
4966 @command('^summary|sum',
4970 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4967 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4971 def summary(ui, repo, **opts):
4968 def summary(ui, repo, **opts):
4972 """summarize working directory state
4969 """summarize working directory state
4973
4970
4974 This generates a brief summary of the working directory state,
4971 This generates a brief summary of the working directory state,
4975 including parents, branch, commit status, and available updates.
4972 including parents, branch, commit status, and available updates.
4976
4973
4977 With the --remote option, this will check the default paths for
4974 With the --remote option, this will check the default paths for
4978 incoming and outgoing changes. This can be time-consuming.
4975 incoming and outgoing changes. This can be time-consuming.
4979
4976
4980 Returns 0 on success.
4977 Returns 0 on success.
4981 """
4978 """
4982
4979
4983 ctx = repo[None]
4980 ctx = repo[None]
4984 parents = ctx.parents()
4981 parents = ctx.parents()
4985 pnode = parents[0].node()
4982 pnode = parents[0].node()
4986 marks = []
4983 marks = []
4987
4984
4988 for p in parents:
4985 for p in parents:
4989 # label with log.changeset (instead of log.parent) since this
4986 # label with log.changeset (instead of log.parent) since this
4990 # shows a working directory parent *changeset*:
4987 # shows a working directory parent *changeset*:
4991 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4988 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4992 label='log.changeset')
4989 label='log.changeset')
4993 ui.write(' '.join(p.tags()), label='log.tag')
4990 ui.write(' '.join(p.tags()), label='log.tag')
4994 if p.bookmarks():
4991 if p.bookmarks():
4995 marks.extend(p.bookmarks())
4992 marks.extend(p.bookmarks())
4996 if p.rev() == -1:
4993 if p.rev() == -1:
4997 if not len(repo):
4994 if not len(repo):
4998 ui.write(_(' (empty repository)'))
4995 ui.write(_(' (empty repository)'))
4999 else:
4996 else:
5000 ui.write(_(' (no revision checked out)'))
4997 ui.write(_(' (no revision checked out)'))
5001 ui.write('\n')
4998 ui.write('\n')
5002 if p.description():
4999 if p.description():
5003 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5000 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5004 label='log.summary')
5001 label='log.summary')
5005
5002
5006 branch = ctx.branch()
5003 branch = ctx.branch()
5007 bheads = repo.branchheads(branch)
5004 bheads = repo.branchheads(branch)
5008 m = _('branch: %s\n') % branch
5005 m = _('branch: %s\n') % branch
5009 if branch != 'default':
5006 if branch != 'default':
5010 ui.write(m, label='log.branch')
5007 ui.write(m, label='log.branch')
5011 else:
5008 else:
5012 ui.status(m, label='log.branch')
5009 ui.status(m, label='log.branch')
5013
5010
5014 if marks:
5011 if marks:
5015 current = repo._bookmarkcurrent
5012 current = repo._bookmarkcurrent
5016 ui.write(_('bookmarks:'), label='log.bookmark')
5013 ui.write(_('bookmarks:'), label='log.bookmark')
5017 if current is not None:
5014 if current is not None:
5018 try:
5015 try:
5019 marks.remove(current)
5016 marks.remove(current)
5020 ui.write(' *' + current, label='bookmarks.current')
5017 ui.write(' *' + current, label='bookmarks.current')
5021 except ValueError:
5018 except ValueError:
5022 # current bookmark not in parent ctx marks
5019 # current bookmark not in parent ctx marks
5023 pass
5020 pass
5024 for m in marks:
5021 for m in marks:
5025 ui.write(' ' + m, label='log.bookmark')
5022 ui.write(' ' + m, label='log.bookmark')
5026 ui.write('\n', label='log.bookmark')
5023 ui.write('\n', label='log.bookmark')
5027
5024
5028 st = list(repo.status(unknown=True))[:6]
5025 st = list(repo.status(unknown=True))[:6]
5029
5026
5030 c = repo.dirstate.copies()
5027 c = repo.dirstate.copies()
5031 copied, renamed = [], []
5028 copied, renamed = [], []
5032 for d, s in c.iteritems():
5029 for d, s in c.iteritems():
5033 if s in st[2]:
5030 if s in st[2]:
5034 st[2].remove(s)
5031 st[2].remove(s)
5035 renamed.append(d)
5032 renamed.append(d)
5036 else:
5033 else:
5037 copied.append(d)
5034 copied.append(d)
5038 if d in st[1]:
5035 if d in st[1]:
5039 st[1].remove(d)
5036 st[1].remove(d)
5040 st.insert(3, renamed)
5037 st.insert(3, renamed)
5041 st.insert(4, copied)
5038 st.insert(4, copied)
5042
5039
5043 ms = mergemod.mergestate(repo)
5040 ms = mergemod.mergestate(repo)
5044 st.append([f for f in ms if ms[f] == 'u'])
5041 st.append([f for f in ms if ms[f] == 'u'])
5045
5042
5046 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5043 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5047 st.append(subs)
5044 st.append(subs)
5048
5045
5049 labels = [ui.label(_('%d modified'), 'status.modified'),
5046 labels = [ui.label(_('%d modified'), 'status.modified'),
5050 ui.label(_('%d added'), 'status.added'),
5047 ui.label(_('%d added'), 'status.added'),
5051 ui.label(_('%d removed'), 'status.removed'),
5048 ui.label(_('%d removed'), 'status.removed'),
5052 ui.label(_('%d renamed'), 'status.copied'),
5049 ui.label(_('%d renamed'), 'status.copied'),
5053 ui.label(_('%d copied'), 'status.copied'),
5050 ui.label(_('%d copied'), 'status.copied'),
5054 ui.label(_('%d deleted'), 'status.deleted'),
5051 ui.label(_('%d deleted'), 'status.deleted'),
5055 ui.label(_('%d unknown'), 'status.unknown'),
5052 ui.label(_('%d unknown'), 'status.unknown'),
5056 ui.label(_('%d ignored'), 'status.ignored'),
5053 ui.label(_('%d ignored'), 'status.ignored'),
5057 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5054 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5058 ui.label(_('%d subrepos'), 'status.modified')]
5055 ui.label(_('%d subrepos'), 'status.modified')]
5059 t = []
5056 t = []
5060 for s, l in zip(st, labels):
5057 for s, l in zip(st, labels):
5061 if s:
5058 if s:
5062 t.append(l % len(s))
5059 t.append(l % len(s))
5063
5060
5064 t = ', '.join(t)
5061 t = ', '.join(t)
5065 cleanworkdir = False
5062 cleanworkdir = False
5066
5063
5067 if len(parents) > 1:
5064 if len(parents) > 1:
5068 t += _(' (merge)')
5065 t += _(' (merge)')
5069 elif branch != parents[0].branch():
5066 elif branch != parents[0].branch():
5070 t += _(' (new branch)')
5067 t += _(' (new branch)')
5071 elif (parents[0].extra().get('close') and
5068 elif (parents[0].extra().get('close') and
5072 pnode in repo.branchheads(branch, closed=True)):
5069 pnode in repo.branchheads(branch, closed=True)):
5073 t += _(' (head closed)')
5070 t += _(' (head closed)')
5074 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5071 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5075 t += _(' (clean)')
5072 t += _(' (clean)')
5076 cleanworkdir = True
5073 cleanworkdir = True
5077 elif pnode not in bheads:
5074 elif pnode not in bheads:
5078 t += _(' (new branch head)')
5075 t += _(' (new branch head)')
5079
5076
5080 if cleanworkdir:
5077 if cleanworkdir:
5081 ui.status(_('commit: %s\n') % t.strip())
5078 ui.status(_('commit: %s\n') % t.strip())
5082 else:
5079 else:
5083 ui.write(_('commit: %s\n') % t.strip())
5080 ui.write(_('commit: %s\n') % t.strip())
5084
5081
5085 # all ancestors of branch heads - all ancestors of parent = new csets
5082 # all ancestors of branch heads - all ancestors of parent = new csets
5086 new = [0] * len(repo)
5083 new = [0] * len(repo)
5087 cl = repo.changelog
5084 cl = repo.changelog
5088 for a in [cl.rev(n) for n in bheads]:
5085 for a in [cl.rev(n) for n in bheads]:
5089 new[a] = 1
5086 new[a] = 1
5090 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5087 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5091 new[a] = 1
5088 new[a] = 1
5092 for a in [p.rev() for p in parents]:
5089 for a in [p.rev() for p in parents]:
5093 if a >= 0:
5090 if a >= 0:
5094 new[a] = 0
5091 new[a] = 0
5095 for a in cl.ancestors(*[p.rev() for p in parents]):
5092 for a in cl.ancestors(*[p.rev() for p in parents]):
5096 new[a] = 0
5093 new[a] = 0
5097 new = sum(new)
5094 new = sum(new)
5098
5095
5099 if new == 0:
5096 if new == 0:
5100 ui.status(_('update: (current)\n'))
5097 ui.status(_('update: (current)\n'))
5101 elif pnode not in bheads:
5098 elif pnode not in bheads:
5102 ui.write(_('update: %d new changesets (update)\n') % new)
5099 ui.write(_('update: %d new changesets (update)\n') % new)
5103 else:
5100 else:
5104 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5101 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5105 (new, len(bheads)))
5102 (new, len(bheads)))
5106
5103
5107 if opts.get('remote'):
5104 if opts.get('remote'):
5108 t = []
5105 t = []
5109 source, branches = hg.parseurl(ui.expandpath('default'))
5106 source, branches = hg.parseurl(ui.expandpath('default'))
5110 other = hg.peer(repo, {}, source)
5107 other = hg.peer(repo, {}, source)
5111 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5108 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5112 ui.debug('comparing with %s\n' % util.hidepassword(source))
5109 ui.debug('comparing with %s\n' % util.hidepassword(source))
5113 repo.ui.pushbuffer()
5110 repo.ui.pushbuffer()
5114 commoninc = discovery.findcommonincoming(repo, other)
5111 commoninc = discovery.findcommonincoming(repo, other)
5115 _common, incoming, _rheads = commoninc
5112 _common, incoming, _rheads = commoninc
5116 repo.ui.popbuffer()
5113 repo.ui.popbuffer()
5117 if incoming:
5114 if incoming:
5118 t.append(_('1 or more incoming'))
5115 t.append(_('1 or more incoming'))
5119
5116
5120 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5117 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5121 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5118 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5122 if source != dest:
5119 if source != dest:
5123 other = hg.peer(repo, {}, dest)
5120 other = hg.peer(repo, {}, dest)
5124 commoninc = None
5121 commoninc = None
5125 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5122 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5126 repo.ui.pushbuffer()
5123 repo.ui.pushbuffer()
5127 common, outheads = discovery.findcommonoutgoing(repo, other,
5124 common, outheads = discovery.findcommonoutgoing(repo, other,
5128 commoninc=commoninc)
5125 commoninc=commoninc)
5129 repo.ui.popbuffer()
5126 repo.ui.popbuffer()
5130 o = repo.changelog.findmissing(common=common, heads=outheads)
5127 o = repo.changelog.findmissing(common=common, heads=outheads)
5131 if o:
5128 if o:
5132 t.append(_('%d outgoing') % len(o))
5129 t.append(_('%d outgoing') % len(o))
5133 if 'bookmarks' in other.listkeys('namespaces'):
5130 if 'bookmarks' in other.listkeys('namespaces'):
5134 lmarks = repo.listkeys('bookmarks')
5131 lmarks = repo.listkeys('bookmarks')
5135 rmarks = other.listkeys('bookmarks')
5132 rmarks = other.listkeys('bookmarks')
5136 diff = set(rmarks) - set(lmarks)
5133 diff = set(rmarks) - set(lmarks)
5137 if len(diff) > 0:
5134 if len(diff) > 0:
5138 t.append(_('%d incoming bookmarks') % len(diff))
5135 t.append(_('%d incoming bookmarks') % len(diff))
5139 diff = set(lmarks) - set(rmarks)
5136 diff = set(lmarks) - set(rmarks)
5140 if len(diff) > 0:
5137 if len(diff) > 0:
5141 t.append(_('%d outgoing bookmarks') % len(diff))
5138 t.append(_('%d outgoing bookmarks') % len(diff))
5142
5139
5143 if t:
5140 if t:
5144 ui.write(_('remote: %s\n') % (', '.join(t)))
5141 ui.write(_('remote: %s\n') % (', '.join(t)))
5145 else:
5142 else:
5146 ui.status(_('remote: (synced)\n'))
5143 ui.status(_('remote: (synced)\n'))
5147
5144
5148 @command('tag',
5145 @command('tag',
5149 [('f', 'force', None, _('force tag')),
5146 [('f', 'force', None, _('force tag')),
5150 ('l', 'local', None, _('make the tag local')),
5147 ('l', 'local', None, _('make the tag local')),
5151 ('r', 'rev', '', _('revision to tag'), _('REV')),
5148 ('r', 'rev', '', _('revision to tag'), _('REV')),
5152 ('', 'remove', None, _('remove a tag')),
5149 ('', 'remove', None, _('remove a tag')),
5153 # -l/--local is already there, commitopts cannot be used
5150 # -l/--local is already there, commitopts cannot be used
5154 ('e', 'edit', None, _('edit commit message')),
5151 ('e', 'edit', None, _('edit commit message')),
5155 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5152 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5156 ] + commitopts2,
5153 ] + commitopts2,
5157 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5154 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5158 def tag(ui, repo, name1, *names, **opts):
5155 def tag(ui, repo, name1, *names, **opts):
5159 """add one or more tags for the current or given revision
5156 """add one or more tags for the current or given revision
5160
5157
5161 Name a particular revision using <name>.
5158 Name a particular revision using <name>.
5162
5159
5163 Tags are used to name particular revisions of the repository and are
5160 Tags are used to name particular revisions of the repository and are
5164 very useful to compare different revisions, to go back to significant
5161 very useful to compare different revisions, to go back to significant
5165 earlier versions or to mark branch points as releases, etc. Changing
5162 earlier versions or to mark branch points as releases, etc. Changing
5166 an existing tag is normally disallowed; use -f/--force to override.
5163 an existing tag is normally disallowed; use -f/--force to override.
5167
5164
5168 If no revision is given, the parent of the working directory is
5165 If no revision is given, the parent of the working directory is
5169 used, or tip if no revision is checked out.
5166 used, or tip if no revision is checked out.
5170
5167
5171 To facilitate version control, distribution, and merging of tags,
5168 To facilitate version control, distribution, and merging of tags,
5172 they are stored as a file named ".hgtags" which is managed similarly
5169 they are stored as a file named ".hgtags" which is managed similarly
5173 to other project files and can be hand-edited if necessary. This
5170 to other project files and can be hand-edited if necessary. This
5174 also means that tagging creates a new commit. The file
5171 also means that tagging creates a new commit. The file
5175 ".hg/localtags" is used for local tags (not shared among
5172 ".hg/localtags" is used for local tags (not shared among
5176 repositories).
5173 repositories).
5177
5174
5178 Tag commits are usually made at the head of a branch. If the parent
5175 Tag commits are usually made at the head of a branch. If the parent
5179 of the working directory is not a branch head, :hg:`tag` aborts; use
5176 of the working directory is not a branch head, :hg:`tag` aborts; use
5180 -f/--force to force the tag commit to be based on a non-head
5177 -f/--force to force the tag commit to be based on a non-head
5181 changeset.
5178 changeset.
5182
5179
5183 See :hg:`help dates` for a list of formats valid for -d/--date.
5180 See :hg:`help dates` for a list of formats valid for -d/--date.
5184
5181
5185 Since tag names have priority over branch names during revision
5182 Since tag names have priority over branch names during revision
5186 lookup, using an existing branch name as a tag name is discouraged.
5183 lookup, using an existing branch name as a tag name is discouraged.
5187
5184
5188 Returns 0 on success.
5185 Returns 0 on success.
5189 """
5186 """
5190
5187
5191 rev_ = "."
5188 rev_ = "."
5192 names = [t.strip() for t in (name1,) + names]
5189 names = [t.strip() for t in (name1,) + names]
5193 if len(names) != len(set(names)):
5190 if len(names) != len(set(names)):
5194 raise util.Abort(_('tag names must be unique'))
5191 raise util.Abort(_('tag names must be unique'))
5195 for n in names:
5192 for n in names:
5196 if n in ['tip', '.', 'null']:
5193 if n in ['tip', '.', 'null']:
5197 raise util.Abort(_("the name '%s' is reserved") % n)
5194 raise util.Abort(_("the name '%s' is reserved") % n)
5198 if not n:
5195 if not n:
5199 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5196 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5200 if opts.get('rev') and opts.get('remove'):
5197 if opts.get('rev') and opts.get('remove'):
5201 raise util.Abort(_("--rev and --remove are incompatible"))
5198 raise util.Abort(_("--rev and --remove are incompatible"))
5202 if opts.get('rev'):
5199 if opts.get('rev'):
5203 rev_ = opts['rev']
5200 rev_ = opts['rev']
5204 message = opts.get('message')
5201 message = opts.get('message')
5205 if opts.get('remove'):
5202 if opts.get('remove'):
5206 expectedtype = opts.get('local') and 'local' or 'global'
5203 expectedtype = opts.get('local') and 'local' or 'global'
5207 for n in names:
5204 for n in names:
5208 if not repo.tagtype(n):
5205 if not repo.tagtype(n):
5209 raise util.Abort(_("tag '%s' does not exist") % n)
5206 raise util.Abort(_("tag '%s' does not exist") % n)
5210 if repo.tagtype(n) != expectedtype:
5207 if repo.tagtype(n) != expectedtype:
5211 if expectedtype == 'global':
5208 if expectedtype == 'global':
5212 raise util.Abort(_("tag '%s' is not a global tag") % n)
5209 raise util.Abort(_("tag '%s' is not a global tag") % n)
5213 else:
5210 else:
5214 raise util.Abort(_("tag '%s' is not a local tag") % n)
5211 raise util.Abort(_("tag '%s' is not a local tag") % n)
5215 rev_ = nullid
5212 rev_ = nullid
5216 if not message:
5213 if not message:
5217 # we don't translate commit messages
5214 # we don't translate commit messages
5218 message = 'Removed tag %s' % ', '.join(names)
5215 message = 'Removed tag %s' % ', '.join(names)
5219 elif not opts.get('force'):
5216 elif not opts.get('force'):
5220 for n in names:
5217 for n in names:
5221 if n in repo.tags():
5218 if n in repo.tags():
5222 raise util.Abort(_("tag '%s' already exists "
5219 raise util.Abort(_("tag '%s' already exists "
5223 "(use -f to force)") % n)
5220 "(use -f to force)") % n)
5224 if not opts.get('local'):
5221 if not opts.get('local'):
5225 p1, p2 = repo.dirstate.parents()
5222 p1, p2 = repo.dirstate.parents()
5226 if p2 != nullid:
5223 if p2 != nullid:
5227 raise util.Abort(_('uncommitted merge'))
5224 raise util.Abort(_('uncommitted merge'))
5228 bheads = repo.branchheads()
5225 bheads = repo.branchheads()
5229 if not opts.get('force') and bheads and p1 not in bheads:
5226 if not opts.get('force') and bheads and p1 not in bheads:
5230 raise util.Abort(_('not at a branch head (use -f to force)'))
5227 raise util.Abort(_('not at a branch head (use -f to force)'))
5231 r = scmutil.revsingle(repo, rev_).node()
5228 r = scmutil.revsingle(repo, rev_).node()
5232
5229
5233 if not message:
5230 if not message:
5234 # we don't translate commit messages
5231 # we don't translate commit messages
5235 message = ('Added tag %s for changeset %s' %
5232 message = ('Added tag %s for changeset %s' %
5236 (', '.join(names), short(r)))
5233 (', '.join(names), short(r)))
5237
5234
5238 date = opts.get('date')
5235 date = opts.get('date')
5239 if date:
5236 if date:
5240 date = util.parsedate(date)
5237 date = util.parsedate(date)
5241
5238
5242 if opts.get('edit'):
5239 if opts.get('edit'):
5243 message = ui.edit(message, ui.username())
5240 message = ui.edit(message, ui.username())
5244
5241
5245 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5242 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5246
5243
5247 @command('tags', [], '')
5244 @command('tags', [], '')
5248 def tags(ui, repo):
5245 def tags(ui, repo):
5249 """list repository tags
5246 """list repository tags
5250
5247
5251 This lists both regular and local tags. When the -v/--verbose
5248 This lists both regular and local tags. When the -v/--verbose
5252 switch is used, a third column "local" is printed for local tags.
5249 switch is used, a third column "local" is printed for local tags.
5253
5250
5254 Returns 0 on success.
5251 Returns 0 on success.
5255 """
5252 """
5256
5253
5257 hexfunc = ui.debugflag and hex or short
5254 hexfunc = ui.debugflag and hex or short
5258 tagtype = ""
5255 tagtype = ""
5259
5256
5260 for t, n in reversed(repo.tagslist()):
5257 for t, n in reversed(repo.tagslist()):
5261 if ui.quiet:
5258 if ui.quiet:
5262 ui.write("%s\n" % t, label='tags.normal')
5259 ui.write("%s\n" % t, label='tags.normal')
5263 continue
5260 continue
5264
5261
5265 hn = hexfunc(n)
5262 hn = hexfunc(n)
5266 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5263 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5267 rev = ui.label(r, 'log.changeset')
5264 rev = ui.label(r, 'log.changeset')
5268 spaces = " " * (30 - encoding.colwidth(t))
5265 spaces = " " * (30 - encoding.colwidth(t))
5269
5266
5270 tag = ui.label(t, 'tags.normal')
5267 tag = ui.label(t, 'tags.normal')
5271 if ui.verbose:
5268 if ui.verbose:
5272 if repo.tagtype(t) == 'local':
5269 if repo.tagtype(t) == 'local':
5273 tagtype = " local"
5270 tagtype = " local"
5274 tag = ui.label(t, 'tags.local')
5271 tag = ui.label(t, 'tags.local')
5275 else:
5272 else:
5276 tagtype = ""
5273 tagtype = ""
5277 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5274 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5278
5275
5279 @command('tip',
5276 @command('tip',
5280 [('p', 'patch', None, _('show patch')),
5277 [('p', 'patch', None, _('show patch')),
5281 ('g', 'git', None, _('use git extended diff format')),
5278 ('g', 'git', None, _('use git extended diff format')),
5282 ] + templateopts,
5279 ] + templateopts,
5283 _('[-p] [-g]'))
5280 _('[-p] [-g]'))
5284 def tip(ui, repo, **opts):
5281 def tip(ui, repo, **opts):
5285 """show the tip revision
5282 """show the tip revision
5286
5283
5287 The tip revision (usually just called the tip) is the changeset
5284 The tip revision (usually just called the tip) is the changeset
5288 most recently added to the repository (and therefore the most
5285 most recently added to the repository (and therefore the most
5289 recently changed head).
5286 recently changed head).
5290
5287
5291 If you have just made a commit, that commit will be the tip. If
5288 If you have just made a commit, that commit will be the tip. If
5292 you have just pulled changes from another repository, the tip of
5289 you have just pulled changes from another repository, the tip of
5293 that repository becomes the current tip. The "tip" tag is special
5290 that repository becomes the current tip. The "tip" tag is special
5294 and cannot be renamed or assigned to a different changeset.
5291 and cannot be renamed or assigned to a different changeset.
5295
5292
5296 Returns 0 on success.
5293 Returns 0 on success.
5297 """
5294 """
5298 displayer = cmdutil.show_changeset(ui, repo, opts)
5295 displayer = cmdutil.show_changeset(ui, repo, opts)
5299 displayer.show(repo[len(repo) - 1])
5296 displayer.show(repo[len(repo) - 1])
5300 displayer.close()
5297 displayer.close()
5301
5298
5302 @command('unbundle',
5299 @command('unbundle',
5303 [('u', 'update', None,
5300 [('u', 'update', None,
5304 _('update to new branch head if changesets were unbundled'))],
5301 _('update to new branch head if changesets were unbundled'))],
5305 _('[-u] FILE...'))
5302 _('[-u] FILE...'))
5306 def unbundle(ui, repo, fname1, *fnames, **opts):
5303 def unbundle(ui, repo, fname1, *fnames, **opts):
5307 """apply one or more changegroup files
5304 """apply one or more changegroup files
5308
5305
5309 Apply one or more compressed changegroup files generated by the
5306 Apply one or more compressed changegroup files generated by the
5310 bundle command.
5307 bundle command.
5311
5308
5312 Returns 0 on success, 1 if an update has unresolved files.
5309 Returns 0 on success, 1 if an update has unresolved files.
5313 """
5310 """
5314 fnames = (fname1,) + fnames
5311 fnames = (fname1,) + fnames
5315
5312
5316 lock = repo.lock()
5313 lock = repo.lock()
5317 wc = repo['.']
5314 wc = repo['.']
5318 try:
5315 try:
5319 for fname in fnames:
5316 for fname in fnames:
5320 f = url.open(ui, fname)
5317 f = url.open(ui, fname)
5321 gen = changegroup.readbundle(f, fname)
5318 gen = changegroup.readbundle(f, fname)
5322 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5319 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5323 lock=lock)
5320 lock=lock)
5324 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5321 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5325 finally:
5322 finally:
5326 lock.release()
5323 lock.release()
5327 return postincoming(ui, repo, modheads, opts.get('update'), None)
5324 return postincoming(ui, repo, modheads, opts.get('update'), None)
5328
5325
5329 @command('^update|up|checkout|co',
5326 @command('^update|up|checkout|co',
5330 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5327 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5331 ('c', 'check', None,
5328 ('c', 'check', None,
5332 _('update across branches if no uncommitted changes')),
5329 _('update across branches if no uncommitted changes')),
5333 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5330 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5334 ('r', 'rev', '', _('revision'), _('REV'))],
5331 ('r', 'rev', '', _('revision'), _('REV'))],
5335 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5332 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5336 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5333 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5337 """update working directory (or switch revisions)
5334 """update working directory (or switch revisions)
5338
5335
5339 Update the repository's working directory to the specified
5336 Update the repository's working directory to the specified
5340 changeset. If no changeset is specified, update to the tip of the
5337 changeset. If no changeset is specified, update to the tip of the
5341 current named branch.
5338 current named branch.
5342
5339
5343 If the changeset is not a descendant of the working directory's
5340 If the changeset is not a descendant of the working directory's
5344 parent, the update is aborted. With the -c/--check option, the
5341 parent, the update is aborted. With the -c/--check option, the
5345 working directory is checked for uncommitted changes; if none are
5342 working directory is checked for uncommitted changes; if none are
5346 found, the working directory is updated to the specified
5343 found, the working directory is updated to the specified
5347 changeset.
5344 changeset.
5348
5345
5349 Update sets the working directory's parent revison to the specified
5346 Update sets the working directory's parent revison to the specified
5350 changeset (see :hg:`help parents`).
5347 changeset (see :hg:`help parents`).
5351
5348
5352 The following rules apply when the working directory contains
5349 The following rules apply when the working directory contains
5353 uncommitted changes:
5350 uncommitted changes:
5354
5351
5355 1. If neither -c/--check nor -C/--clean is specified, and if
5352 1. If neither -c/--check nor -C/--clean is specified, and if
5356 the requested changeset is an ancestor or descendant of
5353 the requested changeset is an ancestor or descendant of
5357 the working directory's parent, the uncommitted changes
5354 the working directory's parent, the uncommitted changes
5358 are merged into the requested changeset and the merged
5355 are merged into the requested changeset and the merged
5359 result is left uncommitted. If the requested changeset is
5356 result is left uncommitted. If the requested changeset is
5360 not an ancestor or descendant (that is, it is on another
5357 not an ancestor or descendant (that is, it is on another
5361 branch), the update is aborted and the uncommitted changes
5358 branch), the update is aborted and the uncommitted changes
5362 are preserved.
5359 are preserved.
5363
5360
5364 2. With the -c/--check option, the update is aborted and the
5361 2. With the -c/--check option, the update is aborted and the
5365 uncommitted changes are preserved.
5362 uncommitted changes are preserved.
5366
5363
5367 3. With the -C/--clean option, uncommitted changes are discarded and
5364 3. With the -C/--clean option, uncommitted changes are discarded and
5368 the working directory is updated to the requested changeset.
5365 the working directory is updated to the requested changeset.
5369
5366
5370 Use null as the changeset to remove the working directory (like
5367 Use null as the changeset to remove the working directory (like
5371 :hg:`clone -U`).
5368 :hg:`clone -U`).
5372
5369
5373 If you want to revert just one file to an older revision, use
5370 If you want to revert just one file to an older revision, use
5374 :hg:`revert [-r REV] NAME`.
5371 :hg:`revert [-r REV] NAME`.
5375
5372
5376 See :hg:`help dates` for a list of formats valid for -d/--date.
5373 See :hg:`help dates` for a list of formats valid for -d/--date.
5377
5374
5378 Returns 0 on success, 1 if there are unresolved files.
5375 Returns 0 on success, 1 if there are unresolved files.
5379 """
5376 """
5380 if rev and node:
5377 if rev and node:
5381 raise util.Abort(_("please specify just one revision"))
5378 raise util.Abort(_("please specify just one revision"))
5382
5379
5383 if rev is None or rev == '':
5380 if rev is None or rev == '':
5384 rev = node
5381 rev = node
5385
5382
5386 # if we defined a bookmark, we have to remember the original bookmark name
5383 # if we defined a bookmark, we have to remember the original bookmark name
5387 brev = rev
5384 brev = rev
5388 rev = scmutil.revsingle(repo, rev, rev).rev()
5385 rev = scmutil.revsingle(repo, rev, rev).rev()
5389
5386
5390 if check and clean:
5387 if check and clean:
5391 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5388 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5392
5389
5393 if check:
5390 if check:
5394 # we could use dirty() but we can ignore merge and branch trivia
5391 # we could use dirty() but we can ignore merge and branch trivia
5395 c = repo[None]
5392 c = repo[None]
5396 if c.modified() or c.added() or c.removed():
5393 if c.modified() or c.added() or c.removed():
5397 raise util.Abort(_("uncommitted local changes"))
5394 raise util.Abort(_("uncommitted local changes"))
5398
5395
5399 if date:
5396 if date:
5400 if rev is not None:
5397 if rev is not None:
5401 raise util.Abort(_("you can't specify a revision and a date"))
5398 raise util.Abort(_("you can't specify a revision and a date"))
5402 rev = cmdutil.finddate(ui, repo, date)
5399 rev = cmdutil.finddate(ui, repo, date)
5403
5400
5404 if clean or check:
5401 if clean or check:
5405 ret = hg.clean(repo, rev)
5402 ret = hg.clean(repo, rev)
5406 else:
5403 else:
5407 ret = hg.update(repo, rev)
5404 ret = hg.update(repo, rev)
5408
5405
5409 if brev in repo._bookmarks:
5406 if brev in repo._bookmarks:
5410 bookmarks.setcurrent(repo, brev)
5407 bookmarks.setcurrent(repo, brev)
5411
5408
5412 return ret
5409 return ret
5413
5410
5414 @command('verify', [])
5411 @command('verify', [])
5415 def verify(ui, repo):
5412 def verify(ui, repo):
5416 """verify the integrity of the repository
5413 """verify the integrity of the repository
5417
5414
5418 Verify the integrity of the current repository.
5415 Verify the integrity of the current repository.
5419
5416
5420 This will perform an extensive check of the repository's
5417 This will perform an extensive check of the repository's
5421 integrity, validating the hashes and checksums of each entry in
5418 integrity, validating the hashes and checksums of each entry in
5422 the changelog, manifest, and tracked files, as well as the
5419 the changelog, manifest, and tracked files, as well as the
5423 integrity of their crosslinks and indices.
5420 integrity of their crosslinks and indices.
5424
5421
5425 Returns 0 on success, 1 if errors are encountered.
5422 Returns 0 on success, 1 if errors are encountered.
5426 """
5423 """
5427 return hg.verify(repo)
5424 return hg.verify(repo)
5428
5425
5429 @command('version', [])
5426 @command('version', [])
5430 def version_(ui):
5427 def version_(ui):
5431 """output version and copyright information"""
5428 """output version and copyright information"""
5432 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5429 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5433 % util.version())
5430 % util.version())
5434 ui.status(_(
5431 ui.status(_(
5435 "(see http://mercurial.selenic.com for more information)\n"
5432 "(see http://mercurial.selenic.com for more information)\n"
5436 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5433 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5437 "This is free software; see the source for copying conditions. "
5434 "This is free software; see the source for copying conditions. "
5438 "There is NO\nwarranty; "
5435 "There is NO\nwarranty; "
5439 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5436 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5440 ))
5437 ))
5441
5438
5442 norepo = ("clone init version help debugcommands debugcomplete"
5439 norepo = ("clone init version help debugcommands debugcomplete"
5443 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5440 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5444 " debugknown debuggetbundle debugbundle")
5441 " debugknown debuggetbundle debugbundle")
5445 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5442 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5446 " debugdata debugindex debugindexdot debugrevlog")
5443 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,258 +1,256 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "purge=" >> $HGRCPATH
2 $ echo "purge=" >> $HGRCPATH
3 $ echo "graphlog=" >> $HGRCPATH
3 $ echo "graphlog=" >> $HGRCPATH
4
4
5 $ shortlog() {
5 $ shortlog() {
6 > hg glog --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
6 > hg glog --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
7 > }
7 > }
8
8
9 Test --bypass with other options
9 Test --bypass with other options
10
10
11 $ hg init repo-options
11 $ hg init repo-options
12 $ cd repo-options
12 $ cd repo-options
13 $ echo a > a
13 $ echo a > a
14 $ hg ci -Am adda
14 $ hg ci -Am adda
15 adding a
15 adding a
16 $ echo a >> a
16 $ echo a >> a
17 $ hg branch foo
17 $ hg branch foo
18 marked working directory as branch foo
18 marked working directory as branch foo
19 $ hg ci -Am changea
19 $ hg ci -Am changea
20 $ hg export . > ../test.diff
20 $ hg export . > ../test.diff
21 $ hg up null
21 $ hg up null
22 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
22 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
23
23
24 Test importing an existing revision
24 Test importing an existing revision
25
25
26 $ hg import --bypass --exact ../test.diff
26 $ hg import --bypass --exact ../test.diff
27 applying ../test.diff
27 applying ../test.diff
28 $ shortlog
28 $ shortlog
29 o 1:4e322f7ce8e3 test 0 0 - foo - changea
29 o 1:4e322f7ce8e3 test 0 0 - foo - changea
30 |
30 |
31 o 0:07f494440405 test 0 0 - default - adda
31 o 0:07f494440405 test 0 0 - default - adda
32
32
33
33
34 Test failure without --exact
34 Test failure without --exact
35
35
36 $ hg import --bypass ../test.diff
36 $ hg import --bypass ../test.diff
37 applying ../test.diff
37 applying ../test.diff
38 unable to find 'a' for patching
38 unable to find 'a' for patching
39 abort: patch failed to apply
39 abort: patch failed to apply
40 [255]
40 [255]
41 $ hg st
41 $ hg st
42 $ shortlog
42 $ shortlog
43 o 1:4e322f7ce8e3 test 0 0 - foo - changea
43 o 1:4e322f7ce8e3 test 0 0 - foo - changea
44 |
44 |
45 o 0:07f494440405 test 0 0 - default - adda
45 o 0:07f494440405 test 0 0 - default - adda
46
46
47
47
48 Test --user, --date and --message
48 Test --user, --date and --message
49
49
50 $ hg up 0
50 $ hg up 0
51 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
52 $ hg import --bypass --u test2 -d '1 0' -m patch2 ../test.diff
52 $ hg import --bypass --u test2 -d '1 0' -m patch2 ../test.diff
53 applying ../test.diff
53 applying ../test.diff
54 $ cat .hg/last-message.txt
54 $ cat .hg/last-message.txt
55 patch2 (no-eol)
55 patch2 (no-eol)
56 $ shortlog
56 $ shortlog
57 o 2:2e127d1da504 test2 1 0 - default - patch2
57 o 2:2e127d1da504 test2 1 0 - default - patch2
58 |
58 |
59 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
59 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
60 |/
60 |/
61 @ 0:07f494440405 test 0 0 - default - adda
61 @ 0:07f494440405 test 0 0 - default - adda
62
62
63 $ hg rollback -f
63 $ hg rollback -f
64 repository tip rolled back to revision 1 (undo commit)
64 repository tip rolled back to revision 1 (undo commit)
65
65
66 Test --import-branch
66 Test --import-branch
67
67
68 $ hg import --bypass --import-branch ../test.diff
68 $ hg import --bypass --import-branch ../test.diff
69 applying ../test.diff
69 applying ../test.diff
70 $ shortlog
70 $ shortlog
71 o 1:4e322f7ce8e3 test 0 0 - foo - changea
71 o 1:4e322f7ce8e3 test 0 0 - foo - changea
72 |
72 |
73 @ 0:07f494440405 test 0 0 - default - adda
73 @ 0:07f494440405 test 0 0 - default - adda
74
74
75 $ hg rollback -f
75 $ hg rollback -f
76 repository tip rolled back to revision 1 (undo commit)
76 repository tip rolled back to revision 1 (undo commit)
77
77
78 Test --strip
78 Test --strip
79
79
80 $ hg import --bypass --strip 0 - <<EOF
80 $ hg import --bypass --strip 0 - <<EOF
81 > # HG changeset patch
81 > # HG changeset patch
82 > # User test
82 > # User test
83 > # Date 0 0
83 > # Date 0 0
84 > # Branch foo
84 > # Branch foo
85 > # Node ID 4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c
85 > # Node ID 4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c
86 > # Parent 07f4944404050f47db2e5c5071e0e84e7a27bba9
86 > # Parent 07f4944404050f47db2e5c5071e0e84e7a27bba9
87 > changea
87 > changea
88 >
88 >
89 > diff -r 07f494440405 -r 4e322f7ce8e3 a
89 > diff -r 07f494440405 -r 4e322f7ce8e3 a
90 > --- a Thu Jan 01 00:00:00 1970 +0000
90 > --- a Thu Jan 01 00:00:00 1970 +0000
91 > +++ a Thu Jan 01 00:00:00 1970 +0000
91 > +++ a Thu Jan 01 00:00:00 1970 +0000
92 > @@ -1,1 +1,2 @@
92 > @@ -1,1 +1,2 @@
93 > a
93 > a
94 > +a
94 > +a
95 > EOF
95 > EOF
96 applying patch from stdin
96 applying patch from stdin
97 $ hg rollback -f
97 $ hg rollback -f
98 repository tip rolled back to revision 1 (undo commit)
98 repository tip rolled back to revision 1 (undo commit)
99
99
100 Test unsupported combinations
100 Test unsupported combinations
101
101
102 $ hg import --bypass --no-commit ../test.diff
102 $ hg import --bypass --no-commit ../test.diff
103 abort: cannot use --no-commit with --bypass
103 abort: cannot use --no-commit with --bypass
104 [255]
104 [255]
105 $ hg import --bypass --similarity 50 ../test.diff
105 $ hg import --bypass --similarity 50 ../test.diff
106 abort: cannot use --similarity with --bypass
106 abort: cannot use --similarity with --bypass
107 [255]
107 [255]
108
108
109 Test commit editor
109 Test commit editor
110
110
111 $ hg diff -c 1 > ../test.diff
111 $ hg diff -c 1 > ../test.diff
112 $ HGEDITOR=cat hg import --bypass ../test.diff
112 $ HGEDITOR=cat hg import --bypass ../test.diff
113 applying ../test.diff
113 applying ../test.diff
114
114
115
115
116 HG: Enter commit message. Lines beginning with 'HG:' are removed.
116 HG: Enter commit message. Lines beginning with 'HG:' are removed.
117 HG: Leave message empty to abort commit.
117 HG: Leave message empty to abort commit.
118 HG: --
118 HG: --
119 HG: user: test
119 HG: user: test
120 HG: branch 'default'
120 HG: branch 'default'
121 HG: changed a
121 HG: changed a
122 abort: empty commit message
122 abort: empty commit message
123 [255]
123 [255]
124
124
125 Test patch.eol is handled
125 Test patch.eol is handled
126
126
127 $ python -c 'file("a", "wb").write("a\r\n")'
127 $ python -c 'file("a", "wb").write("a\r\n")'
128 $ hg ci -m makeacrlf
128 $ hg ci -m makeacrlf
129 $ hg import -m 'should fail because of eol' --bypass ../test.diff
129 $ hg import -m 'should fail because of eol' --bypass ../test.diff
130 applying ../test.diff
130 applying ../test.diff
131 patching file a
131 patching file a
132 Hunk #1 FAILED at 0
132 Hunk #1 FAILED at 0
133 abort: patch failed to apply
133 abort: patch failed to apply
134 [255]
134 [255]
135 $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
135 $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
136 applying ../test.diff
136 applying ../test.diff
137 $ shortlog
137 $ shortlog
138 o 3:d7805b4d2cb3 test 0 0 - default - test patch.eol
138 o 3:d7805b4d2cb3 test 0 0 - default - test patch.eol
139 |
139 |
140 @ 2:872023de769d test 0 0 - default - makeacrlf
140 @ 2:872023de769d test 0 0 - default - makeacrlf
141 |
141 |
142 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
142 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
143 |/
143 |/
144 o 0:07f494440405 test 0 0 - default - adda
144 o 0:07f494440405 test 0 0 - default - adda
145
145
146
146
147 Test applying multiple patches
147 Test applying multiple patches
148
148
149 $ hg up -qC 0
149 $ hg up -qC 0
150 $ echo e > e
150 $ echo e > e
151 $ hg ci -Am adde
151 $ hg ci -Am adde
152 adding e
152 adding e
153 created new head
153 created new head
154 $ hg export . > ../patch1.diff
154 $ hg export . > ../patch1.diff
155 $ hg up -qC 1
155 $ hg up -qC 1
156 $ echo f > f
156 $ echo f > f
157 $ hg ci -Am addf
157 $ hg ci -Am addf
158 adding f
158 adding f
159 $ hg export . > ../patch2.diff
159 $ hg export . > ../patch2.diff
160 $ cd ..
160 $ cd ..
161 $ hg clone -r1 repo-options repo-multi1
161 $ hg clone -r1 repo-options repo-multi1
162 adding changesets
162 adding changesets
163 adding manifests
163 adding manifests
164 adding file changes
164 adding file changes
165 added 2 changesets with 2 changes to 1 files
165 added 2 changesets with 2 changes to 1 files
166 updating to branch foo
166 updating to branch foo
167 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
167 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
168 $ cd repo-multi1
168 $ cd repo-multi1
169 $ hg up 0
169 $ hg up 0
170 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
171 $ hg import --bypass ../patch1.diff ../patch2.diff
171 $ hg import --bypass ../patch1.diff ../patch2.diff
172 applying ../patch1.diff
172 applying ../patch1.diff
173 applying ../patch2.diff
173 applying ../patch2.diff
174 applied 16581080145e
175 $ shortlog
174 $ shortlog
176 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
175 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
177 |
176 |
178 o 2:16581080145e test 0 0 - default - adde
177 o 2:16581080145e test 0 0 - default - adde
179 |
178 |
180 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
179 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
181 |/
180 |/
182 @ 0:07f494440405 test 0 0 - default - adda
181 @ 0:07f494440405 test 0 0 - default - adda
183
182
184
183
185 Test applying multiple patches with --exact
184 Test applying multiple patches with --exact
186
185
187 $ cd ..
186 $ cd ..
188 $ hg clone -r1 repo-options repo-multi2
187 $ hg clone -r1 repo-options repo-multi2
189 adding changesets
188 adding changesets
190 adding manifests
189 adding manifests
191 adding file changes
190 adding file changes
192 added 2 changesets with 2 changes to 1 files
191 added 2 changesets with 2 changes to 1 files
193 updating to branch foo
192 updating to branch foo
194 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 $ cd repo-multi2
194 $ cd repo-multi2
196 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
195 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
197 applying ../patch1.diff
196 applying ../patch1.diff
198 applying ../patch2.diff
197 applying ../patch2.diff
199 applied 16581080145e
200 $ shortlog
198 $ shortlog
201 o 3:d60cb8989666 test 0 0 - foo - addf
199 o 3:d60cb8989666 test 0 0 - foo - addf
202 |
200 |
203 | o 2:16581080145e test 0 0 - default - adde
201 | o 2:16581080145e test 0 0 - default - adde
204 | |
202 | |
205 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
203 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
206 |/
204 |/
207 o 0:07f494440405 test 0 0 - default - adda
205 o 0:07f494440405 test 0 0 - default - adda
208
206
209
207
210 $ cd ..
208 $ cd ..
211
209
212 Test complicated patch with --exact
210 Test complicated patch with --exact
213
211
214 $ hg init repo-exact
212 $ hg init repo-exact
215 $ cd repo-exact
213 $ cd repo-exact
216 $ echo a > a
214 $ echo a > a
217 $ echo c > c
215 $ echo c > c
218 $ echo d > d
216 $ echo d > d
219 $ echo e > e
217 $ echo e > e
220 $ echo f > f
218 $ echo f > f
221 $ chmod +x f
219 $ chmod +x f
222 $ ln -s c linkc
220 $ ln -s c linkc
223 $ hg ci -Am t
221 $ hg ci -Am t
224 adding a
222 adding a
225 adding c
223 adding c
226 adding d
224 adding d
227 adding e
225 adding e
228 adding f
226 adding f
229 adding linkc
227 adding linkc
230 $ hg cp a aa1
228 $ hg cp a aa1
231 $ echo b >> a
229 $ echo b >> a
232 $ echo b > b
230 $ echo b > b
233 $ hg add b
231 $ hg add b
234 $ hg cp a aa2
232 $ hg cp a aa2
235 $ echo aa >> aa2
233 $ echo aa >> aa2
236 $ chmod +x e
234 $ chmod +x e
237 $ chmod -x f
235 $ chmod -x f
238 $ ln -s a linka
236 $ ln -s a linka
239 $ hg rm d
237 $ hg rm d
240 $ hg rm linkc
238 $ hg rm linkc
241 $ hg mv c cc
239 $ hg mv c cc
242 $ hg ci -m patch
240 $ hg ci -m patch
243 $ hg export --git . > ../test.diff
241 $ hg export --git . > ../test.diff
244 $ hg up -C null
242 $ hg up -C null
245 0 files updated, 0 files merged, 7 files removed, 0 files unresolved
243 0 files updated, 0 files merged, 7 files removed, 0 files unresolved
246 $ hg purge
244 $ hg purge
247 $ hg st
245 $ hg st
248 $ hg import --bypass --exact ../test.diff
246 $ hg import --bypass --exact ../test.diff
249 applying ../test.diff
247 applying ../test.diff
250
248
251 The patch should have matched the exported revision and generated no additional
249 The patch should have matched the exported revision and generated no additional
252 data. If not, diff both heads to debug it.
250 data. If not, diff both heads to debug it.
253
251
254 $ shortlog
252 $ shortlog
255 o 1:2978fd5c8aa4 test 0 0 - default - patch
253 o 1:2978fd5c8aa4 test 0 0 - default - patch
256 |
254 |
257 o 0:a0e19e636a43 test 0 0 - default - t
255 o 0:a0e19e636a43 test 0 0 - default - t
258
256
@@ -1,930 +1,938 b''
1 $ hg init a
1 $ hg init a
2 $ mkdir a/d1
2 $ mkdir a/d1
3 $ mkdir a/d1/d2
3 $ mkdir a/d1/d2
4 $ echo line 1 > a/a
4 $ echo line 1 > a/a
5 $ echo line 1 > a/d1/d2/a
5 $ echo line 1 > a/d1/d2/a
6 $ hg --cwd a ci -Ama
6 $ hg --cwd a ci -Ama
7 adding a
7 adding a
8 adding d1/d2/a
8 adding d1/d2/a
9
9
10 $ echo line 2 >> a/a
10 $ echo line 2 >> a/a
11 $ hg --cwd a ci -u someone -d '1 0' -m'second change'
11 $ hg --cwd a ci -u someone -d '1 0' -m'second change'
12
12
13
13
14 generate patches for the test
14 generate patches for the test
15
15
16 $ hg --cwd a export tip > exported-tip.patch
16 $ hg --cwd a export tip > exported-tip.patch
17 $ hg --cwd a diff -r0:1 > diffed-tip.patch
17 $ hg --cwd a diff -r0:1 > diffed-tip.patch
18
18
19
19
20 import exported patch
20 import exported patch
21
21
22 $ hg clone -r0 a b
22 $ hg clone -r0 a b
23 adding changesets
23 adding changesets
24 adding manifests
24 adding manifests
25 adding file changes
25 adding file changes
26 added 1 changesets with 2 changes to 2 files
26 added 1 changesets with 2 changes to 2 files
27 updating to branch default
27 updating to branch default
28 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 $ hg --cwd b import ../exported-tip.patch
29 $ hg --cwd b import ../exported-tip.patch
30 applying ../exported-tip.patch
30 applying ../exported-tip.patch
31
31
32 message and committer should be same
32 message and committer should be same
33
33
34 $ hg --cwd b tip
34 $ hg --cwd b tip
35 changeset: 1:1d4bd90af0e4
35 changeset: 1:1d4bd90af0e4
36 tag: tip
36 tag: tip
37 user: someone
37 user: someone
38 date: Thu Jan 01 00:00:01 1970 +0000
38 date: Thu Jan 01 00:00:01 1970 +0000
39 summary: second change
39 summary: second change
40
40
41 $ rm -r b
41 $ rm -r b
42
42
43
43
44 import exported patch with external patcher
44 import exported patch with external patcher
45
45
46 $ cat > dummypatch.py <<EOF
46 $ cat > dummypatch.py <<EOF
47 > print 'patching file a'
47 > print 'patching file a'
48 > file('a', 'wb').write('line2\n')
48 > file('a', 'wb').write('line2\n')
49 > EOF
49 > EOF
50 $ chmod +x dummypatch.py
50 $ chmod +x dummypatch.py
51 $ hg clone -r0 a b
51 $ hg clone -r0 a b
52 adding changesets
52 adding changesets
53 adding manifests
53 adding manifests
54 adding file changes
54 adding file changes
55 added 1 changesets with 2 changes to 2 files
55 added 1 changesets with 2 changes to 2 files
56 updating to branch default
56 updating to branch default
57 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
58 $ hg --config ui.patch='python ../dummypatch.py' --cwd b import ../exported-tip.patch
58 $ hg --config ui.patch='python ../dummypatch.py' --cwd b import ../exported-tip.patch
59 applying ../exported-tip.patch
59 applying ../exported-tip.patch
60 $ cat b/a
60 $ cat b/a
61 line2
61 line2
62 $ rm -r b
62 $ rm -r b
63
63
64
64
65 import of plain diff should fail without message
65 import of plain diff should fail without message
66
66
67 $ hg clone -r0 a b
67 $ hg clone -r0 a b
68 adding changesets
68 adding changesets
69 adding manifests
69 adding manifests
70 adding file changes
70 adding file changes
71 added 1 changesets with 2 changes to 2 files
71 added 1 changesets with 2 changes to 2 files
72 updating to branch default
72 updating to branch default
73 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
73 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 $ hg --cwd b import ../diffed-tip.patch
74 $ hg --cwd b import ../diffed-tip.patch
75 applying ../diffed-tip.patch
75 applying ../diffed-tip.patch
76 abort: empty commit message
76 abort: empty commit message
77 [255]
77 [255]
78 $ rm -r b
78 $ rm -r b
79
79
80
80
81 import of plain diff should be ok with message
81 import of plain diff should be ok with message
82
82
83 $ hg clone -r0 a b
83 $ hg clone -r0 a b
84 adding changesets
84 adding changesets
85 adding manifests
85 adding manifests
86 adding file changes
86 adding file changes
87 added 1 changesets with 2 changes to 2 files
87 added 1 changesets with 2 changes to 2 files
88 updating to branch default
88 updating to branch default
89 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
89 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 $ hg --cwd b import -mpatch ../diffed-tip.patch
90 $ hg --cwd b import -mpatch ../diffed-tip.patch
91 applying ../diffed-tip.patch
91 applying ../diffed-tip.patch
92 $ rm -r b
92 $ rm -r b
93
93
94
94
95 import of plain diff with specific date and user
95 import of plain diff with specific date and user
96
96
97 $ hg clone -r0 a b
97 $ hg clone -r0 a b
98 adding changesets
98 adding changesets
99 adding manifests
99 adding manifests
100 adding file changes
100 adding file changes
101 added 1 changesets with 2 changes to 2 files
101 added 1 changesets with 2 changes to 2 files
102 updating to branch default
102 updating to branch default
103 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
104 $ hg --cwd b import -mpatch -d '1 0' -u 'user@nowhere.net' ../diffed-tip.patch
104 $ hg --cwd b import -mpatch -d '1 0' -u 'user@nowhere.net' ../diffed-tip.patch
105 applying ../diffed-tip.patch
105 applying ../diffed-tip.patch
106 $ hg -R b tip -pv
106 $ hg -R b tip -pv
107 changeset: 1:ca68f19f3a40
107 changeset: 1:ca68f19f3a40
108 tag: tip
108 tag: tip
109 user: user@nowhere.net
109 user: user@nowhere.net
110 date: Thu Jan 01 00:00:01 1970 +0000
110 date: Thu Jan 01 00:00:01 1970 +0000
111 files: a
111 files: a
112 description:
112 description:
113 patch
113 patch
114
114
115
115
116 diff -r 80971e65b431 -r ca68f19f3a40 a
116 diff -r 80971e65b431 -r ca68f19f3a40 a
117 --- a/a Thu Jan 01 00:00:00 1970 +0000
117 --- a/a Thu Jan 01 00:00:00 1970 +0000
118 +++ b/a Thu Jan 01 00:00:01 1970 +0000
118 +++ b/a Thu Jan 01 00:00:01 1970 +0000
119 @@ -1,1 +1,2 @@
119 @@ -1,1 +1,2 @@
120 line 1
120 line 1
121 +line 2
121 +line 2
122
122
123 $ rm -r b
123 $ rm -r b
124
124
125
125
126 import of plain diff should be ok with --no-commit
126 import of plain diff should be ok with --no-commit
127
127
128 $ hg clone -r0 a b
128 $ hg clone -r0 a b
129 adding changesets
129 adding changesets
130 adding manifests
130 adding manifests
131 adding file changes
131 adding file changes
132 added 1 changesets with 2 changes to 2 files
132 added 1 changesets with 2 changes to 2 files
133 updating to branch default
133 updating to branch default
134 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
134 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 $ hg --cwd b import --no-commit ../diffed-tip.patch
135 $ hg --cwd b import --no-commit ../diffed-tip.patch
136 applying ../diffed-tip.patch
136 applying ../diffed-tip.patch
137 $ hg --cwd b diff --nodates
137 $ hg --cwd b diff --nodates
138 diff -r 80971e65b431 a
138 diff -r 80971e65b431 a
139 --- a/a
139 --- a/a
140 +++ b/a
140 +++ b/a
141 @@ -1,1 +1,2 @@
141 @@ -1,1 +1,2 @@
142 line 1
142 line 1
143 +line 2
143 +line 2
144 $ rm -r b
144 $ rm -r b
145
145
146
146
147 import of malformed plain diff should fail
147 import of malformed plain diff should fail
148
148
149 $ hg clone -r0 a b
149 $ hg clone -r0 a b
150 adding changesets
150 adding changesets
151 adding manifests
151 adding manifests
152 adding file changes
152 adding file changes
153 added 1 changesets with 2 changes to 2 files
153 added 1 changesets with 2 changes to 2 files
154 updating to branch default
154 updating to branch default
155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
155 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
156 $ sed 's/1,1/foo/' < diffed-tip.patch > broken.patch
156 $ sed 's/1,1/foo/' < diffed-tip.patch > broken.patch
157 $ hg --cwd b import -mpatch ../broken.patch
157 $ hg --cwd b import -mpatch ../broken.patch
158 applying ../broken.patch
158 applying ../broken.patch
159 abort: bad hunk #1
159 abort: bad hunk #1
160 [255]
160 [255]
161 $ rm -r b
161 $ rm -r b
162
162
163
163
164 hg -R repo import
164 hg -R repo import
165 put the clone in a subdir - having a directory named "a"
165 put the clone in a subdir - having a directory named "a"
166 used to hide a bug.
166 used to hide a bug.
167
167
168 $ mkdir dir
168 $ mkdir dir
169 $ hg clone -r0 a dir/b
169 $ hg clone -r0 a dir/b
170 adding changesets
170 adding changesets
171 adding manifests
171 adding manifests
172 adding file changes
172 adding file changes
173 added 1 changesets with 2 changes to 2 files
173 added 1 changesets with 2 changes to 2 files
174 updating to branch default
174 updating to branch default
175 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
176 $ cd dir
176 $ cd dir
177 $ hg -R b import ../exported-tip.patch
177 $ hg -R b import ../exported-tip.patch
178 applying ../exported-tip.patch
178 applying ../exported-tip.patch
179 $ cd ..
179 $ cd ..
180 $ rm -r dir
180 $ rm -r dir
181
181
182
182
183 import from stdin
183 import from stdin
184
184
185 $ hg clone -r0 a b
185 $ hg clone -r0 a b
186 adding changesets
186 adding changesets
187 adding manifests
187 adding manifests
188 adding file changes
188 adding file changes
189 added 1 changesets with 2 changes to 2 files
189 added 1 changesets with 2 changes to 2 files
190 updating to branch default
190 updating to branch default
191 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 $ hg --cwd b import - < exported-tip.patch
192 $ hg --cwd b import - < exported-tip.patch
193 applying patch from stdin
193 applying patch from stdin
194 $ rm -r b
194 $ rm -r b
195
195
196
196
197 import two patches in one stream
197 import two patches in one stream
198
198
199 $ hg init b
199 $ hg init b
200 $ hg --cwd a export 0:tip | hg --cwd b import -
200 $ hg --cwd a export 0:tip | hg --cwd b import -
201 applying patch from stdin
201 applying patch from stdin
202 applied 80971e65b431
203 $ hg --cwd a id
202 $ hg --cwd a id
204 1d4bd90af0e4 tip
203 1d4bd90af0e4 tip
205 $ hg --cwd b id
204 $ hg --cwd b id
206 1d4bd90af0e4 tip
205 1d4bd90af0e4 tip
207 $ rm -r b
206 $ rm -r b
208
207
209
208
210 override commit message
209 override commit message
211
210
212 $ hg clone -r0 a b
211 $ hg clone -r0 a b
213 adding changesets
212 adding changesets
214 adding manifests
213 adding manifests
215 adding file changes
214 adding file changes
216 added 1 changesets with 2 changes to 2 files
215 added 1 changesets with 2 changes to 2 files
217 updating to branch default
216 updating to branch default
218 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
217 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 $ hg --cwd b import -m 'override' - < exported-tip.patch
218 $ hg --cwd b import -m 'override' - < exported-tip.patch
220 applying patch from stdin
219 applying patch from stdin
221 $ hg --cwd b tip | grep override
220 $ hg --cwd b tip | grep override
222 summary: override
221 summary: override
223 $ rm -r b
222 $ rm -r b
224
223
225 $ cat > mkmsg.py <<EOF
224 $ cat > mkmsg.py <<EOF
226 > import email.Message, sys
225 > import email.Message, sys
227 > msg = email.Message.Message()
226 > msg = email.Message.Message()
228 > patch = open(sys.argv[1], 'rb').read()
227 > patch = open(sys.argv[1], 'rb').read()
229 > msg.set_payload('email commit message\n' + patch)
228 > msg.set_payload('email commit message\n' + patch)
230 > msg['Subject'] = 'email patch'
229 > msg['Subject'] = 'email patch'
231 > msg['From'] = 'email patcher'
230 > msg['From'] = 'email patcher'
232 > sys.stdout.write(msg.as_string())
231 > sys.stdout.write(msg.as_string())
233 > EOF
232 > EOF
234
233
235
234
236 plain diff in email, subject, message body
235 plain diff in email, subject, message body
237
236
238 $ hg clone -r0 a b
237 $ hg clone -r0 a b
239 adding changesets
238 adding changesets
240 adding manifests
239 adding manifests
241 adding file changes
240 adding file changes
242 added 1 changesets with 2 changes to 2 files
241 added 1 changesets with 2 changes to 2 files
243 updating to branch default
242 updating to branch default
244 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
243 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
245 $ python mkmsg.py diffed-tip.patch > msg.patch
244 $ python mkmsg.py diffed-tip.patch > msg.patch
246 $ hg --cwd b import ../msg.patch
245 $ hg --cwd b import ../msg.patch
247 applying ../msg.patch
246 applying ../msg.patch
248 $ hg --cwd b tip | grep email
247 $ hg --cwd b tip | grep email
249 user: email patcher
248 user: email patcher
250 summary: email patch
249 summary: email patch
251 $ rm -r b
250 $ rm -r b
252
251
253
252
254 plain diff in email, no subject, message body
253 plain diff in email, no subject, message body
255
254
256 $ hg clone -r0 a b
255 $ hg clone -r0 a b
257 adding changesets
256 adding changesets
258 adding manifests
257 adding manifests
259 adding file changes
258 adding file changes
260 added 1 changesets with 2 changes to 2 files
259 added 1 changesets with 2 changes to 2 files
261 updating to branch default
260 updating to branch default
262 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
261 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 $ grep -v '^Subject:' msg.patch | hg --cwd b import -
262 $ grep -v '^Subject:' msg.patch | hg --cwd b import -
264 applying patch from stdin
263 applying patch from stdin
265 $ rm -r b
264 $ rm -r b
266
265
267
266
268 plain diff in email, subject, no message body
267 plain diff in email, subject, no message body
269
268
270 $ hg clone -r0 a b
269 $ hg clone -r0 a b
271 adding changesets
270 adding changesets
272 adding manifests
271 adding manifests
273 adding file changes
272 adding file changes
274 added 1 changesets with 2 changes to 2 files
273 added 1 changesets with 2 changes to 2 files
275 updating to branch default
274 updating to branch default
276 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
275 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
277 $ grep -v '^email ' msg.patch | hg --cwd b import -
276 $ grep -v '^email ' msg.patch | hg --cwd b import -
278 applying patch from stdin
277 applying patch from stdin
279 $ rm -r b
278 $ rm -r b
280
279
281
280
282 plain diff in email, no subject, no message body, should fail
281 plain diff in email, no subject, no message body, should fail
283
282
284 $ hg clone -r0 a b
283 $ hg clone -r0 a b
285 adding changesets
284 adding changesets
286 adding manifests
285 adding manifests
287 adding file changes
286 adding file changes
288 added 1 changesets with 2 changes to 2 files
287 added 1 changesets with 2 changes to 2 files
289 updating to branch default
288 updating to branch default
290 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
289 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
291 $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
290 $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
292 applying patch from stdin
291 applying patch from stdin
293 abort: empty commit message
292 abort: empty commit message
294 [255]
293 [255]
295 $ rm -r b
294 $ rm -r b
296
295
297
296
298 hg export in email, should use patch header
297 hg export in email, should use patch header
299
298
300 $ hg clone -r0 a b
299 $ hg clone -r0 a b
301 adding changesets
300 adding changesets
302 adding manifests
301 adding manifests
303 adding file changes
302 adding file changes
304 added 1 changesets with 2 changes to 2 files
303 added 1 changesets with 2 changes to 2 files
305 updating to branch default
304 updating to branch default
306 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
305 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
307 $ python mkmsg.py exported-tip.patch | hg --cwd b import -
306 $ python mkmsg.py exported-tip.patch | hg --cwd b import -
308 applying patch from stdin
307 applying patch from stdin
309 $ hg --cwd b tip | grep second
308 $ hg --cwd b tip | grep second
310 summary: second change
309 summary: second change
311 $ rm -r b
310 $ rm -r b
312
311
313
312
314 subject: duplicate detection, removal of [PATCH]
313 subject: duplicate detection, removal of [PATCH]
315 The '---' tests the gitsendmail handling without proper mail headers
314 The '---' tests the gitsendmail handling without proper mail headers
316
315
317 $ cat > mkmsg2.py <<EOF
316 $ cat > mkmsg2.py <<EOF
318 > import email.Message, sys
317 > import email.Message, sys
319 > msg = email.Message.Message()
318 > msg = email.Message.Message()
320 > patch = open(sys.argv[1], 'rb').read()
319 > patch = open(sys.argv[1], 'rb').read()
321 > msg.set_payload('email patch\n\nnext line\n---\n' + patch)
320 > msg.set_payload('email patch\n\nnext line\n---\n' + patch)
322 > msg['Subject'] = '[PATCH] email patch'
321 > msg['Subject'] = '[PATCH] email patch'
323 > msg['From'] = 'email patcher'
322 > msg['From'] = 'email patcher'
324 > sys.stdout.write(msg.as_string())
323 > sys.stdout.write(msg.as_string())
325 > EOF
324 > EOF
326
325
327
326
328 plain diff in email, [PATCH] subject, message body with subject
327 plain diff in email, [PATCH] subject, message body with subject
329
328
330 $ hg clone -r0 a b
329 $ hg clone -r0 a b
331 adding changesets
330 adding changesets
332 adding manifests
331 adding manifests
333 adding file changes
332 adding file changes
334 added 1 changesets with 2 changes to 2 files
333 added 1 changesets with 2 changes to 2 files
335 updating to branch default
334 updating to branch default
336 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
335 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
337 $ python mkmsg2.py diffed-tip.patch | hg --cwd b import -
336 $ python mkmsg2.py diffed-tip.patch | hg --cwd b import -
338 applying patch from stdin
337 applying patch from stdin
339 $ hg --cwd b tip --template '{desc}\n'
338 $ hg --cwd b tip --template '{desc}\n'
340 email patch
339 email patch
341
340
342 next line
341 next line
343 ---
342 ---
344 $ rm -r b
343 $ rm -r b
345
344
346
345
347 Issue963: Parent of working dir incorrect after import of multiple
346 Issue963: Parent of working dir incorrect after import of multiple
348 patches and rollback
347 patches and rollback
349
348
350 We weren't backing up the correct dirstate file when importing many
349 We weren't backing up the correct dirstate file when importing many
351 patches: import patch1 patch2; rollback
350 patches: import patch1 patch2; rollback
352
351
353 $ echo line 3 >> a/a
352 $ echo line 3 >> a/a
354 $ hg --cwd a ci -m'third change'
353 $ hg --cwd a ci -m'third change'
355 $ hg --cwd a export -o '../patch%R' 1 2
354 $ hg --cwd a export -o '../patch%R' 1 2
356 $ hg clone -qr0 a b
355 $ hg clone -qr0 a b
357 $ hg --cwd b parents --template 'parent: {rev}\n'
356 $ hg --cwd b parents --template 'parent: {rev}\n'
358 parent: 0
357 parent: 0
359 $ hg --cwd b import ../patch1 ../patch2
358 $ hg --cwd b import -v ../patch1 ../patch2
360 applying ../patch1
359 applying ../patch1
360 patching file a
361 a
362 created 1d4bd90af0e4
361 applying ../patch2
363 applying ../patch2
362 applied 1d4bd90af0e4
364 patching file a
365 a
366 created 6d019af21222
363 $ hg --cwd b rollback
367 $ hg --cwd b rollback
364 repository tip rolled back to revision 1 (undo commit)
368 repository tip rolled back to revision 1 (undo commit)
365 working directory now based on revision 1
369 working directory now based on revision 1
366 $ hg --cwd b parents --template 'parent: {rev}\n'
370 $ hg --cwd b parents --template 'parent: {rev}\n'
367 parent: 1
371 parent: 1
368 $ rm -r b
372 $ rm -r b
369
373
370
374
371 importing a patch in a subdirectory failed at the commit stage
375 importing a patch in a subdirectory failed at the commit stage
372
376
373 $ echo line 2 >> a/d1/d2/a
377 $ echo line 2 >> a/d1/d2/a
374 $ hg --cwd a ci -u someoneelse -d '1 0' -m'subdir change'
378 $ hg --cwd a ci -u someoneelse -d '1 0' -m'subdir change'
375
379
376 hg import in a subdirectory
380 hg import in a subdirectory
377
381
378 $ hg clone -r0 a b
382 $ hg clone -r0 a b
379 adding changesets
383 adding changesets
380 adding manifests
384 adding manifests
381 adding file changes
385 adding file changes
382 added 1 changesets with 2 changes to 2 files
386 added 1 changesets with 2 changes to 2 files
383 updating to branch default
387 updating to branch default
384 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
388 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
385 $ hg --cwd a export tip > tmp
389 $ hg --cwd a export tip > tmp
386 $ sed -e 's/d1\/d2\///' < tmp > subdir-tip.patch
390 $ sed -e 's/d1\/d2\///' < tmp > subdir-tip.patch
387 $ dir=`pwd`
391 $ dir=`pwd`
388 $ cd b/d1/d2 2>&1 > /dev/null
392 $ cd b/d1/d2 2>&1 > /dev/null
389 $ hg import ../../../subdir-tip.patch
393 $ hg import ../../../subdir-tip.patch
390 applying ../../../subdir-tip.patch
394 applying ../../../subdir-tip.patch
391 $ cd "$dir"
395 $ cd "$dir"
392
396
393 message should be 'subdir change'
397 message should be 'subdir change'
394 committer should be 'someoneelse'
398 committer should be 'someoneelse'
395
399
396 $ hg --cwd b tip
400 $ hg --cwd b tip
397 changeset: 1:3577f5aea227
401 changeset: 1:3577f5aea227
398 tag: tip
402 tag: tip
399 user: someoneelse
403 user: someoneelse
400 date: Thu Jan 01 00:00:01 1970 +0000
404 date: Thu Jan 01 00:00:01 1970 +0000
401 summary: subdir change
405 summary: subdir change
402
406
403
407
404 should be empty
408 should be empty
405
409
406 $ hg --cwd b status
410 $ hg --cwd b status
407
411
408
412
409 Test fuzziness (ambiguous patch location, fuzz=2)
413 Test fuzziness (ambiguous patch location, fuzz=2)
410
414
411 $ hg init fuzzy
415 $ hg init fuzzy
412 $ cd fuzzy
416 $ cd fuzzy
413 $ echo line1 > a
417 $ echo line1 > a
414 $ echo line0 >> a
418 $ echo line0 >> a
415 $ echo line3 >> a
419 $ echo line3 >> a
416 $ hg ci -Am adda
420 $ hg ci -Am adda
417 adding a
421 adding a
418 $ echo line1 > a
422 $ echo line1 > a
419 $ echo line2 >> a
423 $ echo line2 >> a
420 $ echo line0 >> a
424 $ echo line0 >> a
421 $ echo line3 >> a
425 $ echo line3 >> a
422 $ hg ci -m change a
426 $ hg ci -m change a
423 $ hg export tip > fuzzy-tip.patch
427 $ hg export tip > fuzzy-tip.patch
424 $ hg up -C 0
428 $ hg up -C 0
425 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
429 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 $ echo line1 > a
430 $ echo line1 > a
427 $ echo line0 >> a
431 $ echo line0 >> a
428 $ echo line1 >> a
432 $ echo line1 >> a
429 $ echo line0 >> a
433 $ echo line0 >> a
430 $ hg ci -m brancha
434 $ hg ci -m brancha
431 created new head
435 created new head
432 $ hg import --no-commit -v fuzzy-tip.patch
436 $ hg import --no-commit -v fuzzy-tip.patch
433 applying fuzzy-tip.patch
437 applying fuzzy-tip.patch
434 patching file a
438 patching file a
435 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
439 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
440 applied to working directory
436 $ hg revert -a
441 $ hg revert -a
437 reverting a
442 reverting a
438
443
439
444
440 import with --no-commit should have written .hg/last-message.txt
445 import with --no-commit should have written .hg/last-message.txt
441
446
442 $ cat .hg/last-message.txt
447 $ cat .hg/last-message.txt
443 change (no-eol)
448 change (no-eol)
444
449
445
450
446 test fuzziness with eol=auto
451 test fuzziness with eol=auto
447
452
448 $ hg --config patch.eol=auto import --no-commit -v fuzzy-tip.patch
453 $ hg --config patch.eol=auto import --no-commit -v fuzzy-tip.patch
449 applying fuzzy-tip.patch
454 applying fuzzy-tip.patch
450 patching file a
455 patching file a
451 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
456 Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
457 applied to working directory
452 $ cd ..
458 $ cd ..
453
459
454
460
455 Test hunk touching empty files (issue906)
461 Test hunk touching empty files (issue906)
456
462
457 $ hg init empty
463 $ hg init empty
458 $ cd empty
464 $ cd empty
459 $ touch a
465 $ touch a
460 $ touch b1
466 $ touch b1
461 $ touch c1
467 $ touch c1
462 $ echo d > d
468 $ echo d > d
463 $ hg ci -Am init
469 $ hg ci -Am init
464 adding a
470 adding a
465 adding b1
471 adding b1
466 adding c1
472 adding c1
467 adding d
473 adding d
468 $ echo a > a
474 $ echo a > a
469 $ echo b > b1
475 $ echo b > b1
470 $ hg mv b1 b2
476 $ hg mv b1 b2
471 $ echo c > c1
477 $ echo c > c1
472 $ hg copy c1 c2
478 $ hg copy c1 c2
473 $ rm d
479 $ rm d
474 $ touch d
480 $ touch d
475 $ hg diff --git
481 $ hg diff --git
476 diff --git a/a b/a
482 diff --git a/a b/a
477 --- a/a
483 --- a/a
478 +++ b/a
484 +++ b/a
479 @@ -0,0 +1,1 @@
485 @@ -0,0 +1,1 @@
480 +a
486 +a
481 diff --git a/b1 b/b2
487 diff --git a/b1 b/b2
482 rename from b1
488 rename from b1
483 rename to b2
489 rename to b2
484 --- a/b1
490 --- a/b1
485 +++ b/b2
491 +++ b/b2
486 @@ -0,0 +1,1 @@
492 @@ -0,0 +1,1 @@
487 +b
493 +b
488 diff --git a/c1 b/c1
494 diff --git a/c1 b/c1
489 --- a/c1
495 --- a/c1
490 +++ b/c1
496 +++ b/c1
491 @@ -0,0 +1,1 @@
497 @@ -0,0 +1,1 @@
492 +c
498 +c
493 diff --git a/c1 b/c2
499 diff --git a/c1 b/c2
494 copy from c1
500 copy from c1
495 copy to c2
501 copy to c2
496 --- a/c1
502 --- a/c1
497 +++ b/c2
503 +++ b/c2
498 @@ -0,0 +1,1 @@
504 @@ -0,0 +1,1 @@
499 +c
505 +c
500 diff --git a/d b/d
506 diff --git a/d b/d
501 --- a/d
507 --- a/d
502 +++ b/d
508 +++ b/d
503 @@ -1,1 +0,0 @@
509 @@ -1,1 +0,0 @@
504 -d
510 -d
505 $ hg ci -m empty
511 $ hg ci -m empty
506 $ hg export --git tip > empty.diff
512 $ hg export --git tip > empty.diff
507 $ hg up -C 0
513 $ hg up -C 0
508 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
514 4 files updated, 0 files merged, 2 files removed, 0 files unresolved
509 $ hg import empty.diff
515 $ hg import empty.diff
510 applying empty.diff
516 applying empty.diff
511 $ for name in a b1 b2 c1 c2 d; do
517 $ for name in a b1 b2 c1 c2 d; do
512 > echo % $name file
518 > echo % $name file
513 > test -f $name && cat $name
519 > test -f $name && cat $name
514 > done
520 > done
515 % a file
521 % a file
516 a
522 a
517 % b1 file
523 % b1 file
518 % b2 file
524 % b2 file
519 b
525 b
520 % c1 file
526 % c1 file
521 c
527 c
522 % c2 file
528 % c2 file
523 c
529 c
524 % d file
530 % d file
525 $ cd ..
531 $ cd ..
526
532
527
533
528 Test importing a patch ending with a binary file removal
534 Test importing a patch ending with a binary file removal
529
535
530 $ hg init binaryremoval
536 $ hg init binaryremoval
531 $ cd binaryremoval
537 $ cd binaryremoval
532 $ echo a > a
538 $ echo a > a
533 $ python -c "file('b', 'wb').write('a\x00b')"
539 $ python -c "file('b', 'wb').write('a\x00b')"
534 $ hg ci -Am addall
540 $ hg ci -Am addall
535 adding a
541 adding a
536 adding b
542 adding b
537 $ hg rm a
543 $ hg rm a
538 $ hg rm b
544 $ hg rm b
539 $ hg st
545 $ hg st
540 R a
546 R a
541 R b
547 R b
542 $ hg ci -m remove
548 $ hg ci -m remove
543 $ hg export --git . > remove.diff
549 $ hg export --git . > remove.diff
544 $ cat remove.diff | grep git
550 $ cat remove.diff | grep git
545 diff --git a/a b/a
551 diff --git a/a b/a
546 diff --git a/b b/b
552 diff --git a/b b/b
547 $ hg up -C 0
553 $ hg up -C 0
548 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
554 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
549 $ hg import remove.diff
555 $ hg import remove.diff
550 applying remove.diff
556 applying remove.diff
551 $ hg manifest
557 $ hg manifest
552 $ cd ..
558 $ cd ..
553
559
554
560
555 Issue927: test update+rename with common name
561 Issue927: test update+rename with common name
556
562
557 $ hg init t
563 $ hg init t
558 $ cd t
564 $ cd t
559 $ touch a
565 $ touch a
560 $ hg ci -Am t
566 $ hg ci -Am t
561 adding a
567 adding a
562 $ echo a > a
568 $ echo a > a
563
569
564 Here, bfile.startswith(afile)
570 Here, bfile.startswith(afile)
565
571
566 $ hg copy a a2
572 $ hg copy a a2
567 $ hg ci -m copya
573 $ hg ci -m copya
568 $ hg export --git tip > copy.diff
574 $ hg export --git tip > copy.diff
569 $ hg up -C 0
575 $ hg up -C 0
570 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
576 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
571 $ hg import copy.diff
577 $ hg import copy.diff
572 applying copy.diff
578 applying copy.diff
573
579
574 a should contain an 'a'
580 a should contain an 'a'
575
581
576 $ cat a
582 $ cat a
577 a
583 a
578
584
579 and a2 should have duplicated it
585 and a2 should have duplicated it
580
586
581 $ cat a2
587 $ cat a2
582 a
588 a
583 $ cd ..
589 $ cd ..
584
590
585
591
586 test -p0
592 test -p0
587
593
588 $ hg init p0
594 $ hg init p0
589 $ cd p0
595 $ cd p0
590 $ echo a > a
596 $ echo a > a
591 $ hg ci -Am t
597 $ hg ci -Am t
592 adding a
598 adding a
593 $ hg import -p0 - << EOF
599 $ hg import -p0 - << EOF
594 > foobar
600 > foobar
595 > --- a Sat Apr 12 22:43:58 2008 -0400
601 > --- a Sat Apr 12 22:43:58 2008 -0400
596 > +++ a Sat Apr 12 22:44:05 2008 -0400
602 > +++ a Sat Apr 12 22:44:05 2008 -0400
597 > @@ -1,1 +1,1 @@
603 > @@ -1,1 +1,1 @@
598 > -a
604 > -a
599 > +bb
605 > +bb
600 > EOF
606 > EOF
601 applying patch from stdin
607 applying patch from stdin
602 $ hg status
608 $ hg status
603 $ cat a
609 $ cat a
604 bb
610 bb
605 $ cd ..
611 $ cd ..
606
612
607
613
608 test paths outside repo root
614 test paths outside repo root
609
615
610 $ mkdir outside
616 $ mkdir outside
611 $ touch outside/foo
617 $ touch outside/foo
612 $ hg init inside
618 $ hg init inside
613 $ cd inside
619 $ cd inside
614 $ hg import - <<EOF
620 $ hg import - <<EOF
615 > diff --git a/a b/b
621 > diff --git a/a b/b
616 > rename from ../outside/foo
622 > rename from ../outside/foo
617 > rename to bar
623 > rename to bar
618 > EOF
624 > EOF
619 applying patch from stdin
625 applying patch from stdin
620 abort: path contains illegal component: ../outside/foo
626 abort: path contains illegal component: ../outside/foo
621 [255]
627 [255]
622 $ cd ..
628 $ cd ..
623
629
624
630
625 test import with similarity and git and strip (issue295 et al.)
631 test import with similarity and git and strip (issue295 et al.)
626
632
627 $ hg init sim
633 $ hg init sim
628 $ cd sim
634 $ cd sim
629 $ echo 'this is a test' > a
635 $ echo 'this is a test' > a
630 $ hg ci -Ama
636 $ hg ci -Ama
631 adding a
637 adding a
632 $ cat > ../rename.diff <<EOF
638 $ cat > ../rename.diff <<EOF
633 > diff --git a/foo/a b/foo/a
639 > diff --git a/foo/a b/foo/a
634 > deleted file mode 100644
640 > deleted file mode 100644
635 > --- a/foo/a
641 > --- a/foo/a
636 > +++ /dev/null
642 > +++ /dev/null
637 > @@ -1,1 +0,0 @@
643 > @@ -1,1 +0,0 @@
638 > -this is a test
644 > -this is a test
639 > diff --git a/foo/b b/foo/b
645 > diff --git a/foo/b b/foo/b
640 > new file mode 100644
646 > new file mode 100644
641 > --- /dev/null
647 > --- /dev/null
642 > +++ b/foo/b
648 > +++ b/foo/b
643 > @@ -0,0 +1,2 @@
649 > @@ -0,0 +1,2 @@
644 > +this is a test
650 > +this is a test
645 > +foo
651 > +foo
646 > EOF
652 > EOF
647 $ hg import --no-commit -v -s 1 ../rename.diff -p2
653 $ hg import --no-commit -v -s 1 ../rename.diff -p2
648 applying ../rename.diff
654 applying ../rename.diff
649 patching file a
655 patching file a
650 patching file b
656 patching file b
651 removing a
657 removing a
652 adding b
658 adding b
653 recording removal of a as rename to b (88% similar)
659 recording removal of a as rename to b (88% similar)
660 applied to working directory
654 $ hg st -C
661 $ hg st -C
655 A b
662 A b
656 a
663 a
657 R a
664 R a
658 $ hg revert -a
665 $ hg revert -a
659 undeleting a
666 undeleting a
660 forgetting b
667 forgetting b
661 $ rm b
668 $ rm b
662 $ hg import --no-commit -v -s 100 ../rename.diff -p2
669 $ hg import --no-commit -v -s 100 ../rename.diff -p2
663 applying ../rename.diff
670 applying ../rename.diff
664 patching file a
671 patching file a
665 patching file b
672 patching file b
666 removing a
673 removing a
667 adding b
674 adding b
675 applied to working directory
668 $ hg st -C
676 $ hg st -C
669 A b
677 A b
670 R a
678 R a
671 $ cd ..
679 $ cd ..
672
680
673
681
674 Issue1495: add empty file from the end of patch
682 Issue1495: add empty file from the end of patch
675
683
676 $ hg init addemptyend
684 $ hg init addemptyend
677 $ cd addemptyend
685 $ cd addemptyend
678 $ touch a
686 $ touch a
679 $ hg addremove
687 $ hg addremove
680 adding a
688 adding a
681 $ hg ci -m "commit"
689 $ hg ci -m "commit"
682 $ cat > a.patch <<EOF
690 $ cat > a.patch <<EOF
683 > diff --git a/a b/a
691 > diff --git a/a b/a
684 > --- a/a
692 > --- a/a
685 > +++ b/a
693 > +++ b/a
686 > @@ -0,0 +1,1 @@
694 > @@ -0,0 +1,1 @@
687 > +a
695 > +a
688 > diff --git a/b b/b
696 > diff --git a/b b/b
689 > new file mode 100644
697 > new file mode 100644
690 > EOF
698 > EOF
691 $ hg import --no-commit a.patch
699 $ hg import --no-commit a.patch
692 applying a.patch
700 applying a.patch
693 $ cd ..
701 $ cd ..
694
702
695
703
696 create file when source is not /dev/null
704 create file when source is not /dev/null
697
705
698 $ cat > create.patch <<EOF
706 $ cat > create.patch <<EOF
699 > diff -Naur proj-orig/foo proj-new/foo
707 > diff -Naur proj-orig/foo proj-new/foo
700 > --- proj-orig/foo 1969-12-31 16:00:00.000000000 -0800
708 > --- proj-orig/foo 1969-12-31 16:00:00.000000000 -0800
701 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
709 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
702 > @@ -0,0 +1,1 @@
710 > @@ -0,0 +1,1 @@
703 > +a
711 > +a
704 > EOF
712 > EOF
705
713
706 some people have patches like the following too
714 some people have patches like the following too
707
715
708 $ cat > create2.patch <<EOF
716 $ cat > create2.patch <<EOF
709 > diff -Naur proj-orig/foo proj-new/foo
717 > diff -Naur proj-orig/foo proj-new/foo
710 > --- proj-orig/foo.orig 1969-12-31 16:00:00.000000000 -0800
718 > --- proj-orig/foo.orig 1969-12-31 16:00:00.000000000 -0800
711 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
719 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
712 > @@ -0,0 +1,1 @@
720 > @@ -0,0 +1,1 @@
713 > +a
721 > +a
714 > EOF
722 > EOF
715 $ hg init oddcreate
723 $ hg init oddcreate
716 $ cd oddcreate
724 $ cd oddcreate
717 $ hg import --no-commit ../create.patch
725 $ hg import --no-commit ../create.patch
718 applying ../create.patch
726 applying ../create.patch
719 $ cat foo
727 $ cat foo
720 a
728 a
721 $ rm foo
729 $ rm foo
722 $ hg revert foo
730 $ hg revert foo
723 $ hg import --no-commit ../create2.patch
731 $ hg import --no-commit ../create2.patch
724 applying ../create2.patch
732 applying ../create2.patch
725 $ cat foo
733 $ cat foo
726 a
734 a
727
735
728
736
729 Issue1859: first line mistaken for email headers
737 Issue1859: first line mistaken for email headers
730
738
731 $ hg init emailconfusion
739 $ hg init emailconfusion
732 $ cd emailconfusion
740 $ cd emailconfusion
733 $ cat > a.patch <<EOF
741 $ cat > a.patch <<EOF
734 > module: summary
742 > module: summary
735 >
743 >
736 > description
744 > description
737 >
745 >
738 >
746 >
739 > diff -r 000000000000 -r 9b4c1e343b55 test.txt
747 > diff -r 000000000000 -r 9b4c1e343b55 test.txt
740 > --- /dev/null
748 > --- /dev/null
741 > +++ b/a
749 > +++ b/a
742 > @@ -0,0 +1,1 @@
750 > @@ -0,0 +1,1 @@
743 > +a
751 > +a
744 > EOF
752 > EOF
745 $ hg import -d '0 0' a.patch
753 $ hg import -d '0 0' a.patch
746 applying a.patch
754 applying a.patch
747 $ hg parents -v
755 $ hg parents -v
748 changeset: 0:5a681217c0ad
756 changeset: 0:5a681217c0ad
749 tag: tip
757 tag: tip
750 user: test
758 user: test
751 date: Thu Jan 01 00:00:00 1970 +0000
759 date: Thu Jan 01 00:00:00 1970 +0000
752 files: a
760 files: a
753 description:
761 description:
754 module: summary
762 module: summary
755
763
756 description
764 description
757
765
758
766
759 $ cd ..
767 $ cd ..
760
768
761
769
762 --- in commit message
770 --- in commit message
763
771
764 $ hg init commitconfusion
772 $ hg init commitconfusion
765 $ cd commitconfusion
773 $ cd commitconfusion
766 $ cat > a.patch <<EOF
774 $ cat > a.patch <<EOF
767 > module: summary
775 > module: summary
768 >
776 >
769 > --- description
777 > --- description
770 >
778 >
771 > diff --git a/a b/a
779 > diff --git a/a b/a
772 > new file mode 100644
780 > new file mode 100644
773 > --- /dev/null
781 > --- /dev/null
774 > +++ b/a
782 > +++ b/a
775 > @@ -0,0 +1,1 @@
783 > @@ -0,0 +1,1 @@
776 > +a
784 > +a
777 > EOF
785 > EOF
778 > hg import -d '0 0' a.patch
786 > hg import -d '0 0' a.patch
779 > hg parents -v
787 > hg parents -v
780 > cd ..
788 > cd ..
781 >
789 >
782 > echo '% tricky header splitting'
790 > echo '% tricky header splitting'
783 > cat > trickyheaders.patch <<EOF
791 > cat > trickyheaders.patch <<EOF
784 > From: User A <user@a>
792 > From: User A <user@a>
785 > Subject: [PATCH] from: tricky!
793 > Subject: [PATCH] from: tricky!
786 >
794 >
787 > # HG changeset patch
795 > # HG changeset patch
788 > # User User B
796 > # User User B
789 > # Date 1266264441 18000
797 > # Date 1266264441 18000
790 > # Branch stable
798 > # Branch stable
791 > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
799 > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
792 > # Parent 0000000000000000000000000000000000000000
800 > # Parent 0000000000000000000000000000000000000000
793 > from: tricky!
801 > from: tricky!
794 >
802 >
795 > That is not a header.
803 > That is not a header.
796 >
804 >
797 > diff -r 000000000000 -r f2be6a1170ac foo
805 > diff -r 000000000000 -r f2be6a1170ac foo
798 > --- /dev/null
806 > --- /dev/null
799 > +++ b/foo
807 > +++ b/foo
800 > @@ -0,0 +1,1 @@
808 > @@ -0,0 +1,1 @@
801 > +foo
809 > +foo
802 > EOF
810 > EOF
803 applying a.patch
811 applying a.patch
804 changeset: 0:f34d9187897d
812 changeset: 0:f34d9187897d
805 tag: tip
813 tag: tip
806 user: test
814 user: test
807 date: Thu Jan 01 00:00:00 1970 +0000
815 date: Thu Jan 01 00:00:00 1970 +0000
808 files: a
816 files: a
809 description:
817 description:
810 module: summary
818 module: summary
811
819
812
820
813 % tricky header splitting
821 % tricky header splitting
814
822
815 $ hg init trickyheaders
823 $ hg init trickyheaders
816 $ cd trickyheaders
824 $ cd trickyheaders
817 $ hg import -d '0 0' ../trickyheaders.patch
825 $ hg import -d '0 0' ../trickyheaders.patch
818 applying ../trickyheaders.patch
826 applying ../trickyheaders.patch
819 $ hg export --git tip
827 $ hg export --git tip
820 # HG changeset patch
828 # HG changeset patch
821 # User User B
829 # User User B
822 # Date 0 0
830 # Date 0 0
823 # Node ID eb56ab91903632294ac504838508cb370c0901d2
831 # Node ID eb56ab91903632294ac504838508cb370c0901d2
824 # Parent 0000000000000000000000000000000000000000
832 # Parent 0000000000000000000000000000000000000000
825 from: tricky!
833 from: tricky!
826
834
827 That is not a header.
835 That is not a header.
828
836
829 diff --git a/foo b/foo
837 diff --git a/foo b/foo
830 new file mode 100644
838 new file mode 100644
831 --- /dev/null
839 --- /dev/null
832 +++ b/foo
840 +++ b/foo
833 @@ -0,0 +1,1 @@
841 @@ -0,0 +1,1 @@
834 +foo
842 +foo
835 $ cd ..
843 $ cd ..
836
844
837
845
838 Issue2102: hg export and hg import speak different languages
846 Issue2102: hg export and hg import speak different languages
839
847
840 $ hg init issue2102
848 $ hg init issue2102
841 $ cd issue2102
849 $ cd issue2102
842 $ mkdir -p src/cmd/gc
850 $ mkdir -p src/cmd/gc
843 $ touch src/cmd/gc/mksys.bash
851 $ touch src/cmd/gc/mksys.bash
844 $ hg ci -Am init
852 $ hg ci -Am init
845 adding src/cmd/gc/mksys.bash
853 adding src/cmd/gc/mksys.bash
846 $ hg import - <<EOF
854 $ hg import - <<EOF
847 > # HG changeset patch
855 > # HG changeset patch
848 > # User Rob Pike
856 > # User Rob Pike
849 > # Date 1216685449 25200
857 > # Date 1216685449 25200
850 > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
858 > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
851 > # Parent 93d10138ad8df586827ca90b4ddb5033e21a3a84
859 > # Parent 93d10138ad8df586827ca90b4ddb5033e21a3a84
852 > help management of empty pkg and lib directories in perforce
860 > help management of empty pkg and lib directories in perforce
853 >
861 >
854 > R=gri
862 > R=gri
855 > DELTA=4 (4 added, 0 deleted, 0 changed)
863 > DELTA=4 (4 added, 0 deleted, 0 changed)
856 > OCL=13328
864 > OCL=13328
857 > CL=13328
865 > CL=13328
858 >
866 >
859 > diff --git a/lib/place-holder b/lib/place-holder
867 > diff --git a/lib/place-holder b/lib/place-holder
860 > new file mode 100644
868 > new file mode 100644
861 > --- /dev/null
869 > --- /dev/null
862 > +++ b/lib/place-holder
870 > +++ b/lib/place-holder
863 > @@ -0,0 +1,2 @@
871 > @@ -0,0 +1,2 @@
864 > +perforce does not maintain empty directories.
872 > +perforce does not maintain empty directories.
865 > +this file helps.
873 > +this file helps.
866 > diff --git a/pkg/place-holder b/pkg/place-holder
874 > diff --git a/pkg/place-holder b/pkg/place-holder
867 > new file mode 100644
875 > new file mode 100644
868 > --- /dev/null
876 > --- /dev/null
869 > +++ b/pkg/place-holder
877 > +++ b/pkg/place-holder
870 > @@ -0,0 +1,2 @@
878 > @@ -0,0 +1,2 @@
871 > +perforce does not maintain empty directories.
879 > +perforce does not maintain empty directories.
872 > +this file helps.
880 > +this file helps.
873 > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
881 > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
874 > old mode 100644
882 > old mode 100644
875 > new mode 100755
883 > new mode 100755
876 > EOF
884 > EOF
877 applying patch from stdin
885 applying patch from stdin
878 $ hg sum
886 $ hg sum
879 parent: 1:d59915696727 tip
887 parent: 1:d59915696727 tip
880 help management of empty pkg and lib directories in perforce
888 help management of empty pkg and lib directories in perforce
881 branch: default
889 branch: default
882 commit: (clean)
890 commit: (clean)
883 update: (current)
891 update: (current)
884 $ hg diff --git -c tip
892 $ hg diff --git -c tip
885 diff --git a/lib/place-holder b/lib/place-holder
893 diff --git a/lib/place-holder b/lib/place-holder
886 new file mode 100644
894 new file mode 100644
887 --- /dev/null
895 --- /dev/null
888 +++ b/lib/place-holder
896 +++ b/lib/place-holder
889 @@ -0,0 +1,2 @@
897 @@ -0,0 +1,2 @@
890 +perforce does not maintain empty directories.
898 +perforce does not maintain empty directories.
891 +this file helps.
899 +this file helps.
892 diff --git a/pkg/place-holder b/pkg/place-holder
900 diff --git a/pkg/place-holder b/pkg/place-holder
893 new file mode 100644
901 new file mode 100644
894 --- /dev/null
902 --- /dev/null
895 +++ b/pkg/place-holder
903 +++ b/pkg/place-holder
896 @@ -0,0 +1,2 @@
904 @@ -0,0 +1,2 @@
897 +perforce does not maintain empty directories.
905 +perforce does not maintain empty directories.
898 +this file helps.
906 +this file helps.
899 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
907 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
900 old mode 100644
908 old mode 100644
901 new mode 100755
909 new mode 100755
902 $ cd ..
910 $ cd ..
903
911
904
912
905 diff lines looking like headers
913 diff lines looking like headers
906
914
907 $ hg init difflineslikeheaders
915 $ hg init difflineslikeheaders
908 $ cd difflineslikeheaders
916 $ cd difflineslikeheaders
909 $ echo a >a
917 $ echo a >a
910 $ echo b >b
918 $ echo b >b
911 $ echo c >c
919 $ echo c >c
912 $ hg ci -Am1
920 $ hg ci -Am1
913 adding a
921 adding a
914 adding b
922 adding b
915 adding c
923 adding c
916
924
917 $ echo "key: value" >>a
925 $ echo "key: value" >>a
918 $ echo "key: value" >>b
926 $ echo "key: value" >>b
919 $ echo "foo" >>c
927 $ echo "foo" >>c
920 $ hg ci -m2
928 $ hg ci -m2
921
929
922 $ hg up -C 0
930 $ hg up -C 0
923 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
931 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
924 $ hg diff --git -c1 >want
932 $ hg diff --git -c1 >want
925 $ hg diff -c1 | hg import --no-commit -
933 $ hg diff -c1 | hg import --no-commit -
926 applying patch from stdin
934 applying patch from stdin
927 $ hg diff --git >have
935 $ hg diff --git >have
928 $ diff want have
936 $ diff want have
929 $ cd ..
937 $ cd ..
930
938
@@ -1,76 +1,77 b''
1
1
2 $ cat > writepatterns.py <<EOF
2 $ cat > writepatterns.py <<EOF
3 > import sys
3 > import sys
4 >
4 >
5 > path = sys.argv[1]
5 > path = sys.argv[1]
6 > patterns = sys.argv[2:]
6 > patterns = sys.argv[2:]
7 >
7 >
8 > fp = file(path, 'wb')
8 > fp = file(path, 'wb')
9 > for pattern in patterns:
9 > for pattern in patterns:
10 > count = int(pattern[0:-1])
10 > count = int(pattern[0:-1])
11 > char = pattern[-1] + '\n'
11 > char = pattern[-1] + '\n'
12 > fp.write(char*count)
12 > fp.write(char*count)
13 > fp.close()
13 > fp.close()
14 > EOF
14 > EOF
15
15
16 prepare repo
16 prepare repo
17
17
18 $ hg init a
18 $ hg init a
19 $ cd a
19 $ cd a
20
20
21 These initial lines of Xs were not in the original file used to generate
21 These initial lines of Xs were not in the original file used to generate
22 the patch. So all the patch hunks need to be applied to a constant offset
22 the patch. So all the patch hunks need to be applied to a constant offset
23 within this file. If the offset isn't tracked then the hunks can be
23 within this file. If the offset isn't tracked then the hunks can be
24 applied to the wrong lines of this file.
24 applied to the wrong lines of this file.
25
25
26 $ python ../writepatterns.py a 34X 10A 1B 10A 1C 10A 1B 10A 1D 10A 1B 10A 1E 10A 1B 10A
26 $ python ../writepatterns.py a 34X 10A 1B 10A 1C 10A 1B 10A 1D 10A 1B 10A 1E 10A 1B 10A
27 $ hg commit -Am adda
27 $ hg commit -Am adda
28 adding a
28 adding a
29
29
30 This is a cleaner patch generated via diff
30 This is a cleaner patch generated via diff
31 In this case it reproduces the problem when
31 In this case it reproduces the problem when
32 the output of hg export does not
32 the output of hg export does not
33 import patch
33 import patch
34
34
35 $ hg import -v -m 'b' -d '2 0' - <<EOF
35 $ hg import -v -m 'b' -d '2 0' - <<EOF
36 > --- a/a 2009-12-08 19:26:17.000000000 -0800
36 > --- a/a 2009-12-08 19:26:17.000000000 -0800
37 > +++ b/a 2009-12-08 19:26:17.000000000 -0800
37 > +++ b/a 2009-12-08 19:26:17.000000000 -0800
38 > @@ -9,7 +9,7 @@
38 > @@ -9,7 +9,7 @@
39 > A
39 > A
40 > A
40 > A
41 > B
41 > B
42 > -A
42 > -A
43 > +a
43 > +a
44 > A
44 > A
45 > A
45 > A
46 > A
46 > A
47 > @@ -53,7 +53,7 @@
47 > @@ -53,7 +53,7 @@
48 > A
48 > A
49 > A
49 > A
50 > B
50 > B
51 > -A
51 > -A
52 > +a
52 > +a
53 > A
53 > A
54 > A
54 > A
55 > A
55 > A
56 > @@ -75,7 +75,7 @@
56 > @@ -75,7 +75,7 @@
57 > A
57 > A
58 > A
58 > A
59 > B
59 > B
60 > -A
60 > -A
61 > +a
61 > +a
62 > A
62 > A
63 > A
63 > A
64 > A
64 > A
65 > EOF
65 > EOF
66 applying patch from stdin
66 applying patch from stdin
67 patching file a
67 patching file a
68 Hunk #1 succeeded at 43 (offset 34 lines).
68 Hunk #1 succeeded at 43 (offset 34 lines).
69 Hunk #2 succeeded at 87 (offset 34 lines).
69 Hunk #2 succeeded at 87 (offset 34 lines).
70 Hunk #3 succeeded at 109 (offset 34 lines).
70 Hunk #3 succeeded at 109 (offset 34 lines).
71 a
71 a
72 created 189885cecb41
72
73
73 compare imported changes against reference file
74 compare imported changes against reference file
74
75
75 $ python ../writepatterns.py aref 34X 10A 1B 1a 9A 1C 10A 1B 10A 1D 10A 1B 1a 9A 1E 10A 1B 1a 9A
76 $ python ../writepatterns.py aref 34X 10A 1B 1a 9A 1C 10A 1B 10A 1D 10A 1B 1a 9A 1E 10A 1B 1a 9A
76 $ diff aref a
77 $ diff aref a
@@ -1,89 +1,89 b''
1 $ cat > patchtool.py <<EOF
1 $ cat > patchtool.py <<EOF
2 > import sys
2 > import sys
3 > print 'Using custom patch'
3 > print 'Using custom patch'
4 > if '--binary' in sys.argv:
4 > if '--binary' in sys.argv:
5 > print '--binary found !'
5 > print '--binary found !'
6 > EOF
6 > EOF
7
7
8 $ echo "[ui]" >> $HGRCPATH
8 $ echo "[ui]" >> $HGRCPATH
9 $ echo "patch=python ../patchtool.py" >> $HGRCPATH
9 $ echo "patch=python ../patchtool.py" >> $HGRCPATH
10
10
11 $ hg init a
11 $ hg init a
12 $ cd a
12 $ cd a
13 $ echo a > a
13 $ echo a > a
14 $ hg commit -Ama -d '1 0'
14 $ hg commit -Ama -d '1 0'
15 adding a
15 adding a
16 $ echo b >> a
16 $ echo b >> a
17 $ hg commit -Amb -d '2 0'
17 $ hg commit -Amb -d '2 0'
18 $ cd ..
18 $ cd ..
19
19
20 This test checks that:
20 This test checks that:
21 - custom patch commands with arguments actually work
21 - custom patch commands with arguments actually work
22 - patch code does not try to add weird arguments like
22 - patch code does not try to add weird arguments like
23 --binary when custom patch commands are used. For instance
23 --binary when custom patch commands are used. For instance
24 --binary is added by default under win32.
24 --binary is added by default under win32.
25
25
26 check custom patch options are honored
26 check custom patch options are honored
27
27
28 $ hg --cwd a export -o ../a.diff tip
28 $ hg --cwd a export -o ../a.diff tip
29 $ hg clone -r 0 a b
29 $ hg clone -r 0 a b
30 adding changesets
30 adding changesets
31 adding manifests
31 adding manifests
32 adding file changes
32 adding file changes
33 added 1 changesets with 1 changes to 1 files
33 added 1 changesets with 1 changes to 1 files
34 updating to branch default
34 updating to branch default
35 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
35 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
36
36
37 $ hg --cwd b import -v ../a.diff
37 $ hg --cwd b import -v ../a.diff
38 applying ../a.diff
38 applying ../a.diff
39 Using custom patch
39 Using custom patch
40
40 applied to working directory
41
41
42 Issue2417: hg import with # comments in description
42 Issue2417: hg import with # comments in description
43
43
44 Prepare source repo and patch:
44 Prepare source repo and patch:
45
45
46 $ rm $HGRCPATH
46 $ rm $HGRCPATH
47 $ hg init c
47 $ hg init c
48 $ cd c
48 $ cd c
49 $ printf "a\rc" > a
49 $ printf "a\rc" > a
50 $ hg ci -A -m 0 a -d '0 0'
50 $ hg ci -A -m 0 a -d '0 0'
51 $ printf "a\rb\rc" > a
51 $ printf "a\rb\rc" > a
52 $ cat << eof > log
52 $ cat << eof > log
53 > first line which can't start with '# '
53 > first line which can't start with '# '
54 > # second line is a comment but that shouldn't be a problem.
54 > # second line is a comment but that shouldn't be a problem.
55 > A patch marker like this was more problematic even after d7452292f9d3:
55 > A patch marker like this was more problematic even after d7452292f9d3:
56 > # HG changeset patch
56 > # HG changeset patch
57 > # User lines looks like this - but it _is_ just a comment
57 > # User lines looks like this - but it _is_ just a comment
58 > eof
58 > eof
59 $ hg ci -l log -d '0 0'
59 $ hg ci -l log -d '0 0'
60 $ hg export -o p 1
60 $ hg export -o p 1
61 $ cd ..
61 $ cd ..
62
62
63 Clone and apply patch:
63 Clone and apply patch:
64
64
65 $ hg clone -r 0 c d
65 $ hg clone -r 0 c d
66 adding changesets
66 adding changesets
67 adding manifests
67 adding manifests
68 adding file changes
68 adding file changes
69 added 1 changesets with 1 changes to 1 files
69 added 1 changesets with 1 changes to 1 files
70 updating to branch default
70 updating to branch default
71 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
71 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
72 $ cd d
72 $ cd d
73 $ hg import ../c/p
73 $ hg import ../c/p
74 applying ../c/p
74 applying ../c/p
75 $ hg log -v -r 1
75 $ hg log -v -r 1
76 changeset: 1:cd0bde79c428
76 changeset: 1:cd0bde79c428
77 tag: tip
77 tag: tip
78 user: test
78 user: test
79 date: Thu Jan 01 00:00:00 1970 +0000
79 date: Thu Jan 01 00:00:00 1970 +0000
80 files: a
80 files: a
81 description:
81 description:
82 first line which can't start with '# '
82 first line which can't start with '# '
83 # second line is a comment but that shouldn't be a problem.
83 # second line is a comment but that shouldn't be a problem.
84 A patch marker like this was more problematic even after d7452292f9d3:
84 A patch marker like this was more problematic even after d7452292f9d3:
85 # HG changeset patch
85 # HG changeset patch
86 # User lines looks like this - but it _is_ just a comment
86 # User lines looks like this - but it _is_ just a comment
87
87
88
88
89 $ cd ..
89 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now