##// END OF EJS Templates
Have verbose flag print the changeset hash when committing
Gilles Moris -
r6932:d557749c default
parent child Browse files
Show More
@@ -1,3315 +1,3316 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
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from repo import RepoError, NoCapability
9 from repo import RepoError, NoCapability
10 from i18n import _
10 from i18n import _
11 import os, re, sys, urllib
11 import os, re, sys, urllib
12 import hg, util, revlog, bundlerepo, extensions, copies
12 import hg, util, revlog, bundlerepo, extensions, copies
13 import difflib, patch, time, help, mdiff, tempfile
13 import difflib, patch, time, help, mdiff, tempfile
14 import version, socket
14 import version, socket
15 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
15 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
16 import merge as merge_
16 import merge as merge_
17
17
18 # Commands start here, listed alphabetically
18 # Commands start here, listed alphabetically
19
19
20 def add(ui, repo, *pats, **opts):
20 def add(ui, repo, *pats, **opts):
21 """add the specified files on the next commit
21 """add the specified files on the next commit
22
22
23 Schedule files to be version controlled and added to the repository.
23 Schedule files to be version controlled and added to the repository.
24
24
25 The files will be added to the repository at the next commit. To
25 The files will be added to the repository at the next commit. To
26 undo an add before that, see hg revert.
26 undo an add before that, see hg revert.
27
27
28 If no names are given, add all files in the repository.
28 If no names are given, add all files in the repository.
29 """
29 """
30
30
31 rejected = None
31 rejected = None
32 exacts = {}
32 exacts = {}
33 names = []
33 names = []
34 m = cmdutil.match(repo, pats, opts)
34 m = cmdutil.match(repo, pats, opts)
35 m.bad = lambda x,y: True
35 m.bad = lambda x,y: True
36 for abs in repo.walk(m):
36 for abs in repo.walk(m):
37 if m.exact(abs):
37 if m.exact(abs):
38 if ui.verbose:
38 if ui.verbose:
39 ui.status(_('adding %s\n') % m.rel(abs))
39 ui.status(_('adding %s\n') % m.rel(abs))
40 names.append(abs)
40 names.append(abs)
41 exacts[abs] = 1
41 exacts[abs] = 1
42 elif abs not in repo.dirstate:
42 elif abs not in repo.dirstate:
43 ui.status(_('adding %s\n') % m.rel(abs))
43 ui.status(_('adding %s\n') % m.rel(abs))
44 names.append(abs)
44 names.append(abs)
45 if not opts.get('dry_run'):
45 if not opts.get('dry_run'):
46 rejected = repo.add(names)
46 rejected = repo.add(names)
47 rejected = [p for p in rejected if p in exacts]
47 rejected = [p for p in rejected if p in exacts]
48 return rejected and 1 or 0
48 return rejected and 1 or 0
49
49
50 def addremove(ui, repo, *pats, **opts):
50 def addremove(ui, repo, *pats, **opts):
51 """add all new files, delete all missing files
51 """add all new files, delete all missing files
52
52
53 Add all new files and remove all missing files from the repository.
53 Add all new files and remove all missing files from the repository.
54
54
55 New files are ignored if they match any of the patterns in .hgignore. As
55 New files are ignored if they match any of the patterns in .hgignore. As
56 with add, these changes take effect at the next commit.
56 with add, these changes take effect at the next commit.
57
57
58 Use the -s option to detect renamed files. With a parameter > 0,
58 Use the -s option to detect renamed files. With a parameter > 0,
59 this compares every removed file with every added file and records
59 this compares every removed file with every added file and records
60 those similar enough as renames. This option takes a percentage
60 those similar enough as renames. This option takes a percentage
61 between 0 (disabled) and 100 (files must be identical) as its
61 between 0 (disabled) and 100 (files must be identical) as its
62 parameter. Detecting renamed files this way can be expensive.
62 parameter. Detecting renamed files this way can be expensive.
63 """
63 """
64 try:
64 try:
65 sim = float(opts.get('similarity') or 0)
65 sim = float(opts.get('similarity') or 0)
66 except ValueError:
66 except ValueError:
67 raise util.Abort(_('similarity must be a number'))
67 raise util.Abort(_('similarity must be a number'))
68 if sim < 0 or sim > 100:
68 if sim < 0 or sim > 100:
69 raise util.Abort(_('similarity must be between 0 and 100'))
69 raise util.Abort(_('similarity must be between 0 and 100'))
70 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
70 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
71
71
72 def annotate(ui, repo, *pats, **opts):
72 def annotate(ui, repo, *pats, **opts):
73 """show changeset information per file line
73 """show changeset information per file line
74
74
75 List changes in files, showing the revision id responsible for each line
75 List changes in files, showing the revision id responsible for each line
76
76
77 This command is useful to discover who did a change or when a change took
77 This command is useful to discover who did a change or when a change took
78 place.
78 place.
79
79
80 Without the -a option, annotate will avoid processing files it
80 Without the -a option, annotate will avoid processing files it
81 detects as binary. With -a, annotate will generate an annotation
81 detects as binary. With -a, annotate will generate an annotation
82 anyway, probably with undesirable results.
82 anyway, probably with undesirable results.
83 """
83 """
84 datefunc = ui.quiet and util.shortdate or util.datestr
84 datefunc = ui.quiet and util.shortdate or util.datestr
85 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
85 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
86
86
87 if not pats:
87 if not pats:
88 raise util.Abort(_('at least one file name or pattern required'))
88 raise util.Abort(_('at least one file name or pattern required'))
89
89
90 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
90 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
91 ('number', lambda x: str(x[0].rev())),
91 ('number', lambda x: str(x[0].rev())),
92 ('changeset', lambda x: short(x[0].node())),
92 ('changeset', lambda x: short(x[0].node())),
93 ('date', getdate),
93 ('date', getdate),
94 ('follow', lambda x: x[0].path()),
94 ('follow', lambda x: x[0].path()),
95 ]
95 ]
96
96
97 if (not opts['user'] and not opts['changeset'] and not opts['date']
97 if (not opts['user'] and not opts['changeset'] and not opts['date']
98 and not opts['follow']):
98 and not opts['follow']):
99 opts['number'] = 1
99 opts['number'] = 1
100
100
101 linenumber = opts.get('line_number') is not None
101 linenumber = opts.get('line_number') is not None
102 if (linenumber and (not opts['changeset']) and (not opts['number'])):
102 if (linenumber and (not opts['changeset']) and (not opts['number'])):
103 raise util.Abort(_('at least one of -n/-c is required for -l'))
103 raise util.Abort(_('at least one of -n/-c is required for -l'))
104
104
105 funcmap = [func for op, func in opmap if opts.get(op)]
105 funcmap = [func for op, func in opmap if opts.get(op)]
106 if linenumber:
106 if linenumber:
107 lastfunc = funcmap[-1]
107 lastfunc = funcmap[-1]
108 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
108 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
109
109
110 ctx = repo[opts['rev']]
110 ctx = repo[opts['rev']]
111
111
112 m = cmdutil.match(repo, pats, opts)
112 m = cmdutil.match(repo, pats, opts)
113 for abs in ctx.walk(m):
113 for abs in ctx.walk(m):
114 fctx = ctx[abs]
114 fctx = ctx[abs]
115 if not opts['text'] and util.binary(fctx.data()):
115 if not opts['text'] and util.binary(fctx.data()):
116 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
116 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
117 continue
117 continue
118
118
119 lines = fctx.annotate(follow=opts.get('follow'),
119 lines = fctx.annotate(follow=opts.get('follow'),
120 linenumber=linenumber)
120 linenumber=linenumber)
121 pieces = []
121 pieces = []
122
122
123 for f in funcmap:
123 for f in funcmap:
124 l = [f(n) for n, dummy in lines]
124 l = [f(n) for n, dummy in lines]
125 if l:
125 if l:
126 m = max(map(len, l))
126 m = max(map(len, l))
127 pieces.append(["%*s" % (m, x) for x in l])
127 pieces.append(["%*s" % (m, x) for x in l])
128
128
129 if pieces:
129 if pieces:
130 for p, l in zip(zip(*pieces), lines):
130 for p, l in zip(zip(*pieces), lines):
131 ui.write("%s: %s" % (" ".join(p), l[1]))
131 ui.write("%s: %s" % (" ".join(p), l[1]))
132
132
133 def archive(ui, repo, dest, **opts):
133 def archive(ui, repo, dest, **opts):
134 '''create unversioned archive of a repository revision
134 '''create unversioned archive of a repository revision
135
135
136 By default, the revision used is the parent of the working
136 By default, the revision used is the parent of the working
137 directory; use "-r" to specify a different revision.
137 directory; use "-r" to specify a different revision.
138
138
139 To specify the type of archive to create, use "-t". Valid
139 To specify the type of archive to create, use "-t". Valid
140 types are:
140 types are:
141
141
142 "files" (default): a directory full of files
142 "files" (default): a directory full of files
143 "tar": tar archive, uncompressed
143 "tar": tar archive, uncompressed
144 "tbz2": tar archive, compressed using bzip2
144 "tbz2": tar archive, compressed using bzip2
145 "tgz": tar archive, compressed using gzip
145 "tgz": tar archive, compressed using gzip
146 "uzip": zip archive, uncompressed
146 "uzip": zip archive, uncompressed
147 "zip": zip archive, compressed using deflate
147 "zip": zip archive, compressed using deflate
148
148
149 The exact name of the destination archive or directory is given
149 The exact name of the destination archive or directory is given
150 using a format string; see "hg help export" for details.
150 using a format string; see "hg help export" for details.
151
151
152 Each member added to an archive file has a directory prefix
152 Each member added to an archive file has a directory prefix
153 prepended. Use "-p" to specify a format string for the prefix.
153 prepended. Use "-p" to specify a format string for the prefix.
154 The default is the basename of the archive, with suffixes removed.
154 The default is the basename of the archive, with suffixes removed.
155 '''
155 '''
156
156
157 ctx = repo[opts['rev']]
157 ctx = repo[opts['rev']]
158 if not ctx:
158 if not ctx:
159 raise util.Abort(_('repository has no revisions'))
159 raise util.Abort(_('repository has no revisions'))
160 node = ctx.node()
160 node = ctx.node()
161 dest = cmdutil.make_filename(repo, dest, node)
161 dest = cmdutil.make_filename(repo, dest, node)
162 if os.path.realpath(dest) == repo.root:
162 if os.path.realpath(dest) == repo.root:
163 raise util.Abort(_('repository root cannot be destination'))
163 raise util.Abort(_('repository root cannot be destination'))
164 matchfn = cmdutil.match(repo, [], opts)
164 matchfn = cmdutil.match(repo, [], opts)
165 kind = opts.get('type') or 'files'
165 kind = opts.get('type') or 'files'
166 prefix = opts['prefix']
166 prefix = opts['prefix']
167 if dest == '-':
167 if dest == '-':
168 if kind == 'files':
168 if kind == 'files':
169 raise util.Abort(_('cannot archive plain files to stdout'))
169 raise util.Abort(_('cannot archive plain files to stdout'))
170 dest = sys.stdout
170 dest = sys.stdout
171 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
171 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
172 prefix = cmdutil.make_filename(repo, prefix, node)
172 prefix = cmdutil.make_filename(repo, prefix, node)
173 archival.archive(repo, dest, node, kind, not opts['no_decode'],
173 archival.archive(repo, dest, node, kind, not opts['no_decode'],
174 matchfn, prefix)
174 matchfn, prefix)
175
175
176 def backout(ui, repo, node=None, rev=None, **opts):
176 def backout(ui, repo, node=None, rev=None, **opts):
177 '''reverse effect of earlier changeset
177 '''reverse effect of earlier changeset
178
178
179 Commit the backed out changes as a new changeset. The new
179 Commit the backed out changes as a new changeset. The new
180 changeset is a child of the backed out changeset.
180 changeset is a child of the backed out changeset.
181
181
182 If you back out a changeset other than the tip, a new head is
182 If you back out a changeset other than the tip, a new head is
183 created. This head will be the new tip and you should merge this
183 created. This head will be the new tip and you should merge this
184 backout changeset with another head (current one by default).
184 backout changeset with another head (current one by default).
185
185
186 The --merge option remembers the parent of the working directory
186 The --merge option remembers the parent of the working directory
187 before starting the backout, then merges the new head with that
187 before starting the backout, then merges the new head with that
188 changeset afterwards. This saves you from doing the merge by
188 changeset afterwards. This saves you from doing the merge by
189 hand. The result of this merge is not committed, as for a normal
189 hand. The result of this merge is not committed, as for a normal
190 merge.
190 merge.
191
191
192 See \'hg help dates\' for a list of formats valid for -d/--date.
192 See \'hg help dates\' for a list of formats valid for -d/--date.
193 '''
193 '''
194 if rev and node:
194 if rev and node:
195 raise util.Abort(_("please specify just one revision"))
195 raise util.Abort(_("please specify just one revision"))
196
196
197 if not rev:
197 if not rev:
198 rev = node
198 rev = node
199
199
200 if not rev:
200 if not rev:
201 raise util.Abort(_("please specify a revision to backout"))
201 raise util.Abort(_("please specify a revision to backout"))
202
202
203 date = opts.get('date')
203 date = opts.get('date')
204 if date:
204 if date:
205 opts['date'] = util.parsedate(date)
205 opts['date'] = util.parsedate(date)
206
206
207 cmdutil.bail_if_changed(repo)
207 cmdutil.bail_if_changed(repo)
208 node = repo.lookup(rev)
208 node = repo.lookup(rev)
209
209
210 op1, op2 = repo.dirstate.parents()
210 op1, op2 = repo.dirstate.parents()
211 a = repo.changelog.ancestor(op1, node)
211 a = repo.changelog.ancestor(op1, node)
212 if a != node:
212 if a != node:
213 raise util.Abort(_('cannot back out change on a different branch'))
213 raise util.Abort(_('cannot back out change on a different branch'))
214
214
215 p1, p2 = repo.changelog.parents(node)
215 p1, p2 = repo.changelog.parents(node)
216 if p1 == nullid:
216 if p1 == nullid:
217 raise util.Abort(_('cannot back out a change with no parents'))
217 raise util.Abort(_('cannot back out a change with no parents'))
218 if p2 != nullid:
218 if p2 != nullid:
219 if not opts['parent']:
219 if not opts['parent']:
220 raise util.Abort(_('cannot back out a merge changeset without '
220 raise util.Abort(_('cannot back out a merge changeset without '
221 '--parent'))
221 '--parent'))
222 p = repo.lookup(opts['parent'])
222 p = repo.lookup(opts['parent'])
223 if p not in (p1, p2):
223 if p not in (p1, p2):
224 raise util.Abort(_('%s is not a parent of %s') %
224 raise util.Abort(_('%s is not a parent of %s') %
225 (short(p), short(node)))
225 (short(p), short(node)))
226 parent = p
226 parent = p
227 else:
227 else:
228 if opts['parent']:
228 if opts['parent']:
229 raise util.Abort(_('cannot use --parent on non-merge changeset'))
229 raise util.Abort(_('cannot use --parent on non-merge changeset'))
230 parent = p1
230 parent = p1
231
231
232 # the backout should appear on the same branch
232 # the backout should appear on the same branch
233 branch = repo.dirstate.branch()
233 branch = repo.dirstate.branch()
234 hg.clean(repo, node, show_stats=False)
234 hg.clean(repo, node, show_stats=False)
235 repo.dirstate.setbranch(branch)
235 repo.dirstate.setbranch(branch)
236 revert_opts = opts.copy()
236 revert_opts = opts.copy()
237 revert_opts['date'] = None
237 revert_opts['date'] = None
238 revert_opts['all'] = True
238 revert_opts['all'] = True
239 revert_opts['rev'] = hex(parent)
239 revert_opts['rev'] = hex(parent)
240 revert_opts['no_backup'] = None
240 revert_opts['no_backup'] = None
241 revert(ui, repo, **revert_opts)
241 revert(ui, repo, **revert_opts)
242 commit_opts = opts.copy()
242 commit_opts = opts.copy()
243 commit_opts['addremove'] = False
243 commit_opts['addremove'] = False
244 if not commit_opts['message'] and not commit_opts['logfile']:
244 if not commit_opts['message'] and not commit_opts['logfile']:
245 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
245 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
246 commit_opts['force_editor'] = True
246 commit_opts['force_editor'] = True
247 commit(ui, repo, **commit_opts)
247 commit(ui, repo, **commit_opts)
248 def nice(node):
248 def nice(node):
249 return '%d:%s' % (repo.changelog.rev(node), short(node))
249 return '%d:%s' % (repo.changelog.rev(node), short(node))
250 ui.status(_('changeset %s backs out changeset %s\n') %
250 ui.status(_('changeset %s backs out changeset %s\n') %
251 (nice(repo.changelog.tip()), nice(node)))
251 (nice(repo.changelog.tip()), nice(node)))
252 if op1 != node:
252 if op1 != node:
253 hg.clean(repo, op1, show_stats=False)
253 hg.clean(repo, op1, show_stats=False)
254 if opts['merge']:
254 if opts['merge']:
255 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
255 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
256 hg.merge(repo, hex(repo.changelog.tip()))
256 hg.merge(repo, hex(repo.changelog.tip()))
257 else:
257 else:
258 ui.status(_('the backout changeset is a new head - '
258 ui.status(_('the backout changeset is a new head - '
259 'do not forget to merge\n'))
259 'do not forget to merge\n'))
260 ui.status(_('(use "backout --merge" '
260 ui.status(_('(use "backout --merge" '
261 'if you want to auto-merge)\n'))
261 'if you want to auto-merge)\n'))
262
262
263 def bisect(ui, repo, rev=None, extra=None,
263 def bisect(ui, repo, rev=None, extra=None,
264 reset=None, good=None, bad=None, skip=None, noupdate=None):
264 reset=None, good=None, bad=None, skip=None, noupdate=None):
265 """subdivision search of changesets
265 """subdivision search of changesets
266
266
267 This command helps to find changesets which introduce problems.
267 This command helps to find changesets which introduce problems.
268 To use, mark the earliest changeset you know exhibits the problem
268 To use, mark the earliest changeset you know exhibits the problem
269 as bad, then mark the latest changeset which is free from the
269 as bad, then mark the latest changeset which is free from the
270 problem as good. Bisect will update your working directory to a
270 problem as good. Bisect will update your working directory to a
271 revision for testing (unless the --noupdate option is specified).
271 revision for testing (unless the --noupdate option is specified).
272 Once you have performed tests, mark the working directory as bad
272 Once you have performed tests, mark the working directory as bad
273 or good and bisect will either update to another candidate changeset
273 or good and bisect will either update to another candidate changeset
274 or announce that it has found the bad revision.
274 or announce that it has found the bad revision.
275
275
276 As a shortcut, you can also use the revision argument to mark a
276 As a shortcut, you can also use the revision argument to mark a
277 revision as good or bad without checking it out first.
277 revision as good or bad without checking it out first.
278 """
278 """
279 # backward compatibility
279 # backward compatibility
280 if rev in "good bad reset init".split():
280 if rev in "good bad reset init".split():
281 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
281 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
282 cmd, rev, extra = rev, extra, None
282 cmd, rev, extra = rev, extra, None
283 if cmd == "good":
283 if cmd == "good":
284 good = True
284 good = True
285 elif cmd == "bad":
285 elif cmd == "bad":
286 bad = True
286 bad = True
287 else:
287 else:
288 reset = True
288 reset = True
289 elif extra or good + bad + skip + reset > 1:
289 elif extra or good + bad + skip + reset > 1:
290 raise util.Abort(_('incompatible arguments'))
290 raise util.Abort(_('incompatible arguments'))
291 elif not (good or bad or skip or reset):
291 elif not (good or bad or skip or reset):
292 ui.status(_('(no action selected)\n'))
292 ui.status(_('(no action selected)\n'))
293 return
293 return
294
294
295 if reset:
295 if reset:
296 p = repo.join("bisect.state")
296 p = repo.join("bisect.state")
297 if os.path.exists(p):
297 if os.path.exists(p):
298 os.unlink(p)
298 os.unlink(p)
299 return
299 return
300
300
301 # load state
301 # load state
302 state = {'good': [], 'bad': [], 'skip': []}
302 state = {'good': [], 'bad': [], 'skip': []}
303 if os.path.exists(repo.join("bisect.state")):
303 if os.path.exists(repo.join("bisect.state")):
304 for l in repo.opener("bisect.state"):
304 for l in repo.opener("bisect.state"):
305 kind, node = l[:-1].split()
305 kind, node = l[:-1].split()
306 node = repo.lookup(node)
306 node = repo.lookup(node)
307 if kind not in state:
307 if kind not in state:
308 raise util.Abort(_("unknown bisect kind %s") % kind)
308 raise util.Abort(_("unknown bisect kind %s") % kind)
309 state[kind].append(node)
309 state[kind].append(node)
310
310
311 # update state
311 # update state
312 node = repo.lookup(rev or '.')
312 node = repo.lookup(rev or '.')
313 if good:
313 if good:
314 state['good'].append(node)
314 state['good'].append(node)
315 elif bad:
315 elif bad:
316 state['bad'].append(node)
316 state['bad'].append(node)
317 elif skip:
317 elif skip:
318 state['skip'].append(node)
318 state['skip'].append(node)
319
319
320 # save state
320 # save state
321 f = repo.opener("bisect.state", "w", atomictemp=True)
321 f = repo.opener("bisect.state", "w", atomictemp=True)
322 wlock = repo.wlock()
322 wlock = repo.wlock()
323 try:
323 try:
324 for kind in state:
324 for kind in state:
325 for node in state[kind]:
325 for node in state[kind]:
326 f.write("%s %s\n" % (kind, hex(node)))
326 f.write("%s %s\n" % (kind, hex(node)))
327 f.rename()
327 f.rename()
328 finally:
328 finally:
329 del wlock
329 del wlock
330
330
331 if not state['good'] or not state['bad']:
331 if not state['good'] or not state['bad']:
332 return
332 return
333
333
334 # actually bisect
334 # actually bisect
335 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
335 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
336 if changesets == 0:
336 if changesets == 0:
337 displayer = cmdutil.show_changeset(ui, repo, {})
337 displayer = cmdutil.show_changeset(ui, repo, {})
338 transition = (good and "good" or "bad")
338 transition = (good and "good" or "bad")
339 if len(nodes) == 1:
339 if len(nodes) == 1:
340 # narrowed it down to a single revision
340 # narrowed it down to a single revision
341 ui.write(_("The first %s revision is:\n") % transition)
341 ui.write(_("The first %s revision is:\n") % transition)
342 displayer.show(changenode=nodes[0])
342 displayer.show(changenode=nodes[0])
343 else:
343 else:
344 # multiple possible revisions
344 # multiple possible revisions
345 ui.write(_("Due to skipped revisions, the first "
345 ui.write(_("Due to skipped revisions, the first "
346 "%s revision could be any of:\n") % transition)
346 "%s revision could be any of:\n") % transition)
347 for n in nodes:
347 for n in nodes:
348 displayer.show(changenode=n)
348 displayer.show(changenode=n)
349 else:
349 else:
350 assert len(nodes) == 1 # only a single node can be tested next
350 assert len(nodes) == 1 # only a single node can be tested next
351 node = nodes[0]
351 node = nodes[0]
352 # compute the approximate number of remaining tests
352 # compute the approximate number of remaining tests
353 tests, size = 0, 2
353 tests, size = 0, 2
354 while size <= changesets:
354 while size <= changesets:
355 tests, size = tests + 1, size * 2
355 tests, size = tests + 1, size * 2
356 rev = repo.changelog.rev(node)
356 rev = repo.changelog.rev(node)
357 ui.write(_("Testing changeset %s:%s "
357 ui.write(_("Testing changeset %s:%s "
358 "(%s changesets remaining, ~%s tests)\n")
358 "(%s changesets remaining, ~%s tests)\n")
359 % (rev, short(node), changesets, tests))
359 % (rev, short(node), changesets, tests))
360 if not noupdate:
360 if not noupdate:
361 cmdutil.bail_if_changed(repo)
361 cmdutil.bail_if_changed(repo)
362 return hg.clean(repo, node)
362 return hg.clean(repo, node)
363
363
364 def branch(ui, repo, label=None, **opts):
364 def branch(ui, repo, label=None, **opts):
365 """set or show the current branch name
365 """set or show the current branch name
366
366
367 With no argument, show the current branch name. With one argument,
367 With no argument, show the current branch name. With one argument,
368 set the working directory branch name (the branch does not exist in
368 set the working directory branch name (the branch does not exist in
369 the repository until the next commit).
369 the repository until the next commit).
370
370
371 Unless --force is specified, branch will not let you set a
371 Unless --force is specified, branch will not let you set a
372 branch name that shadows an existing branch.
372 branch name that shadows an existing branch.
373
373
374 Use the command 'hg update' to switch to an existing branch.
374 Use the command 'hg update' to switch to an existing branch.
375 """
375 """
376
376
377 if label:
377 if label:
378 if not opts.get('force') and label in repo.branchtags():
378 if not opts.get('force') and label in repo.branchtags():
379 if label not in [p.branch() for p in repo.parents()]:
379 if label not in [p.branch() for p in repo.parents()]:
380 raise util.Abort(_('a branch of the same name already exists'
380 raise util.Abort(_('a branch of the same name already exists'
381 ' (use --force to override)'))
381 ' (use --force to override)'))
382 repo.dirstate.setbranch(util.fromlocal(label))
382 repo.dirstate.setbranch(util.fromlocal(label))
383 ui.status(_('marked working directory as branch %s\n') % label)
383 ui.status(_('marked working directory as branch %s\n') % label)
384 else:
384 else:
385 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
385 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
386
386
387 def branches(ui, repo, active=False):
387 def branches(ui, repo, active=False):
388 """list repository named branches
388 """list repository named branches
389
389
390 List the repository's named branches, indicating which ones are
390 List the repository's named branches, indicating which ones are
391 inactive. If active is specified, only show active branches.
391 inactive. If active is specified, only show active branches.
392
392
393 A branch is considered active if it contains repository heads.
393 A branch is considered active if it contains repository heads.
394
394
395 Use the command 'hg update' to switch to an existing branch.
395 Use the command 'hg update' to switch to an existing branch.
396 """
396 """
397 hexfunc = ui.debugflag and hex or short
397 hexfunc = ui.debugflag and hex or short
398 activebranches = [util.tolocal(repo[n].branch())
398 activebranches = [util.tolocal(repo[n].branch())
399 for n in repo.heads()]
399 for n in repo.heads()]
400 branches = util.sort([(tag in activebranches, repo.changelog.rev(node), tag)
400 branches = util.sort([(tag in activebranches, repo.changelog.rev(node), tag)
401 for tag, node in repo.branchtags().items()])
401 for tag, node in repo.branchtags().items()])
402 branches.reverse()
402 branches.reverse()
403
403
404 for isactive, node, tag in branches:
404 for isactive, node, tag in branches:
405 if (not active) or isactive:
405 if (not active) or isactive:
406 if ui.quiet:
406 if ui.quiet:
407 ui.write("%s\n" % tag)
407 ui.write("%s\n" % tag)
408 else:
408 else:
409 rev = str(node).rjust(31 - util.locallen(tag))
409 rev = str(node).rjust(31 - util.locallen(tag))
410 isinactive = ((not isactive) and " (inactive)") or ''
410 isinactive = ((not isactive) and " (inactive)") or ''
411 data = tag, rev, hexfunc(repo.lookup(node)), isinactive
411 data = tag, rev, hexfunc(repo.lookup(node)), isinactive
412 ui.write("%s %s:%s%s\n" % data)
412 ui.write("%s %s:%s%s\n" % data)
413
413
414 def bundle(ui, repo, fname, dest=None, **opts):
414 def bundle(ui, repo, fname, dest=None, **opts):
415 """create a changegroup file
415 """create a changegroup file
416
416
417 Generate a compressed changegroup file collecting changesets not
417 Generate a compressed changegroup file collecting changesets not
418 found in the other repository.
418 found in the other repository.
419
419
420 If no destination repository is specified the destination is
420 If no destination repository is specified the destination is
421 assumed to have all the nodes specified by one or more --base
421 assumed to have all the nodes specified by one or more --base
422 parameters. To create a bundle containing all changesets, use
422 parameters. To create a bundle containing all changesets, use
423 --all (or --base null). To change the compression method applied,
423 --all (or --base null). To change the compression method applied,
424 use the -t option (by default, bundles are compressed using bz2).
424 use the -t option (by default, bundles are compressed using bz2).
425
425
426 The bundle file can then be transferred using conventional means and
426 The bundle file can then be transferred using conventional means and
427 applied to another repository with the unbundle or pull command.
427 applied to another repository with the unbundle or pull command.
428 This is useful when direct push and pull are not available or when
428 This is useful when direct push and pull are not available or when
429 exporting an entire repository is undesirable.
429 exporting an entire repository is undesirable.
430
430
431 Applying bundles preserves all changeset contents including
431 Applying bundles preserves all changeset contents including
432 permissions, copy/rename information, and revision history.
432 permissions, copy/rename information, and revision history.
433 """
433 """
434 revs = opts.get('rev') or None
434 revs = opts.get('rev') or None
435 if revs:
435 if revs:
436 revs = [repo.lookup(rev) for rev in revs]
436 revs = [repo.lookup(rev) for rev in revs]
437 if opts.get('all'):
437 if opts.get('all'):
438 base = ['null']
438 base = ['null']
439 else:
439 else:
440 base = opts.get('base')
440 base = opts.get('base')
441 if base:
441 if base:
442 if dest:
442 if dest:
443 raise util.Abort(_("--base is incompatible with specifiying "
443 raise util.Abort(_("--base is incompatible with specifiying "
444 "a destination"))
444 "a destination"))
445 base = [repo.lookup(rev) for rev in base]
445 base = [repo.lookup(rev) for rev in base]
446 # create the right base
446 # create the right base
447 # XXX: nodesbetween / changegroup* should be "fixed" instead
447 # XXX: nodesbetween / changegroup* should be "fixed" instead
448 o = []
448 o = []
449 has = {nullid: None}
449 has = {nullid: None}
450 for n in base:
450 for n in base:
451 has.update(repo.changelog.reachable(n))
451 has.update(repo.changelog.reachable(n))
452 if revs:
452 if revs:
453 visit = list(revs)
453 visit = list(revs)
454 else:
454 else:
455 visit = repo.changelog.heads()
455 visit = repo.changelog.heads()
456 seen = {}
456 seen = {}
457 while visit:
457 while visit:
458 n = visit.pop(0)
458 n = visit.pop(0)
459 parents = [p for p in repo.changelog.parents(n) if p not in has]
459 parents = [p for p in repo.changelog.parents(n) if p not in has]
460 if len(parents) == 0:
460 if len(parents) == 0:
461 o.insert(0, n)
461 o.insert(0, n)
462 else:
462 else:
463 for p in parents:
463 for p in parents:
464 if p not in seen:
464 if p not in seen:
465 seen[p] = 1
465 seen[p] = 1
466 visit.append(p)
466 visit.append(p)
467 else:
467 else:
468 cmdutil.setremoteconfig(ui, opts)
468 cmdutil.setremoteconfig(ui, opts)
469 dest, revs, checkout = hg.parseurl(
469 dest, revs, checkout = hg.parseurl(
470 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
470 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
471 other = hg.repository(ui, dest)
471 other = hg.repository(ui, dest)
472 o = repo.findoutgoing(other, force=opts['force'])
472 o = repo.findoutgoing(other, force=opts['force'])
473
473
474 if revs:
474 if revs:
475 cg = repo.changegroupsubset(o, revs, 'bundle')
475 cg = repo.changegroupsubset(o, revs, 'bundle')
476 else:
476 else:
477 cg = repo.changegroup(o, 'bundle')
477 cg = repo.changegroup(o, 'bundle')
478
478
479 bundletype = opts.get('type', 'bzip2').lower()
479 bundletype = opts.get('type', 'bzip2').lower()
480 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
480 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
481 bundletype = btypes.get(bundletype)
481 bundletype = btypes.get(bundletype)
482 if bundletype not in changegroup.bundletypes:
482 if bundletype not in changegroup.bundletypes:
483 raise util.Abort(_('unknown bundle type specified with --type'))
483 raise util.Abort(_('unknown bundle type specified with --type'))
484
484
485 changegroup.writebundle(cg, fname, bundletype)
485 changegroup.writebundle(cg, fname, bundletype)
486
486
487 def cat(ui, repo, file1, *pats, **opts):
487 def cat(ui, repo, file1, *pats, **opts):
488 """output the current or given revision of files
488 """output the current or given revision of files
489
489
490 Print the specified files as they were at the given revision.
490 Print the specified files as they were at the given revision.
491 If no revision is given, the parent of the working directory is used,
491 If no revision is given, the parent of the working directory is used,
492 or tip if no revision is checked out.
492 or tip if no revision is checked out.
493
493
494 Output may be to a file, in which case the name of the file is
494 Output may be to a file, in which case the name of the file is
495 given using a format string. The formatting rules are the same as
495 given using a format string. The formatting rules are the same as
496 for the export command, with the following additions:
496 for the export command, with the following additions:
497
497
498 %s basename of file being printed
498 %s basename of file being printed
499 %d dirname of file being printed, or '.' if in repo root
499 %d dirname of file being printed, or '.' if in repo root
500 %p root-relative path name of file being printed
500 %p root-relative path name of file being printed
501 """
501 """
502 ctx = repo[opts['rev']]
502 ctx = repo[opts['rev']]
503 err = 1
503 err = 1
504 m = cmdutil.match(repo, (file1,) + pats, opts)
504 m = cmdutil.match(repo, (file1,) + pats, opts)
505 for abs in ctx.walk(m):
505 for abs in ctx.walk(m):
506 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
506 fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
507 data = ctx[abs].data()
507 data = ctx[abs].data()
508 if opts.get('decode'):
508 if opts.get('decode'):
509 data = repo.wwritedata(abs, data)
509 data = repo.wwritedata(abs, data)
510 fp.write(data)
510 fp.write(data)
511 err = 0
511 err = 0
512 return err
512 return err
513
513
514 def clone(ui, source, dest=None, **opts):
514 def clone(ui, source, dest=None, **opts):
515 """make a copy of an existing repository
515 """make a copy of an existing repository
516
516
517 Create a copy of an existing repository in a new directory.
517 Create a copy of an existing repository in a new directory.
518
518
519 If no destination directory name is specified, it defaults to the
519 If no destination directory name is specified, it defaults to the
520 basename of the source.
520 basename of the source.
521
521
522 The location of the source is added to the new repository's
522 The location of the source is added to the new repository's
523 .hg/hgrc file, as the default to be used for future pulls.
523 .hg/hgrc file, as the default to be used for future pulls.
524
524
525 For efficiency, hardlinks are used for cloning whenever the source
525 For efficiency, hardlinks are used for cloning whenever the source
526 and destination are on the same filesystem (note this applies only
526 and destination are on the same filesystem (note this applies only
527 to the repository data, not to the checked out files). Some
527 to the repository data, not to the checked out files). Some
528 filesystems, such as AFS, implement hardlinking incorrectly, but
528 filesystems, such as AFS, implement hardlinking incorrectly, but
529 do not report errors. In these cases, use the --pull option to
529 do not report errors. In these cases, use the --pull option to
530 avoid hardlinking.
530 avoid hardlinking.
531
531
532 In some cases, you can clone repositories and checked out files
532 In some cases, you can clone repositories and checked out files
533 using full hardlinks with
533 using full hardlinks with
534
534
535 $ cp -al REPO REPOCLONE
535 $ cp -al REPO REPOCLONE
536
536
537 This is the fastest way to clone, but it is not always safe. The
537 This is the fastest way to clone, but it is not always safe. The
538 operation is not atomic (making sure REPO is not modified during
538 operation is not atomic (making sure REPO is not modified during
539 the operation is up to you) and you have to make sure your editor
539 the operation is up to you) and you have to make sure your editor
540 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
540 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
541 this is not compatible with certain extensions that place their
541 this is not compatible with certain extensions that place their
542 metadata under the .hg directory, such as mq.
542 metadata under the .hg directory, such as mq.
543
543
544 If you use the -r option to clone up to a specific revision, no
544 If you use the -r option to clone up to a specific revision, no
545 subsequent revisions will be present in the cloned repository.
545 subsequent revisions will be present in the cloned repository.
546 This option implies --pull, even on local repositories.
546 This option implies --pull, even on local repositories.
547
547
548 If the -U option is used, the new clone will contain only a repository
548 If the -U option is used, the new clone will contain only a repository
549 (.hg) and no working copy (the working copy parent is the null revision).
549 (.hg) and no working copy (the working copy parent is the null revision).
550
550
551 See pull for valid source format details.
551 See pull for valid source format details.
552
552
553 It is possible to specify an ssh:// URL as the destination, but no
553 It is possible to specify an ssh:// URL as the destination, but no
554 .hg/hgrc and working directory will be created on the remote side.
554 .hg/hgrc and working directory will be created on the remote side.
555 Look at the help text for the pull command for important details
555 Look at the help text for the pull command for important details
556 about ssh:// URLs.
556 about ssh:// URLs.
557 """
557 """
558 cmdutil.setremoteconfig(ui, opts)
558 cmdutil.setremoteconfig(ui, opts)
559 hg.clone(ui, source, dest,
559 hg.clone(ui, source, dest,
560 pull=opts['pull'],
560 pull=opts['pull'],
561 stream=opts['uncompressed'],
561 stream=opts['uncompressed'],
562 rev=opts['rev'],
562 rev=opts['rev'],
563 update=not opts['noupdate'])
563 update=not opts['noupdate'])
564
564
565 def commit(ui, repo, *pats, **opts):
565 def commit(ui, repo, *pats, **opts):
566 """commit the specified files or all outstanding changes
566 """commit the specified files or all outstanding changes
567
567
568 Commit changes to the given files into the repository.
568 Commit changes to the given files into the repository.
569
569
570 If a list of files is omitted, all changes reported by "hg status"
570 If a list of files is omitted, all changes reported by "hg status"
571 will be committed.
571 will be committed.
572
572
573 If you are committing the result of a merge, do not provide any
573 If you are committing the result of a merge, do not provide any
574 file names or -I/-X filters.
574 file names or -I/-X filters.
575
575
576 If no commit message is specified, the configured editor is started to
576 If no commit message is specified, the configured editor is started to
577 enter a message.
577 enter a message.
578
578
579 See 'hg help dates' for a list of formats valid for -d/--date.
579 See 'hg help dates' for a list of formats valid for -d/--date.
580 """
580 """
581 def commitfunc(ui, repo, message, match, opts):
581 def commitfunc(ui, repo, message, match, opts):
582 return repo.commit(match.files(), message, opts['user'], opts['date'],
582 return repo.commit(match.files(), message, opts['user'], opts['date'],
583 match, force_editor=opts.get('force_editor'))
583 match, force_editor=opts.get('force_editor'))
584
584
585 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
585 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
586 if not node:
586 if not node:
587 return
587 return
588 cl = repo.changelog
588 cl = repo.changelog
589 rev = cl.rev(node)
589 rev = cl.rev(node)
590 ui.note(_('committed changeset %s\n') % short(node))
590 parents = cl.parentrevs(rev)
591 parents = cl.parentrevs(rev)
591 if rev - 1 in parents:
592 if rev - 1 in parents:
592 # one of the parents was the old tip
593 # one of the parents was the old tip
593 return
594 return
594 if (parents == (nullrev, nullrev) or
595 if (parents == (nullrev, nullrev) or
595 len(cl.heads(cl.node(parents[0]))) > 1 and
596 len(cl.heads(cl.node(parents[0]))) > 1 and
596 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
597 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
597 ui.status(_('created new head\n'))
598 ui.status(_('created new head\n'))
598
599
599 def copy(ui, repo, *pats, **opts):
600 def copy(ui, repo, *pats, **opts):
600 """mark files as copied for the next commit
601 """mark files as copied for the next commit
601
602
602 Mark dest as having copies of source files. If dest is a
603 Mark dest as having copies of source files. If dest is a
603 directory, copies are put in that directory. If dest is a file,
604 directory, copies are put in that directory. If dest is a file,
604 there can only be one source.
605 there can only be one source.
605
606
606 By default, this command copies the contents of files as they
607 By default, this command copies the contents of files as they
607 stand in the working directory. If invoked with --after, the
608 stand in the working directory. If invoked with --after, the
608 operation is recorded, but no copying is performed.
609 operation is recorded, but no copying is performed.
609
610
610 This command takes effect in the next commit. To undo a copy
611 This command takes effect in the next commit. To undo a copy
611 before that, see hg revert.
612 before that, see hg revert.
612 """
613 """
613 wlock = repo.wlock(False)
614 wlock = repo.wlock(False)
614 try:
615 try:
615 return cmdutil.copy(ui, repo, pats, opts)
616 return cmdutil.copy(ui, repo, pats, opts)
616 finally:
617 finally:
617 del wlock
618 del wlock
618
619
619 def debugancestor(ui, repo, *args):
620 def debugancestor(ui, repo, *args):
620 """find the ancestor revision of two revisions in a given index"""
621 """find the ancestor revision of two revisions in a given index"""
621 if len(args) == 3:
622 if len(args) == 3:
622 index, rev1, rev2 = args
623 index, rev1, rev2 = args
623 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
624 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
624 lookup = r.lookup
625 lookup = r.lookup
625 elif len(args) == 2:
626 elif len(args) == 2:
626 if not repo:
627 if not repo:
627 raise util.Abort(_("There is no Mercurial repository here "
628 raise util.Abort(_("There is no Mercurial repository here "
628 "(.hg not found)"))
629 "(.hg not found)"))
629 rev1, rev2 = args
630 rev1, rev2 = args
630 r = repo.changelog
631 r = repo.changelog
631 lookup = repo.lookup
632 lookup = repo.lookup
632 else:
633 else:
633 raise util.Abort(_('either two or three arguments required'))
634 raise util.Abort(_('either two or three arguments required'))
634 a = r.ancestor(lookup(rev1), lookup(rev2))
635 a = r.ancestor(lookup(rev1), lookup(rev2))
635 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
636 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
636
637
637 def debugcomplete(ui, cmd='', **opts):
638 def debugcomplete(ui, cmd='', **opts):
638 """returns the completion list associated with the given command"""
639 """returns the completion list associated with the given command"""
639
640
640 if opts['options']:
641 if opts['options']:
641 options = []
642 options = []
642 otables = [globalopts]
643 otables = [globalopts]
643 if cmd:
644 if cmd:
644 aliases, entry = cmdutil.findcmd(ui, cmd, table)
645 aliases, entry = cmdutil.findcmd(ui, cmd, table)
645 otables.append(entry[1])
646 otables.append(entry[1])
646 for t in otables:
647 for t in otables:
647 for o in t:
648 for o in t:
648 if o[0]:
649 if o[0]:
649 options.append('-%s' % o[0])
650 options.append('-%s' % o[0])
650 options.append('--%s' % o[1])
651 options.append('--%s' % o[1])
651 ui.write("%s\n" % "\n".join(options))
652 ui.write("%s\n" % "\n".join(options))
652 return
653 return
653
654
654 ui.write("%s\n" % "\n".join(util.sort(cmdutil.findpossible(ui, cmd, table))))
655 ui.write("%s\n" % "\n".join(util.sort(cmdutil.findpossible(ui, cmd, table))))
655
656
656 def debugfsinfo(ui, path = "."):
657 def debugfsinfo(ui, path = "."):
657 file('.debugfsinfo', 'w').write('')
658 file('.debugfsinfo', 'w').write('')
658 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
659 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
659 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
660 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
660 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
661 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
661 and 'yes' or 'no'))
662 and 'yes' or 'no'))
662 os.unlink('.debugfsinfo')
663 os.unlink('.debugfsinfo')
663
664
664 def debugrebuildstate(ui, repo, rev="tip"):
665 def debugrebuildstate(ui, repo, rev="tip"):
665 """rebuild the dirstate as it would look like for the given revision"""
666 """rebuild the dirstate as it would look like for the given revision"""
666 ctx = repo[rev]
667 ctx = repo[rev]
667 wlock = repo.wlock()
668 wlock = repo.wlock()
668 try:
669 try:
669 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
670 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
670 finally:
671 finally:
671 del wlock
672 del wlock
672
673
673 def debugcheckstate(ui, repo):
674 def debugcheckstate(ui, repo):
674 """validate the correctness of the current dirstate"""
675 """validate the correctness of the current dirstate"""
675 parent1, parent2 = repo.dirstate.parents()
676 parent1, parent2 = repo.dirstate.parents()
676 m1 = repo[parent1].manifest()
677 m1 = repo[parent1].manifest()
677 m2 = repo[parent2].manifest()
678 m2 = repo[parent2].manifest()
678 errors = 0
679 errors = 0
679 for f in repo.dirstate:
680 for f in repo.dirstate:
680 state = repo.dirstate[f]
681 state = repo.dirstate[f]
681 if state in "nr" and f not in m1:
682 if state in "nr" and f not in m1:
682 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
683 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
683 errors += 1
684 errors += 1
684 if state in "a" and f in m1:
685 if state in "a" and f in m1:
685 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
686 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
686 errors += 1
687 errors += 1
687 if state in "m" and f not in m1 and f not in m2:
688 if state in "m" and f not in m1 and f not in m2:
688 ui.warn(_("%s in state %s, but not in either manifest\n") %
689 ui.warn(_("%s in state %s, but not in either manifest\n") %
689 (f, state))
690 (f, state))
690 errors += 1
691 errors += 1
691 for f in m1:
692 for f in m1:
692 state = repo.dirstate[f]
693 state = repo.dirstate[f]
693 if state not in "nrm":
694 if state not in "nrm":
694 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
695 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
695 errors += 1
696 errors += 1
696 if errors:
697 if errors:
697 error = _(".hg/dirstate inconsistent with current parent's manifest")
698 error = _(".hg/dirstate inconsistent with current parent's manifest")
698 raise util.Abort(error)
699 raise util.Abort(error)
699
700
700 def showconfig(ui, repo, *values, **opts):
701 def showconfig(ui, repo, *values, **opts):
701 """show combined config settings from all hgrc files
702 """show combined config settings from all hgrc files
702
703
703 With no args, print names and values of all config items.
704 With no args, print names and values of all config items.
704
705
705 With one arg of the form section.name, print just the value of
706 With one arg of the form section.name, print just the value of
706 that config item.
707 that config item.
707
708
708 With multiple args, print names and values of all config items
709 With multiple args, print names and values of all config items
709 with matching section names."""
710 with matching section names."""
710
711
711 untrusted = bool(opts.get('untrusted'))
712 untrusted = bool(opts.get('untrusted'))
712 if values:
713 if values:
713 if len([v for v in values if '.' in v]) > 1:
714 if len([v for v in values if '.' in v]) > 1:
714 raise util.Abort(_('only one config item permitted'))
715 raise util.Abort(_('only one config item permitted'))
715 for section, name, value in ui.walkconfig(untrusted=untrusted):
716 for section, name, value in ui.walkconfig(untrusted=untrusted):
716 sectname = section + '.' + name
717 sectname = section + '.' + name
717 if values:
718 if values:
718 for v in values:
719 for v in values:
719 if v == section:
720 if v == section:
720 ui.write('%s=%s\n' % (sectname, value))
721 ui.write('%s=%s\n' % (sectname, value))
721 elif v == sectname:
722 elif v == sectname:
722 ui.write(value, '\n')
723 ui.write(value, '\n')
723 else:
724 else:
724 ui.write('%s=%s\n' % (sectname, value))
725 ui.write('%s=%s\n' % (sectname, value))
725
726
726 def debugsetparents(ui, repo, rev1, rev2=None):
727 def debugsetparents(ui, repo, rev1, rev2=None):
727 """manually set the parents of the current working directory
728 """manually set the parents of the current working directory
728
729
729 This is useful for writing repository conversion tools, but should
730 This is useful for writing repository conversion tools, but should
730 be used with care.
731 be used with care.
731 """
732 """
732
733
733 if not rev2:
734 if not rev2:
734 rev2 = hex(nullid)
735 rev2 = hex(nullid)
735
736
736 wlock = repo.wlock()
737 wlock = repo.wlock()
737 try:
738 try:
738 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
739 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
739 finally:
740 finally:
740 del wlock
741 del wlock
741
742
742 def debugstate(ui, repo, nodates=None):
743 def debugstate(ui, repo, nodates=None):
743 """show the contents of the current dirstate"""
744 """show the contents of the current dirstate"""
744 timestr = ""
745 timestr = ""
745 showdate = not nodates
746 showdate = not nodates
746 for file_, ent in util.sort(repo.dirstate._map.items()):
747 for file_, ent in util.sort(repo.dirstate._map.items()):
747 if showdate:
748 if showdate:
748 if ent[3] == -1:
749 if ent[3] == -1:
749 # Pad or slice to locale representation
750 # Pad or slice to locale representation
750 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(0)))
751 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(0)))
751 timestr = 'unset'
752 timestr = 'unset'
752 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
753 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
753 else:
754 else:
754 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(ent[3]))
755 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(ent[3]))
755 if ent[1] & 020000:
756 if ent[1] & 020000:
756 mode = 'lnk'
757 mode = 'lnk'
757 else:
758 else:
758 mode = '%3o' % (ent[1] & 0777)
759 mode = '%3o' % (ent[1] & 0777)
759 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
760 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
760 for f in repo.dirstate.copies():
761 for f in repo.dirstate.copies():
761 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
762 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
762
763
763 def debugdata(ui, file_, rev):
764 def debugdata(ui, file_, rev):
764 """dump the contents of a data file revision"""
765 """dump the contents of a data file revision"""
765 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
766 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
766 try:
767 try:
767 ui.write(r.revision(r.lookup(rev)))
768 ui.write(r.revision(r.lookup(rev)))
768 except KeyError:
769 except KeyError:
769 raise util.Abort(_('invalid revision identifier %s') % rev)
770 raise util.Abort(_('invalid revision identifier %s') % rev)
770
771
771 def debugdate(ui, date, range=None, **opts):
772 def debugdate(ui, date, range=None, **opts):
772 """parse and display a date"""
773 """parse and display a date"""
773 if opts["extended"]:
774 if opts["extended"]:
774 d = util.parsedate(date, util.extendeddateformats)
775 d = util.parsedate(date, util.extendeddateformats)
775 else:
776 else:
776 d = util.parsedate(date)
777 d = util.parsedate(date)
777 ui.write("internal: %s %s\n" % d)
778 ui.write("internal: %s %s\n" % d)
778 ui.write("standard: %s\n" % util.datestr(d))
779 ui.write("standard: %s\n" % util.datestr(d))
779 if range:
780 if range:
780 m = util.matchdate(range)
781 m = util.matchdate(range)
781 ui.write("match: %s\n" % m(d[0]))
782 ui.write("match: %s\n" % m(d[0]))
782
783
783 def debugindex(ui, file_):
784 def debugindex(ui, file_):
784 """dump the contents of an index file"""
785 """dump the contents of an index file"""
785 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
786 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
786 ui.write(" rev offset length base linkrev" +
787 ui.write(" rev offset length base linkrev" +
787 " nodeid p1 p2\n")
788 " nodeid p1 p2\n")
788 for i in r:
789 for i in r:
789 node = r.node(i)
790 node = r.node(i)
790 try:
791 try:
791 pp = r.parents(node)
792 pp = r.parents(node)
792 except:
793 except:
793 pp = [nullid, nullid]
794 pp = [nullid, nullid]
794 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
795 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
795 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
796 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
796 short(node), short(pp[0]), short(pp[1])))
797 short(node), short(pp[0]), short(pp[1])))
797
798
798 def debugindexdot(ui, file_):
799 def debugindexdot(ui, file_):
799 """dump an index DAG as a .dot file"""
800 """dump an index DAG as a .dot file"""
800 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
801 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
801 ui.write("digraph G {\n")
802 ui.write("digraph G {\n")
802 for i in r:
803 for i in r:
803 node = r.node(i)
804 node = r.node(i)
804 pp = r.parents(node)
805 pp = r.parents(node)
805 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
806 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
806 if pp[1] != nullid:
807 if pp[1] != nullid:
807 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
808 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
808 ui.write("}\n")
809 ui.write("}\n")
809
810
810 def debuginstall(ui):
811 def debuginstall(ui):
811 '''test Mercurial installation'''
812 '''test Mercurial installation'''
812
813
813 def writetemp(contents):
814 def writetemp(contents):
814 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
815 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
815 f = os.fdopen(fd, "wb")
816 f = os.fdopen(fd, "wb")
816 f.write(contents)
817 f.write(contents)
817 f.close()
818 f.close()
818 return name
819 return name
819
820
820 problems = 0
821 problems = 0
821
822
822 # encoding
823 # encoding
823 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
824 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
824 try:
825 try:
825 util.fromlocal("test")
826 util.fromlocal("test")
826 except util.Abort, inst:
827 except util.Abort, inst:
827 ui.write(" %s\n" % inst)
828 ui.write(" %s\n" % inst)
828 ui.write(_(" (check that your locale is properly set)\n"))
829 ui.write(_(" (check that your locale is properly set)\n"))
829 problems += 1
830 problems += 1
830
831
831 # compiled modules
832 # compiled modules
832 ui.status(_("Checking extensions...\n"))
833 ui.status(_("Checking extensions...\n"))
833 try:
834 try:
834 import bdiff, mpatch, base85
835 import bdiff, mpatch, base85
835 except Exception, inst:
836 except Exception, inst:
836 ui.write(" %s\n" % inst)
837 ui.write(" %s\n" % inst)
837 ui.write(_(" One or more extensions could not be found"))
838 ui.write(_(" One or more extensions could not be found"))
838 ui.write(_(" (check that you compiled the extensions)\n"))
839 ui.write(_(" (check that you compiled the extensions)\n"))
839 problems += 1
840 problems += 1
840
841
841 # templates
842 # templates
842 ui.status(_("Checking templates...\n"))
843 ui.status(_("Checking templates...\n"))
843 try:
844 try:
844 import templater
845 import templater
845 t = templater.templater(templater.templatepath("map-cmdline.default"))
846 t = templater.templater(templater.templatepath("map-cmdline.default"))
846 except Exception, inst:
847 except Exception, inst:
847 ui.write(" %s\n" % inst)
848 ui.write(" %s\n" % inst)
848 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
849 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
849 problems += 1
850 problems += 1
850
851
851 # patch
852 # patch
852 ui.status(_("Checking patch...\n"))
853 ui.status(_("Checking patch...\n"))
853 patchproblems = 0
854 patchproblems = 0
854 a = "1\n2\n3\n4\n"
855 a = "1\n2\n3\n4\n"
855 b = "1\n2\n3\ninsert\n4\n"
856 b = "1\n2\n3\ninsert\n4\n"
856 fa = writetemp(a)
857 fa = writetemp(a)
857 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
858 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
858 os.path.basename(fa))
859 os.path.basename(fa))
859 fd = writetemp(d)
860 fd = writetemp(d)
860
861
861 files = {}
862 files = {}
862 try:
863 try:
863 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
864 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
864 except util.Abort, e:
865 except util.Abort, e:
865 ui.write(_(" patch call failed:\n"))
866 ui.write(_(" patch call failed:\n"))
866 ui.write(" " + str(e) + "\n")
867 ui.write(" " + str(e) + "\n")
867 patchproblems += 1
868 patchproblems += 1
868 else:
869 else:
869 if list(files) != [os.path.basename(fa)]:
870 if list(files) != [os.path.basename(fa)]:
870 ui.write(_(" unexpected patch output!\n"))
871 ui.write(_(" unexpected patch output!\n"))
871 patchproblems += 1
872 patchproblems += 1
872 a = file(fa).read()
873 a = file(fa).read()
873 if a != b:
874 if a != b:
874 ui.write(_(" patch test failed!\n"))
875 ui.write(_(" patch test failed!\n"))
875 patchproblems += 1
876 patchproblems += 1
876
877
877 if patchproblems:
878 if patchproblems:
878 if ui.config('ui', 'patch'):
879 if ui.config('ui', 'patch'):
879 ui.write(_(" (Current patch tool may be incompatible with patch,"
880 ui.write(_(" (Current patch tool may be incompatible with patch,"
880 " or misconfigured. Please check your .hgrc file)\n"))
881 " or misconfigured. Please check your .hgrc file)\n"))
881 else:
882 else:
882 ui.write(_(" Internal patcher failure, please report this error"
883 ui.write(_(" Internal patcher failure, please report this error"
883 " to http://www.selenic.com/mercurial/bts\n"))
884 " to http://www.selenic.com/mercurial/bts\n"))
884 problems += patchproblems
885 problems += patchproblems
885
886
886 os.unlink(fa)
887 os.unlink(fa)
887 os.unlink(fd)
888 os.unlink(fd)
888
889
889 # editor
890 # editor
890 ui.status(_("Checking commit editor...\n"))
891 ui.status(_("Checking commit editor...\n"))
891 editor = ui.geteditor()
892 editor = ui.geteditor()
892 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
893 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
893 if not cmdpath:
894 if not cmdpath:
894 if editor == 'vi':
895 if editor == 'vi':
895 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
896 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
896 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
897 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
897 else:
898 else:
898 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
899 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
899 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
900 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
900 problems += 1
901 problems += 1
901
902
902 # check username
903 # check username
903 ui.status(_("Checking username...\n"))
904 ui.status(_("Checking username...\n"))
904 user = os.environ.get("HGUSER")
905 user = os.environ.get("HGUSER")
905 if user is None:
906 if user is None:
906 user = ui.config("ui", "username")
907 user = ui.config("ui", "username")
907 if user is None:
908 if user is None:
908 user = os.environ.get("EMAIL")
909 user = os.environ.get("EMAIL")
909 if not user:
910 if not user:
910 ui.warn(" ")
911 ui.warn(" ")
911 ui.username()
912 ui.username()
912 ui.write(_(" (specify a username in your .hgrc file)\n"))
913 ui.write(_(" (specify a username in your .hgrc file)\n"))
913
914
914 if not problems:
915 if not problems:
915 ui.status(_("No problems detected\n"))
916 ui.status(_("No problems detected\n"))
916 else:
917 else:
917 ui.write(_("%s problems detected,"
918 ui.write(_("%s problems detected,"
918 " please check your install!\n") % problems)
919 " please check your install!\n") % problems)
919
920
920 return problems
921 return problems
921
922
922 def debugrename(ui, repo, file1, *pats, **opts):
923 def debugrename(ui, repo, file1, *pats, **opts):
923 """dump rename information"""
924 """dump rename information"""
924
925
925 ctx = repo[opts.get('rev')]
926 ctx = repo[opts.get('rev')]
926 m = cmdutil.match(repo, (file1,) + pats, opts)
927 m = cmdutil.match(repo, (file1,) + pats, opts)
927 for abs in ctx.walk(m):
928 for abs in ctx.walk(m):
928 fctx = ctx[abs]
929 fctx = ctx[abs]
929 o = fctx.filelog().renamed(fctx.filenode())
930 o = fctx.filelog().renamed(fctx.filenode())
930 rel = m.rel(abs)
931 rel = m.rel(abs)
931 if o:
932 if o:
932 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
933 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
933 else:
934 else:
934 ui.write(_("%s not renamed\n") % rel)
935 ui.write(_("%s not renamed\n") % rel)
935
936
936 def debugwalk(ui, repo, *pats, **opts):
937 def debugwalk(ui, repo, *pats, **opts):
937 """show how files match on given patterns"""
938 """show how files match on given patterns"""
938 m = cmdutil.match(repo, pats, opts)
939 m = cmdutil.match(repo, pats, opts)
939 items = list(repo.walk(m))
940 items = list(repo.walk(m))
940 if not items:
941 if not items:
941 return
942 return
942 fmt = 'f %%-%ds %%-%ds %%s' % (
943 fmt = 'f %%-%ds %%-%ds %%s' % (
943 max([len(abs) for abs in items]),
944 max([len(abs) for abs in items]),
944 max([len(m.rel(abs)) for abs in items]))
945 max([len(m.rel(abs)) for abs in items]))
945 for abs in items:
946 for abs in items:
946 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
947 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
947 ui.write("%s\n" % line.rstrip())
948 ui.write("%s\n" % line.rstrip())
948
949
949 def diff(ui, repo, *pats, **opts):
950 def diff(ui, repo, *pats, **opts):
950 """diff repository (or selected files)
951 """diff repository (or selected files)
951
952
952 Show differences between revisions for the specified files.
953 Show differences between revisions for the specified files.
953
954
954 Differences between files are shown using the unified diff format.
955 Differences between files are shown using the unified diff format.
955
956
956 NOTE: diff may generate unexpected results for merges, as it will
957 NOTE: diff may generate unexpected results for merges, as it will
957 default to comparing against the working directory's first parent
958 default to comparing against the working directory's first parent
958 changeset if no revisions are specified.
959 changeset if no revisions are specified.
959
960
960 When two revision arguments are given, then changes are shown
961 When two revision arguments are given, then changes are shown
961 between those revisions. If only one revision is specified then
962 between those revisions. If only one revision is specified then
962 that revision is compared to the working directory, and, when no
963 that revision is compared to the working directory, and, when no
963 revisions are specified, the working directory files are compared
964 revisions are specified, the working directory files are compared
964 to its parent.
965 to its parent.
965
966
966 Without the -a option, diff will avoid generating diffs of files
967 Without the -a option, diff will avoid generating diffs of files
967 it detects as binary. With -a, diff will generate a diff anyway,
968 it detects as binary. With -a, diff will generate a diff anyway,
968 probably with undesirable results.
969 probably with undesirable results.
969 """
970 """
970 node1, node2 = cmdutil.revpair(repo, opts['rev'])
971 node1, node2 = cmdutil.revpair(repo, opts['rev'])
971
972
972 m = cmdutil.match(repo, pats, opts)
973 m = cmdutil.match(repo, pats, opts)
973 patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
974 patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
974
975
975 def export(ui, repo, *changesets, **opts):
976 def export(ui, repo, *changesets, **opts):
976 """dump the header and diffs for one or more changesets
977 """dump the header and diffs for one or more changesets
977
978
978 Print the changeset header and diffs for one or more revisions.
979 Print the changeset header and diffs for one or more revisions.
979
980
980 The information shown in the changeset header is: author,
981 The information shown in the changeset header is: author,
981 changeset hash, parent(s) and commit comment.
982 changeset hash, parent(s) and commit comment.
982
983
983 NOTE: export may generate unexpected diff output for merge changesets,
984 NOTE: export may generate unexpected diff output for merge changesets,
984 as it will compare the merge changeset against its first parent only.
985 as it will compare the merge changeset against its first parent only.
985
986
986 Output may be to a file, in which case the name of the file is
987 Output may be to a file, in which case the name of the file is
987 given using a format string. The formatting rules are as follows:
988 given using a format string. The formatting rules are as follows:
988
989
989 %% literal "%" character
990 %% literal "%" character
990 %H changeset hash (40 bytes of hexadecimal)
991 %H changeset hash (40 bytes of hexadecimal)
991 %N number of patches being generated
992 %N number of patches being generated
992 %R changeset revision number
993 %R changeset revision number
993 %b basename of the exporting repository
994 %b basename of the exporting repository
994 %h short-form changeset hash (12 bytes of hexadecimal)
995 %h short-form changeset hash (12 bytes of hexadecimal)
995 %n zero-padded sequence number, starting at 1
996 %n zero-padded sequence number, starting at 1
996 %r zero-padded changeset revision number
997 %r zero-padded changeset revision number
997
998
998 Without the -a option, export will avoid generating diffs of files
999 Without the -a option, export will avoid generating diffs of files
999 it detects as binary. With -a, export will generate a diff anyway,
1000 it detects as binary. With -a, export will generate a diff anyway,
1000 probably with undesirable results.
1001 probably with undesirable results.
1001
1002
1002 With the --switch-parent option, the diff will be against the second
1003 With the --switch-parent option, the diff will be against the second
1003 parent. It can be useful to review a merge.
1004 parent. It can be useful to review a merge.
1004 """
1005 """
1005 if not changesets:
1006 if not changesets:
1006 raise util.Abort(_("export requires at least one changeset"))
1007 raise util.Abort(_("export requires at least one changeset"))
1007 revs = cmdutil.revrange(repo, changesets)
1008 revs = cmdutil.revrange(repo, changesets)
1008 if len(revs) > 1:
1009 if len(revs) > 1:
1009 ui.note(_('exporting patches:\n'))
1010 ui.note(_('exporting patches:\n'))
1010 else:
1011 else:
1011 ui.note(_('exporting patch:\n'))
1012 ui.note(_('exporting patch:\n'))
1012 patch.export(repo, revs, template=opts['output'],
1013 patch.export(repo, revs, template=opts['output'],
1013 switch_parent=opts['switch_parent'],
1014 switch_parent=opts['switch_parent'],
1014 opts=patch.diffopts(ui, opts))
1015 opts=patch.diffopts(ui, opts))
1015
1016
1016 def grep(ui, repo, pattern, *pats, **opts):
1017 def grep(ui, repo, pattern, *pats, **opts):
1017 """search for a pattern in specified files and revisions
1018 """search for a pattern in specified files and revisions
1018
1019
1019 Search revisions of files for a regular expression.
1020 Search revisions of files for a regular expression.
1020
1021
1021 This command behaves differently than Unix grep. It only accepts
1022 This command behaves differently than Unix grep. It only accepts
1022 Python/Perl regexps. It searches repository history, not the
1023 Python/Perl regexps. It searches repository history, not the
1023 working directory. It always prints the revision number in which
1024 working directory. It always prints the revision number in which
1024 a match appears.
1025 a match appears.
1025
1026
1026 By default, grep only prints output for the first revision of a
1027 By default, grep only prints output for the first revision of a
1027 file in which it finds a match. To get it to print every revision
1028 file in which it finds a match. To get it to print every revision
1028 that contains a change in match status ("-" for a match that
1029 that contains a change in match status ("-" for a match that
1029 becomes a non-match, or "+" for a non-match that becomes a match),
1030 becomes a non-match, or "+" for a non-match that becomes a match),
1030 use the --all flag.
1031 use the --all flag.
1031 """
1032 """
1032 reflags = 0
1033 reflags = 0
1033 if opts['ignore_case']:
1034 if opts['ignore_case']:
1034 reflags |= re.I
1035 reflags |= re.I
1035 try:
1036 try:
1036 regexp = re.compile(pattern, reflags)
1037 regexp = re.compile(pattern, reflags)
1037 except Exception, inst:
1038 except Exception, inst:
1038 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1039 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1039 return None
1040 return None
1040 sep, eol = ':', '\n'
1041 sep, eol = ':', '\n'
1041 if opts['print0']:
1042 if opts['print0']:
1042 sep = eol = '\0'
1043 sep = eol = '\0'
1043
1044
1044 fcache = {}
1045 fcache = {}
1045 def getfile(fn):
1046 def getfile(fn):
1046 if fn not in fcache:
1047 if fn not in fcache:
1047 fcache[fn] = repo.file(fn)
1048 fcache[fn] = repo.file(fn)
1048 return fcache[fn]
1049 return fcache[fn]
1049
1050
1050 def matchlines(body):
1051 def matchlines(body):
1051 begin = 0
1052 begin = 0
1052 linenum = 0
1053 linenum = 0
1053 while True:
1054 while True:
1054 match = regexp.search(body, begin)
1055 match = regexp.search(body, begin)
1055 if not match:
1056 if not match:
1056 break
1057 break
1057 mstart, mend = match.span()
1058 mstart, mend = match.span()
1058 linenum += body.count('\n', begin, mstart) + 1
1059 linenum += body.count('\n', begin, mstart) + 1
1059 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1060 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1060 lend = body.find('\n', mend)
1061 lend = body.find('\n', mend)
1061 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1062 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1062 begin = lend + 1
1063 begin = lend + 1
1063
1064
1064 class linestate(object):
1065 class linestate(object):
1065 def __init__(self, line, linenum, colstart, colend):
1066 def __init__(self, line, linenum, colstart, colend):
1066 self.line = line
1067 self.line = line
1067 self.linenum = linenum
1068 self.linenum = linenum
1068 self.colstart = colstart
1069 self.colstart = colstart
1069 self.colend = colend
1070 self.colend = colend
1070
1071
1071 def __hash__(self):
1072 def __hash__(self):
1072 return hash((self.linenum, self.line))
1073 return hash((self.linenum, self.line))
1073
1074
1074 def __eq__(self, other):
1075 def __eq__(self, other):
1075 return self.line == other.line
1076 return self.line == other.line
1076
1077
1077 matches = {}
1078 matches = {}
1078 copies = {}
1079 copies = {}
1079 def grepbody(fn, rev, body):
1080 def grepbody(fn, rev, body):
1080 matches[rev].setdefault(fn, [])
1081 matches[rev].setdefault(fn, [])
1081 m = matches[rev][fn]
1082 m = matches[rev][fn]
1082 for lnum, cstart, cend, line in matchlines(body):
1083 for lnum, cstart, cend, line in matchlines(body):
1083 s = linestate(line, lnum, cstart, cend)
1084 s = linestate(line, lnum, cstart, cend)
1084 m.append(s)
1085 m.append(s)
1085
1086
1086 def difflinestates(a, b):
1087 def difflinestates(a, b):
1087 sm = difflib.SequenceMatcher(None, a, b)
1088 sm = difflib.SequenceMatcher(None, a, b)
1088 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1089 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1089 if tag == 'insert':
1090 if tag == 'insert':
1090 for i in xrange(blo, bhi):
1091 for i in xrange(blo, bhi):
1091 yield ('+', b[i])
1092 yield ('+', b[i])
1092 elif tag == 'delete':
1093 elif tag == 'delete':
1093 for i in xrange(alo, ahi):
1094 for i in xrange(alo, ahi):
1094 yield ('-', a[i])
1095 yield ('-', a[i])
1095 elif tag == 'replace':
1096 elif tag == 'replace':
1096 for i in xrange(alo, ahi):
1097 for i in xrange(alo, ahi):
1097 yield ('-', a[i])
1098 yield ('-', a[i])
1098 for i in xrange(blo, bhi):
1099 for i in xrange(blo, bhi):
1099 yield ('+', b[i])
1100 yield ('+', b[i])
1100
1101
1101 prev = {}
1102 prev = {}
1102 def display(fn, rev, states, prevstates):
1103 def display(fn, rev, states, prevstates):
1103 datefunc = ui.quiet and util.shortdate or util.datestr
1104 datefunc = ui.quiet and util.shortdate or util.datestr
1104 found = False
1105 found = False
1105 filerevmatches = {}
1106 filerevmatches = {}
1106 r = prev.get(fn, -1)
1107 r = prev.get(fn, -1)
1107 if opts['all']:
1108 if opts['all']:
1108 iter = difflinestates(states, prevstates)
1109 iter = difflinestates(states, prevstates)
1109 else:
1110 else:
1110 iter = [('', l) for l in prevstates]
1111 iter = [('', l) for l in prevstates]
1111 for change, l in iter:
1112 for change, l in iter:
1112 cols = [fn, str(r)]
1113 cols = [fn, str(r)]
1113 if opts['line_number']:
1114 if opts['line_number']:
1114 cols.append(str(l.linenum))
1115 cols.append(str(l.linenum))
1115 if opts['all']:
1116 if opts['all']:
1116 cols.append(change)
1117 cols.append(change)
1117 if opts['user']:
1118 if opts['user']:
1118 cols.append(ui.shortuser(get(r)[1]))
1119 cols.append(ui.shortuser(get(r)[1]))
1119 if opts.get('date'):
1120 if opts.get('date'):
1120 cols.append(datefunc(get(r)[2]))
1121 cols.append(datefunc(get(r)[2]))
1121 if opts['files_with_matches']:
1122 if opts['files_with_matches']:
1122 c = (fn, r)
1123 c = (fn, r)
1123 if c in filerevmatches:
1124 if c in filerevmatches:
1124 continue
1125 continue
1125 filerevmatches[c] = 1
1126 filerevmatches[c] = 1
1126 else:
1127 else:
1127 cols.append(l.line)
1128 cols.append(l.line)
1128 ui.write(sep.join(cols), eol)
1129 ui.write(sep.join(cols), eol)
1129 found = True
1130 found = True
1130 return found
1131 return found
1131
1132
1132 fstate = {}
1133 fstate = {}
1133 skip = {}
1134 skip = {}
1134 get = util.cachefunc(lambda r: repo[r].changeset())
1135 get = util.cachefunc(lambda r: repo[r].changeset())
1135 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1136 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1136 found = False
1137 found = False
1137 follow = opts.get('follow')
1138 follow = opts.get('follow')
1138 for st, rev, fns in changeiter:
1139 for st, rev, fns in changeiter:
1139 if st == 'window':
1140 if st == 'window':
1140 matches.clear()
1141 matches.clear()
1141 elif st == 'add':
1142 elif st == 'add':
1142 ctx = repo[rev]
1143 ctx = repo[rev]
1143 matches[rev] = {}
1144 matches[rev] = {}
1144 for fn in fns:
1145 for fn in fns:
1145 if fn in skip:
1146 if fn in skip:
1146 continue
1147 continue
1147 try:
1148 try:
1148 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1149 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1149 fstate.setdefault(fn, [])
1150 fstate.setdefault(fn, [])
1150 if follow:
1151 if follow:
1151 copied = getfile(fn).renamed(ctx.filenode(fn))
1152 copied = getfile(fn).renamed(ctx.filenode(fn))
1152 if copied:
1153 if copied:
1153 copies.setdefault(rev, {})[fn] = copied[0]
1154 copies.setdefault(rev, {})[fn] = copied[0]
1154 except revlog.LookupError:
1155 except revlog.LookupError:
1155 pass
1156 pass
1156 elif st == 'iter':
1157 elif st == 'iter':
1157 for fn, m in util.sort(matches[rev].items()):
1158 for fn, m in util.sort(matches[rev].items()):
1158 copy = copies.get(rev, {}).get(fn)
1159 copy = copies.get(rev, {}).get(fn)
1159 if fn in skip:
1160 if fn in skip:
1160 if copy:
1161 if copy:
1161 skip[copy] = True
1162 skip[copy] = True
1162 continue
1163 continue
1163 if fn in prev or fstate[fn]:
1164 if fn in prev or fstate[fn]:
1164 r = display(fn, rev, m, fstate[fn])
1165 r = display(fn, rev, m, fstate[fn])
1165 found = found or r
1166 found = found or r
1166 if r and not opts['all']:
1167 if r and not opts['all']:
1167 skip[fn] = True
1168 skip[fn] = True
1168 if copy:
1169 if copy:
1169 skip[copy] = True
1170 skip[copy] = True
1170 fstate[fn] = m
1171 fstate[fn] = m
1171 if copy:
1172 if copy:
1172 fstate[copy] = m
1173 fstate[copy] = m
1173 prev[fn] = rev
1174 prev[fn] = rev
1174
1175
1175 for fn, state in util.sort(fstate.items()):
1176 for fn, state in util.sort(fstate.items()):
1176 if fn in skip:
1177 if fn in skip:
1177 continue
1178 continue
1178 if fn not in copies.get(prev[fn], {}):
1179 if fn not in copies.get(prev[fn], {}):
1179 found = display(fn, rev, {}, state) or found
1180 found = display(fn, rev, {}, state) or found
1180 return (not found and 1) or 0
1181 return (not found and 1) or 0
1181
1182
1182 def heads(ui, repo, *branchrevs, **opts):
1183 def heads(ui, repo, *branchrevs, **opts):
1183 """show current repository heads or show branch heads
1184 """show current repository heads or show branch heads
1184
1185
1185 With no arguments, show all repository head changesets.
1186 With no arguments, show all repository head changesets.
1186
1187
1187 If branch or revisions names are given this will show the heads of
1188 If branch or revisions names are given this will show the heads of
1188 the specified branches or the branches those revisions are tagged
1189 the specified branches or the branches those revisions are tagged
1189 with.
1190 with.
1190
1191
1191 Repository "heads" are changesets that don't have child
1192 Repository "heads" are changesets that don't have child
1192 changesets. They are where development generally takes place and
1193 changesets. They are where development generally takes place and
1193 are the usual targets for update and merge operations.
1194 are the usual targets for update and merge operations.
1194
1195
1195 Branch heads are changesets that have a given branch tag, but have
1196 Branch heads are changesets that have a given branch tag, but have
1196 no child changesets with that tag. They are usually where
1197 no child changesets with that tag. They are usually where
1197 development on the given branch takes place.
1198 development on the given branch takes place.
1198 """
1199 """
1199 if opts['rev']:
1200 if opts['rev']:
1200 start = repo.lookup(opts['rev'])
1201 start = repo.lookup(opts['rev'])
1201 else:
1202 else:
1202 start = None
1203 start = None
1203 if not branchrevs:
1204 if not branchrevs:
1204 # Assume we're looking repo-wide heads if no revs were specified.
1205 # Assume we're looking repo-wide heads if no revs were specified.
1205 heads = repo.heads(start)
1206 heads = repo.heads(start)
1206 else:
1207 else:
1207 heads = []
1208 heads = []
1208 visitedset = util.set()
1209 visitedset = util.set()
1209 for branchrev in branchrevs:
1210 for branchrev in branchrevs:
1210 branch = repo[branchrev].branch()
1211 branch = repo[branchrev].branch()
1211 if branch in visitedset:
1212 if branch in visitedset:
1212 continue
1213 continue
1213 visitedset.add(branch)
1214 visitedset.add(branch)
1214 bheads = repo.branchheads(branch, start)
1215 bheads = repo.branchheads(branch, start)
1215 if not bheads:
1216 if not bheads:
1216 if branch != branchrev:
1217 if branch != branchrev:
1217 ui.warn(_("no changes on branch %s containing %s are "
1218 ui.warn(_("no changes on branch %s containing %s are "
1218 "reachable from %s\n")
1219 "reachable from %s\n")
1219 % (branch, branchrev, opts['rev']))
1220 % (branch, branchrev, opts['rev']))
1220 else:
1221 else:
1221 ui.warn(_("no changes on branch %s are reachable from %s\n")
1222 ui.warn(_("no changes on branch %s are reachable from %s\n")
1222 % (branch, opts['rev']))
1223 % (branch, opts['rev']))
1223 heads.extend(bheads)
1224 heads.extend(bheads)
1224 if not heads:
1225 if not heads:
1225 return 1
1226 return 1
1226 displayer = cmdutil.show_changeset(ui, repo, opts)
1227 displayer = cmdutil.show_changeset(ui, repo, opts)
1227 for n in heads:
1228 for n in heads:
1228 displayer.show(changenode=n)
1229 displayer.show(changenode=n)
1229
1230
1230 def help_(ui, name=None, with_version=False):
1231 def help_(ui, name=None, with_version=False):
1231 """show help for a command, extension, or list of commands
1232 """show help for a command, extension, or list of commands
1232
1233
1233 With no arguments, print a list of commands and short help.
1234 With no arguments, print a list of commands and short help.
1234
1235
1235 Given a command name, print help for that command.
1236 Given a command name, print help for that command.
1236
1237
1237 Given an extension name, print help for that extension, and the
1238 Given an extension name, print help for that extension, and the
1238 commands it provides."""
1239 commands it provides."""
1239 option_lists = []
1240 option_lists = []
1240
1241
1241 def addglobalopts(aliases):
1242 def addglobalopts(aliases):
1242 if ui.verbose:
1243 if ui.verbose:
1243 option_lists.append((_("global options:"), globalopts))
1244 option_lists.append((_("global options:"), globalopts))
1244 if name == 'shortlist':
1245 if name == 'shortlist':
1245 option_lists.append((_('use "hg help" for the full list '
1246 option_lists.append((_('use "hg help" for the full list '
1246 'of commands'), ()))
1247 'of commands'), ()))
1247 else:
1248 else:
1248 if name == 'shortlist':
1249 if name == 'shortlist':
1249 msg = _('use "hg help" for the full list of commands '
1250 msg = _('use "hg help" for the full list of commands '
1250 'or "hg -v" for details')
1251 'or "hg -v" for details')
1251 elif aliases:
1252 elif aliases:
1252 msg = _('use "hg -v help%s" to show aliases and '
1253 msg = _('use "hg -v help%s" to show aliases and '
1253 'global options') % (name and " " + name or "")
1254 'global options') % (name and " " + name or "")
1254 else:
1255 else:
1255 msg = _('use "hg -v help %s" to show global options') % name
1256 msg = _('use "hg -v help %s" to show global options') % name
1256 option_lists.append((msg, ()))
1257 option_lists.append((msg, ()))
1257
1258
1258 def helpcmd(name):
1259 def helpcmd(name):
1259 if with_version:
1260 if with_version:
1260 version_(ui)
1261 version_(ui)
1261 ui.write('\n')
1262 ui.write('\n')
1262
1263
1263 try:
1264 try:
1264 aliases, i = cmdutil.findcmd(ui, name, table)
1265 aliases, i = cmdutil.findcmd(ui, name, table)
1265 except cmdutil.AmbiguousCommand, inst:
1266 except cmdutil.AmbiguousCommand, inst:
1266 select = lambda c: c.lstrip('^').startswith(inst.args[0])
1267 select = lambda c: c.lstrip('^').startswith(inst.args[0])
1267 helplist(_('list of commands:\n\n'), select)
1268 helplist(_('list of commands:\n\n'), select)
1268 return
1269 return
1269
1270
1270 # synopsis
1271 # synopsis
1271 ui.write("%s\n" % i[2])
1272 ui.write("%s\n" % i[2])
1272
1273
1273 # aliases
1274 # aliases
1274 if not ui.quiet and len(aliases) > 1:
1275 if not ui.quiet and len(aliases) > 1:
1275 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1276 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1276
1277
1277 # description
1278 # description
1278 doc = i[0].__doc__
1279 doc = i[0].__doc__
1279 if not doc:
1280 if not doc:
1280 doc = _("(No help text available)")
1281 doc = _("(No help text available)")
1281 if ui.quiet:
1282 if ui.quiet:
1282 doc = doc.splitlines(0)[0]
1283 doc = doc.splitlines(0)[0]
1283 ui.write("\n%s\n" % doc.rstrip())
1284 ui.write("\n%s\n" % doc.rstrip())
1284
1285
1285 if not ui.quiet:
1286 if not ui.quiet:
1286 # options
1287 # options
1287 if i[1]:
1288 if i[1]:
1288 option_lists.append((_("options:\n"), i[1]))
1289 option_lists.append((_("options:\n"), i[1]))
1289
1290
1290 addglobalopts(False)
1291 addglobalopts(False)
1291
1292
1292 def helplist(header, select=None):
1293 def helplist(header, select=None):
1293 h = {}
1294 h = {}
1294 cmds = {}
1295 cmds = {}
1295 for c, e in table.items():
1296 for c, e in table.items():
1296 f = c.split("|", 1)[0]
1297 f = c.split("|", 1)[0]
1297 if select and not select(f):
1298 if select and not select(f):
1298 continue
1299 continue
1299 if name == "shortlist" and not f.startswith("^"):
1300 if name == "shortlist" and not f.startswith("^"):
1300 continue
1301 continue
1301 f = f.lstrip("^")
1302 f = f.lstrip("^")
1302 if not ui.debugflag and f.startswith("debug"):
1303 if not ui.debugflag and f.startswith("debug"):
1303 continue
1304 continue
1304 doc = e[0].__doc__
1305 doc = e[0].__doc__
1305 if not doc:
1306 if not doc:
1306 doc = _("(No help text available)")
1307 doc = _("(No help text available)")
1307 h[f] = doc.splitlines(0)[0].rstrip()
1308 h[f] = doc.splitlines(0)[0].rstrip()
1308 cmds[f] = c.lstrip("^")
1309 cmds[f] = c.lstrip("^")
1309
1310
1310 if not h:
1311 if not h:
1311 ui.status(_('no commands defined\n'))
1312 ui.status(_('no commands defined\n'))
1312 return
1313 return
1313
1314
1314 ui.status(header)
1315 ui.status(header)
1315 fns = util.sort(h)
1316 fns = util.sort(h)
1316 m = max(map(len, fns))
1317 m = max(map(len, fns))
1317 for f in fns:
1318 for f in fns:
1318 if ui.verbose:
1319 if ui.verbose:
1319 commands = cmds[f].replace("|",", ")
1320 commands = cmds[f].replace("|",", ")
1320 ui.write(" %s:\n %s\n"%(commands, h[f]))
1321 ui.write(" %s:\n %s\n"%(commands, h[f]))
1321 else:
1322 else:
1322 ui.write(' %-*s %s\n' % (m, f, h[f]))
1323 ui.write(' %-*s %s\n' % (m, f, h[f]))
1323
1324
1324 if not ui.quiet:
1325 if not ui.quiet:
1325 addglobalopts(True)
1326 addglobalopts(True)
1326
1327
1327 def helptopic(name):
1328 def helptopic(name):
1328 v = None
1329 v = None
1329 for i, d in help.helptable:
1330 for i, d in help.helptable:
1330 l = i.split('|')
1331 l = i.split('|')
1331 if name in l:
1332 if name in l:
1332 v = i
1333 v = i
1333 header = l[-1]
1334 header = l[-1]
1334 doc = d
1335 doc = d
1335 if not v:
1336 if not v:
1336 raise cmdutil.UnknownCommand(name)
1337 raise cmdutil.UnknownCommand(name)
1337
1338
1338 # description
1339 # description
1339 if not doc:
1340 if not doc:
1340 doc = _("(No help text available)")
1341 doc = _("(No help text available)")
1341 if callable(doc):
1342 if callable(doc):
1342 doc = doc()
1343 doc = doc()
1343
1344
1344 ui.write("%s\n" % header)
1345 ui.write("%s\n" % header)
1345 ui.write("%s\n" % doc.rstrip())
1346 ui.write("%s\n" % doc.rstrip())
1346
1347
1347 def helpext(name):
1348 def helpext(name):
1348 try:
1349 try:
1349 mod = extensions.find(name)
1350 mod = extensions.find(name)
1350 except KeyError:
1351 except KeyError:
1351 raise cmdutil.UnknownCommand(name)
1352 raise cmdutil.UnknownCommand(name)
1352
1353
1353 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1354 doc = (mod.__doc__ or _('No help text available')).splitlines(0)
1354 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1355 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1355 for d in doc[1:]:
1356 for d in doc[1:]:
1356 ui.write(d, '\n')
1357 ui.write(d, '\n')
1357
1358
1358 ui.status('\n')
1359 ui.status('\n')
1359
1360
1360 try:
1361 try:
1361 ct = mod.cmdtable
1362 ct = mod.cmdtable
1362 except AttributeError:
1363 except AttributeError:
1363 ct = {}
1364 ct = {}
1364
1365
1365 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1366 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1366 helplist(_('list of commands:\n\n'), modcmds.has_key)
1367 helplist(_('list of commands:\n\n'), modcmds.has_key)
1367
1368
1368 if name and name != 'shortlist':
1369 if name and name != 'shortlist':
1369 i = None
1370 i = None
1370 for f in (helpcmd, helptopic, helpext):
1371 for f in (helpcmd, helptopic, helpext):
1371 try:
1372 try:
1372 f(name)
1373 f(name)
1373 i = None
1374 i = None
1374 break
1375 break
1375 except cmdutil.UnknownCommand, inst:
1376 except cmdutil.UnknownCommand, inst:
1376 i = inst
1377 i = inst
1377 if i:
1378 if i:
1378 raise i
1379 raise i
1379
1380
1380 else:
1381 else:
1381 # program name
1382 # program name
1382 if ui.verbose or with_version:
1383 if ui.verbose or with_version:
1383 version_(ui)
1384 version_(ui)
1384 else:
1385 else:
1385 ui.status(_("Mercurial Distributed SCM\n"))
1386 ui.status(_("Mercurial Distributed SCM\n"))
1386 ui.status('\n')
1387 ui.status('\n')
1387
1388
1388 # list of commands
1389 # list of commands
1389 if name == "shortlist":
1390 if name == "shortlist":
1390 header = _('basic commands:\n\n')
1391 header = _('basic commands:\n\n')
1391 else:
1392 else:
1392 header = _('list of commands:\n\n')
1393 header = _('list of commands:\n\n')
1393
1394
1394 helplist(header)
1395 helplist(header)
1395
1396
1396 # list all option lists
1397 # list all option lists
1397 opt_output = []
1398 opt_output = []
1398 for title, options in option_lists:
1399 for title, options in option_lists:
1399 opt_output.append(("\n%s" % title, None))
1400 opt_output.append(("\n%s" % title, None))
1400 for shortopt, longopt, default, desc in options:
1401 for shortopt, longopt, default, desc in options:
1401 if "DEPRECATED" in desc and not ui.verbose: continue
1402 if "DEPRECATED" in desc and not ui.verbose: continue
1402 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1403 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1403 longopt and " --%s" % longopt),
1404 longopt and " --%s" % longopt),
1404 "%s%s" % (desc,
1405 "%s%s" % (desc,
1405 default
1406 default
1406 and _(" (default: %s)") % default
1407 and _(" (default: %s)") % default
1407 or "")))
1408 or "")))
1408
1409
1409 if ui.verbose:
1410 if ui.verbose:
1410 ui.write(_("\nspecial help topics:\n"))
1411 ui.write(_("\nspecial help topics:\n"))
1411 topics = []
1412 topics = []
1412 for i, d in help.helptable:
1413 for i, d in help.helptable:
1413 l = i.split('|')
1414 l = i.split('|')
1414 topics.append((", ".join(l[:-1]), l[-1]))
1415 topics.append((", ".join(l[:-1]), l[-1]))
1415 topics_len = max([len(s[0]) for s in topics])
1416 topics_len = max([len(s[0]) for s in topics])
1416 for t, desc in topics:
1417 for t, desc in topics:
1417 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1418 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1418
1419
1419 if opt_output:
1420 if opt_output:
1420 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1421 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1421 for first, second in opt_output:
1422 for first, second in opt_output:
1422 if second:
1423 if second:
1423 ui.write(" %-*s %s\n" % (opts_len, first, second))
1424 ui.write(" %-*s %s\n" % (opts_len, first, second))
1424 else:
1425 else:
1425 ui.write("%s\n" % first)
1426 ui.write("%s\n" % first)
1426
1427
1427 def identify(ui, repo, source=None,
1428 def identify(ui, repo, source=None,
1428 rev=None, num=None, id=None, branch=None, tags=None):
1429 rev=None, num=None, id=None, branch=None, tags=None):
1429 """identify the working copy or specified revision
1430 """identify the working copy or specified revision
1430
1431
1431 With no revision, print a summary of the current state of the repo.
1432 With no revision, print a summary of the current state of the repo.
1432
1433
1433 With a path, do a lookup in another repository.
1434 With a path, do a lookup in another repository.
1434
1435
1435 This summary identifies the repository state using one or two parent
1436 This summary identifies the repository state using one or two parent
1436 hash identifiers, followed by a "+" if there are uncommitted changes
1437 hash identifiers, followed by a "+" if there are uncommitted changes
1437 in the working directory, a list of tags for this revision and a branch
1438 in the working directory, a list of tags for this revision and a branch
1438 name for non-default branches.
1439 name for non-default branches.
1439 """
1440 """
1440
1441
1441 if not repo and not source:
1442 if not repo and not source:
1442 raise util.Abort(_("There is no Mercurial repository here "
1443 raise util.Abort(_("There is no Mercurial repository here "
1443 "(.hg not found)"))
1444 "(.hg not found)"))
1444
1445
1445 hexfunc = ui.debugflag and hex or short
1446 hexfunc = ui.debugflag and hex or short
1446 default = not (num or id or branch or tags)
1447 default = not (num or id or branch or tags)
1447 output = []
1448 output = []
1448
1449
1449 if source:
1450 if source:
1450 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1451 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1451 srepo = hg.repository(ui, source)
1452 srepo = hg.repository(ui, source)
1452 if not rev and revs:
1453 if not rev and revs:
1453 rev = revs[0]
1454 rev = revs[0]
1454 if not rev:
1455 if not rev:
1455 rev = "tip"
1456 rev = "tip"
1456 if num or branch or tags:
1457 if num or branch or tags:
1457 raise util.Abort(
1458 raise util.Abort(
1458 "can't query remote revision number, branch, or tags")
1459 "can't query remote revision number, branch, or tags")
1459 output = [hexfunc(srepo.lookup(rev))]
1460 output = [hexfunc(srepo.lookup(rev))]
1460 elif not rev:
1461 elif not rev:
1461 ctx = repo[None]
1462 ctx = repo[None]
1462 parents = ctx.parents()
1463 parents = ctx.parents()
1463 changed = False
1464 changed = False
1464 if default or id or num:
1465 if default or id or num:
1465 changed = ctx.files() + ctx.deleted()
1466 changed = ctx.files() + ctx.deleted()
1466 if default or id:
1467 if default or id:
1467 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1468 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1468 (changed) and "+" or "")]
1469 (changed) and "+" or "")]
1469 if num:
1470 if num:
1470 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1471 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1471 (changed) and "+" or ""))
1472 (changed) and "+" or ""))
1472 else:
1473 else:
1473 ctx = repo[rev]
1474 ctx = repo[rev]
1474 if default or id:
1475 if default or id:
1475 output = [hexfunc(ctx.node())]
1476 output = [hexfunc(ctx.node())]
1476 if num:
1477 if num:
1477 output.append(str(ctx.rev()))
1478 output.append(str(ctx.rev()))
1478
1479
1479 if not source and default and not ui.quiet:
1480 if not source and default and not ui.quiet:
1480 b = util.tolocal(ctx.branch())
1481 b = util.tolocal(ctx.branch())
1481 if b != 'default':
1482 if b != 'default':
1482 output.append("(%s)" % b)
1483 output.append("(%s)" % b)
1483
1484
1484 # multiple tags for a single parent separated by '/'
1485 # multiple tags for a single parent separated by '/'
1485 t = "/".join(ctx.tags())
1486 t = "/".join(ctx.tags())
1486 if t:
1487 if t:
1487 output.append(t)
1488 output.append(t)
1488
1489
1489 if branch:
1490 if branch:
1490 output.append(util.tolocal(ctx.branch()))
1491 output.append(util.tolocal(ctx.branch()))
1491
1492
1492 if tags:
1493 if tags:
1493 output.extend(ctx.tags())
1494 output.extend(ctx.tags())
1494
1495
1495 ui.write("%s\n" % ' '.join(output))
1496 ui.write("%s\n" % ' '.join(output))
1496
1497
1497 def import_(ui, repo, patch1, *patches, **opts):
1498 def import_(ui, repo, patch1, *patches, **opts):
1498 """import an ordered set of patches
1499 """import an ordered set of patches
1499
1500
1500 Import a list of patches and commit them individually.
1501 Import a list of patches and commit them individually.
1501
1502
1502 If there are outstanding changes in the working directory, import
1503 If there are outstanding changes in the working directory, import
1503 will abort unless given the -f flag.
1504 will abort unless given the -f flag.
1504
1505
1505 You can import a patch straight from a mail message. Even patches
1506 You can import a patch straight from a mail message. Even patches
1506 as attachments work (body part must be type text/plain or
1507 as attachments work (body part must be type text/plain or
1507 text/x-patch to be used). From and Subject headers of email
1508 text/x-patch to be used). From and Subject headers of email
1508 message are used as default committer and commit message. All
1509 message are used as default committer and commit message. All
1509 text/plain body parts before first diff are added to commit
1510 text/plain body parts before first diff are added to commit
1510 message.
1511 message.
1511
1512
1512 If the imported patch was generated by hg export, user and description
1513 If the imported patch was generated by hg export, user and description
1513 from patch override values from message headers and body. Values
1514 from patch override values from message headers and body. Values
1514 given on command line with -m and -u override these.
1515 given on command line with -m and -u override these.
1515
1516
1516 If --exact is specified, import will set the working directory
1517 If --exact is specified, import will set the working directory
1517 to the parent of each patch before applying it, and will abort
1518 to the parent of each patch before applying it, and will abort
1518 if the resulting changeset has a different ID than the one
1519 if the resulting changeset has a different ID than the one
1519 recorded in the patch. This may happen due to character set
1520 recorded in the patch. This may happen due to character set
1520 problems or other deficiencies in the text patch format.
1521 problems or other deficiencies in the text patch format.
1521
1522
1522 To read a patch from standard input, use patch name "-".
1523 To read a patch from standard input, use patch name "-".
1523 See 'hg help dates' for a list of formats valid for -d/--date.
1524 See 'hg help dates' for a list of formats valid for -d/--date.
1524 """
1525 """
1525 patches = (patch1,) + patches
1526 patches = (patch1,) + patches
1526
1527
1527 date = opts.get('date')
1528 date = opts.get('date')
1528 if date:
1529 if date:
1529 opts['date'] = util.parsedate(date)
1530 opts['date'] = util.parsedate(date)
1530
1531
1531 if opts.get('exact') or not opts['force']:
1532 if opts.get('exact') or not opts['force']:
1532 cmdutil.bail_if_changed(repo)
1533 cmdutil.bail_if_changed(repo)
1533
1534
1534 d = opts["base"]
1535 d = opts["base"]
1535 strip = opts["strip"]
1536 strip = opts["strip"]
1536 wlock = lock = None
1537 wlock = lock = None
1537 try:
1538 try:
1538 wlock = repo.wlock()
1539 wlock = repo.wlock()
1539 lock = repo.lock()
1540 lock = repo.lock()
1540 for p in patches:
1541 for p in patches:
1541 pf = os.path.join(d, p)
1542 pf = os.path.join(d, p)
1542
1543
1543 if pf == '-':
1544 if pf == '-':
1544 ui.status(_("applying patch from stdin\n"))
1545 ui.status(_("applying patch from stdin\n"))
1545 data = patch.extract(ui, sys.stdin)
1546 data = patch.extract(ui, sys.stdin)
1546 else:
1547 else:
1547 ui.status(_("applying %s\n") % p)
1548 ui.status(_("applying %s\n") % p)
1548 if os.path.exists(pf):
1549 if os.path.exists(pf):
1549 data = patch.extract(ui, file(pf, 'rb'))
1550 data = patch.extract(ui, file(pf, 'rb'))
1550 else:
1551 else:
1551 data = patch.extract(ui, urllib.urlopen(pf))
1552 data = patch.extract(ui, urllib.urlopen(pf))
1552 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1553 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1553
1554
1554 if tmpname is None:
1555 if tmpname is None:
1555 raise util.Abort(_('no diffs found'))
1556 raise util.Abort(_('no diffs found'))
1556
1557
1557 try:
1558 try:
1558 cmdline_message = cmdutil.logmessage(opts)
1559 cmdline_message = cmdutil.logmessage(opts)
1559 if cmdline_message:
1560 if cmdline_message:
1560 # pickup the cmdline msg
1561 # pickup the cmdline msg
1561 message = cmdline_message
1562 message = cmdline_message
1562 elif message:
1563 elif message:
1563 # pickup the patch msg
1564 # pickup the patch msg
1564 message = message.strip()
1565 message = message.strip()
1565 else:
1566 else:
1566 # launch the editor
1567 # launch the editor
1567 message = None
1568 message = None
1568 ui.debug(_('message:\n%s\n') % message)
1569 ui.debug(_('message:\n%s\n') % message)
1569
1570
1570 wp = repo.parents()
1571 wp = repo.parents()
1571 if opts.get('exact'):
1572 if opts.get('exact'):
1572 if not nodeid or not p1:
1573 if not nodeid or not p1:
1573 raise util.Abort(_('not a mercurial patch'))
1574 raise util.Abort(_('not a mercurial patch'))
1574 p1 = repo.lookup(p1)
1575 p1 = repo.lookup(p1)
1575 p2 = repo.lookup(p2 or hex(nullid))
1576 p2 = repo.lookup(p2 or hex(nullid))
1576
1577
1577 if p1 != wp[0].node():
1578 if p1 != wp[0].node():
1578 hg.clean(repo, p1)
1579 hg.clean(repo, p1)
1579 repo.dirstate.setparents(p1, p2)
1580 repo.dirstate.setparents(p1, p2)
1580 elif p2:
1581 elif p2:
1581 try:
1582 try:
1582 p1 = repo.lookup(p1)
1583 p1 = repo.lookup(p1)
1583 p2 = repo.lookup(p2)
1584 p2 = repo.lookup(p2)
1584 if p1 == wp[0].node():
1585 if p1 == wp[0].node():
1585 repo.dirstate.setparents(p1, p2)
1586 repo.dirstate.setparents(p1, p2)
1586 except RepoError:
1587 except RepoError:
1587 pass
1588 pass
1588 if opts.get('exact') or opts.get('import_branch'):
1589 if opts.get('exact') or opts.get('import_branch'):
1589 repo.dirstate.setbranch(branch or 'default')
1590 repo.dirstate.setbranch(branch or 'default')
1590
1591
1591 files = {}
1592 files = {}
1592 try:
1593 try:
1593 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1594 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1594 files=files)
1595 files=files)
1595 finally:
1596 finally:
1596 files = patch.updatedir(ui, repo, files)
1597 files = patch.updatedir(ui, repo, files)
1597 if not opts.get('no_commit'):
1598 if not opts.get('no_commit'):
1598 n = repo.commit(files, message, opts.get('user') or user,
1599 n = repo.commit(files, message, opts.get('user') or user,
1599 opts.get('date') or date)
1600 opts.get('date') or date)
1600 if opts.get('exact'):
1601 if opts.get('exact'):
1601 if hex(n) != nodeid:
1602 if hex(n) != nodeid:
1602 repo.rollback()
1603 repo.rollback()
1603 raise util.Abort(_('patch is damaged'
1604 raise util.Abort(_('patch is damaged'
1604 ' or loses information'))
1605 ' or loses information'))
1605 # Force a dirstate write so that the next transaction
1606 # Force a dirstate write so that the next transaction
1606 # backups an up-do-date file.
1607 # backups an up-do-date file.
1607 repo.dirstate.write()
1608 repo.dirstate.write()
1608 finally:
1609 finally:
1609 os.unlink(tmpname)
1610 os.unlink(tmpname)
1610 finally:
1611 finally:
1611 del lock, wlock
1612 del lock, wlock
1612
1613
1613 def incoming(ui, repo, source="default", **opts):
1614 def incoming(ui, repo, source="default", **opts):
1614 """show new changesets found in source
1615 """show new changesets found in source
1615
1616
1616 Show new changesets found in the specified path/URL or the default
1617 Show new changesets found in the specified path/URL or the default
1617 pull location. These are the changesets that would be pulled if a pull
1618 pull location. These are the changesets that would be pulled if a pull
1618 was requested.
1619 was requested.
1619
1620
1620 For remote repository, using --bundle avoids downloading the changesets
1621 For remote repository, using --bundle avoids downloading the changesets
1621 twice if the incoming is followed by a pull.
1622 twice if the incoming is followed by a pull.
1622
1623
1623 See pull for valid source format details.
1624 See pull for valid source format details.
1624 """
1625 """
1625 limit = cmdutil.loglimit(opts)
1626 limit = cmdutil.loglimit(opts)
1626 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
1627 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
1627 cmdutil.setremoteconfig(ui, opts)
1628 cmdutil.setremoteconfig(ui, opts)
1628
1629
1629 other = hg.repository(ui, source)
1630 other = hg.repository(ui, source)
1630 ui.status(_('comparing with %s\n') % util.hidepassword(source))
1631 ui.status(_('comparing with %s\n') % util.hidepassword(source))
1631 if revs:
1632 if revs:
1632 revs = [other.lookup(rev) for rev in revs]
1633 revs = [other.lookup(rev) for rev in revs]
1633 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
1634 incoming = repo.findincoming(other, heads=revs, force=opts["force"])
1634 if not incoming:
1635 if not incoming:
1635 try:
1636 try:
1636 os.unlink(opts["bundle"])
1637 os.unlink(opts["bundle"])
1637 except:
1638 except:
1638 pass
1639 pass
1639 ui.status(_("no changes found\n"))
1640 ui.status(_("no changes found\n"))
1640 return 1
1641 return 1
1641
1642
1642 cleanup = None
1643 cleanup = None
1643 try:
1644 try:
1644 fname = opts["bundle"]
1645 fname = opts["bundle"]
1645 if fname or not other.local():
1646 if fname or not other.local():
1646 # create a bundle (uncompressed if other repo is not local)
1647 # create a bundle (uncompressed if other repo is not local)
1647 if revs is None:
1648 if revs is None:
1648 cg = other.changegroup(incoming, "incoming")
1649 cg = other.changegroup(incoming, "incoming")
1649 else:
1650 else:
1650 cg = other.changegroupsubset(incoming, revs, 'incoming')
1651 cg = other.changegroupsubset(incoming, revs, 'incoming')
1651 bundletype = other.local() and "HG10BZ" or "HG10UN"
1652 bundletype = other.local() and "HG10BZ" or "HG10UN"
1652 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1653 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1653 # keep written bundle?
1654 # keep written bundle?
1654 if opts["bundle"]:
1655 if opts["bundle"]:
1655 cleanup = None
1656 cleanup = None
1656 if not other.local():
1657 if not other.local():
1657 # use the created uncompressed bundlerepo
1658 # use the created uncompressed bundlerepo
1658 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1659 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1659
1660
1660 o = other.changelog.nodesbetween(incoming, revs)[0]
1661 o = other.changelog.nodesbetween(incoming, revs)[0]
1661 if opts['newest_first']:
1662 if opts['newest_first']:
1662 o.reverse()
1663 o.reverse()
1663 displayer = cmdutil.show_changeset(ui, other, opts)
1664 displayer = cmdutil.show_changeset(ui, other, opts)
1664 count = 0
1665 count = 0
1665 for n in o:
1666 for n in o:
1666 if count >= limit:
1667 if count >= limit:
1667 break
1668 break
1668 parents = [p for p in other.changelog.parents(n) if p != nullid]
1669 parents = [p for p in other.changelog.parents(n) if p != nullid]
1669 if opts['no_merges'] and len(parents) == 2:
1670 if opts['no_merges'] and len(parents) == 2:
1670 continue
1671 continue
1671 count += 1
1672 count += 1
1672 displayer.show(changenode=n)
1673 displayer.show(changenode=n)
1673 finally:
1674 finally:
1674 if hasattr(other, 'close'):
1675 if hasattr(other, 'close'):
1675 other.close()
1676 other.close()
1676 if cleanup:
1677 if cleanup:
1677 os.unlink(cleanup)
1678 os.unlink(cleanup)
1678
1679
1679 def init(ui, dest=".", **opts):
1680 def init(ui, dest=".", **opts):
1680 """create a new repository in the given directory
1681 """create a new repository in the given directory
1681
1682
1682 Initialize a new repository in the given directory. If the given
1683 Initialize a new repository in the given directory. If the given
1683 directory does not exist, it is created.
1684 directory does not exist, it is created.
1684
1685
1685 If no directory is given, the current directory is used.
1686 If no directory is given, the current directory is used.
1686
1687
1687 It is possible to specify an ssh:// URL as the destination.
1688 It is possible to specify an ssh:// URL as the destination.
1688 Look at the help text for the pull command for important details
1689 Look at the help text for the pull command for important details
1689 about ssh:// URLs.
1690 about ssh:// URLs.
1690 """
1691 """
1691 cmdutil.setremoteconfig(ui, opts)
1692 cmdutil.setremoteconfig(ui, opts)
1692 hg.repository(ui, dest, create=1)
1693 hg.repository(ui, dest, create=1)
1693
1694
1694 def locate(ui, repo, *pats, **opts):
1695 def locate(ui, repo, *pats, **opts):
1695 """locate files matching specific patterns
1696 """locate files matching specific patterns
1696
1697
1697 Print all files under Mercurial control whose names match the
1698 Print all files under Mercurial control whose names match the
1698 given patterns.
1699 given patterns.
1699
1700
1700 This command searches the entire repository by default. To search
1701 This command searches the entire repository by default. To search
1701 just the current directory and its subdirectories, use
1702 just the current directory and its subdirectories, use
1702 "--include .".
1703 "--include .".
1703
1704
1704 If no patterns are given to match, this command prints all file
1705 If no patterns are given to match, this command prints all file
1705 names.
1706 names.
1706
1707
1707 If you want to feed the output of this command into the "xargs"
1708 If you want to feed the output of this command into the "xargs"
1708 command, use the "-0" option to both this command and "xargs".
1709 command, use the "-0" option to both this command and "xargs".
1709 This will avoid the problem of "xargs" treating single filenames
1710 This will avoid the problem of "xargs" treating single filenames
1710 that contain white space as multiple filenames.
1711 that contain white space as multiple filenames.
1711 """
1712 """
1712 end = opts['print0'] and '\0' or '\n'
1713 end = opts['print0'] and '\0' or '\n'
1713 rev = opts.get('rev') or None
1714 rev = opts.get('rev') or None
1714
1715
1715 ret = 1
1716 ret = 1
1716 m = cmdutil.match(repo, pats, opts, default='relglob')
1717 m = cmdutil.match(repo, pats, opts, default='relglob')
1717 m.bad = lambda x,y: False
1718 m.bad = lambda x,y: False
1718 for abs in repo[rev].walk(m):
1719 for abs in repo[rev].walk(m):
1719 if not rev and abs not in repo.dirstate:
1720 if not rev and abs not in repo.dirstate:
1720 continue
1721 continue
1721 if opts['fullpath']:
1722 if opts['fullpath']:
1722 ui.write(os.path.join(repo.root, abs), end)
1723 ui.write(os.path.join(repo.root, abs), end)
1723 else:
1724 else:
1724 ui.write(((pats and m.rel(abs)) or abs), end)
1725 ui.write(((pats and m.rel(abs)) or abs), end)
1725 ret = 0
1726 ret = 0
1726
1727
1727 return ret
1728 return ret
1728
1729
1729 def log(ui, repo, *pats, **opts):
1730 def log(ui, repo, *pats, **opts):
1730 """show revision history of entire repository or files
1731 """show revision history of entire repository or files
1731
1732
1732 Print the revision history of the specified files or the entire
1733 Print the revision history of the specified files or the entire
1733 project.
1734 project.
1734
1735
1735 File history is shown without following rename or copy history of
1736 File history is shown without following rename or copy history of
1736 files. Use -f/--follow with a file name to follow history across
1737 files. Use -f/--follow with a file name to follow history across
1737 renames and copies. --follow without a file name will only show
1738 renames and copies. --follow without a file name will only show
1738 ancestors or descendants of the starting revision. --follow-first
1739 ancestors or descendants of the starting revision. --follow-first
1739 only follows the first parent of merge revisions.
1740 only follows the first parent of merge revisions.
1740
1741
1741 If no revision range is specified, the default is tip:0 unless
1742 If no revision range is specified, the default is tip:0 unless
1742 --follow is set, in which case the working directory parent is
1743 --follow is set, in which case the working directory parent is
1743 used as the starting revision.
1744 used as the starting revision.
1744
1745
1745 See 'hg help dates' for a list of formats valid for -d/--date.
1746 See 'hg help dates' for a list of formats valid for -d/--date.
1746
1747
1747 By default this command outputs: changeset id and hash, tags,
1748 By default this command outputs: changeset id and hash, tags,
1748 non-trivial parents, user, date and time, and a summary for each
1749 non-trivial parents, user, date and time, and a summary for each
1749 commit. When the -v/--verbose switch is used, the list of changed
1750 commit. When the -v/--verbose switch is used, the list of changed
1750 files and full commit message is shown.
1751 files and full commit message is shown.
1751
1752
1752 NOTE: log -p may generate unexpected diff output for merge
1753 NOTE: log -p may generate unexpected diff output for merge
1753 changesets, as it will compare the merge changeset against its
1754 changesets, as it will compare the merge changeset against its
1754 first parent only. Also, the files: list will only reflect files
1755 first parent only. Also, the files: list will only reflect files
1755 that are different from BOTH parents.
1756 that are different from BOTH parents.
1756
1757
1757 """
1758 """
1758
1759
1759 get = util.cachefunc(lambda r: repo[r].changeset())
1760 get = util.cachefunc(lambda r: repo[r].changeset())
1760 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1761 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1761
1762
1762 limit = cmdutil.loglimit(opts)
1763 limit = cmdutil.loglimit(opts)
1763 count = 0
1764 count = 0
1764
1765
1765 if opts['copies'] and opts['rev']:
1766 if opts['copies'] and opts['rev']:
1766 endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
1767 endrev = max(cmdutil.revrange(repo, opts['rev'])) + 1
1767 else:
1768 else:
1768 endrev = len(repo)
1769 endrev = len(repo)
1769 rcache = {}
1770 rcache = {}
1770 ncache = {}
1771 ncache = {}
1771 def getrenamed(fn, rev):
1772 def getrenamed(fn, rev):
1772 '''looks up all renames for a file (up to endrev) the first
1773 '''looks up all renames for a file (up to endrev) the first
1773 time the file is given. It indexes on the changerev and only
1774 time the file is given. It indexes on the changerev and only
1774 parses the manifest if linkrev != changerev.
1775 parses the manifest if linkrev != changerev.
1775 Returns rename info for fn at changerev rev.'''
1776 Returns rename info for fn at changerev rev.'''
1776 if fn not in rcache:
1777 if fn not in rcache:
1777 rcache[fn] = {}
1778 rcache[fn] = {}
1778 ncache[fn] = {}
1779 ncache[fn] = {}
1779 fl = repo.file(fn)
1780 fl = repo.file(fn)
1780 for i in fl:
1781 for i in fl:
1781 node = fl.node(i)
1782 node = fl.node(i)
1782 lr = fl.linkrev(node)
1783 lr = fl.linkrev(node)
1783 renamed = fl.renamed(node)
1784 renamed = fl.renamed(node)
1784 rcache[fn][lr] = renamed
1785 rcache[fn][lr] = renamed
1785 if renamed:
1786 if renamed:
1786 ncache[fn][node] = renamed
1787 ncache[fn][node] = renamed
1787 if lr >= endrev:
1788 if lr >= endrev:
1788 break
1789 break
1789 if rev in rcache[fn]:
1790 if rev in rcache[fn]:
1790 return rcache[fn][rev]
1791 return rcache[fn][rev]
1791
1792
1792 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1793 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1793 # filectx logic.
1794 # filectx logic.
1794
1795
1795 try:
1796 try:
1796 return repo[rev][fn].renamed()
1797 return repo[rev][fn].renamed()
1797 except revlog.LookupError:
1798 except revlog.LookupError:
1798 pass
1799 pass
1799 return None
1800 return None
1800
1801
1801 df = False
1802 df = False
1802 if opts["date"]:
1803 if opts["date"]:
1803 df = util.matchdate(opts["date"])
1804 df = util.matchdate(opts["date"])
1804
1805
1805 only_branches = opts['only_branch']
1806 only_branches = opts['only_branch']
1806
1807
1807 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1808 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1808 for st, rev, fns in changeiter:
1809 for st, rev, fns in changeiter:
1809 if st == 'add':
1810 if st == 'add':
1810 changenode = repo.changelog.node(rev)
1811 changenode = repo.changelog.node(rev)
1811 parents = [p for p in repo.changelog.parentrevs(rev)
1812 parents = [p for p in repo.changelog.parentrevs(rev)
1812 if p != nullrev]
1813 if p != nullrev]
1813 if opts['no_merges'] and len(parents) == 2:
1814 if opts['no_merges'] and len(parents) == 2:
1814 continue
1815 continue
1815 if opts['only_merges'] and len(parents) != 2:
1816 if opts['only_merges'] and len(parents) != 2:
1816 continue
1817 continue
1817
1818
1818 if only_branches:
1819 if only_branches:
1819 revbranch = get(rev)[5]['branch']
1820 revbranch = get(rev)[5]['branch']
1820 if revbranch not in only_branches:
1821 if revbranch not in only_branches:
1821 continue
1822 continue
1822
1823
1823 if df:
1824 if df:
1824 changes = get(rev)
1825 changes = get(rev)
1825 if not df(changes[2][0]):
1826 if not df(changes[2][0]):
1826 continue
1827 continue
1827
1828
1828 if opts['keyword']:
1829 if opts['keyword']:
1829 changes = get(rev)
1830 changes = get(rev)
1830 miss = 0
1831 miss = 0
1831 for k in [kw.lower() for kw in opts['keyword']]:
1832 for k in [kw.lower() for kw in opts['keyword']]:
1832 if not (k in changes[1].lower() or
1833 if not (k in changes[1].lower() or
1833 k in changes[4].lower() or
1834 k in changes[4].lower() or
1834 k in " ".join(changes[3]).lower()):
1835 k in " ".join(changes[3]).lower()):
1835 miss = 1
1836 miss = 1
1836 break
1837 break
1837 if miss:
1838 if miss:
1838 continue
1839 continue
1839
1840
1840 copies = []
1841 copies = []
1841 if opts.get('copies') and rev:
1842 if opts.get('copies') and rev:
1842 for fn in get(rev)[3]:
1843 for fn in get(rev)[3]:
1843 rename = getrenamed(fn, rev)
1844 rename = getrenamed(fn, rev)
1844 if rename:
1845 if rename:
1845 copies.append((fn, rename[0]))
1846 copies.append((fn, rename[0]))
1846 displayer.show(rev, changenode, copies=copies)
1847 displayer.show(rev, changenode, copies=copies)
1847 elif st == 'iter':
1848 elif st == 'iter':
1848 if count == limit: break
1849 if count == limit: break
1849 if displayer.flush(rev):
1850 if displayer.flush(rev):
1850 count += 1
1851 count += 1
1851
1852
1852 def manifest(ui, repo, node=None, rev=None):
1853 def manifest(ui, repo, node=None, rev=None):
1853 """output the current or given revision of the project manifest
1854 """output the current or given revision of the project manifest
1854
1855
1855 Print a list of version controlled files for the given revision.
1856 Print a list of version controlled files for the given revision.
1856 If no revision is given, the parent of the working directory is used,
1857 If no revision is given, the parent of the working directory is used,
1857 or tip if no revision is checked out.
1858 or tip if no revision is checked out.
1858
1859
1859 The manifest is the list of files being version controlled. If no revision
1860 The manifest is the list of files being version controlled. If no revision
1860 is given then the first parent of the working directory is used.
1861 is given then the first parent of the working directory is used.
1861
1862
1862 With -v flag, print file permissions, symlink and executable bits. With
1863 With -v flag, print file permissions, symlink and executable bits. With
1863 --debug flag, print file revision hashes.
1864 --debug flag, print file revision hashes.
1864 """
1865 """
1865
1866
1866 if rev and node:
1867 if rev and node:
1867 raise util.Abort(_("please specify just one revision"))
1868 raise util.Abort(_("please specify just one revision"))
1868
1869
1869 if not node:
1870 if not node:
1870 node = rev
1871 node = rev
1871
1872
1872 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
1873 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
1873 ctx = repo[node]
1874 ctx = repo[node]
1874 for f in ctx:
1875 for f in ctx:
1875 if ui.debugflag:
1876 if ui.debugflag:
1876 ui.write("%40s " % hex(ctx.manifest()[f]))
1877 ui.write("%40s " % hex(ctx.manifest()[f]))
1877 if ui.verbose:
1878 if ui.verbose:
1878 ui.write(decor[ctx.flags(f)])
1879 ui.write(decor[ctx.flags(f)])
1879 ui.write("%s\n" % f)
1880 ui.write("%s\n" % f)
1880
1881
1881 def merge(ui, repo, node=None, force=None, rev=None):
1882 def merge(ui, repo, node=None, force=None, rev=None):
1882 """merge working directory with another revision
1883 """merge working directory with another revision
1883
1884
1884 Merge the contents of the current working directory and the
1885 Merge the contents of the current working directory and the
1885 requested revision. Files that changed between either parent are
1886 requested revision. Files that changed between either parent are
1886 marked as changed for the next commit and a commit must be
1887 marked as changed for the next commit and a commit must be
1887 performed before any further updates are allowed.
1888 performed before any further updates are allowed.
1888
1889
1889 If no revision is specified, the working directory's parent is a
1890 If no revision is specified, the working directory's parent is a
1890 head revision, and the current branch contains exactly one other head,
1891 head revision, and the current branch contains exactly one other head,
1891 the other head is merged with by default. Otherwise, an explicit
1892 the other head is merged with by default. Otherwise, an explicit
1892 revision to merge with must be provided.
1893 revision to merge with must be provided.
1893 """
1894 """
1894
1895
1895 if rev and node:
1896 if rev and node:
1896 raise util.Abort(_("please specify just one revision"))
1897 raise util.Abort(_("please specify just one revision"))
1897 if not node:
1898 if not node:
1898 node = rev
1899 node = rev
1899
1900
1900 if not node:
1901 if not node:
1901 branch = repo.changectx(None).branch()
1902 branch = repo.changectx(None).branch()
1902 bheads = repo.branchheads(branch)
1903 bheads = repo.branchheads(branch)
1903 if len(bheads) > 2:
1904 if len(bheads) > 2:
1904 raise util.Abort(_("branch '%s' has %d heads - "
1905 raise util.Abort(_("branch '%s' has %d heads - "
1905 "please merge with an explicit rev") %
1906 "please merge with an explicit rev") %
1906 (branch, len(bheads)))
1907 (branch, len(bheads)))
1907
1908
1908 parent = repo.dirstate.parents()[0]
1909 parent = repo.dirstate.parents()[0]
1909 if len(bheads) == 1:
1910 if len(bheads) == 1:
1910 if len(repo.heads()) > 1:
1911 if len(repo.heads()) > 1:
1911 raise util.Abort(_("branch '%s' has one head - "
1912 raise util.Abort(_("branch '%s' has one head - "
1912 "please merge with an explicit rev") %
1913 "please merge with an explicit rev") %
1913 branch)
1914 branch)
1914 msg = _('there is nothing to merge')
1915 msg = _('there is nothing to merge')
1915 if parent != repo.lookup(repo[None].branch()):
1916 if parent != repo.lookup(repo[None].branch()):
1916 msg = _('%s - use "hg update" instead') % msg
1917 msg = _('%s - use "hg update" instead') % msg
1917 raise util.Abort(msg)
1918 raise util.Abort(msg)
1918
1919
1919 if parent not in bheads:
1920 if parent not in bheads:
1920 raise util.Abort(_('working dir not at a head rev - '
1921 raise util.Abort(_('working dir not at a head rev - '
1921 'use "hg update" or merge with an explicit rev'))
1922 'use "hg update" or merge with an explicit rev'))
1922 node = parent == bheads[0] and bheads[-1] or bheads[0]
1923 node = parent == bheads[0] and bheads[-1] or bheads[0]
1923 return hg.merge(repo, node, force=force)
1924 return hg.merge(repo, node, force=force)
1924
1925
1925 def outgoing(ui, repo, dest=None, **opts):
1926 def outgoing(ui, repo, dest=None, **opts):
1926 """show changesets not found in destination
1927 """show changesets not found in destination
1927
1928
1928 Show changesets not found in the specified destination repository or
1929 Show changesets not found in the specified destination repository or
1929 the default push location. These are the changesets that would be pushed
1930 the default push location. These are the changesets that would be pushed
1930 if a push was requested.
1931 if a push was requested.
1931
1932
1932 See pull for valid destination format details.
1933 See pull for valid destination format details.
1933 """
1934 """
1934 limit = cmdutil.loglimit(opts)
1935 limit = cmdutil.loglimit(opts)
1935 dest, revs, checkout = hg.parseurl(
1936 dest, revs, checkout = hg.parseurl(
1936 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
1937 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
1937 cmdutil.setremoteconfig(ui, opts)
1938 cmdutil.setremoteconfig(ui, opts)
1938 if revs:
1939 if revs:
1939 revs = [repo.lookup(rev) for rev in revs]
1940 revs = [repo.lookup(rev) for rev in revs]
1940
1941
1941 other = hg.repository(ui, dest)
1942 other = hg.repository(ui, dest)
1942 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
1943 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
1943 o = repo.findoutgoing(other, force=opts['force'])
1944 o = repo.findoutgoing(other, force=opts['force'])
1944 if not o:
1945 if not o:
1945 ui.status(_("no changes found\n"))
1946 ui.status(_("no changes found\n"))
1946 return 1
1947 return 1
1947 o = repo.changelog.nodesbetween(o, revs)[0]
1948 o = repo.changelog.nodesbetween(o, revs)[0]
1948 if opts['newest_first']:
1949 if opts['newest_first']:
1949 o.reverse()
1950 o.reverse()
1950 displayer = cmdutil.show_changeset(ui, repo, opts)
1951 displayer = cmdutil.show_changeset(ui, repo, opts)
1951 count = 0
1952 count = 0
1952 for n in o:
1953 for n in o:
1953 if count >= limit:
1954 if count >= limit:
1954 break
1955 break
1955 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1956 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1956 if opts['no_merges'] and len(parents) == 2:
1957 if opts['no_merges'] and len(parents) == 2:
1957 continue
1958 continue
1958 count += 1
1959 count += 1
1959 displayer.show(changenode=n)
1960 displayer.show(changenode=n)
1960
1961
1961 def parents(ui, repo, file_=None, **opts):
1962 def parents(ui, repo, file_=None, **opts):
1962 """show the parents of the working dir or revision
1963 """show the parents of the working dir or revision
1963
1964
1964 Print the working directory's parent revisions. If a
1965 Print the working directory's parent revisions. If a
1965 revision is given via --rev, the parent of that revision
1966 revision is given via --rev, the parent of that revision
1966 will be printed. If a file argument is given, revision in
1967 will be printed. If a file argument is given, revision in
1967 which the file was last changed (before the working directory
1968 which the file was last changed (before the working directory
1968 revision or the argument to --rev if given) is printed.
1969 revision or the argument to --rev if given) is printed.
1969 """
1970 """
1970 rev = opts.get('rev')
1971 rev = opts.get('rev')
1971 if rev:
1972 if rev:
1972 ctx = repo[rev]
1973 ctx = repo[rev]
1973 else:
1974 else:
1974 ctx = repo[None]
1975 ctx = repo[None]
1975
1976
1976 if file_:
1977 if file_:
1977 m = cmdutil.match(repo, (file_,), opts)
1978 m = cmdutil.match(repo, (file_,), opts)
1978 if m.anypats() or len(m.files()) != 1:
1979 if m.anypats() or len(m.files()) != 1:
1979 raise util.Abort(_('can only specify an explicit file name'))
1980 raise util.Abort(_('can only specify an explicit file name'))
1980 file_ = m.files()[0]
1981 file_ = m.files()[0]
1981 filenodes = []
1982 filenodes = []
1982 for cp in ctx.parents():
1983 for cp in ctx.parents():
1983 if not cp:
1984 if not cp:
1984 continue
1985 continue
1985 try:
1986 try:
1986 filenodes.append(cp.filenode(file_))
1987 filenodes.append(cp.filenode(file_))
1987 except revlog.LookupError:
1988 except revlog.LookupError:
1988 pass
1989 pass
1989 if not filenodes:
1990 if not filenodes:
1990 raise util.Abort(_("'%s' not found in manifest!") % file_)
1991 raise util.Abort(_("'%s' not found in manifest!") % file_)
1991 fl = repo.file(file_)
1992 fl = repo.file(file_)
1992 p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
1993 p = [repo.lookup(fl.linkrev(fn)) for fn in filenodes]
1993 else:
1994 else:
1994 p = [cp.node() for cp in ctx.parents()]
1995 p = [cp.node() for cp in ctx.parents()]
1995
1996
1996 displayer = cmdutil.show_changeset(ui, repo, opts)
1997 displayer = cmdutil.show_changeset(ui, repo, opts)
1997 for n in p:
1998 for n in p:
1998 if n != nullid:
1999 if n != nullid:
1999 displayer.show(changenode=n)
2000 displayer.show(changenode=n)
2000
2001
2001 def paths(ui, repo, search=None):
2002 def paths(ui, repo, search=None):
2002 """show definition of symbolic path names
2003 """show definition of symbolic path names
2003
2004
2004 Show definition of symbolic path name NAME. If no name is given, show
2005 Show definition of symbolic path name NAME. If no name is given, show
2005 definition of available names.
2006 definition of available names.
2006
2007
2007 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2008 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2008 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2009 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2009 """
2010 """
2010 if search:
2011 if search:
2011 for name, path in ui.configitems("paths"):
2012 for name, path in ui.configitems("paths"):
2012 if name == search:
2013 if name == search:
2013 ui.write("%s\n" % util.hidepassword(path))
2014 ui.write("%s\n" % util.hidepassword(path))
2014 return
2015 return
2015 ui.warn(_("not found!\n"))
2016 ui.warn(_("not found!\n"))
2016 return 1
2017 return 1
2017 else:
2018 else:
2018 for name, path in ui.configitems("paths"):
2019 for name, path in ui.configitems("paths"):
2019 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
2020 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
2020
2021
2021 def postincoming(ui, repo, modheads, optupdate, checkout):
2022 def postincoming(ui, repo, modheads, optupdate, checkout):
2022 if modheads == 0:
2023 if modheads == 0:
2023 return
2024 return
2024 if optupdate:
2025 if optupdate:
2025 if modheads <= 1 or checkout:
2026 if modheads <= 1 or checkout:
2026 return hg.update(repo, checkout)
2027 return hg.update(repo, checkout)
2027 else:
2028 else:
2028 ui.status(_("not updating, since new heads added\n"))
2029 ui.status(_("not updating, since new heads added\n"))
2029 if modheads > 1:
2030 if modheads > 1:
2030 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2031 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2031 else:
2032 else:
2032 ui.status(_("(run 'hg update' to get a working copy)\n"))
2033 ui.status(_("(run 'hg update' to get a working copy)\n"))
2033
2034
2034 def pull(ui, repo, source="default", **opts):
2035 def pull(ui, repo, source="default", **opts):
2035 """pull changes from the specified source
2036 """pull changes from the specified source
2036
2037
2037 Pull changes from a remote repository to a local one.
2038 Pull changes from a remote repository to a local one.
2038
2039
2039 This finds all changes from the repository at the specified path
2040 This finds all changes from the repository at the specified path
2040 or URL and adds them to the local repository. By default, this
2041 or URL and adds them to the local repository. By default, this
2041 does not update the copy of the project in the working directory.
2042 does not update the copy of the project in the working directory.
2042
2043
2043 Valid URLs are of the form:
2044 Valid URLs are of the form:
2044
2045
2045 local/filesystem/path (or file://local/filesystem/path)
2046 local/filesystem/path (or file://local/filesystem/path)
2046 http://[user[:pass]@]host[:port]/[path]
2047 http://[user[:pass]@]host[:port]/[path]
2047 https://[user[:pass]@]host[:port]/[path]
2048 https://[user[:pass]@]host[:port]/[path]
2048 ssh://[user[:pass]@]host[:port]/[path]
2049 ssh://[user[:pass]@]host[:port]/[path]
2049 static-http://host[:port]/[path]
2050 static-http://host[:port]/[path]
2050
2051
2051 Paths in the local filesystem can either point to Mercurial
2052 Paths in the local filesystem can either point to Mercurial
2052 repositories or to bundle files (as created by 'hg bundle' or
2053 repositories or to bundle files (as created by 'hg bundle' or
2053 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
2054 'hg incoming --bundle'). The static-http:// protocol, albeit slow,
2054 allows access to a Mercurial repository where you simply use a web
2055 allows access to a Mercurial repository where you simply use a web
2055 server to publish the .hg directory as static content.
2056 server to publish the .hg directory as static content.
2056
2057
2057 An optional identifier after # indicates a particular branch, tag,
2058 An optional identifier after # indicates a particular branch, tag,
2058 or changeset to pull.
2059 or changeset to pull.
2059
2060
2060 Some notes about using SSH with Mercurial:
2061 Some notes about using SSH with Mercurial:
2061 - SSH requires an accessible shell account on the destination machine
2062 - SSH requires an accessible shell account on the destination machine
2062 and a copy of hg in the remote path or specified with as remotecmd.
2063 and a copy of hg in the remote path or specified with as remotecmd.
2063 - path is relative to the remote user's home directory by default.
2064 - path is relative to the remote user's home directory by default.
2064 Use an extra slash at the start of a path to specify an absolute path:
2065 Use an extra slash at the start of a path to specify an absolute path:
2065 ssh://example.com//tmp/repository
2066 ssh://example.com//tmp/repository
2066 - Mercurial doesn't use its own compression via SSH; the right thing
2067 - Mercurial doesn't use its own compression via SSH; the right thing
2067 to do is to configure it in your ~/.ssh/config, e.g.:
2068 to do is to configure it in your ~/.ssh/config, e.g.:
2068 Host *.mylocalnetwork.example.com
2069 Host *.mylocalnetwork.example.com
2069 Compression no
2070 Compression no
2070 Host *
2071 Host *
2071 Compression yes
2072 Compression yes
2072 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2073 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2073 with the --ssh command line option.
2074 with the --ssh command line option.
2074 """
2075 """
2075 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
2076 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts['rev'])
2076 cmdutil.setremoteconfig(ui, opts)
2077 cmdutil.setremoteconfig(ui, opts)
2077
2078
2078 other = hg.repository(ui, source)
2079 other = hg.repository(ui, source)
2079 ui.status(_('pulling from %s\n') % util.hidepassword(source))
2080 ui.status(_('pulling from %s\n') % util.hidepassword(source))
2080 if revs:
2081 if revs:
2081 try:
2082 try:
2082 revs = [other.lookup(rev) for rev in revs]
2083 revs = [other.lookup(rev) for rev in revs]
2083 except NoCapability:
2084 except NoCapability:
2084 error = _("Other repository doesn't support revision lookup, "
2085 error = _("Other repository doesn't support revision lookup, "
2085 "so a rev cannot be specified.")
2086 "so a rev cannot be specified.")
2086 raise util.Abort(error)
2087 raise util.Abort(error)
2087
2088
2088 modheads = repo.pull(other, heads=revs, force=opts['force'])
2089 modheads = repo.pull(other, heads=revs, force=opts['force'])
2089 return postincoming(ui, repo, modheads, opts['update'], checkout)
2090 return postincoming(ui, repo, modheads, opts['update'], checkout)
2090
2091
2091 def push(ui, repo, dest=None, **opts):
2092 def push(ui, repo, dest=None, **opts):
2092 """push changes to the specified destination
2093 """push changes to the specified destination
2093
2094
2094 Push changes from the local repository to the given destination.
2095 Push changes from the local repository to the given destination.
2095
2096
2096 This is the symmetrical operation for pull. It helps to move
2097 This is the symmetrical operation for pull. It helps to move
2097 changes from the current repository to a different one. If the
2098 changes from the current repository to a different one. If the
2098 destination is local this is identical to a pull in that directory
2099 destination is local this is identical to a pull in that directory
2099 from the current one.
2100 from the current one.
2100
2101
2101 By default, push will refuse to run if it detects the result would
2102 By default, push will refuse to run if it detects the result would
2102 increase the number of remote heads. This generally indicates the
2103 increase the number of remote heads. This generally indicates the
2103 the client has forgotten to pull and merge before pushing.
2104 the client has forgotten to pull and merge before pushing.
2104
2105
2105 Valid URLs are of the form:
2106 Valid URLs are of the form:
2106
2107
2107 local/filesystem/path (or file://local/filesystem/path)
2108 local/filesystem/path (or file://local/filesystem/path)
2108 ssh://[user[:pass]@]host[:port]/[path]
2109 ssh://[user[:pass]@]host[:port]/[path]
2109 http://[user[:pass]@]host[:port]/[path]
2110 http://[user[:pass]@]host[:port]/[path]
2110 https://[user[:pass]@]host[:port]/[path]
2111 https://[user[:pass]@]host[:port]/[path]
2111
2112
2112 An optional identifier after # indicates a particular branch, tag,
2113 An optional identifier after # indicates a particular branch, tag,
2113 or changeset to push. If -r is used, the named changeset and all its
2114 or changeset to push. If -r is used, the named changeset and all its
2114 ancestors will be pushed to the remote repository.
2115 ancestors will be pushed to the remote repository.
2115
2116
2116 Look at the help text for the pull command for important details
2117 Look at the help text for the pull command for important details
2117 about ssh:// URLs.
2118 about ssh:// URLs.
2118
2119
2119 Pushing to http:// and https:// URLs is only possible, if this
2120 Pushing to http:// and https:// URLs is only possible, if this
2120 feature is explicitly enabled on the remote Mercurial server.
2121 feature is explicitly enabled on the remote Mercurial server.
2121 """
2122 """
2122 dest, revs, checkout = hg.parseurl(
2123 dest, revs, checkout = hg.parseurl(
2123 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2124 ui.expandpath(dest or 'default-push', dest or 'default'), opts['rev'])
2124 cmdutil.setremoteconfig(ui, opts)
2125 cmdutil.setremoteconfig(ui, opts)
2125
2126
2126 other = hg.repository(ui, dest)
2127 other = hg.repository(ui, dest)
2127 ui.status('pushing to %s\n' % util.hidepassword(dest))
2128 ui.status('pushing to %s\n' % util.hidepassword(dest))
2128 if revs:
2129 if revs:
2129 revs = [repo.lookup(rev) for rev in revs]
2130 revs = [repo.lookup(rev) for rev in revs]
2130 r = repo.push(other, opts['force'], revs=revs)
2131 r = repo.push(other, opts['force'], revs=revs)
2131 return r == 0
2132 return r == 0
2132
2133
2133 def rawcommit(ui, repo, *pats, **opts):
2134 def rawcommit(ui, repo, *pats, **opts):
2134 """raw commit interface (DEPRECATED)
2135 """raw commit interface (DEPRECATED)
2135
2136
2136 (DEPRECATED)
2137 (DEPRECATED)
2137 Lowlevel commit, for use in helper scripts.
2138 Lowlevel commit, for use in helper scripts.
2138
2139
2139 This command is not intended to be used by normal users, as it is
2140 This command is not intended to be used by normal users, as it is
2140 primarily useful for importing from other SCMs.
2141 primarily useful for importing from other SCMs.
2141
2142
2142 This command is now deprecated and will be removed in a future
2143 This command is now deprecated and will be removed in a future
2143 release, please use debugsetparents and commit instead.
2144 release, please use debugsetparents and commit instead.
2144 """
2145 """
2145
2146
2146 ui.warn(_("(the rawcommit command is deprecated)\n"))
2147 ui.warn(_("(the rawcommit command is deprecated)\n"))
2147
2148
2148 message = cmdutil.logmessage(opts)
2149 message = cmdutil.logmessage(opts)
2149
2150
2150 files = cmdutil.match(repo, pats, opts).files()
2151 files = cmdutil.match(repo, pats, opts).files()
2151 if opts['files']:
2152 if opts['files']:
2152 files += open(opts['files']).read().splitlines()
2153 files += open(opts['files']).read().splitlines()
2153
2154
2154 parents = [repo.lookup(p) for p in opts['parent']]
2155 parents = [repo.lookup(p) for p in opts['parent']]
2155
2156
2156 try:
2157 try:
2157 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2158 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2158 except ValueError, inst:
2159 except ValueError, inst:
2159 raise util.Abort(str(inst))
2160 raise util.Abort(str(inst))
2160
2161
2161 def recover(ui, repo):
2162 def recover(ui, repo):
2162 """roll back an interrupted transaction
2163 """roll back an interrupted transaction
2163
2164
2164 Recover from an interrupted commit or pull.
2165 Recover from an interrupted commit or pull.
2165
2166
2166 This command tries to fix the repository status after an interrupted
2167 This command tries to fix the repository status after an interrupted
2167 operation. It should only be necessary when Mercurial suggests it.
2168 operation. It should only be necessary when Mercurial suggests it.
2168 """
2169 """
2169 if repo.recover():
2170 if repo.recover():
2170 return hg.verify(repo)
2171 return hg.verify(repo)
2171 return 1
2172 return 1
2172
2173
2173 def remove(ui, repo, *pats, **opts):
2174 def remove(ui, repo, *pats, **opts):
2174 """remove the specified files on the next commit
2175 """remove the specified files on the next commit
2175
2176
2176 Schedule the indicated files for removal from the repository.
2177 Schedule the indicated files for removal from the repository.
2177
2178
2178 This only removes files from the current branch, not from the entire
2179 This only removes files from the current branch, not from the entire
2179 project history. -A can be used to remove only files that have already
2180 project history. -A can be used to remove only files that have already
2180 been deleted, -f can be used to force deletion, and -Af can be used
2181 been deleted, -f can be used to force deletion, and -Af can be used
2181 to remove files from the next revision without deleting them.
2182 to remove files from the next revision without deleting them.
2182
2183
2183 The following table details the behavior of remove for different file
2184 The following table details the behavior of remove for different file
2184 states (columns) and option combinations (rows). The file states are
2185 states (columns) and option combinations (rows). The file states are
2185 Added, Clean, Modified and Missing (as reported by hg status). The
2186 Added, Clean, Modified and Missing (as reported by hg status). The
2186 actions are Warn, Remove (from branch) and Delete (from disk).
2187 actions are Warn, Remove (from branch) and Delete (from disk).
2187
2188
2188 A C M !
2189 A C M !
2189 none W RD W R
2190 none W RD W R
2190 -f R RD RD R
2191 -f R RD RD R
2191 -A W W W R
2192 -A W W W R
2192 -Af R R R R
2193 -Af R R R R
2193
2194
2194 This command schedules the files to be removed at the next commit.
2195 This command schedules the files to be removed at the next commit.
2195 To undo a remove before that, see hg revert.
2196 To undo a remove before that, see hg revert.
2196 """
2197 """
2197
2198
2198 after, force = opts.get('after'), opts.get('force')
2199 after, force = opts.get('after'), opts.get('force')
2199 if not pats and not after:
2200 if not pats and not after:
2200 raise util.Abort(_('no files specified'))
2201 raise util.Abort(_('no files specified'))
2201
2202
2202 m = cmdutil.match(repo, pats, opts)
2203 m = cmdutil.match(repo, pats, opts)
2203 s = repo.status(match=m, clean=True)
2204 s = repo.status(match=m, clean=True)
2204 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2205 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2205
2206
2206 def warn(files, reason):
2207 def warn(files, reason):
2207 for f in files:
2208 for f in files:
2208 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2209 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2209 % (m.rel(f), reason))
2210 % (m.rel(f), reason))
2210
2211
2211 if force:
2212 if force:
2212 remove, forget = modified + deleted + clean, added
2213 remove, forget = modified + deleted + clean, added
2213 elif after:
2214 elif after:
2214 remove, forget = deleted, []
2215 remove, forget = deleted, []
2215 warn(modified + added + clean, _('still exists'))
2216 warn(modified + added + clean, _('still exists'))
2216 else:
2217 else:
2217 remove, forget = deleted + clean, []
2218 remove, forget = deleted + clean, []
2218 warn(modified, _('is modified'))
2219 warn(modified, _('is modified'))
2219 warn(added, _('has been marked for add'))
2220 warn(added, _('has been marked for add'))
2220
2221
2221 for f in util.sort(remove + forget):
2222 for f in util.sort(remove + forget):
2222 if ui.verbose or not m.exact(f):
2223 if ui.verbose or not m.exact(f):
2223 ui.status(_('removing %s\n') % m.rel(f))
2224 ui.status(_('removing %s\n') % m.rel(f))
2224
2225
2225 repo.forget(forget)
2226 repo.forget(forget)
2226 repo.remove(remove, unlink=not after)
2227 repo.remove(remove, unlink=not after)
2227
2228
2228 def rename(ui, repo, *pats, **opts):
2229 def rename(ui, repo, *pats, **opts):
2229 """rename files; equivalent of copy + remove
2230 """rename files; equivalent of copy + remove
2230
2231
2231 Mark dest as copies of sources; mark sources for deletion. If
2232 Mark dest as copies of sources; mark sources for deletion. If
2232 dest is a directory, copies are put in that directory. If dest is
2233 dest is a directory, copies are put in that directory. If dest is
2233 a file, there can only be one source.
2234 a file, there can only be one source.
2234
2235
2235 By default, this command copies the contents of files as they
2236 By default, this command copies the contents of files as they
2236 stand in the working directory. If invoked with --after, the
2237 stand in the working directory. If invoked with --after, the
2237 operation is recorded, but no copying is performed.
2238 operation is recorded, but no copying is performed.
2238
2239
2239 This command takes effect in the next commit. To undo a rename
2240 This command takes effect in the next commit. To undo a rename
2240 before that, see hg revert.
2241 before that, see hg revert.
2241 """
2242 """
2242 wlock = repo.wlock(False)
2243 wlock = repo.wlock(False)
2243 try:
2244 try:
2244 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2245 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2245 finally:
2246 finally:
2246 del wlock
2247 del wlock
2247
2248
2248 def resolve(ui, repo, *pats, **opts):
2249 def resolve(ui, repo, *pats, **opts):
2249 """resolve file merges from a branch merge or update
2250 """resolve file merges from a branch merge or update
2250
2251
2251 This command will attempt to resolve unresolved merges from the
2252 This command will attempt to resolve unresolved merges from the
2252 last update or merge command. This will use the local file
2253 last update or merge command. This will use the local file
2253 revision preserved at the last update or merge to cleanly retry
2254 revision preserved at the last update or merge to cleanly retry
2254 the file merge attempt. With no file or options specified, this
2255 the file merge attempt. With no file or options specified, this
2255 command will attempt to resolve all unresolved files.
2256 command will attempt to resolve all unresolved files.
2256
2257
2257 The codes used to show the status of files are:
2258 The codes used to show the status of files are:
2258 U = unresolved
2259 U = unresolved
2259 R = resolved
2260 R = resolved
2260 """
2261 """
2261
2262
2262 if len([x for x in opts if opts[x]]) > 1:
2263 if len([x for x in opts if opts[x]]) > 1:
2263 raise util.Abort(_("too many options specified"))
2264 raise util.Abort(_("too many options specified"))
2264
2265
2265 ms = merge_.mergestate(repo)
2266 ms = merge_.mergestate(repo)
2266 m = cmdutil.match(repo, pats, opts)
2267 m = cmdutil.match(repo, pats, opts)
2267
2268
2268 for f in ms:
2269 for f in ms:
2269 if m(f):
2270 if m(f):
2270 if opts.get("list"):
2271 if opts.get("list"):
2271 ui.write("%s %s\n" % (ms[f].upper(), f))
2272 ui.write("%s %s\n" % (ms[f].upper(), f))
2272 elif opts.get("mark"):
2273 elif opts.get("mark"):
2273 ms.mark(f, "r")
2274 ms.mark(f, "r")
2274 elif opts.get("unmark"):
2275 elif opts.get("unmark"):
2275 ms.mark(f, "u")
2276 ms.mark(f, "u")
2276 else:
2277 else:
2277 wctx = repo[None]
2278 wctx = repo[None]
2278 mctx = wctx.parents()[-1]
2279 mctx = wctx.parents()[-1]
2279 ms.resolve(f, wctx, mctx)
2280 ms.resolve(f, wctx, mctx)
2280
2281
2281 def revert(ui, repo, *pats, **opts):
2282 def revert(ui, repo, *pats, **opts):
2282 """restore individual files or dirs to an earlier state
2283 """restore individual files or dirs to an earlier state
2283
2284
2284 (use update -r to check out earlier revisions, revert does not
2285 (use update -r to check out earlier revisions, revert does not
2285 change the working dir parents)
2286 change the working dir parents)
2286
2287
2287 With no revision specified, revert the named files or directories
2288 With no revision specified, revert the named files or directories
2288 to the contents they had in the parent of the working directory.
2289 to the contents they had in the parent of the working directory.
2289 This restores the contents of the affected files to an unmodified
2290 This restores the contents of the affected files to an unmodified
2290 state and unschedules adds, removes, copies, and renames. If the
2291 state and unschedules adds, removes, copies, and renames. If the
2291 working directory has two parents, you must explicitly specify the
2292 working directory has two parents, you must explicitly specify the
2292 revision to revert to.
2293 revision to revert to.
2293
2294
2294 Using the -r option, revert the given files or directories to their
2295 Using the -r option, revert the given files or directories to their
2295 contents as of a specific revision. This can be helpful to "roll
2296 contents as of a specific revision. This can be helpful to "roll
2296 back" some or all of an earlier change.
2297 back" some or all of an earlier change.
2297 See 'hg help dates' for a list of formats valid for -d/--date.
2298 See 'hg help dates' for a list of formats valid for -d/--date.
2298
2299
2299 Revert modifies the working directory. It does not commit any
2300 Revert modifies the working directory. It does not commit any
2300 changes, or change the parent of the working directory. If you
2301 changes, or change the parent of the working directory. If you
2301 revert to a revision other than the parent of the working
2302 revert to a revision other than the parent of the working
2302 directory, the reverted files will thus appear modified
2303 directory, the reverted files will thus appear modified
2303 afterwards.
2304 afterwards.
2304
2305
2305 If a file has been deleted, it is restored. If the executable
2306 If a file has been deleted, it is restored. If the executable
2306 mode of a file was changed, it is reset.
2307 mode of a file was changed, it is reset.
2307
2308
2308 If names are given, all files matching the names are reverted.
2309 If names are given, all files matching the names are reverted.
2309 If no arguments are given, no files are reverted.
2310 If no arguments are given, no files are reverted.
2310
2311
2311 Modified files are saved with a .orig suffix before reverting.
2312 Modified files are saved with a .orig suffix before reverting.
2312 To disable these backups, use --no-backup.
2313 To disable these backups, use --no-backup.
2313 """
2314 """
2314
2315
2315 if opts["date"]:
2316 if opts["date"]:
2316 if opts["rev"]:
2317 if opts["rev"]:
2317 raise util.Abort(_("you can't specify a revision and a date"))
2318 raise util.Abort(_("you can't specify a revision and a date"))
2318 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2319 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2319
2320
2320 if not pats and not opts['all']:
2321 if not pats and not opts['all']:
2321 raise util.Abort(_('no files or directories specified; '
2322 raise util.Abort(_('no files or directories specified; '
2322 'use --all to revert the whole repo'))
2323 'use --all to revert the whole repo'))
2323
2324
2324 parent, p2 = repo.dirstate.parents()
2325 parent, p2 = repo.dirstate.parents()
2325 if not opts['rev'] and p2 != nullid:
2326 if not opts['rev'] and p2 != nullid:
2326 raise util.Abort(_('uncommitted merge - please provide a '
2327 raise util.Abort(_('uncommitted merge - please provide a '
2327 'specific revision'))
2328 'specific revision'))
2328 ctx = repo[opts['rev']]
2329 ctx = repo[opts['rev']]
2329 node = ctx.node()
2330 node = ctx.node()
2330 mf = ctx.manifest()
2331 mf = ctx.manifest()
2331 if node == parent:
2332 if node == parent:
2332 pmf = mf
2333 pmf = mf
2333 else:
2334 else:
2334 pmf = None
2335 pmf = None
2335
2336
2336 # need all matching names in dirstate and manifest of target rev,
2337 # need all matching names in dirstate and manifest of target rev,
2337 # so have to walk both. do not print errors if files exist in one
2338 # so have to walk both. do not print errors if files exist in one
2338 # but not other.
2339 # but not other.
2339
2340
2340 names = {}
2341 names = {}
2341
2342
2342 wlock = repo.wlock()
2343 wlock = repo.wlock()
2343 try:
2344 try:
2344 # walk dirstate.
2345 # walk dirstate.
2345 files = []
2346 files = []
2346
2347
2347 m = cmdutil.match(repo, pats, opts)
2348 m = cmdutil.match(repo, pats, opts)
2348 m.bad = lambda x,y: False
2349 m.bad = lambda x,y: False
2349 for abs in repo.walk(m):
2350 for abs in repo.walk(m):
2350 names[abs] = m.rel(abs), m.exact(abs)
2351 names[abs] = m.rel(abs), m.exact(abs)
2351
2352
2352 # walk target manifest.
2353 # walk target manifest.
2353
2354
2354 def badfn(path, msg):
2355 def badfn(path, msg):
2355 if path in names:
2356 if path in names:
2356 return False
2357 return False
2357 path_ = path + '/'
2358 path_ = path + '/'
2358 for f in names:
2359 for f in names:
2359 if f.startswith(path_):
2360 if f.startswith(path_):
2360 return False
2361 return False
2361 repo.ui.warn("%s: %s\n" % (m.rel(path), msg))
2362 repo.ui.warn("%s: %s\n" % (m.rel(path), msg))
2362 return False
2363 return False
2363
2364
2364 m = cmdutil.match(repo, pats, opts)
2365 m = cmdutil.match(repo, pats, opts)
2365 m.bad = badfn
2366 m.bad = badfn
2366 for abs in repo[node].walk(m):
2367 for abs in repo[node].walk(m):
2367 if abs not in names:
2368 if abs not in names:
2368 names[abs] = m.rel(abs), m.exact(abs)
2369 names[abs] = m.rel(abs), m.exact(abs)
2369
2370
2370 m = cmdutil.matchfiles(repo, names)
2371 m = cmdutil.matchfiles(repo, names)
2371 changes = repo.status(match=m)[:4]
2372 changes = repo.status(match=m)[:4]
2372 modified, added, removed, deleted = map(dict.fromkeys, changes)
2373 modified, added, removed, deleted = map(dict.fromkeys, changes)
2373
2374
2374 # if f is a rename, also revert the source
2375 # if f is a rename, also revert the source
2375 cwd = repo.getcwd()
2376 cwd = repo.getcwd()
2376 for f in added:
2377 for f in added:
2377 src = repo.dirstate.copied(f)
2378 src = repo.dirstate.copied(f)
2378 if src and src not in names and repo.dirstate[src] == 'r':
2379 if src and src not in names and repo.dirstate[src] == 'r':
2379 removed[src] = None
2380 removed[src] = None
2380 names[src] = (repo.pathto(src, cwd), True)
2381 names[src] = (repo.pathto(src, cwd), True)
2381
2382
2382 def removeforget(abs):
2383 def removeforget(abs):
2383 if repo.dirstate[abs] == 'a':
2384 if repo.dirstate[abs] == 'a':
2384 return _('forgetting %s\n')
2385 return _('forgetting %s\n')
2385 return _('removing %s\n')
2386 return _('removing %s\n')
2386
2387
2387 revert = ([], _('reverting %s\n'))
2388 revert = ([], _('reverting %s\n'))
2388 add = ([], _('adding %s\n'))
2389 add = ([], _('adding %s\n'))
2389 remove = ([], removeforget)
2390 remove = ([], removeforget)
2390 undelete = ([], _('undeleting %s\n'))
2391 undelete = ([], _('undeleting %s\n'))
2391
2392
2392 disptable = (
2393 disptable = (
2393 # dispatch table:
2394 # dispatch table:
2394 # file state
2395 # file state
2395 # action if in target manifest
2396 # action if in target manifest
2396 # action if not in target manifest
2397 # action if not in target manifest
2397 # make backup if in target manifest
2398 # make backup if in target manifest
2398 # make backup if not in target manifest
2399 # make backup if not in target manifest
2399 (modified, revert, remove, True, True),
2400 (modified, revert, remove, True, True),
2400 (added, revert, remove, True, False),
2401 (added, revert, remove, True, False),
2401 (removed, undelete, None, False, False),
2402 (removed, undelete, None, False, False),
2402 (deleted, revert, remove, False, False),
2403 (deleted, revert, remove, False, False),
2403 )
2404 )
2404
2405
2405 for abs, (rel, exact) in util.sort(names.items()):
2406 for abs, (rel, exact) in util.sort(names.items()):
2406 mfentry = mf.get(abs)
2407 mfentry = mf.get(abs)
2407 target = repo.wjoin(abs)
2408 target = repo.wjoin(abs)
2408 def handle(xlist, dobackup):
2409 def handle(xlist, dobackup):
2409 xlist[0].append(abs)
2410 xlist[0].append(abs)
2410 if dobackup and not opts['no_backup'] and util.lexists(target):
2411 if dobackup and not opts['no_backup'] and util.lexists(target):
2411 bakname = "%s.orig" % rel
2412 bakname = "%s.orig" % rel
2412 ui.note(_('saving current version of %s as %s\n') %
2413 ui.note(_('saving current version of %s as %s\n') %
2413 (rel, bakname))
2414 (rel, bakname))
2414 if not opts.get('dry_run'):
2415 if not opts.get('dry_run'):
2415 util.copyfile(target, bakname)
2416 util.copyfile(target, bakname)
2416 if ui.verbose or not exact:
2417 if ui.verbose or not exact:
2417 msg = xlist[1]
2418 msg = xlist[1]
2418 if not isinstance(msg, basestring):
2419 if not isinstance(msg, basestring):
2419 msg = msg(abs)
2420 msg = msg(abs)
2420 ui.status(msg % rel)
2421 ui.status(msg % rel)
2421 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2422 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2422 if abs not in table: continue
2423 if abs not in table: continue
2423 # file has changed in dirstate
2424 # file has changed in dirstate
2424 if mfentry:
2425 if mfentry:
2425 handle(hitlist, backuphit)
2426 handle(hitlist, backuphit)
2426 elif misslist is not None:
2427 elif misslist is not None:
2427 handle(misslist, backupmiss)
2428 handle(misslist, backupmiss)
2428 break
2429 break
2429 else:
2430 else:
2430 if abs not in repo.dirstate:
2431 if abs not in repo.dirstate:
2431 if mfentry:
2432 if mfentry:
2432 handle(add, True)
2433 handle(add, True)
2433 elif exact:
2434 elif exact:
2434 ui.warn(_('file not managed: %s\n') % rel)
2435 ui.warn(_('file not managed: %s\n') % rel)
2435 continue
2436 continue
2436 # file has not changed in dirstate
2437 # file has not changed in dirstate
2437 if node == parent:
2438 if node == parent:
2438 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2439 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2439 continue
2440 continue
2440 if pmf is None:
2441 if pmf is None:
2441 # only need parent manifest in this unlikely case,
2442 # only need parent manifest in this unlikely case,
2442 # so do not read by default
2443 # so do not read by default
2443 pmf = repo[parent].manifest()
2444 pmf = repo[parent].manifest()
2444 if abs in pmf:
2445 if abs in pmf:
2445 if mfentry:
2446 if mfentry:
2446 # if version of file is same in parent and target
2447 # if version of file is same in parent and target
2447 # manifests, do nothing
2448 # manifests, do nothing
2448 if (pmf[abs] != mfentry or
2449 if (pmf[abs] != mfentry or
2449 pmf.flags(abs) != mf.flags(abs)):
2450 pmf.flags(abs) != mf.flags(abs)):
2450 handle(revert, False)
2451 handle(revert, False)
2451 else:
2452 else:
2452 handle(remove, False)
2453 handle(remove, False)
2453
2454
2454 if not opts.get('dry_run'):
2455 if not opts.get('dry_run'):
2455 def checkout(f):
2456 def checkout(f):
2456 fc = ctx[f]
2457 fc = ctx[f]
2457 repo.wwrite(f, fc.data(), fc.flags())
2458 repo.wwrite(f, fc.data(), fc.flags())
2458
2459
2459 audit_path = util.path_auditor(repo.root)
2460 audit_path = util.path_auditor(repo.root)
2460 for f in remove[0]:
2461 for f in remove[0]:
2461 if repo.dirstate[f] == 'a':
2462 if repo.dirstate[f] == 'a':
2462 repo.dirstate.forget(f)
2463 repo.dirstate.forget(f)
2463 continue
2464 continue
2464 audit_path(f)
2465 audit_path(f)
2465 try:
2466 try:
2466 util.unlink(repo.wjoin(f))
2467 util.unlink(repo.wjoin(f))
2467 except OSError:
2468 except OSError:
2468 pass
2469 pass
2469 repo.dirstate.remove(f)
2470 repo.dirstate.remove(f)
2470
2471
2471 normal = None
2472 normal = None
2472 if node == parent:
2473 if node == parent:
2473 # We're reverting to our parent. If possible, we'd like status
2474 # We're reverting to our parent. If possible, we'd like status
2474 # to report the file as clean. We have to use normallookup for
2475 # to report the file as clean. We have to use normallookup for
2475 # merges to avoid losing information about merged/dirty files.
2476 # merges to avoid losing information about merged/dirty files.
2476 if p2 != nullid:
2477 if p2 != nullid:
2477 normal = repo.dirstate.normallookup
2478 normal = repo.dirstate.normallookup
2478 else:
2479 else:
2479 normal = repo.dirstate.normal
2480 normal = repo.dirstate.normal
2480 for f in revert[0]:
2481 for f in revert[0]:
2481 checkout(f)
2482 checkout(f)
2482 if normal:
2483 if normal:
2483 normal(f)
2484 normal(f)
2484
2485
2485 for f in add[0]:
2486 for f in add[0]:
2486 checkout(f)
2487 checkout(f)
2487 repo.dirstate.add(f)
2488 repo.dirstate.add(f)
2488
2489
2489 normal = repo.dirstate.normallookup
2490 normal = repo.dirstate.normallookup
2490 if node == parent and p2 == nullid:
2491 if node == parent and p2 == nullid:
2491 normal = repo.dirstate.normal
2492 normal = repo.dirstate.normal
2492 for f in undelete[0]:
2493 for f in undelete[0]:
2493 checkout(f)
2494 checkout(f)
2494 normal(f)
2495 normal(f)
2495
2496
2496 finally:
2497 finally:
2497 del wlock
2498 del wlock
2498
2499
2499 def rollback(ui, repo):
2500 def rollback(ui, repo):
2500 """roll back the last transaction
2501 """roll back the last transaction
2501
2502
2502 This command should be used with care. There is only one level of
2503 This command should be used with care. There is only one level of
2503 rollback, and there is no way to undo a rollback. It will also
2504 rollback, and there is no way to undo a rollback. It will also
2504 restore the dirstate at the time of the last transaction, losing
2505 restore the dirstate at the time of the last transaction, losing
2505 any dirstate changes since that time.
2506 any dirstate changes since that time.
2506
2507
2507 Transactions are used to encapsulate the effects of all commands
2508 Transactions are used to encapsulate the effects of all commands
2508 that create new changesets or propagate existing changesets into a
2509 that create new changesets or propagate existing changesets into a
2509 repository. For example, the following commands are transactional,
2510 repository. For example, the following commands are transactional,
2510 and their effects can be rolled back:
2511 and their effects can be rolled back:
2511
2512
2512 commit
2513 commit
2513 import
2514 import
2514 pull
2515 pull
2515 push (with this repository as destination)
2516 push (with this repository as destination)
2516 unbundle
2517 unbundle
2517
2518
2518 This command is not intended for use on public repositories. Once
2519 This command is not intended for use on public repositories. Once
2519 changes are visible for pull by other users, rolling a transaction
2520 changes are visible for pull by other users, rolling a transaction
2520 back locally is ineffective (someone else may already have pulled
2521 back locally is ineffective (someone else may already have pulled
2521 the changes). Furthermore, a race is possible with readers of the
2522 the changes). Furthermore, a race is possible with readers of the
2522 repository; for example an in-progress pull from the repository
2523 repository; for example an in-progress pull from the repository
2523 may fail if a rollback is performed.
2524 may fail if a rollback is performed.
2524 """
2525 """
2525 repo.rollback()
2526 repo.rollback()
2526
2527
2527 def root(ui, repo):
2528 def root(ui, repo):
2528 """print the root (top) of the current working dir
2529 """print the root (top) of the current working dir
2529
2530
2530 Print the root directory of the current repository.
2531 Print the root directory of the current repository.
2531 """
2532 """
2532 ui.write(repo.root + "\n")
2533 ui.write(repo.root + "\n")
2533
2534
2534 def serve(ui, repo, **opts):
2535 def serve(ui, repo, **opts):
2535 """export the repository via HTTP
2536 """export the repository via HTTP
2536
2537
2537 Start a local HTTP repository browser and pull server.
2538 Start a local HTTP repository browser and pull server.
2538
2539
2539 By default, the server logs accesses to stdout and errors to
2540 By default, the server logs accesses to stdout and errors to
2540 stderr. Use the "-A" and "-E" options to log to files.
2541 stderr. Use the "-A" and "-E" options to log to files.
2541 """
2542 """
2542
2543
2543 if opts["stdio"]:
2544 if opts["stdio"]:
2544 if repo is None:
2545 if repo is None:
2545 raise RepoError(_("There is no Mercurial repository here"
2546 raise RepoError(_("There is no Mercurial repository here"
2546 " (.hg not found)"))
2547 " (.hg not found)"))
2547 s = sshserver.sshserver(ui, repo)
2548 s = sshserver.sshserver(ui, repo)
2548 s.serve_forever()
2549 s.serve_forever()
2549
2550
2550 parentui = ui.parentui or ui
2551 parentui = ui.parentui or ui
2551 optlist = ("name templates style address port prefix ipv6"
2552 optlist = ("name templates style address port prefix ipv6"
2552 " accesslog errorlog webdir_conf certificate")
2553 " accesslog errorlog webdir_conf certificate")
2553 for o in optlist.split():
2554 for o in optlist.split():
2554 if opts[o]:
2555 if opts[o]:
2555 parentui.setconfig("web", o, str(opts[o]))
2556 parentui.setconfig("web", o, str(opts[o]))
2556 if (repo is not None) and (repo.ui != parentui):
2557 if (repo is not None) and (repo.ui != parentui):
2557 repo.ui.setconfig("web", o, str(opts[o]))
2558 repo.ui.setconfig("web", o, str(opts[o]))
2558
2559
2559 if repo is None and not ui.config("web", "webdir_conf"):
2560 if repo is None and not ui.config("web", "webdir_conf"):
2560 raise RepoError(_("There is no Mercurial repository here"
2561 raise RepoError(_("There is no Mercurial repository here"
2561 " (.hg not found)"))
2562 " (.hg not found)"))
2562
2563
2563 class service:
2564 class service:
2564 def init(self):
2565 def init(self):
2565 util.set_signal_handler()
2566 util.set_signal_handler()
2566 self.httpd = hgweb.server.create_server(parentui, repo)
2567 self.httpd = hgweb.server.create_server(parentui, repo)
2567
2568
2568 if not ui.verbose: return
2569 if not ui.verbose: return
2569
2570
2570 if self.httpd.prefix:
2571 if self.httpd.prefix:
2571 prefix = self.httpd.prefix.strip('/') + '/'
2572 prefix = self.httpd.prefix.strip('/') + '/'
2572 else:
2573 else:
2573 prefix = ''
2574 prefix = ''
2574
2575
2575 port = ':%d' % self.httpd.port
2576 port = ':%d' % self.httpd.port
2576 if port == ':80':
2577 if port == ':80':
2577 port = ''
2578 port = ''
2578
2579
2579 bindaddr = self.httpd.addr
2580 bindaddr = self.httpd.addr
2580 if bindaddr == '0.0.0.0':
2581 if bindaddr == '0.0.0.0':
2581 bindaddr = '*'
2582 bindaddr = '*'
2582 elif ':' in bindaddr: # IPv6
2583 elif ':' in bindaddr: # IPv6
2583 bindaddr = '[%s]' % bindaddr
2584 bindaddr = '[%s]' % bindaddr
2584
2585
2585 fqaddr = self.httpd.fqaddr
2586 fqaddr = self.httpd.fqaddr
2586 if ':' in fqaddr:
2587 if ':' in fqaddr:
2587 fqaddr = '[%s]' % fqaddr
2588 fqaddr = '[%s]' % fqaddr
2588 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2589 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2589 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2590 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2590
2591
2591 def run(self):
2592 def run(self):
2592 self.httpd.serve_forever()
2593 self.httpd.serve_forever()
2593
2594
2594 service = service()
2595 service = service()
2595
2596
2596 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2597 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2597
2598
2598 def status(ui, repo, *pats, **opts):
2599 def status(ui, repo, *pats, **opts):
2599 """show changed files in the working directory
2600 """show changed files in the working directory
2600
2601
2601 Show status of files in the repository. If names are given, only
2602 Show status of files in the repository. If names are given, only
2602 files that match are shown. Files that are clean or ignored or
2603 files that match are shown. Files that are clean or ignored or
2603 source of a copy/move operation, are not listed unless -c (clean),
2604 source of a copy/move operation, are not listed unless -c (clean),
2604 -i (ignored), -C (copies) or -A is given. Unless options described
2605 -i (ignored), -C (copies) or -A is given. Unless options described
2605 with "show only ..." are given, the options -mardu are used.
2606 with "show only ..." are given, the options -mardu are used.
2606
2607
2607 Option -q/--quiet hides untracked (unknown and ignored) files
2608 Option -q/--quiet hides untracked (unknown and ignored) files
2608 unless explicitly requested with -u/--unknown or -i/-ignored.
2609 unless explicitly requested with -u/--unknown or -i/-ignored.
2609
2610
2610 NOTE: status may appear to disagree with diff if permissions have
2611 NOTE: status may appear to disagree with diff if permissions have
2611 changed or a merge has occurred. The standard diff format does not
2612 changed or a merge has occurred. The standard diff format does not
2612 report permission changes and diff only reports changes relative
2613 report permission changes and diff only reports changes relative
2613 to one merge parent.
2614 to one merge parent.
2614
2615
2615 If one revision is given, it is used as the base revision.
2616 If one revision is given, it is used as the base revision.
2616 If two revisions are given, the difference between them is shown.
2617 If two revisions are given, the difference between them is shown.
2617
2618
2618 The codes used to show the status of files are:
2619 The codes used to show the status of files are:
2619 M = modified
2620 M = modified
2620 A = added
2621 A = added
2621 R = removed
2622 R = removed
2622 C = clean
2623 C = clean
2623 ! = deleted, but still tracked
2624 ! = deleted, but still tracked
2624 ? = not tracked
2625 ? = not tracked
2625 I = ignored
2626 I = ignored
2626 = the previous added file was copied from here
2627 = the previous added file was copied from here
2627 """
2628 """
2628
2629
2629 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2630 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2630 cwd = (pats and repo.getcwd()) or ''
2631 cwd = (pats and repo.getcwd()) or ''
2631 end = opts['print0'] and '\0' or '\n'
2632 end = opts['print0'] and '\0' or '\n'
2632 copy = {}
2633 copy = {}
2633 states = 'modified added removed deleted unknown ignored clean'.split()
2634 states = 'modified added removed deleted unknown ignored clean'.split()
2634 show = [k for k in states if opts[k]]
2635 show = [k for k in states if opts[k]]
2635 if opts['all']:
2636 if opts['all']:
2636 show += ui.quiet and (states[:4] + ['clean']) or states
2637 show += ui.quiet and (states[:4] + ['clean']) or states
2637 if not show:
2638 if not show:
2638 show = ui.quiet and states[:4] or states[:5]
2639 show = ui.quiet and states[:4] or states[:5]
2639
2640
2640 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2641 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2641 'ignored' in show, 'clean' in show, 'unknown' in show)
2642 'ignored' in show, 'clean' in show, 'unknown' in show)
2642 changestates = zip(states, 'MAR!?IC', stat)
2643 changestates = zip(states, 'MAR!?IC', stat)
2643
2644
2644 if (opts['all'] or opts['copies']) and not opts['no_status']:
2645 if (opts['all'] or opts['copies']) and not opts['no_status']:
2645 ctxn = repo[nullid]
2646 ctxn = repo[nullid]
2646 ctx1 = repo[node1]
2647 ctx1 = repo[node1]
2647 ctx2 = repo[node2]
2648 ctx2 = repo[node2]
2648 added = stat[1]
2649 added = stat[1]
2649 if node2 is None:
2650 if node2 is None:
2650 added = stat[0] + stat[1] # merged?
2651 added = stat[0] + stat[1] # merged?
2651
2652
2652 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].items():
2653 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].items():
2653 if k in added:
2654 if k in added:
2654 copy[k] = v
2655 copy[k] = v
2655 elif v in added:
2656 elif v in added:
2656 copy[v] = k
2657 copy[v] = k
2657
2658
2658 for state, char, files in changestates:
2659 for state, char, files in changestates:
2659 if state in show:
2660 if state in show:
2660 format = "%s %%s%s" % (char, end)
2661 format = "%s %%s%s" % (char, end)
2661 if opts['no_status']:
2662 if opts['no_status']:
2662 format = "%%s%s" % end
2663 format = "%%s%s" % end
2663
2664
2664 for f in files:
2665 for f in files:
2665 ui.write(format % repo.pathto(f, cwd))
2666 ui.write(format % repo.pathto(f, cwd))
2666 if f in copy:
2667 if f in copy:
2667 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2668 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2668
2669
2669 def tag(ui, repo, name1, *names, **opts):
2670 def tag(ui, repo, name1, *names, **opts):
2670 """add one or more tags for the current or given revision
2671 """add one or more tags for the current or given revision
2671
2672
2672 Name a particular revision using <name>.
2673 Name a particular revision using <name>.
2673
2674
2674 Tags are used to name particular revisions of the repository and are
2675 Tags are used to name particular revisions of the repository and are
2675 very useful to compare different revisions, to go back to significant
2676 very useful to compare different revisions, to go back to significant
2676 earlier versions or to mark branch points as releases, etc.
2677 earlier versions or to mark branch points as releases, etc.
2677
2678
2678 If no revision is given, the parent of the working directory is used,
2679 If no revision is given, the parent of the working directory is used,
2679 or tip if no revision is checked out.
2680 or tip if no revision is checked out.
2680
2681
2681 To facilitate version control, distribution, and merging of tags,
2682 To facilitate version control, distribution, and merging of tags,
2682 they are stored as a file named ".hgtags" which is managed
2683 they are stored as a file named ".hgtags" which is managed
2683 similarly to other project files and can be hand-edited if
2684 similarly to other project files and can be hand-edited if
2684 necessary. The file '.hg/localtags' is used for local tags (not
2685 necessary. The file '.hg/localtags' is used for local tags (not
2685 shared among repositories).
2686 shared among repositories).
2686
2687
2687 See 'hg help dates' for a list of formats valid for -d/--date.
2688 See 'hg help dates' for a list of formats valid for -d/--date.
2688 """
2689 """
2689
2690
2690 rev_ = "."
2691 rev_ = "."
2691 names = (name1,) + names
2692 names = (name1,) + names
2692 if len(names) != len(dict.fromkeys(names)):
2693 if len(names) != len(dict.fromkeys(names)):
2693 raise util.Abort(_('tag names must be unique'))
2694 raise util.Abort(_('tag names must be unique'))
2694 for n in names:
2695 for n in names:
2695 if n in ['tip', '.', 'null']:
2696 if n in ['tip', '.', 'null']:
2696 raise util.Abort(_('the name \'%s\' is reserved') % n)
2697 raise util.Abort(_('the name \'%s\' is reserved') % n)
2697 if opts['rev'] and opts['remove']:
2698 if opts['rev'] and opts['remove']:
2698 raise util.Abort(_("--rev and --remove are incompatible"))
2699 raise util.Abort(_("--rev and --remove are incompatible"))
2699 if opts['rev']:
2700 if opts['rev']:
2700 rev_ = opts['rev']
2701 rev_ = opts['rev']
2701 message = opts['message']
2702 message = opts['message']
2702 if opts['remove']:
2703 if opts['remove']:
2703 expectedtype = opts['local'] and 'local' or 'global'
2704 expectedtype = opts['local'] and 'local' or 'global'
2704 for n in names:
2705 for n in names:
2705 if not repo.tagtype(n):
2706 if not repo.tagtype(n):
2706 raise util.Abort(_('tag \'%s\' does not exist') % n)
2707 raise util.Abort(_('tag \'%s\' does not exist') % n)
2707 if repo.tagtype(n) != expectedtype:
2708 if repo.tagtype(n) != expectedtype:
2708 raise util.Abort(_('tag \'%s\' is not a %s tag') %
2709 raise util.Abort(_('tag \'%s\' is not a %s tag') %
2709 (n, expectedtype))
2710 (n, expectedtype))
2710 rev_ = nullid
2711 rev_ = nullid
2711 if not message:
2712 if not message:
2712 message = _('Removed tag %s') % ', '.join(names)
2713 message = _('Removed tag %s') % ', '.join(names)
2713 elif not opts['force']:
2714 elif not opts['force']:
2714 for n in names:
2715 for n in names:
2715 if n in repo.tags():
2716 if n in repo.tags():
2716 raise util.Abort(_('tag \'%s\' already exists '
2717 raise util.Abort(_('tag \'%s\' already exists '
2717 '(use -f to force)') % n)
2718 '(use -f to force)') % n)
2718 if not rev_ and repo.dirstate.parents()[1] != nullid:
2719 if not rev_ and repo.dirstate.parents()[1] != nullid:
2719 raise util.Abort(_('uncommitted merge - please provide a '
2720 raise util.Abort(_('uncommitted merge - please provide a '
2720 'specific revision'))
2721 'specific revision'))
2721 r = repo[rev_].node()
2722 r = repo[rev_].node()
2722
2723
2723 if not message:
2724 if not message:
2724 message = (_('Added tag %s for changeset %s') %
2725 message = (_('Added tag %s for changeset %s') %
2725 (', '.join(names), short(r)))
2726 (', '.join(names), short(r)))
2726
2727
2727 date = opts.get('date')
2728 date = opts.get('date')
2728 if date:
2729 if date:
2729 date = util.parsedate(date)
2730 date = util.parsedate(date)
2730
2731
2731 repo.tag(names, r, message, opts['local'], opts['user'], date)
2732 repo.tag(names, r, message, opts['local'], opts['user'], date)
2732
2733
2733 def tags(ui, repo):
2734 def tags(ui, repo):
2734 """list repository tags
2735 """list repository tags
2735
2736
2736 List the repository tags.
2737 List the repository tags.
2737
2738
2738 This lists both regular and local tags. When the -v/--verbose switch
2739 This lists both regular and local tags. When the -v/--verbose switch
2739 is used, a third column "local" is printed for local tags.
2740 is used, a third column "local" is printed for local tags.
2740 """
2741 """
2741
2742
2742 l = repo.tagslist()
2743 l = repo.tagslist()
2743 l.reverse()
2744 l.reverse()
2744 hexfunc = ui.debugflag and hex or short
2745 hexfunc = ui.debugflag and hex or short
2745 tagtype = ""
2746 tagtype = ""
2746
2747
2747 for t, n in l:
2748 for t, n in l:
2748 if ui.quiet:
2749 if ui.quiet:
2749 ui.write("%s\n" % t)
2750 ui.write("%s\n" % t)
2750 continue
2751 continue
2751
2752
2752 try:
2753 try:
2753 hn = hexfunc(n)
2754 hn = hexfunc(n)
2754 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2755 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2755 except revlog.LookupError:
2756 except revlog.LookupError:
2756 r = " ?:%s" % hn
2757 r = " ?:%s" % hn
2757 else:
2758 else:
2758 spaces = " " * (30 - util.locallen(t))
2759 spaces = " " * (30 - util.locallen(t))
2759 if ui.verbose:
2760 if ui.verbose:
2760 if repo.tagtype(t) == 'local':
2761 if repo.tagtype(t) == 'local':
2761 tagtype = " local"
2762 tagtype = " local"
2762 else:
2763 else:
2763 tagtype = ""
2764 tagtype = ""
2764 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2765 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2765
2766
2766 def tip(ui, repo, **opts):
2767 def tip(ui, repo, **opts):
2767 """show the tip revision
2768 """show the tip revision
2768
2769
2769 The tip revision (usually just called the tip) is the most
2770 The tip revision (usually just called the tip) is the most
2770 recently added changeset in the repository, the most recently
2771 recently added changeset in the repository, the most recently
2771 changed head.
2772 changed head.
2772
2773
2773 If you have just made a commit, that commit will be the tip. If
2774 If you have just made a commit, that commit will be the tip. If
2774 you have just pulled changes from another repository, the tip of
2775 you have just pulled changes from another repository, the tip of
2775 that repository becomes the current tip. The "tip" tag is special
2776 that repository becomes the current tip. The "tip" tag is special
2776 and cannot be renamed or assigned to a different changeset.
2777 and cannot be renamed or assigned to a different changeset.
2777 """
2778 """
2778 cmdutil.show_changeset(ui, repo, opts).show(len(repo) - 1)
2779 cmdutil.show_changeset(ui, repo, opts).show(len(repo) - 1)
2779
2780
2780 def unbundle(ui, repo, fname1, *fnames, **opts):
2781 def unbundle(ui, repo, fname1, *fnames, **opts):
2781 """apply one or more changegroup files
2782 """apply one or more changegroup files
2782
2783
2783 Apply one or more compressed changegroup files generated by the
2784 Apply one or more compressed changegroup files generated by the
2784 bundle command.
2785 bundle command.
2785 """
2786 """
2786 fnames = (fname1,) + fnames
2787 fnames = (fname1,) + fnames
2787
2788
2788 lock = None
2789 lock = None
2789 try:
2790 try:
2790 lock = repo.lock()
2791 lock = repo.lock()
2791 for fname in fnames:
2792 for fname in fnames:
2792 if os.path.exists(fname):
2793 if os.path.exists(fname):
2793 f = open(fname, "rb")
2794 f = open(fname, "rb")
2794 else:
2795 else:
2795 f = urllib.urlopen(fname)
2796 f = urllib.urlopen(fname)
2796 gen = changegroup.readbundle(f, fname)
2797 gen = changegroup.readbundle(f, fname)
2797 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2798 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2798 finally:
2799 finally:
2799 del lock
2800 del lock
2800
2801
2801 return postincoming(ui, repo, modheads, opts['update'], None)
2802 return postincoming(ui, repo, modheads, opts['update'], None)
2802
2803
2803 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2804 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2804 """update working directory
2805 """update working directory
2805
2806
2806 Update the repository's working directory to the specified revision,
2807 Update the repository's working directory to the specified revision,
2807 or the tip of the current branch if none is specified.
2808 or the tip of the current branch if none is specified.
2808
2809
2809 If the requested revision is a descendant of the working
2810 If the requested revision is a descendant of the working
2810 directory, any outstanding changes in the working directory will
2811 directory, any outstanding changes in the working directory will
2811 be merged into the result. If it is not directly descended but is
2812 be merged into the result. If it is not directly descended but is
2812 on the same named branch, update aborts with a suggestion to use
2813 on the same named branch, update aborts with a suggestion to use
2813 merge or update -C instead.
2814 merge or update -C instead.
2814
2815
2815 If the requested revision is on a different named branch and the
2816 If the requested revision is on a different named branch and the
2816 working directory is clean, update quietly switches branches.
2817 working directory is clean, update quietly switches branches.
2817
2818
2818 If you want to update just one file to an older revision, use revert.
2819 If you want to update just one file to an older revision, use revert.
2819
2820
2820 See 'hg help dates' for a list of formats valid for --date.
2821 See 'hg help dates' for a list of formats valid for --date.
2821 """
2822 """
2822 if rev and node:
2823 if rev and node:
2823 raise util.Abort(_("please specify just one revision"))
2824 raise util.Abort(_("please specify just one revision"))
2824
2825
2825 if not rev:
2826 if not rev:
2826 rev = node
2827 rev = node
2827
2828
2828 if date:
2829 if date:
2829 if rev:
2830 if rev:
2830 raise util.Abort(_("you can't specify a revision and a date"))
2831 raise util.Abort(_("you can't specify a revision and a date"))
2831 rev = cmdutil.finddate(ui, repo, date)
2832 rev = cmdutil.finddate(ui, repo, date)
2832
2833
2833 if clean:
2834 if clean:
2834 return hg.clean(repo, rev)
2835 return hg.clean(repo, rev)
2835 else:
2836 else:
2836 return hg.update(repo, rev)
2837 return hg.update(repo, rev)
2837
2838
2838 def verify(ui, repo):
2839 def verify(ui, repo):
2839 """verify the integrity of the repository
2840 """verify the integrity of the repository
2840
2841
2841 Verify the integrity of the current repository.
2842 Verify the integrity of the current repository.
2842
2843
2843 This will perform an extensive check of the repository's
2844 This will perform an extensive check of the repository's
2844 integrity, validating the hashes and checksums of each entry in
2845 integrity, validating the hashes and checksums of each entry in
2845 the changelog, manifest, and tracked files, as well as the
2846 the changelog, manifest, and tracked files, as well as the
2846 integrity of their crosslinks and indices.
2847 integrity of their crosslinks and indices.
2847 """
2848 """
2848 return hg.verify(repo)
2849 return hg.verify(repo)
2849
2850
2850 def version_(ui):
2851 def version_(ui):
2851 """output version and copyright information"""
2852 """output version and copyright information"""
2852 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2853 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2853 % version.get_version())
2854 % version.get_version())
2854 ui.status(_(
2855 ui.status(_(
2855 "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
2856 "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
2856 "This is free software; see the source for copying conditions. "
2857 "This is free software; see the source for copying conditions. "
2857 "There is NO\nwarranty; "
2858 "There is NO\nwarranty; "
2858 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2859 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2859 ))
2860 ))
2860
2861
2861 # Command options and aliases are listed here, alphabetically
2862 # Command options and aliases are listed here, alphabetically
2862
2863
2863 globalopts = [
2864 globalopts = [
2864 ('R', 'repository', '',
2865 ('R', 'repository', '',
2865 _('repository root directory or symbolic path name')),
2866 _('repository root directory or symbolic path name')),
2866 ('', 'cwd', '', _('change working directory')),
2867 ('', 'cwd', '', _('change working directory')),
2867 ('y', 'noninteractive', None,
2868 ('y', 'noninteractive', None,
2868 _('do not prompt, assume \'yes\' for any required answers')),
2869 _('do not prompt, assume \'yes\' for any required answers')),
2869 ('q', 'quiet', None, _('suppress output')),
2870 ('q', 'quiet', None, _('suppress output')),
2870 ('v', 'verbose', None, _('enable additional output')),
2871 ('v', 'verbose', None, _('enable additional output')),
2871 ('', 'config', [], _('set/override config option')),
2872 ('', 'config', [], _('set/override config option')),
2872 ('', 'debug', None, _('enable debugging output')),
2873 ('', 'debug', None, _('enable debugging output')),
2873 ('', 'debugger', None, _('start debugger')),
2874 ('', 'debugger', None, _('start debugger')),
2874 ('', 'encoding', util._encoding, _('set the charset encoding')),
2875 ('', 'encoding', util._encoding, _('set the charset encoding')),
2875 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2876 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2876 ('', 'lsprof', None, _('print improved command execution profile')),
2877 ('', 'lsprof', None, _('print improved command execution profile')),
2877 ('', 'traceback', None, _('print traceback on exception')),
2878 ('', 'traceback', None, _('print traceback on exception')),
2878 ('', 'time', None, _('time how long the command takes')),
2879 ('', 'time', None, _('time how long the command takes')),
2879 ('', 'profile', None, _('print command execution profile')),
2880 ('', 'profile', None, _('print command execution profile')),
2880 ('', 'version', None, _('output version information and exit')),
2881 ('', 'version', None, _('output version information and exit')),
2881 ('h', 'help', None, _('display help and exit')),
2882 ('h', 'help', None, _('display help and exit')),
2882 ]
2883 ]
2883
2884
2884 dryrunopts = [('n', 'dry-run', None,
2885 dryrunopts = [('n', 'dry-run', None,
2885 _('do not perform actions, just print output'))]
2886 _('do not perform actions, just print output'))]
2886
2887
2887 remoteopts = [
2888 remoteopts = [
2888 ('e', 'ssh', '', _('specify ssh command to use')),
2889 ('e', 'ssh', '', _('specify ssh command to use')),
2889 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2890 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2890 ]
2891 ]
2891
2892
2892 walkopts = [
2893 walkopts = [
2893 ('I', 'include', [], _('include names matching the given patterns')),
2894 ('I', 'include', [], _('include names matching the given patterns')),
2894 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2895 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2895 ]
2896 ]
2896
2897
2897 commitopts = [
2898 commitopts = [
2898 ('m', 'message', '', _('use <text> as commit message')),
2899 ('m', 'message', '', _('use <text> as commit message')),
2899 ('l', 'logfile', '', _('read commit message from <file>')),
2900 ('l', 'logfile', '', _('read commit message from <file>')),
2900 ]
2901 ]
2901
2902
2902 commitopts2 = [
2903 commitopts2 = [
2903 ('d', 'date', '', _('record datecode as commit date')),
2904 ('d', 'date', '', _('record datecode as commit date')),
2904 ('u', 'user', '', _('record user as committer')),
2905 ('u', 'user', '', _('record user as committer')),
2905 ]
2906 ]
2906
2907
2907 templateopts = [
2908 templateopts = [
2908 ('', 'style', '', _('display using template map file')),
2909 ('', 'style', '', _('display using template map file')),
2909 ('', 'template', '', _('display with template')),
2910 ('', 'template', '', _('display with template')),
2910 ]
2911 ]
2911
2912
2912 logopts = [
2913 logopts = [
2913 ('p', 'patch', None, _('show patch')),
2914 ('p', 'patch', None, _('show patch')),
2914 ('l', 'limit', '', _('limit number of changes displayed')),
2915 ('l', 'limit', '', _('limit number of changes displayed')),
2915 ('M', 'no-merges', None, _('do not show merges')),
2916 ('M', 'no-merges', None, _('do not show merges')),
2916 ] + templateopts
2917 ] + templateopts
2917
2918
2918 diffopts = [
2919 diffopts = [
2919 ('a', 'text', None, _('treat all files as text')),
2920 ('a', 'text', None, _('treat all files as text')),
2920 ('g', 'git', None, _('use git extended diff format')),
2921 ('g', 'git', None, _('use git extended diff format')),
2921 ('', 'nodates', None, _("don't include dates in diff headers"))
2922 ('', 'nodates', None, _("don't include dates in diff headers"))
2922 ]
2923 ]
2923
2924
2924 diffopts2 = [
2925 diffopts2 = [
2925 ('p', 'show-function', None, _('show which function each change is in')),
2926 ('p', 'show-function', None, _('show which function each change is in')),
2926 ('w', 'ignore-all-space', None,
2927 ('w', 'ignore-all-space', None,
2927 _('ignore white space when comparing lines')),
2928 _('ignore white space when comparing lines')),
2928 ('b', 'ignore-space-change', None,
2929 ('b', 'ignore-space-change', None,
2929 _('ignore changes in the amount of white space')),
2930 _('ignore changes in the amount of white space')),
2930 ('B', 'ignore-blank-lines', None,
2931 ('B', 'ignore-blank-lines', None,
2931 _('ignore changes whose lines are all blank')),
2932 _('ignore changes whose lines are all blank')),
2932 ('U', 'unified', '', _('number of lines of context to show'))
2933 ('U', 'unified', '', _('number of lines of context to show'))
2933 ]
2934 ]
2934
2935
2935 table = {
2936 table = {
2936 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2937 "^add": (add, walkopts + dryrunopts, _('hg add [OPTION]... [FILE]...')),
2937 "addremove":
2938 "addremove":
2938 (addremove,
2939 (addremove,
2939 [('s', 'similarity', '',
2940 [('s', 'similarity', '',
2940 _('guess renamed files by similarity (0<=s<=100)')),
2941 _('guess renamed files by similarity (0<=s<=100)')),
2941 ] + walkopts + dryrunopts,
2942 ] + walkopts + dryrunopts,
2942 _('hg addremove [OPTION]... [FILE]...')),
2943 _('hg addremove [OPTION]... [FILE]...')),
2943 "^annotate|blame":
2944 "^annotate|blame":
2944 (annotate,
2945 (annotate,
2945 [('r', 'rev', '', _('annotate the specified revision')),
2946 [('r', 'rev', '', _('annotate the specified revision')),
2946 ('f', 'follow', None, _('follow file copies and renames')),
2947 ('f', 'follow', None, _('follow file copies and renames')),
2947 ('a', 'text', None, _('treat all files as text')),
2948 ('a', 'text', None, _('treat all files as text')),
2948 ('u', 'user', None, _('list the author (long with -v)')),
2949 ('u', 'user', None, _('list the author (long with -v)')),
2949 ('d', 'date', None, _('list the date (short with -q)')),
2950 ('d', 'date', None, _('list the date (short with -q)')),
2950 ('n', 'number', None, _('list the revision number (default)')),
2951 ('n', 'number', None, _('list the revision number (default)')),
2951 ('c', 'changeset', None, _('list the changeset')),
2952 ('c', 'changeset', None, _('list the changeset')),
2952 ('l', 'line-number', None,
2953 ('l', 'line-number', None,
2953 _('show line number at the first appearance'))
2954 _('show line number at the first appearance'))
2954 ] + walkopts,
2955 ] + walkopts,
2955 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2956 _('hg annotate [-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
2956 "archive":
2957 "archive":
2957 (archive,
2958 (archive,
2958 [('', 'no-decode', None, _('do not pass files through decoders')),
2959 [('', 'no-decode', None, _('do not pass files through decoders')),
2959 ('p', 'prefix', '', _('directory prefix for files in archive')),
2960 ('p', 'prefix', '', _('directory prefix for files in archive')),
2960 ('r', 'rev', '', _('revision to distribute')),
2961 ('r', 'rev', '', _('revision to distribute')),
2961 ('t', 'type', '', _('type of distribution to create')),
2962 ('t', 'type', '', _('type of distribution to create')),
2962 ] + walkopts,
2963 ] + walkopts,
2963 _('hg archive [OPTION]... DEST')),
2964 _('hg archive [OPTION]... DEST')),
2964 "backout":
2965 "backout":
2965 (backout,
2966 (backout,
2966 [('', 'merge', None,
2967 [('', 'merge', None,
2967 _('merge with old dirstate parent after backout')),
2968 _('merge with old dirstate parent after backout')),
2968 ('', 'parent', '', _('parent to choose when backing out merge')),
2969 ('', 'parent', '', _('parent to choose when backing out merge')),
2969 ('r', 'rev', '', _('revision to backout')),
2970 ('r', 'rev', '', _('revision to backout')),
2970 ] + walkopts + commitopts + commitopts2,
2971 ] + walkopts + commitopts + commitopts2,
2971 _('hg backout [OPTION]... [-r] REV')),
2972 _('hg backout [OPTION]... [-r] REV')),
2972 "bisect":
2973 "bisect":
2973 (bisect,
2974 (bisect,
2974 [('r', 'reset', False, _('reset bisect state')),
2975 [('r', 'reset', False, _('reset bisect state')),
2975 ('g', 'good', False, _('mark changeset good')),
2976 ('g', 'good', False, _('mark changeset good')),
2976 ('b', 'bad', False, _('mark changeset bad')),
2977 ('b', 'bad', False, _('mark changeset bad')),
2977 ('s', 'skip', False, _('skip testing changeset')),
2978 ('s', 'skip', False, _('skip testing changeset')),
2978 ('U', 'noupdate', False, _('do not update to target'))],
2979 ('U', 'noupdate', False, _('do not update to target'))],
2979 _("hg bisect [-gbsr] [REV]")),
2980 _("hg bisect [-gbsr] [REV]")),
2980 "branch":
2981 "branch":
2981 (branch,
2982 (branch,
2982 [('f', 'force', None,
2983 [('f', 'force', None,
2983 _('set branch name even if it shadows an existing branch'))],
2984 _('set branch name even if it shadows an existing branch'))],
2984 _('hg branch [-f] [NAME]')),
2985 _('hg branch [-f] [NAME]')),
2985 "branches":
2986 "branches":
2986 (branches,
2987 (branches,
2987 [('a', 'active', False,
2988 [('a', 'active', False,
2988 _('show only branches that have unmerged heads'))],
2989 _('show only branches that have unmerged heads'))],
2989 _('hg branches [-a]')),
2990 _('hg branches [-a]')),
2990 "bundle":
2991 "bundle":
2991 (bundle,
2992 (bundle,
2992 [('f', 'force', None,
2993 [('f', 'force', None,
2993 _('run even when remote repository is unrelated')),
2994 _('run even when remote repository is unrelated')),
2994 ('r', 'rev', [],
2995 ('r', 'rev', [],
2995 _('a changeset up to which you would like to bundle')),
2996 _('a changeset up to which you would like to bundle')),
2996 ('', 'base', [],
2997 ('', 'base', [],
2997 _('a base changeset to specify instead of a destination')),
2998 _('a base changeset to specify instead of a destination')),
2998 ('a', 'all', None, _('bundle all changesets in the repository')),
2999 ('a', 'all', None, _('bundle all changesets in the repository')),
2999 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3000 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3000 ] + remoteopts,
3001 ] + remoteopts,
3001 _('hg bundle [-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3002 _('hg bundle [-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3002 "cat":
3003 "cat":
3003 (cat,
3004 (cat,
3004 [('o', 'output', '', _('print output to file with formatted name')),
3005 [('o', 'output', '', _('print output to file with formatted name')),
3005 ('r', 'rev', '', _('print the given revision')),
3006 ('r', 'rev', '', _('print the given revision')),
3006 ('', 'decode', None, _('apply any matching decode filter')),
3007 ('', 'decode', None, _('apply any matching decode filter')),
3007 ] + walkopts,
3008 ] + walkopts,
3008 _('hg cat [OPTION]... FILE...')),
3009 _('hg cat [OPTION]... FILE...')),
3009 "^clone":
3010 "^clone":
3010 (clone,
3011 (clone,
3011 [('U', 'noupdate', None,
3012 [('U', 'noupdate', None,
3012 _('the clone will only contain a repository (no working copy)')),
3013 _('the clone will only contain a repository (no working copy)')),
3013 ('r', 'rev', [],
3014 ('r', 'rev', [],
3014 _('a changeset you would like to have after cloning')),
3015 _('a changeset you would like to have after cloning')),
3015 ('', 'pull', None, _('use pull protocol to copy metadata')),
3016 ('', 'pull', None, _('use pull protocol to copy metadata')),
3016 ('', 'uncompressed', None,
3017 ('', 'uncompressed', None,
3017 _('use uncompressed transfer (fast over LAN)')),
3018 _('use uncompressed transfer (fast over LAN)')),
3018 ] + remoteopts,
3019 ] + remoteopts,
3019 _('hg clone [OPTION]... SOURCE [DEST]')),
3020 _('hg clone [OPTION]... SOURCE [DEST]')),
3020 "^commit|ci":
3021 "^commit|ci":
3021 (commit,
3022 (commit,
3022 [('A', 'addremove', None,
3023 [('A', 'addremove', None,
3023 _('mark new/missing files as added/removed before committing')),
3024 _('mark new/missing files as added/removed before committing')),
3024 ] + walkopts + commitopts + commitopts2,
3025 ] + walkopts + commitopts + commitopts2,
3025 _('hg commit [OPTION]... [FILE]...')),
3026 _('hg commit [OPTION]... [FILE]...')),
3026 "copy|cp":
3027 "copy|cp":
3027 (copy,
3028 (copy,
3028 [('A', 'after', None, _('record a copy that has already occurred')),
3029 [('A', 'after', None, _('record a copy that has already occurred')),
3029 ('f', 'force', None,
3030 ('f', 'force', None,
3030 _('forcibly copy over an existing managed file')),
3031 _('forcibly copy over an existing managed file')),
3031 ] + walkopts + dryrunopts,
3032 ] + walkopts + dryrunopts,
3032 _('hg copy [OPTION]... [SOURCE]... DEST')),
3033 _('hg copy [OPTION]... [SOURCE]... DEST')),
3033 "debugancestor": (debugancestor, [],
3034 "debugancestor": (debugancestor, [],
3034 _('hg debugancestor [INDEX] REV1 REV2')),
3035 _('hg debugancestor [INDEX] REV1 REV2')),
3035 "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
3036 "debugcheckstate": (debugcheckstate, [], _('hg debugcheckstate')),
3036 "debugcomplete":
3037 "debugcomplete":
3037 (debugcomplete,
3038 (debugcomplete,
3038 [('o', 'options', None, _('show the command options'))],
3039 [('o', 'options', None, _('show the command options'))],
3039 _('hg debugcomplete [-o] CMD')),
3040 _('hg debugcomplete [-o] CMD')),
3040 "debugdate":
3041 "debugdate":
3041 (debugdate,
3042 (debugdate,
3042 [('e', 'extended', None, _('try extended date formats'))],
3043 [('e', 'extended', None, _('try extended date formats'))],
3043 _('hg debugdate [-e] DATE [RANGE]')),
3044 _('hg debugdate [-e] DATE [RANGE]')),
3044 "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
3045 "debugdata": (debugdata, [], _('hg debugdata FILE REV')),
3045 "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
3046 "debugfsinfo": (debugfsinfo, [], _('hg debugfsinfo [PATH]')),
3046 "debugindex": (debugindex, [], _('hg debugindex FILE')),
3047 "debugindex": (debugindex, [], _('hg debugindex FILE')),
3047 "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
3048 "debugindexdot": (debugindexdot, [], _('hg debugindexdot FILE')),
3048 "debuginstall": (debuginstall, [], _('hg debuginstall')),
3049 "debuginstall": (debuginstall, [], _('hg debuginstall')),
3049 "debugrawcommit|rawcommit":
3050 "debugrawcommit|rawcommit":
3050 (rawcommit,
3051 (rawcommit,
3051 [('p', 'parent', [], _('parent')),
3052 [('p', 'parent', [], _('parent')),
3052 ('F', 'files', '', _('file list'))
3053 ('F', 'files', '', _('file list'))
3053 ] + commitopts + commitopts2,
3054 ] + commitopts + commitopts2,
3054 _('hg debugrawcommit [OPTION]... [FILE]...')),
3055 _('hg debugrawcommit [OPTION]... [FILE]...')),
3055 "debugrebuildstate":
3056 "debugrebuildstate":
3056 (debugrebuildstate,
3057 (debugrebuildstate,
3057 [('r', 'rev', '', _('revision to rebuild to'))],
3058 [('r', 'rev', '', _('revision to rebuild to'))],
3058 _('hg debugrebuildstate [-r REV] [REV]')),
3059 _('hg debugrebuildstate [-r REV] [REV]')),
3059 "debugrename":
3060 "debugrename":
3060 (debugrename,
3061 (debugrename,
3061 [('r', 'rev', '', _('revision to debug'))],
3062 [('r', 'rev', '', _('revision to debug'))],
3062 _('hg debugrename [-r REV] FILE')),
3063 _('hg debugrename [-r REV] FILE')),
3063 "debugsetparents":
3064 "debugsetparents":
3064 (debugsetparents,
3065 (debugsetparents,
3065 [],
3066 [],
3066 _('hg debugsetparents REV1 [REV2]')),
3067 _('hg debugsetparents REV1 [REV2]')),
3067 "debugstate":
3068 "debugstate":
3068 (debugstate,
3069 (debugstate,
3069 [('', 'nodates', None, _('do not display the saved mtime'))],
3070 [('', 'nodates', None, _('do not display the saved mtime'))],
3070 _('hg debugstate [OPTS]')),
3071 _('hg debugstate [OPTS]')),
3071 "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
3072 "debugwalk": (debugwalk, walkopts, _('hg debugwalk [OPTION]... [FILE]...')),
3072 "^diff":
3073 "^diff":
3073 (diff,
3074 (diff,
3074 [('r', 'rev', [], _('revision'))
3075 [('r', 'rev', [], _('revision'))
3075 ] + diffopts + diffopts2 + walkopts,
3076 ] + diffopts + diffopts2 + walkopts,
3076 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3077 _('hg diff [OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3077 "^export":
3078 "^export":
3078 (export,
3079 (export,
3079 [('o', 'output', '', _('print output to file with formatted name')),
3080 [('o', 'output', '', _('print output to file with formatted name')),
3080 ('', 'switch-parent', None, _('diff against the second parent'))
3081 ('', 'switch-parent', None, _('diff against the second parent'))
3081 ] + diffopts,
3082 ] + diffopts,
3082 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
3083 _('hg export [OPTION]... [-o OUTFILESPEC] REV...')),
3083 "grep":
3084 "grep":
3084 (grep,
3085 (grep,
3085 [('0', 'print0', None, _('end fields with NUL')),
3086 [('0', 'print0', None, _('end fields with NUL')),
3086 ('', 'all', None, _('print all revisions that match')),
3087 ('', 'all', None, _('print all revisions that match')),
3087 ('f', 'follow', None,
3088 ('f', 'follow', None,
3088 _('follow changeset history, or file history across copies and renames')),
3089 _('follow changeset history, or file history across copies and renames')),
3089 ('i', 'ignore-case', None, _('ignore case when matching')),
3090 ('i', 'ignore-case', None, _('ignore case when matching')),
3090 ('l', 'files-with-matches', None,
3091 ('l', 'files-with-matches', None,
3091 _('print only filenames and revs that match')),
3092 _('print only filenames and revs that match')),
3092 ('n', 'line-number', None, _('print matching line numbers')),
3093 ('n', 'line-number', None, _('print matching line numbers')),
3093 ('r', 'rev', [], _('search in given revision range')),
3094 ('r', 'rev', [], _('search in given revision range')),
3094 ('u', 'user', None, _('list the author (long with -v)')),
3095 ('u', 'user', None, _('list the author (long with -v)')),
3095 ('d', 'date', None, _('list the date (short with -q)')),
3096 ('d', 'date', None, _('list the date (short with -q)')),
3096 ] + walkopts,
3097 ] + walkopts,
3097 _('hg grep [OPTION]... PATTERN [FILE]...')),
3098 _('hg grep [OPTION]... PATTERN [FILE]...')),
3098 "heads":
3099 "heads":
3099 (heads,
3100 (heads,
3100 [('r', 'rev', '', _('show only heads which are descendants of rev')),
3101 [('r', 'rev', '', _('show only heads which are descendants of rev')),
3101 ] + templateopts,
3102 ] + templateopts,
3102 _('hg heads [-r REV] [REV]...')),
3103 _('hg heads [-r REV] [REV]...')),
3103 "help": (help_, [], _('hg help [COMMAND]')),
3104 "help": (help_, [], _('hg help [COMMAND]')),
3104 "identify|id":
3105 "identify|id":
3105 (identify,
3106 (identify,
3106 [('r', 'rev', '', _('identify the specified rev')),
3107 [('r', 'rev', '', _('identify the specified rev')),
3107 ('n', 'num', None, _('show local revision number')),
3108 ('n', 'num', None, _('show local revision number')),
3108 ('i', 'id', None, _('show global revision id')),
3109 ('i', 'id', None, _('show global revision id')),
3109 ('b', 'branch', None, _('show branch')),
3110 ('b', 'branch', None, _('show branch')),
3110 ('t', 'tags', None, _('show tags'))],
3111 ('t', 'tags', None, _('show tags'))],
3111 _('hg identify [-nibt] [-r REV] [SOURCE]')),
3112 _('hg identify [-nibt] [-r REV] [SOURCE]')),
3112 "import|patch":
3113 "import|patch":
3113 (import_,
3114 (import_,
3114 [('p', 'strip', 1,
3115 [('p', 'strip', 1,
3115 _('directory strip option for patch. This has the same\n'
3116 _('directory strip option for patch. This has the same\n'
3116 'meaning as the corresponding patch option')),
3117 'meaning as the corresponding patch option')),
3117 ('b', 'base', '', _('base path')),
3118 ('b', 'base', '', _('base path')),
3118 ('f', 'force', None,
3119 ('f', 'force', None,
3119 _('skip check for outstanding uncommitted changes')),
3120 _('skip check for outstanding uncommitted changes')),
3120 ('', 'no-commit', None, _("don't commit, just update the working directory")),
3121 ('', 'no-commit', None, _("don't commit, just update the working directory")),
3121 ('', 'exact', None,
3122 ('', 'exact', None,
3122 _('apply patch to the nodes from which it was generated')),
3123 _('apply patch to the nodes from which it was generated')),
3123 ('', 'import-branch', None,
3124 ('', 'import-branch', None,
3124 _('Use any branch information in patch (implied by --exact)'))] +
3125 _('Use any branch information in patch (implied by --exact)'))] +
3125 commitopts + commitopts2,
3126 commitopts + commitopts2,
3126 _('hg import [OPTION]... PATCH...')),
3127 _('hg import [OPTION]... PATCH...')),
3127 "incoming|in":
3128 "incoming|in":
3128 (incoming,
3129 (incoming,
3129 [('f', 'force', None,
3130 [('f', 'force', None,
3130 _('run even when remote repository is unrelated')),
3131 _('run even when remote repository is unrelated')),
3131 ('n', 'newest-first', None, _('show newest record first')),
3132 ('n', 'newest-first', None, _('show newest record first')),
3132 ('', 'bundle', '', _('file to store the bundles into')),
3133 ('', 'bundle', '', _('file to store the bundles into')),
3133 ('r', 'rev', [],
3134 ('r', 'rev', [],
3134 _('a specific revision up to which you would like to pull')),
3135 _('a specific revision up to which you would like to pull')),
3135 ] + logopts + remoteopts,
3136 ] + logopts + remoteopts,
3136 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
3137 _('hg incoming [-p] [-n] [-M] [-f] [-r REV]...'
3137 ' [--bundle FILENAME] [SOURCE]')),
3138 ' [--bundle FILENAME] [SOURCE]')),
3138 "^init":
3139 "^init":
3139 (init,
3140 (init,
3140 remoteopts,
3141 remoteopts,
3141 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
3142 _('hg init [-e CMD] [--remotecmd CMD] [DEST]')),
3142 "locate":
3143 "locate":
3143 (locate,
3144 (locate,
3144 [('r', 'rev', '', _('search the repository as it stood at rev')),
3145 [('r', 'rev', '', _('search the repository as it stood at rev')),
3145 ('0', 'print0', None,
3146 ('0', 'print0', None,
3146 _('end filenames with NUL, for use with xargs')),
3147 _('end filenames with NUL, for use with xargs')),
3147 ('f', 'fullpath', None,
3148 ('f', 'fullpath', None,
3148 _('print complete paths from the filesystem root')),
3149 _('print complete paths from the filesystem root')),
3149 ] + walkopts,
3150 ] + walkopts,
3150 _('hg locate [OPTION]... [PATTERN]...')),
3151 _('hg locate [OPTION]... [PATTERN]...')),
3151 "^log|history":
3152 "^log|history":
3152 (log,
3153 (log,
3153 [('f', 'follow', None,
3154 [('f', 'follow', None,
3154 _('follow changeset history, or file history across copies and renames')),
3155 _('follow changeset history, or file history across copies and renames')),
3155 ('', 'follow-first', None,
3156 ('', 'follow-first', None,
3156 _('only follow the first parent of merge changesets')),
3157 _('only follow the first parent of merge changesets')),
3157 ('d', 'date', '', _('show revs matching date spec')),
3158 ('d', 'date', '', _('show revs matching date spec')),
3158 ('C', 'copies', None, _('show copied files')),
3159 ('C', 'copies', None, _('show copied files')),
3159 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3160 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3160 ('r', 'rev', [], _('show the specified revision or range')),
3161 ('r', 'rev', [], _('show the specified revision or range')),
3161 ('', 'removed', None, _('include revs where files were removed')),
3162 ('', 'removed', None, _('include revs where files were removed')),
3162 ('m', 'only-merges', None, _('show only merges')),
3163 ('m', 'only-merges', None, _('show only merges')),
3163 ('b', 'only-branch', [],
3164 ('b', 'only-branch', [],
3164 _('show only changesets within the given named branch')),
3165 _('show only changesets within the given named branch')),
3165 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3166 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3166 ] + logopts + walkopts,
3167 ] + logopts + walkopts,
3167 _('hg log [OPTION]... [FILE]')),
3168 _('hg log [OPTION]... [FILE]')),
3168 "manifest":
3169 "manifest":
3169 (manifest,
3170 (manifest,
3170 [('r', 'rev', '', _('revision to display'))],
3171 [('r', 'rev', '', _('revision to display'))],
3171 _('hg manifest [-r REV]')),
3172 _('hg manifest [-r REV]')),
3172 "^merge":
3173 "^merge":
3173 (merge,
3174 (merge,
3174 [('f', 'force', None, _('force a merge with outstanding changes')),
3175 [('f', 'force', None, _('force a merge with outstanding changes')),
3175 ('r', 'rev', '', _('revision to merge')),
3176 ('r', 'rev', '', _('revision to merge')),
3176 ],
3177 ],
3177 _('hg merge [-f] [[-r] REV]')),
3178 _('hg merge [-f] [[-r] REV]')),
3178 "outgoing|out":
3179 "outgoing|out":
3179 (outgoing,
3180 (outgoing,
3180 [('f', 'force', None,
3181 [('f', 'force', None,
3181 _('run even when remote repository is unrelated')),
3182 _('run even when remote repository is unrelated')),
3182 ('r', 'rev', [],
3183 ('r', 'rev', [],
3183 _('a specific revision up to which you would like to push')),
3184 _('a specific revision up to which you would like to push')),
3184 ('n', 'newest-first', None, _('show newest record first')),
3185 ('n', 'newest-first', None, _('show newest record first')),
3185 ] + logopts + remoteopts,
3186 ] + logopts + remoteopts,
3186 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3187 _('hg outgoing [-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3187 "^parents":
3188 "^parents":
3188 (parents,
3189 (parents,
3189 [('r', 'rev', '', _('show parents from the specified rev')),
3190 [('r', 'rev', '', _('show parents from the specified rev')),
3190 ] + templateopts,
3191 ] + templateopts,
3191 _('hg parents [-r REV] [FILE]')),
3192 _('hg parents [-r REV] [FILE]')),
3192 "paths": (paths, [], _('hg paths [NAME]')),
3193 "paths": (paths, [], _('hg paths [NAME]')),
3193 "^pull":
3194 "^pull":
3194 (pull,
3195 (pull,
3195 [('u', 'update', None,
3196 [('u', 'update', None,
3196 _('update to new tip if changesets were pulled')),
3197 _('update to new tip if changesets were pulled')),
3197 ('f', 'force', None,
3198 ('f', 'force', None,
3198 _('run even when remote repository is unrelated')),
3199 _('run even when remote repository is unrelated')),
3199 ('r', 'rev', [],
3200 ('r', 'rev', [],
3200 _('a specific revision up to which you would like to pull')),
3201 _('a specific revision up to which you would like to pull')),
3201 ] + remoteopts,
3202 ] + remoteopts,
3202 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3203 _('hg pull [-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3203 "^push":
3204 "^push":
3204 (push,
3205 (push,
3205 [('f', 'force', None, _('force push')),
3206 [('f', 'force', None, _('force push')),
3206 ('r', 'rev', [],
3207 ('r', 'rev', [],
3207 _('a specific revision up to which you would like to push')),
3208 _('a specific revision up to which you would like to push')),
3208 ] + remoteopts,
3209 ] + remoteopts,
3209 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3210 _('hg push [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3210 "recover": (recover, [], _('hg recover')),
3211 "recover": (recover, [], _('hg recover')),
3211 "^remove|rm":
3212 "^remove|rm":
3212 (remove,
3213 (remove,
3213 [('A', 'after', None, _('record delete for missing files')),
3214 [('A', 'after', None, _('record delete for missing files')),
3214 ('f', 'force', None,
3215 ('f', 'force', None,
3215 _('remove (and delete) file even if added or modified')),
3216 _('remove (and delete) file even if added or modified')),
3216 ] + walkopts,
3217 ] + walkopts,
3217 _('hg remove [OPTION]... FILE...')),
3218 _('hg remove [OPTION]... FILE...')),
3218 "rename|mv":
3219 "rename|mv":
3219 (rename,
3220 (rename,
3220 [('A', 'after', None, _('record a rename that has already occurred')),
3221 [('A', 'after', None, _('record a rename that has already occurred')),
3221 ('f', 'force', None,
3222 ('f', 'force', None,
3222 _('forcibly copy over an existing managed file')),
3223 _('forcibly copy over an existing managed file')),
3223 ] + walkopts + dryrunopts,
3224 ] + walkopts + dryrunopts,
3224 _('hg rename [OPTION]... SOURCE... DEST')),
3225 _('hg rename [OPTION]... SOURCE... DEST')),
3225 "resolve":
3226 "resolve":
3226 (resolve,
3227 (resolve,
3227 [('l', 'list', None, _('list state of files needing merge')),
3228 [('l', 'list', None, _('list state of files needing merge')),
3228 ('m', 'mark', None, _('mark files as resolved')),
3229 ('m', 'mark', None, _('mark files as resolved')),
3229 ('u', 'unmark', None, _('unmark files as resolved'))],
3230 ('u', 'unmark', None, _('unmark files as resolved'))],
3230 ('hg resolve [OPTION] [FILES...]')),
3231 ('hg resolve [OPTION] [FILES...]')),
3231 "revert":
3232 "revert":
3232 (revert,
3233 (revert,
3233 [('a', 'all', None, _('revert all changes when no arguments given')),
3234 [('a', 'all', None, _('revert all changes when no arguments given')),
3234 ('d', 'date', '', _('tipmost revision matching date')),
3235 ('d', 'date', '', _('tipmost revision matching date')),
3235 ('r', 'rev', '', _('revision to revert to')),
3236 ('r', 'rev', '', _('revision to revert to')),
3236 ('', 'no-backup', None, _('do not save backup copies of files')),
3237 ('', 'no-backup', None, _('do not save backup copies of files')),
3237 ] + walkopts + dryrunopts,
3238 ] + walkopts + dryrunopts,
3238 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3239 _('hg revert [OPTION]... [-r REV] [NAME]...')),
3239 "rollback": (rollback, [], _('hg rollback')),
3240 "rollback": (rollback, [], _('hg rollback')),
3240 "root": (root, [], _('hg root')),
3241 "root": (root, [], _('hg root')),
3241 "^serve":
3242 "^serve":
3242 (serve,
3243 (serve,
3243 [('A', 'accesslog', '', _('name of access log file to write to')),
3244 [('A', 'accesslog', '', _('name of access log file to write to')),
3244 ('d', 'daemon', None, _('run server in background')),
3245 ('d', 'daemon', None, _('run server in background')),
3245 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3246 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3246 ('E', 'errorlog', '', _('name of error log file to write to')),
3247 ('E', 'errorlog', '', _('name of error log file to write to')),
3247 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3248 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3248 ('a', 'address', '', _('address to listen on (default: all interfaces)')),
3249 ('a', 'address', '', _('address to listen on (default: all interfaces)')),
3249 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3250 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3250 ('n', 'name', '',
3251 ('n', 'name', '',
3251 _('name to show in web pages (default: working dir)')),
3252 _('name to show in web pages (default: working dir)')),
3252 ('', 'webdir-conf', '', _('name of the webdir config file'
3253 ('', 'webdir-conf', '', _('name of the webdir config file'
3253 ' (serve more than one repo)')),
3254 ' (serve more than one repo)')),
3254 ('', 'pid-file', '', _('name of file to write process ID to')),
3255 ('', 'pid-file', '', _('name of file to write process ID to')),
3255 ('', 'stdio', None, _('for remote clients')),
3256 ('', 'stdio', None, _('for remote clients')),
3256 ('t', 'templates', '', _('web templates to use')),
3257 ('t', 'templates', '', _('web templates to use')),
3257 ('', 'style', '', _('template style to use')),
3258 ('', 'style', '', _('template style to use')),
3258 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3259 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3259 ('', 'certificate', '', _('SSL certificate file'))],
3260 ('', 'certificate', '', _('SSL certificate file'))],
3260 _('hg serve [OPTION]...')),
3261 _('hg serve [OPTION]...')),
3261 "showconfig|debugconfig":
3262 "showconfig|debugconfig":
3262 (showconfig,
3263 (showconfig,
3263 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3264 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3264 _('hg showconfig [-u] [NAME]...')),
3265 _('hg showconfig [-u] [NAME]...')),
3265 "^status|st":
3266 "^status|st":
3266 (status,
3267 (status,
3267 [('A', 'all', None, _('show status of all files')),
3268 [('A', 'all', None, _('show status of all files')),
3268 ('m', 'modified', None, _('show only modified files')),
3269 ('m', 'modified', None, _('show only modified files')),
3269 ('a', 'added', None, _('show only added files')),
3270 ('a', 'added', None, _('show only added files')),
3270 ('r', 'removed', None, _('show only removed files')),
3271 ('r', 'removed', None, _('show only removed files')),
3271 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3272 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3272 ('c', 'clean', None, _('show only files without changes')),
3273 ('c', 'clean', None, _('show only files without changes')),
3273 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3274 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3274 ('i', 'ignored', None, _('show only ignored files')),
3275 ('i', 'ignored', None, _('show only ignored files')),
3275 ('n', 'no-status', None, _('hide status prefix')),
3276 ('n', 'no-status', None, _('hide status prefix')),
3276 ('C', 'copies', None, _('show source of copied files')),
3277 ('C', 'copies', None, _('show source of copied files')),
3277 ('0', 'print0', None,
3278 ('0', 'print0', None,
3278 _('end filenames with NUL, for use with xargs')),
3279 _('end filenames with NUL, for use with xargs')),
3279 ('', 'rev', [], _('show difference from revision')),
3280 ('', 'rev', [], _('show difference from revision')),
3280 ] + walkopts,
3281 ] + walkopts,
3281 _('hg status [OPTION]... [FILE]...')),
3282 _('hg status [OPTION]... [FILE]...')),
3282 "tag":
3283 "tag":
3283 (tag,
3284 (tag,
3284 [('f', 'force', None, _('replace existing tag')),
3285 [('f', 'force', None, _('replace existing tag')),
3285 ('l', 'local', None, _('make the tag local')),
3286 ('l', 'local', None, _('make the tag local')),
3286 ('r', 'rev', '', _('revision to tag')),
3287 ('r', 'rev', '', _('revision to tag')),
3287 ('', 'remove', None, _('remove a tag')),
3288 ('', 'remove', None, _('remove a tag')),
3288 # -l/--local is already there, commitopts cannot be used
3289 # -l/--local is already there, commitopts cannot be used
3289 ('m', 'message', '', _('use <text> as commit message')),
3290 ('m', 'message', '', _('use <text> as commit message')),
3290 ] + commitopts2,
3291 ] + commitopts2,
3291 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3292 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3292 "tags": (tags, [], _('hg tags')),
3293 "tags": (tags, [], _('hg tags')),
3293 "tip":
3294 "tip":
3294 (tip,
3295 (tip,
3295 [('p', 'patch', None, _('show patch')),
3296 [('p', 'patch', None, _('show patch')),
3296 ] + templateopts,
3297 ] + templateopts,
3297 _('hg tip [-p]')),
3298 _('hg tip [-p]')),
3298 "unbundle":
3299 "unbundle":
3299 (unbundle,
3300 (unbundle,
3300 [('u', 'update', None,
3301 [('u', 'update', None,
3301 _('update to new tip if changesets were unbundled'))],
3302 _('update to new tip if changesets were unbundled'))],
3302 _('hg unbundle [-u] FILE...')),
3303 _('hg unbundle [-u] FILE...')),
3303 "^update|up|checkout|co":
3304 "^update|up|checkout|co":
3304 (update,
3305 (update,
3305 [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
3306 [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
3306 ('d', 'date', '', _('tipmost revision matching date')),
3307 ('d', 'date', '', _('tipmost revision matching date')),
3307 ('r', 'rev', '', _('revision'))],
3308 ('r', 'rev', '', _('revision'))],
3308 _('hg update [-C] [-d DATE] [[-r] REV]')),
3309 _('hg update [-C] [-d DATE] [[-r] REV]')),
3309 "verify": (verify, [], _('hg verify')),
3310 "verify": (verify, [], _('hg verify')),
3310 "version": (version_, [], _('hg version')),
3311 "version": (version_, [], _('hg version')),
3311 }
3312 }
3312
3313
3313 norepo = ("clone init version help debugcomplete debugdata"
3314 norepo = ("clone init version help debugcomplete debugdata"
3314 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3315 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3315 optionalrepo = ("identify paths serve showconfig debugancestor")
3316 optionalrepo = ("identify paths serve showconfig debugancestor")
@@ -1,15 +1,17 b''
1 adding dir/bar
1 adding dir/bar
2 adding foo
2 adding foo
3 dir/bar
3 dir/bar
4 foo
4 foo
5 committed changeset d44511117907
5 adding dir/bar_2
6 adding dir/bar_2
6 adding foo_2
7 adding foo_2
7 dir/bar_2
8 dir/bar_2
8 foo_2
9 foo_2
10 committed changeset a85812e0561a
9 adding a
11 adding a
10 adding c
12 adding c
11 removing a
13 removing a
12 adding b
14 adding b
13 removing c
15 removing c
14 adding d
16 adding d
15 recording removal of a as rename to b (100% similar)
17 recording removal of a as rename to b (100% similar)
@@ -1,13 +1,14 b''
1 % test file addition with bad case
1 % test file addition with bad case
2 adding a
2 adding a
3 A a
3 A a
4 a
4 a
5 % test case collision on rename (issue 750)
5 % test case collision on rename (issue 750)
6 adding a
6 adding a
7 a
7 a
8 committed changeset 07f494440405
8 A: not overwriting - file exists
9 A: not overwriting - file exists
9 % test case collision between revisions (issue 912)
10 % test case collision between revisions (issue 912)
10 adding a
11 adding a
11 adding A
12 adding A
12 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
13 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
13 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
14 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
@@ -1,110 +1,110 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 echo % commit date test
3 echo % commit date test
4 hg init test
4 hg init test
5 cd test
5 cd test
6 echo foo > foo
6 echo foo > foo
7 hg add foo
7 hg add foo
8 HGEDITOR=true hg commit -m ""
8 HGEDITOR=true hg commit -m ""
9 hg commit -d '0 0' -m commit-1
9 hg commit -d '0 0' -m commit-1
10 # An empty date was interpreted as epoch origin
11 echo foo >> foo
12 hg commit -d '' -m commit-no-date
13 hg tip --template '{date|isodate}\n' | grep '1970'
14 echo foo >> foo
10 echo foo >> foo
15 hg commit -d '1 4444444' -m commit-3
11 hg commit -d '1 4444444' -m commit-3
16 hg commit -d '1 15.1' -m commit-4
12 hg commit -d '1 15.1' -m commit-4
17 hg commit -d 'foo bar' -m commit-5
13 hg commit -d 'foo bar' -m commit-5
18 hg commit -d ' 1 4444' -m commit-6
14 hg commit -d ' 1 4444' -m commit-6
19 hg commit -d '111111111111 0' -m commit-7
15 hg commit -d '111111111111 0' -m commit-7
20
16
21 echo % commit added file that has been deleted
17 echo % commit added file that has been deleted
22 echo bar > bar
18 echo bar > bar
23 hg add bar
19 hg add bar
24 rm bar
20 rm bar
25 hg commit -d "1000000 0" -m commit-8
21 hg commit -d "1000000 0" -m commit-8
26 hg commit -d "1000000 0" -m commit-8-2 bar
22 hg commit -d "1000000 0" -m commit-8-2 bar
27
23
28 hg -q revert -a --no-backup
24 hg -q revert -a --no-backup
29
25
30 mkdir dir
26 mkdir dir
31 echo boo > dir/file
27 echo boo > dir/file
32 hg add
28 hg add
33 hg -v commit -d '0 0' -m commit-9 dir
29 hg -v commit -d '0 0' -m commit-9 dir
34
30
35 echo > dir.file
31 echo > dir.file
36 hg add
32 hg add
37 hg commit -d '0 0' -m commit-10 dir dir.file
33 hg commit -d '0 0' -m commit-10 dir dir.file
38
34
39 echo >> dir/file
35 echo >> dir/file
40 mkdir bleh
36 mkdir bleh
41 mkdir dir2
37 mkdir dir2
42 cd bleh
38 cd bleh
43 hg commit -d '0 0' -m commit-11 .
39 hg commit -d '0 0' -m commit-11 .
44 hg commit -d '0 0' -m commit-12 ../dir ../dir2
40 hg commit -d '0 0' -m commit-12 ../dir ../dir2
45 hg -v commit -d '0 0' -m commit-13 ../dir
41 hg -v commit -d '0 0' -m commit-13 ../dir
46 cd ..
42 cd ..
47
43
48 hg commit -d '0 0' -m commit-14 does-not-exist
44 hg commit -d '0 0' -m commit-14 does-not-exist
49 ln -s foo baz
45 ln -s foo baz
50 hg commit -d '0 0' -m commit-15 baz
46 hg commit -d '0 0' -m commit-15 baz
51 touch quux
47 touch quux
52 hg commit -d '0 0' -m commit-16 quux
48 hg commit -d '0 0' -m commit-16 quux
53 echo >> dir/file
49 echo >> dir/file
54 hg -v commit -d '0 0' -m commit-17 dir/file
50 hg -v commit -d '0 0' -m commit-17 dir/file
51 # An empty date was interpreted as epoch origin
52 echo foo >> foo
53 hg commit -d '' -m commit-no-date
54 hg tip --template '{date|isodate}\n' | grep '1970'
55 cd ..
55 cd ..
56
56
57 echo % partial subdir commit test
57 echo % partial subdir commit test
58 hg init test2
58 hg init test2
59 cd test2
59 cd test2
60 mkdir foo
60 mkdir foo
61 echo foo > foo/foo
61 echo foo > foo/foo
62 mkdir bar
62 mkdir bar
63 echo bar > bar/bar
63 echo bar > bar/bar
64 hg add
64 hg add
65 hg ci -d '1000000 0' -u test -m commit-subdir-1 foo
65 hg ci -d '1000000 0' -u test -m commit-subdir-1 foo
66 hg ci -d '1000001 0' -u test -m commit-subdir-2 bar
66 hg ci -d '1000001 0' -u test -m commit-subdir-2 bar
67 echo % subdir log 1
67 echo % subdir log 1
68 hg log -v foo
68 hg log -v foo
69 echo % subdir log 2
69 echo % subdir log 2
70 hg log -v bar
70 hg log -v bar
71 echo % full log
71 echo % full log
72 hg log -v
72 hg log -v
73 cd ..
73 cd ..
74
74
75 echo % dot and subdir commit test
75 echo % dot and subdir commit test
76 hg init test3
76 hg init test3
77 cd test3
77 cd test3
78 mkdir foo
78 mkdir foo
79 echo foo content > foo/plain-file
79 echo foo content > foo/plain-file
80 hg add foo/plain-file
80 hg add foo/plain-file
81 hg ci -d '1000000 0' -u test -m commit-foo-subdir foo
81 hg ci -d '1000000 0' -u test -m commit-foo-subdir foo
82 echo modified foo content > foo/plain-file
82 echo modified foo content > foo/plain-file
83 hg ci -d '2000000 0' -u test -m commit-foo-dot .
83 hg ci -d '2000000 0' -u test -m commit-foo-dot .
84 echo % full log
84 echo % full log
85 hg log -v
85 hg log -v
86 echo % subdir log
86 echo % subdir log
87 cd foo
87 cd foo
88 hg log .
88 hg log .
89 cd ..
89 cd ..
90 cd ..
90 cd ..
91
91
92 cd ..
92 cd ..
93 hg init issue1049
93 hg init issue1049
94 cd issue1049
94 cd issue1049
95 echo a > a
95 echo a > a
96 hg ci -Ama
96 hg ci -Ama
97 echo a >> a
97 echo a >> a
98 hg ci -mb
98 hg ci -mb
99 hg up 0
99 hg up 0
100 echo b >> a
100 echo b >> a
101 hg ci -mc
101 hg ci -mc
102 HGMERGE=true hg merge
102 HGMERGE=true hg merge
103 echo % should fail because we are specifying a file name
103 echo % should fail because we are specifying a file name
104 hg ci -mmerge a
104 hg ci -mmerge a
105 echo % should fail because we are specifying a pattern
105 echo % should fail because we are specifying a pattern
106 hg ci -mmerge -I a
106 hg ci -mmerge -I a
107 echo % should succeed
107 echo % should succeed
108 hg ci -mmerge
108 hg ci -mmerge
109
109
110 exit 0
110 exit 0
@@ -1,105 +1,108 b''
1 % commit date test
1 % commit date test
2 transaction abort!
2 transaction abort!
3 rollback completed
3 rollback completed
4 abort: empty commit message
4 abort: empty commit message
5 abort: impossible time zone offset: 4444444
5 abort: impossible time zone offset: 4444444
6 abort: invalid date: '1\t15.1'
6 abort: invalid date: '1\t15.1'
7 abort: invalid date: 'foo bar'
7 abort: invalid date: 'foo bar'
8 abort: date exceeds 32 bits: 111111111111
8 abort: date exceeds 32 bits: 111111111111
9 % commit added file that has been deleted
9 % commit added file that has been deleted
10 nothing changed
10 nothing changed
11 abort: file bar not found!
11 abort: file bar not found!
12 adding dir/file
12 adding dir/file
13 dir/file
13 dir/file
14 committed changeset d2a76177cb42
14 adding dir.file
15 adding dir.file
15 abort: no match under directory dir!
16 abort: no match under directory dir!
16 abort: no match under directory .!
17 abort: no match under directory .!
17 abort: no match under directory ../dir2!
18 abort: no match under directory ../dir2!
18 dir/file
19 dir/file
20 committed changeset 1cd62a2d8db5
19 does-not-exist: No such file or directory
21 does-not-exist: No such file or directory
20 abort: file does-not-exist not found!
22 abort: file does-not-exist not found!
21 abort: file baz not tracked!
23 abort: file baz not tracked!
22 abort: file quux not tracked!
24 abort: file quux not tracked!
23 dir/file
25 dir/file
26 committed changeset 49176991390e
24 % partial subdir commit test
27 % partial subdir commit test
25 adding bar/bar
28 adding bar/bar
26 adding foo/foo
29 adding foo/foo
27 % subdir log 1
30 % subdir log 1
28 changeset: 0:6ef3cb06bb80
31 changeset: 0:6ef3cb06bb80
29 user: test
32 user: test
30 date: Mon Jan 12 13:46:40 1970 +0000
33 date: Mon Jan 12 13:46:40 1970 +0000
31 files: foo/foo
34 files: foo/foo
32 description:
35 description:
33 commit-subdir-1
36 commit-subdir-1
34
37
35
38
36 % subdir log 2
39 % subdir log 2
37 changeset: 1:f2e51572cf5a
40 changeset: 1:f2e51572cf5a
38 tag: tip
41 tag: tip
39 user: test
42 user: test
40 date: Mon Jan 12 13:46:41 1970 +0000
43 date: Mon Jan 12 13:46:41 1970 +0000
41 files: bar/bar
44 files: bar/bar
42 description:
45 description:
43 commit-subdir-2
46 commit-subdir-2
44
47
45
48
46 % full log
49 % full log
47 changeset: 1:f2e51572cf5a
50 changeset: 1:f2e51572cf5a
48 tag: tip
51 tag: tip
49 user: test
52 user: test
50 date: Mon Jan 12 13:46:41 1970 +0000
53 date: Mon Jan 12 13:46:41 1970 +0000
51 files: bar/bar
54 files: bar/bar
52 description:
55 description:
53 commit-subdir-2
56 commit-subdir-2
54
57
55
58
56 changeset: 0:6ef3cb06bb80
59 changeset: 0:6ef3cb06bb80
57 user: test
60 user: test
58 date: Mon Jan 12 13:46:40 1970 +0000
61 date: Mon Jan 12 13:46:40 1970 +0000
59 files: foo/foo
62 files: foo/foo
60 description:
63 description:
61 commit-subdir-1
64 commit-subdir-1
62
65
63
66
64 % dot and subdir commit test
67 % dot and subdir commit test
65 % full log
68 % full log
66 changeset: 1:d9180e04fa8a
69 changeset: 1:d9180e04fa8a
67 tag: tip
70 tag: tip
68 user: test
71 user: test
69 date: Sat Jan 24 03:33:20 1970 +0000
72 date: Sat Jan 24 03:33:20 1970 +0000
70 files: foo/plain-file
73 files: foo/plain-file
71 description:
74 description:
72 commit-foo-dot
75 commit-foo-dot
73
76
74
77
75 changeset: 0:80b572aaf098
78 changeset: 0:80b572aaf098
76 user: test
79 user: test
77 date: Mon Jan 12 13:46:40 1970 +0000
80 date: Mon Jan 12 13:46:40 1970 +0000
78 files: foo/plain-file
81 files: foo/plain-file
79 description:
82 description:
80 commit-foo-subdir
83 commit-foo-subdir
81
84
82
85
83 % subdir log
86 % subdir log
84 changeset: 1:d9180e04fa8a
87 changeset: 1:d9180e04fa8a
85 tag: tip
88 tag: tip
86 user: test
89 user: test
87 date: Sat Jan 24 03:33:20 1970 +0000
90 date: Sat Jan 24 03:33:20 1970 +0000
88 summary: commit-foo-dot
91 summary: commit-foo-dot
89
92
90 changeset: 0:80b572aaf098
93 changeset: 0:80b572aaf098
91 user: test
94 user: test
92 date: Mon Jan 12 13:46:40 1970 +0000
95 date: Mon Jan 12 13:46:40 1970 +0000
93 summary: commit-foo-subdir
96 summary: commit-foo-subdir
94
97
95 adding a
98 adding a
96 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
97 created new head
100 created new head
98 merging a
101 merging a
99 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
102 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
100 (branch merge, don't forget to commit)
103 (branch merge, don't forget to commit)
101 % should fail because we are specifying a file name
104 % should fail because we are specifying a file name
102 abort: cannot partially commit a merge (do not specify files or patterns)
105 abort: cannot partially commit a merge (do not specify files or patterns)
103 % should fail because we are specifying a pattern
106 % should fail because we are specifying a pattern
104 abort: cannot partially commit a merge (do not specify files or patterns)
107 abort: cannot partially commit a merge (do not specify files or patterns)
105 % should succeed
108 % should succeed
@@ -1,51 +1,52 b''
1 A b
1 A b
2 b
2 b
3 b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
3 b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
4 committed changeset 386a3cc01532
4 we should see two history entries
5 we should see two history entries
5 changeset: 1:386a3cc01532
6 changeset: 1:386a3cc01532
6 tag: tip
7 tag: tip
7 user: test
8 user: test
8 date: Mon Jan 12 13:46:40 1970 +0000
9 date: Mon Jan 12 13:46:40 1970 +0000
9 files: b
10 files: b
10 description:
11 description:
11 2
12 2
12
13
13
14
14 changeset: 0:33aaa84a386b
15 changeset: 0:33aaa84a386b
15 user: test
16 user: test
16 date: Mon Jan 12 13:46:40 1970 +0000
17 date: Mon Jan 12 13:46:40 1970 +0000
17 files: a
18 files: a
18 description:
19 description:
19 1
20 1
20
21
21
22
22 we should see one log entry for a
23 we should see one log entry for a
23 changeset: 0:33aaa84a386b
24 changeset: 0:33aaa84a386b
24 user: test
25 user: test
25 date: Mon Jan 12 13:46:40 1970 +0000
26 date: Mon Jan 12 13:46:40 1970 +0000
26 summary: 1
27 summary: 1
27
28
28 this should show a revision linked to changeset 0
29 this should show a revision linked to changeset 0
29 rev offset length base linkrev nodeid p1 p2
30 rev offset length base linkrev nodeid p1 p2
30 0 0 3 0 0 b789fdd96dc2 000000000000 000000000000
31 0 0 3 0 0 b789fdd96dc2 000000000000 000000000000
31 we should see one log entry for b
32 we should see one log entry for b
32 changeset: 1:386a3cc01532
33 changeset: 1:386a3cc01532
33 tag: tip
34 tag: tip
34 user: test
35 user: test
35 date: Mon Jan 12 13:46:40 1970 +0000
36 date: Mon Jan 12 13:46:40 1970 +0000
36 summary: 2
37 summary: 2
37
38
38 this should show a revision linked to changeset 1
39 this should show a revision linked to changeset 1
39 rev offset length base linkrev nodeid p1 p2
40 rev offset length base linkrev nodeid p1 p2
40 0 0 65 0 1 9a263dd772e0 000000000000 000000000000
41 0 0 65 0 1 9a263dd772e0 000000000000 000000000000
41 this should show the rename information in the metadata
42 this should show the rename information in the metadata
42 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
43 copyrev: b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
43 copy: a
44 copy: a
44 ed156f22f0a6fde642de0b5eba0cbbb2 .hg/store/data/b.i
45 ed156f22f0a6fde642de0b5eba0cbbb2 .hg/store/data/b.i
45 60b725f10c9c85c70d97880dfe8191b3 bsum
46 60b725f10c9c85c70d97880dfe8191b3 bsum
46 60b725f10c9c85c70d97880dfe8191b3 asum
47 60b725f10c9c85c70d97880dfe8191b3 asum
47 checking changesets
48 checking changesets
48 checking manifests
49 checking manifests
49 crosschecking files in changesets and manifests
50 crosschecking files in changesets and manifests
50 checking files
51 checking files
51 2 files, 2 changesets, 2 total revisions
52 2 files, 2 changesets, 2 total revisions
@@ -1,153 +1,154 b''
1 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
1 precommit hook: HG_PARENT1=0000000000000000000000000000000000000000
2 pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
2 pretxncommit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
3 0:29b62aeb769f
3 0:29b62aeb769f
4 commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
4 commit hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
5 commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
5 commit.b hook: HG_NODE=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b HG_PARENT1=0000000000000000000000000000000000000000
6 updating working directory
6 updating working directory
7 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
7 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
8 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
8 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
9 pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
9 pretxncommit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
10 1:b702efe96888
10 1:b702efe96888
11 commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
11 commit hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
12 commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
12 commit.b hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
13 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
14 precommit hook: HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
15 pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
15 pretxncommit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
16 2:1324a5531bac
16 2:1324a5531bac
17 commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
17 commit hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
18 commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
18 commit.b hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT1=29b62aeb769fdf78d8d9c5f28b017f76d7ef824b
19 created new head
19 created new head
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
20 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 (branch merge, don't forget to commit)
21 (branch merge, don't forget to commit)
22 precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
22 precommit hook: HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
23 pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
23 pretxncommit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
24 3:4c52fb2e4022
24 3:4c52fb2e4022
25 commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
25 commit hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
26 commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
26 commit.b hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_PARENT1=1324a5531bac09b329c3845d35ae6a7526874edb HG_PARENT2=b702efe9688826e3a91283852b328b84dbf37bc2
27 pre-identify hook: HG_ARGS=id
27 pre-identify hook: HG_ARGS=id
28 warning: pre-identify hook exited with status 1
28 warning: pre-identify hook exited with status 1
29 pre-cat hook: HG_ARGS=cat b
29 pre-cat hook: HG_ARGS=cat b
30 post-cat hook: HG_ARGS=cat b HG_RESULT=0
30 post-cat hook: HG_ARGS=cat b HG_RESULT=0
31 b
31 b
32 prechangegroup hook: HG_SOURCE=pull HG_URL=file:
32 prechangegroup hook: HG_SOURCE=pull HG_URL=file:
33 changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
33 changegroup hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
34 incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
34 incoming hook: HG_NODE=b702efe9688826e3a91283852b328b84dbf37bc2 HG_SOURCE=pull HG_URL=file:
35 incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
35 incoming hook: HG_NODE=1324a5531bac09b329c3845d35ae6a7526874edb HG_SOURCE=pull HG_URL=file:
36 incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
36 incoming hook: HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_SOURCE=pull HG_URL=file:
37 pulling from ../a
37 pulling from ../a
38 searching for changes
38 searching for changes
39 adding changesets
39 adding changesets
40 adding manifests
40 adding manifests
41 adding file changes
41 adding file changes
42 added 3 changesets with 2 changes to 2 files
42 added 3 changesets with 2 changes to 2 files
43 (run 'hg update' to get a working copy)
43 (run 'hg update' to get a working copy)
44 pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
44 pretag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
45 precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
45 precommit hook: HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
46 pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
46 pretxncommit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
47 4:8ea2ef7ad3e8
47 4:8ea2ef7ad3e8
48 commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
48 commit hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
49 commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
49 commit.b hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_PARENT1=4c52fb2e402287dd5dc052090682536c8406c321
50 tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
50 tag hook: HG_LOCAL=0 HG_NODE=4c52fb2e402287dd5dc052090682536c8406c321 HG_TAG=a
51 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
51 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
52 tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
52 tag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=la
53 pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
53 pretag hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
54 pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
54 pretag.forbid hook: HG_LOCAL=0 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fa
55 abort: pretag.forbid hook exited with status 1
55 abort: pretag.forbid hook exited with status 1
56 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
56 pretag hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
57 pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
57 pretag.forbid hook: HG_LOCAL=1 HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_TAG=fla
58 abort: pretag.forbid hook exited with status 1
58 abort: pretag.forbid hook exited with status 1
59 4:8ea2ef7ad3e8
59 4:8ea2ef7ad3e8
60 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
60 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
61 pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
61 pretxncommit hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
62 5:fad284daf8c0
62 5:fad284daf8c0
63 pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
63 pretxncommit.forbid hook: HG_NODE=fad284daf8c032148abaffcd745dafeceefceb61 HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
64 transaction abort!
64 transaction abort!
65 rollback completed
65 rollback completed
66 abort: pretxncommit.forbid1 hook exited with status 1
66 abort: pretxncommit.forbid1 hook exited with status 1
67 4:8ea2ef7ad3e8
67 4:8ea2ef7ad3e8
68 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
68 precommit hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
69 precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
69 precommit.forbid hook: HG_PARENT1=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198
70 abort: precommit.forbid hook exited with status 1
70 abort: precommit.forbid hook exited with status 1
71 4:8ea2ef7ad3e8
71 4:8ea2ef7ad3e8
72 preupdate hook: HG_PARENT1=b702efe96888
72 preupdate hook: HG_PARENT1=b702efe96888
73 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
73 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
74 preupdate hook: HG_PARENT1=8ea2ef7ad3e8
74 preupdate hook: HG_PARENT1=8ea2ef7ad3e8
75 update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
75 update hook: HG_ERROR=0 HG_PARENT1=8ea2ef7ad3e8
76 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
76 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 3:4c52fb2e4022
77 3:4c52fb2e4022
78 prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
78 prechangegroup.forbid hook: HG_SOURCE=pull HG_URL=file:
79 pulling from ../a
79 pulling from ../a
80 searching for changes
80 searching for changes
81 abort: prechangegroup.forbid hook exited with status 1
81 abort: prechangegroup.forbid hook exited with status 1
82 4:8ea2ef7ad3e8
82 4:8ea2ef7ad3e8
83 pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull HG_URL=file:
83 pretxnchangegroup.forbid hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull HG_URL=file:
84 pulling from ../a
84 pulling from ../a
85 searching for changes
85 searching for changes
86 adding changesets
86 adding changesets
87 adding manifests
87 adding manifests
88 adding file changes
88 adding file changes
89 added 1 changesets with 1 changes to 1 files
89 added 1 changesets with 1 changes to 1 files
90 transaction abort!
90 transaction abort!
91 rollback completed
91 rollback completed
92 abort: pretxnchangegroup.forbid1 hook exited with status 1
92 abort: pretxnchangegroup.forbid1 hook exited with status 1
93 3:4c52fb2e4022
93 3:4c52fb2e4022
94 preoutgoing hook: HG_SOURCE=pull
94 preoutgoing hook: HG_SOURCE=pull
95 outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
95 outgoing hook: HG_NODE=8ea2ef7ad3e8cac946c72f1e0c79d6aebc301198 HG_SOURCE=pull
96 pulling from ../a
96 pulling from ../a
97 searching for changes
97 searching for changes
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 1 changes to 1 files
101 added 1 changesets with 1 changes to 1 files
102 (run 'hg update' to get a working copy)
102 (run 'hg update' to get a working copy)
103 rolling back last transaction
103 rolling back last transaction
104 preoutgoing hook: HG_SOURCE=pull
104 preoutgoing hook: HG_SOURCE=pull
105 preoutgoing.forbid hook: HG_SOURCE=pull
105 preoutgoing.forbid hook: HG_SOURCE=pull
106 pulling from ../a
106 pulling from ../a
107 searching for changes
107 searching for changes
108 abort: preoutgoing.forbid hook exited with status 1
108 abort: preoutgoing.forbid hook exited with status 1
109 # test python hooks
109 # test python hooks
110 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
110 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
111 error: preoutgoing.raise hook raised an exception: exception from hook
111 error: preoutgoing.raise hook raised an exception: exception from hook
112 pulling from ../a
112 pulling from ../a
113 searching for changes
113 searching for changes
114 error: preoutgoing.abort hook failed: raise abort from hook
114 error: preoutgoing.abort hook failed: raise abort from hook
115 abort: raise abort from hook
115 abort: raise abort from hook
116 pulling from ../a
116 pulling from ../a
117 searching for changes
117 searching for changes
118 hook args:
118 hook args:
119 hooktype preoutgoing
119 hooktype preoutgoing
120 source pull
120 source pull
121 abort: preoutgoing.fail hook failed
121 abort: preoutgoing.fail hook failed
122 pulling from ../a
122 pulling from ../a
123 searching for changes
123 searching for changes
124 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
124 abort: preoutgoing.uncallable hook is invalid ("hooktests.uncallable" is not callable)
125 pulling from ../a
125 pulling from ../a
126 searching for changes
126 searching for changes
127 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
127 abort: preoutgoing.nohook hook is invalid ("hooktests.nohook" is not defined)
128 pulling from ../a
128 pulling from ../a
129 searching for changes
129 searching for changes
130 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
130 abort: preoutgoing.nomodule hook is invalid ("nomodule" not in a module)
131 pulling from ../a
131 pulling from ../a
132 searching for changes
132 searching for changes
133 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
133 abort: preoutgoing.badmodule hook is invalid (import of "nomodule" failed)
134 pulling from ../a
134 pulling from ../a
135 searching for changes
135 searching for changes
136 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
136 abort: preoutgoing.unreachable hook is invalid (import of "hooktests.container" failed)
137 pulling from ../a
137 pulling from ../a
138 searching for changes
138 searching for changes
139 hook args:
139 hook args:
140 hooktype preoutgoing
140 hooktype preoutgoing
141 source pull
141 source pull
142 adding changesets
142 adding changesets
143 adding manifests
143 adding manifests
144 adding file changes
144 adding file changes
145 added 1 changesets with 1 changes to 1 files
145 added 1 changesets with 1 changes to 1 files
146 (run 'hg update' to get a working copy)
146 (run 'hg update' to get a working copy)
147 # make sure --traceback works
147 # make sure --traceback works
148 Traceback (most recent call last):
148 Traceback (most recent call last):
149 Automatically installed hook
149 Automatically installed hook
150 foo
150 foo
151 calling hook commit.auto: <function autohook>
151 calling hook commit.auto: <function autohook>
152 Automatically installed hook
152 Automatically installed hook
153 committed changeset 52998019f625
153 hooks.commit.auto=<function autohook>
154 hooks.commit.auto=<function autohook>
@@ -1,24 +1,25 b''
1 adding a
1 adding a
2 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
2 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
3 warning: detected divergent renames of a to:
3 warning: detected divergent renames of a to:
4 a2
4 a2
5 a1
5 a1
6 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
6 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
7 adding a
7 adding a
8 b
8 b
9 b: searching for copy revision for a
9 b: searching for copy revision for a
10 b: copy a:b80de5d138758541c5f05265ad144ab9fa86d1db
10 b: copy a:b80de5d138758541c5f05265ad144ab9fa86d1db
11 committed changeset 755e75751bf6
11 checking changesets
12 checking changesets
12 checking manifests
13 checking manifests
13 crosschecking files in changesets and manifests
14 crosschecking files in changesets and manifests
14 checking files
15 checking files
15 4 files, 6 changesets, 4 total revisions
16 4 files, 6 changesets, 4 total revisions
16 # HG changeset patch
17 # HG changeset patch
17 # User test
18 # User test
18 # Date 0 0
19 # Date 0 0
19 # Node ID 755e75751bf67eb4378bca61987df035d90a7a06
20 # Node ID 755e75751bf67eb4378bca61987df035d90a7a06
20 # Parent 7399822c2e395fe7d57c2fcf4b310f6fb22f8c2d
21 # Parent 7399822c2e395fe7d57c2fcf4b310f6fb22f8c2d
21 5
22 5
22
23
23 diff --git a/b b/b
24 diff --git a/b b/b
24 new file mode 100644
25 new file mode 100644
@@ -1,463 +1,469 b''
1 % help
1 % help
2 keyword extension - keyword expansion in local repositories
2 keyword extension - keyword expansion in local repositories
3
3
4 This extension expands RCS/CVS-like or self-customized $Keywords$
4 This extension expands RCS/CVS-like or self-customized $Keywords$
5 in tracked text files selected by your configuration.
5 in tracked text files selected by your configuration.
6
6
7 Keywords are only expanded in local repositories and not stored in
7 Keywords are only expanded in local repositories and not stored in
8 the change history. The mechanism can be regarded as a convenience
8 the change history. The mechanism can be regarded as a convenience
9 for the current user or for archive distribution.
9 for the current user or for archive distribution.
10
10
11 Configuration is done in the [keyword] and [keywordmaps] sections
11 Configuration is done in the [keyword] and [keywordmaps] sections
12 of hgrc files.
12 of hgrc files.
13
13
14 Example:
14 Example:
15
15
16 [keyword]
16 [keyword]
17 # expand keywords in every python file except those matching "x*"
17 # expand keywords in every python file except those matching "x*"
18 **.py =
18 **.py =
19 x* = ignore
19 x* = ignore
20
20
21 Note: the more specific you are in your filename patterns
21 Note: the more specific you are in your filename patterns
22 the less you lose speed in huge repos.
22 the less you lose speed in huge repos.
23
23
24 For [keywordmaps] template mapping and expansion demonstration and
24 For [keywordmaps] template mapping and expansion demonstration and
25 control run "hg kwdemo".
25 control run "hg kwdemo".
26
26
27 An additional date template filter {date|utcdate} is provided.
27 An additional date template filter {date|utcdate} is provided.
28
28
29 The default template mappings (view with "hg kwdemo -d") can be replaced
29 The default template mappings (view with "hg kwdemo -d") can be replaced
30 with customized keywords and templates.
30 with customized keywords and templates.
31 Again, run "hg kwdemo" to control the results of your config changes.
31 Again, run "hg kwdemo" to control the results of your config changes.
32
32
33 Before changing/disabling active keywords, run "hg kwshrink" to avoid
33 Before changing/disabling active keywords, run "hg kwshrink" to avoid
34 the risk of inadvertedly storing expanded keywords in the change history.
34 the risk of inadvertedly storing expanded keywords in the change history.
35
35
36 To force expansion after enabling it, or a configuration change, run
36 To force expansion after enabling it, or a configuration change, run
37 "hg kwexpand".
37 "hg kwexpand".
38
38
39 Also, when committing with the record extension or using mq's qrecord, be aware
39 Also, when committing with the record extension or using mq's qrecord, be aware
40 that keywords cannot be updated. Again, run "hg kwexpand" on the files in
40 that keywords cannot be updated. Again, run "hg kwexpand" on the files in
41 question to update keyword expansions after all changes have been checked in.
41 question to update keyword expansions after all changes have been checked in.
42
42
43 Expansions spanning more than one line and incremental expansions,
43 Expansions spanning more than one line and incremental expansions,
44 like CVS' $Log$, are not supported. A keyword template map
44 like CVS' $Log$, are not supported. A keyword template map
45 "Log = {desc}" expands to the first line of the changeset description.
45 "Log = {desc}" expands to the first line of the changeset description.
46
46
47 list of commands:
47 list of commands:
48
48
49 kwdemo print [keywordmaps] configuration and an expansion example
49 kwdemo print [keywordmaps] configuration and an expansion example
50 kwexpand expand keywords in working directory
50 kwexpand expand keywords in working directory
51 kwfiles print files currently configured for keyword expansion
51 kwfiles print files currently configured for keyword expansion
52 kwshrink revert expanded keywords in working directory
52 kwshrink revert expanded keywords in working directory
53
53
54 use "hg -v help keyword" to show aliases and global options
54 use "hg -v help keyword" to show aliases and global options
55 % hg kwdemo
55 % hg kwdemo
56 [extensions]
56 [extensions]
57 hgext.keyword =
57 hgext.keyword =
58 [keyword]
58 [keyword]
59 * =
59 * =
60 b = ignore
60 b = ignore
61 demo.txt =
61 demo.txt =
62 [keywordmaps]
62 [keywordmaps]
63 RCSFile = {file|basename},v
63 RCSFile = {file|basename},v
64 Author = {author|user}
64 Author = {author|user}
65 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
65 Header = {root}/{file},v {node|short} {date|utcdate} {author|user}
66 Source = {root}/{file},v
66 Source = {root}/{file},v
67 Date = {date|utcdate}
67 Date = {date|utcdate}
68 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
68 Id = {file|basename},v {node|short} {date|utcdate} {author|user}
69 Revision = {node|short}
69 Revision = {node|short}
70 $RCSFile: demo.txt,v $
70 $RCSFile: demo.txt,v $
71 $Author: test $
71 $Author: test $
72 $Header: /TMP/demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
72 $Header: /TMP/demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
73 $Source: /TMP/demo.txt,v $
73 $Source: /TMP/demo.txt,v $
74 $Date: 2000/00/00 00:00:00 $
74 $Date: 2000/00/00 00:00:00 $
75 $Id: demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
75 $Id: demo.txt,v xxxxxxxxxxxx 2000/00/00 00:00:00 test $
76 $Revision: xxxxxxxxxxxx $
76 $Revision: xxxxxxxxxxxx $
77 [extensions]
77 [extensions]
78 hgext.keyword =
78 hgext.keyword =
79 [keyword]
79 [keyword]
80 * =
80 * =
81 b = ignore
81 b = ignore
82 demo.txt =
82 demo.txt =
83 [keywordmaps]
83 [keywordmaps]
84 Branch = {branches}
84 Branch = {branches}
85 $Branch: demobranch $
85 $Branch: demobranch $
86 % kwshrink should exit silently in empty/invalid repo
86 % kwshrink should exit silently in empty/invalid repo
87 pulling from test-keyword.hg
87 pulling from test-keyword.hg
88 requesting all changes
88 requesting all changes
89 adding changesets
89 adding changesets
90 adding manifests
90 adding manifests
91 adding file changes
91 adding file changes
92 added 1 changesets with 1 changes to 1 files
92 added 1 changesets with 1 changes to 1 files
93 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
93 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 % cat
94 % cat
95 expand $Id$
95 expand $Id$
96 do not process $Id:
96 do not process $Id:
97 xxx $
97 xxx $
98 ignore $Id$
98 ignore $Id$
99 % addremove
99 % addremove
100 adding a
100 adding a
101 adding b
101 adding b
102 % status
102 % status
103 A a
103 A a
104 A b
104 A b
105 % default keyword expansion including commit hook
105 % default keyword expansion including commit hook
106 % interrupted commit should not change state or run commit hook
106 % interrupted commit should not change state or run commit hook
107 a
107 a
108 b
108 b
109 transaction abort!
109 transaction abort!
110 rollback completed
110 rollback completed
111 abort: empty commit message
111 abort: empty commit message
112 % status
112 % status
113 A a
113 A a
114 A b
114 A b
115 % commit
115 % commit
116 a
116 a
117 b
117 b
118 overwriting a expanding keywords
118 overwriting a expanding keywords
119 running hook commit.test: cp a hooktest
119 running hook commit.test: cp a hooktest
120 committed changeset ef63ca68695b
120 % status
121 % status
121 ? hooktest
122 ? hooktest
122 % identify
123 % identify
123 ef63ca68695b
124 ef63ca68695b
124 % cat
125 % cat
125 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
126 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
126 do not process $Id:
127 do not process $Id:
127 xxx $
128 xxx $
128 ignore $Id$
129 ignore $Id$
129 % hg cat
130 % hg cat
130 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
131 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
131 do not process $Id:
132 do not process $Id:
132 xxx $
133 xxx $
133 ignore $Id$
134 ignore $Id$
134 a
135 a
135 % diff a hooktest
136 % diff a hooktest
136 % removing commit hook from config
137 % removing commit hook from config
137 % bundle
138 % bundle
138 2 changesets found
139 2 changesets found
139 % notify on pull to check whether keywords stay as is in email
140 % notify on pull to check whether keywords stay as is in email
140 % ie. if patch.diff wrapper acts as it should
141 % ie. if patch.diff wrapper acts as it should
141 % pull from bundle
142 % pull from bundle
142 pulling from ../kw.hg
143 pulling from ../kw.hg
143 requesting all changes
144 requesting all changes
144 adding changesets
145 adding changesets
145 adding manifests
146 adding manifests
146 adding file changes
147 adding file changes
147 added 2 changesets with 3 changes to 3 files
148 added 2 changesets with 3 changes to 3 files
148
149
149 diff -r 000000000000 -r a2392c293916 sym
150 diff -r 000000000000 -r a2392c293916 sym
150 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
151 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
151 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
152 +++ b/sym Sat Feb 09 20:25:47 2008 +0100
152 @@ -0,0 +1,1 @@
153 @@ -0,0 +1,1 @@
153 +a
154 +a
154 \ No newline at end of file
155 \ No newline at end of file
155
156
156 diff -r a2392c293916 -r ef63ca68695b a
157 diff -r a2392c293916 -r ef63ca68695b a
157 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
158 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
158 +++ b/a Thu Jan 01 00:00:00 1970 +0000
159 +++ b/a Thu Jan 01 00:00:00 1970 +0000
159 @@ -0,0 +1,3 @@
160 @@ -0,0 +1,3 @@
160 +expand $Id$
161 +expand $Id$
161 +do not process $Id:
162 +do not process $Id:
162 +xxx $
163 +xxx $
163 diff -r a2392c293916 -r ef63ca68695b b
164 diff -r a2392c293916 -r ef63ca68695b b
164 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
165 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
165 +++ b/b Thu Jan 01 00:00:00 1970 +0000
166 +++ b/b Thu Jan 01 00:00:00 1970 +0000
166 @@ -0,0 +1,1 @@
167 @@ -0,0 +1,1 @@
167 +ignore $Id$
168 +ignore $Id$
168 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
169 % remove notify config
170 % remove notify config
170 % touch
171 % touch
171 % status
172 % status
172 % update
173 % update
173 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 % cat
175 % cat
175 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
176 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
176 do not process $Id:
177 do not process $Id:
177 xxx $
178 xxx $
178 ignore $Id$
179 ignore $Id$
179 % check whether expansion is filewise
180 % check whether expansion is filewise
180 % commit c
181 % commit c
181 adding c
182 adding c
182 % force expansion
183 % force expansion
183 overwriting a expanding keywords
184 overwriting a expanding keywords
184 overwriting c expanding keywords
185 overwriting c expanding keywords
185 % compare changenodes in a c
186 % compare changenodes in a c
186 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
187 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
187 do not process $Id:
188 do not process $Id:
188 xxx $
189 xxx $
189 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
190 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
190 tests for different changenodes
191 tests for different changenodes
191 % qinit -c
192 % qinit -c
192 % qimport
193 % qimport
193 % qcommit
194 % qcommit
194 % keywords should not be expanded in patch
195 % keywords should not be expanded in patch
195 # HG changeset patch
196 # HG changeset patch
196 # User User Name <user@example.com>
197 # User User Name <user@example.com>
197 # Date 1 0
198 # Date 1 0
198 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
199 # Node ID 40a904bbbe4cd4ab0a1f28411e35db26341a40ad
199 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
200 # Parent ef63ca68695bc9495032c6fda1350c71e6d256e9
200 cndiff
201 cndiff
201
202
202 diff -r ef63ca68695b -r 40a904bbbe4c c
203 diff -r ef63ca68695b -r 40a904bbbe4c c
203 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
204 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
204 +++ b/c Thu Jan 01 00:00:01 1970 +0000
205 +++ b/c Thu Jan 01 00:00:01 1970 +0000
205 @@ -0,0 +1,2 @@
206 @@ -0,0 +1,2 @@
206 +$Id$
207 +$Id$
207 +tests for different changenodes
208 +tests for different changenodes
208 % qpop
209 % qpop
209 Patch queue now empty
210 Patch queue now empty
210 % qgoto - should imply qpush
211 % qgoto - should imply qpush
211 applying mqtest.diff
212 applying mqtest.diff
212 Now at: mqtest.diff
213 Now at: mqtest.diff
213 % cat
214 % cat
214 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
215 $Id: c,v 40a904bbbe4c 1970/01/01 00:00:01 user $
215 tests for different changenodes
216 tests for different changenodes
216 % qpop and move on
217 % qpop and move on
217 Patch queue now empty
218 Patch queue now empty
218 % copy
219 % copy
219 % kwfiles added
220 % kwfiles added
220 a
221 a
221 c
222 c
222 % commit
223 % commit
223 c
224 c
224 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
225 c: copy a:0045e12f6c5791aac80ca6cbfd97709a88307292
225 overwriting c expanding keywords
226 overwriting c expanding keywords
227 committed changeset e22d299ac0c2
226 % cat a c
228 % cat a c
227 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
229 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
228 do not process $Id:
230 do not process $Id:
229 xxx $
231 xxx $
230 expand $Id: c,v e22d299ac0c2 1970/01/01 00:00:01 user $
232 expand $Id: c,v e22d299ac0c2 1970/01/01 00:00:01 user $
231 do not process $Id:
233 do not process $Id:
232 xxx $
234 xxx $
233 % touch copied c
235 % touch copied c
234 % status
236 % status
235 % kwfiles
237 % kwfiles
236 a
238 a
237 c
239 c
238 % diff --rev
240 % diff --rev
239 diff -r ef63ca68695b c
241 diff -r ef63ca68695b c
240 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
242 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
241 @@ -0,0 +1,3 @@
243 @@ -0,0 +1,3 @@
242 +expand $Id$
244 +expand $Id$
243 +do not process $Id:
245 +do not process $Id:
244 +xxx $
246 +xxx $
245 % rollback
247 % rollback
246 rolling back last transaction
248 rolling back last transaction
247 % status
249 % status
248 A c
250 A c
249 % update -C
251 % update -C
250 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
252 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
251 % custom keyword expansion
253 % custom keyword expansion
252 % try with kwdemo
254 % try with kwdemo
253 [extensions]
255 [extensions]
254 hgext.keyword =
256 hgext.keyword =
255 [keyword]
257 [keyword]
256 * =
258 * =
257 b = ignore
259 b = ignore
258 demo.txt =
260 demo.txt =
259 [keywordmaps]
261 [keywordmaps]
260 Xinfo = {author}: {desc}
262 Xinfo = {author}: {desc}
261 $Xinfo: test: hg keyword config and expansion example $
263 $Xinfo: test: hg keyword config and expansion example $
262 % cat
264 % cat
263 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
265 expand $Id: a,v ef63ca68695b 1970/01/01 00:00:00 user $
264 do not process $Id:
266 do not process $Id:
265 xxx $
267 xxx $
266 ignore $Id$
268 ignore $Id$
267 % hg cat
269 % hg cat
268 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
270 expand $Id: a ef63ca68695b Thu, 01 Jan 1970 00:00:00 +0000 user $
269 do not process $Id:
271 do not process $Id:
270 xxx $
272 xxx $
271 ignore $Id$
273 ignore $Id$
272 a
274 a
273 % interrupted commit should not change state
275 % interrupted commit should not change state
274 transaction abort!
276 transaction abort!
275 rollback completed
277 rollback completed
276 abort: empty commit message
278 abort: empty commit message
277 % status
279 % status
278 M a
280 M a
279 ? log
281 ? log
280 % commit
282 % commit
281 a
283 a
282 overwriting a expanding keywords
284 overwriting a expanding keywords
285 committed changeset bb948857c743
283 % status
286 % status
284 % verify
287 % verify
285 checking changesets
288 checking changesets
286 checking manifests
289 checking manifests
287 crosschecking files in changesets and manifests
290 crosschecking files in changesets and manifests
288 checking files
291 checking files
289 3 files, 3 changesets, 4 total revisions
292 3 files, 3 changesets, 4 total revisions
290 % cat
293 % cat
291 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
294 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
292 do not process $Id:
295 do not process $Id:
293 xxx $
296 xxx $
294 $Xinfo: User Name <user@example.com>: firstline $
297 $Xinfo: User Name <user@example.com>: firstline $
295 ignore $Id$
298 ignore $Id$
296 % hg cat
299 % hg cat
297 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
300 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
298 do not process $Id:
301 do not process $Id:
299 xxx $
302 xxx $
300 $Xinfo: User Name <user@example.com>: firstline $
303 $Xinfo: User Name <user@example.com>: firstline $
301 ignore $Id$
304 ignore $Id$
302 a
305 a
303 % annotate
306 % annotate
304 1: expand $Id$
307 1: expand $Id$
305 1: do not process $Id:
308 1: do not process $Id:
306 1: xxx $
309 1: xxx $
307 2: $Xinfo$
310 2: $Xinfo$
308 % remove
311 % remove
312 committed changeset d14c71265376
309 % status
313 % status
310 % rollback
314 % rollback
311 rolling back last transaction
315 rolling back last transaction
312 % status
316 % status
313 R a
317 R a
314 % revert a
318 % revert a
315 % cat a
319 % cat a
316 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
320 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
317 do not process $Id:
321 do not process $Id:
318 xxx $
322 xxx $
319 $Xinfo: User Name <user@example.com>: firstline $
323 $Xinfo: User Name <user@example.com>: firstline $
320 % clone to test incoming
324 % clone to test incoming
321 requesting all changes
325 requesting all changes
322 adding changesets
326 adding changesets
323 adding manifests
327 adding manifests
324 adding file changes
328 adding file changes
325 added 2 changesets with 3 changes to 3 files
329 added 2 changesets with 3 changes to 3 files
326 updating working directory
330 updating working directory
327 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
328 % incoming
332 % incoming
329 comparing with test-keyword/Test
333 comparing with test-keyword/Test
330 searching for changes
334 searching for changes
331 changeset: 2:bb948857c743
335 changeset: 2:bb948857c743
332 tag: tip
336 tag: tip
333 user: User Name <user@example.com>
337 user: User Name <user@example.com>
334 date: Thu Jan 01 00:00:02 1970 +0000
338 date: Thu Jan 01 00:00:02 1970 +0000
335 summary: firstline
339 summary: firstline
336
340
337 % commit rejecttest
341 % commit rejecttest
338 a
342 a
339 overwriting a expanding keywords
343 overwriting a expanding keywords
344 committed changeset 85e279d709ff
340 % export
345 % export
341 % import
346 % import
342 applying ../rejecttest.diff
347 applying ../rejecttest.diff
343 % cat
348 % cat
344 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
349 expand $Id: a 4e0994474d25 Thu, 01 Jan 1970 00:00:03 +0000 user $ rejecttest
345 do not process $Id: rejecttest
350 do not process $Id: rejecttest
346 xxx $
351 xxx $
347 $Xinfo: User Name <user@example.com>: rejects? $
352 $Xinfo: User Name <user@example.com>: rejects? $
348 ignore $Id$
353 ignore $Id$
349
354
350 % rollback
355 % rollback
351 rolling back last transaction
356 rolling back last transaction
352 % clean update
357 % clean update
353 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
354 % kwexpand/kwshrink on selected files
359 % kwexpand/kwshrink on selected files
355 % copy a x/a
360 % copy a x/a
356 % kwexpand a
361 % kwexpand a
357 overwriting a expanding keywords
362 overwriting a expanding keywords
358 % kwexpand x/a should abort
363 % kwexpand x/a should abort
359 abort: outstanding uncommitted changes
364 abort: outstanding uncommitted changes
360 x/a
365 x/a
361 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
366 x/a: copy a:779c764182ce5d43e2b1eb66ce06d7b47bfe342e
362 overwriting x/a expanding keywords
367 overwriting x/a expanding keywords
368 committed changeset cfa68229c116
363 % cat a
369 % cat a
364 expand $Id: x/a cfa68229c116 Thu, 01 Jan 1970 00:00:03 +0000 user $
370 expand $Id: x/a cfa68229c116 Thu, 01 Jan 1970 00:00:03 +0000 user $
365 do not process $Id:
371 do not process $Id:
366 xxx $
372 xxx $
367 $Xinfo: User Name <user@example.com>: xa $
373 $Xinfo: User Name <user@example.com>: xa $
368 % kwshrink a inside directory x
374 % kwshrink a inside directory x
369 overwriting x/a shrinking keywords
375 overwriting x/a shrinking keywords
370 % cat a
376 % cat a
371 expand $Id$
377 expand $Id$
372 do not process $Id:
378 do not process $Id:
373 xxx $
379 xxx $
374 $Xinfo$
380 $Xinfo$
375 % kwexpand nonexistent
381 % kwexpand nonexistent
376 nonexistent:
382 nonexistent:
377 % hg serve
383 % hg serve
378 % expansion
384 % expansion
379 % hgweb file
385 % hgweb file
380 200 Script output follows
386 200 Script output follows
381
387
382 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
388 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
383 do not process $Id:
389 do not process $Id:
384 xxx $
390 xxx $
385 $Xinfo: User Name <user@example.com>: firstline $
391 $Xinfo: User Name <user@example.com>: firstline $
386 % no expansion
392 % no expansion
387 % hgweb annotate
393 % hgweb annotate
388 200 Script output follows
394 200 Script output follows
389
395
390
396
391 User Name <user@example.com>@1: expand $Id$
397 User Name <user@example.com>@1: expand $Id$
392 User Name <user@example.com>@1: do not process $Id:
398 User Name <user@example.com>@1: do not process $Id:
393 User Name <user@example.com>@1: xxx $
399 User Name <user@example.com>@1: xxx $
394 User Name <user@example.com>@2: $Xinfo$
400 User Name <user@example.com>@2: $Xinfo$
395
401
396
402
397
403
398
404
399 % hgweb changeset
405 % hgweb changeset
400 200 Script output follows
406 200 Script output follows
401
407
402
408
403 # HG changeset patch
409 # HG changeset patch
404 # User User Name <user@example.com>
410 # User User Name <user@example.com>
405 # Date 3 0
411 # Date 3 0
406 # Node ID cfa68229c1167443337266ebac453c73b1d5d16e
412 # Node ID cfa68229c1167443337266ebac453c73b1d5d16e
407 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
413 # Parent bb948857c743469b22bbf51f7ec8112279ca5d83
408 xa
414 xa
409
415
410 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
416 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
411 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
417 +++ b/x/a Thu Jan 01 00:00:03 1970 +0000
412 @@ -0,0 +1,4 @@
418 @@ -0,0 +1,4 @@
413 +expand $Id$
419 +expand $Id$
414 +do not process $Id:
420 +do not process $Id:
415 +xxx $
421 +xxx $
416 +$Xinfo$
422 +$Xinfo$
417
423
418 % hgweb filediff
424 % hgweb filediff
419 200 Script output follows
425 200 Script output follows
420
426
421
427
422 --- a/a Thu Jan 01 00:00:00 1970 +0000
428 --- a/a Thu Jan 01 00:00:00 1970 +0000
423 +++ b/a Thu Jan 01 00:00:02 1970 +0000
429 +++ b/a Thu Jan 01 00:00:02 1970 +0000
424 @@ -1,3 +1,4 @@
430 @@ -1,3 +1,4 @@
425 expand $Id$
431 expand $Id$
426 do not process $Id:
432 do not process $Id:
427 xxx $
433 xxx $
428 +$Xinfo$
434 +$Xinfo$
429
435
430
436
431
437
432
438
433 % errors encountered
439 % errors encountered
434 % switch off expansion
440 % switch off expansion
435 % kwshrink with unknown file u
441 % kwshrink with unknown file u
436 overwriting a shrinking keywords
442 overwriting a shrinking keywords
437 overwriting x/a shrinking keywords
443 overwriting x/a shrinking keywords
438 % cat
444 % cat
439 expand $Id$
445 expand $Id$
440 do not process $Id:
446 do not process $Id:
441 xxx $
447 xxx $
442 $Xinfo$
448 $Xinfo$
443 ignore $Id$
449 ignore $Id$
444 % hg cat
450 % hg cat
445 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
451 expand $Id: a bb948857c743 Thu, 01 Jan 1970 00:00:02 +0000 user $
446 do not process $Id:
452 do not process $Id:
447 xxx $
453 xxx $
448 $Xinfo: User Name <user@example.com>: firstline $
454 $Xinfo: User Name <user@example.com>: firstline $
449 ignore $Id$
455 ignore $Id$
450 a
456 a
451 % cat
457 % cat
452 expand $Id$
458 expand $Id$
453 do not process $Id:
459 do not process $Id:
454 xxx $
460 xxx $
455 $Xinfo$
461 $Xinfo$
456 ignore $Id$
462 ignore $Id$
457 % hg cat
463 % hg cat
458 expand $Id$
464 expand $Id$
459 do not process $Id:
465 do not process $Id:
460 xxx $
466 xxx $
461 $Xinfo$
467 $Xinfo$
462 ignore $Id$
468 ignore $Id$
463 a
469 a
General Comments 0
You need to be logged in to leave comments. Login now