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