##// END OF EJS Templates
import: wrap a transaction around the whole command...
Greg Ward -
r15198:62dc0e7a default
parent child Browse files
Show More
@@ -1,5443 +1,5450 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 base = opts["base"]
3264 base = opts["base"]
3265 strip = opts["strip"]
3265 strip = opts["strip"]
3266 wlock = lock = None
3266 wlock = lock = tr = 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, None)
3279 return (None, None)
3280 msg = _('applied 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
3338 # backups an up-to-date file.
3339 repo.dirstate.write()
3340 else:
3337 else:
3341 if opts.get('exact') or opts.get('import_branch'):
3338 if opts.get('exact') or opts.get('import_branch'):
3342 branch = branch or 'default'
3339 branch = branch or 'default'
3343 else:
3340 else:
3344 branch = p1.branch()
3341 branch = p1.branch()
3345 store = patch.filestore()
3342 store = patch.filestore()
3346 try:
3343 try:
3347 files = set()
3344 files = set()
3348 try:
3345 try:
3349 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3346 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3350 files, eolmode=None)
3347 files, eolmode=None)
3351 except patch.PatchError, e:
3348 except patch.PatchError, e:
3352 raise util.Abort(str(e))
3349 raise util.Abort(str(e))
3353 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3350 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3354 message,
3351 message,
3355 opts.get('user') or user,
3352 opts.get('user') or user,
3356 opts.get('date') or date,
3353 opts.get('date') or date,
3357 branch, files, store,
3354 branch, files, store,
3358 editor=cmdutil.commiteditor)
3355 editor=cmdutil.commiteditor)
3359 repo.savecommitmessage(memctx.description())
3356 repo.savecommitmessage(memctx.description())
3360 n = memctx.commit()
3357 n = memctx.commit()
3361 checkexact(repo, n, nodeid)
3358 checkexact(repo, n, nodeid)
3362 finally:
3359 finally:
3363 store.close()
3360 store.close()
3364 if n:
3361 if n:
3365 msg = _('created %s') % short(n)
3362 msg = _('created %s') % short(n)
3366 return (msg, n)
3363 return (msg, n)
3367 finally:
3364 finally:
3368 os.unlink(tmpname)
3365 os.unlink(tmpname)
3369
3366
3370 try:
3367 try:
3371 wlock = repo.wlock()
3368 wlock = repo.wlock()
3372 lock = repo.lock()
3369 lock = repo.lock()
3370 tr = repo.transaction('import')
3373 parents = repo.parents()
3371 parents = repo.parents()
3374 for patchurl in patches:
3372 for patchurl in patches:
3375 if patchurl == '-':
3373 if patchurl == '-':
3376 ui.status(_('applying patch from stdin\n'))
3374 ui.status(_('applying patch from stdin\n'))
3377 patchfile = ui.fin
3375 patchfile = ui.fin
3378 patchurl = 'stdin' # for error message
3376 patchurl = 'stdin' # for error message
3379 else:
3377 else:
3380 patchurl = os.path.join(base, patchurl)
3378 patchurl = os.path.join(base, patchurl)
3381 ui.status(_('applying %s\n') % patchurl)
3379 ui.status(_('applying %s\n') % patchurl)
3382 patchfile = url.open(ui, patchurl)
3380 patchfile = url.open(ui, patchurl)
3383
3381
3384 haspatch = False
3382 haspatch = False
3385 for hunk in patch.split(patchfile):
3383 for hunk in patch.split(patchfile):
3386 (msg, node) = tryone(ui, hunk, parents)
3384 (msg, node) = tryone(ui, hunk, parents)
3387 if msg:
3385 if msg:
3388 haspatch = True
3386 haspatch = True
3389 ui.note(msg + '\n')
3387 ui.note(msg + '\n')
3390 if update or opts.get('exact'):
3388 if update or opts.get('exact'):
3391 parents = repo.parents()
3389 parents = repo.parents()
3392 else:
3390 else:
3393 parents = [repo[node]]
3391 parents = [repo[node]]
3394
3392
3395 if not haspatch:
3393 if not haspatch:
3396 raise util.Abort(_('%s: no diffs found') % patchurl)
3394 raise util.Abort(_('%s: no diffs found') % patchurl)
3397
3395
3396 tr.close()
3398 if msgs:
3397 if msgs:
3399 repo.savecommitmessage('\n* * *\n'.join(msgs))
3398 repo.savecommitmessage('\n* * *\n'.join(msgs))
3399 except:
3400 # wlock.release() indirectly calls dirstate.write(): since
3401 # we're crashing, we do not want to change the working dir
3402 # parent after all, so make sure it writes nothing
3403 repo.dirstate.invalidate()
3404 raise
3400 finally:
3405 finally:
3406 if tr:
3407 tr.release()
3401 release(lock, wlock)
3408 release(lock, wlock)
3402
3409
3403 @command('incoming|in',
3410 @command('incoming|in',
3404 [('f', 'force', None,
3411 [('f', 'force', None,
3405 _('run even if remote repository is unrelated')),
3412 _('run even if remote repository is unrelated')),
3406 ('n', 'newest-first', None, _('show newest record first')),
3413 ('n', 'newest-first', None, _('show newest record first')),
3407 ('', 'bundle', '',
3414 ('', 'bundle', '',
3408 _('file to store the bundles into'), _('FILE')),
3415 _('file to store the bundles into'), _('FILE')),
3409 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3416 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3410 ('B', 'bookmarks', False, _("compare bookmarks")),
3417 ('B', 'bookmarks', False, _("compare bookmarks")),
3411 ('b', 'branch', [],
3418 ('b', 'branch', [],
3412 _('a specific branch you would like to pull'), _('BRANCH')),
3419 _('a specific branch you would like to pull'), _('BRANCH')),
3413 ] + logopts + remoteopts + subrepoopts,
3420 ] + logopts + remoteopts + subrepoopts,
3414 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3421 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3415 def incoming(ui, repo, source="default", **opts):
3422 def incoming(ui, repo, source="default", **opts):
3416 """show new changesets found in source
3423 """show new changesets found in source
3417
3424
3418 Show new changesets found in the specified path/URL or the default
3425 Show new changesets found in the specified path/URL or the default
3419 pull location. These are the changesets that would have been pulled
3426 pull location. These are the changesets that would have been pulled
3420 if a pull at the time you issued this command.
3427 if a pull at the time you issued this command.
3421
3428
3422 For remote repository, using --bundle avoids downloading the
3429 For remote repository, using --bundle avoids downloading the
3423 changesets twice if the incoming is followed by a pull.
3430 changesets twice if the incoming is followed by a pull.
3424
3431
3425 See pull for valid source format details.
3432 See pull for valid source format details.
3426
3433
3427 Returns 0 if there are incoming changes, 1 otherwise.
3434 Returns 0 if there are incoming changes, 1 otherwise.
3428 """
3435 """
3429 if opts.get('bundle') and opts.get('subrepos'):
3436 if opts.get('bundle') and opts.get('subrepos'):
3430 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3437 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3431
3438
3432 if opts.get('bookmarks'):
3439 if opts.get('bookmarks'):
3433 source, branches = hg.parseurl(ui.expandpath(source),
3440 source, branches = hg.parseurl(ui.expandpath(source),
3434 opts.get('branch'))
3441 opts.get('branch'))
3435 other = hg.peer(repo, opts, source)
3442 other = hg.peer(repo, opts, source)
3436 if 'bookmarks' not in other.listkeys('namespaces'):
3443 if 'bookmarks' not in other.listkeys('namespaces'):
3437 ui.warn(_("remote doesn't support bookmarks\n"))
3444 ui.warn(_("remote doesn't support bookmarks\n"))
3438 return 0
3445 return 0
3439 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3446 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3440 return bookmarks.diff(ui, repo, other)
3447 return bookmarks.diff(ui, repo, other)
3441
3448
3442 repo._subtoppath = ui.expandpath(source)
3449 repo._subtoppath = ui.expandpath(source)
3443 try:
3450 try:
3444 return hg.incoming(ui, repo, source, opts)
3451 return hg.incoming(ui, repo, source, opts)
3445 finally:
3452 finally:
3446 del repo._subtoppath
3453 del repo._subtoppath
3447
3454
3448
3455
3449 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3456 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3450 def init(ui, dest=".", **opts):
3457 def init(ui, dest=".", **opts):
3451 """create a new repository in the given directory
3458 """create a new repository in the given directory
3452
3459
3453 Initialize a new repository in the given directory. If the given
3460 Initialize a new repository in the given directory. If the given
3454 directory does not exist, it will be created.
3461 directory does not exist, it will be created.
3455
3462
3456 If no directory is given, the current directory is used.
3463 If no directory is given, the current directory is used.
3457
3464
3458 It is possible to specify an ``ssh://`` URL as the destination.
3465 It is possible to specify an ``ssh://`` URL as the destination.
3459 See :hg:`help urls` for more information.
3466 See :hg:`help urls` for more information.
3460
3467
3461 Returns 0 on success.
3468 Returns 0 on success.
3462 """
3469 """
3463 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3470 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3464
3471
3465 @command('locate',
3472 @command('locate',
3466 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3473 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3467 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3474 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3468 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3475 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3469 ] + walkopts,
3476 ] + walkopts,
3470 _('[OPTION]... [PATTERN]...'))
3477 _('[OPTION]... [PATTERN]...'))
3471 def locate(ui, repo, *pats, **opts):
3478 def locate(ui, repo, *pats, **opts):
3472 """locate files matching specific patterns
3479 """locate files matching specific patterns
3473
3480
3474 Print files under Mercurial control in the working directory whose
3481 Print files under Mercurial control in the working directory whose
3475 names match the given patterns.
3482 names match the given patterns.
3476
3483
3477 By default, this command searches all directories in the working
3484 By default, this command searches all directories in the working
3478 directory. To search just the current directory and its
3485 directory. To search just the current directory and its
3479 subdirectories, use "--include .".
3486 subdirectories, use "--include .".
3480
3487
3481 If no patterns are given to match, this command prints the names
3488 If no patterns are given to match, this command prints the names
3482 of all files under Mercurial control in the working directory.
3489 of all files under Mercurial control in the working directory.
3483
3490
3484 If you want to feed the output of this command into the "xargs"
3491 If you want to feed the output of this command into the "xargs"
3485 command, use the -0 option to both this command and "xargs". This
3492 command, use the -0 option to both this command and "xargs". This
3486 will avoid the problem of "xargs" treating single filenames that
3493 will avoid the problem of "xargs" treating single filenames that
3487 contain whitespace as multiple filenames.
3494 contain whitespace as multiple filenames.
3488
3495
3489 Returns 0 if a match is found, 1 otherwise.
3496 Returns 0 if a match is found, 1 otherwise.
3490 """
3497 """
3491 end = opts.get('print0') and '\0' or '\n'
3498 end = opts.get('print0') and '\0' or '\n'
3492 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3499 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3493
3500
3494 ret = 1
3501 ret = 1
3495 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3502 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3496 m.bad = lambda x, y: False
3503 m.bad = lambda x, y: False
3497 for abs in repo[rev].walk(m):
3504 for abs in repo[rev].walk(m):
3498 if not rev and abs not in repo.dirstate:
3505 if not rev and abs not in repo.dirstate:
3499 continue
3506 continue
3500 if opts.get('fullpath'):
3507 if opts.get('fullpath'):
3501 ui.write(repo.wjoin(abs), end)
3508 ui.write(repo.wjoin(abs), end)
3502 else:
3509 else:
3503 ui.write(((pats and m.rel(abs)) or abs), end)
3510 ui.write(((pats and m.rel(abs)) or abs), end)
3504 ret = 0
3511 ret = 0
3505
3512
3506 return ret
3513 return ret
3507
3514
3508 @command('^log|history',
3515 @command('^log|history',
3509 [('f', 'follow', None,
3516 [('f', 'follow', None,
3510 _('follow changeset history, or file history across copies and renames')),
3517 _('follow changeset history, or file history across copies and renames')),
3511 ('', 'follow-first', None,
3518 ('', 'follow-first', None,
3512 _('only follow the first parent of merge changesets')),
3519 _('only follow the first parent of merge changesets')),
3513 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3520 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3514 ('C', 'copies', None, _('show copied files')),
3521 ('C', 'copies', None, _('show copied files')),
3515 ('k', 'keyword', [],
3522 ('k', 'keyword', [],
3516 _('do case-insensitive search for a given text'), _('TEXT')),
3523 _('do case-insensitive search for a given text'), _('TEXT')),
3517 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3524 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3518 ('', 'removed', None, _('include revisions where files were removed')),
3525 ('', 'removed', None, _('include revisions where files were removed')),
3519 ('m', 'only-merges', None, _('show only merges')),
3526 ('m', 'only-merges', None, _('show only merges')),
3520 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3527 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3521 ('', 'only-branch', [],
3528 ('', 'only-branch', [],
3522 _('show only changesets within the given named branch (DEPRECATED)'),
3529 _('show only changesets within the given named branch (DEPRECATED)'),
3523 _('BRANCH')),
3530 _('BRANCH')),
3524 ('b', 'branch', [],
3531 ('b', 'branch', [],
3525 _('show changesets within the given named branch'), _('BRANCH')),
3532 _('show changesets within the given named branch'), _('BRANCH')),
3526 ('P', 'prune', [],
3533 ('P', 'prune', [],
3527 _('do not display revision or any of its ancestors'), _('REV')),
3534 _('do not display revision or any of its ancestors'), _('REV')),
3528 ('', 'hidden', False, _('show hidden changesets')),
3535 ('', 'hidden', False, _('show hidden changesets')),
3529 ] + logopts + walkopts,
3536 ] + logopts + walkopts,
3530 _('[OPTION]... [FILE]'))
3537 _('[OPTION]... [FILE]'))
3531 def log(ui, repo, *pats, **opts):
3538 def log(ui, repo, *pats, **opts):
3532 """show revision history of entire repository or files
3539 """show revision history of entire repository or files
3533
3540
3534 Print the revision history of the specified files or the entire
3541 Print the revision history of the specified files or the entire
3535 project.
3542 project.
3536
3543
3537 If no revision range is specified, the default is ``tip:0`` unless
3544 If no revision range is specified, the default is ``tip:0`` unless
3538 --follow is set, in which case the working directory parent is
3545 --follow is set, in which case the working directory parent is
3539 used as the starting revision.
3546 used as the starting revision.
3540
3547
3541 File history is shown without following rename or copy history of
3548 File history is shown without following rename or copy history of
3542 files. Use -f/--follow with a filename to follow history across
3549 files. Use -f/--follow with a filename to follow history across
3543 renames and copies. --follow without a filename will only show
3550 renames and copies. --follow without a filename will only show
3544 ancestors or descendants of the starting revision.
3551 ancestors or descendants of the starting revision.
3545
3552
3546 By default this command prints revision number and changeset id,
3553 By default this command prints revision number and changeset id,
3547 tags, non-trivial parents, user, date and time, and a summary for
3554 tags, non-trivial parents, user, date and time, and a summary for
3548 each commit. When the -v/--verbose switch is used, the list of
3555 each commit. When the -v/--verbose switch is used, the list of
3549 changed files and full commit message are shown.
3556 changed files and full commit message are shown.
3550
3557
3551 .. note::
3558 .. note::
3552 log -p/--patch may generate unexpected diff output for merge
3559 log -p/--patch may generate unexpected diff output for merge
3553 changesets, as it will only compare the merge changeset against
3560 changesets, as it will only compare the merge changeset against
3554 its first parent. Also, only files different from BOTH parents
3561 its first parent. Also, only files different from BOTH parents
3555 will appear in files:.
3562 will appear in files:.
3556
3563
3557 .. note::
3564 .. note::
3558 for performance reasons, log FILE may omit duplicate changes
3565 for performance reasons, log FILE may omit duplicate changes
3559 made on branches and will not show deletions. To see all
3566 made on branches and will not show deletions. To see all
3560 changes including duplicates and deletions, use the --removed
3567 changes including duplicates and deletions, use the --removed
3561 switch.
3568 switch.
3562
3569
3563 .. container:: verbose
3570 .. container:: verbose
3564
3571
3565 Some examples:
3572 Some examples:
3566
3573
3567 - changesets with full descriptions and file lists::
3574 - changesets with full descriptions and file lists::
3568
3575
3569 hg log -v
3576 hg log -v
3570
3577
3571 - changesets ancestral to the working directory::
3578 - changesets ancestral to the working directory::
3572
3579
3573 hg log -f
3580 hg log -f
3574
3581
3575 - last 10 commits on the current branch::
3582 - last 10 commits on the current branch::
3576
3583
3577 hg log -l 10 -b .
3584 hg log -l 10 -b .
3578
3585
3579 - changesets showing all modifications of a file, including removals::
3586 - changesets showing all modifications of a file, including removals::
3580
3587
3581 hg log --removed file.c
3588 hg log --removed file.c
3582
3589
3583 - all changesets that touch a directory, with diffs, excluding merges::
3590 - all changesets that touch a directory, with diffs, excluding merges::
3584
3591
3585 hg log -Mp lib/
3592 hg log -Mp lib/
3586
3593
3587 - all revision numbers that match a keyword::
3594 - all revision numbers that match a keyword::
3588
3595
3589 hg log -k bug --template "{rev}\\n"
3596 hg log -k bug --template "{rev}\\n"
3590
3597
3591 - check if a given changeset is included is a tagged release::
3598 - check if a given changeset is included is a tagged release::
3592
3599
3593 hg log -r "a21ccf and ancestor(1.9)"
3600 hg log -r "a21ccf and ancestor(1.9)"
3594
3601
3595 - find all changesets by some user in a date range::
3602 - find all changesets by some user in a date range::
3596
3603
3597 hg log -k alice -d "may 2008 to jul 2008"
3604 hg log -k alice -d "may 2008 to jul 2008"
3598
3605
3599 - summary of all changesets after the last tag::
3606 - summary of all changesets after the last tag::
3600
3607
3601 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3608 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3602
3609
3603 See :hg:`help dates` for a list of formats valid for -d/--date.
3610 See :hg:`help dates` for a list of formats valid for -d/--date.
3604
3611
3605 See :hg:`help revisions` and :hg:`help revsets` for more about
3612 See :hg:`help revisions` and :hg:`help revsets` for more about
3606 specifying revisions.
3613 specifying revisions.
3607
3614
3608 Returns 0 on success.
3615 Returns 0 on success.
3609 """
3616 """
3610
3617
3611 matchfn = scmutil.match(repo[None], pats, opts)
3618 matchfn = scmutil.match(repo[None], pats, opts)
3612 limit = cmdutil.loglimit(opts)
3619 limit = cmdutil.loglimit(opts)
3613 count = 0
3620 count = 0
3614
3621
3615 endrev = None
3622 endrev = None
3616 if opts.get('copies') and opts.get('rev'):
3623 if opts.get('copies') and opts.get('rev'):
3617 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3624 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3618
3625
3619 df = False
3626 df = False
3620 if opts["date"]:
3627 if opts["date"]:
3621 df = util.matchdate(opts["date"])
3628 df = util.matchdate(opts["date"])
3622
3629
3623 branches = opts.get('branch', []) + opts.get('only_branch', [])
3630 branches = opts.get('branch', []) + opts.get('only_branch', [])
3624 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3631 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3625
3632
3626 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3633 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3627 def prep(ctx, fns):
3634 def prep(ctx, fns):
3628 rev = ctx.rev()
3635 rev = ctx.rev()
3629 parents = [p for p in repo.changelog.parentrevs(rev)
3636 parents = [p for p in repo.changelog.parentrevs(rev)
3630 if p != nullrev]
3637 if p != nullrev]
3631 if opts.get('no_merges') and len(parents) == 2:
3638 if opts.get('no_merges') and len(parents) == 2:
3632 return
3639 return
3633 if opts.get('only_merges') and len(parents) != 2:
3640 if opts.get('only_merges') and len(parents) != 2:
3634 return
3641 return
3635 if opts.get('branch') and ctx.branch() not in opts['branch']:
3642 if opts.get('branch') and ctx.branch() not in opts['branch']:
3636 return
3643 return
3637 if not opts.get('hidden') and ctx.hidden():
3644 if not opts.get('hidden') and ctx.hidden():
3638 return
3645 return
3639 if df and not df(ctx.date()[0]):
3646 if df and not df(ctx.date()[0]):
3640 return
3647 return
3641 if opts['user'] and not [k for k in opts['user']
3648 if opts['user'] and not [k for k in opts['user']
3642 if k.lower() in ctx.user().lower()]:
3649 if k.lower() in ctx.user().lower()]:
3643 return
3650 return
3644 if opts.get('keyword'):
3651 if opts.get('keyword'):
3645 for k in [kw.lower() for kw in opts['keyword']]:
3652 for k in [kw.lower() for kw in opts['keyword']]:
3646 if (k in ctx.user().lower() or
3653 if (k in ctx.user().lower() or
3647 k in ctx.description().lower() or
3654 k in ctx.description().lower() or
3648 k in " ".join(ctx.files()).lower()):
3655 k in " ".join(ctx.files()).lower()):
3649 break
3656 break
3650 else:
3657 else:
3651 return
3658 return
3652
3659
3653 copies = None
3660 copies = None
3654 if opts.get('copies') and rev:
3661 if opts.get('copies') and rev:
3655 copies = []
3662 copies = []
3656 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3663 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3657 for fn in ctx.files():
3664 for fn in ctx.files():
3658 rename = getrenamed(fn, rev)
3665 rename = getrenamed(fn, rev)
3659 if rename:
3666 if rename:
3660 copies.append((fn, rename[0]))
3667 copies.append((fn, rename[0]))
3661
3668
3662 revmatchfn = None
3669 revmatchfn = None
3663 if opts.get('patch') or opts.get('stat'):
3670 if opts.get('patch') or opts.get('stat'):
3664 if opts.get('follow') or opts.get('follow_first'):
3671 if opts.get('follow') or opts.get('follow_first'):
3665 # note: this might be wrong when following through merges
3672 # note: this might be wrong when following through merges
3666 revmatchfn = scmutil.match(repo[None], fns, default='path')
3673 revmatchfn = scmutil.match(repo[None], fns, default='path')
3667 else:
3674 else:
3668 revmatchfn = matchfn
3675 revmatchfn = matchfn
3669
3676
3670 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3677 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3671
3678
3672 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3679 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3673 if count == limit:
3680 if count == limit:
3674 break
3681 break
3675 if displayer.flush(ctx.rev()):
3682 if displayer.flush(ctx.rev()):
3676 count += 1
3683 count += 1
3677 displayer.close()
3684 displayer.close()
3678
3685
3679 @command('manifest',
3686 @command('manifest',
3680 [('r', 'rev', '', _('revision to display'), _('REV')),
3687 [('r', 'rev', '', _('revision to display'), _('REV')),
3681 ('', 'all', False, _("list files from all revisions"))],
3688 ('', 'all', False, _("list files from all revisions"))],
3682 _('[-r REV]'))
3689 _('[-r REV]'))
3683 def manifest(ui, repo, node=None, rev=None, **opts):
3690 def manifest(ui, repo, node=None, rev=None, **opts):
3684 """output the current or given revision of the project manifest
3691 """output the current or given revision of the project manifest
3685
3692
3686 Print a list of version controlled files for the given revision.
3693 Print a list of version controlled files for the given revision.
3687 If no revision is given, the first parent of the working directory
3694 If no revision is given, the first parent of the working directory
3688 is used, or the null revision if no revision is checked out.
3695 is used, or the null revision if no revision is checked out.
3689
3696
3690 With -v, print file permissions, symlink and executable bits.
3697 With -v, print file permissions, symlink and executable bits.
3691 With --debug, print file revision hashes.
3698 With --debug, print file revision hashes.
3692
3699
3693 If option --all is specified, the list of all files from all revisions
3700 If option --all is specified, the list of all files from all revisions
3694 is printed. This includes deleted and renamed files.
3701 is printed. This includes deleted and renamed files.
3695
3702
3696 Returns 0 on success.
3703 Returns 0 on success.
3697 """
3704 """
3698 if opts.get('all'):
3705 if opts.get('all'):
3699 if rev or node:
3706 if rev or node:
3700 raise util.Abort(_("can't specify a revision with --all"))
3707 raise util.Abort(_("can't specify a revision with --all"))
3701
3708
3702 res = []
3709 res = []
3703 prefix = "data/"
3710 prefix = "data/"
3704 suffix = ".i"
3711 suffix = ".i"
3705 plen = len(prefix)
3712 plen = len(prefix)
3706 slen = len(suffix)
3713 slen = len(suffix)
3707 lock = repo.lock()
3714 lock = repo.lock()
3708 try:
3715 try:
3709 for fn, b, size in repo.store.datafiles():
3716 for fn, b, size in repo.store.datafiles():
3710 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3717 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3711 res.append(fn[plen:-slen])
3718 res.append(fn[plen:-slen])
3712 finally:
3719 finally:
3713 lock.release()
3720 lock.release()
3714 for f in sorted(res):
3721 for f in sorted(res):
3715 ui.write("%s\n" % f)
3722 ui.write("%s\n" % f)
3716 return
3723 return
3717
3724
3718 if rev and node:
3725 if rev and node:
3719 raise util.Abort(_("please specify just one revision"))
3726 raise util.Abort(_("please specify just one revision"))
3720
3727
3721 if not node:
3728 if not node:
3722 node = rev
3729 node = rev
3723
3730
3724 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3731 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3725 ctx = scmutil.revsingle(repo, node)
3732 ctx = scmutil.revsingle(repo, node)
3726 for f in ctx:
3733 for f in ctx:
3727 if ui.debugflag:
3734 if ui.debugflag:
3728 ui.write("%40s " % hex(ctx.manifest()[f]))
3735 ui.write("%40s " % hex(ctx.manifest()[f]))
3729 if ui.verbose:
3736 if ui.verbose:
3730 ui.write(decor[ctx.flags(f)])
3737 ui.write(decor[ctx.flags(f)])
3731 ui.write("%s\n" % f)
3738 ui.write("%s\n" % f)
3732
3739
3733 @command('^merge',
3740 @command('^merge',
3734 [('f', 'force', None, _('force a merge with outstanding changes')),
3741 [('f', 'force', None, _('force a merge with outstanding changes')),
3735 ('r', 'rev', '', _('revision to merge'), _('REV')),
3742 ('r', 'rev', '', _('revision to merge'), _('REV')),
3736 ('P', 'preview', None,
3743 ('P', 'preview', None,
3737 _('review revisions to merge (no merge is performed)'))
3744 _('review revisions to merge (no merge is performed)'))
3738 ] + mergetoolopts,
3745 ] + mergetoolopts,
3739 _('[-P] [-f] [[-r] REV]'))
3746 _('[-P] [-f] [[-r] REV]'))
3740 def merge(ui, repo, node=None, **opts):
3747 def merge(ui, repo, node=None, **opts):
3741 """merge working directory with another revision
3748 """merge working directory with another revision
3742
3749
3743 The current working directory is updated with all changes made in
3750 The current working directory is updated with all changes made in
3744 the requested revision since the last common predecessor revision.
3751 the requested revision since the last common predecessor revision.
3745
3752
3746 Files that changed between either parent are marked as changed for
3753 Files that changed between either parent are marked as changed for
3747 the next commit and a commit must be performed before any further
3754 the next commit and a commit must be performed before any further
3748 updates to the repository are allowed. The next commit will have
3755 updates to the repository are allowed. The next commit will have
3749 two parents.
3756 two parents.
3750
3757
3751 ``--tool`` can be used to specify the merge tool used for file
3758 ``--tool`` can be used to specify the merge tool used for file
3752 merges. It overrides the HGMERGE environment variable and your
3759 merges. It overrides the HGMERGE environment variable and your
3753 configuration files. See :hg:`help merge-tools` for options.
3760 configuration files. See :hg:`help merge-tools` for options.
3754
3761
3755 If no revision is specified, the working directory's parent is a
3762 If no revision is specified, the working directory's parent is a
3756 head revision, and the current branch contains exactly one other
3763 head revision, and the current branch contains exactly one other
3757 head, the other head is merged with by default. Otherwise, an
3764 head, the other head is merged with by default. Otherwise, an
3758 explicit revision with which to merge with must be provided.
3765 explicit revision with which to merge with must be provided.
3759
3766
3760 :hg:`resolve` must be used to resolve unresolved files.
3767 :hg:`resolve` must be used to resolve unresolved files.
3761
3768
3762 To undo an uncommitted merge, use :hg:`update --clean .` which
3769 To undo an uncommitted merge, use :hg:`update --clean .` which
3763 will check out a clean copy of the original merge parent, losing
3770 will check out a clean copy of the original merge parent, losing
3764 all changes.
3771 all changes.
3765
3772
3766 Returns 0 on success, 1 if there are unresolved files.
3773 Returns 0 on success, 1 if there are unresolved files.
3767 """
3774 """
3768
3775
3769 if opts.get('rev') and node:
3776 if opts.get('rev') and node:
3770 raise util.Abort(_("please specify just one revision"))
3777 raise util.Abort(_("please specify just one revision"))
3771 if not node:
3778 if not node:
3772 node = opts.get('rev')
3779 node = opts.get('rev')
3773
3780
3774 if not node:
3781 if not node:
3775 branch = repo[None].branch()
3782 branch = repo[None].branch()
3776 bheads = repo.branchheads(branch)
3783 bheads = repo.branchheads(branch)
3777 if len(bheads) > 2:
3784 if len(bheads) > 2:
3778 raise util.Abort(_("branch '%s' has %d heads - "
3785 raise util.Abort(_("branch '%s' has %d heads - "
3779 "please merge with an explicit rev")
3786 "please merge with an explicit rev")
3780 % (branch, len(bheads)),
3787 % (branch, len(bheads)),
3781 hint=_("run 'hg heads .' to see heads"))
3788 hint=_("run 'hg heads .' to see heads"))
3782
3789
3783 parent = repo.dirstate.p1()
3790 parent = repo.dirstate.p1()
3784 if len(bheads) == 1:
3791 if len(bheads) == 1:
3785 if len(repo.heads()) > 1:
3792 if len(repo.heads()) > 1:
3786 raise util.Abort(_("branch '%s' has one head - "
3793 raise util.Abort(_("branch '%s' has one head - "
3787 "please merge with an explicit rev")
3794 "please merge with an explicit rev")
3788 % branch,
3795 % branch,
3789 hint=_("run 'hg heads' to see all heads"))
3796 hint=_("run 'hg heads' to see all heads"))
3790 msg = _('there is nothing to merge')
3797 msg = _('there is nothing to merge')
3791 if parent != repo.lookup(repo[None].branch()):
3798 if parent != repo.lookup(repo[None].branch()):
3792 msg = _('%s - use "hg update" instead') % msg
3799 msg = _('%s - use "hg update" instead') % msg
3793 raise util.Abort(msg)
3800 raise util.Abort(msg)
3794
3801
3795 if parent not in bheads:
3802 if parent not in bheads:
3796 raise util.Abort(_('working directory not at a head revision'),
3803 raise util.Abort(_('working directory not at a head revision'),
3797 hint=_("use 'hg update' or merge with an "
3804 hint=_("use 'hg update' or merge with an "
3798 "explicit revision"))
3805 "explicit revision"))
3799 node = parent == bheads[0] and bheads[-1] or bheads[0]
3806 node = parent == bheads[0] and bheads[-1] or bheads[0]
3800 else:
3807 else:
3801 node = scmutil.revsingle(repo, node).node()
3808 node = scmutil.revsingle(repo, node).node()
3802
3809
3803 if opts.get('preview'):
3810 if opts.get('preview'):
3804 # find nodes that are ancestors of p2 but not of p1
3811 # find nodes that are ancestors of p2 but not of p1
3805 p1 = repo.lookup('.')
3812 p1 = repo.lookup('.')
3806 p2 = repo.lookup(node)
3813 p2 = repo.lookup(node)
3807 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3814 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3808
3815
3809 displayer = cmdutil.show_changeset(ui, repo, opts)
3816 displayer = cmdutil.show_changeset(ui, repo, opts)
3810 for node in nodes:
3817 for node in nodes:
3811 displayer.show(repo[node])
3818 displayer.show(repo[node])
3812 displayer.close()
3819 displayer.close()
3813 return 0
3820 return 0
3814
3821
3815 try:
3822 try:
3816 # ui.forcemerge is an internal variable, do not document
3823 # ui.forcemerge is an internal variable, do not document
3817 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3824 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3818 return hg.merge(repo, node, force=opts.get('force'))
3825 return hg.merge(repo, node, force=opts.get('force'))
3819 finally:
3826 finally:
3820 ui.setconfig('ui', 'forcemerge', '')
3827 ui.setconfig('ui', 'forcemerge', '')
3821
3828
3822 @command('outgoing|out',
3829 @command('outgoing|out',
3823 [('f', 'force', None, _('run even when the destination is unrelated')),
3830 [('f', 'force', None, _('run even when the destination is unrelated')),
3824 ('r', 'rev', [],
3831 ('r', 'rev', [],
3825 _('a changeset intended to be included in the destination'), _('REV')),
3832 _('a changeset intended to be included in the destination'), _('REV')),
3826 ('n', 'newest-first', None, _('show newest record first')),
3833 ('n', 'newest-first', None, _('show newest record first')),
3827 ('B', 'bookmarks', False, _('compare bookmarks')),
3834 ('B', 'bookmarks', False, _('compare bookmarks')),
3828 ('b', 'branch', [], _('a specific branch you would like to push'),
3835 ('b', 'branch', [], _('a specific branch you would like to push'),
3829 _('BRANCH')),
3836 _('BRANCH')),
3830 ] + logopts + remoteopts + subrepoopts,
3837 ] + logopts + remoteopts + subrepoopts,
3831 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3838 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3832 def outgoing(ui, repo, dest=None, **opts):
3839 def outgoing(ui, repo, dest=None, **opts):
3833 """show changesets not found in the destination
3840 """show changesets not found in the destination
3834
3841
3835 Show changesets not found in the specified destination repository
3842 Show changesets not found in the specified destination repository
3836 or the default push location. These are the changesets that would
3843 or the default push location. These are the changesets that would
3837 be pushed if a push was requested.
3844 be pushed if a push was requested.
3838
3845
3839 See pull for details of valid destination formats.
3846 See pull for details of valid destination formats.
3840
3847
3841 Returns 0 if there are outgoing changes, 1 otherwise.
3848 Returns 0 if there are outgoing changes, 1 otherwise.
3842 """
3849 """
3843
3850
3844 if opts.get('bookmarks'):
3851 if opts.get('bookmarks'):
3845 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3852 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3846 dest, branches = hg.parseurl(dest, opts.get('branch'))
3853 dest, branches = hg.parseurl(dest, opts.get('branch'))
3847 other = hg.peer(repo, opts, dest)
3854 other = hg.peer(repo, opts, dest)
3848 if 'bookmarks' not in other.listkeys('namespaces'):
3855 if 'bookmarks' not in other.listkeys('namespaces'):
3849 ui.warn(_("remote doesn't support bookmarks\n"))
3856 ui.warn(_("remote doesn't support bookmarks\n"))
3850 return 0
3857 return 0
3851 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3858 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3852 return bookmarks.diff(ui, other, repo)
3859 return bookmarks.diff(ui, other, repo)
3853
3860
3854 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3861 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3855 try:
3862 try:
3856 return hg.outgoing(ui, repo, dest, opts)
3863 return hg.outgoing(ui, repo, dest, opts)
3857 finally:
3864 finally:
3858 del repo._subtoppath
3865 del repo._subtoppath
3859
3866
3860 @command('parents',
3867 @command('parents',
3861 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3868 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3862 ] + templateopts,
3869 ] + templateopts,
3863 _('[-r REV] [FILE]'))
3870 _('[-r REV] [FILE]'))
3864 def parents(ui, repo, file_=None, **opts):
3871 def parents(ui, repo, file_=None, **opts):
3865 """show the parents of the working directory or revision
3872 """show the parents of the working directory or revision
3866
3873
3867 Print the working directory's parent revisions. If a revision is
3874 Print the working directory's parent revisions. If a revision is
3868 given via -r/--rev, the parent of that revision will be printed.
3875 given via -r/--rev, the parent of that revision will be printed.
3869 If a file argument is given, the revision in which the file was
3876 If a file argument is given, the revision in which the file was
3870 last changed (before the working directory revision or the
3877 last changed (before the working directory revision or the
3871 argument to --rev if given) is printed.
3878 argument to --rev if given) is printed.
3872
3879
3873 Returns 0 on success.
3880 Returns 0 on success.
3874 """
3881 """
3875
3882
3876 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3883 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3877
3884
3878 if file_:
3885 if file_:
3879 m = scmutil.match(ctx, (file_,), opts)
3886 m = scmutil.match(ctx, (file_,), opts)
3880 if m.anypats() or len(m.files()) != 1:
3887 if m.anypats() or len(m.files()) != 1:
3881 raise util.Abort(_('can only specify an explicit filename'))
3888 raise util.Abort(_('can only specify an explicit filename'))
3882 file_ = m.files()[0]
3889 file_ = m.files()[0]
3883 filenodes = []
3890 filenodes = []
3884 for cp in ctx.parents():
3891 for cp in ctx.parents():
3885 if not cp:
3892 if not cp:
3886 continue
3893 continue
3887 try:
3894 try:
3888 filenodes.append(cp.filenode(file_))
3895 filenodes.append(cp.filenode(file_))
3889 except error.LookupError:
3896 except error.LookupError:
3890 pass
3897 pass
3891 if not filenodes:
3898 if not filenodes:
3892 raise util.Abort(_("'%s' not found in manifest!") % file_)
3899 raise util.Abort(_("'%s' not found in manifest!") % file_)
3893 fl = repo.file(file_)
3900 fl = repo.file(file_)
3894 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3901 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3895 else:
3902 else:
3896 p = [cp.node() for cp in ctx.parents()]
3903 p = [cp.node() for cp in ctx.parents()]
3897
3904
3898 displayer = cmdutil.show_changeset(ui, repo, opts)
3905 displayer = cmdutil.show_changeset(ui, repo, opts)
3899 for n in p:
3906 for n in p:
3900 if n != nullid:
3907 if n != nullid:
3901 displayer.show(repo[n])
3908 displayer.show(repo[n])
3902 displayer.close()
3909 displayer.close()
3903
3910
3904 @command('paths', [], _('[NAME]'))
3911 @command('paths', [], _('[NAME]'))
3905 def paths(ui, repo, search=None):
3912 def paths(ui, repo, search=None):
3906 """show aliases for remote repositories
3913 """show aliases for remote repositories
3907
3914
3908 Show definition of symbolic path name NAME. If no name is given,
3915 Show definition of symbolic path name NAME. If no name is given,
3909 show definition of all available names.
3916 show definition of all available names.
3910
3917
3911 Option -q/--quiet suppresses all output when searching for NAME
3918 Option -q/--quiet suppresses all output when searching for NAME
3912 and shows only the path names when listing all definitions.
3919 and shows only the path names when listing all definitions.
3913
3920
3914 Path names are defined in the [paths] section of your
3921 Path names are defined in the [paths] section of your
3915 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3922 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3916 repository, ``.hg/hgrc`` is used, too.
3923 repository, ``.hg/hgrc`` is used, too.
3917
3924
3918 The path names ``default`` and ``default-push`` have a special
3925 The path names ``default`` and ``default-push`` have a special
3919 meaning. When performing a push or pull operation, they are used
3926 meaning. When performing a push or pull operation, they are used
3920 as fallbacks if no location is specified on the command-line.
3927 as fallbacks if no location is specified on the command-line.
3921 When ``default-push`` is set, it will be used for push and
3928 When ``default-push`` is set, it will be used for push and
3922 ``default`` will be used for pull; otherwise ``default`` is used
3929 ``default`` will be used for pull; otherwise ``default`` is used
3923 as the fallback for both. When cloning a repository, the clone
3930 as the fallback for both. When cloning a repository, the clone
3924 source is written as ``default`` in ``.hg/hgrc``. Note that
3931 source is written as ``default`` in ``.hg/hgrc``. Note that
3925 ``default`` and ``default-push`` apply to all inbound (e.g.
3932 ``default`` and ``default-push`` apply to all inbound (e.g.
3926 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3933 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3927 :hg:`bundle`) operations.
3934 :hg:`bundle`) operations.
3928
3935
3929 See :hg:`help urls` for more information.
3936 See :hg:`help urls` for more information.
3930
3937
3931 Returns 0 on success.
3938 Returns 0 on success.
3932 """
3939 """
3933 if search:
3940 if search:
3934 for name, path in ui.configitems("paths"):
3941 for name, path in ui.configitems("paths"):
3935 if name == search:
3942 if name == search:
3936 ui.status("%s\n" % util.hidepassword(path))
3943 ui.status("%s\n" % util.hidepassword(path))
3937 return
3944 return
3938 if not ui.quiet:
3945 if not ui.quiet:
3939 ui.warn(_("not found!\n"))
3946 ui.warn(_("not found!\n"))
3940 return 1
3947 return 1
3941 else:
3948 else:
3942 for name, path in ui.configitems("paths"):
3949 for name, path in ui.configitems("paths"):
3943 if ui.quiet:
3950 if ui.quiet:
3944 ui.write("%s\n" % name)
3951 ui.write("%s\n" % name)
3945 else:
3952 else:
3946 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3953 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3947
3954
3948 def postincoming(ui, repo, modheads, optupdate, checkout):
3955 def postincoming(ui, repo, modheads, optupdate, checkout):
3949 if modheads == 0:
3956 if modheads == 0:
3950 return
3957 return
3951 if optupdate:
3958 if optupdate:
3952 try:
3959 try:
3953 return hg.update(repo, checkout)
3960 return hg.update(repo, checkout)
3954 except util.Abort, inst:
3961 except util.Abort, inst:
3955 ui.warn(_("not updating: %s\n" % str(inst)))
3962 ui.warn(_("not updating: %s\n" % str(inst)))
3956 return 0
3963 return 0
3957 if modheads > 1:
3964 if modheads > 1:
3958 currentbranchheads = len(repo.branchheads())
3965 currentbranchheads = len(repo.branchheads())
3959 if currentbranchheads == modheads:
3966 if currentbranchheads == modheads:
3960 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3967 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3961 elif currentbranchheads > 1:
3968 elif currentbranchheads > 1:
3962 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3969 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3963 else:
3970 else:
3964 ui.status(_("(run 'hg heads' to see heads)\n"))
3971 ui.status(_("(run 'hg heads' to see heads)\n"))
3965 else:
3972 else:
3966 ui.status(_("(run 'hg update' to get a working copy)\n"))
3973 ui.status(_("(run 'hg update' to get a working copy)\n"))
3967
3974
3968 @command('^pull',
3975 @command('^pull',
3969 [('u', 'update', None,
3976 [('u', 'update', None,
3970 _('update to new branch head if changesets were pulled')),
3977 _('update to new branch head if changesets were pulled')),
3971 ('f', 'force', None, _('run even when remote repository is unrelated')),
3978 ('f', 'force', None, _('run even when remote repository is unrelated')),
3972 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3979 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3973 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3980 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3974 ('b', 'branch', [], _('a specific branch you would like to pull'),
3981 ('b', 'branch', [], _('a specific branch you would like to pull'),
3975 _('BRANCH')),
3982 _('BRANCH')),
3976 ] + remoteopts,
3983 ] + remoteopts,
3977 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3984 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3978 def pull(ui, repo, source="default", **opts):
3985 def pull(ui, repo, source="default", **opts):
3979 """pull changes from the specified source
3986 """pull changes from the specified source
3980
3987
3981 Pull changes from a remote repository to a local one.
3988 Pull changes from a remote repository to a local one.
3982
3989
3983 This finds all changes from the repository at the specified path
3990 This finds all changes from the repository at the specified path
3984 or URL and adds them to a local repository (the current one unless
3991 or URL and adds them to a local repository (the current one unless
3985 -R is specified). By default, this does not update the copy of the
3992 -R is specified). By default, this does not update the copy of the
3986 project in the working directory.
3993 project in the working directory.
3987
3994
3988 Use :hg:`incoming` if you want to see what would have been added
3995 Use :hg:`incoming` if you want to see what would have been added
3989 by a pull at the time you issued this command. If you then decide
3996 by a pull at the time you issued this command. If you then decide
3990 to add those changes to the repository, you should use :hg:`pull
3997 to add those changes to the repository, you should use :hg:`pull
3991 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3998 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3992
3999
3993 If SOURCE is omitted, the 'default' path will be used.
4000 If SOURCE is omitted, the 'default' path will be used.
3994 See :hg:`help urls` for more information.
4001 See :hg:`help urls` for more information.
3995
4002
3996 Returns 0 on success, 1 if an update had unresolved files.
4003 Returns 0 on success, 1 if an update had unresolved files.
3997 """
4004 """
3998 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4005 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3999 other = hg.peer(repo, opts, source)
4006 other = hg.peer(repo, opts, source)
4000 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4007 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4001 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4008 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4002
4009
4003 if opts.get('bookmark'):
4010 if opts.get('bookmark'):
4004 if not revs:
4011 if not revs:
4005 revs = []
4012 revs = []
4006 rb = other.listkeys('bookmarks')
4013 rb = other.listkeys('bookmarks')
4007 for b in opts['bookmark']:
4014 for b in opts['bookmark']:
4008 if b not in rb:
4015 if b not in rb:
4009 raise util.Abort(_('remote bookmark %s not found!') % b)
4016 raise util.Abort(_('remote bookmark %s not found!') % b)
4010 revs.append(rb[b])
4017 revs.append(rb[b])
4011
4018
4012 if revs:
4019 if revs:
4013 try:
4020 try:
4014 revs = [other.lookup(rev) for rev in revs]
4021 revs = [other.lookup(rev) for rev in revs]
4015 except error.CapabilityError:
4022 except error.CapabilityError:
4016 err = _("other repository doesn't support revision lookup, "
4023 err = _("other repository doesn't support revision lookup, "
4017 "so a rev cannot be specified.")
4024 "so a rev cannot be specified.")
4018 raise util.Abort(err)
4025 raise util.Abort(err)
4019
4026
4020 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4027 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4021 bookmarks.updatefromremote(ui, repo, other)
4028 bookmarks.updatefromremote(ui, repo, other)
4022 if checkout:
4029 if checkout:
4023 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4030 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4024 repo._subtoppath = source
4031 repo._subtoppath = source
4025 try:
4032 try:
4026 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4033 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4027
4034
4028 finally:
4035 finally:
4029 del repo._subtoppath
4036 del repo._subtoppath
4030
4037
4031 # update specified bookmarks
4038 # update specified bookmarks
4032 if opts.get('bookmark'):
4039 if opts.get('bookmark'):
4033 for b in opts['bookmark']:
4040 for b in opts['bookmark']:
4034 # explicit pull overrides local bookmark if any
4041 # explicit pull overrides local bookmark if any
4035 ui.status(_("importing bookmark %s\n") % b)
4042 ui.status(_("importing bookmark %s\n") % b)
4036 repo._bookmarks[b] = repo[rb[b]].node()
4043 repo._bookmarks[b] = repo[rb[b]].node()
4037 bookmarks.write(repo)
4044 bookmarks.write(repo)
4038
4045
4039 return ret
4046 return ret
4040
4047
4041 @command('^push',
4048 @command('^push',
4042 [('f', 'force', None, _('force push')),
4049 [('f', 'force', None, _('force push')),
4043 ('r', 'rev', [],
4050 ('r', 'rev', [],
4044 _('a changeset intended to be included in the destination'),
4051 _('a changeset intended to be included in the destination'),
4045 _('REV')),
4052 _('REV')),
4046 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4053 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4047 ('b', 'branch', [],
4054 ('b', 'branch', [],
4048 _('a specific branch you would like to push'), _('BRANCH')),
4055 _('a specific branch you would like to push'), _('BRANCH')),
4049 ('', 'new-branch', False, _('allow pushing a new branch')),
4056 ('', 'new-branch', False, _('allow pushing a new branch')),
4050 ] + remoteopts,
4057 ] + remoteopts,
4051 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4058 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4052 def push(ui, repo, dest=None, **opts):
4059 def push(ui, repo, dest=None, **opts):
4053 """push changes to the specified destination
4060 """push changes to the specified destination
4054
4061
4055 Push changesets from the local repository to the specified
4062 Push changesets from the local repository to the specified
4056 destination.
4063 destination.
4057
4064
4058 This operation is symmetrical to pull: it is identical to a pull
4065 This operation is symmetrical to pull: it is identical to a pull
4059 in the destination repository from the current one.
4066 in the destination repository from the current one.
4060
4067
4061 By default, push will not allow creation of new heads at the
4068 By default, push will not allow creation of new heads at the
4062 destination, since multiple heads would make it unclear which head
4069 destination, since multiple heads would make it unclear which head
4063 to use. In this situation, it is recommended to pull and merge
4070 to use. In this situation, it is recommended to pull and merge
4064 before pushing.
4071 before pushing.
4065
4072
4066 Use --new-branch if you want to allow push to create a new named
4073 Use --new-branch if you want to allow push to create a new named
4067 branch that is not present at the destination. This allows you to
4074 branch that is not present at the destination. This allows you to
4068 only create a new branch without forcing other changes.
4075 only create a new branch without forcing other changes.
4069
4076
4070 Use -f/--force to override the default behavior and push all
4077 Use -f/--force to override the default behavior and push all
4071 changesets on all branches.
4078 changesets on all branches.
4072
4079
4073 If -r/--rev is used, the specified revision and all its ancestors
4080 If -r/--rev is used, the specified revision and all its ancestors
4074 will be pushed to the remote repository.
4081 will be pushed to the remote repository.
4075
4082
4076 Please see :hg:`help urls` for important details about ``ssh://``
4083 Please see :hg:`help urls` for important details about ``ssh://``
4077 URLs. If DESTINATION is omitted, a default path will be used.
4084 URLs. If DESTINATION is omitted, a default path will be used.
4078
4085
4079 Returns 0 if push was successful, 1 if nothing to push.
4086 Returns 0 if push was successful, 1 if nothing to push.
4080 """
4087 """
4081
4088
4082 if opts.get('bookmark'):
4089 if opts.get('bookmark'):
4083 for b in opts['bookmark']:
4090 for b in opts['bookmark']:
4084 # translate -B options to -r so changesets get pushed
4091 # translate -B options to -r so changesets get pushed
4085 if b in repo._bookmarks:
4092 if b in repo._bookmarks:
4086 opts.setdefault('rev', []).append(b)
4093 opts.setdefault('rev', []).append(b)
4087 else:
4094 else:
4088 # if we try to push a deleted bookmark, translate it to null
4095 # if we try to push a deleted bookmark, translate it to null
4089 # this lets simultaneous -r, -b options continue working
4096 # this lets simultaneous -r, -b options continue working
4090 opts.setdefault('rev', []).append("null")
4097 opts.setdefault('rev', []).append("null")
4091
4098
4092 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4099 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4093 dest, branches = hg.parseurl(dest, opts.get('branch'))
4100 dest, branches = hg.parseurl(dest, opts.get('branch'))
4094 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4101 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4095 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4102 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4096 other = hg.peer(repo, opts, dest)
4103 other = hg.peer(repo, opts, dest)
4097 if revs:
4104 if revs:
4098 revs = [repo.lookup(rev) for rev in revs]
4105 revs = [repo.lookup(rev) for rev in revs]
4099
4106
4100 repo._subtoppath = dest
4107 repo._subtoppath = dest
4101 try:
4108 try:
4102 # push subrepos depth-first for coherent ordering
4109 # push subrepos depth-first for coherent ordering
4103 c = repo['']
4110 c = repo['']
4104 subs = c.substate # only repos that are committed
4111 subs = c.substate # only repos that are committed
4105 for s in sorted(subs):
4112 for s in sorted(subs):
4106 if not c.sub(s).push(opts.get('force')):
4113 if not c.sub(s).push(opts.get('force')):
4107 return False
4114 return False
4108 finally:
4115 finally:
4109 del repo._subtoppath
4116 del repo._subtoppath
4110 result = repo.push(other, opts.get('force'), revs=revs,
4117 result = repo.push(other, opts.get('force'), revs=revs,
4111 newbranch=opts.get('new_branch'))
4118 newbranch=opts.get('new_branch'))
4112
4119
4113 result = (result == 0)
4120 result = (result == 0)
4114
4121
4115 if opts.get('bookmark'):
4122 if opts.get('bookmark'):
4116 rb = other.listkeys('bookmarks')
4123 rb = other.listkeys('bookmarks')
4117 for b in opts['bookmark']:
4124 for b in opts['bookmark']:
4118 # explicit push overrides remote bookmark if any
4125 # explicit push overrides remote bookmark if any
4119 if b in repo._bookmarks:
4126 if b in repo._bookmarks:
4120 ui.status(_("exporting bookmark %s\n") % b)
4127 ui.status(_("exporting bookmark %s\n") % b)
4121 new = repo[b].hex()
4128 new = repo[b].hex()
4122 elif b in rb:
4129 elif b in rb:
4123 ui.status(_("deleting remote bookmark %s\n") % b)
4130 ui.status(_("deleting remote bookmark %s\n") % b)
4124 new = '' # delete
4131 new = '' # delete
4125 else:
4132 else:
4126 ui.warn(_('bookmark %s does not exist on the local '
4133 ui.warn(_('bookmark %s does not exist on the local '
4127 'or remote repository!\n') % b)
4134 'or remote repository!\n') % b)
4128 return 2
4135 return 2
4129 old = rb.get(b, '')
4136 old = rb.get(b, '')
4130 r = other.pushkey('bookmarks', b, old, new)
4137 r = other.pushkey('bookmarks', b, old, new)
4131 if not r:
4138 if not r:
4132 ui.warn(_('updating bookmark %s failed!\n') % b)
4139 ui.warn(_('updating bookmark %s failed!\n') % b)
4133 if not result:
4140 if not result:
4134 result = 2
4141 result = 2
4135
4142
4136 return result
4143 return result
4137
4144
4138 @command('recover', [])
4145 @command('recover', [])
4139 def recover(ui, repo):
4146 def recover(ui, repo):
4140 """roll back an interrupted transaction
4147 """roll back an interrupted transaction
4141
4148
4142 Recover from an interrupted commit or pull.
4149 Recover from an interrupted commit or pull.
4143
4150
4144 This command tries to fix the repository status after an
4151 This command tries to fix the repository status after an
4145 interrupted operation. It should only be necessary when Mercurial
4152 interrupted operation. It should only be necessary when Mercurial
4146 suggests it.
4153 suggests it.
4147
4154
4148 Returns 0 if successful, 1 if nothing to recover or verify fails.
4155 Returns 0 if successful, 1 if nothing to recover or verify fails.
4149 """
4156 """
4150 if repo.recover():
4157 if repo.recover():
4151 return hg.verify(repo)
4158 return hg.verify(repo)
4152 return 1
4159 return 1
4153
4160
4154 @command('^remove|rm',
4161 @command('^remove|rm',
4155 [('A', 'after', None, _('record delete for missing files')),
4162 [('A', 'after', None, _('record delete for missing files')),
4156 ('f', 'force', None,
4163 ('f', 'force', None,
4157 _('remove (and delete) file even if added or modified')),
4164 _('remove (and delete) file even if added or modified')),
4158 ] + walkopts,
4165 ] + walkopts,
4159 _('[OPTION]... FILE...'))
4166 _('[OPTION]... FILE...'))
4160 def remove(ui, repo, *pats, **opts):
4167 def remove(ui, repo, *pats, **opts):
4161 """remove the specified files on the next commit
4168 """remove the specified files on the next commit
4162
4169
4163 Schedule the indicated files for removal from the current branch.
4170 Schedule the indicated files for removal from the current branch.
4164
4171
4165 This command schedules the files to be removed at the next commit.
4172 This command schedules the files to be removed at the next commit.
4166 To undo a remove before that, see :hg:`revert`. To undo added
4173 To undo a remove before that, see :hg:`revert`. To undo added
4167 files, see :hg:`forget`.
4174 files, see :hg:`forget`.
4168
4175
4169 .. container:: verbose
4176 .. container:: verbose
4170
4177
4171 -A/--after can be used to remove only files that have already
4178 -A/--after can be used to remove only files that have already
4172 been deleted, -f/--force can be used to force deletion, and -Af
4179 been deleted, -f/--force can be used to force deletion, and -Af
4173 can be used to remove files from the next revision without
4180 can be used to remove files from the next revision without
4174 deleting them from the working directory.
4181 deleting them from the working directory.
4175
4182
4176 The following table details the behavior of remove for different
4183 The following table details the behavior of remove for different
4177 file states (columns) and option combinations (rows). The file
4184 file states (columns) and option combinations (rows). The file
4178 states are Added [A], Clean [C], Modified [M] and Missing [!]
4185 states are Added [A], Clean [C], Modified [M] and Missing [!]
4179 (as reported by :hg:`status`). The actions are Warn, Remove
4186 (as reported by :hg:`status`). The actions are Warn, Remove
4180 (from branch) and Delete (from disk):
4187 (from branch) and Delete (from disk):
4181
4188
4182 ======= == == == ==
4189 ======= == == == ==
4183 A C M !
4190 A C M !
4184 ======= == == == ==
4191 ======= == == == ==
4185 none W RD W R
4192 none W RD W R
4186 -f R RD RD R
4193 -f R RD RD R
4187 -A W W W R
4194 -A W W W R
4188 -Af R R R R
4195 -Af R R R R
4189 ======= == == == ==
4196 ======= == == == ==
4190
4197
4191 Note that remove never deletes files in Added [A] state from the
4198 Note that remove never deletes files in Added [A] state from the
4192 working directory, not even if option --force is specified.
4199 working directory, not even if option --force is specified.
4193
4200
4194 Returns 0 on success, 1 if any warnings encountered.
4201 Returns 0 on success, 1 if any warnings encountered.
4195 """
4202 """
4196
4203
4197 ret = 0
4204 ret = 0
4198 after, force = opts.get('after'), opts.get('force')
4205 after, force = opts.get('after'), opts.get('force')
4199 if not pats and not after:
4206 if not pats and not after:
4200 raise util.Abort(_('no files specified'))
4207 raise util.Abort(_('no files specified'))
4201
4208
4202 m = scmutil.match(repo[None], pats, opts)
4209 m = scmutil.match(repo[None], pats, opts)
4203 s = repo.status(match=m, clean=True)
4210 s = repo.status(match=m, clean=True)
4204 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4211 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4205
4212
4206 for f in m.files():
4213 for f in m.files():
4207 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4214 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4208 if os.path.exists(m.rel(f)):
4215 if os.path.exists(m.rel(f)):
4209 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4216 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4210 ret = 1
4217 ret = 1
4211
4218
4212 if force:
4219 if force:
4213 list = modified + deleted + clean + added
4220 list = modified + deleted + clean + added
4214 elif after:
4221 elif after:
4215 list = deleted
4222 list = deleted
4216 for f in modified + added + clean:
4223 for f in modified + added + clean:
4217 ui.warn(_('not removing %s: file still exists (use -f'
4224 ui.warn(_('not removing %s: file still exists (use -f'
4218 ' to force removal)\n') % m.rel(f))
4225 ' to force removal)\n') % m.rel(f))
4219 ret = 1
4226 ret = 1
4220 else:
4227 else:
4221 list = deleted + clean
4228 list = deleted + clean
4222 for f in modified:
4229 for f in modified:
4223 ui.warn(_('not removing %s: file is modified (use -f'
4230 ui.warn(_('not removing %s: file is modified (use -f'
4224 ' to force removal)\n') % m.rel(f))
4231 ' to force removal)\n') % m.rel(f))
4225 ret = 1
4232 ret = 1
4226 for f in added:
4233 for f in added:
4227 ui.warn(_('not removing %s: file has been marked for add'
4234 ui.warn(_('not removing %s: file has been marked for add'
4228 ' (use forget to undo)\n') % m.rel(f))
4235 ' (use forget to undo)\n') % m.rel(f))
4229 ret = 1
4236 ret = 1
4230
4237
4231 for f in sorted(list):
4238 for f in sorted(list):
4232 if ui.verbose or not m.exact(f):
4239 if ui.verbose or not m.exact(f):
4233 ui.status(_('removing %s\n') % m.rel(f))
4240 ui.status(_('removing %s\n') % m.rel(f))
4234
4241
4235 wlock = repo.wlock()
4242 wlock = repo.wlock()
4236 try:
4243 try:
4237 if not after:
4244 if not after:
4238 for f in list:
4245 for f in list:
4239 if f in added:
4246 if f in added:
4240 continue # we never unlink added files on remove
4247 continue # we never unlink added files on remove
4241 try:
4248 try:
4242 util.unlinkpath(repo.wjoin(f))
4249 util.unlinkpath(repo.wjoin(f))
4243 except OSError, inst:
4250 except OSError, inst:
4244 if inst.errno != errno.ENOENT:
4251 if inst.errno != errno.ENOENT:
4245 raise
4252 raise
4246 repo[None].forget(list)
4253 repo[None].forget(list)
4247 finally:
4254 finally:
4248 wlock.release()
4255 wlock.release()
4249
4256
4250 return ret
4257 return ret
4251
4258
4252 @command('rename|move|mv',
4259 @command('rename|move|mv',
4253 [('A', 'after', None, _('record a rename that has already occurred')),
4260 [('A', 'after', None, _('record a rename that has already occurred')),
4254 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4261 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4255 ] + walkopts + dryrunopts,
4262 ] + walkopts + dryrunopts,
4256 _('[OPTION]... SOURCE... DEST'))
4263 _('[OPTION]... SOURCE... DEST'))
4257 def rename(ui, repo, *pats, **opts):
4264 def rename(ui, repo, *pats, **opts):
4258 """rename files; equivalent of copy + remove
4265 """rename files; equivalent of copy + remove
4259
4266
4260 Mark dest as copies of sources; mark sources for deletion. If dest
4267 Mark dest as copies of sources; mark sources for deletion. If dest
4261 is a directory, copies are put in that directory. If dest is a
4268 is a directory, copies are put in that directory. If dest is a
4262 file, there can only be one source.
4269 file, there can only be one source.
4263
4270
4264 By default, this command copies the contents of files as they
4271 By default, this command copies the contents of files as they
4265 exist in the working directory. If invoked with -A/--after, the
4272 exist in the working directory. If invoked with -A/--after, the
4266 operation is recorded, but no copying is performed.
4273 operation is recorded, but no copying is performed.
4267
4274
4268 This command takes effect at the next commit. To undo a rename
4275 This command takes effect at the next commit. To undo a rename
4269 before that, see :hg:`revert`.
4276 before that, see :hg:`revert`.
4270
4277
4271 Returns 0 on success, 1 if errors are encountered.
4278 Returns 0 on success, 1 if errors are encountered.
4272 """
4279 """
4273 wlock = repo.wlock(False)
4280 wlock = repo.wlock(False)
4274 try:
4281 try:
4275 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4282 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4276 finally:
4283 finally:
4277 wlock.release()
4284 wlock.release()
4278
4285
4279 @command('resolve',
4286 @command('resolve',
4280 [('a', 'all', None, _('select all unresolved files')),
4287 [('a', 'all', None, _('select all unresolved files')),
4281 ('l', 'list', None, _('list state of files needing merge')),
4288 ('l', 'list', None, _('list state of files needing merge')),
4282 ('m', 'mark', None, _('mark files as resolved')),
4289 ('m', 'mark', None, _('mark files as resolved')),
4283 ('u', 'unmark', None, _('mark files as unresolved')),
4290 ('u', 'unmark', None, _('mark files as unresolved')),
4284 ('n', 'no-status', None, _('hide status prefix'))]
4291 ('n', 'no-status', None, _('hide status prefix'))]
4285 + mergetoolopts + walkopts,
4292 + mergetoolopts + walkopts,
4286 _('[OPTION]... [FILE]...'))
4293 _('[OPTION]... [FILE]...'))
4287 def resolve(ui, repo, *pats, **opts):
4294 def resolve(ui, repo, *pats, **opts):
4288 """redo merges or set/view the merge status of files
4295 """redo merges or set/view the merge status of files
4289
4296
4290 Merges with unresolved conflicts are often the result of
4297 Merges with unresolved conflicts are often the result of
4291 non-interactive merging using the ``internal:merge`` configuration
4298 non-interactive merging using the ``internal:merge`` configuration
4292 setting, or a command-line merge tool like ``diff3``. The resolve
4299 setting, or a command-line merge tool like ``diff3``. The resolve
4293 command is used to manage the files involved in a merge, after
4300 command is used to manage the files involved in a merge, after
4294 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4301 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4295 working directory must have two parents).
4302 working directory must have two parents).
4296
4303
4297 The resolve command can be used in the following ways:
4304 The resolve command can be used in the following ways:
4298
4305
4299 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4306 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4300 files, discarding any previous merge attempts. Re-merging is not
4307 files, discarding any previous merge attempts. Re-merging is not
4301 performed for files already marked as resolved. Use ``--all/-a``
4308 performed for files already marked as resolved. Use ``--all/-a``
4302 to select all unresolved files. ``--tool`` can be used to specify
4309 to select all unresolved files. ``--tool`` can be used to specify
4303 the merge tool used for the given files. It overrides the HGMERGE
4310 the merge tool used for the given files. It overrides the HGMERGE
4304 environment variable and your configuration files.
4311 environment variable and your configuration files.
4305
4312
4306 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4313 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4307 (e.g. after having manually fixed-up the files). The default is
4314 (e.g. after having manually fixed-up the files). The default is
4308 to mark all unresolved files.
4315 to mark all unresolved files.
4309
4316
4310 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4317 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4311 default is to mark all resolved files.
4318 default is to mark all resolved files.
4312
4319
4313 - :hg:`resolve -l`: list files which had or still have conflicts.
4320 - :hg:`resolve -l`: list files which had or still have conflicts.
4314 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4321 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4315
4322
4316 Note that Mercurial will not let you commit files with unresolved
4323 Note that Mercurial will not let you commit files with unresolved
4317 merge conflicts. You must use :hg:`resolve -m ...` before you can
4324 merge conflicts. You must use :hg:`resolve -m ...` before you can
4318 commit after a conflicting merge.
4325 commit after a conflicting merge.
4319
4326
4320 Returns 0 on success, 1 if any files fail a resolve attempt.
4327 Returns 0 on success, 1 if any files fail a resolve attempt.
4321 """
4328 """
4322
4329
4323 all, mark, unmark, show, nostatus = \
4330 all, mark, unmark, show, nostatus = \
4324 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4331 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4325
4332
4326 if (show and (mark or unmark)) or (mark and unmark):
4333 if (show and (mark or unmark)) or (mark and unmark):
4327 raise util.Abort(_("too many options specified"))
4334 raise util.Abort(_("too many options specified"))
4328 if pats and all:
4335 if pats and all:
4329 raise util.Abort(_("can't specify --all and patterns"))
4336 raise util.Abort(_("can't specify --all and patterns"))
4330 if not (all or pats or show or mark or unmark):
4337 if not (all or pats or show or mark or unmark):
4331 raise util.Abort(_('no files or directories specified; '
4338 raise util.Abort(_('no files or directories specified; '
4332 'use --all to remerge all files'))
4339 'use --all to remerge all files'))
4333
4340
4334 ms = mergemod.mergestate(repo)
4341 ms = mergemod.mergestate(repo)
4335 m = scmutil.match(repo[None], pats, opts)
4342 m = scmutil.match(repo[None], pats, opts)
4336 ret = 0
4343 ret = 0
4337
4344
4338 for f in ms:
4345 for f in ms:
4339 if m(f):
4346 if m(f):
4340 if show:
4347 if show:
4341 if nostatus:
4348 if nostatus:
4342 ui.write("%s\n" % f)
4349 ui.write("%s\n" % f)
4343 else:
4350 else:
4344 ui.write("%s %s\n" % (ms[f].upper(), f),
4351 ui.write("%s %s\n" % (ms[f].upper(), f),
4345 label='resolve.' +
4352 label='resolve.' +
4346 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4353 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4347 elif mark:
4354 elif mark:
4348 ms.mark(f, "r")
4355 ms.mark(f, "r")
4349 elif unmark:
4356 elif unmark:
4350 ms.mark(f, "u")
4357 ms.mark(f, "u")
4351 else:
4358 else:
4352 wctx = repo[None]
4359 wctx = repo[None]
4353 mctx = wctx.parents()[-1]
4360 mctx = wctx.parents()[-1]
4354
4361
4355 # backup pre-resolve (merge uses .orig for its own purposes)
4362 # backup pre-resolve (merge uses .orig for its own purposes)
4356 a = repo.wjoin(f)
4363 a = repo.wjoin(f)
4357 util.copyfile(a, a + ".resolve")
4364 util.copyfile(a, a + ".resolve")
4358
4365
4359 try:
4366 try:
4360 # resolve file
4367 # resolve file
4361 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4368 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4362 if ms.resolve(f, wctx, mctx):
4369 if ms.resolve(f, wctx, mctx):
4363 ret = 1
4370 ret = 1
4364 finally:
4371 finally:
4365 ui.setconfig('ui', 'forcemerge', '')
4372 ui.setconfig('ui', 'forcemerge', '')
4366
4373
4367 # replace filemerge's .orig file with our resolve file
4374 # replace filemerge's .orig file with our resolve file
4368 util.rename(a + ".resolve", a + ".orig")
4375 util.rename(a + ".resolve", a + ".orig")
4369
4376
4370 ms.commit()
4377 ms.commit()
4371 return ret
4378 return ret
4372
4379
4373 @command('revert',
4380 @command('revert',
4374 [('a', 'all', None, _('revert all changes when no arguments given')),
4381 [('a', 'all', None, _('revert all changes when no arguments given')),
4375 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4382 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4376 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4383 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4377 ('C', 'no-backup', None, _('do not save backup copies of files')),
4384 ('C', 'no-backup', None, _('do not save backup copies of files')),
4378 ] + walkopts + dryrunopts,
4385 ] + walkopts + dryrunopts,
4379 _('[OPTION]... [-r REV] [NAME]...'))
4386 _('[OPTION]... [-r REV] [NAME]...'))
4380 def revert(ui, repo, *pats, **opts):
4387 def revert(ui, repo, *pats, **opts):
4381 """restore files to their checkout state
4388 """restore files to their checkout state
4382
4389
4383 .. note::
4390 .. note::
4384 To check out earlier revisions, you should use :hg:`update REV`.
4391 To check out earlier revisions, you should use :hg:`update REV`.
4385 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4392 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4386
4393
4387 With no revision specified, revert the specified files or directories
4394 With no revision specified, revert the specified files or directories
4388 to the contents they had in the parent of the working directory.
4395 to the contents they had in the parent of the working directory.
4389 This restores the contents of files to an unmodified
4396 This restores the contents of files to an unmodified
4390 state and unschedules adds, removes, copies, and renames. If the
4397 state and unschedules adds, removes, copies, and renames. If the
4391 working directory has two parents, you must explicitly specify a
4398 working directory has two parents, you must explicitly specify a
4392 revision.
4399 revision.
4393
4400
4394 Using the -r/--rev or -d/--date options, revert the given files or
4401 Using the -r/--rev or -d/--date options, revert the given files or
4395 directories to their states as of a specific revision. Because
4402 directories to their states as of a specific revision. Because
4396 revert does not change the working directory parents, this will
4403 revert does not change the working directory parents, this will
4397 cause these files to appear modified. This can be helpful to "back
4404 cause these files to appear modified. This can be helpful to "back
4398 out" some or all of an earlier change. See :hg:`backout` for a
4405 out" some or all of an earlier change. See :hg:`backout` for a
4399 related method.
4406 related method.
4400
4407
4401 Modified files are saved with a .orig suffix before reverting.
4408 Modified files are saved with a .orig suffix before reverting.
4402 To disable these backups, use --no-backup.
4409 To disable these backups, use --no-backup.
4403
4410
4404 See :hg:`help dates` for a list of formats valid for -d/--date.
4411 See :hg:`help dates` for a list of formats valid for -d/--date.
4405
4412
4406 Returns 0 on success.
4413 Returns 0 on success.
4407 """
4414 """
4408
4415
4409 if opts.get("date"):
4416 if opts.get("date"):
4410 if opts.get("rev"):
4417 if opts.get("rev"):
4411 raise util.Abort(_("you can't specify a revision and a date"))
4418 raise util.Abort(_("you can't specify a revision and a date"))
4412 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4419 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4413
4420
4414 parent, p2 = repo.dirstate.parents()
4421 parent, p2 = repo.dirstate.parents()
4415 if not opts.get('rev') and p2 != nullid:
4422 if not opts.get('rev') and p2 != nullid:
4416 # revert after merge is a trap for new users (issue2915)
4423 # revert after merge is a trap for new users (issue2915)
4417 raise util.Abort(_('uncommitted merge with no revision specified'),
4424 raise util.Abort(_('uncommitted merge with no revision specified'),
4418 hint=_('use "hg update" or see "hg help revert"'))
4425 hint=_('use "hg update" or see "hg help revert"'))
4419
4426
4420 ctx = scmutil.revsingle(repo, opts.get('rev'))
4427 ctx = scmutil.revsingle(repo, opts.get('rev'))
4421 node = ctx.node()
4428 node = ctx.node()
4422
4429
4423 if not pats and not opts.get('all'):
4430 if not pats and not opts.get('all'):
4424 msg = _("no files or directories specified")
4431 msg = _("no files or directories specified")
4425 if p2 != nullid:
4432 if p2 != nullid:
4426 hint = _("uncommitted merge, use --all to discard all changes,"
4433 hint = _("uncommitted merge, use --all to discard all changes,"
4427 " or 'hg update -C .' to abort the merge")
4434 " or 'hg update -C .' to abort the merge")
4428 raise util.Abort(msg, hint=hint)
4435 raise util.Abort(msg, hint=hint)
4429 dirty = util.any(repo.status())
4436 dirty = util.any(repo.status())
4430 if node != parent:
4437 if node != parent:
4431 if dirty:
4438 if dirty:
4432 hint = _("uncommitted changes, use --all to discard all"
4439 hint = _("uncommitted changes, use --all to discard all"
4433 " changes, or 'hg update %s' to update") % ctx.rev()
4440 " changes, or 'hg update %s' to update") % ctx.rev()
4434 else:
4441 else:
4435 hint = _("use --all to revert all files,"
4442 hint = _("use --all to revert all files,"
4436 " or 'hg update %s' to update") % ctx.rev()
4443 " or 'hg update %s' to update") % ctx.rev()
4437 elif dirty:
4444 elif dirty:
4438 hint = _("uncommitted changes, use --all to discard all changes")
4445 hint = _("uncommitted changes, use --all to discard all changes")
4439 else:
4446 else:
4440 hint = _("use --all to revert all files")
4447 hint = _("use --all to revert all files")
4441 raise util.Abort(msg, hint=hint)
4448 raise util.Abort(msg, hint=hint)
4442
4449
4443 mf = ctx.manifest()
4450 mf = ctx.manifest()
4444 if node == parent:
4451 if node == parent:
4445 pmf = mf
4452 pmf = mf
4446 else:
4453 else:
4447 pmf = None
4454 pmf = None
4448
4455
4449 # need all matching names in dirstate and manifest of target rev,
4456 # need all matching names in dirstate and manifest of target rev,
4450 # so have to walk both. do not print errors if files exist in one
4457 # so have to walk both. do not print errors if files exist in one
4451 # but not other.
4458 # but not other.
4452
4459
4453 names = {}
4460 names = {}
4454
4461
4455 wlock = repo.wlock()
4462 wlock = repo.wlock()
4456 try:
4463 try:
4457 # walk dirstate.
4464 # walk dirstate.
4458
4465
4459 m = scmutil.match(repo[None], pats, opts)
4466 m = scmutil.match(repo[None], pats, opts)
4460 m.bad = lambda x, y: False
4467 m.bad = lambda x, y: False
4461 for abs in repo.walk(m):
4468 for abs in repo.walk(m):
4462 names[abs] = m.rel(abs), m.exact(abs)
4469 names[abs] = m.rel(abs), m.exact(abs)
4463
4470
4464 # walk target manifest.
4471 # walk target manifest.
4465
4472
4466 def badfn(path, msg):
4473 def badfn(path, msg):
4467 if path in names:
4474 if path in names:
4468 return
4475 return
4469 path_ = path + '/'
4476 path_ = path + '/'
4470 for f in names:
4477 for f in names:
4471 if f.startswith(path_):
4478 if f.startswith(path_):
4472 return
4479 return
4473 ui.warn("%s: %s\n" % (m.rel(path), msg))
4480 ui.warn("%s: %s\n" % (m.rel(path), msg))
4474
4481
4475 m = scmutil.match(repo[node], pats, opts)
4482 m = scmutil.match(repo[node], pats, opts)
4476 m.bad = badfn
4483 m.bad = badfn
4477 for abs in repo[node].walk(m):
4484 for abs in repo[node].walk(m):
4478 if abs not in names:
4485 if abs not in names:
4479 names[abs] = m.rel(abs), m.exact(abs)
4486 names[abs] = m.rel(abs), m.exact(abs)
4480
4487
4481 m = scmutil.matchfiles(repo, names)
4488 m = scmutil.matchfiles(repo, names)
4482 changes = repo.status(match=m)[:4]
4489 changes = repo.status(match=m)[:4]
4483 modified, added, removed, deleted = map(set, changes)
4490 modified, added, removed, deleted = map(set, changes)
4484
4491
4485 # if f is a rename, also revert the source
4492 # if f is a rename, also revert the source
4486 cwd = repo.getcwd()
4493 cwd = repo.getcwd()
4487 for f in added:
4494 for f in added:
4488 src = repo.dirstate.copied(f)
4495 src = repo.dirstate.copied(f)
4489 if src and src not in names and repo.dirstate[src] == 'r':
4496 if src and src not in names and repo.dirstate[src] == 'r':
4490 removed.add(src)
4497 removed.add(src)
4491 names[src] = (repo.pathto(src, cwd), True)
4498 names[src] = (repo.pathto(src, cwd), True)
4492
4499
4493 def removeforget(abs):
4500 def removeforget(abs):
4494 if repo.dirstate[abs] == 'a':
4501 if repo.dirstate[abs] == 'a':
4495 return _('forgetting %s\n')
4502 return _('forgetting %s\n')
4496 return _('removing %s\n')
4503 return _('removing %s\n')
4497
4504
4498 revert = ([], _('reverting %s\n'))
4505 revert = ([], _('reverting %s\n'))
4499 add = ([], _('adding %s\n'))
4506 add = ([], _('adding %s\n'))
4500 remove = ([], removeforget)
4507 remove = ([], removeforget)
4501 undelete = ([], _('undeleting %s\n'))
4508 undelete = ([], _('undeleting %s\n'))
4502
4509
4503 disptable = (
4510 disptable = (
4504 # dispatch table:
4511 # dispatch table:
4505 # file state
4512 # file state
4506 # action if in target manifest
4513 # action if in target manifest
4507 # action if not in target manifest
4514 # action if not in target manifest
4508 # make backup if in target manifest
4515 # make backup if in target manifest
4509 # make backup if not in target manifest
4516 # make backup if not in target manifest
4510 (modified, revert, remove, True, True),
4517 (modified, revert, remove, True, True),
4511 (added, revert, remove, True, False),
4518 (added, revert, remove, True, False),
4512 (removed, undelete, None, False, False),
4519 (removed, undelete, None, False, False),
4513 (deleted, revert, remove, False, False),
4520 (deleted, revert, remove, False, False),
4514 )
4521 )
4515
4522
4516 for abs, (rel, exact) in sorted(names.items()):
4523 for abs, (rel, exact) in sorted(names.items()):
4517 mfentry = mf.get(abs)
4524 mfentry = mf.get(abs)
4518 target = repo.wjoin(abs)
4525 target = repo.wjoin(abs)
4519 def handle(xlist, dobackup):
4526 def handle(xlist, dobackup):
4520 xlist[0].append(abs)
4527 xlist[0].append(abs)
4521 if (dobackup and not opts.get('no_backup') and
4528 if (dobackup and not opts.get('no_backup') and
4522 os.path.lexists(target)):
4529 os.path.lexists(target)):
4523 bakname = "%s.orig" % rel
4530 bakname = "%s.orig" % rel
4524 ui.note(_('saving current version of %s as %s\n') %
4531 ui.note(_('saving current version of %s as %s\n') %
4525 (rel, bakname))
4532 (rel, bakname))
4526 if not opts.get('dry_run'):
4533 if not opts.get('dry_run'):
4527 util.rename(target, bakname)
4534 util.rename(target, bakname)
4528 if ui.verbose or not exact:
4535 if ui.verbose or not exact:
4529 msg = xlist[1]
4536 msg = xlist[1]
4530 if not isinstance(msg, basestring):
4537 if not isinstance(msg, basestring):
4531 msg = msg(abs)
4538 msg = msg(abs)
4532 ui.status(msg % rel)
4539 ui.status(msg % rel)
4533 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4540 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4534 if abs not in table:
4541 if abs not in table:
4535 continue
4542 continue
4536 # file has changed in dirstate
4543 # file has changed in dirstate
4537 if mfentry:
4544 if mfentry:
4538 handle(hitlist, backuphit)
4545 handle(hitlist, backuphit)
4539 elif misslist is not None:
4546 elif misslist is not None:
4540 handle(misslist, backupmiss)
4547 handle(misslist, backupmiss)
4541 break
4548 break
4542 else:
4549 else:
4543 if abs not in repo.dirstate:
4550 if abs not in repo.dirstate:
4544 if mfentry:
4551 if mfentry:
4545 handle(add, True)
4552 handle(add, True)
4546 elif exact:
4553 elif exact:
4547 ui.warn(_('file not managed: %s\n') % rel)
4554 ui.warn(_('file not managed: %s\n') % rel)
4548 continue
4555 continue
4549 # file has not changed in dirstate
4556 # file has not changed in dirstate
4550 if node == parent:
4557 if node == parent:
4551 if exact:
4558 if exact:
4552 ui.warn(_('no changes needed to %s\n') % rel)
4559 ui.warn(_('no changes needed to %s\n') % rel)
4553 continue
4560 continue
4554 if pmf is None:
4561 if pmf is None:
4555 # only need parent manifest in this unlikely case,
4562 # only need parent manifest in this unlikely case,
4556 # so do not read by default
4563 # so do not read by default
4557 pmf = repo[parent].manifest()
4564 pmf = repo[parent].manifest()
4558 if abs in pmf:
4565 if abs in pmf:
4559 if mfentry:
4566 if mfentry:
4560 # if version of file is same in parent and target
4567 # if version of file is same in parent and target
4561 # manifests, do nothing
4568 # manifests, do nothing
4562 if (pmf[abs] != mfentry or
4569 if (pmf[abs] != mfentry or
4563 pmf.flags(abs) != mf.flags(abs)):
4570 pmf.flags(abs) != mf.flags(abs)):
4564 handle(revert, False)
4571 handle(revert, False)
4565 else:
4572 else:
4566 handle(remove, False)
4573 handle(remove, False)
4567
4574
4568 if not opts.get('dry_run'):
4575 if not opts.get('dry_run'):
4569 def checkout(f):
4576 def checkout(f):
4570 fc = ctx[f]
4577 fc = ctx[f]
4571 repo.wwrite(f, fc.data(), fc.flags())
4578 repo.wwrite(f, fc.data(), fc.flags())
4572
4579
4573 audit_path = scmutil.pathauditor(repo.root)
4580 audit_path = scmutil.pathauditor(repo.root)
4574 for f in remove[0]:
4581 for f in remove[0]:
4575 if repo.dirstate[f] == 'a':
4582 if repo.dirstate[f] == 'a':
4576 repo.dirstate.drop(f)
4583 repo.dirstate.drop(f)
4577 continue
4584 continue
4578 audit_path(f)
4585 audit_path(f)
4579 try:
4586 try:
4580 util.unlinkpath(repo.wjoin(f))
4587 util.unlinkpath(repo.wjoin(f))
4581 except OSError:
4588 except OSError:
4582 pass
4589 pass
4583 repo.dirstate.remove(f)
4590 repo.dirstate.remove(f)
4584
4591
4585 normal = None
4592 normal = None
4586 if node == parent:
4593 if node == parent:
4587 # We're reverting to our parent. If possible, we'd like status
4594 # We're reverting to our parent. If possible, we'd like status
4588 # to report the file as clean. We have to use normallookup for
4595 # to report the file as clean. We have to use normallookup for
4589 # merges to avoid losing information about merged/dirty files.
4596 # merges to avoid losing information about merged/dirty files.
4590 if p2 != nullid:
4597 if p2 != nullid:
4591 normal = repo.dirstate.normallookup
4598 normal = repo.dirstate.normallookup
4592 else:
4599 else:
4593 normal = repo.dirstate.normal
4600 normal = repo.dirstate.normal
4594 for f in revert[0]:
4601 for f in revert[0]:
4595 checkout(f)
4602 checkout(f)
4596 if normal:
4603 if normal:
4597 normal(f)
4604 normal(f)
4598
4605
4599 for f in add[0]:
4606 for f in add[0]:
4600 checkout(f)
4607 checkout(f)
4601 repo.dirstate.add(f)
4608 repo.dirstate.add(f)
4602
4609
4603 normal = repo.dirstate.normallookup
4610 normal = repo.dirstate.normallookup
4604 if node == parent and p2 == nullid:
4611 if node == parent and p2 == nullid:
4605 normal = repo.dirstate.normal
4612 normal = repo.dirstate.normal
4606 for f in undelete[0]:
4613 for f in undelete[0]:
4607 checkout(f)
4614 checkout(f)
4608 normal(f)
4615 normal(f)
4609
4616
4610 finally:
4617 finally:
4611 wlock.release()
4618 wlock.release()
4612
4619
4613 @command('rollback', dryrunopts +
4620 @command('rollback', dryrunopts +
4614 [('f', 'force', False, _('ignore safety measures'))])
4621 [('f', 'force', False, _('ignore safety measures'))])
4615 def rollback(ui, repo, **opts):
4622 def rollback(ui, repo, **opts):
4616 """roll back the last transaction (dangerous)
4623 """roll back the last transaction (dangerous)
4617
4624
4618 This command should be used with care. There is only one level of
4625 This command should be used with care. There is only one level of
4619 rollback, and there is no way to undo a rollback. It will also
4626 rollback, and there is no way to undo a rollback. It will also
4620 restore the dirstate at the time of the last transaction, losing
4627 restore the dirstate at the time of the last transaction, losing
4621 any dirstate changes since that time. This command does not alter
4628 any dirstate changes since that time. This command does not alter
4622 the working directory.
4629 the working directory.
4623
4630
4624 Transactions are used to encapsulate the effects of all commands
4631 Transactions are used to encapsulate the effects of all commands
4625 that create new changesets or propagate existing changesets into a
4632 that create new changesets or propagate existing changesets into a
4626 repository. For example, the following commands are transactional,
4633 repository. For example, the following commands are transactional,
4627 and their effects can be rolled back:
4634 and their effects can be rolled back:
4628
4635
4629 - commit
4636 - commit
4630 - import
4637 - import
4631 - pull
4638 - pull
4632 - push (with this repository as the destination)
4639 - push (with this repository as the destination)
4633 - unbundle
4640 - unbundle
4634
4641
4635 It's possible to lose data with rollback: commit, update back to
4642 It's possible to lose data with rollback: commit, update back to
4636 an older changeset, and then rollback. The update removes the
4643 an older changeset, and then rollback. The update removes the
4637 changes you committed from the working directory, and rollback
4644 changes you committed from the working directory, and rollback
4638 removes them from history. To avoid data loss, you must pass
4645 removes them from history. To avoid data loss, you must pass
4639 --force in this case.
4646 --force in this case.
4640
4647
4641 This command is not intended for use on public repositories. Once
4648 This command is not intended for use on public repositories. Once
4642 changes are visible for pull by other users, rolling a transaction
4649 changes are visible for pull by other users, rolling a transaction
4643 back locally is ineffective (someone else may already have pulled
4650 back locally is ineffective (someone else may already have pulled
4644 the changes). Furthermore, a race is possible with readers of the
4651 the changes). Furthermore, a race is possible with readers of the
4645 repository; for example an in-progress pull from the repository
4652 repository; for example an in-progress pull from the repository
4646 may fail if a rollback is performed.
4653 may fail if a rollback is performed.
4647
4654
4648 Returns 0 on success, 1 if no rollback data is available.
4655 Returns 0 on success, 1 if no rollback data is available.
4649 """
4656 """
4650 return repo.rollback(dryrun=opts.get('dry_run'),
4657 return repo.rollback(dryrun=opts.get('dry_run'),
4651 force=opts.get('force'))
4658 force=opts.get('force'))
4652
4659
4653 @command('root', [])
4660 @command('root', [])
4654 def root(ui, repo):
4661 def root(ui, repo):
4655 """print the root (top) of the current working directory
4662 """print the root (top) of the current working directory
4656
4663
4657 Print the root directory of the current repository.
4664 Print the root directory of the current repository.
4658
4665
4659 Returns 0 on success.
4666 Returns 0 on success.
4660 """
4667 """
4661 ui.write(repo.root + "\n")
4668 ui.write(repo.root + "\n")
4662
4669
4663 @command('^serve',
4670 @command('^serve',
4664 [('A', 'accesslog', '', _('name of access log file to write to'),
4671 [('A', 'accesslog', '', _('name of access log file to write to'),
4665 _('FILE')),
4672 _('FILE')),
4666 ('d', 'daemon', None, _('run server in background')),
4673 ('d', 'daemon', None, _('run server in background')),
4667 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4674 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4668 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4675 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4669 # use string type, then we can check if something was passed
4676 # use string type, then we can check if something was passed
4670 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4677 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4671 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4678 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4672 _('ADDR')),
4679 _('ADDR')),
4673 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4680 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4674 _('PREFIX')),
4681 _('PREFIX')),
4675 ('n', 'name', '',
4682 ('n', 'name', '',
4676 _('name to show in web pages (default: working directory)'), _('NAME')),
4683 _('name to show in web pages (default: working directory)'), _('NAME')),
4677 ('', 'web-conf', '',
4684 ('', 'web-conf', '',
4678 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4685 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4679 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4686 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4680 _('FILE')),
4687 _('FILE')),
4681 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4688 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4682 ('', 'stdio', None, _('for remote clients')),
4689 ('', 'stdio', None, _('for remote clients')),
4683 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4690 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4684 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4691 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4685 ('', 'style', '', _('template style to use'), _('STYLE')),
4692 ('', 'style', '', _('template style to use'), _('STYLE')),
4686 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4693 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4687 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4694 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4688 _('[OPTION]...'))
4695 _('[OPTION]...'))
4689 def serve(ui, repo, **opts):
4696 def serve(ui, repo, **opts):
4690 """start stand-alone webserver
4697 """start stand-alone webserver
4691
4698
4692 Start a local HTTP repository browser and pull server. You can use
4699 Start a local HTTP repository browser and pull server. You can use
4693 this for ad-hoc sharing and browsing of repositories. It is
4700 this for ad-hoc sharing and browsing of repositories. It is
4694 recommended to use a real web server to serve a repository for
4701 recommended to use a real web server to serve a repository for
4695 longer periods of time.
4702 longer periods of time.
4696
4703
4697 Please note that the server does not implement access control.
4704 Please note that the server does not implement access control.
4698 This means that, by default, anybody can read from the server and
4705 This means that, by default, anybody can read from the server and
4699 nobody can write to it by default. Set the ``web.allow_push``
4706 nobody can write to it by default. Set the ``web.allow_push``
4700 option to ``*`` to allow everybody to push to the server. You
4707 option to ``*`` to allow everybody to push to the server. You
4701 should use a real web server if you need to authenticate users.
4708 should use a real web server if you need to authenticate users.
4702
4709
4703 By default, the server logs accesses to stdout and errors to
4710 By default, the server logs accesses to stdout and errors to
4704 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4711 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4705 files.
4712 files.
4706
4713
4707 To have the server choose a free port number to listen on, specify
4714 To have the server choose a free port number to listen on, specify
4708 a port number of 0; in this case, the server will print the port
4715 a port number of 0; in this case, the server will print the port
4709 number it uses.
4716 number it uses.
4710
4717
4711 Returns 0 on success.
4718 Returns 0 on success.
4712 """
4719 """
4713
4720
4714 if opts["stdio"] and opts["cmdserver"]:
4721 if opts["stdio"] and opts["cmdserver"]:
4715 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4722 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4716
4723
4717 def checkrepo():
4724 def checkrepo():
4718 if repo is None:
4725 if repo is None:
4719 raise error.RepoError(_("There is no Mercurial repository here"
4726 raise error.RepoError(_("There is no Mercurial repository here"
4720 " (.hg not found)"))
4727 " (.hg not found)"))
4721
4728
4722 if opts["stdio"]:
4729 if opts["stdio"]:
4723 checkrepo()
4730 checkrepo()
4724 s = sshserver.sshserver(ui, repo)
4731 s = sshserver.sshserver(ui, repo)
4725 s.serve_forever()
4732 s.serve_forever()
4726
4733
4727 if opts["cmdserver"]:
4734 if opts["cmdserver"]:
4728 checkrepo()
4735 checkrepo()
4729 s = commandserver.server(ui, repo, opts["cmdserver"])
4736 s = commandserver.server(ui, repo, opts["cmdserver"])
4730 return s.serve()
4737 return s.serve()
4731
4738
4732 # this way we can check if something was given in the command-line
4739 # this way we can check if something was given in the command-line
4733 if opts.get('port'):
4740 if opts.get('port'):
4734 opts['port'] = util.getport(opts.get('port'))
4741 opts['port'] = util.getport(opts.get('port'))
4735
4742
4736 baseui = repo and repo.baseui or ui
4743 baseui = repo and repo.baseui or ui
4737 optlist = ("name templates style address port prefix ipv6"
4744 optlist = ("name templates style address port prefix ipv6"
4738 " accesslog errorlog certificate encoding")
4745 " accesslog errorlog certificate encoding")
4739 for o in optlist.split():
4746 for o in optlist.split():
4740 val = opts.get(o, '')
4747 val = opts.get(o, '')
4741 if val in (None, ''): # should check against default options instead
4748 if val in (None, ''): # should check against default options instead
4742 continue
4749 continue
4743 baseui.setconfig("web", o, val)
4750 baseui.setconfig("web", o, val)
4744 if repo and repo.ui != baseui:
4751 if repo and repo.ui != baseui:
4745 repo.ui.setconfig("web", o, val)
4752 repo.ui.setconfig("web", o, val)
4746
4753
4747 o = opts.get('web_conf') or opts.get('webdir_conf')
4754 o = opts.get('web_conf') or opts.get('webdir_conf')
4748 if not o:
4755 if not o:
4749 if not repo:
4756 if not repo:
4750 raise error.RepoError(_("There is no Mercurial repository"
4757 raise error.RepoError(_("There is no Mercurial repository"
4751 " here (.hg not found)"))
4758 " here (.hg not found)"))
4752 o = repo.root
4759 o = repo.root
4753
4760
4754 app = hgweb.hgweb(o, baseui=ui)
4761 app = hgweb.hgweb(o, baseui=ui)
4755
4762
4756 class service(object):
4763 class service(object):
4757 def init(self):
4764 def init(self):
4758 util.setsignalhandler()
4765 util.setsignalhandler()
4759 self.httpd = hgweb.server.create_server(ui, app)
4766 self.httpd = hgweb.server.create_server(ui, app)
4760
4767
4761 if opts['port'] and not ui.verbose:
4768 if opts['port'] and not ui.verbose:
4762 return
4769 return
4763
4770
4764 if self.httpd.prefix:
4771 if self.httpd.prefix:
4765 prefix = self.httpd.prefix.strip('/') + '/'
4772 prefix = self.httpd.prefix.strip('/') + '/'
4766 else:
4773 else:
4767 prefix = ''
4774 prefix = ''
4768
4775
4769 port = ':%d' % self.httpd.port
4776 port = ':%d' % self.httpd.port
4770 if port == ':80':
4777 if port == ':80':
4771 port = ''
4778 port = ''
4772
4779
4773 bindaddr = self.httpd.addr
4780 bindaddr = self.httpd.addr
4774 if bindaddr == '0.0.0.0':
4781 if bindaddr == '0.0.0.0':
4775 bindaddr = '*'
4782 bindaddr = '*'
4776 elif ':' in bindaddr: # IPv6
4783 elif ':' in bindaddr: # IPv6
4777 bindaddr = '[%s]' % bindaddr
4784 bindaddr = '[%s]' % bindaddr
4778
4785
4779 fqaddr = self.httpd.fqaddr
4786 fqaddr = self.httpd.fqaddr
4780 if ':' in fqaddr:
4787 if ':' in fqaddr:
4781 fqaddr = '[%s]' % fqaddr
4788 fqaddr = '[%s]' % fqaddr
4782 if opts['port']:
4789 if opts['port']:
4783 write = ui.status
4790 write = ui.status
4784 else:
4791 else:
4785 write = ui.write
4792 write = ui.write
4786 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4793 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4787 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4794 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4788
4795
4789 def run(self):
4796 def run(self):
4790 self.httpd.serve_forever()
4797 self.httpd.serve_forever()
4791
4798
4792 service = service()
4799 service = service()
4793
4800
4794 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4801 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4795
4802
4796 @command('showconfig|debugconfig',
4803 @command('showconfig|debugconfig',
4797 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4804 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4798 _('[-u] [NAME]...'))
4805 _('[-u] [NAME]...'))
4799 def showconfig(ui, repo, *values, **opts):
4806 def showconfig(ui, repo, *values, **opts):
4800 """show combined config settings from all hgrc files
4807 """show combined config settings from all hgrc files
4801
4808
4802 With no arguments, print names and values of all config items.
4809 With no arguments, print names and values of all config items.
4803
4810
4804 With one argument of the form section.name, print just the value
4811 With one argument of the form section.name, print just the value
4805 of that config item.
4812 of that config item.
4806
4813
4807 With multiple arguments, print names and values of all config
4814 With multiple arguments, print names and values of all config
4808 items with matching section names.
4815 items with matching section names.
4809
4816
4810 With --debug, the source (filename and line number) is printed
4817 With --debug, the source (filename and line number) is printed
4811 for each config item.
4818 for each config item.
4812
4819
4813 Returns 0 on success.
4820 Returns 0 on success.
4814 """
4821 """
4815
4822
4816 for f in scmutil.rcpath():
4823 for f in scmutil.rcpath():
4817 ui.debug('read config from: %s\n' % f)
4824 ui.debug('read config from: %s\n' % f)
4818 untrusted = bool(opts.get('untrusted'))
4825 untrusted = bool(opts.get('untrusted'))
4819 if values:
4826 if values:
4820 sections = [v for v in values if '.' not in v]
4827 sections = [v for v in values if '.' not in v]
4821 items = [v for v in values if '.' in v]
4828 items = [v for v in values if '.' in v]
4822 if len(items) > 1 or items and sections:
4829 if len(items) > 1 or items and sections:
4823 raise util.Abort(_('only one config item permitted'))
4830 raise util.Abort(_('only one config item permitted'))
4824 for section, name, value in ui.walkconfig(untrusted=untrusted):
4831 for section, name, value in ui.walkconfig(untrusted=untrusted):
4825 value = str(value).replace('\n', '\\n')
4832 value = str(value).replace('\n', '\\n')
4826 sectname = section + '.' + name
4833 sectname = section + '.' + name
4827 if values:
4834 if values:
4828 for v in values:
4835 for v in values:
4829 if v == section:
4836 if v == section:
4830 ui.debug('%s: ' %
4837 ui.debug('%s: ' %
4831 ui.configsource(section, name, untrusted))
4838 ui.configsource(section, name, untrusted))
4832 ui.write('%s=%s\n' % (sectname, value))
4839 ui.write('%s=%s\n' % (sectname, value))
4833 elif v == sectname:
4840 elif v == sectname:
4834 ui.debug('%s: ' %
4841 ui.debug('%s: ' %
4835 ui.configsource(section, name, untrusted))
4842 ui.configsource(section, name, untrusted))
4836 ui.write(value, '\n')
4843 ui.write(value, '\n')
4837 else:
4844 else:
4838 ui.debug('%s: ' %
4845 ui.debug('%s: ' %
4839 ui.configsource(section, name, untrusted))
4846 ui.configsource(section, name, untrusted))
4840 ui.write('%s=%s\n' % (sectname, value))
4847 ui.write('%s=%s\n' % (sectname, value))
4841
4848
4842 @command('^status|st',
4849 @command('^status|st',
4843 [('A', 'all', None, _('show status of all files')),
4850 [('A', 'all', None, _('show status of all files')),
4844 ('m', 'modified', None, _('show only modified files')),
4851 ('m', 'modified', None, _('show only modified files')),
4845 ('a', 'added', None, _('show only added files')),
4852 ('a', 'added', None, _('show only added files')),
4846 ('r', 'removed', None, _('show only removed files')),
4853 ('r', 'removed', None, _('show only removed files')),
4847 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4854 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4848 ('c', 'clean', None, _('show only files without changes')),
4855 ('c', 'clean', None, _('show only files without changes')),
4849 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4856 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4850 ('i', 'ignored', None, _('show only ignored files')),
4857 ('i', 'ignored', None, _('show only ignored files')),
4851 ('n', 'no-status', None, _('hide status prefix')),
4858 ('n', 'no-status', None, _('hide status prefix')),
4852 ('C', 'copies', None, _('show source of copied files')),
4859 ('C', 'copies', None, _('show source of copied files')),
4853 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4860 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4854 ('', 'rev', [], _('show difference from revision'), _('REV')),
4861 ('', 'rev', [], _('show difference from revision'), _('REV')),
4855 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4862 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4856 ] + walkopts + subrepoopts,
4863 ] + walkopts + subrepoopts,
4857 _('[OPTION]... [FILE]...'))
4864 _('[OPTION]... [FILE]...'))
4858 def status(ui, repo, *pats, **opts):
4865 def status(ui, repo, *pats, **opts):
4859 """show changed files in the working directory
4866 """show changed files in the working directory
4860
4867
4861 Show status of files in the repository. If names are given, only
4868 Show status of files in the repository. If names are given, only
4862 files that match are shown. Files that are clean or ignored or
4869 files that match are shown. Files that are clean or ignored or
4863 the source of a copy/move operation, are not listed unless
4870 the source of a copy/move operation, are not listed unless
4864 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4871 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4865 Unless options described with "show only ..." are given, the
4872 Unless options described with "show only ..." are given, the
4866 options -mardu are used.
4873 options -mardu are used.
4867
4874
4868 Option -q/--quiet hides untracked (unknown and ignored) files
4875 Option -q/--quiet hides untracked (unknown and ignored) files
4869 unless explicitly requested with -u/--unknown or -i/--ignored.
4876 unless explicitly requested with -u/--unknown or -i/--ignored.
4870
4877
4871 .. note::
4878 .. note::
4872 status may appear to disagree with diff if permissions have
4879 status may appear to disagree with diff if permissions have
4873 changed or a merge has occurred. The standard diff format does
4880 changed or a merge has occurred. The standard diff format does
4874 not report permission changes and diff only reports changes
4881 not report permission changes and diff only reports changes
4875 relative to one merge parent.
4882 relative to one merge parent.
4876
4883
4877 If one revision is given, it is used as the base revision.
4884 If one revision is given, it is used as the base revision.
4878 If two revisions are given, the differences between them are
4885 If two revisions are given, the differences between them are
4879 shown. The --change option can also be used as a shortcut to list
4886 shown. The --change option can also be used as a shortcut to list
4880 the changed files of a revision from its first parent.
4887 the changed files of a revision from its first parent.
4881
4888
4882 The codes used to show the status of files are::
4889 The codes used to show the status of files are::
4883
4890
4884 M = modified
4891 M = modified
4885 A = added
4892 A = added
4886 R = removed
4893 R = removed
4887 C = clean
4894 C = clean
4888 ! = missing (deleted by non-hg command, but still tracked)
4895 ! = missing (deleted by non-hg command, but still tracked)
4889 ? = not tracked
4896 ? = not tracked
4890 I = ignored
4897 I = ignored
4891 = origin of the previous file listed as A (added)
4898 = origin of the previous file listed as A (added)
4892
4899
4893 .. container:: verbose
4900 .. container:: verbose
4894
4901
4895 Examples:
4902 Examples:
4896
4903
4897 - show changes in the working directory relative to a changeset:
4904 - show changes in the working directory relative to a changeset:
4898
4905
4899 hg status --rev 9353
4906 hg status --rev 9353
4900
4907
4901 - show all changes including copies in an existing changeset::
4908 - show all changes including copies in an existing changeset::
4902
4909
4903 hg status --copies --change 9353
4910 hg status --copies --change 9353
4904
4911
4905 - get a NUL separated list of added files, suitable for xargs::
4912 - get a NUL separated list of added files, suitable for xargs::
4906
4913
4907 hg status -an0
4914 hg status -an0
4908
4915
4909 Returns 0 on success.
4916 Returns 0 on success.
4910 """
4917 """
4911
4918
4912 revs = opts.get('rev')
4919 revs = opts.get('rev')
4913 change = opts.get('change')
4920 change = opts.get('change')
4914
4921
4915 if revs and change:
4922 if revs and change:
4916 msg = _('cannot specify --rev and --change at the same time')
4923 msg = _('cannot specify --rev and --change at the same time')
4917 raise util.Abort(msg)
4924 raise util.Abort(msg)
4918 elif change:
4925 elif change:
4919 node2 = repo.lookup(change)
4926 node2 = repo.lookup(change)
4920 node1 = repo[node2].p1().node()
4927 node1 = repo[node2].p1().node()
4921 else:
4928 else:
4922 node1, node2 = scmutil.revpair(repo, revs)
4929 node1, node2 = scmutil.revpair(repo, revs)
4923
4930
4924 cwd = (pats and repo.getcwd()) or ''
4931 cwd = (pats and repo.getcwd()) or ''
4925 end = opts.get('print0') and '\0' or '\n'
4932 end = opts.get('print0') and '\0' or '\n'
4926 copy = {}
4933 copy = {}
4927 states = 'modified added removed deleted unknown ignored clean'.split()
4934 states = 'modified added removed deleted unknown ignored clean'.split()
4928 show = [k for k in states if opts.get(k)]
4935 show = [k for k in states if opts.get(k)]
4929 if opts.get('all'):
4936 if opts.get('all'):
4930 show += ui.quiet and (states[:4] + ['clean']) or states
4937 show += ui.quiet and (states[:4] + ['clean']) or states
4931 if not show:
4938 if not show:
4932 show = ui.quiet and states[:4] or states[:5]
4939 show = ui.quiet and states[:4] or states[:5]
4933
4940
4934 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4941 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4935 'ignored' in show, 'clean' in show, 'unknown' in show,
4942 'ignored' in show, 'clean' in show, 'unknown' in show,
4936 opts.get('subrepos'))
4943 opts.get('subrepos'))
4937 changestates = zip(states, 'MAR!?IC', stat)
4944 changestates = zip(states, 'MAR!?IC', stat)
4938
4945
4939 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4946 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4940 ctxn = repo[nullid]
4947 ctxn = repo[nullid]
4941 ctx1 = repo[node1]
4948 ctx1 = repo[node1]
4942 ctx2 = repo[node2]
4949 ctx2 = repo[node2]
4943 added = stat[1]
4950 added = stat[1]
4944 if node2 is None:
4951 if node2 is None:
4945 added = stat[0] + stat[1] # merged?
4952 added = stat[0] + stat[1] # merged?
4946
4953
4947 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4954 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4948 if k in added:
4955 if k in added:
4949 copy[k] = v
4956 copy[k] = v
4950 elif v in added:
4957 elif v in added:
4951 copy[v] = k
4958 copy[v] = k
4952
4959
4953 for state, char, files in changestates:
4960 for state, char, files in changestates:
4954 if state in show:
4961 if state in show:
4955 format = "%s %%s%s" % (char, end)
4962 format = "%s %%s%s" % (char, end)
4956 if opts.get('no_status'):
4963 if opts.get('no_status'):
4957 format = "%%s%s" % end
4964 format = "%%s%s" % end
4958
4965
4959 for f in files:
4966 for f in files:
4960 ui.write(format % repo.pathto(f, cwd),
4967 ui.write(format % repo.pathto(f, cwd),
4961 label='status.' + state)
4968 label='status.' + state)
4962 if f in copy:
4969 if f in copy:
4963 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4970 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4964 label='status.copied')
4971 label='status.copied')
4965
4972
4966 @command('^summary|sum',
4973 @command('^summary|sum',
4967 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4974 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4968 def summary(ui, repo, **opts):
4975 def summary(ui, repo, **opts):
4969 """summarize working directory state
4976 """summarize working directory state
4970
4977
4971 This generates a brief summary of the working directory state,
4978 This generates a brief summary of the working directory state,
4972 including parents, branch, commit status, and available updates.
4979 including parents, branch, commit status, and available updates.
4973
4980
4974 With the --remote option, this will check the default paths for
4981 With the --remote option, this will check the default paths for
4975 incoming and outgoing changes. This can be time-consuming.
4982 incoming and outgoing changes. This can be time-consuming.
4976
4983
4977 Returns 0 on success.
4984 Returns 0 on success.
4978 """
4985 """
4979
4986
4980 ctx = repo[None]
4987 ctx = repo[None]
4981 parents = ctx.parents()
4988 parents = ctx.parents()
4982 pnode = parents[0].node()
4989 pnode = parents[0].node()
4983 marks = []
4990 marks = []
4984
4991
4985 for p in parents:
4992 for p in parents:
4986 # label with log.changeset (instead of log.parent) since this
4993 # label with log.changeset (instead of log.parent) since this
4987 # shows a working directory parent *changeset*:
4994 # shows a working directory parent *changeset*:
4988 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4995 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4989 label='log.changeset')
4996 label='log.changeset')
4990 ui.write(' '.join(p.tags()), label='log.tag')
4997 ui.write(' '.join(p.tags()), label='log.tag')
4991 if p.bookmarks():
4998 if p.bookmarks():
4992 marks.extend(p.bookmarks())
4999 marks.extend(p.bookmarks())
4993 if p.rev() == -1:
5000 if p.rev() == -1:
4994 if not len(repo):
5001 if not len(repo):
4995 ui.write(_(' (empty repository)'))
5002 ui.write(_(' (empty repository)'))
4996 else:
5003 else:
4997 ui.write(_(' (no revision checked out)'))
5004 ui.write(_(' (no revision checked out)'))
4998 ui.write('\n')
5005 ui.write('\n')
4999 if p.description():
5006 if p.description():
5000 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5007 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5001 label='log.summary')
5008 label='log.summary')
5002
5009
5003 branch = ctx.branch()
5010 branch = ctx.branch()
5004 bheads = repo.branchheads(branch)
5011 bheads = repo.branchheads(branch)
5005 m = _('branch: %s\n') % branch
5012 m = _('branch: %s\n') % branch
5006 if branch != 'default':
5013 if branch != 'default':
5007 ui.write(m, label='log.branch')
5014 ui.write(m, label='log.branch')
5008 else:
5015 else:
5009 ui.status(m, label='log.branch')
5016 ui.status(m, label='log.branch')
5010
5017
5011 if marks:
5018 if marks:
5012 current = repo._bookmarkcurrent
5019 current = repo._bookmarkcurrent
5013 ui.write(_('bookmarks:'), label='log.bookmark')
5020 ui.write(_('bookmarks:'), label='log.bookmark')
5014 if current is not None:
5021 if current is not None:
5015 try:
5022 try:
5016 marks.remove(current)
5023 marks.remove(current)
5017 ui.write(' *' + current, label='bookmarks.current')
5024 ui.write(' *' + current, label='bookmarks.current')
5018 except ValueError:
5025 except ValueError:
5019 # current bookmark not in parent ctx marks
5026 # current bookmark not in parent ctx marks
5020 pass
5027 pass
5021 for m in marks:
5028 for m in marks:
5022 ui.write(' ' + m, label='log.bookmark')
5029 ui.write(' ' + m, label='log.bookmark')
5023 ui.write('\n', label='log.bookmark')
5030 ui.write('\n', label='log.bookmark')
5024
5031
5025 st = list(repo.status(unknown=True))[:6]
5032 st = list(repo.status(unknown=True))[:6]
5026
5033
5027 c = repo.dirstate.copies()
5034 c = repo.dirstate.copies()
5028 copied, renamed = [], []
5035 copied, renamed = [], []
5029 for d, s in c.iteritems():
5036 for d, s in c.iteritems():
5030 if s in st[2]:
5037 if s in st[2]:
5031 st[2].remove(s)
5038 st[2].remove(s)
5032 renamed.append(d)
5039 renamed.append(d)
5033 else:
5040 else:
5034 copied.append(d)
5041 copied.append(d)
5035 if d in st[1]:
5042 if d in st[1]:
5036 st[1].remove(d)
5043 st[1].remove(d)
5037 st.insert(3, renamed)
5044 st.insert(3, renamed)
5038 st.insert(4, copied)
5045 st.insert(4, copied)
5039
5046
5040 ms = mergemod.mergestate(repo)
5047 ms = mergemod.mergestate(repo)
5041 st.append([f for f in ms if ms[f] == 'u'])
5048 st.append([f for f in ms if ms[f] == 'u'])
5042
5049
5043 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5050 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5044 st.append(subs)
5051 st.append(subs)
5045
5052
5046 labels = [ui.label(_('%d modified'), 'status.modified'),
5053 labels = [ui.label(_('%d modified'), 'status.modified'),
5047 ui.label(_('%d added'), 'status.added'),
5054 ui.label(_('%d added'), 'status.added'),
5048 ui.label(_('%d removed'), 'status.removed'),
5055 ui.label(_('%d removed'), 'status.removed'),
5049 ui.label(_('%d renamed'), 'status.copied'),
5056 ui.label(_('%d renamed'), 'status.copied'),
5050 ui.label(_('%d copied'), 'status.copied'),
5057 ui.label(_('%d copied'), 'status.copied'),
5051 ui.label(_('%d deleted'), 'status.deleted'),
5058 ui.label(_('%d deleted'), 'status.deleted'),
5052 ui.label(_('%d unknown'), 'status.unknown'),
5059 ui.label(_('%d unknown'), 'status.unknown'),
5053 ui.label(_('%d ignored'), 'status.ignored'),
5060 ui.label(_('%d ignored'), 'status.ignored'),
5054 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5061 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5055 ui.label(_('%d subrepos'), 'status.modified')]
5062 ui.label(_('%d subrepos'), 'status.modified')]
5056 t = []
5063 t = []
5057 for s, l in zip(st, labels):
5064 for s, l in zip(st, labels):
5058 if s:
5065 if s:
5059 t.append(l % len(s))
5066 t.append(l % len(s))
5060
5067
5061 t = ', '.join(t)
5068 t = ', '.join(t)
5062 cleanworkdir = False
5069 cleanworkdir = False
5063
5070
5064 if len(parents) > 1:
5071 if len(parents) > 1:
5065 t += _(' (merge)')
5072 t += _(' (merge)')
5066 elif branch != parents[0].branch():
5073 elif branch != parents[0].branch():
5067 t += _(' (new branch)')
5074 t += _(' (new branch)')
5068 elif (parents[0].extra().get('close') and
5075 elif (parents[0].extra().get('close') and
5069 pnode in repo.branchheads(branch, closed=True)):
5076 pnode in repo.branchheads(branch, closed=True)):
5070 t += _(' (head closed)')
5077 t += _(' (head closed)')
5071 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5078 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5072 t += _(' (clean)')
5079 t += _(' (clean)')
5073 cleanworkdir = True
5080 cleanworkdir = True
5074 elif pnode not in bheads:
5081 elif pnode not in bheads:
5075 t += _(' (new branch head)')
5082 t += _(' (new branch head)')
5076
5083
5077 if cleanworkdir:
5084 if cleanworkdir:
5078 ui.status(_('commit: %s\n') % t.strip())
5085 ui.status(_('commit: %s\n') % t.strip())
5079 else:
5086 else:
5080 ui.write(_('commit: %s\n') % t.strip())
5087 ui.write(_('commit: %s\n') % t.strip())
5081
5088
5082 # all ancestors of branch heads - all ancestors of parent = new csets
5089 # all ancestors of branch heads - all ancestors of parent = new csets
5083 new = [0] * len(repo)
5090 new = [0] * len(repo)
5084 cl = repo.changelog
5091 cl = repo.changelog
5085 for a in [cl.rev(n) for n in bheads]:
5092 for a in [cl.rev(n) for n in bheads]:
5086 new[a] = 1
5093 new[a] = 1
5087 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5094 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5088 new[a] = 1
5095 new[a] = 1
5089 for a in [p.rev() for p in parents]:
5096 for a in [p.rev() for p in parents]:
5090 if a >= 0:
5097 if a >= 0:
5091 new[a] = 0
5098 new[a] = 0
5092 for a in cl.ancestors(*[p.rev() for p in parents]):
5099 for a in cl.ancestors(*[p.rev() for p in parents]):
5093 new[a] = 0
5100 new[a] = 0
5094 new = sum(new)
5101 new = sum(new)
5095
5102
5096 if new == 0:
5103 if new == 0:
5097 ui.status(_('update: (current)\n'))
5104 ui.status(_('update: (current)\n'))
5098 elif pnode not in bheads:
5105 elif pnode not in bheads:
5099 ui.write(_('update: %d new changesets (update)\n') % new)
5106 ui.write(_('update: %d new changesets (update)\n') % new)
5100 else:
5107 else:
5101 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5108 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5102 (new, len(bheads)))
5109 (new, len(bheads)))
5103
5110
5104 if opts.get('remote'):
5111 if opts.get('remote'):
5105 t = []
5112 t = []
5106 source, branches = hg.parseurl(ui.expandpath('default'))
5113 source, branches = hg.parseurl(ui.expandpath('default'))
5107 other = hg.peer(repo, {}, source)
5114 other = hg.peer(repo, {}, source)
5108 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5115 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5109 ui.debug('comparing with %s\n' % util.hidepassword(source))
5116 ui.debug('comparing with %s\n' % util.hidepassword(source))
5110 repo.ui.pushbuffer()
5117 repo.ui.pushbuffer()
5111 commoninc = discovery.findcommonincoming(repo, other)
5118 commoninc = discovery.findcommonincoming(repo, other)
5112 _common, incoming, _rheads = commoninc
5119 _common, incoming, _rheads = commoninc
5113 repo.ui.popbuffer()
5120 repo.ui.popbuffer()
5114 if incoming:
5121 if incoming:
5115 t.append(_('1 or more incoming'))
5122 t.append(_('1 or more incoming'))
5116
5123
5117 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5124 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5118 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5125 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5119 if source != dest:
5126 if source != dest:
5120 other = hg.peer(repo, {}, dest)
5127 other = hg.peer(repo, {}, dest)
5121 commoninc = None
5128 commoninc = None
5122 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5129 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5123 repo.ui.pushbuffer()
5130 repo.ui.pushbuffer()
5124 common, outheads = discovery.findcommonoutgoing(repo, other,
5131 common, outheads = discovery.findcommonoutgoing(repo, other,
5125 commoninc=commoninc)
5132 commoninc=commoninc)
5126 repo.ui.popbuffer()
5133 repo.ui.popbuffer()
5127 o = repo.changelog.findmissing(common=common, heads=outheads)
5134 o = repo.changelog.findmissing(common=common, heads=outheads)
5128 if o:
5135 if o:
5129 t.append(_('%d outgoing') % len(o))
5136 t.append(_('%d outgoing') % len(o))
5130 if 'bookmarks' in other.listkeys('namespaces'):
5137 if 'bookmarks' in other.listkeys('namespaces'):
5131 lmarks = repo.listkeys('bookmarks')
5138 lmarks = repo.listkeys('bookmarks')
5132 rmarks = other.listkeys('bookmarks')
5139 rmarks = other.listkeys('bookmarks')
5133 diff = set(rmarks) - set(lmarks)
5140 diff = set(rmarks) - set(lmarks)
5134 if len(diff) > 0:
5141 if len(diff) > 0:
5135 t.append(_('%d incoming bookmarks') % len(diff))
5142 t.append(_('%d incoming bookmarks') % len(diff))
5136 diff = set(lmarks) - set(rmarks)
5143 diff = set(lmarks) - set(rmarks)
5137 if len(diff) > 0:
5144 if len(diff) > 0:
5138 t.append(_('%d outgoing bookmarks') % len(diff))
5145 t.append(_('%d outgoing bookmarks') % len(diff))
5139
5146
5140 if t:
5147 if t:
5141 ui.write(_('remote: %s\n') % (', '.join(t)))
5148 ui.write(_('remote: %s\n') % (', '.join(t)))
5142 else:
5149 else:
5143 ui.status(_('remote: (synced)\n'))
5150 ui.status(_('remote: (synced)\n'))
5144
5151
5145 @command('tag',
5152 @command('tag',
5146 [('f', 'force', None, _('force tag')),
5153 [('f', 'force', None, _('force tag')),
5147 ('l', 'local', None, _('make the tag local')),
5154 ('l', 'local', None, _('make the tag local')),
5148 ('r', 'rev', '', _('revision to tag'), _('REV')),
5155 ('r', 'rev', '', _('revision to tag'), _('REV')),
5149 ('', 'remove', None, _('remove a tag')),
5156 ('', 'remove', None, _('remove a tag')),
5150 # -l/--local is already there, commitopts cannot be used
5157 # -l/--local is already there, commitopts cannot be used
5151 ('e', 'edit', None, _('edit commit message')),
5158 ('e', 'edit', None, _('edit commit message')),
5152 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5159 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5153 ] + commitopts2,
5160 ] + commitopts2,
5154 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5161 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5155 def tag(ui, repo, name1, *names, **opts):
5162 def tag(ui, repo, name1, *names, **opts):
5156 """add one or more tags for the current or given revision
5163 """add one or more tags for the current or given revision
5157
5164
5158 Name a particular revision using <name>.
5165 Name a particular revision using <name>.
5159
5166
5160 Tags are used to name particular revisions of the repository and are
5167 Tags are used to name particular revisions of the repository and are
5161 very useful to compare different revisions, to go back to significant
5168 very useful to compare different revisions, to go back to significant
5162 earlier versions or to mark branch points as releases, etc. Changing
5169 earlier versions or to mark branch points as releases, etc. Changing
5163 an existing tag is normally disallowed; use -f/--force to override.
5170 an existing tag is normally disallowed; use -f/--force to override.
5164
5171
5165 If no revision is given, the parent of the working directory is
5172 If no revision is given, the parent of the working directory is
5166 used, or tip if no revision is checked out.
5173 used, or tip if no revision is checked out.
5167
5174
5168 To facilitate version control, distribution, and merging of tags,
5175 To facilitate version control, distribution, and merging of tags,
5169 they are stored as a file named ".hgtags" which is managed similarly
5176 they are stored as a file named ".hgtags" which is managed similarly
5170 to other project files and can be hand-edited if necessary. This
5177 to other project files and can be hand-edited if necessary. This
5171 also means that tagging creates a new commit. The file
5178 also means that tagging creates a new commit. The file
5172 ".hg/localtags" is used for local tags (not shared among
5179 ".hg/localtags" is used for local tags (not shared among
5173 repositories).
5180 repositories).
5174
5181
5175 Tag commits are usually made at the head of a branch. If the parent
5182 Tag commits are usually made at the head of a branch. If the parent
5176 of the working directory is not a branch head, :hg:`tag` aborts; use
5183 of the working directory is not a branch head, :hg:`tag` aborts; use
5177 -f/--force to force the tag commit to be based on a non-head
5184 -f/--force to force the tag commit to be based on a non-head
5178 changeset.
5185 changeset.
5179
5186
5180 See :hg:`help dates` for a list of formats valid for -d/--date.
5187 See :hg:`help dates` for a list of formats valid for -d/--date.
5181
5188
5182 Since tag names have priority over branch names during revision
5189 Since tag names have priority over branch names during revision
5183 lookup, using an existing branch name as a tag name is discouraged.
5190 lookup, using an existing branch name as a tag name is discouraged.
5184
5191
5185 Returns 0 on success.
5192 Returns 0 on success.
5186 """
5193 """
5187
5194
5188 rev_ = "."
5195 rev_ = "."
5189 names = [t.strip() for t in (name1,) + names]
5196 names = [t.strip() for t in (name1,) + names]
5190 if len(names) != len(set(names)):
5197 if len(names) != len(set(names)):
5191 raise util.Abort(_('tag names must be unique'))
5198 raise util.Abort(_('tag names must be unique'))
5192 for n in names:
5199 for n in names:
5193 if n in ['tip', '.', 'null']:
5200 if n in ['tip', '.', 'null']:
5194 raise util.Abort(_("the name '%s' is reserved") % n)
5201 raise util.Abort(_("the name '%s' is reserved") % n)
5195 if not n:
5202 if not n:
5196 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5203 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5197 if opts.get('rev') and opts.get('remove'):
5204 if opts.get('rev') and opts.get('remove'):
5198 raise util.Abort(_("--rev and --remove are incompatible"))
5205 raise util.Abort(_("--rev and --remove are incompatible"))
5199 if opts.get('rev'):
5206 if opts.get('rev'):
5200 rev_ = opts['rev']
5207 rev_ = opts['rev']
5201 message = opts.get('message')
5208 message = opts.get('message')
5202 if opts.get('remove'):
5209 if opts.get('remove'):
5203 expectedtype = opts.get('local') and 'local' or 'global'
5210 expectedtype = opts.get('local') and 'local' or 'global'
5204 for n in names:
5211 for n in names:
5205 if not repo.tagtype(n):
5212 if not repo.tagtype(n):
5206 raise util.Abort(_("tag '%s' does not exist") % n)
5213 raise util.Abort(_("tag '%s' does not exist") % n)
5207 if repo.tagtype(n) != expectedtype:
5214 if repo.tagtype(n) != expectedtype:
5208 if expectedtype == 'global':
5215 if expectedtype == 'global':
5209 raise util.Abort(_("tag '%s' is not a global tag") % n)
5216 raise util.Abort(_("tag '%s' is not a global tag") % n)
5210 else:
5217 else:
5211 raise util.Abort(_("tag '%s' is not a local tag") % n)
5218 raise util.Abort(_("tag '%s' is not a local tag") % n)
5212 rev_ = nullid
5219 rev_ = nullid
5213 if not message:
5220 if not message:
5214 # we don't translate commit messages
5221 # we don't translate commit messages
5215 message = 'Removed tag %s' % ', '.join(names)
5222 message = 'Removed tag %s' % ', '.join(names)
5216 elif not opts.get('force'):
5223 elif not opts.get('force'):
5217 for n in names:
5224 for n in names:
5218 if n in repo.tags():
5225 if n in repo.tags():
5219 raise util.Abort(_("tag '%s' already exists "
5226 raise util.Abort(_("tag '%s' already exists "
5220 "(use -f to force)") % n)
5227 "(use -f to force)") % n)
5221 if not opts.get('local'):
5228 if not opts.get('local'):
5222 p1, p2 = repo.dirstate.parents()
5229 p1, p2 = repo.dirstate.parents()
5223 if p2 != nullid:
5230 if p2 != nullid:
5224 raise util.Abort(_('uncommitted merge'))
5231 raise util.Abort(_('uncommitted merge'))
5225 bheads = repo.branchheads()
5232 bheads = repo.branchheads()
5226 if not opts.get('force') and bheads and p1 not in bheads:
5233 if not opts.get('force') and bheads and p1 not in bheads:
5227 raise util.Abort(_('not at a branch head (use -f to force)'))
5234 raise util.Abort(_('not at a branch head (use -f to force)'))
5228 r = scmutil.revsingle(repo, rev_).node()
5235 r = scmutil.revsingle(repo, rev_).node()
5229
5236
5230 if not message:
5237 if not message:
5231 # we don't translate commit messages
5238 # we don't translate commit messages
5232 message = ('Added tag %s for changeset %s' %
5239 message = ('Added tag %s for changeset %s' %
5233 (', '.join(names), short(r)))
5240 (', '.join(names), short(r)))
5234
5241
5235 date = opts.get('date')
5242 date = opts.get('date')
5236 if date:
5243 if date:
5237 date = util.parsedate(date)
5244 date = util.parsedate(date)
5238
5245
5239 if opts.get('edit'):
5246 if opts.get('edit'):
5240 message = ui.edit(message, ui.username())
5247 message = ui.edit(message, ui.username())
5241
5248
5242 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5249 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5243
5250
5244 @command('tags', [], '')
5251 @command('tags', [], '')
5245 def tags(ui, repo):
5252 def tags(ui, repo):
5246 """list repository tags
5253 """list repository tags
5247
5254
5248 This lists both regular and local tags. When the -v/--verbose
5255 This lists both regular and local tags. When the -v/--verbose
5249 switch is used, a third column "local" is printed for local tags.
5256 switch is used, a third column "local" is printed for local tags.
5250
5257
5251 Returns 0 on success.
5258 Returns 0 on success.
5252 """
5259 """
5253
5260
5254 hexfunc = ui.debugflag and hex or short
5261 hexfunc = ui.debugflag and hex or short
5255 tagtype = ""
5262 tagtype = ""
5256
5263
5257 for t, n in reversed(repo.tagslist()):
5264 for t, n in reversed(repo.tagslist()):
5258 if ui.quiet:
5265 if ui.quiet:
5259 ui.write("%s\n" % t, label='tags.normal')
5266 ui.write("%s\n" % t, label='tags.normal')
5260 continue
5267 continue
5261
5268
5262 hn = hexfunc(n)
5269 hn = hexfunc(n)
5263 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5270 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5264 rev = ui.label(r, 'log.changeset')
5271 rev = ui.label(r, 'log.changeset')
5265 spaces = " " * (30 - encoding.colwidth(t))
5272 spaces = " " * (30 - encoding.colwidth(t))
5266
5273
5267 tag = ui.label(t, 'tags.normal')
5274 tag = ui.label(t, 'tags.normal')
5268 if ui.verbose:
5275 if ui.verbose:
5269 if repo.tagtype(t) == 'local':
5276 if repo.tagtype(t) == 'local':
5270 tagtype = " local"
5277 tagtype = " local"
5271 tag = ui.label(t, 'tags.local')
5278 tag = ui.label(t, 'tags.local')
5272 else:
5279 else:
5273 tagtype = ""
5280 tagtype = ""
5274 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5281 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5275
5282
5276 @command('tip',
5283 @command('tip',
5277 [('p', 'patch', None, _('show patch')),
5284 [('p', 'patch', None, _('show patch')),
5278 ('g', 'git', None, _('use git extended diff format')),
5285 ('g', 'git', None, _('use git extended diff format')),
5279 ] + templateopts,
5286 ] + templateopts,
5280 _('[-p] [-g]'))
5287 _('[-p] [-g]'))
5281 def tip(ui, repo, **opts):
5288 def tip(ui, repo, **opts):
5282 """show the tip revision
5289 """show the tip revision
5283
5290
5284 The tip revision (usually just called the tip) is the changeset
5291 The tip revision (usually just called the tip) is the changeset
5285 most recently added to the repository (and therefore the most
5292 most recently added to the repository (and therefore the most
5286 recently changed head).
5293 recently changed head).
5287
5294
5288 If you have just made a commit, that commit will be the tip. If
5295 If you have just made a commit, that commit will be the tip. If
5289 you have just pulled changes from another repository, the tip of
5296 you have just pulled changes from another repository, the tip of
5290 that repository becomes the current tip. The "tip" tag is special
5297 that repository becomes the current tip. The "tip" tag is special
5291 and cannot be renamed or assigned to a different changeset.
5298 and cannot be renamed or assigned to a different changeset.
5292
5299
5293 Returns 0 on success.
5300 Returns 0 on success.
5294 """
5301 """
5295 displayer = cmdutil.show_changeset(ui, repo, opts)
5302 displayer = cmdutil.show_changeset(ui, repo, opts)
5296 displayer.show(repo[len(repo) - 1])
5303 displayer.show(repo[len(repo) - 1])
5297 displayer.close()
5304 displayer.close()
5298
5305
5299 @command('unbundle',
5306 @command('unbundle',
5300 [('u', 'update', None,
5307 [('u', 'update', None,
5301 _('update to new branch head if changesets were unbundled'))],
5308 _('update to new branch head if changesets were unbundled'))],
5302 _('[-u] FILE...'))
5309 _('[-u] FILE...'))
5303 def unbundle(ui, repo, fname1, *fnames, **opts):
5310 def unbundle(ui, repo, fname1, *fnames, **opts):
5304 """apply one or more changegroup files
5311 """apply one or more changegroup files
5305
5312
5306 Apply one or more compressed changegroup files generated by the
5313 Apply one or more compressed changegroup files generated by the
5307 bundle command.
5314 bundle command.
5308
5315
5309 Returns 0 on success, 1 if an update has unresolved files.
5316 Returns 0 on success, 1 if an update has unresolved files.
5310 """
5317 """
5311 fnames = (fname1,) + fnames
5318 fnames = (fname1,) + fnames
5312
5319
5313 lock = repo.lock()
5320 lock = repo.lock()
5314 wc = repo['.']
5321 wc = repo['.']
5315 try:
5322 try:
5316 for fname in fnames:
5323 for fname in fnames:
5317 f = url.open(ui, fname)
5324 f = url.open(ui, fname)
5318 gen = changegroup.readbundle(f, fname)
5325 gen = changegroup.readbundle(f, fname)
5319 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5326 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5320 lock=lock)
5327 lock=lock)
5321 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5328 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5322 finally:
5329 finally:
5323 lock.release()
5330 lock.release()
5324 return postincoming(ui, repo, modheads, opts.get('update'), None)
5331 return postincoming(ui, repo, modheads, opts.get('update'), None)
5325
5332
5326 @command('^update|up|checkout|co',
5333 @command('^update|up|checkout|co',
5327 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5334 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5328 ('c', 'check', None,
5335 ('c', 'check', None,
5329 _('update across branches if no uncommitted changes')),
5336 _('update across branches if no uncommitted changes')),
5330 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5337 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5331 ('r', 'rev', '', _('revision'), _('REV'))],
5338 ('r', 'rev', '', _('revision'), _('REV'))],
5332 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5339 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5333 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5340 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5334 """update working directory (or switch revisions)
5341 """update working directory (or switch revisions)
5335
5342
5336 Update the repository's working directory to the specified
5343 Update the repository's working directory to the specified
5337 changeset. If no changeset is specified, update to the tip of the
5344 changeset. If no changeset is specified, update to the tip of the
5338 current named branch.
5345 current named branch.
5339
5346
5340 If the changeset is not a descendant of the working directory's
5347 If the changeset is not a descendant of the working directory's
5341 parent, the update is aborted. With the -c/--check option, the
5348 parent, the update is aborted. With the -c/--check option, the
5342 working directory is checked for uncommitted changes; if none are
5349 working directory is checked for uncommitted changes; if none are
5343 found, the working directory is updated to the specified
5350 found, the working directory is updated to the specified
5344 changeset.
5351 changeset.
5345
5352
5346 Update sets the working directory's parent revison to the specified
5353 Update sets the working directory's parent revison to the specified
5347 changeset (see :hg:`help parents`).
5354 changeset (see :hg:`help parents`).
5348
5355
5349 The following rules apply when the working directory contains
5356 The following rules apply when the working directory contains
5350 uncommitted changes:
5357 uncommitted changes:
5351
5358
5352 1. If neither -c/--check nor -C/--clean is specified, and if
5359 1. If neither -c/--check nor -C/--clean is specified, and if
5353 the requested changeset is an ancestor or descendant of
5360 the requested changeset is an ancestor or descendant of
5354 the working directory's parent, the uncommitted changes
5361 the working directory's parent, the uncommitted changes
5355 are merged into the requested changeset and the merged
5362 are merged into the requested changeset and the merged
5356 result is left uncommitted. If the requested changeset is
5363 result is left uncommitted. If the requested changeset is
5357 not an ancestor or descendant (that is, it is on another
5364 not an ancestor or descendant (that is, it is on another
5358 branch), the update is aborted and the uncommitted changes
5365 branch), the update is aborted and the uncommitted changes
5359 are preserved.
5366 are preserved.
5360
5367
5361 2. With the -c/--check option, the update is aborted and the
5368 2. With the -c/--check option, the update is aborted and the
5362 uncommitted changes are preserved.
5369 uncommitted changes are preserved.
5363
5370
5364 3. With the -C/--clean option, uncommitted changes are discarded and
5371 3. With the -C/--clean option, uncommitted changes are discarded and
5365 the working directory is updated to the requested changeset.
5372 the working directory is updated to the requested changeset.
5366
5373
5367 Use null as the changeset to remove the working directory (like
5374 Use null as the changeset to remove the working directory (like
5368 :hg:`clone -U`).
5375 :hg:`clone -U`).
5369
5376
5370 If you want to revert just one file to an older revision, use
5377 If you want to revert just one file to an older revision, use
5371 :hg:`revert [-r REV] NAME`.
5378 :hg:`revert [-r REV] NAME`.
5372
5379
5373 See :hg:`help dates` for a list of formats valid for -d/--date.
5380 See :hg:`help dates` for a list of formats valid for -d/--date.
5374
5381
5375 Returns 0 on success, 1 if there are unresolved files.
5382 Returns 0 on success, 1 if there are unresolved files.
5376 """
5383 """
5377 if rev and node:
5384 if rev and node:
5378 raise util.Abort(_("please specify just one revision"))
5385 raise util.Abort(_("please specify just one revision"))
5379
5386
5380 if rev is None or rev == '':
5387 if rev is None or rev == '':
5381 rev = node
5388 rev = node
5382
5389
5383 # if we defined a bookmark, we have to remember the original bookmark name
5390 # if we defined a bookmark, we have to remember the original bookmark name
5384 brev = rev
5391 brev = rev
5385 rev = scmutil.revsingle(repo, rev, rev).rev()
5392 rev = scmutil.revsingle(repo, rev, rev).rev()
5386
5393
5387 if check and clean:
5394 if check and clean:
5388 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5395 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5389
5396
5390 if check:
5397 if check:
5391 # we could use dirty() but we can ignore merge and branch trivia
5398 # we could use dirty() but we can ignore merge and branch trivia
5392 c = repo[None]
5399 c = repo[None]
5393 if c.modified() or c.added() or c.removed():
5400 if c.modified() or c.added() or c.removed():
5394 raise util.Abort(_("uncommitted local changes"))
5401 raise util.Abort(_("uncommitted local changes"))
5395
5402
5396 if date:
5403 if date:
5397 if rev is not None:
5404 if rev is not None:
5398 raise util.Abort(_("you can't specify a revision and a date"))
5405 raise util.Abort(_("you can't specify a revision and a date"))
5399 rev = cmdutil.finddate(ui, repo, date)
5406 rev = cmdutil.finddate(ui, repo, date)
5400
5407
5401 if clean or check:
5408 if clean or check:
5402 ret = hg.clean(repo, rev)
5409 ret = hg.clean(repo, rev)
5403 else:
5410 else:
5404 ret = hg.update(repo, rev)
5411 ret = hg.update(repo, rev)
5405
5412
5406 if brev in repo._bookmarks:
5413 if brev in repo._bookmarks:
5407 bookmarks.setcurrent(repo, brev)
5414 bookmarks.setcurrent(repo, brev)
5408
5415
5409 return ret
5416 return ret
5410
5417
5411 @command('verify', [])
5418 @command('verify', [])
5412 def verify(ui, repo):
5419 def verify(ui, repo):
5413 """verify the integrity of the repository
5420 """verify the integrity of the repository
5414
5421
5415 Verify the integrity of the current repository.
5422 Verify the integrity of the current repository.
5416
5423
5417 This will perform an extensive check of the repository's
5424 This will perform an extensive check of the repository's
5418 integrity, validating the hashes and checksums of each entry in
5425 integrity, validating the hashes and checksums of each entry in
5419 the changelog, manifest, and tracked files, as well as the
5426 the changelog, manifest, and tracked files, as well as the
5420 integrity of their crosslinks and indices.
5427 integrity of their crosslinks and indices.
5421
5428
5422 Returns 0 on success, 1 if errors are encountered.
5429 Returns 0 on success, 1 if errors are encountered.
5423 """
5430 """
5424 return hg.verify(repo)
5431 return hg.verify(repo)
5425
5432
5426 @command('version', [])
5433 @command('version', [])
5427 def version_(ui):
5434 def version_(ui):
5428 """output version and copyright information"""
5435 """output version and copyright information"""
5429 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5436 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5430 % util.version())
5437 % util.version())
5431 ui.status(_(
5438 ui.status(_(
5432 "(see http://mercurial.selenic.com for more information)\n"
5439 "(see http://mercurial.selenic.com for more information)\n"
5433 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5440 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5434 "This is free software; see the source for copying conditions. "
5441 "This is free software; see the source for copying conditions. "
5435 "There is NO\nwarranty; "
5442 "There is NO\nwarranty; "
5436 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5443 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5437 ))
5444 ))
5438
5445
5439 norepo = ("clone init version help debugcommands debugcomplete"
5446 norepo = ("clone init version help debugcommands debugcomplete"
5440 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5447 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5441 " debugknown debuggetbundle debugbundle")
5448 " debugknown debuggetbundle debugbundle")
5442 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5449 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5443 " debugdata debugindex debugindexdot debugrevlog")
5450 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,256 +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
64 repository tip rolled back to revision 1 (undo commit)
64 repository tip rolled back to revision 1 (undo import)
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
76 repository tip rolled back to revision 1 (undo commit)
76 repository tip rolled back to revision 1 (undo import)
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
98 repository tip rolled back to revision 1 (undo commit)
98 repository tip rolled back to revision 1 (undo import)
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 $ shortlog
174 $ shortlog
175 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
175 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
176 |
176 |
177 o 2:16581080145e test 0 0 - default - adde
177 o 2:16581080145e test 0 0 - default - adde
178 |
178 |
179 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
179 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
180 |/
180 |/
181 @ 0:07f494440405 test 0 0 - default - adda
181 @ 0:07f494440405 test 0 0 - default - adda
182
182
183
183
184 Test applying multiple patches with --exact
184 Test applying multiple patches with --exact
185
185
186 $ cd ..
186 $ cd ..
187 $ hg clone -r1 repo-options repo-multi2
187 $ hg clone -r1 repo-options repo-multi2
188 adding changesets
188 adding changesets
189 adding manifests
189 adding manifests
190 adding file changes
190 adding file changes
191 added 2 changesets with 2 changes to 1 files
191 added 2 changesets with 2 changes to 1 files
192 updating to branch foo
192 updating to branch foo
193 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
194 $ cd repo-multi2
194 $ cd repo-multi2
195 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
195 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
196 applying ../patch1.diff
196 applying ../patch1.diff
197 applying ../patch2.diff
197 applying ../patch2.diff
198 $ shortlog
198 $ shortlog
199 o 3:d60cb8989666 test 0 0 - foo - addf
199 o 3:d60cb8989666 test 0 0 - foo - addf
200 |
200 |
201 | o 2:16581080145e test 0 0 - default - adde
201 | o 2:16581080145e test 0 0 - default - adde
202 | |
202 | |
203 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
203 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
204 |/
204 |/
205 o 0:07f494440405 test 0 0 - default - adda
205 o 0:07f494440405 test 0 0 - default - adda
206
206
207
207
208 $ cd ..
208 $ cd ..
209
209
210 Test complicated patch with --exact
210 Test complicated patch with --exact
211
211
212 $ hg init repo-exact
212 $ hg init repo-exact
213 $ cd repo-exact
213 $ cd repo-exact
214 $ echo a > a
214 $ echo a > a
215 $ echo c > c
215 $ echo c > c
216 $ echo d > d
216 $ echo d > d
217 $ echo e > e
217 $ echo e > e
218 $ echo f > f
218 $ echo f > f
219 $ chmod +x f
219 $ chmod +x f
220 $ ln -s c linkc
220 $ ln -s c linkc
221 $ hg ci -Am t
221 $ hg ci -Am t
222 adding a
222 adding a
223 adding c
223 adding c
224 adding d
224 adding d
225 adding e
225 adding e
226 adding f
226 adding f
227 adding linkc
227 adding linkc
228 $ hg cp a aa1
228 $ hg cp a aa1
229 $ echo b >> a
229 $ echo b >> a
230 $ echo b > b
230 $ echo b > b
231 $ hg add b
231 $ hg add b
232 $ hg cp a aa2
232 $ hg cp a aa2
233 $ echo aa >> aa2
233 $ echo aa >> aa2
234 $ chmod +x e
234 $ chmod +x e
235 $ chmod -x f
235 $ chmod -x f
236 $ ln -s a linka
236 $ ln -s a linka
237 $ hg rm d
237 $ hg rm d
238 $ hg rm linkc
238 $ hg rm linkc
239 $ hg mv c cc
239 $ hg mv c cc
240 $ hg ci -m patch
240 $ hg ci -m patch
241 $ hg export --git . > ../test.diff
241 $ hg export --git . > ../test.diff
242 $ hg up -C null
242 $ hg up -C null
243 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
244 $ hg purge
244 $ hg purge
245 $ hg st
245 $ hg st
246 $ hg import --bypass --exact ../test.diff
246 $ hg import --bypass --exact ../test.diff
247 applying ../test.diff
247 applying ../test.diff
248
248
249 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
250 data. If not, diff both heads to debug it.
250 data. If not, diff both heads to debug it.
251
251
252 $ shortlog
252 $ shortlog
253 o 1:2978fd5c8aa4 test 0 0 - default - patch
253 o 1:2978fd5c8aa4 test 0 0 - default - patch
254 |
254 |
255 o 0:a0e19e636a43 test 0 0 - default - t
255 o 0:a0e19e636a43 test 0 0 - default - t
256
256
@@ -1,938 +1,955 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 $ hg --cwd a id
202 $ hg --cwd a id
203 1d4bd90af0e4 tip
203 1d4bd90af0e4 tip
204 $ hg --cwd b id
204 $ hg --cwd b id
205 1d4bd90af0e4 tip
205 1d4bd90af0e4 tip
206 $ rm -r b
206 $ rm -r b
207
207
208
208
209 override commit message
209 override commit message
210
210
211 $ hg clone -r0 a b
211 $ hg clone -r0 a b
212 adding changesets
212 adding changesets
213 adding manifests
213 adding manifests
214 adding file changes
214 adding file changes
215 added 1 changesets with 2 changes to 2 files
215 added 1 changesets with 2 changes to 2 files
216 updating to branch default
216 updating to branch default
217 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
218 $ hg --cwd b import -m 'override' - < exported-tip.patch
218 $ hg --cwd b import -m 'override' - < exported-tip.patch
219 applying patch from stdin
219 applying patch from stdin
220 $ hg --cwd b tip | grep override
220 $ hg --cwd b tip | grep override
221 summary: override
221 summary: override
222 $ rm -r b
222 $ rm -r b
223
223
224 $ cat > mkmsg.py <<EOF
224 $ cat > mkmsg.py <<EOF
225 > import email.Message, sys
225 > import email.Message, sys
226 > msg = email.Message.Message()
226 > msg = email.Message.Message()
227 > patch = open(sys.argv[1], 'rb').read()
227 > patch = open(sys.argv[1], 'rb').read()
228 > msg.set_payload('email commit message\n' + patch)
228 > msg.set_payload('email commit message\n' + patch)
229 > msg['Subject'] = 'email patch'
229 > msg['Subject'] = 'email patch'
230 > msg['From'] = 'email patcher'
230 > msg['From'] = 'email patcher'
231 > sys.stdout.write(msg.as_string())
231 > sys.stdout.write(msg.as_string())
232 > EOF
232 > EOF
233
233
234
234
235 plain diff in email, subject, message body
235 plain diff in email, subject, message body
236
236
237 $ hg clone -r0 a b
237 $ hg clone -r0 a b
238 adding changesets
238 adding changesets
239 adding manifests
239 adding manifests
240 adding file changes
240 adding file changes
241 added 1 changesets with 2 changes to 2 files
241 added 1 changesets with 2 changes to 2 files
242 updating to branch default
242 updating to branch default
243 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
244 $ python mkmsg.py diffed-tip.patch > msg.patch
244 $ python mkmsg.py diffed-tip.patch > msg.patch
245 $ hg --cwd b import ../msg.patch
245 $ hg --cwd b import ../msg.patch
246 applying ../msg.patch
246 applying ../msg.patch
247 $ hg --cwd b tip | grep email
247 $ hg --cwd b tip | grep email
248 user: email patcher
248 user: email patcher
249 summary: email patch
249 summary: email patch
250 $ rm -r b
250 $ rm -r b
251
251
252
252
253 plain diff in email, no subject, message body
253 plain diff in email, no subject, message body
254
254
255 $ hg clone -r0 a b
255 $ hg clone -r0 a b
256 adding changesets
256 adding changesets
257 adding manifests
257 adding manifests
258 adding file changes
258 adding file changes
259 added 1 changesets with 2 changes to 2 files
259 added 1 changesets with 2 changes to 2 files
260 updating to branch default
260 updating to branch default
261 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
262 $ grep -v '^Subject:' msg.patch | hg --cwd b import -
262 $ grep -v '^Subject:' msg.patch | hg --cwd b import -
263 applying patch from stdin
263 applying patch from stdin
264 $ rm -r b
264 $ rm -r b
265
265
266
266
267 plain diff in email, subject, no message body
267 plain diff in email, subject, no message body
268
268
269 $ hg clone -r0 a b
269 $ hg clone -r0 a b
270 adding changesets
270 adding changesets
271 adding manifests
271 adding manifests
272 adding file changes
272 adding file changes
273 added 1 changesets with 2 changes to 2 files
273 added 1 changesets with 2 changes to 2 files
274 updating to branch default
274 updating to branch default
275 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
276 $ grep -v '^email ' msg.patch | hg --cwd b import -
276 $ grep -v '^email ' msg.patch | hg --cwd b import -
277 applying patch from stdin
277 applying patch from stdin
278 $ rm -r b
278 $ rm -r b
279
279
280
280
281 plain diff in email, no subject, no message body, should fail
281 plain diff in email, no subject, no message body, should fail
282
282
283 $ hg clone -r0 a b
283 $ hg clone -r0 a b
284 adding changesets
284 adding changesets
285 adding manifests
285 adding manifests
286 adding file changes
286 adding file changes
287 added 1 changesets with 2 changes to 2 files
287 added 1 changesets with 2 changes to 2 files
288 updating to branch default
288 updating to branch default
289 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
290 $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
290 $ egrep -v '^(Subject|email)' msg.patch | hg --cwd b import -
291 applying patch from stdin
291 applying patch from stdin
292 abort: empty commit message
292 abort: empty commit message
293 [255]
293 [255]
294 $ rm -r b
294 $ rm -r b
295
295
296
296
297 hg export in email, should use patch header
297 hg export in email, should use patch header
298
298
299 $ hg clone -r0 a b
299 $ hg clone -r0 a b
300 adding changesets
300 adding changesets
301 adding manifests
301 adding manifests
302 adding file changes
302 adding file changes
303 added 1 changesets with 2 changes to 2 files
303 added 1 changesets with 2 changes to 2 files
304 updating to branch default
304 updating to branch default
305 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
306 $ python mkmsg.py exported-tip.patch | hg --cwd b import -
306 $ python mkmsg.py exported-tip.patch | hg --cwd b import -
307 applying patch from stdin
307 applying patch from stdin
308 $ hg --cwd b tip | grep second
308 $ hg --cwd b tip | grep second
309 summary: second change
309 summary: second change
310 $ rm -r b
310 $ rm -r b
311
311
312
312
313 subject: duplicate detection, removal of [PATCH]
313 subject: duplicate detection, removal of [PATCH]
314 The '---' tests the gitsendmail handling without proper mail headers
314 The '---' tests the gitsendmail handling without proper mail headers
315
315
316 $ cat > mkmsg2.py <<EOF
316 $ cat > mkmsg2.py <<EOF
317 > import email.Message, sys
317 > import email.Message, sys
318 > msg = email.Message.Message()
318 > msg = email.Message.Message()
319 > patch = open(sys.argv[1], 'rb').read()
319 > patch = open(sys.argv[1], 'rb').read()
320 > msg.set_payload('email patch\n\nnext line\n---\n' + patch)
320 > msg.set_payload('email patch\n\nnext line\n---\n' + patch)
321 > msg['Subject'] = '[PATCH] email patch'
321 > msg['Subject'] = '[PATCH] email patch'
322 > msg['From'] = 'email patcher'
322 > msg['From'] = 'email patcher'
323 > sys.stdout.write(msg.as_string())
323 > sys.stdout.write(msg.as_string())
324 > EOF
324 > EOF
325
325
326
326
327 plain diff in email, [PATCH] subject, message body with subject
327 plain diff in email, [PATCH] subject, message body with subject
328
328
329 $ hg clone -r0 a b
329 $ hg clone -r0 a b
330 adding changesets
330 adding changesets
331 adding manifests
331 adding manifests
332 adding file changes
332 adding file changes
333 added 1 changesets with 2 changes to 2 files
333 added 1 changesets with 2 changes to 2 files
334 updating to branch default
334 updating to branch default
335 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
336 $ python mkmsg2.py diffed-tip.patch | hg --cwd b import -
336 $ python mkmsg2.py diffed-tip.patch | hg --cwd b import -
337 applying patch from stdin
337 applying patch from stdin
338 $ hg --cwd b tip --template '{desc}\n'
338 $ hg --cwd b tip --template '{desc}\n'
339 email patch
339 email patch
340
340
341 next line
341 next line
342 ---
342 ---
343 $ rm -r b
343 $ rm -r b
344
344
345
345
346 Issue963: Parent of working dir incorrect after import of multiple
346 Issue963: Parent of working dir incorrect after import of multiple
347 patches and rollback
347 patches and rollback
348
348
349 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
350 patches: import patch1 patch2; rollback
350 patches: import patch1 patch2; rollback
351
351
352 $ echo line 3 >> a/a
352 $ echo line 3 >> a/a
353 $ hg --cwd a ci -m'third change'
353 $ hg --cwd a ci -m'third change'
354 $ hg --cwd a export -o '../patch%R' 1 2
354 $ hg --cwd a export -o '../patch%R' 1 2
355 $ hg clone -qr0 a b
355 $ hg clone -qr0 a b
356 $ hg --cwd b parents --template 'parent: {rev}\n'
356 $ hg --cwd b parents --template 'parent: {rev}\n'
357 parent: 0
357 parent: 0
358 $ hg --cwd b import -v ../patch1 ../patch2
358 $ hg --cwd b import -v ../patch1 ../patch2
359 applying ../patch1
359 applying ../patch1
360 patching file a
360 patching file a
361 a
361 a
362 created 1d4bd90af0e4
362 created 1d4bd90af0e4
363 applying ../patch2
363 applying ../patch2
364 patching file a
364 patching file a
365 a
365 a
366 created 6d019af21222
366 created 6d019af21222
367 $ hg --cwd b rollback
367 $ hg --cwd b rollback
368 repository tip rolled back to revision 1 (undo commit)
368 repository tip rolled back to revision 0 (undo import)
369 working directory now based on revision 1
369 working directory now based on revision 0
370 $ hg --cwd b parents --template 'parent: {rev}\n'
370 $ hg --cwd b parents --template 'parent: {rev}\n'
371 parent: 1
371 parent: 0
372 $ rm -r b
372 $ rm -r b
373
373
374
374
375 importing a patch in a subdirectory failed at the commit stage
375 importing a patch in a subdirectory failed at the commit stage
376
376
377 $ echo line 2 >> a/d1/d2/a
377 $ echo line 2 >> a/d1/d2/a
378 $ 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'
379
379
380 hg import in a subdirectory
380 hg import in a subdirectory
381
381
382 $ hg clone -r0 a b
382 $ hg clone -r0 a b
383 adding changesets
383 adding changesets
384 adding manifests
384 adding manifests
385 adding file changes
385 adding file changes
386 added 1 changesets with 2 changes to 2 files
386 added 1 changesets with 2 changes to 2 files
387 updating to branch default
387 updating to branch default
388 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
389 $ hg --cwd a export tip > tmp
389 $ hg --cwd a export tip > tmp
390 $ sed -e 's/d1\/d2\///' < tmp > subdir-tip.patch
390 $ sed -e 's/d1\/d2\///' < tmp > subdir-tip.patch
391 $ dir=`pwd`
391 $ dir=`pwd`
392 $ cd b/d1/d2 2>&1 > /dev/null
392 $ cd b/d1/d2 2>&1 > /dev/null
393 $ hg import ../../../subdir-tip.patch
393 $ hg import ../../../subdir-tip.patch
394 applying ../../../subdir-tip.patch
394 applying ../../../subdir-tip.patch
395 $ cd "$dir"
395 $ cd "$dir"
396
396
397 message should be 'subdir change'
397 message should be 'subdir change'
398 committer should be 'someoneelse'
398 committer should be 'someoneelse'
399
399
400 $ hg --cwd b tip
400 $ hg --cwd b tip
401 changeset: 1:3577f5aea227
401 changeset: 1:3577f5aea227
402 tag: tip
402 tag: tip
403 user: someoneelse
403 user: someoneelse
404 date: Thu Jan 01 00:00:01 1970 +0000
404 date: Thu Jan 01 00:00:01 1970 +0000
405 summary: subdir change
405 summary: subdir change
406
406
407
407
408 should be empty
408 should be empty
409
409
410 $ hg --cwd b status
410 $ hg --cwd b status
411
411
412
412
413 Test fuzziness (ambiguous patch location, fuzz=2)
413 Test fuzziness (ambiguous patch location, fuzz=2)
414
414
415 $ hg init fuzzy
415 $ hg init fuzzy
416 $ cd fuzzy
416 $ cd fuzzy
417 $ echo line1 > a
417 $ echo line1 > a
418 $ echo line0 >> a
418 $ echo line0 >> a
419 $ echo line3 >> a
419 $ echo line3 >> a
420 $ hg ci -Am adda
420 $ hg ci -Am adda
421 adding a
421 adding a
422 $ echo line1 > a
422 $ echo line1 > a
423 $ echo line2 >> a
423 $ echo line2 >> a
424 $ echo line0 >> a
424 $ echo line0 >> a
425 $ echo line3 >> a
425 $ echo line3 >> a
426 $ hg ci -m change a
426 $ hg ci -m change a
427 $ hg export tip > fuzzy-tip.patch
427 $ hg export tip > fuzzy-tip.patch
428 $ hg up -C 0
428 $ hg up -C 0
429 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
430 $ echo line1 > a
430 $ echo line1 > a
431 $ echo line0 >> a
431 $ echo line0 >> a
432 $ echo line1 >> a
432 $ echo line1 >> a
433 $ echo line0 >> a
433 $ echo line0 >> a
434 $ hg ci -m brancha
434 $ hg ci -m brancha
435 created new head
435 created new head
436 $ hg import --no-commit -v fuzzy-tip.patch
436 $ hg import --no-commit -v fuzzy-tip.patch
437 applying fuzzy-tip.patch
437 applying fuzzy-tip.patch
438 patching file a
438 patching file a
439 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
440 applied to working directory
441 $ hg revert -a
441 $ hg revert -a
442 reverting a
442 reverting a
443
443
444
444
445 import with --no-commit should have written .hg/last-message.txt
445 import with --no-commit should have written .hg/last-message.txt
446
446
447 $ cat .hg/last-message.txt
447 $ cat .hg/last-message.txt
448 change (no-eol)
448 change (no-eol)
449
449
450
450
451 test fuzziness with eol=auto
451 test fuzziness with eol=auto
452
452
453 $ 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
454 applying fuzzy-tip.patch
454 applying fuzzy-tip.patch
455 patching file a
455 patching file a
456 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
457 applied to working directory
458 $ cd ..
458 $ cd ..
459
459
460
460
461 Test hunk touching empty files (issue906)
461 Test hunk touching empty files (issue906)
462
462
463 $ hg init empty
463 $ hg init empty
464 $ cd empty
464 $ cd empty
465 $ touch a
465 $ touch a
466 $ touch b1
466 $ touch b1
467 $ touch c1
467 $ touch c1
468 $ echo d > d
468 $ echo d > d
469 $ hg ci -Am init
469 $ hg ci -Am init
470 adding a
470 adding a
471 adding b1
471 adding b1
472 adding c1
472 adding c1
473 adding d
473 adding d
474 $ echo a > a
474 $ echo a > a
475 $ echo b > b1
475 $ echo b > b1
476 $ hg mv b1 b2
476 $ hg mv b1 b2
477 $ echo c > c1
477 $ echo c > c1
478 $ hg copy c1 c2
478 $ hg copy c1 c2
479 $ rm d
479 $ rm d
480 $ touch d
480 $ touch d
481 $ hg diff --git
481 $ hg diff --git
482 diff --git a/a b/a
482 diff --git a/a b/a
483 --- a/a
483 --- a/a
484 +++ b/a
484 +++ b/a
485 @@ -0,0 +1,1 @@
485 @@ -0,0 +1,1 @@
486 +a
486 +a
487 diff --git a/b1 b/b2
487 diff --git a/b1 b/b2
488 rename from b1
488 rename from b1
489 rename to b2
489 rename to b2
490 --- a/b1
490 --- a/b1
491 +++ b/b2
491 +++ b/b2
492 @@ -0,0 +1,1 @@
492 @@ -0,0 +1,1 @@
493 +b
493 +b
494 diff --git a/c1 b/c1
494 diff --git a/c1 b/c1
495 --- a/c1
495 --- a/c1
496 +++ b/c1
496 +++ b/c1
497 @@ -0,0 +1,1 @@
497 @@ -0,0 +1,1 @@
498 +c
498 +c
499 diff --git a/c1 b/c2
499 diff --git a/c1 b/c2
500 copy from c1
500 copy from c1
501 copy to c2
501 copy to c2
502 --- a/c1
502 --- a/c1
503 +++ b/c2
503 +++ b/c2
504 @@ -0,0 +1,1 @@
504 @@ -0,0 +1,1 @@
505 +c
505 +c
506 diff --git a/d b/d
506 diff --git a/d b/d
507 --- a/d
507 --- a/d
508 +++ b/d
508 +++ b/d
509 @@ -1,1 +0,0 @@
509 @@ -1,1 +0,0 @@
510 -d
510 -d
511 $ hg ci -m empty
511 $ hg ci -m empty
512 $ hg export --git tip > empty.diff
512 $ hg export --git tip > empty.diff
513 $ hg up -C 0
513 $ hg up -C 0
514 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
515 $ hg import empty.diff
515 $ hg import empty.diff
516 applying empty.diff
516 applying empty.diff
517 $ for name in a b1 b2 c1 c2 d; do
517 $ for name in a b1 b2 c1 c2 d; do
518 > echo % $name file
518 > echo % $name file
519 > test -f $name && cat $name
519 > test -f $name && cat $name
520 > done
520 > done
521 % a file
521 % a file
522 a
522 a
523 % b1 file
523 % b1 file
524 % b2 file
524 % b2 file
525 b
525 b
526 % c1 file
526 % c1 file
527 c
527 c
528 % c2 file
528 % c2 file
529 c
529 c
530 % d file
530 % d file
531 $ cd ..
531 $ cd ..
532
532
533
533
534 Test importing a patch ending with a binary file removal
534 Test importing a patch ending with a binary file removal
535
535
536 $ hg init binaryremoval
536 $ hg init binaryremoval
537 $ cd binaryremoval
537 $ cd binaryremoval
538 $ echo a > a
538 $ echo a > a
539 $ python -c "file('b', 'wb').write('a\x00b')"
539 $ python -c "file('b', 'wb').write('a\x00b')"
540 $ hg ci -Am addall
540 $ hg ci -Am addall
541 adding a
541 adding a
542 adding b
542 adding b
543 $ hg rm a
543 $ hg rm a
544 $ hg rm b
544 $ hg rm b
545 $ hg st
545 $ hg st
546 R a
546 R a
547 R b
547 R b
548 $ hg ci -m remove
548 $ hg ci -m remove
549 $ hg export --git . > remove.diff
549 $ hg export --git . > remove.diff
550 $ cat remove.diff | grep git
550 $ cat remove.diff | grep git
551 diff --git a/a b/a
551 diff --git a/a b/a
552 diff --git a/b b/b
552 diff --git a/b b/b
553 $ hg up -C 0
553 $ hg up -C 0
554 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
555 $ hg import remove.diff
555 $ hg import remove.diff
556 applying remove.diff
556 applying remove.diff
557 $ hg manifest
557 $ hg manifest
558 $ cd ..
558 $ cd ..
559
559
560
560
561 Issue927: test update+rename with common name
561 Issue927: test update+rename with common name
562
562
563 $ hg init t
563 $ hg init t
564 $ cd t
564 $ cd t
565 $ touch a
565 $ touch a
566 $ hg ci -Am t
566 $ hg ci -Am t
567 adding a
567 adding a
568 $ echo a > a
568 $ echo a > a
569
569
570 Here, bfile.startswith(afile)
570 Here, bfile.startswith(afile)
571
571
572 $ hg copy a a2
572 $ hg copy a a2
573 $ hg ci -m copya
573 $ hg ci -m copya
574 $ hg export --git tip > copy.diff
574 $ hg export --git tip > copy.diff
575 $ hg up -C 0
575 $ hg up -C 0
576 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
577 $ hg import copy.diff
577 $ hg import copy.diff
578 applying copy.diff
578 applying copy.diff
579
579
580 a should contain an 'a'
580 a should contain an 'a'
581
581
582 $ cat a
582 $ cat a
583 a
583 a
584
584
585 and a2 should have duplicated it
585 and a2 should have duplicated it
586
586
587 $ cat a2
587 $ cat a2
588 a
588 a
589 $ cd ..
589 $ cd ..
590
590
591
591
592 test -p0
592 test -p0
593
593
594 $ hg init p0
594 $ hg init p0
595 $ cd p0
595 $ cd p0
596 $ echo a > a
596 $ echo a > a
597 $ hg ci -Am t
597 $ hg ci -Am t
598 adding a
598 adding a
599 $ hg import -p0 - << EOF
599 $ hg import -p0 - << EOF
600 > foobar
600 > foobar
601 > --- a Sat Apr 12 22:43:58 2008 -0400
601 > --- a Sat Apr 12 22:43:58 2008 -0400
602 > +++ a Sat Apr 12 22:44:05 2008 -0400
602 > +++ a Sat Apr 12 22:44:05 2008 -0400
603 > @@ -1,1 +1,1 @@
603 > @@ -1,1 +1,1 @@
604 > -a
604 > -a
605 > +bb
605 > +bb
606 > EOF
606 > EOF
607 applying patch from stdin
607 applying patch from stdin
608 $ hg status
608 $ hg status
609 $ cat a
609 $ cat a
610 bb
610 bb
611 $ cd ..
611 $ cd ..
612
612
613
613
614 test paths outside repo root
614 test paths outside repo root
615
615
616 $ mkdir outside
616 $ mkdir outside
617 $ touch outside/foo
617 $ touch outside/foo
618 $ hg init inside
618 $ hg init inside
619 $ cd inside
619 $ cd inside
620 $ hg import - <<EOF
620 $ hg import - <<EOF
621 > diff --git a/a b/b
621 > diff --git a/a b/b
622 > rename from ../outside/foo
622 > rename from ../outside/foo
623 > rename to bar
623 > rename to bar
624 > EOF
624 > EOF
625 applying patch from stdin
625 applying patch from stdin
626 abort: path contains illegal component: ../outside/foo
626 abort: path contains illegal component: ../outside/foo
627 [255]
627 [255]
628 $ cd ..
628 $ cd ..
629
629
630
630
631 test import with similarity and git and strip (issue295 et al.)
631 test import with similarity and git and strip (issue295 et al.)
632
632
633 $ hg init sim
633 $ hg init sim
634 $ cd sim
634 $ cd sim
635 $ echo 'this is a test' > a
635 $ echo 'this is a test' > a
636 $ hg ci -Ama
636 $ hg ci -Ama
637 adding a
637 adding a
638 $ cat > ../rename.diff <<EOF
638 $ cat > ../rename.diff <<EOF
639 > diff --git a/foo/a b/foo/a
639 > diff --git a/foo/a b/foo/a
640 > deleted file mode 100644
640 > deleted file mode 100644
641 > --- a/foo/a
641 > --- a/foo/a
642 > +++ /dev/null
642 > +++ /dev/null
643 > @@ -1,1 +0,0 @@
643 > @@ -1,1 +0,0 @@
644 > -this is a test
644 > -this is a test
645 > diff --git a/foo/b b/foo/b
645 > diff --git a/foo/b b/foo/b
646 > new file mode 100644
646 > new file mode 100644
647 > --- /dev/null
647 > --- /dev/null
648 > +++ b/foo/b
648 > +++ b/foo/b
649 > @@ -0,0 +1,2 @@
649 > @@ -0,0 +1,2 @@
650 > +this is a test
650 > +this is a test
651 > +foo
651 > +foo
652 > EOF
652 > EOF
653 $ hg import --no-commit -v -s 1 ../rename.diff -p2
653 $ hg import --no-commit -v -s 1 ../rename.diff -p2
654 applying ../rename.diff
654 applying ../rename.diff
655 patching file a
655 patching file a
656 patching file b
656 patching file b
657 removing a
657 removing a
658 adding b
658 adding b
659 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
660 applied to working directory
661 $ hg st -C
661 $ hg st -C
662 A b
662 A b
663 a
663 a
664 R a
664 R a
665 $ hg revert -a
665 $ hg revert -a
666 undeleting a
666 undeleting a
667 forgetting b
667 forgetting b
668 $ rm b
668 $ rm b
669 $ hg import --no-commit -v -s 100 ../rename.diff -p2
669 $ hg import --no-commit -v -s 100 ../rename.diff -p2
670 applying ../rename.diff
670 applying ../rename.diff
671 patching file a
671 patching file a
672 patching file b
672 patching file b
673 removing a
673 removing a
674 adding b
674 adding b
675 applied to working directory
675 applied to working directory
676 $ hg st -C
676 $ hg st -C
677 A b
677 A b
678 R a
678 R a
679 $ cd ..
679 $ cd ..
680
680
681
681
682 Issue1495: add empty file from the end of patch
682 Issue1495: add empty file from the end of patch
683
683
684 $ hg init addemptyend
684 $ hg init addemptyend
685 $ cd addemptyend
685 $ cd addemptyend
686 $ touch a
686 $ touch a
687 $ hg addremove
687 $ hg addremove
688 adding a
688 adding a
689 $ hg ci -m "commit"
689 $ hg ci -m "commit"
690 $ cat > a.patch <<EOF
690 $ cat > a.patch <<EOF
691 > add a, b
691 > diff --git a/a b/a
692 > diff --git a/a b/a
692 > --- a/a
693 > --- a/a
693 > +++ b/a
694 > +++ b/a
694 > @@ -0,0 +1,1 @@
695 > @@ -0,0 +1,1 @@
695 > +a
696 > +a
696 > diff --git a/b b/b
697 > diff --git a/b b/b
697 > new file mode 100644
698 > new file mode 100644
698 > EOF
699 > EOF
699 $ hg import --no-commit a.patch
700 $ hg import --no-commit a.patch
700 applying a.patch
701 applying a.patch
702
703 apply a good patch followed by an empty patch (mainly to ensure
704 that dirstate is *not* updated when import crashes)
705 $ hg update -q -C .
706 $ rm b
707 $ touch empty.patch
708 $ hg import a.patch empty.patch
709 applying a.patch
710 applying empty.patch
711 transaction abort!
712 rollback completed
713 abort: empty.patch: no diffs found
714 [255]
715 $ hg tip --template '{rev} {desc|firstline}\n'
716 0 commit
717 $ hg -q status
718 M a
701 $ cd ..
719 $ cd ..
702
720
703
704 create file when source is not /dev/null
721 create file when source is not /dev/null
705
722
706 $ cat > create.patch <<EOF
723 $ cat > create.patch <<EOF
707 > diff -Naur proj-orig/foo proj-new/foo
724 > diff -Naur proj-orig/foo proj-new/foo
708 > --- proj-orig/foo 1969-12-31 16:00:00.000000000 -0800
725 > --- proj-orig/foo 1969-12-31 16:00:00.000000000 -0800
709 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
726 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
710 > @@ -0,0 +1,1 @@
727 > @@ -0,0 +1,1 @@
711 > +a
728 > +a
712 > EOF
729 > EOF
713
730
714 some people have patches like the following too
731 some people have patches like the following too
715
732
716 $ cat > create2.patch <<EOF
733 $ cat > create2.patch <<EOF
717 > diff -Naur proj-orig/foo proj-new/foo
734 > diff -Naur proj-orig/foo proj-new/foo
718 > --- proj-orig/foo.orig 1969-12-31 16:00:00.000000000 -0800
735 > --- proj-orig/foo.orig 1969-12-31 16:00:00.000000000 -0800
719 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
736 > +++ proj-new/foo 2009-07-17 16:50:45.801368000 -0700
720 > @@ -0,0 +1,1 @@
737 > @@ -0,0 +1,1 @@
721 > +a
738 > +a
722 > EOF
739 > EOF
723 $ hg init oddcreate
740 $ hg init oddcreate
724 $ cd oddcreate
741 $ cd oddcreate
725 $ hg import --no-commit ../create.patch
742 $ hg import --no-commit ../create.patch
726 applying ../create.patch
743 applying ../create.patch
727 $ cat foo
744 $ cat foo
728 a
745 a
729 $ rm foo
746 $ rm foo
730 $ hg revert foo
747 $ hg revert foo
731 $ hg import --no-commit ../create2.patch
748 $ hg import --no-commit ../create2.patch
732 applying ../create2.patch
749 applying ../create2.patch
733 $ cat foo
750 $ cat foo
734 a
751 a
735
752
736
753
737 Issue1859: first line mistaken for email headers
754 Issue1859: first line mistaken for email headers
738
755
739 $ hg init emailconfusion
756 $ hg init emailconfusion
740 $ cd emailconfusion
757 $ cd emailconfusion
741 $ cat > a.patch <<EOF
758 $ cat > a.patch <<EOF
742 > module: summary
759 > module: summary
743 >
760 >
744 > description
761 > description
745 >
762 >
746 >
763 >
747 > diff -r 000000000000 -r 9b4c1e343b55 test.txt
764 > diff -r 000000000000 -r 9b4c1e343b55 test.txt
748 > --- /dev/null
765 > --- /dev/null
749 > +++ b/a
766 > +++ b/a
750 > @@ -0,0 +1,1 @@
767 > @@ -0,0 +1,1 @@
751 > +a
768 > +a
752 > EOF
769 > EOF
753 $ hg import -d '0 0' a.patch
770 $ hg import -d '0 0' a.patch
754 applying a.patch
771 applying a.patch
755 $ hg parents -v
772 $ hg parents -v
756 changeset: 0:5a681217c0ad
773 changeset: 0:5a681217c0ad
757 tag: tip
774 tag: tip
758 user: test
775 user: test
759 date: Thu Jan 01 00:00:00 1970 +0000
776 date: Thu Jan 01 00:00:00 1970 +0000
760 files: a
777 files: a
761 description:
778 description:
762 module: summary
779 module: summary
763
780
764 description
781 description
765
782
766
783
767 $ cd ..
784 $ cd ..
768
785
769
786
770 --- in commit message
787 --- in commit message
771
788
772 $ hg init commitconfusion
789 $ hg init commitconfusion
773 $ cd commitconfusion
790 $ cd commitconfusion
774 $ cat > a.patch <<EOF
791 $ cat > a.patch <<EOF
775 > module: summary
792 > module: summary
776 >
793 >
777 > --- description
794 > --- description
778 >
795 >
779 > diff --git a/a b/a
796 > diff --git a/a b/a
780 > new file mode 100644
797 > new file mode 100644
781 > --- /dev/null
798 > --- /dev/null
782 > +++ b/a
799 > +++ b/a
783 > @@ -0,0 +1,1 @@
800 > @@ -0,0 +1,1 @@
784 > +a
801 > +a
785 > EOF
802 > EOF
786 > hg import -d '0 0' a.patch
803 > hg import -d '0 0' a.patch
787 > hg parents -v
804 > hg parents -v
788 > cd ..
805 > cd ..
789 >
806 >
790 > echo '% tricky header splitting'
807 > echo '% tricky header splitting'
791 > cat > trickyheaders.patch <<EOF
808 > cat > trickyheaders.patch <<EOF
792 > From: User A <user@a>
809 > From: User A <user@a>
793 > Subject: [PATCH] from: tricky!
810 > Subject: [PATCH] from: tricky!
794 >
811 >
795 > # HG changeset patch
812 > # HG changeset patch
796 > # User User B
813 > # User User B
797 > # Date 1266264441 18000
814 > # Date 1266264441 18000
798 > # Branch stable
815 > # Branch stable
799 > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
816 > # Node ID f2be6a1170ac83bf31cb4ae0bad00d7678115bc0
800 > # Parent 0000000000000000000000000000000000000000
817 > # Parent 0000000000000000000000000000000000000000
801 > from: tricky!
818 > from: tricky!
802 >
819 >
803 > That is not a header.
820 > That is not a header.
804 >
821 >
805 > diff -r 000000000000 -r f2be6a1170ac foo
822 > diff -r 000000000000 -r f2be6a1170ac foo
806 > --- /dev/null
823 > --- /dev/null
807 > +++ b/foo
824 > +++ b/foo
808 > @@ -0,0 +1,1 @@
825 > @@ -0,0 +1,1 @@
809 > +foo
826 > +foo
810 > EOF
827 > EOF
811 applying a.patch
828 applying a.patch
812 changeset: 0:f34d9187897d
829 changeset: 0:f34d9187897d
813 tag: tip
830 tag: tip
814 user: test
831 user: test
815 date: Thu Jan 01 00:00:00 1970 +0000
832 date: Thu Jan 01 00:00:00 1970 +0000
816 files: a
833 files: a
817 description:
834 description:
818 module: summary
835 module: summary
819
836
820
837
821 % tricky header splitting
838 % tricky header splitting
822
839
823 $ hg init trickyheaders
840 $ hg init trickyheaders
824 $ cd trickyheaders
841 $ cd trickyheaders
825 $ hg import -d '0 0' ../trickyheaders.patch
842 $ hg import -d '0 0' ../trickyheaders.patch
826 applying ../trickyheaders.patch
843 applying ../trickyheaders.patch
827 $ hg export --git tip
844 $ hg export --git tip
828 # HG changeset patch
845 # HG changeset patch
829 # User User B
846 # User User B
830 # Date 0 0
847 # Date 0 0
831 # Node ID eb56ab91903632294ac504838508cb370c0901d2
848 # Node ID eb56ab91903632294ac504838508cb370c0901d2
832 # Parent 0000000000000000000000000000000000000000
849 # Parent 0000000000000000000000000000000000000000
833 from: tricky!
850 from: tricky!
834
851
835 That is not a header.
852 That is not a header.
836
853
837 diff --git a/foo b/foo
854 diff --git a/foo b/foo
838 new file mode 100644
855 new file mode 100644
839 --- /dev/null
856 --- /dev/null
840 +++ b/foo
857 +++ b/foo
841 @@ -0,0 +1,1 @@
858 @@ -0,0 +1,1 @@
842 +foo
859 +foo
843 $ cd ..
860 $ cd ..
844
861
845
862
846 Issue2102: hg export and hg import speak different languages
863 Issue2102: hg export and hg import speak different languages
847
864
848 $ hg init issue2102
865 $ hg init issue2102
849 $ cd issue2102
866 $ cd issue2102
850 $ mkdir -p src/cmd/gc
867 $ mkdir -p src/cmd/gc
851 $ touch src/cmd/gc/mksys.bash
868 $ touch src/cmd/gc/mksys.bash
852 $ hg ci -Am init
869 $ hg ci -Am init
853 adding src/cmd/gc/mksys.bash
870 adding src/cmd/gc/mksys.bash
854 $ hg import - <<EOF
871 $ hg import - <<EOF
855 > # HG changeset patch
872 > # HG changeset patch
856 > # User Rob Pike
873 > # User Rob Pike
857 > # Date 1216685449 25200
874 > # Date 1216685449 25200
858 > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
875 > # Node ID 03aa2b206f499ad6eb50e6e207b9e710d6409c98
859 > # Parent 93d10138ad8df586827ca90b4ddb5033e21a3a84
876 > # Parent 93d10138ad8df586827ca90b4ddb5033e21a3a84
860 > help management of empty pkg and lib directories in perforce
877 > help management of empty pkg and lib directories in perforce
861 >
878 >
862 > R=gri
879 > R=gri
863 > DELTA=4 (4 added, 0 deleted, 0 changed)
880 > DELTA=4 (4 added, 0 deleted, 0 changed)
864 > OCL=13328
881 > OCL=13328
865 > CL=13328
882 > CL=13328
866 >
883 >
867 > diff --git a/lib/place-holder b/lib/place-holder
884 > diff --git a/lib/place-holder b/lib/place-holder
868 > new file mode 100644
885 > new file mode 100644
869 > --- /dev/null
886 > --- /dev/null
870 > +++ b/lib/place-holder
887 > +++ b/lib/place-holder
871 > @@ -0,0 +1,2 @@
888 > @@ -0,0 +1,2 @@
872 > +perforce does not maintain empty directories.
889 > +perforce does not maintain empty directories.
873 > +this file helps.
890 > +this file helps.
874 > diff --git a/pkg/place-holder b/pkg/place-holder
891 > diff --git a/pkg/place-holder b/pkg/place-holder
875 > new file mode 100644
892 > new file mode 100644
876 > --- /dev/null
893 > --- /dev/null
877 > +++ b/pkg/place-holder
894 > +++ b/pkg/place-holder
878 > @@ -0,0 +1,2 @@
895 > @@ -0,0 +1,2 @@
879 > +perforce does not maintain empty directories.
896 > +perforce does not maintain empty directories.
880 > +this file helps.
897 > +this file helps.
881 > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
898 > diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
882 > old mode 100644
899 > old mode 100644
883 > new mode 100755
900 > new mode 100755
884 > EOF
901 > EOF
885 applying patch from stdin
902 applying patch from stdin
886 $ hg sum
903 $ hg sum
887 parent: 1:d59915696727 tip
904 parent: 1:d59915696727 tip
888 help management of empty pkg and lib directories in perforce
905 help management of empty pkg and lib directories in perforce
889 branch: default
906 branch: default
890 commit: (clean)
907 commit: (clean)
891 update: (current)
908 update: (current)
892 $ hg diff --git -c tip
909 $ hg diff --git -c tip
893 diff --git a/lib/place-holder b/lib/place-holder
910 diff --git a/lib/place-holder b/lib/place-holder
894 new file mode 100644
911 new file mode 100644
895 --- /dev/null
912 --- /dev/null
896 +++ b/lib/place-holder
913 +++ b/lib/place-holder
897 @@ -0,0 +1,2 @@
914 @@ -0,0 +1,2 @@
898 +perforce does not maintain empty directories.
915 +perforce does not maintain empty directories.
899 +this file helps.
916 +this file helps.
900 diff --git a/pkg/place-holder b/pkg/place-holder
917 diff --git a/pkg/place-holder b/pkg/place-holder
901 new file mode 100644
918 new file mode 100644
902 --- /dev/null
919 --- /dev/null
903 +++ b/pkg/place-holder
920 +++ b/pkg/place-holder
904 @@ -0,0 +1,2 @@
921 @@ -0,0 +1,2 @@
905 +perforce does not maintain empty directories.
922 +perforce does not maintain empty directories.
906 +this file helps.
923 +this file helps.
907 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
924 diff --git a/src/cmd/gc/mksys.bash b/src/cmd/gc/mksys.bash
908 old mode 100644
925 old mode 100644
909 new mode 100755
926 new mode 100755
910 $ cd ..
927 $ cd ..
911
928
912
929
913 diff lines looking like headers
930 diff lines looking like headers
914
931
915 $ hg init difflineslikeheaders
932 $ hg init difflineslikeheaders
916 $ cd difflineslikeheaders
933 $ cd difflineslikeheaders
917 $ echo a >a
934 $ echo a >a
918 $ echo b >b
935 $ echo b >b
919 $ echo c >c
936 $ echo c >c
920 $ hg ci -Am1
937 $ hg ci -Am1
921 adding a
938 adding a
922 adding b
939 adding b
923 adding c
940 adding c
924
941
925 $ echo "key: value" >>a
942 $ echo "key: value" >>a
926 $ echo "key: value" >>b
943 $ echo "key: value" >>b
927 $ echo "foo" >>c
944 $ echo "foo" >>c
928 $ hg ci -m2
945 $ hg ci -m2
929
946
930 $ hg up -C 0
947 $ hg up -C 0
931 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
948 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
932 $ hg diff --git -c1 >want
949 $ hg diff --git -c1 >want
933 $ hg diff -c1 | hg import --no-commit -
950 $ hg diff -c1 | hg import --no-commit -
934 applying patch from stdin
951 applying patch from stdin
935 $ hg diff --git >have
952 $ hg diff --git >have
936 $ diff want have
953 $ diff want have
937 $ cd ..
954 $ cd ..
938
955
@@ -1,1083 +1,1083 b''
1 $ cat <<EOF >> $HGRCPATH
1 $ cat <<EOF >> $HGRCPATH
2 > [extensions]
2 > [extensions]
3 > keyword =
3 > keyword =
4 > mq =
4 > mq =
5 > notify =
5 > notify =
6 > record =
6 > record =
7 > transplant =
7 > transplant =
8 > [ui]
8 > [ui]
9 > interactive = true
9 > interactive = true
10 > EOF
10 > EOF
11
11
12 Run kwdemo before [keyword] files are set up
12 Run kwdemo before [keyword] files are set up
13 as it would succeed without uisetup otherwise
13 as it would succeed without uisetup otherwise
14
14
15 $ hg --quiet kwdemo
15 $ hg --quiet kwdemo
16 [extensions]
16 [extensions]
17 keyword =
17 keyword =
18 [keyword]
18 [keyword]
19 demo.txt =
19 demo.txt =
20 [keywordset]
20 [keywordset]
21 svn = False
21 svn = False
22 [keywordmaps]
22 [keywordmaps]
23 Author = {author|user}
23 Author = {author|user}
24 Date = {date|utcdate}
24 Date = {date|utcdate}
25 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
25 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
26 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
26 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
27 RCSFile = {file|basename},v
27 RCSFile = {file|basename},v
28 RCSfile = {file|basename},v
28 RCSfile = {file|basename},v
29 Revision = {node|short}
29 Revision = {node|short}
30 Source = {root}/{file},v
30 Source = {root}/{file},v
31 $Author: test $
31 $Author: test $
32 $Date: ????/??/?? ??:??:?? $ (glob)
32 $Date: ????/??/?? ??:??:?? $ (glob)
33 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
33 $Header: */demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
34 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
34 $Id: demo.txt,v ???????????? ????/??/?? ??:??:?? test $ (glob)
35 $RCSFile: demo.txt,v $
35 $RCSFile: demo.txt,v $
36 $RCSfile: demo.txt,v $
36 $RCSfile: demo.txt,v $
37 $Revision: ???????????? $ (glob)
37 $Revision: ???????????? $ (glob)
38 $Source: */demo.txt,v $ (glob)
38 $Source: */demo.txt,v $ (glob)
39
39
40 $ hg --quiet kwdemo "Branch = {branches}"
40 $ hg --quiet kwdemo "Branch = {branches}"
41 [extensions]
41 [extensions]
42 keyword =
42 keyword =
43 [keyword]
43 [keyword]
44 demo.txt =
44 demo.txt =
45 [keywordset]
45 [keywordset]
46 svn = False
46 svn = False
47 [keywordmaps]
47 [keywordmaps]
48 Branch = {branches}
48 Branch = {branches}
49 $Branch: demobranch $
49 $Branch: demobranch $
50
50
51 $ cat <<EOF >> $HGRCPATH
51 $ cat <<EOF >> $HGRCPATH
52 > [keyword]
52 > [keyword]
53 > ** =
53 > ** =
54 > b = ignore
54 > b = ignore
55 > i = ignore
55 > i = ignore
56 > [hooks]
56 > [hooks]
57 > EOF
57 > EOF
58 $ cp $HGRCPATH $HGRCPATH.nohooks
58 $ cp $HGRCPATH $HGRCPATH.nohooks
59 > cat <<EOF >> $HGRCPATH
59 > cat <<EOF >> $HGRCPATH
60 > commit=
60 > commit=
61 > commit.test=cp a hooktest
61 > commit.test=cp a hooktest
62 > EOF
62 > EOF
63
63
64 $ hg init Test-bndl
64 $ hg init Test-bndl
65 $ cd Test-bndl
65 $ cd Test-bndl
66
66
67 kwshrink should exit silently in empty/invalid repo
67 kwshrink should exit silently in empty/invalid repo
68
68
69 $ hg kwshrink
69 $ hg kwshrink
70
70
71 Symlinks cannot be created on Windows.
71 Symlinks cannot be created on Windows.
72 A bundle to test this was made with:
72 A bundle to test this was made with:
73 hg init t
73 hg init t
74 cd t
74 cd t
75 echo a > a
75 echo a > a
76 ln -s a sym
76 ln -s a sym
77 hg add sym
77 hg add sym
78 hg ci -m addsym -u mercurial
78 hg ci -m addsym -u mercurial
79 hg bundle --base null ../test-keyword.hg
79 hg bundle --base null ../test-keyword.hg
80
80
81 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
81 $ hg pull -u "$TESTDIR"/bundles/test-keyword.hg
82 pulling from *test-keyword.hg (glob)
82 pulling from *test-keyword.hg (glob)
83 requesting all changes
83 requesting all changes
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 1 changes to 1 files
87 added 1 changesets with 1 changes to 1 files
88 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
89
89
90 $ echo 'expand $Id$' > a
90 $ echo 'expand $Id$' > a
91 $ echo 'do not process $Id:' >> a
91 $ echo 'do not process $Id:' >> a
92 $ echo 'xxx $' >> a
92 $ echo 'xxx $' >> a
93 $ echo 'ignore $Id$' > b
93 $ echo 'ignore $Id$' > b
94
94
95 Output files as they were created
95 Output files as they were created
96
96
97 $ cat a b
97 $ cat a b
98 expand $Id$
98 expand $Id$
99 do not process $Id:
99 do not process $Id:
100 xxx $
100 xxx $
101 ignore $Id$
101 ignore $Id$
102
102
103 no kwfiles
103 no kwfiles
104
104
105 $ hg kwfiles
105 $ hg kwfiles
106
106
107 untracked candidates
107 untracked candidates
108
108
109 $ hg -v kwfiles --unknown
109 $ hg -v kwfiles --unknown
110 k a
110 k a
111
111
112 Add files and check status
112 Add files and check status
113
113
114 $ hg addremove
114 $ hg addremove
115 adding a
115 adding a
116 adding b
116 adding b
117 $ hg status
117 $ hg status
118 A a
118 A a
119 A b
119 A b
120
120
121
121
122 Default keyword expansion including commit hook
122 Default keyword expansion including commit hook
123 Interrupted commit should not change state or run commit hook
123 Interrupted commit should not change state or run commit hook
124
124
125 $ hg --debug commit
125 $ hg --debug commit
126 abort: empty commit message
126 abort: empty commit message
127 [255]
127 [255]
128 $ hg status
128 $ hg status
129 A a
129 A a
130 A b
130 A b
131
131
132 Commit with several checks
132 Commit with several checks
133
133
134 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
134 $ hg --debug commit -mabsym -u 'User Name <user@example.com>'
135 a
135 a
136 b
136 b
137 overwriting a expanding keywords
137 overwriting a expanding keywords
138 running hook commit.test: cp a hooktest
138 running hook commit.test: cp a hooktest
139 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
139 committed changeset 1:ef63ca68695bc9495032c6fda1350c71e6d256e9
140 $ hg status
140 $ hg status
141 ? hooktest
141 ? hooktest
142 $ hg debugrebuildstate
142 $ hg debugrebuildstate
143 $ hg --quiet identify
143 $ hg --quiet identify
144 ef63ca68695b
144 ef63ca68695b
145
145
146 cat files in working directory with keywords expanded
146 cat files in working directory with keywords expanded
147
147
148 $ cat a b
148 $ cat a b
149 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
149 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
150 do not process $Id:
150 do not process $Id:
151 xxx $
151 xxx $
152 ignore $Id$
152 ignore $Id$
153
153
154 hg cat files and symlink, no expansion
154 hg cat files and symlink, no expansion
155
155
156 $ hg cat sym a b && echo
156 $ hg cat sym a b && echo
157 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
157 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
158 do not process $Id:
158 do not process $Id:
159 xxx $
159 xxx $
160 ignore $Id$
160 ignore $Id$
161 a
161 a
162
162
163 Test hook execution
163 Test hook execution
164
164
165 $ diff a hooktest
165 $ diff a hooktest
166
166
167 $ cp $HGRCPATH.nohooks $HGRCPATH
167 $ cp $HGRCPATH.nohooks $HGRCPATH
168 $ rm hooktest
168 $ rm hooktest
169
169
170 bundle
170 bundle
171
171
172 $ hg bundle --base null ../kw.hg
172 $ hg bundle --base null ../kw.hg
173 2 changesets found
173 2 changesets found
174 $ cd ..
174 $ cd ..
175 $ hg init Test
175 $ hg init Test
176 $ cd Test
176 $ cd Test
177
177
178 Notify on pull to check whether keywords stay as is in email
178 Notify on pull to check whether keywords stay as is in email
179 ie. if patch.diff wrapper acts as it should
179 ie. if patch.diff wrapper acts as it should
180
180
181 $ cat <<EOF >> $HGRCPATH
181 $ cat <<EOF >> $HGRCPATH
182 > [hooks]
182 > [hooks]
183 > incoming.notify = python:hgext.notify.hook
183 > incoming.notify = python:hgext.notify.hook
184 > [notify]
184 > [notify]
185 > sources = pull
185 > sources = pull
186 > diffstat = False
186 > diffstat = False
187 > maxsubject = 15
187 > maxsubject = 15
188 > [reposubs]
188 > [reposubs]
189 > * = Test
189 > * = Test
190 > EOF
190 > EOF
191
191
192 Pull from bundle and trigger notify
192 Pull from bundle and trigger notify
193
193
194 $ hg pull -u ../kw.hg
194 $ hg pull -u ../kw.hg
195 pulling from ../kw.hg
195 pulling from ../kw.hg
196 requesting all changes
196 requesting all changes
197 adding changesets
197 adding changesets
198 adding manifests
198 adding manifests
199 adding file changes
199 adding file changes
200 added 2 changesets with 3 changes to 3 files
200 added 2 changesets with 3 changes to 3 files
201 Content-Type: text/plain; charset="us-ascii"
201 Content-Type: text/plain; charset="us-ascii"
202 MIME-Version: 1.0
202 MIME-Version: 1.0
203 Content-Transfer-Encoding: 7bit
203 Content-Transfer-Encoding: 7bit
204 Date: * (glob)
204 Date: * (glob)
205 Subject: changeset in...
205 Subject: changeset in...
206 From: mercurial
206 From: mercurial
207 X-Hg-Notification: changeset a2392c293916
207 X-Hg-Notification: changeset a2392c293916
208 Message-Id: <hg.a2392c293916*> (glob)
208 Message-Id: <hg.a2392c293916*> (glob)
209 To: Test
209 To: Test
210
210
211 changeset a2392c293916 in $TESTTMP/Test
211 changeset a2392c293916 in $TESTTMP/Test
212 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
212 details: $TESTTMP/Test?cmd=changeset;node=a2392c293916
213 description:
213 description:
214 addsym
214 addsym
215
215
216 diffs (6 lines):
216 diffs (6 lines):
217
217
218 diff -r 000000000000 -r a2392c293916 sym
218 diff -r 000000000000 -r a2392c293916 sym
219 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
219 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
220 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
220 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
221 @@ -0,0 +1,1 @@
221 @@ -0,0 +1,1 @@
222 +a
222 +a
223 \ No newline at end of file
223 \ No newline at end of file
224 Content-Type: text/plain; charset="us-ascii"
224 Content-Type: text/plain; charset="us-ascii"
225 MIME-Version: 1.0
225 MIME-Version: 1.0
226 Content-Transfer-Encoding: 7bit
226 Content-Transfer-Encoding: 7bit
227 Date:* (glob)
227 Date:* (glob)
228 Subject: changeset in...
228 Subject: changeset in...
229 From: User Name <user@example.com>
229 From: User Name <user@example.com>
230 X-Hg-Notification: changeset ef63ca68695b
230 X-Hg-Notification: changeset ef63ca68695b
231 Message-Id: <hg.ef63ca68695b*> (glob)
231 Message-Id: <hg.ef63ca68695b*> (glob)
232 To: Test
232 To: Test
233
233
234 changeset ef63ca68695b in $TESTTMP/Test
234 changeset ef63ca68695b in $TESTTMP/Test
235 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
235 details: $TESTTMP/Test?cmd=changeset;node=ef63ca68695b
236 description:
236 description:
237 absym
237 absym
238
238
239 diffs (12 lines):
239 diffs (12 lines):
240
240
241 diff -r a2392c293916 -r ef63ca68695b a
241 diff -r a2392c293916 -r ef63ca68695b a
242 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
242 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
243 +++ b/a Thu Jan 01 00:00:00 1970 +0000
243 +++ b/a Thu Jan 01 00:00:00 1970 +0000
244 @@ -0,0 +1,3 @@
244 @@ -0,0 +1,3 @@
245 +expand $Id$
245 +expand $Id$
246 +do not process $Id:
246 +do not process $Id:
247 +xxx $
247 +xxx $
248 diff -r a2392c293916 -r ef63ca68695b b
248 diff -r a2392c293916 -r ef63ca68695b b
249 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
249 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
250 +++ b/b Thu Jan 01 00:00:00 1970 +0000
250 +++ b/b Thu Jan 01 00:00:00 1970 +0000
251 @@ -0,0 +1,1 @@
251 @@ -0,0 +1,1 @@
252 +ignore $Id$
252 +ignore $Id$
253 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
253 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
254
254
255 $ cp $HGRCPATH.nohooks $HGRCPATH
255 $ cp $HGRCPATH.nohooks $HGRCPATH
256
256
257 Touch files and check with status
257 Touch files and check with status
258
258
259 $ touch a b
259 $ touch a b
260 $ hg status
260 $ hg status
261
261
262 Update and expand
262 Update and expand
263
263
264 $ rm sym a b
264 $ rm sym a b
265 $ hg update -C
265 $ hg update -C
266 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
267 $ cat a b
267 $ cat a b
268 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
268 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
269 do not process $Id:
269 do not process $Id:
270 xxx $
270 xxx $
271 ignore $Id$
271 ignore $Id$
272
272
273 Check whether expansion is filewise and file mode is preserved
273 Check whether expansion is filewise and file mode is preserved
274
274
275 $ echo '$Id$' > c
275 $ echo '$Id$' > c
276 $ echo 'tests for different changenodes' >> c
276 $ echo 'tests for different changenodes' >> c
277 $ chmod 600 c
277 $ chmod 600 c
278 $ ls -l c | cut -b 1-10
278 $ ls -l c | cut -b 1-10
279 -rw-------
279 -rw-------
280
280
281 commit file c
281 commit file c
282
282
283 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
283 $ hg commit -A -mcndiff -d '1 0' -u 'User Name <user@example.com>'
284 adding c
284 adding c
285 $ ls -l c | cut -b 1-10
285 $ ls -l c | cut -b 1-10
286 -rw-------
286 -rw-------
287
287
288 force expansion
288 force expansion
289
289
290 $ hg -v kwexpand
290 $ hg -v kwexpand
291 overwriting a expanding keywords
291 overwriting a expanding keywords
292 overwriting c expanding keywords
292 overwriting c expanding keywords
293
293
294 compare changenodes in a and c
294 compare changenodes in a and c
295
295
296 $ cat a c
296 $ cat a c
297 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
297 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
298 do not process $Id:
298 do not process $Id:
299 xxx $
299 xxx $
300 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
300 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
301 tests for different changenodes
301 tests for different changenodes
302
302
303 record
303 record
304
304
305 $ echo '$Id$' > r
305 $ echo '$Id$' > r
306 $ hg add r
306 $ hg add r
307
307
308 record chunk
308 record chunk
309
309
310 $ python -c \
310 $ python -c \
311 > 'l=open("a").readlines();l.insert(1,"foo\n");l.append("bar\n");open("a","w").writelines(l);'
311 > 'l=open("a").readlines();l.insert(1,"foo\n");l.append("bar\n");open("a","w").writelines(l);'
312 $ hg record -d '1 10' -m rectest a<<EOF
312 $ hg record -d '1 10' -m rectest a<<EOF
313 > y
313 > y
314 > y
314 > y
315 > n
315 > n
316 > EOF
316 > EOF
317 diff --git a/a b/a
317 diff --git a/a b/a
318 2 hunks, 2 lines changed
318 2 hunks, 2 lines changed
319 examine changes to 'a'? [Ynsfdaq?]
319 examine changes to 'a'? [Ynsfdaq?]
320 @@ -1,3 +1,4 @@
320 @@ -1,3 +1,4 @@
321 expand $Id$
321 expand $Id$
322 +foo
322 +foo
323 do not process $Id:
323 do not process $Id:
324 xxx $
324 xxx $
325 record change 1/2 to 'a'? [Ynsfdaq?]
325 record change 1/2 to 'a'? [Ynsfdaq?]
326 @@ -2,2 +3,3 @@
326 @@ -2,2 +3,3 @@
327 do not process $Id:
327 do not process $Id:
328 xxx $
328 xxx $
329 +bar
329 +bar
330 record change 2/2 to 'a'? [Ynsfdaq?]
330 record change 2/2 to 'a'? [Ynsfdaq?]
331
331
332 $ hg identify
332 $ hg identify
333 d17e03c92c97+ tip
333 d17e03c92c97+ tip
334 $ hg status
334 $ hg status
335 M a
335 M a
336 A r
336 A r
337
337
338 Cat modified file a
338 Cat modified file a
339
339
340 $ cat a
340 $ cat a
341 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
341 expand $Id: a,v d17e03c92c97 1970/01/01 00:00:01 test $
342 foo
342 foo
343 do not process $Id:
343 do not process $Id:
344 xxx $
344 xxx $
345 bar
345 bar
346
346
347 Diff remaining chunk
347 Diff remaining chunk
348
348
349 $ hg diff a
349 $ hg diff a
350 diff -r d17e03c92c97 a
350 diff -r d17e03c92c97 a
351 --- a/a Wed Dec 31 23:59:51 1969 -0000
351 --- a/a Wed Dec 31 23:59:51 1969 -0000
352 +++ b/a * (glob)
352 +++ b/a * (glob)
353 @@ -2,3 +2,4 @@
353 @@ -2,3 +2,4 @@
354 foo
354 foo
355 do not process $Id:
355 do not process $Id:
356 xxx $
356 xxx $
357 +bar
357 +bar
358
358
359 $ hg rollback
359 $ hg rollback
360 repository tip rolled back to revision 2 (undo commit)
360 repository tip rolled back to revision 2 (undo commit)
361 working directory now based on revision 2
361 working directory now based on revision 2
362
362
363 Record all chunks in file a
363 Record all chunks in file a
364
364
365 $ echo foo > msg
365 $ echo foo > msg
366
366
367 - do not use "hg record -m" here!
367 - do not use "hg record -m" here!
368
368
369 $ hg record -l msg -d '1 11' a<<EOF
369 $ hg record -l msg -d '1 11' a<<EOF
370 > y
370 > y
371 > y
371 > y
372 > y
372 > y
373 > EOF
373 > EOF
374 diff --git a/a b/a
374 diff --git a/a b/a
375 2 hunks, 2 lines changed
375 2 hunks, 2 lines changed
376 examine changes to 'a'? [Ynsfdaq?]
376 examine changes to 'a'? [Ynsfdaq?]
377 @@ -1,3 +1,4 @@
377 @@ -1,3 +1,4 @@
378 expand $Id$
378 expand $Id$
379 +foo
379 +foo
380 do not process $Id:
380 do not process $Id:
381 xxx $
381 xxx $
382 record change 1/2 to 'a'? [Ynsfdaq?]
382 record change 1/2 to 'a'? [Ynsfdaq?]
383 @@ -2,2 +3,3 @@
383 @@ -2,2 +3,3 @@
384 do not process $Id:
384 do not process $Id:
385 xxx $
385 xxx $
386 +bar
386 +bar
387 record change 2/2 to 'a'? [Ynsfdaq?]
387 record change 2/2 to 'a'? [Ynsfdaq?]
388
388
389 File a should be clean
389 File a should be clean
390
390
391 $ hg status -A a
391 $ hg status -A a
392 C a
392 C a
393
393
394 rollback and revert expansion
394 rollback and revert expansion
395
395
396 $ cat a
396 $ cat a
397 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
397 expand $Id: a,v 59f969a3b52c 1970/01/01 00:00:01 test $
398 foo
398 foo
399 do not process $Id:
399 do not process $Id:
400 xxx $
400 xxx $
401 bar
401 bar
402 $ hg --verbose rollback
402 $ hg --verbose rollback
403 repository tip rolled back to revision 2 (undo commit)
403 repository tip rolled back to revision 2 (undo commit)
404 working directory now based on revision 2
404 working directory now based on revision 2
405 overwriting a expanding keywords
405 overwriting a expanding keywords
406 $ hg status a
406 $ hg status a
407 M a
407 M a
408 $ cat a
408 $ cat a
409 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
409 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
410 foo
410 foo
411 do not process $Id:
411 do not process $Id:
412 xxx $
412 xxx $
413 bar
413 bar
414 $ echo '$Id$' > y
414 $ echo '$Id$' > y
415 $ echo '$Id$' > z
415 $ echo '$Id$' > z
416 $ hg add y
416 $ hg add y
417 $ hg commit -Am "rollback only" z
417 $ hg commit -Am "rollback only" z
418 $ cat z
418 $ cat z
419 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
419 $Id: z,v 45a5d3adce53 1970/01/01 00:00:00 test $
420 $ hg --verbose rollback
420 $ hg --verbose rollback
421 repository tip rolled back to revision 2 (undo commit)
421 repository tip rolled back to revision 2 (undo commit)
422 working directory now based on revision 2
422 working directory now based on revision 2
423 overwriting z shrinking keywords
423 overwriting z shrinking keywords
424
424
425 Only z should be overwritten
425 Only z should be overwritten
426
426
427 $ hg status a y z
427 $ hg status a y z
428 M a
428 M a
429 A y
429 A y
430 A z
430 A z
431 $ cat z
431 $ cat z
432 $Id$
432 $Id$
433 $ hg forget y z
433 $ hg forget y z
434 $ rm y z
434 $ rm y z
435
435
436 record added file alone
436 record added file alone
437
437
438 $ hg -v record -l msg -d '1 12' r<<EOF
438 $ hg -v record -l msg -d '1 12' r<<EOF
439 > y
439 > y
440 > EOF
440 > EOF
441 diff --git a/r b/r
441 diff --git a/r b/r
442 new file mode 100644
442 new file mode 100644
443 examine changes to 'r'? [Ynsfdaq?]
443 examine changes to 'r'? [Ynsfdaq?]
444 r
444 r
445 committed changeset 3:899491280810
445 committed changeset 3:899491280810
446 overwriting r expanding keywords
446 overwriting r expanding keywords
447 - status call required for dirstate.normallookup() check
447 - status call required for dirstate.normallookup() check
448 $ hg status r
448 $ hg status r
449 $ hg --verbose rollback
449 $ hg --verbose rollback
450 repository tip rolled back to revision 2 (undo commit)
450 repository tip rolled back to revision 2 (undo commit)
451 working directory now based on revision 2
451 working directory now based on revision 2
452 overwriting r shrinking keywords
452 overwriting r shrinking keywords
453 $ hg forget r
453 $ hg forget r
454 $ rm msg r
454 $ rm msg r
455 $ hg update -C
455 $ hg update -C
456 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
456 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
457
457
458 record added keyword ignored file
458 record added keyword ignored file
459
459
460 $ echo '$Id$' > i
460 $ echo '$Id$' > i
461 $ hg add i
461 $ hg add i
462 $ hg --verbose record -d '1 13' -m recignored<<EOF
462 $ hg --verbose record -d '1 13' -m recignored<<EOF
463 > y
463 > y
464 > EOF
464 > EOF
465 diff --git a/i b/i
465 diff --git a/i b/i
466 new file mode 100644
466 new file mode 100644
467 examine changes to 'i'? [Ynsfdaq?]
467 examine changes to 'i'? [Ynsfdaq?]
468 i
468 i
469 committed changeset 3:5f40fe93bbdc
469 committed changeset 3:5f40fe93bbdc
470 $ cat i
470 $ cat i
471 $Id$
471 $Id$
472 $ hg -q rollback
472 $ hg -q rollback
473 $ hg forget i
473 $ hg forget i
474 $ rm i
474 $ rm i
475
475
476 Test patch queue repo
476 Test patch queue repo
477
477
478 $ hg init --mq
478 $ hg init --mq
479 $ hg qimport -r tip -n mqtest.diff
479 $ hg qimport -r tip -n mqtest.diff
480 $ hg commit --mq -m mqtest
480 $ hg commit --mq -m mqtest
481
481
482 Keywords should not be expanded in patch
482 Keywords should not be expanded in patch
483
483
484 $ cat .hg/patches/mqtest.diff
484 $ cat .hg/patches/mqtest.diff
485 # HG changeset patch
485 # HG changeset patch
486 # User User Name <user@example.com>
486 # User User Name <user@example.com>
487 # Date 1 0
487 # Date 1 0
488 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
488 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
489 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
489 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
490 cndiff
490 cndiff
491
491
492 diff -r ef63ca68695b -r 40a904bbbe4c c
492 diff -r ef63ca68695b -r 40a904bbbe4c c
493 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
493 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
494 +++ b/c Thu Jan 01 00:00:01 1970 +0000
494 +++ b/c Thu Jan 01 00:00:01 1970 +0000
495 @@ -0,0 +1,2 @@
495 @@ -0,0 +1,2 @@
496 +$Id$
496 +$Id$
497 +tests for different changenodes
497 +tests for different changenodes
498
498
499 $ hg qpop
499 $ hg qpop
500 popping mqtest.diff
500 popping mqtest.diff
501 patch queue now empty
501 patch queue now empty
502
502
503 qgoto, implying qpush, should expand
503 qgoto, implying qpush, should expand
504
504
505 $ hg qgoto mqtest.diff
505 $ hg qgoto mqtest.diff
506 applying mqtest.diff
506 applying mqtest.diff
507 now at: mqtest.diff
507 now at: mqtest.diff
508 $ cat c
508 $ cat c
509 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
509 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
510 tests for different changenodes
510 tests for different changenodes
511 $ hg cat c
511 $ hg cat c
512 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
512 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
513 tests for different changenodes
513 tests for different changenodes
514
514
515 Keywords should not be expanded in filelog
515 Keywords should not be expanded in filelog
516
516
517 $ hg --config 'extensions.keyword=!' cat c
517 $ hg --config 'extensions.keyword=!' cat c
518 $Id$
518 $Id$
519 tests for different changenodes
519 tests for different changenodes
520
520
521 qpop and move on
521 qpop and move on
522
522
523 $ hg qpop
523 $ hg qpop
524 popping mqtest.diff
524 popping mqtest.diff
525 patch queue now empty
525 patch queue now empty
526
526
527 Copy and show added kwfiles
527 Copy and show added kwfiles
528
528
529 $ hg cp a c
529 $ hg cp a c
530 $ hg kwfiles
530 $ hg kwfiles
531 a
531 a
532 c
532 c
533
533
534 Commit and show expansion in original and copy
534 Commit and show expansion in original and copy
535
535
536 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
536 $ hg --debug commit -ma2c -d '1 0' -u 'User Name <user@example.com>'
537 c
537 c
538 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
538 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
539 overwriting c expanding keywords
539 overwriting c expanding keywords
540 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
540 committed changeset 2:25736cf2f5cbe41f6be4e6784ef6ecf9f3bbcc7d
541 $ cat a c
541 $ cat a c
542 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
542 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
543 do not process $Id:
543 do not process $Id:
544 xxx $
544 xxx $
545 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
545 expand $Id: c,v 25736cf2f5cb 1970/01/01 00:00:01 user $
546 do not process $Id:
546 do not process $Id:
547 xxx $
547 xxx $
548
548
549 Touch copied c and check its status
549 Touch copied c and check its status
550
550
551 $ touch c
551 $ touch c
552 $ hg status
552 $ hg status
553
553
554 Copy kwfile to keyword ignored file unexpanding keywords
554 Copy kwfile to keyword ignored file unexpanding keywords
555
555
556 $ hg --verbose copy a i
556 $ hg --verbose copy a i
557 copying a to i
557 copying a to i
558 overwriting i shrinking keywords
558 overwriting i shrinking keywords
559 $ head -n 1 i
559 $ head -n 1 i
560 expand $Id$
560 expand $Id$
561 $ hg forget i
561 $ hg forget i
562 $ rm i
562 $ rm i
563
563
564 Copy ignored file to ignored file: no overwriting
564 Copy ignored file to ignored file: no overwriting
565
565
566 $ hg --verbose copy b i
566 $ hg --verbose copy b i
567 copying b to i
567 copying b to i
568 $ hg forget i
568 $ hg forget i
569 $ rm i
569 $ rm i
570
570
571 cp symlink file; hg cp -A symlink file (part1)
571 cp symlink file; hg cp -A symlink file (part1)
572 - copied symlink points to kwfile: overwrite
572 - copied symlink points to kwfile: overwrite
573
573
574 $ cp sym i
574 $ cp sym i
575 $ ls -l i
575 $ ls -l i
576 -rw-r--r--* (glob)
576 -rw-r--r--* (glob)
577 $ head -1 i
577 $ head -1 i
578 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
578 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
579 $ hg copy --after --verbose sym i
579 $ hg copy --after --verbose sym i
580 copying sym to i
580 copying sym to i
581 overwriting i shrinking keywords
581 overwriting i shrinking keywords
582 $ head -1 i
582 $ head -1 i
583 expand $Id$
583 expand $Id$
584 $ hg forget i
584 $ hg forget i
585 $ rm i
585 $ rm i
586
586
587 Test different options of hg kwfiles
587 Test different options of hg kwfiles
588
588
589 $ hg kwfiles
589 $ hg kwfiles
590 a
590 a
591 c
591 c
592 $ hg -v kwfiles --ignore
592 $ hg -v kwfiles --ignore
593 I b
593 I b
594 I sym
594 I sym
595 $ hg kwfiles --all
595 $ hg kwfiles --all
596 K a
596 K a
597 K c
597 K c
598 I b
598 I b
599 I sym
599 I sym
600
600
601 Diff specific revision
601 Diff specific revision
602
602
603 $ hg diff --rev 1
603 $ hg diff --rev 1
604 diff -r ef63ca68695b c
604 diff -r ef63ca68695b c
605 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
605 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
606 +++ b/c * (glob)
606 +++ b/c * (glob)
607 @@ -0,0 +1,3 @@
607 @@ -0,0 +1,3 @@
608 +expand $Id$
608 +expand $Id$
609 +do not process $Id:
609 +do not process $Id:
610 +xxx $
610 +xxx $
611
611
612 Status after rollback:
612 Status after rollback:
613
613
614 $ hg rollback
614 $ hg rollback
615 repository tip rolled back to revision 1 (undo commit)
615 repository tip rolled back to revision 1 (undo commit)
616 working directory now based on revision 1
616 working directory now based on revision 1
617 $ hg status
617 $ hg status
618 A c
618 A c
619 $ hg update --clean
619 $ hg update --clean
620 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
620 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
621
621
622 cp symlink file; hg cp -A symlink file (part2)
622 cp symlink file; hg cp -A symlink file (part2)
623 - copied symlink points to kw ignored file: do not overwrite
623 - copied symlink points to kw ignored file: do not overwrite
624
624
625 $ cat a > i
625 $ cat a > i
626 $ ln -s i symignored
626 $ ln -s i symignored
627 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
627 $ hg commit -Am 'fake expansion in ignored and symlink' i symignored
628 $ cp symignored x
628 $ cp symignored x
629 $ hg copy --after --verbose symignored x
629 $ hg copy --after --verbose symignored x
630 copying symignored to x
630 copying symignored to x
631 $ head -n 1 x
631 $ head -n 1 x
632 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
632 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
633 $ hg forget x
633 $ hg forget x
634 $ rm x
634 $ rm x
635
635
636 $ hg rollback
636 $ hg rollback
637 repository tip rolled back to revision 1 (undo commit)
637 repository tip rolled back to revision 1 (undo commit)
638 working directory now based on revision 1
638 working directory now based on revision 1
639 $ hg update --clean
639 $ hg update --clean
640 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
640 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
641 $ rm i symignored
641 $ rm i symignored
642
642
643 Custom keywordmaps as argument to kwdemo
643 Custom keywordmaps as argument to kwdemo
644
644
645 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
645 $ hg --quiet kwdemo "Xinfo = {author}: {desc}"
646 [extensions]
646 [extensions]
647 keyword =
647 keyword =
648 [keyword]
648 [keyword]
649 ** =
649 ** =
650 b = ignore
650 b = ignore
651 demo.txt =
651 demo.txt =
652 i = ignore
652 i = ignore
653 [keywordset]
653 [keywordset]
654 svn = False
654 svn = False
655 [keywordmaps]
655 [keywordmaps]
656 Xinfo = {author}: {desc}
656 Xinfo = {author}: {desc}
657 $Xinfo: test: hg keyword configuration and expansion example $
657 $Xinfo: test: hg keyword configuration and expansion example $
658
658
659 Configure custom keywordmaps
659 Configure custom keywordmaps
660
660
661 $ cat <<EOF >>$HGRCPATH
661 $ cat <<EOF >>$HGRCPATH
662 > [keywordmaps]
662 > [keywordmaps]
663 > Id = {file} {node|short} {date|rfc822date} {author|user}
663 > Id = {file} {node|short} {date|rfc822date} {author|user}
664 > Xinfo = {author}: {desc}
664 > Xinfo = {author}: {desc}
665 > EOF
665 > EOF
666
666
667 Cat and hg cat files before custom expansion
667 Cat and hg cat files before custom expansion
668
668
669 $ cat a b
669 $ cat a b
670 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
670 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
671 do not process $Id:
671 do not process $Id:
672 xxx $
672 xxx $
673 ignore $Id$
673 ignore $Id$
674 $ hg cat sym a b && echo
674 $ hg cat sym a b && echo
675 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
675 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
676 do not process $Id:
676 do not process $Id:
677 xxx $
677 xxx $
678 ignore $Id$
678 ignore $Id$
679 a
679 a
680
680
681 Write custom keyword and prepare multiline commit message
681 Write custom keyword and prepare multiline commit message
682
682
683 $ echo '$Xinfo$' >> a
683 $ echo '$Xinfo$' >> a
684 $ cat <<EOF >> log
684 $ cat <<EOF >> log
685 > firstline
685 > firstline
686 > secondline
686 > secondline
687 > EOF
687 > EOF
688
688
689 Interrupted commit should not change state
689 Interrupted commit should not change state
690
690
691 $ hg commit
691 $ hg commit
692 abort: empty commit message
692 abort: empty commit message
693 [255]
693 [255]
694 $ hg status
694 $ hg status
695 M a
695 M a
696 ? c
696 ? c
697 ? log
697 ? log
698
698
699 Commit with multiline message and custom expansion
699 Commit with multiline message and custom expansion
700
700
701 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
701 $ hg --debug commit -l log -d '2 0' -u 'User Name <user@example.com>'
702 a
702 a
703 overwriting a expanding keywords
703 overwriting a expanding keywords
704 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
704 committed changeset 2:bb948857c743469b22bbf51f7ec8112279ca5d83
705 $ rm log
705 $ rm log
706
706
707 Stat, verify and show custom expansion (firstline)
707 Stat, verify and show custom expansion (firstline)
708
708
709 $ hg status
709 $ hg status
710 ? c
710 ? c
711 $ hg verify
711 $ hg verify
712 checking changesets
712 checking changesets
713 checking manifests
713 checking manifests
714 crosschecking files in changesets and manifests
714 crosschecking files in changesets and manifests
715 checking files
715 checking files
716 3 files, 3 changesets, 4 total revisions
716 3 files, 3 changesets, 4 total revisions
717 $ cat a b
717 $ cat a b
718 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
718 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
719 do not process $Id:
719 do not process $Id:
720 xxx $
720 xxx $
721 $Xinfo: User Name <user@example.com>: firstline $
721 $Xinfo: User Name <user@example.com>: firstline $
722 ignore $Id$
722 ignore $Id$
723 $ hg cat sym a b && echo
723 $ hg cat sym a b && echo
724 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
724 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
725 do not process $Id:
725 do not process $Id:
726 xxx $
726 xxx $
727 $Xinfo: User Name <user@example.com>: firstline $
727 $Xinfo: User Name <user@example.com>: firstline $
728 ignore $Id$
728 ignore $Id$
729 a
729 a
730
730
731 annotate
731 annotate
732
732
733 $ hg annotate a
733 $ hg annotate a
734 1: expand $Id$
734 1: expand $Id$
735 1: do not process $Id:
735 1: do not process $Id:
736 1: xxx $
736 1: xxx $
737 2: $Xinfo$
737 2: $Xinfo$
738
738
739 remove with status checks
739 remove with status checks
740
740
741 $ hg debugrebuildstate
741 $ hg debugrebuildstate
742 $ hg remove a
742 $ hg remove a
743 $ hg --debug commit -m rma
743 $ hg --debug commit -m rma
744 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
744 committed changeset 3:d14c712653769de926994cf7fbb06c8fbd68f012
745 $ hg status
745 $ hg status
746 ? c
746 ? c
747
747
748 Rollback, revert, and check expansion
748 Rollback, revert, and check expansion
749
749
750 $ hg rollback
750 $ hg rollback
751 repository tip rolled back to revision 2 (undo commit)
751 repository tip rolled back to revision 2 (undo commit)
752 working directory now based on revision 2
752 working directory now based on revision 2
753 $ hg status
753 $ hg status
754 R a
754 R a
755 ? c
755 ? c
756 $ hg revert --no-backup --rev tip a
756 $ hg revert --no-backup --rev tip a
757 $ cat a
757 $ cat a
758 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
758 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
759 do not process $Id:
759 do not process $Id:
760 xxx $
760 xxx $
761 $Xinfo: User Name <user@example.com>: firstline $
761 $Xinfo: User Name <user@example.com>: firstline $
762
762
763 Clone to test global and local configurations
763 Clone to test global and local configurations
764
764
765 $ cd ..
765 $ cd ..
766
766
767 Expansion in destinaton with global configuration
767 Expansion in destinaton with global configuration
768
768
769 $ hg --quiet clone Test globalconf
769 $ hg --quiet clone Test globalconf
770 $ cat globalconf/a
770 $ cat globalconf/a
771 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
771 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
772 do not process $Id:
772 do not process $Id:
773 xxx $
773 xxx $
774 $Xinfo: User Name <user@example.com>: firstline $
774 $Xinfo: User Name <user@example.com>: firstline $
775
775
776 No expansion in destination with local configuration in origin only
776 No expansion in destination with local configuration in origin only
777
777
778 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
778 $ hg --quiet --config 'keyword.**=ignore' clone Test localconf
779 $ cat localconf/a
779 $ cat localconf/a
780 expand $Id$
780 expand $Id$
781 do not process $Id:
781 do not process $Id:
782 xxx $
782 xxx $
783 $Xinfo$
783 $Xinfo$
784
784
785 Clone to test incoming
785 Clone to test incoming
786
786
787 $ hg clone -r1 Test Test-a
787 $ hg clone -r1 Test Test-a
788 adding changesets
788 adding changesets
789 adding manifests
789 adding manifests
790 adding file changes
790 adding file changes
791 added 2 changesets with 3 changes to 3 files
791 added 2 changesets with 3 changes to 3 files
792 updating to branch default
792 updating to branch default
793 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
793 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
794 $ cd Test-a
794 $ cd Test-a
795 $ cat <<EOF >> .hg/hgrc
795 $ cat <<EOF >> .hg/hgrc
796 > [paths]
796 > [paths]
797 > default = ../Test
797 > default = ../Test
798 > EOF
798 > EOF
799 $ hg incoming
799 $ hg incoming
800 comparing with $TESTTMP/Test
800 comparing with $TESTTMP/Test
801 searching for changes
801 searching for changes
802 changeset: 2:bb948857c743
802 changeset: 2:bb948857c743
803 tag: tip
803 tag: tip
804 user: User Name <user@example.com>
804 user: User Name <user@example.com>
805 date: Thu Jan 01 00:00:02 1970 +0000
805 date: Thu Jan 01 00:00:02 1970 +0000
806 summary: firstline
806 summary: firstline
807
807
808 Imported patch should not be rejected
808 Imported patch should not be rejected
809
809
810 $ python -c \
810 $ python -c \
811 > 'import re; s=re.sub("(Id.*)","\\1 rejecttest",open("a").read()); open("a","wb").write(s);'
811 > 'import re; s=re.sub("(Id.*)","\\1 rejecttest",open("a").read()); open("a","wb").write(s);'
812 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
812 $ hg --debug commit -m'rejects?' -d '3 0' -u 'User Name <user@example.com>'
813 a
813 a
814 overwriting a expanding keywords
814 overwriting a expanding keywords
815 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
815 committed changeset 2:85e279d709ffc28c9fdd1b868570985fc3d87082
816 $ hg export -o ../rejecttest.diff tip
816 $ hg export -o ../rejecttest.diff tip
817 $ cd ../Test
817 $ cd ../Test
818 $ hg import ../rejecttest.diff
818 $ hg import ../rejecttest.diff
819 applying ../rejecttest.diff
819 applying ../rejecttest.diff
820 $ cat a b
820 $ cat a b
821 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
821 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
822 do not process $Id: rejecttest
822 do not process $Id: rejecttest
823 xxx $
823 xxx $
824 $Xinfo: User Name <user@example.com>: rejects? $
824 $Xinfo: User Name <user@example.com>: rejects? $
825 ignore $Id$
825 ignore $Id$
826
826
827 $ hg rollback
827 $ hg rollback
828 repository tip rolled back to revision 2 (undo commit)
828 repository tip rolled back to revision 2 (undo import)
829 working directory now based on revision 2
829 working directory now based on revision 2
830 $ hg update --clean
830 $ hg update --clean
831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
831 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
832
832
833 kwexpand/kwshrink on selected files
833 kwexpand/kwshrink on selected files
834
834
835 $ mkdir x
835 $ mkdir x
836 $ hg copy a x/a
836 $ hg copy a x/a
837 $ hg --verbose kwshrink a
837 $ hg --verbose kwshrink a
838 overwriting a shrinking keywords
838 overwriting a shrinking keywords
839 - sleep required for dirstate.normal() check
839 - sleep required for dirstate.normal() check
840 $ sleep 1
840 $ sleep 1
841 $ hg status a
841 $ hg status a
842 $ hg --verbose kwexpand a
842 $ hg --verbose kwexpand a
843 overwriting a expanding keywords
843 overwriting a expanding keywords
844 $ hg status a
844 $ hg status a
845
845
846 kwexpand x/a should abort
846 kwexpand x/a should abort
847
847
848 $ hg --verbose kwexpand x/a
848 $ hg --verbose kwexpand x/a
849 abort: outstanding uncommitted changes
849 abort: outstanding uncommitted changes
850 [255]
850 [255]
851 $ cd x
851 $ cd x
852 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
852 $ hg --debug commit -m xa -d '3 0' -u 'User Name <user@example.com>'
853 x/a
853 x/a
854 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
854 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
855 overwriting x/a expanding keywords
855 overwriting x/a expanding keywords
856 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
856 committed changeset 3:b4560182a3f9a358179fd2d835c15e9da379c1e4
857 $ cat a
857 $ cat a
858 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
858 expand $Id: x/a b4560182a3f9 Thu, 01 Jan 1970 00:00:03 +0000 user $
859 do not process $Id:
859 do not process $Id:
860 xxx $
860 xxx $
861 $Xinfo: User Name <user@example.com>: xa $
861 $Xinfo: User Name <user@example.com>: xa $
862
862
863 kwshrink a inside directory x
863 kwshrink a inside directory x
864
864
865 $ hg --verbose kwshrink a
865 $ hg --verbose kwshrink a
866 overwriting x/a shrinking keywords
866 overwriting x/a shrinking keywords
867 $ cat a
867 $ cat a
868 expand $Id$
868 expand $Id$
869 do not process $Id:
869 do not process $Id:
870 xxx $
870 xxx $
871 $Xinfo$
871 $Xinfo$
872 $ cd ..
872 $ cd ..
873
873
874 kwexpand nonexistent
874 kwexpand nonexistent
875
875
876 $ hg kwexpand nonexistent
876 $ hg kwexpand nonexistent
877 nonexistent:* (glob)
877 nonexistent:* (glob)
878
878
879
879
880 hg serve
880 hg serve
881 - expand with hgweb file
881 - expand with hgweb file
882 - no expansion with hgweb annotate/changeset/filediff
882 - no expansion with hgweb annotate/changeset/filediff
883 - check errors
883 - check errors
884
884
885 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
885 $ hg serve -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
886 $ cat hg.pid >> $DAEMON_PIDS
886 $ cat hg.pid >> $DAEMON_PIDS
887 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
887 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/file/tip/a/?style=raw'
888 200 Script output follows
888 200 Script output follows
889
889
890 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
890 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
891 do not process $Id:
891 do not process $Id:
892 xxx $
892 xxx $
893 $Xinfo: User Name <user@example.com>: firstline $
893 $Xinfo: User Name <user@example.com>: firstline $
894 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
894 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/annotate/tip/a/?style=raw'
895 200 Script output follows
895 200 Script output follows
896
896
897
897
898 user@1: expand $Id$
898 user@1: expand $Id$
899 user@1: do not process $Id:
899 user@1: do not process $Id:
900 user@1: xxx $
900 user@1: xxx $
901 user@2: $Xinfo$
901 user@2: $Xinfo$
902
902
903
903
904
904
905
905
906 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
906 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/rev/tip/?style=raw'
907 200 Script output follows
907 200 Script output follows
908
908
909
909
910 # HG changeset patch
910 # HG changeset patch
911 # User User Name <user@example.com>
911 # User User Name <user@example.com>
912 # Date 3 0
912 # Date 3 0
913 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
913 # Node ID b4560182a3f9a358179fd2d835c15e9da379c1e4
914 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
914 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
915 xa
915 xa
916
916
917 diff -r bb948857c743 -r b4560182a3f9 x/a
917 diff -r bb948857c743 -r b4560182a3f9 x/a
918 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
918 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
919 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
919 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
920 @@ -0,0 +1,4 @@
920 @@ -0,0 +1,4 @@
921 +expand $Id$
921 +expand $Id$
922 +do not process $Id:
922 +do not process $Id:
923 +xxx $
923 +xxx $
924 +$Xinfo$
924 +$Xinfo$
925
925
926 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
926 $ $TESTDIR/get-with-headers.py localhost:$HGPORT '/diff/bb948857c743/a?style=raw'
927 200 Script output follows
927 200 Script output follows
928
928
929
929
930 diff -r ef63ca68695b -r bb948857c743 a
930 diff -r ef63ca68695b -r bb948857c743 a
931 --- a/a Thu Jan 01 00:00:00 1970 +0000
931 --- a/a Thu Jan 01 00:00:00 1970 +0000
932 +++ b/a Thu Jan 01 00:00:02 1970 +0000
932 +++ b/a Thu Jan 01 00:00:02 1970 +0000
933 @@ -1,3 +1,4 @@
933 @@ -1,3 +1,4 @@
934 expand $Id$
934 expand $Id$
935 do not process $Id:
935 do not process $Id:
936 xxx $
936 xxx $
937 +$Xinfo$
937 +$Xinfo$
938
938
939
939
940
940
941
941
942 $ cat errors.log
942 $ cat errors.log
943
943
944 Prepare merge and resolve tests
944 Prepare merge and resolve tests
945
945
946 $ echo '$Id$' > m
946 $ echo '$Id$' > m
947 $ hg add m
947 $ hg add m
948 $ hg commit -m 4kw
948 $ hg commit -m 4kw
949 $ echo foo >> m
949 $ echo foo >> m
950 $ hg commit -m 5foo
950 $ hg commit -m 5foo
951
951
952 simplemerge
952 simplemerge
953
953
954 $ hg update 4
954 $ hg update 4
955 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
955 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
956 $ echo foo >> m
956 $ echo foo >> m
957 $ hg commit -m 6foo
957 $ hg commit -m 6foo
958 created new head
958 created new head
959 $ hg merge
959 $ hg merge
960 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
960 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
961 (branch merge, don't forget to commit)
961 (branch merge, don't forget to commit)
962 $ hg commit -m simplemerge
962 $ hg commit -m simplemerge
963 $ cat m
963 $ cat m
964 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
964 $Id: m 27d48ee14f67 Thu, 01 Jan 1970 00:00:00 +0000 test $
965 foo
965 foo
966
966
967 conflict: keyword should stay outside conflict zone
967 conflict: keyword should stay outside conflict zone
968
968
969 $ hg update 4
969 $ hg update 4
970 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
970 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
971 $ echo bar >> m
971 $ echo bar >> m
972 $ hg commit -m 8bar
972 $ hg commit -m 8bar
973 created new head
973 created new head
974 $ hg merge
974 $ hg merge
975 merging m
975 merging m
976 warning: conflicts during merge.
976 warning: conflicts during merge.
977 merging m failed!
977 merging m failed!
978 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
978 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
979 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
979 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
980 [1]
980 [1]
981 $ cat m
981 $ cat m
982 $Id$
982 $Id$
983 <<<<<<< local
983 <<<<<<< local
984 bar
984 bar
985 =======
985 =======
986 foo
986 foo
987 >>>>>>> other
987 >>>>>>> other
988
988
989 resolve to local
989 resolve to local
990
990
991 $ HGMERGE=internal:local hg resolve -a
991 $ HGMERGE=internal:local hg resolve -a
992 $ hg commit -m localresolve
992 $ hg commit -m localresolve
993 $ cat m
993 $ cat m
994 $Id: m 800511b3a22d Thu, 01 Jan 1970 00:00:00 +0000 test $
994 $Id: m 800511b3a22d Thu, 01 Jan 1970 00:00:00 +0000 test $
995 bar
995 bar
996
996
997 Test restricted mode with transplant -b
997 Test restricted mode with transplant -b
998
998
999 $ hg update 6
999 $ hg update 6
1000 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1000 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1001 $ hg branch foo
1001 $ hg branch foo
1002 marked working directory as branch foo
1002 marked working directory as branch foo
1003 $ mv a a.bak
1003 $ mv a a.bak
1004 $ echo foobranch > a
1004 $ echo foobranch > a
1005 $ cat a.bak >> a
1005 $ cat a.bak >> a
1006 $ rm a.bak
1006 $ rm a.bak
1007 $ hg commit -m 9foobranch
1007 $ hg commit -m 9foobranch
1008 $ hg update default
1008 $ hg update default
1009 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1009 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
1010 $ hg -y transplant -b foo tip
1010 $ hg -y transplant -b foo tip
1011 applying 4aa30d025d50
1011 applying 4aa30d025d50
1012 4aa30d025d50 transplanted to e00abbf63521
1012 4aa30d025d50 transplanted to e00abbf63521
1013
1013
1014 Expansion in changeset but not in file
1014 Expansion in changeset but not in file
1015
1015
1016 $ hg tip -p
1016 $ hg tip -p
1017 changeset: 11:e00abbf63521
1017 changeset: 11:e00abbf63521
1018 tag: tip
1018 tag: tip
1019 parent: 9:800511b3a22d
1019 parent: 9:800511b3a22d
1020 user: test
1020 user: test
1021 date: Thu Jan 01 00:00:00 1970 +0000
1021 date: Thu Jan 01 00:00:00 1970 +0000
1022 summary: 9foobranch
1022 summary: 9foobranch
1023
1023
1024 diff -r 800511b3a22d -r e00abbf63521 a
1024 diff -r 800511b3a22d -r e00abbf63521 a
1025 --- a/a Thu Jan 01 00:00:00 1970 +0000
1025 --- a/a Thu Jan 01 00:00:00 1970 +0000
1026 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1026 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1027 @@ -1,3 +1,4 @@
1027 @@ -1,3 +1,4 @@
1028 +foobranch
1028 +foobranch
1029 expand $Id$
1029 expand $Id$
1030 do not process $Id:
1030 do not process $Id:
1031 xxx $
1031 xxx $
1032
1032
1033 $ head -n 2 a
1033 $ head -n 2 a
1034 foobranch
1034 foobranch
1035 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1035 expand $Id: a e00abbf63521 Thu, 01 Jan 1970 00:00:00 +0000 test $
1036
1036
1037 Turn off expansion
1037 Turn off expansion
1038
1038
1039 $ hg -q rollback
1039 $ hg -q rollback
1040 $ hg -q update -C
1040 $ hg -q update -C
1041
1041
1042 kwshrink with unknown file u
1042 kwshrink with unknown file u
1043
1043
1044 $ cp a u
1044 $ cp a u
1045 $ hg --verbose kwshrink
1045 $ hg --verbose kwshrink
1046 overwriting a shrinking keywords
1046 overwriting a shrinking keywords
1047 overwriting m shrinking keywords
1047 overwriting m shrinking keywords
1048 overwriting x/a shrinking keywords
1048 overwriting x/a shrinking keywords
1049
1049
1050 Keywords shrunk in working directory, but not yet disabled
1050 Keywords shrunk in working directory, but not yet disabled
1051 - cat shows unexpanded keywords
1051 - cat shows unexpanded keywords
1052 - hg cat shows expanded keywords
1052 - hg cat shows expanded keywords
1053
1053
1054 $ cat a b
1054 $ cat a b
1055 expand $Id$
1055 expand $Id$
1056 do not process $Id:
1056 do not process $Id:
1057 xxx $
1057 xxx $
1058 $Xinfo$
1058 $Xinfo$
1059 ignore $Id$
1059 ignore $Id$
1060 $ hg cat sym a b && echo
1060 $ hg cat sym a b && echo
1061 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1061 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
1062 do not process $Id:
1062 do not process $Id:
1063 xxx $
1063 xxx $
1064 $Xinfo: User Name <user@example.com>: firstline $
1064 $Xinfo: User Name <user@example.com>: firstline $
1065 ignore $Id$
1065 ignore $Id$
1066 a
1066 a
1067
1067
1068 Now disable keyword expansion
1068 Now disable keyword expansion
1069
1069
1070 $ rm "$HGRCPATH"
1070 $ rm "$HGRCPATH"
1071 $ cat a b
1071 $ cat a b
1072 expand $Id$
1072 expand $Id$
1073 do not process $Id:
1073 do not process $Id:
1074 xxx $
1074 xxx $
1075 $Xinfo$
1075 $Xinfo$
1076 ignore $Id$
1076 ignore $Id$
1077 $ hg cat sym a b && echo
1077 $ hg cat sym a b && echo
1078 expand $Id$
1078 expand $Id$
1079 do not process $Id:
1079 do not process $Id:
1080 xxx $
1080 xxx $
1081 $Xinfo$
1081 $Xinfo$
1082 ignore $Id$
1082 ignore $Id$
1083 a
1083 a
General Comments 0
You need to be logged in to leave comments. Login now