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