##// END OF EJS Templates
dispatch: show empty filename in OSError aborts...
Mads Kiilerich -
r18227:720308f7 default
parent child Browse files
Show More
@@ -1,831 +1,831 b''
1 # dispatch.py - command dispatching for mercurial
1 # dispatch.py - command dispatching for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
9 import os, sys, atexit, signal, pdb, socket, errno, shlex, time, traceback, re
10 import util, commands, hg, fancyopts, extensions, hook, error
10 import util, commands, hg, fancyopts, extensions, hook, error
11 import cmdutil, encoding
11 import cmdutil, encoding
12 import ui as uimod
12 import ui as uimod
13
13
14 class request(object):
14 class request(object):
15 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
15 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
16 ferr=None):
16 ferr=None):
17 self.args = args
17 self.args = args
18 self.ui = ui
18 self.ui = ui
19 self.repo = repo
19 self.repo = repo
20
20
21 # input/output/error streams
21 # input/output/error streams
22 self.fin = fin
22 self.fin = fin
23 self.fout = fout
23 self.fout = fout
24 self.ferr = ferr
24 self.ferr = ferr
25
25
26 def run():
26 def run():
27 "run the command in sys.argv"
27 "run the command in sys.argv"
28 sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
28 sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
29
29
30 def dispatch(req):
30 def dispatch(req):
31 "run the command specified in req.args"
31 "run the command specified in req.args"
32 if req.ferr:
32 if req.ferr:
33 ferr = req.ferr
33 ferr = req.ferr
34 elif req.ui:
34 elif req.ui:
35 ferr = req.ui.ferr
35 ferr = req.ui.ferr
36 else:
36 else:
37 ferr = sys.stderr
37 ferr = sys.stderr
38
38
39 try:
39 try:
40 if not req.ui:
40 if not req.ui:
41 req.ui = uimod.ui()
41 req.ui = uimod.ui()
42 if '--traceback' in req.args:
42 if '--traceback' in req.args:
43 req.ui.setconfig('ui', 'traceback', 'on')
43 req.ui.setconfig('ui', 'traceback', 'on')
44
44
45 # set ui streams from the request
45 # set ui streams from the request
46 if req.fin:
46 if req.fin:
47 req.ui.fin = req.fin
47 req.ui.fin = req.fin
48 if req.fout:
48 if req.fout:
49 req.ui.fout = req.fout
49 req.ui.fout = req.fout
50 if req.ferr:
50 if req.ferr:
51 req.ui.ferr = req.ferr
51 req.ui.ferr = req.ferr
52 except util.Abort, inst:
52 except util.Abort, inst:
53 ferr.write(_("abort: %s\n") % inst)
53 ferr.write(_("abort: %s\n") % inst)
54 if inst.hint:
54 if inst.hint:
55 ferr.write(_("(%s)\n") % inst.hint)
55 ferr.write(_("(%s)\n") % inst.hint)
56 return -1
56 return -1
57 except error.ParseError, inst:
57 except error.ParseError, inst:
58 if len(inst.args) > 1:
58 if len(inst.args) > 1:
59 ferr.write(_("hg: parse error at %s: %s\n") %
59 ferr.write(_("hg: parse error at %s: %s\n") %
60 (inst.args[1], inst.args[0]))
60 (inst.args[1], inst.args[0]))
61 else:
61 else:
62 ferr.write(_("hg: parse error: %s\n") % inst.args[0])
62 ferr.write(_("hg: parse error: %s\n") % inst.args[0])
63 return -1
63 return -1
64
64
65 return _runcatch(req)
65 return _runcatch(req)
66
66
67 def _runcatch(req):
67 def _runcatch(req):
68 def catchterm(*args):
68 def catchterm(*args):
69 raise error.SignalInterrupt
69 raise error.SignalInterrupt
70
70
71 ui = req.ui
71 ui = req.ui
72 try:
72 try:
73 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
73 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
74 num = getattr(signal, name, None)
74 num = getattr(signal, name, None)
75 if num:
75 if num:
76 signal.signal(num, catchterm)
76 signal.signal(num, catchterm)
77 except ValueError:
77 except ValueError:
78 pass # happens if called in a thread
78 pass # happens if called in a thread
79
79
80 try:
80 try:
81 try:
81 try:
82 # enter the debugger before command execution
82 # enter the debugger before command execution
83 if '--debugger' in req.args:
83 if '--debugger' in req.args:
84 ui.warn(_("entering debugger - "
84 ui.warn(_("entering debugger - "
85 "type c to continue starting hg or h for help\n"))
85 "type c to continue starting hg or h for help\n"))
86 pdb.set_trace()
86 pdb.set_trace()
87 try:
87 try:
88 return _dispatch(req)
88 return _dispatch(req)
89 finally:
89 finally:
90 ui.flush()
90 ui.flush()
91 except: # re-raises
91 except: # re-raises
92 # enter the debugger when we hit an exception
92 # enter the debugger when we hit an exception
93 if '--debugger' in req.args:
93 if '--debugger' in req.args:
94 traceback.print_exc()
94 traceback.print_exc()
95 pdb.post_mortem(sys.exc_info()[2])
95 pdb.post_mortem(sys.exc_info()[2])
96 ui.traceback()
96 ui.traceback()
97 raise
97 raise
98
98
99 # Global exception handling, alphabetically
99 # Global exception handling, alphabetically
100 # Mercurial-specific first, followed by built-in and library exceptions
100 # Mercurial-specific first, followed by built-in and library exceptions
101 except error.AmbiguousCommand, inst:
101 except error.AmbiguousCommand, inst:
102 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
102 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
103 (inst.args[0], " ".join(inst.args[1])))
103 (inst.args[0], " ".join(inst.args[1])))
104 except error.ParseError, inst:
104 except error.ParseError, inst:
105 if len(inst.args) > 1:
105 if len(inst.args) > 1:
106 ui.warn(_("hg: parse error at %s: %s\n") %
106 ui.warn(_("hg: parse error at %s: %s\n") %
107 (inst.args[1], inst.args[0]))
107 (inst.args[1], inst.args[0]))
108 else:
108 else:
109 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
109 ui.warn(_("hg: parse error: %s\n") % inst.args[0])
110 return -1
110 return -1
111 except error.LockHeld, inst:
111 except error.LockHeld, inst:
112 if inst.errno == errno.ETIMEDOUT:
112 if inst.errno == errno.ETIMEDOUT:
113 reason = _('timed out waiting for lock held by %s') % inst.locker
113 reason = _('timed out waiting for lock held by %s') % inst.locker
114 else:
114 else:
115 reason = _('lock held by %s') % inst.locker
115 reason = _('lock held by %s') % inst.locker
116 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
116 ui.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
117 except error.LockUnavailable, inst:
117 except error.LockUnavailable, inst:
118 ui.warn(_("abort: could not lock %s: %s\n") %
118 ui.warn(_("abort: could not lock %s: %s\n") %
119 (inst.desc or inst.filename, inst.strerror))
119 (inst.desc or inst.filename, inst.strerror))
120 except error.CommandError, inst:
120 except error.CommandError, inst:
121 if inst.args[0]:
121 if inst.args[0]:
122 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
122 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
123 commands.help_(ui, inst.args[0], full=False, command=True)
123 commands.help_(ui, inst.args[0], full=False, command=True)
124 else:
124 else:
125 ui.warn(_("hg: %s\n") % inst.args[1])
125 ui.warn(_("hg: %s\n") % inst.args[1])
126 commands.help_(ui, 'shortlist')
126 commands.help_(ui, 'shortlist')
127 except error.OutOfBandError, inst:
127 except error.OutOfBandError, inst:
128 ui.warn(_("abort: remote error:\n"))
128 ui.warn(_("abort: remote error:\n"))
129 ui.warn(''.join(inst.args))
129 ui.warn(''.join(inst.args))
130 except error.RepoError, inst:
130 except error.RepoError, inst:
131 ui.warn(_("abort: %s!\n") % inst)
131 ui.warn(_("abort: %s!\n") % inst)
132 if inst.hint:
132 if inst.hint:
133 ui.warn(_("(%s)\n") % inst.hint)
133 ui.warn(_("(%s)\n") % inst.hint)
134 except error.ResponseError, inst:
134 except error.ResponseError, inst:
135 ui.warn(_("abort: %s") % inst.args[0])
135 ui.warn(_("abort: %s") % inst.args[0])
136 if not isinstance(inst.args[1], basestring):
136 if not isinstance(inst.args[1], basestring):
137 ui.warn(" %r\n" % (inst.args[1],))
137 ui.warn(" %r\n" % (inst.args[1],))
138 elif not inst.args[1]:
138 elif not inst.args[1]:
139 ui.warn(_(" empty string\n"))
139 ui.warn(_(" empty string\n"))
140 else:
140 else:
141 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
141 ui.warn("\n%r\n" % util.ellipsis(inst.args[1]))
142 except error.RevlogError, inst:
142 except error.RevlogError, inst:
143 ui.warn(_("abort: %s!\n") % inst)
143 ui.warn(_("abort: %s!\n") % inst)
144 except error.SignalInterrupt:
144 except error.SignalInterrupt:
145 ui.warn(_("killed!\n"))
145 ui.warn(_("killed!\n"))
146 except error.UnknownCommand, inst:
146 except error.UnknownCommand, inst:
147 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
147 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
148 try:
148 try:
149 # check if the command is in a disabled extension
149 # check if the command is in a disabled extension
150 # (but don't check for extensions themselves)
150 # (but don't check for extensions themselves)
151 commands.help_(ui, inst.args[0], unknowncmd=True)
151 commands.help_(ui, inst.args[0], unknowncmd=True)
152 except error.UnknownCommand:
152 except error.UnknownCommand:
153 commands.help_(ui, 'shortlist')
153 commands.help_(ui, 'shortlist')
154 except util.Abort, inst:
154 except util.Abort, inst:
155 ui.warn(_("abort: %s\n") % inst)
155 ui.warn(_("abort: %s\n") % inst)
156 if inst.hint:
156 if inst.hint:
157 ui.warn(_("(%s)\n") % inst.hint)
157 ui.warn(_("(%s)\n") % inst.hint)
158 except ImportError, inst:
158 except ImportError, inst:
159 ui.warn(_("abort: %s!\n") % inst)
159 ui.warn(_("abort: %s!\n") % inst)
160 m = str(inst).split()[-1]
160 m = str(inst).split()[-1]
161 if m in "mpatch bdiff".split():
161 if m in "mpatch bdiff".split():
162 ui.warn(_("(did you forget to compile extensions?)\n"))
162 ui.warn(_("(did you forget to compile extensions?)\n"))
163 elif m in "zlib".split():
163 elif m in "zlib".split():
164 ui.warn(_("(is your Python install correct?)\n"))
164 ui.warn(_("(is your Python install correct?)\n"))
165 except IOError, inst:
165 except IOError, inst:
166 if util.safehasattr(inst, "code"):
166 if util.safehasattr(inst, "code"):
167 ui.warn(_("abort: %s\n") % inst)
167 ui.warn(_("abort: %s\n") % inst)
168 elif util.safehasattr(inst, "reason"):
168 elif util.safehasattr(inst, "reason"):
169 try: # usually it is in the form (errno, strerror)
169 try: # usually it is in the form (errno, strerror)
170 reason = inst.reason.args[1]
170 reason = inst.reason.args[1]
171 except (AttributeError, IndexError):
171 except (AttributeError, IndexError):
172 # it might be anything, for example a string
172 # it might be anything, for example a string
173 reason = inst.reason
173 reason = inst.reason
174 ui.warn(_("abort: error: %s\n") % reason)
174 ui.warn(_("abort: error: %s\n") % reason)
175 elif util.safehasattr(inst, "args") and inst.args[0] == errno.EPIPE:
175 elif util.safehasattr(inst, "args") and inst.args[0] == errno.EPIPE:
176 if ui.debugflag:
176 if ui.debugflag:
177 ui.warn(_("broken pipe\n"))
177 ui.warn(_("broken pipe\n"))
178 elif getattr(inst, "strerror", None):
178 elif getattr(inst, "strerror", None):
179 if getattr(inst, "filename", None):
179 if getattr(inst, "filename", None):
180 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
180 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
181 else:
181 else:
182 ui.warn(_("abort: %s\n") % inst.strerror)
182 ui.warn(_("abort: %s\n") % inst.strerror)
183 else:
183 else:
184 raise
184 raise
185 except OSError, inst:
185 except OSError, inst:
186 if getattr(inst, "filename", None):
186 if getattr(inst, "filename", None) is not None:
187 ui.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
187 ui.warn(_("abort: %s: '%s'\n") % (inst.strerror, inst.filename))
188 else:
188 else:
189 ui.warn(_("abort: %s\n") % inst.strerror)
189 ui.warn(_("abort: %s\n") % inst.strerror)
190 except KeyboardInterrupt:
190 except KeyboardInterrupt:
191 try:
191 try:
192 ui.warn(_("interrupted!\n"))
192 ui.warn(_("interrupted!\n"))
193 except IOError, inst:
193 except IOError, inst:
194 if inst.errno == errno.EPIPE:
194 if inst.errno == errno.EPIPE:
195 if ui.debugflag:
195 if ui.debugflag:
196 ui.warn(_("\nbroken pipe\n"))
196 ui.warn(_("\nbroken pipe\n"))
197 else:
197 else:
198 raise
198 raise
199 except MemoryError:
199 except MemoryError:
200 ui.warn(_("abort: out of memory\n"))
200 ui.warn(_("abort: out of memory\n"))
201 except SystemExit, inst:
201 except SystemExit, inst:
202 # Commands shouldn't sys.exit directly, but give a return code.
202 # Commands shouldn't sys.exit directly, but give a return code.
203 # Just in case catch this and and pass exit code to caller.
203 # Just in case catch this and and pass exit code to caller.
204 return inst.code
204 return inst.code
205 except socket.error, inst:
205 except socket.error, inst:
206 ui.warn(_("abort: %s\n") % inst.args[-1])
206 ui.warn(_("abort: %s\n") % inst.args[-1])
207 except: # re-raises
207 except: # re-raises
208 myver = util.version()
208 myver = util.version()
209 # For compatibility checking, we discard the portion of the hg
209 # For compatibility checking, we discard the portion of the hg
210 # version after the + on the assumption that if a "normal
210 # version after the + on the assumption that if a "normal
211 # user" is running a build with a + in it the packager
211 # user" is running a build with a + in it the packager
212 # probably built from fairly close to a tag and anyone with a
212 # probably built from fairly close to a tag and anyone with a
213 # 'make local' copy of hg (where the version number can be out
213 # 'make local' copy of hg (where the version number can be out
214 # of date) will be clueful enough to notice the implausible
214 # of date) will be clueful enough to notice the implausible
215 # version number and try updating.
215 # version number and try updating.
216 compare = myver.split('+')[0]
216 compare = myver.split('+')[0]
217 ct = tuplever(compare)
217 ct = tuplever(compare)
218 worst = None, ct, ''
218 worst = None, ct, ''
219 for name, mod in extensions.extensions():
219 for name, mod in extensions.extensions():
220 testedwith = getattr(mod, 'testedwith', '')
220 testedwith = getattr(mod, 'testedwith', '')
221 report = getattr(mod, 'buglink', _('the extension author.'))
221 report = getattr(mod, 'buglink', _('the extension author.'))
222 if not testedwith.strip():
222 if not testedwith.strip():
223 # We found an untested extension. It's likely the culprit.
223 # We found an untested extension. It's likely the culprit.
224 worst = name, 'unknown', report
224 worst = name, 'unknown', report
225 break
225 break
226 if compare not in testedwith.split() and testedwith != 'internal':
226 if compare not in testedwith.split() and testedwith != 'internal':
227 tested = [tuplever(v) for v in testedwith.split()]
227 tested = [tuplever(v) for v in testedwith.split()]
228 lower = [t for t in tested if t < ct]
228 lower = [t for t in tested if t < ct]
229 nearest = max(lower or tested)
229 nearest = max(lower or tested)
230 if worst[0] is None or nearest < worst[1]:
230 if worst[0] is None or nearest < worst[1]:
231 worst = name, nearest, report
231 worst = name, nearest, report
232 if worst[0] is not None:
232 if worst[0] is not None:
233 name, testedwith, report = worst
233 name, testedwith, report = worst
234 if not isinstance(testedwith, str):
234 if not isinstance(testedwith, str):
235 testedwith = '.'.join([str(c) for c in testedwith])
235 testedwith = '.'.join([str(c) for c in testedwith])
236 warning = (_('** Unknown exception encountered with '
236 warning = (_('** Unknown exception encountered with '
237 'possibly-broken third-party extension %s\n'
237 'possibly-broken third-party extension %s\n'
238 '** which supports versions %s of Mercurial.\n'
238 '** which supports versions %s of Mercurial.\n'
239 '** Please disable %s and try your action again.\n'
239 '** Please disable %s and try your action again.\n'
240 '** If that fixes the bug please report it to %s\n')
240 '** If that fixes the bug please report it to %s\n')
241 % (name, testedwith, name, report))
241 % (name, testedwith, name, report))
242 else:
242 else:
243 warning = (_("** unknown exception encountered, "
243 warning = (_("** unknown exception encountered, "
244 "please report by visiting\n") +
244 "please report by visiting\n") +
245 _("** http://mercurial.selenic.com/wiki/BugTracker\n"))
245 _("** http://mercurial.selenic.com/wiki/BugTracker\n"))
246 warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
246 warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
247 (_("** Mercurial Distributed SCM (version %s)\n") % myver) +
247 (_("** Mercurial Distributed SCM (version %s)\n") % myver) +
248 (_("** Extensions loaded: %s\n") %
248 (_("** Extensions loaded: %s\n") %
249 ", ".join([x[0] for x in extensions.extensions()])))
249 ", ".join([x[0] for x in extensions.extensions()])))
250 ui.warn(warning)
250 ui.warn(warning)
251 raise
251 raise
252
252
253 return -1
253 return -1
254
254
255 def tuplever(v):
255 def tuplever(v):
256 try:
256 try:
257 return tuple([int(i) for i in v.split('.')])
257 return tuple([int(i) for i in v.split('.')])
258 except ValueError:
258 except ValueError:
259 return tuple()
259 return tuple()
260
260
261 def aliasargs(fn, givenargs):
261 def aliasargs(fn, givenargs):
262 args = getattr(fn, 'args', [])
262 args = getattr(fn, 'args', [])
263 if args:
263 if args:
264 cmd = ' '.join(map(util.shellquote, args))
264 cmd = ' '.join(map(util.shellquote, args))
265
265
266 nums = []
266 nums = []
267 def replacer(m):
267 def replacer(m):
268 num = int(m.group(1)) - 1
268 num = int(m.group(1)) - 1
269 nums.append(num)
269 nums.append(num)
270 if num < len(givenargs):
270 if num < len(givenargs):
271 return givenargs[num]
271 return givenargs[num]
272 raise util.Abort(_('too few arguments for command alias'))
272 raise util.Abort(_('too few arguments for command alias'))
273 cmd = re.sub(r'\$(\d+|\$)', replacer, cmd)
273 cmd = re.sub(r'\$(\d+|\$)', replacer, cmd)
274 givenargs = [x for i, x in enumerate(givenargs)
274 givenargs = [x for i, x in enumerate(givenargs)
275 if i not in nums]
275 if i not in nums]
276 args = shlex.split(cmd)
276 args = shlex.split(cmd)
277 return args + givenargs
277 return args + givenargs
278
278
279 class cmdalias(object):
279 class cmdalias(object):
280 def __init__(self, name, definition, cmdtable):
280 def __init__(self, name, definition, cmdtable):
281 self.name = self.cmd = name
281 self.name = self.cmd = name
282 self.cmdname = ''
282 self.cmdname = ''
283 self.definition = definition
283 self.definition = definition
284 self.args = []
284 self.args = []
285 self.opts = []
285 self.opts = []
286 self.help = ''
286 self.help = ''
287 self.norepo = True
287 self.norepo = True
288 self.optionalrepo = False
288 self.optionalrepo = False
289 self.badalias = False
289 self.badalias = False
290
290
291 try:
291 try:
292 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
292 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
293 for alias, e in cmdtable.iteritems():
293 for alias, e in cmdtable.iteritems():
294 if e is entry:
294 if e is entry:
295 self.cmd = alias
295 self.cmd = alias
296 break
296 break
297 self.shadows = True
297 self.shadows = True
298 except error.UnknownCommand:
298 except error.UnknownCommand:
299 self.shadows = False
299 self.shadows = False
300
300
301 if not self.definition:
301 if not self.definition:
302 def fn(ui, *args):
302 def fn(ui, *args):
303 ui.warn(_("no definition for alias '%s'\n") % self.name)
303 ui.warn(_("no definition for alias '%s'\n") % self.name)
304 return 1
304 return 1
305 self.fn = fn
305 self.fn = fn
306 self.badalias = True
306 self.badalias = True
307 return
307 return
308
308
309 if self.definition.startswith('!'):
309 if self.definition.startswith('!'):
310 self.shell = True
310 self.shell = True
311 def fn(ui, *args):
311 def fn(ui, *args):
312 env = {'HG_ARGS': ' '.join((self.name,) + args)}
312 env = {'HG_ARGS': ' '.join((self.name,) + args)}
313 def _checkvar(m):
313 def _checkvar(m):
314 if m.groups()[0] == '$':
314 if m.groups()[0] == '$':
315 return m.group()
315 return m.group()
316 elif int(m.groups()[0]) <= len(args):
316 elif int(m.groups()[0]) <= len(args):
317 return m.group()
317 return m.group()
318 else:
318 else:
319 ui.debug("No argument found for substitution "
319 ui.debug("No argument found for substitution "
320 "of %i variable in alias '%s' definition."
320 "of %i variable in alias '%s' definition."
321 % (int(m.groups()[0]), self.name))
321 % (int(m.groups()[0]), self.name))
322 return ''
322 return ''
323 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
323 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
324 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
324 replace = dict((str(i + 1), arg) for i, arg in enumerate(args))
325 replace['0'] = self.name
325 replace['0'] = self.name
326 replace['@'] = ' '.join(args)
326 replace['@'] = ' '.join(args)
327 cmd = util.interpolate(r'\$', replace, cmd, escape_prefix=True)
327 cmd = util.interpolate(r'\$', replace, cmd, escape_prefix=True)
328 return util.system(cmd, environ=env, out=ui.fout)
328 return util.system(cmd, environ=env, out=ui.fout)
329 self.fn = fn
329 self.fn = fn
330 return
330 return
331
331
332 args = shlex.split(self.definition)
332 args = shlex.split(self.definition)
333 self.cmdname = cmd = args.pop(0)
333 self.cmdname = cmd = args.pop(0)
334 args = map(util.expandpath, args)
334 args = map(util.expandpath, args)
335
335
336 for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
336 for invalidarg in ("--cwd", "-R", "--repository", "--repo"):
337 if _earlygetopt([invalidarg], args):
337 if _earlygetopt([invalidarg], args):
338 def fn(ui, *args):
338 def fn(ui, *args):
339 ui.warn(_("error in definition for alias '%s': %s may only "
339 ui.warn(_("error in definition for alias '%s': %s may only "
340 "be given on the command line\n")
340 "be given on the command line\n")
341 % (self.name, invalidarg))
341 % (self.name, invalidarg))
342 return 1
342 return 1
343
343
344 self.fn = fn
344 self.fn = fn
345 self.badalias = True
345 self.badalias = True
346 return
346 return
347
347
348 try:
348 try:
349 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
349 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
350 if len(tableentry) > 2:
350 if len(tableentry) > 2:
351 self.fn, self.opts, self.help = tableentry
351 self.fn, self.opts, self.help = tableentry
352 else:
352 else:
353 self.fn, self.opts = tableentry
353 self.fn, self.opts = tableentry
354
354
355 self.args = aliasargs(self.fn, args)
355 self.args = aliasargs(self.fn, args)
356 if cmd not in commands.norepo.split(' '):
356 if cmd not in commands.norepo.split(' '):
357 self.norepo = False
357 self.norepo = False
358 if cmd in commands.optionalrepo.split(' '):
358 if cmd in commands.optionalrepo.split(' '):
359 self.optionalrepo = True
359 self.optionalrepo = True
360 if self.help.startswith("hg " + cmd):
360 if self.help.startswith("hg " + cmd):
361 # drop prefix in old-style help lines so hg shows the alias
361 # drop prefix in old-style help lines so hg shows the alias
362 self.help = self.help[4 + len(cmd):]
362 self.help = self.help[4 + len(cmd):]
363 self.__doc__ = self.fn.__doc__
363 self.__doc__ = self.fn.__doc__
364
364
365 except error.UnknownCommand:
365 except error.UnknownCommand:
366 def fn(ui, *args):
366 def fn(ui, *args):
367 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
367 ui.warn(_("alias '%s' resolves to unknown command '%s'\n") \
368 % (self.name, cmd))
368 % (self.name, cmd))
369 try:
369 try:
370 # check if the command is in a disabled extension
370 # check if the command is in a disabled extension
371 commands.help_(ui, cmd, unknowncmd=True)
371 commands.help_(ui, cmd, unknowncmd=True)
372 except error.UnknownCommand:
372 except error.UnknownCommand:
373 pass
373 pass
374 return 1
374 return 1
375 self.fn = fn
375 self.fn = fn
376 self.badalias = True
376 self.badalias = True
377 except error.AmbiguousCommand:
377 except error.AmbiguousCommand:
378 def fn(ui, *args):
378 def fn(ui, *args):
379 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
379 ui.warn(_("alias '%s' resolves to ambiguous command '%s'\n") \
380 % (self.name, cmd))
380 % (self.name, cmd))
381 return 1
381 return 1
382 self.fn = fn
382 self.fn = fn
383 self.badalias = True
383 self.badalias = True
384
384
385 def __call__(self, ui, *args, **opts):
385 def __call__(self, ui, *args, **opts):
386 if self.shadows:
386 if self.shadows:
387 ui.debug("alias '%s' shadows command '%s'\n" %
387 ui.debug("alias '%s' shadows command '%s'\n" %
388 (self.name, self.cmdname))
388 (self.name, self.cmdname))
389
389
390 if util.safehasattr(self, 'shell'):
390 if util.safehasattr(self, 'shell'):
391 return self.fn(ui, *args, **opts)
391 return self.fn(ui, *args, **opts)
392 else:
392 else:
393 try:
393 try:
394 util.checksignature(self.fn)(ui, *args, **opts)
394 util.checksignature(self.fn)(ui, *args, **opts)
395 except error.SignatureError:
395 except error.SignatureError:
396 args = ' '.join([self.cmdname] + self.args)
396 args = ' '.join([self.cmdname] + self.args)
397 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
397 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
398 raise
398 raise
399
399
400 def addaliases(ui, cmdtable):
400 def addaliases(ui, cmdtable):
401 # aliases are processed after extensions have been loaded, so they
401 # aliases are processed after extensions have been loaded, so they
402 # may use extension commands. Aliases can also use other alias definitions,
402 # may use extension commands. Aliases can also use other alias definitions,
403 # but only if they have been defined prior to the current definition.
403 # but only if they have been defined prior to the current definition.
404 for alias, definition in ui.configitems('alias'):
404 for alias, definition in ui.configitems('alias'):
405 aliasdef = cmdalias(alias, definition, cmdtable)
405 aliasdef = cmdalias(alias, definition, cmdtable)
406
406
407 try:
407 try:
408 olddef = cmdtable[aliasdef.cmd][0]
408 olddef = cmdtable[aliasdef.cmd][0]
409 if olddef.definition == aliasdef.definition:
409 if olddef.definition == aliasdef.definition:
410 continue
410 continue
411 except (KeyError, AttributeError):
411 except (KeyError, AttributeError):
412 # definition might not exist or it might not be a cmdalias
412 # definition might not exist or it might not be a cmdalias
413 pass
413 pass
414
414
415 cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
415 cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
416 if aliasdef.norepo:
416 if aliasdef.norepo:
417 commands.norepo += ' %s' % alias
417 commands.norepo += ' %s' % alias
418 if aliasdef.optionalrepo:
418 if aliasdef.optionalrepo:
419 commands.optionalrepo += ' %s' % alias
419 commands.optionalrepo += ' %s' % alias
420
420
421 def _parse(ui, args):
421 def _parse(ui, args):
422 options = {}
422 options = {}
423 cmdoptions = {}
423 cmdoptions = {}
424
424
425 try:
425 try:
426 args = fancyopts.fancyopts(args, commands.globalopts, options)
426 args = fancyopts.fancyopts(args, commands.globalopts, options)
427 except fancyopts.getopt.GetoptError, inst:
427 except fancyopts.getopt.GetoptError, inst:
428 raise error.CommandError(None, inst)
428 raise error.CommandError(None, inst)
429
429
430 if args:
430 if args:
431 cmd, args = args[0], args[1:]
431 cmd, args = args[0], args[1:]
432 aliases, entry = cmdutil.findcmd(cmd, commands.table,
432 aliases, entry = cmdutil.findcmd(cmd, commands.table,
433 ui.configbool("ui", "strict"))
433 ui.configbool("ui", "strict"))
434 cmd = aliases[0]
434 cmd = aliases[0]
435 args = aliasargs(entry[0], args)
435 args = aliasargs(entry[0], args)
436 defaults = ui.config("defaults", cmd)
436 defaults = ui.config("defaults", cmd)
437 if defaults:
437 if defaults:
438 args = map(util.expandpath, shlex.split(defaults)) + args
438 args = map(util.expandpath, shlex.split(defaults)) + args
439 c = list(entry[1])
439 c = list(entry[1])
440 else:
440 else:
441 cmd = None
441 cmd = None
442 c = []
442 c = []
443
443
444 # combine global options into local
444 # combine global options into local
445 for o in commands.globalopts:
445 for o in commands.globalopts:
446 c.append((o[0], o[1], options[o[1]], o[3]))
446 c.append((o[0], o[1], options[o[1]], o[3]))
447
447
448 try:
448 try:
449 args = fancyopts.fancyopts(args, c, cmdoptions, True)
449 args = fancyopts.fancyopts(args, c, cmdoptions, True)
450 except fancyopts.getopt.GetoptError, inst:
450 except fancyopts.getopt.GetoptError, inst:
451 raise error.CommandError(cmd, inst)
451 raise error.CommandError(cmd, inst)
452
452
453 # separate global options back out
453 # separate global options back out
454 for o in commands.globalopts:
454 for o in commands.globalopts:
455 n = o[1]
455 n = o[1]
456 options[n] = cmdoptions[n]
456 options[n] = cmdoptions[n]
457 del cmdoptions[n]
457 del cmdoptions[n]
458
458
459 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
459 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
460
460
461 def _parseconfig(ui, config):
461 def _parseconfig(ui, config):
462 """parse the --config options from the command line"""
462 """parse the --config options from the command line"""
463 configs = []
463 configs = []
464
464
465 for cfg in config:
465 for cfg in config:
466 try:
466 try:
467 name, value = cfg.split('=', 1)
467 name, value = cfg.split('=', 1)
468 section, name = name.split('.', 1)
468 section, name = name.split('.', 1)
469 if not section or not name:
469 if not section or not name:
470 raise IndexError
470 raise IndexError
471 ui.setconfig(section, name, value)
471 ui.setconfig(section, name, value)
472 configs.append((section, name, value))
472 configs.append((section, name, value))
473 except (IndexError, ValueError):
473 except (IndexError, ValueError):
474 raise util.Abort(_('malformed --config option: %r '
474 raise util.Abort(_('malformed --config option: %r '
475 '(use --config section.name=value)') % cfg)
475 '(use --config section.name=value)') % cfg)
476
476
477 return configs
477 return configs
478
478
479 def _earlygetopt(aliases, args):
479 def _earlygetopt(aliases, args):
480 """Return list of values for an option (or aliases).
480 """Return list of values for an option (or aliases).
481
481
482 The values are listed in the order they appear in args.
482 The values are listed in the order they appear in args.
483 The options and values are removed from args.
483 The options and values are removed from args.
484 """
484 """
485 try:
485 try:
486 argcount = args.index("--")
486 argcount = args.index("--")
487 except ValueError:
487 except ValueError:
488 argcount = len(args)
488 argcount = len(args)
489 shortopts = [opt for opt in aliases if len(opt) == 2]
489 shortopts = [opt for opt in aliases if len(opt) == 2]
490 values = []
490 values = []
491 pos = 0
491 pos = 0
492 while pos < argcount:
492 while pos < argcount:
493 if args[pos] in aliases:
493 if args[pos] in aliases:
494 if pos + 1 >= argcount:
494 if pos + 1 >= argcount:
495 # ignore and let getopt report an error if there is no value
495 # ignore and let getopt report an error if there is no value
496 break
496 break
497 del args[pos]
497 del args[pos]
498 values.append(args.pop(pos))
498 values.append(args.pop(pos))
499 argcount -= 2
499 argcount -= 2
500 elif args[pos][:2] in shortopts:
500 elif args[pos][:2] in shortopts:
501 # short option can have no following space, e.g. hg log -Rfoo
501 # short option can have no following space, e.g. hg log -Rfoo
502 values.append(args.pop(pos)[2:])
502 values.append(args.pop(pos)[2:])
503 argcount -= 1
503 argcount -= 1
504 else:
504 else:
505 pos += 1
505 pos += 1
506 return values
506 return values
507
507
508 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
508 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
509 # run pre-hook, and abort if it fails
509 # run pre-hook, and abort if it fails
510 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
510 ret = hook.hook(lui, repo, "pre-%s" % cmd, False, args=" ".join(fullargs),
511 pats=cmdpats, opts=cmdoptions)
511 pats=cmdpats, opts=cmdoptions)
512 if ret:
512 if ret:
513 return ret
513 return ret
514 ret = _runcommand(ui, options, cmd, d)
514 ret = _runcommand(ui, options, cmd, d)
515 # run post-hook, passing command result
515 # run post-hook, passing command result
516 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
516 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
517 result=ret, pats=cmdpats, opts=cmdoptions)
517 result=ret, pats=cmdpats, opts=cmdoptions)
518 return ret
518 return ret
519
519
520 def _getlocal(ui, rpath):
520 def _getlocal(ui, rpath):
521 """Return (path, local ui object) for the given target path.
521 """Return (path, local ui object) for the given target path.
522
522
523 Takes paths in [cwd]/.hg/hgrc into account."
523 Takes paths in [cwd]/.hg/hgrc into account."
524 """
524 """
525 try:
525 try:
526 wd = os.getcwd()
526 wd = os.getcwd()
527 except OSError, e:
527 except OSError, e:
528 raise util.Abort(_("error getting current working directory: %s") %
528 raise util.Abort(_("error getting current working directory: %s") %
529 e.strerror)
529 e.strerror)
530 path = cmdutil.findrepo(wd) or ""
530 path = cmdutil.findrepo(wd) or ""
531 if not path:
531 if not path:
532 lui = ui
532 lui = ui
533 else:
533 else:
534 lui = ui.copy()
534 lui = ui.copy()
535 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
535 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
536
536
537 if rpath and rpath[-1]:
537 if rpath and rpath[-1]:
538 path = lui.expandpath(rpath[-1])
538 path = lui.expandpath(rpath[-1])
539 lui = ui.copy()
539 lui = ui.copy()
540 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
540 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
541
541
542 return path, lui
542 return path, lui
543
543
544 def _checkshellalias(lui, ui, args):
544 def _checkshellalias(lui, ui, args):
545 options = {}
545 options = {}
546
546
547 try:
547 try:
548 args = fancyopts.fancyopts(args, commands.globalopts, options)
548 args = fancyopts.fancyopts(args, commands.globalopts, options)
549 except fancyopts.getopt.GetoptError:
549 except fancyopts.getopt.GetoptError:
550 return
550 return
551
551
552 if not args:
552 if not args:
553 return
553 return
554
554
555 norepo = commands.norepo
555 norepo = commands.norepo
556 optionalrepo = commands.optionalrepo
556 optionalrepo = commands.optionalrepo
557 def restorecommands():
557 def restorecommands():
558 commands.norepo = norepo
558 commands.norepo = norepo
559 commands.optionalrepo = optionalrepo
559 commands.optionalrepo = optionalrepo
560
560
561 cmdtable = commands.table.copy()
561 cmdtable = commands.table.copy()
562 addaliases(lui, cmdtable)
562 addaliases(lui, cmdtable)
563
563
564 cmd = args[0]
564 cmd = args[0]
565 try:
565 try:
566 aliases, entry = cmdutil.findcmd(cmd, cmdtable,
566 aliases, entry = cmdutil.findcmd(cmd, cmdtable,
567 lui.configbool("ui", "strict"))
567 lui.configbool("ui", "strict"))
568 except (error.AmbiguousCommand, error.UnknownCommand):
568 except (error.AmbiguousCommand, error.UnknownCommand):
569 restorecommands()
569 restorecommands()
570 return
570 return
571
571
572 cmd = aliases[0]
572 cmd = aliases[0]
573 fn = entry[0]
573 fn = entry[0]
574
574
575 if cmd and util.safehasattr(fn, 'shell'):
575 if cmd and util.safehasattr(fn, 'shell'):
576 d = lambda: fn(ui, *args[1:])
576 d = lambda: fn(ui, *args[1:])
577 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
577 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
578 [], {})
578 [], {})
579
579
580 restorecommands()
580 restorecommands()
581
581
582 _loaded = set()
582 _loaded = set()
583 def _dispatch(req):
583 def _dispatch(req):
584 args = req.args
584 args = req.args
585 ui = req.ui
585 ui = req.ui
586
586
587 # read --config before doing anything else
587 # read --config before doing anything else
588 # (e.g. to change trust settings for reading .hg/hgrc)
588 # (e.g. to change trust settings for reading .hg/hgrc)
589 cfgs = _parseconfig(ui, _earlygetopt(['--config'], args))
589 cfgs = _parseconfig(ui, _earlygetopt(['--config'], args))
590
590
591 # check for cwd
591 # check for cwd
592 cwd = _earlygetopt(['--cwd'], args)
592 cwd = _earlygetopt(['--cwd'], args)
593 if cwd:
593 if cwd:
594 os.chdir(cwd[-1])
594 os.chdir(cwd[-1])
595
595
596 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
596 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
597 path, lui = _getlocal(ui, rpath)
597 path, lui = _getlocal(ui, rpath)
598
598
599 # Now that we're operating in the right directory/repository with
599 # Now that we're operating in the right directory/repository with
600 # the right config settings, check for shell aliases
600 # the right config settings, check for shell aliases
601 shellaliasfn = _checkshellalias(lui, ui, args)
601 shellaliasfn = _checkshellalias(lui, ui, args)
602 if shellaliasfn:
602 if shellaliasfn:
603 return shellaliasfn()
603 return shellaliasfn()
604
604
605 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
605 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
606 # reposetup. Programs like TortoiseHg will call _dispatch several
606 # reposetup. Programs like TortoiseHg will call _dispatch several
607 # times so we keep track of configured extensions in _loaded.
607 # times so we keep track of configured extensions in _loaded.
608 extensions.loadall(lui)
608 extensions.loadall(lui)
609 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
609 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
610 # Propagate any changes to lui.__class__ by extensions
610 # Propagate any changes to lui.__class__ by extensions
611 ui.__class__ = lui.__class__
611 ui.__class__ = lui.__class__
612
612
613 # (uisetup and extsetup are handled in extensions.loadall)
613 # (uisetup and extsetup are handled in extensions.loadall)
614
614
615 for name, module in exts:
615 for name, module in exts:
616 cmdtable = getattr(module, 'cmdtable', {})
616 cmdtable = getattr(module, 'cmdtable', {})
617 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
617 overrides = [cmd for cmd in cmdtable if cmd in commands.table]
618 if overrides:
618 if overrides:
619 ui.warn(_("extension '%s' overrides commands: %s\n")
619 ui.warn(_("extension '%s' overrides commands: %s\n")
620 % (name, " ".join(overrides)))
620 % (name, " ".join(overrides)))
621 commands.table.update(cmdtable)
621 commands.table.update(cmdtable)
622 _loaded.add(name)
622 _loaded.add(name)
623
623
624 # (reposetup is handled in hg.repository)
624 # (reposetup is handled in hg.repository)
625
625
626 addaliases(lui, commands.table)
626 addaliases(lui, commands.table)
627
627
628 # check for fallback encoding
628 # check for fallback encoding
629 fallback = lui.config('ui', 'fallbackencoding')
629 fallback = lui.config('ui', 'fallbackencoding')
630 if fallback:
630 if fallback:
631 encoding.fallbackencoding = fallback
631 encoding.fallbackencoding = fallback
632
632
633 fullargs = args
633 fullargs = args
634 cmd, func, args, options, cmdoptions = _parse(lui, args)
634 cmd, func, args, options, cmdoptions = _parse(lui, args)
635
635
636 if options["config"]:
636 if options["config"]:
637 raise util.Abort(_("option --config may not be abbreviated!"))
637 raise util.Abort(_("option --config may not be abbreviated!"))
638 if options["cwd"]:
638 if options["cwd"]:
639 raise util.Abort(_("option --cwd may not be abbreviated!"))
639 raise util.Abort(_("option --cwd may not be abbreviated!"))
640 if options["repository"]:
640 if options["repository"]:
641 raise util.Abort(_(
641 raise util.Abort(_(
642 "option -R has to be separated from other options (e.g. not -qR) "
642 "option -R has to be separated from other options (e.g. not -qR) "
643 "and --repository may only be abbreviated as --repo!"))
643 "and --repository may only be abbreviated as --repo!"))
644
644
645 if options["encoding"]:
645 if options["encoding"]:
646 encoding.encoding = options["encoding"]
646 encoding.encoding = options["encoding"]
647 if options["encodingmode"]:
647 if options["encodingmode"]:
648 encoding.encodingmode = options["encodingmode"]
648 encoding.encodingmode = options["encodingmode"]
649 if options["time"]:
649 if options["time"]:
650 def get_times():
650 def get_times():
651 t = os.times()
651 t = os.times()
652 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
652 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
653 t = (t[0], t[1], t[2], t[3], time.clock())
653 t = (t[0], t[1], t[2], t[3], time.clock())
654 return t
654 return t
655 s = get_times()
655 s = get_times()
656 def print_time():
656 def print_time():
657 t = get_times()
657 t = get_times()
658 ui.warn(_("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
658 ui.warn(_("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
659 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
659 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
660 atexit.register(print_time)
660 atexit.register(print_time)
661
661
662 uis = set([ui, lui])
662 uis = set([ui, lui])
663
663
664 if req.repo:
664 if req.repo:
665 uis.add(req.repo.ui)
665 uis.add(req.repo.ui)
666
666
667 # copy configs that were passed on the cmdline (--config) to the repo ui
667 # copy configs that were passed on the cmdline (--config) to the repo ui
668 for cfg in cfgs:
668 for cfg in cfgs:
669 req.repo.ui.setconfig(*cfg)
669 req.repo.ui.setconfig(*cfg)
670
670
671 if options['verbose'] or options['debug'] or options['quiet']:
671 if options['verbose'] or options['debug'] or options['quiet']:
672 for opt in ('verbose', 'debug', 'quiet'):
672 for opt in ('verbose', 'debug', 'quiet'):
673 val = str(bool(options[opt]))
673 val = str(bool(options[opt]))
674 for ui_ in uis:
674 for ui_ in uis:
675 ui_.setconfig('ui', opt, val)
675 ui_.setconfig('ui', opt, val)
676
676
677 if options['traceback']:
677 if options['traceback']:
678 for ui_ in uis:
678 for ui_ in uis:
679 ui_.setconfig('ui', 'traceback', 'on')
679 ui_.setconfig('ui', 'traceback', 'on')
680
680
681 if options['noninteractive']:
681 if options['noninteractive']:
682 for ui_ in uis:
682 for ui_ in uis:
683 ui_.setconfig('ui', 'interactive', 'off')
683 ui_.setconfig('ui', 'interactive', 'off')
684
684
685 if cmdoptions.get('insecure', False):
685 if cmdoptions.get('insecure', False):
686 for ui_ in uis:
686 for ui_ in uis:
687 ui_.setconfig('web', 'cacerts', '')
687 ui_.setconfig('web', 'cacerts', '')
688
688
689 if options['version']:
689 if options['version']:
690 return commands.version_(ui)
690 return commands.version_(ui)
691 if options['help']:
691 if options['help']:
692 return commands.help_(ui, cmd)
692 return commands.help_(ui, cmd)
693 elif not cmd:
693 elif not cmd:
694 return commands.help_(ui, 'shortlist')
694 return commands.help_(ui, 'shortlist')
695
695
696 repo = None
696 repo = None
697 cmdpats = args[:]
697 cmdpats = args[:]
698 if cmd not in commands.norepo.split():
698 if cmd not in commands.norepo.split():
699 # use the repo from the request only if we don't have -R
699 # use the repo from the request only if we don't have -R
700 if not rpath and not cwd:
700 if not rpath and not cwd:
701 repo = req.repo
701 repo = req.repo
702
702
703 if repo:
703 if repo:
704 # set the descriptors of the repo ui to those of ui
704 # set the descriptors of the repo ui to those of ui
705 repo.ui.fin = ui.fin
705 repo.ui.fin = ui.fin
706 repo.ui.fout = ui.fout
706 repo.ui.fout = ui.fout
707 repo.ui.ferr = ui.ferr
707 repo.ui.ferr = ui.ferr
708 else:
708 else:
709 try:
709 try:
710 repo = hg.repository(ui, path=path)
710 repo = hg.repository(ui, path=path)
711 if not repo.local():
711 if not repo.local():
712 raise util.Abort(_("repository '%s' is not local") % path)
712 raise util.Abort(_("repository '%s' is not local") % path)
713 repo.ui.setconfig("bundle", "mainreporoot", repo.root)
713 repo.ui.setconfig("bundle", "mainreporoot", repo.root)
714 except error.RequirementError:
714 except error.RequirementError:
715 raise
715 raise
716 except error.RepoError:
716 except error.RepoError:
717 if cmd not in commands.optionalrepo.split():
717 if cmd not in commands.optionalrepo.split():
718 if (cmd in commands.inferrepo.split() and
718 if (cmd in commands.inferrepo.split() and
719 args and not path): # try to infer -R from command args
719 args and not path): # try to infer -R from command args
720 repos = map(cmdutil.findrepo, args)
720 repos = map(cmdutil.findrepo, args)
721 guess = repos[0]
721 guess = repos[0]
722 if guess and repos.count(guess) == len(repos):
722 if guess and repos.count(guess) == len(repos):
723 req.args = ['--repository', guess] + fullargs
723 req.args = ['--repository', guess] + fullargs
724 return _dispatch(req)
724 return _dispatch(req)
725 if not path:
725 if not path:
726 raise error.RepoError(_("no repository found in '%s'"
726 raise error.RepoError(_("no repository found in '%s'"
727 " (.hg not found)")
727 " (.hg not found)")
728 % os.getcwd())
728 % os.getcwd())
729 raise
729 raise
730 if repo:
730 if repo:
731 ui = repo.ui
731 ui = repo.ui
732 args.insert(0, repo)
732 args.insert(0, repo)
733 elif rpath:
733 elif rpath:
734 ui.warn(_("warning: --repository ignored\n"))
734 ui.warn(_("warning: --repository ignored\n"))
735
735
736 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
736 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
737 ui.log("command", msg + "\n")
737 ui.log("command", msg + "\n")
738 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
738 d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
739 try:
739 try:
740 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
740 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
741 cmdpats, cmdoptions)
741 cmdpats, cmdoptions)
742 finally:
742 finally:
743 if repo and repo != req.repo:
743 if repo and repo != req.repo:
744 repo.close()
744 repo.close()
745
745
746 def lsprofile(ui, func, fp):
746 def lsprofile(ui, func, fp):
747 format = ui.config('profiling', 'format', default='text')
747 format = ui.config('profiling', 'format', default='text')
748 field = ui.config('profiling', 'sort', default='inlinetime')
748 field = ui.config('profiling', 'sort', default='inlinetime')
749 climit = ui.configint('profiling', 'nested', default=5)
749 climit = ui.configint('profiling', 'nested', default=5)
750
750
751 if format not in ['text', 'kcachegrind']:
751 if format not in ['text', 'kcachegrind']:
752 ui.warn(_("unrecognized profiling format '%s'"
752 ui.warn(_("unrecognized profiling format '%s'"
753 " - Ignored\n") % format)
753 " - Ignored\n") % format)
754 format = 'text'
754 format = 'text'
755
755
756 try:
756 try:
757 from mercurial import lsprof
757 from mercurial import lsprof
758 except ImportError:
758 except ImportError:
759 raise util.Abort(_(
759 raise util.Abort(_(
760 'lsprof not available - install from '
760 'lsprof not available - install from '
761 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
761 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
762 p = lsprof.Profiler()
762 p = lsprof.Profiler()
763 p.enable(subcalls=True)
763 p.enable(subcalls=True)
764 try:
764 try:
765 return func()
765 return func()
766 finally:
766 finally:
767 p.disable()
767 p.disable()
768
768
769 if format == 'kcachegrind':
769 if format == 'kcachegrind':
770 import lsprofcalltree
770 import lsprofcalltree
771 calltree = lsprofcalltree.KCacheGrind(p)
771 calltree = lsprofcalltree.KCacheGrind(p)
772 calltree.output(fp)
772 calltree.output(fp)
773 else:
773 else:
774 # format == 'text'
774 # format == 'text'
775 stats = lsprof.Stats(p.getstats())
775 stats = lsprof.Stats(p.getstats())
776 stats.sort(field)
776 stats.sort(field)
777 stats.pprint(limit=30, file=fp, climit=climit)
777 stats.pprint(limit=30, file=fp, climit=climit)
778
778
779 def statprofile(ui, func, fp):
779 def statprofile(ui, func, fp):
780 try:
780 try:
781 import statprof
781 import statprof
782 except ImportError:
782 except ImportError:
783 raise util.Abort(_(
783 raise util.Abort(_(
784 'statprof not available - install using "easy_install statprof"'))
784 'statprof not available - install using "easy_install statprof"'))
785
785
786 freq = ui.configint('profiling', 'freq', default=1000)
786 freq = ui.configint('profiling', 'freq', default=1000)
787 if freq > 0:
787 if freq > 0:
788 statprof.reset(freq)
788 statprof.reset(freq)
789 else:
789 else:
790 ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq)
790 ui.warn(_("invalid sampling frequency '%s' - ignoring\n") % freq)
791
791
792 statprof.start()
792 statprof.start()
793 try:
793 try:
794 return func()
794 return func()
795 finally:
795 finally:
796 statprof.stop()
796 statprof.stop()
797 statprof.display(fp)
797 statprof.display(fp)
798
798
799 def _runcommand(ui, options, cmd, cmdfunc):
799 def _runcommand(ui, options, cmd, cmdfunc):
800 def checkargs():
800 def checkargs():
801 try:
801 try:
802 return cmdfunc()
802 return cmdfunc()
803 except error.SignatureError:
803 except error.SignatureError:
804 raise error.CommandError(cmd, _("invalid arguments"))
804 raise error.CommandError(cmd, _("invalid arguments"))
805
805
806 if options['profile']:
806 if options['profile']:
807 profiler = os.getenv('HGPROF')
807 profiler = os.getenv('HGPROF')
808 if profiler is None:
808 if profiler is None:
809 profiler = ui.config('profiling', 'type', default='ls')
809 profiler = ui.config('profiling', 'type', default='ls')
810 if profiler not in ('ls', 'stat'):
810 if profiler not in ('ls', 'stat'):
811 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
811 ui.warn(_("unrecognized profiler '%s' - ignored\n") % profiler)
812 profiler = 'ls'
812 profiler = 'ls'
813
813
814 output = ui.config('profiling', 'output')
814 output = ui.config('profiling', 'output')
815
815
816 if output:
816 if output:
817 path = ui.expandpath(output)
817 path = ui.expandpath(output)
818 fp = open(path, 'wb')
818 fp = open(path, 'wb')
819 else:
819 else:
820 fp = sys.stderr
820 fp = sys.stderr
821
821
822 try:
822 try:
823 if profiler == 'ls':
823 if profiler == 'ls':
824 return lsprofile(ui, checkargs, fp)
824 return lsprofile(ui, checkargs, fp)
825 else:
825 else:
826 return statprofile(ui, checkargs, fp)
826 return statprofile(ui, checkargs, fp)
827 finally:
827 finally:
828 if output:
828 if output:
829 fp.close()
829 fp.close()
830 else:
830 else:
831 return checkargs()
831 return checkargs()
@@ -1,92 +1,92 b''
1 $ hg init
1 $ hg init
2
2
3 audit of .hg
3 audit of .hg
4
4
5 $ hg add .hg/00changelog.i
5 $ hg add .hg/00changelog.i
6 abort: path contains illegal component: .hg/00changelog.i (glob)
6 abort: path contains illegal component: .hg/00changelog.i (glob)
7 [255]
7 [255]
8
8
9 #if symlink
9 #if symlink
10
10
11 Symlinks
11 Symlinks
12
12
13 $ mkdir a
13 $ mkdir a
14 $ echo a > a/a
14 $ echo a > a/a
15 $ hg ci -Ama
15 $ hg ci -Ama
16 adding a/a
16 adding a/a
17 $ ln -s a b
17 $ ln -s a b
18 $ echo b > a/b
18 $ echo b > a/b
19 $ hg add b/b
19 $ hg add b/b
20 abort: path 'b/b' traverses symbolic link 'b' (glob)
20 abort: path 'b/b' traverses symbolic link 'b' (glob)
21 [255]
21 [255]
22 $ hg add b
22 $ hg add b
23
23
24 should still fail - maybe
24 should still fail - maybe
25
25
26 $ hg add b/b
26 $ hg add b/b
27 abort: path 'b/b' traverses symbolic link 'b' (glob)
27 abort: path 'b/b' traverses symbolic link 'b' (glob)
28 [255]
28 [255]
29
29
30 #endif
30 #endif
31
31
32
32
33 unbundle tampered bundle
33 unbundle tampered bundle
34
34
35 $ hg init target
35 $ hg init target
36 $ cd target
36 $ cd target
37 $ hg unbundle "$TESTDIR/bundles/tampered.hg"
37 $ hg unbundle "$TESTDIR/bundles/tampered.hg"
38 adding changesets
38 adding changesets
39 adding manifests
39 adding manifests
40 adding file changes
40 adding file changes
41 added 5 changesets with 6 changes to 6 files (+4 heads)
41 added 5 changesets with 6 changes to 6 files (+4 heads)
42 (run 'hg heads' to see heads, 'hg merge' to merge)
42 (run 'hg heads' to see heads, 'hg merge' to merge)
43
43
44 attack .hg/test
44 attack .hg/test
45
45
46 $ hg manifest -r0
46 $ hg manifest -r0
47 .hg/test
47 .hg/test
48 $ hg update -Cr0
48 $ hg update -Cr0
49 abort: path contains illegal component: .hg/test (glob)
49 abort: path contains illegal component: .hg/test (glob)
50 [255]
50 [255]
51
51
52 attack foo/.hg/test
52 attack foo/.hg/test
53
53
54 $ hg manifest -r1
54 $ hg manifest -r1
55 foo/.hg/test
55 foo/.hg/test
56 $ hg update -Cr1
56 $ hg update -Cr1
57 abort: path 'foo/.hg/test' is inside nested repo 'foo' (glob)
57 abort: path 'foo/.hg/test' is inside nested repo 'foo' (glob)
58 [255]
58 [255]
59
59
60 attack back/test where back symlinks to ..
60 attack back/test where back symlinks to ..
61
61
62 $ hg manifest -r2
62 $ hg manifest -r2
63 back
63 back
64 back/test
64 back/test
65 #if symlink
65 #if symlink
66 $ hg update -Cr2
66 $ hg update -Cr2
67 abort: path 'back/test' traverses symbolic link 'back'
67 abort: path 'back/test' traverses symbolic link 'back'
68 [255]
68 [255]
69 #else
69 #else
70 ('back' will be a file and cause some other system specific error)
70 ('back' will be a file and cause some other system specific error)
71 $ hg update -Cr2
71 $ hg update -Cr2
72 abort: * (glob)
72 abort: * (glob)
73 [255]
73 [255]
74 #endif
74 #endif
75
75
76 attack ../test
76 attack ../test
77
77
78 $ hg manifest -r3
78 $ hg manifest -r3
79 ../test
79 ../test
80 $ hg update -Cr3
80 $ hg update -Cr3
81 abort: path contains illegal component: ../test (glob)
81 abort: path contains illegal component: ../test (glob)
82 [255]
82 [255]
83
83
84 attack /tmp/test
84 attack /tmp/test
85
85
86 $ hg manifest -r4
86 $ hg manifest -r4
87 /tmp/test
87 /tmp/test
88 $ hg update -Cr4
88 $ hg update -Cr4
89 abort: *: $TESTTMP/target//tmp/test (glob)
89 abort: *: '$TESTTMP/target//tmp/test' (glob)
90 [255]
90 [255]
91
91
92 $ cd ..
92 $ cd ..
@@ -1,623 +1,623 b''
1 Prepare repo a:
1 Prepare repo a:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ hg add a
6 $ hg add a
7 $ hg commit -m test
7 $ hg commit -m test
8 $ echo first line > b
8 $ echo first line > b
9 $ hg add b
9 $ hg add b
10
10
11 Create a non-inlined filelog:
11 Create a non-inlined filelog:
12
12
13 $ python -c 'file("data1", "wb").write("".join("%s\n" % x for x in range(10000)))'
13 $ python -c 'file("data1", "wb").write("".join("%s\n" % x for x in range(10000)))'
14 $ for j in 0 1 2 3 4 5 6 7 8 9; do
14 $ for j in 0 1 2 3 4 5 6 7 8 9; do
15 > cat data1 >> b
15 > cat data1 >> b
16 > hg commit -m test
16 > hg commit -m test
17 > done
17 > done
18
18
19 List files in store/data (should show a 'b.d'):
19 List files in store/data (should show a 'b.d'):
20
20
21 $ for i in .hg/store/data/*; do
21 $ for i in .hg/store/data/*; do
22 > echo $i
22 > echo $i
23 > done
23 > done
24 .hg/store/data/a.i
24 .hg/store/data/a.i
25 .hg/store/data/b.d
25 .hg/store/data/b.d
26 .hg/store/data/b.i
26 .hg/store/data/b.i
27
27
28 Default operation:
28 Default operation:
29
29
30 $ hg clone . ../b
30 $ hg clone . ../b
31 updating to branch default
31 updating to branch default
32 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
32 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
33 $ cd ../b
33 $ cd ../b
34 $ cat a
34 $ cat a
35 a
35 a
36 $ hg verify
36 $ hg verify
37 checking changesets
37 checking changesets
38 checking manifests
38 checking manifests
39 crosschecking files in changesets and manifests
39 crosschecking files in changesets and manifests
40 checking files
40 checking files
41 2 files, 11 changesets, 11 total revisions
41 2 files, 11 changesets, 11 total revisions
42
42
43 Invalid dest '' must abort:
43 Invalid dest '' must abort:
44
44
45 $ hg clone . ''
45 $ hg clone . ''
46 abort: empty destination path is not valid
46 abort: empty destination path is not valid
47 [255]
47 [255]
48
48
49 No update, with debug option:
49 No update, with debug option:
50
50
51 #if hardlink
51 #if hardlink
52 $ hg --debug clone -U . ../c
52 $ hg --debug clone -U . ../c
53 linked 8 files
53 linked 8 files
54 listing keys for "bookmarks"
54 listing keys for "bookmarks"
55 #else
55 #else
56 $ hg --debug clone -U . ../c
56 $ hg --debug clone -U . ../c
57 copied 8 files
57 copied 8 files
58 listing keys for "bookmarks"
58 listing keys for "bookmarks"
59 #endif
59 #endif
60 $ cd ../c
60 $ cd ../c
61 $ cat a 2>/dev/null || echo "a not present"
61 $ cat a 2>/dev/null || echo "a not present"
62 a not present
62 a not present
63 $ hg verify
63 $ hg verify
64 checking changesets
64 checking changesets
65 checking manifests
65 checking manifests
66 crosschecking files in changesets and manifests
66 crosschecking files in changesets and manifests
67 checking files
67 checking files
68 2 files, 11 changesets, 11 total revisions
68 2 files, 11 changesets, 11 total revisions
69
69
70 Default destination:
70 Default destination:
71
71
72 $ mkdir ../d
72 $ mkdir ../d
73 $ cd ../d
73 $ cd ../d
74 $ hg clone ../a
74 $ hg clone ../a
75 destination directory: a
75 destination directory: a
76 updating to branch default
76 updating to branch default
77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
77 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
78 $ cd a
78 $ cd a
79 $ hg cat a
79 $ hg cat a
80 a
80 a
81 $ cd ../..
81 $ cd ../..
82
82
83 Check that we drop the 'file:' from the path before writing the .hgrc:
83 Check that we drop the 'file:' from the path before writing the .hgrc:
84
84
85 $ hg clone file:a e
85 $ hg clone file:a e
86 updating to branch default
86 updating to branch default
87 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
87 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 $ grep 'file:' e/.hg/hgrc
88 $ grep 'file:' e/.hg/hgrc
89 [1]
89 [1]
90
90
91 Check that path aliases are expanded:
91 Check that path aliases are expanded:
92
92
93 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
93 $ hg clone -q -U --config 'paths.foobar=a#0' foobar f
94 $ hg -R f showconfig paths.default
94 $ hg -R f showconfig paths.default
95 $TESTTMP/a#0 (glob)
95 $TESTTMP/a#0 (glob)
96
96
97 Use --pull:
97 Use --pull:
98
98
99 $ hg clone --pull a g
99 $ hg clone --pull a g
100 requesting all changes
100 requesting all changes
101 adding changesets
101 adding changesets
102 adding manifests
102 adding manifests
103 adding file changes
103 adding file changes
104 added 11 changesets with 11 changes to 2 files
104 added 11 changesets with 11 changes to 2 files
105 updating to branch default
105 updating to branch default
106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 $ hg -R g verify
107 $ hg -R g verify
108 checking changesets
108 checking changesets
109 checking manifests
109 checking manifests
110 crosschecking files in changesets and manifests
110 crosschecking files in changesets and manifests
111 checking files
111 checking files
112 2 files, 11 changesets, 11 total revisions
112 2 files, 11 changesets, 11 total revisions
113
113
114 Invalid dest '' with --pull must abort (issue2528):
114 Invalid dest '' with --pull must abort (issue2528):
115
115
116 $ hg clone --pull a ''
116 $ hg clone --pull a ''
117 abort: empty destination path is not valid
117 abort: empty destination path is not valid
118 [255]
118 [255]
119
119
120 Clone to '.':
120 Clone to '.':
121
121
122 $ mkdir h
122 $ mkdir h
123 $ cd h
123 $ cd h
124 $ hg clone ../a .
124 $ hg clone ../a .
125 updating to branch default
125 updating to branch default
126 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
126 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
127 $ cd ..
127 $ cd ..
128
128
129
129
130 *** Tests for option -u ***
130 *** Tests for option -u ***
131
131
132 Adding some more history to repo a:
132 Adding some more history to repo a:
133
133
134 $ cd a
134 $ cd a
135 $ hg tag ref1
135 $ hg tag ref1
136 $ echo the quick brown fox >a
136 $ echo the quick brown fox >a
137 $ hg ci -m "hacked default"
137 $ hg ci -m "hacked default"
138 $ hg up ref1
138 $ hg up ref1
139 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
139 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
140 $ hg branch stable
140 $ hg branch stable
141 marked working directory as branch stable
141 marked working directory as branch stable
142 (branches are permanent and global, did you want a bookmark?)
142 (branches are permanent and global, did you want a bookmark?)
143 $ echo some text >a
143 $ echo some text >a
144 $ hg ci -m "starting branch stable"
144 $ hg ci -m "starting branch stable"
145 $ hg tag ref2
145 $ hg tag ref2
146 $ echo some more text >a
146 $ echo some more text >a
147 $ hg ci -m "another change for branch stable"
147 $ hg ci -m "another change for branch stable"
148 $ hg up ref2
148 $ hg up ref2
149 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
150 $ hg parents
150 $ hg parents
151 changeset: 13:e8ece76546a6
151 changeset: 13:e8ece76546a6
152 branch: stable
152 branch: stable
153 tag: ref2
153 tag: ref2
154 parent: 10:a7949464abda
154 parent: 10:a7949464abda
155 user: test
155 user: test
156 date: Thu Jan 01 00:00:00 1970 +0000
156 date: Thu Jan 01 00:00:00 1970 +0000
157 summary: starting branch stable
157 summary: starting branch stable
158
158
159
159
160 Repo a has two heads:
160 Repo a has two heads:
161
161
162 $ hg heads
162 $ hg heads
163 changeset: 15:0aae7cf88f0d
163 changeset: 15:0aae7cf88f0d
164 branch: stable
164 branch: stable
165 tag: tip
165 tag: tip
166 user: test
166 user: test
167 date: Thu Jan 01 00:00:00 1970 +0000
167 date: Thu Jan 01 00:00:00 1970 +0000
168 summary: another change for branch stable
168 summary: another change for branch stable
169
169
170 changeset: 12:f21241060d6a
170 changeset: 12:f21241060d6a
171 user: test
171 user: test
172 date: Thu Jan 01 00:00:00 1970 +0000
172 date: Thu Jan 01 00:00:00 1970 +0000
173 summary: hacked default
173 summary: hacked default
174
174
175
175
176 $ cd ..
176 $ cd ..
177
177
178
178
179 Testing --noupdate with --updaterev (must abort):
179 Testing --noupdate with --updaterev (must abort):
180
180
181 $ hg clone --noupdate --updaterev 1 a ua
181 $ hg clone --noupdate --updaterev 1 a ua
182 abort: cannot specify both --noupdate and --updaterev
182 abort: cannot specify both --noupdate and --updaterev
183 [255]
183 [255]
184
184
185
185
186 Testing clone -u:
186 Testing clone -u:
187
187
188 $ hg clone -u . a ua
188 $ hg clone -u . a ua
189 updating to branch stable
189 updating to branch stable
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191
191
192 Repo ua has both heads:
192 Repo ua has both heads:
193
193
194 $ hg -R ua heads
194 $ hg -R ua heads
195 changeset: 15:0aae7cf88f0d
195 changeset: 15:0aae7cf88f0d
196 branch: stable
196 branch: stable
197 tag: tip
197 tag: tip
198 user: test
198 user: test
199 date: Thu Jan 01 00:00:00 1970 +0000
199 date: Thu Jan 01 00:00:00 1970 +0000
200 summary: another change for branch stable
200 summary: another change for branch stable
201
201
202 changeset: 12:f21241060d6a
202 changeset: 12:f21241060d6a
203 user: test
203 user: test
204 date: Thu Jan 01 00:00:00 1970 +0000
204 date: Thu Jan 01 00:00:00 1970 +0000
205 summary: hacked default
205 summary: hacked default
206
206
207
207
208 Same revision checked out in repo a and ua:
208 Same revision checked out in repo a and ua:
209
209
210 $ hg -R a parents --template "{node|short}\n"
210 $ hg -R a parents --template "{node|short}\n"
211 e8ece76546a6
211 e8ece76546a6
212 $ hg -R ua parents --template "{node|short}\n"
212 $ hg -R ua parents --template "{node|short}\n"
213 e8ece76546a6
213 e8ece76546a6
214
214
215 $ rm -r ua
215 $ rm -r ua
216
216
217
217
218 Testing clone --pull -u:
218 Testing clone --pull -u:
219
219
220 $ hg clone --pull -u . a ua
220 $ hg clone --pull -u . a ua
221 requesting all changes
221 requesting all changes
222 adding changesets
222 adding changesets
223 adding manifests
223 adding manifests
224 adding file changes
224 adding file changes
225 added 16 changesets with 16 changes to 3 files (+1 heads)
225 added 16 changesets with 16 changes to 3 files (+1 heads)
226 updating to branch stable
226 updating to branch stable
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
227 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
228
228
229 Repo ua has both heads:
229 Repo ua has both heads:
230
230
231 $ hg -R ua heads
231 $ hg -R ua heads
232 changeset: 15:0aae7cf88f0d
232 changeset: 15:0aae7cf88f0d
233 branch: stable
233 branch: stable
234 tag: tip
234 tag: tip
235 user: test
235 user: test
236 date: Thu Jan 01 00:00:00 1970 +0000
236 date: Thu Jan 01 00:00:00 1970 +0000
237 summary: another change for branch stable
237 summary: another change for branch stable
238
238
239 changeset: 12:f21241060d6a
239 changeset: 12:f21241060d6a
240 user: test
240 user: test
241 date: Thu Jan 01 00:00:00 1970 +0000
241 date: Thu Jan 01 00:00:00 1970 +0000
242 summary: hacked default
242 summary: hacked default
243
243
244
244
245 Same revision checked out in repo a and ua:
245 Same revision checked out in repo a and ua:
246
246
247 $ hg -R a parents --template "{node|short}\n"
247 $ hg -R a parents --template "{node|short}\n"
248 e8ece76546a6
248 e8ece76546a6
249 $ hg -R ua parents --template "{node|short}\n"
249 $ hg -R ua parents --template "{node|short}\n"
250 e8ece76546a6
250 e8ece76546a6
251
251
252 $ rm -r ua
252 $ rm -r ua
253
253
254
254
255 Testing clone -u <branch>:
255 Testing clone -u <branch>:
256
256
257 $ hg clone -u stable a ua
257 $ hg clone -u stable a ua
258 updating to branch stable
258 updating to branch stable
259 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
260
260
261 Repo ua has both heads:
261 Repo ua has both heads:
262
262
263 $ hg -R ua heads
263 $ hg -R ua heads
264 changeset: 15:0aae7cf88f0d
264 changeset: 15:0aae7cf88f0d
265 branch: stable
265 branch: stable
266 tag: tip
266 tag: tip
267 user: test
267 user: test
268 date: Thu Jan 01 00:00:00 1970 +0000
268 date: Thu Jan 01 00:00:00 1970 +0000
269 summary: another change for branch stable
269 summary: another change for branch stable
270
270
271 changeset: 12:f21241060d6a
271 changeset: 12:f21241060d6a
272 user: test
272 user: test
273 date: Thu Jan 01 00:00:00 1970 +0000
273 date: Thu Jan 01 00:00:00 1970 +0000
274 summary: hacked default
274 summary: hacked default
275
275
276
276
277 Branch 'stable' is checked out:
277 Branch 'stable' is checked out:
278
278
279 $ hg -R ua parents
279 $ hg -R ua parents
280 changeset: 15:0aae7cf88f0d
280 changeset: 15:0aae7cf88f0d
281 branch: stable
281 branch: stable
282 tag: tip
282 tag: tip
283 user: test
283 user: test
284 date: Thu Jan 01 00:00:00 1970 +0000
284 date: Thu Jan 01 00:00:00 1970 +0000
285 summary: another change for branch stable
285 summary: another change for branch stable
286
286
287
287
288 $ rm -r ua
288 $ rm -r ua
289
289
290
290
291 Testing default checkout:
291 Testing default checkout:
292
292
293 $ hg clone a ua
293 $ hg clone a ua
294 updating to branch default
294 updating to branch default
295 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
295 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
296
296
297 Repo ua has both heads:
297 Repo ua has both heads:
298
298
299 $ hg -R ua heads
299 $ hg -R ua heads
300 changeset: 15:0aae7cf88f0d
300 changeset: 15:0aae7cf88f0d
301 branch: stable
301 branch: stable
302 tag: tip
302 tag: tip
303 user: test
303 user: test
304 date: Thu Jan 01 00:00:00 1970 +0000
304 date: Thu Jan 01 00:00:00 1970 +0000
305 summary: another change for branch stable
305 summary: another change for branch stable
306
306
307 changeset: 12:f21241060d6a
307 changeset: 12:f21241060d6a
308 user: test
308 user: test
309 date: Thu Jan 01 00:00:00 1970 +0000
309 date: Thu Jan 01 00:00:00 1970 +0000
310 summary: hacked default
310 summary: hacked default
311
311
312
312
313 Branch 'default' is checked out:
313 Branch 'default' is checked out:
314
314
315 $ hg -R ua parents
315 $ hg -R ua parents
316 changeset: 12:f21241060d6a
316 changeset: 12:f21241060d6a
317 user: test
317 user: test
318 date: Thu Jan 01 00:00:00 1970 +0000
318 date: Thu Jan 01 00:00:00 1970 +0000
319 summary: hacked default
319 summary: hacked default
320
320
321 Test clone with a branch named "@" (issue3677)
321 Test clone with a branch named "@" (issue3677)
322
322
323 $ hg -R ua branch @
323 $ hg -R ua branch @
324 marked working directory as branch @
324 marked working directory as branch @
325 (branches are permanent and global, did you want a bookmark?)
325 (branches are permanent and global, did you want a bookmark?)
326 $ hg -R ua commit -m 'created branch @'
326 $ hg -R ua commit -m 'created branch @'
327 $ hg clone ua atbranch
327 $ hg clone ua atbranch
328 updating to branch default
328 updating to branch default
329 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 $ hg -R atbranch heads
330 $ hg -R atbranch heads
331 changeset: 16:798b6d97153e
331 changeset: 16:798b6d97153e
332 branch: @
332 branch: @
333 tag: tip
333 tag: tip
334 parent: 12:f21241060d6a
334 parent: 12:f21241060d6a
335 user: test
335 user: test
336 date: Thu Jan 01 00:00:00 1970 +0000
336 date: Thu Jan 01 00:00:00 1970 +0000
337 summary: created branch @
337 summary: created branch @
338
338
339 changeset: 15:0aae7cf88f0d
339 changeset: 15:0aae7cf88f0d
340 branch: stable
340 branch: stable
341 user: test
341 user: test
342 date: Thu Jan 01 00:00:00 1970 +0000
342 date: Thu Jan 01 00:00:00 1970 +0000
343 summary: another change for branch stable
343 summary: another change for branch stable
344
344
345 changeset: 12:f21241060d6a
345 changeset: 12:f21241060d6a
346 user: test
346 user: test
347 date: Thu Jan 01 00:00:00 1970 +0000
347 date: Thu Jan 01 00:00:00 1970 +0000
348 summary: hacked default
348 summary: hacked default
349
349
350 $ hg -R atbranch parents
350 $ hg -R atbranch parents
351 changeset: 12:f21241060d6a
351 changeset: 12:f21241060d6a
352 user: test
352 user: test
353 date: Thu Jan 01 00:00:00 1970 +0000
353 date: Thu Jan 01 00:00:00 1970 +0000
354 summary: hacked default
354 summary: hacked default
355
355
356
356
357 $ rm -r ua atbranch
357 $ rm -r ua atbranch
358
358
359
359
360 Testing #<branch>:
360 Testing #<branch>:
361
361
362 $ hg clone -u . a#stable ua
362 $ hg clone -u . a#stable ua
363 adding changesets
363 adding changesets
364 adding manifests
364 adding manifests
365 adding file changes
365 adding file changes
366 added 14 changesets with 14 changes to 3 files
366 added 14 changesets with 14 changes to 3 files
367 updating to branch stable
367 updating to branch stable
368 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
368 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
369
369
370 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
370 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
371
371
372 $ hg -R ua heads
372 $ hg -R ua heads
373 changeset: 13:0aae7cf88f0d
373 changeset: 13:0aae7cf88f0d
374 branch: stable
374 branch: stable
375 tag: tip
375 tag: tip
376 user: test
376 user: test
377 date: Thu Jan 01 00:00:00 1970 +0000
377 date: Thu Jan 01 00:00:00 1970 +0000
378 summary: another change for branch stable
378 summary: another change for branch stable
379
379
380 changeset: 10:a7949464abda
380 changeset: 10:a7949464abda
381 user: test
381 user: test
382 date: Thu Jan 01 00:00:00 1970 +0000
382 date: Thu Jan 01 00:00:00 1970 +0000
383 summary: test
383 summary: test
384
384
385
385
386 Same revision checked out in repo a and ua:
386 Same revision checked out in repo a and ua:
387
387
388 $ hg -R a parents --template "{node|short}\n"
388 $ hg -R a parents --template "{node|short}\n"
389 e8ece76546a6
389 e8ece76546a6
390 $ hg -R ua parents --template "{node|short}\n"
390 $ hg -R ua parents --template "{node|short}\n"
391 e8ece76546a6
391 e8ece76546a6
392
392
393 $ rm -r ua
393 $ rm -r ua
394
394
395
395
396 Testing -u -r <branch>:
396 Testing -u -r <branch>:
397
397
398 $ hg clone -u . -r stable a ua
398 $ hg clone -u . -r stable a ua
399 adding changesets
399 adding changesets
400 adding manifests
400 adding manifests
401 adding file changes
401 adding file changes
402 added 14 changesets with 14 changes to 3 files
402 added 14 changesets with 14 changes to 3 files
403 updating to branch stable
403 updating to branch stable
404 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
404 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
405
405
406 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
406 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
407
407
408 $ hg -R ua heads
408 $ hg -R ua heads
409 changeset: 13:0aae7cf88f0d
409 changeset: 13:0aae7cf88f0d
410 branch: stable
410 branch: stable
411 tag: tip
411 tag: tip
412 user: test
412 user: test
413 date: Thu Jan 01 00:00:00 1970 +0000
413 date: Thu Jan 01 00:00:00 1970 +0000
414 summary: another change for branch stable
414 summary: another change for branch stable
415
415
416 changeset: 10:a7949464abda
416 changeset: 10:a7949464abda
417 user: test
417 user: test
418 date: Thu Jan 01 00:00:00 1970 +0000
418 date: Thu Jan 01 00:00:00 1970 +0000
419 summary: test
419 summary: test
420
420
421
421
422 Same revision checked out in repo a and ua:
422 Same revision checked out in repo a and ua:
423
423
424 $ hg -R a parents --template "{node|short}\n"
424 $ hg -R a parents --template "{node|short}\n"
425 e8ece76546a6
425 e8ece76546a6
426 $ hg -R ua parents --template "{node|short}\n"
426 $ hg -R ua parents --template "{node|short}\n"
427 e8ece76546a6
427 e8ece76546a6
428
428
429 $ rm -r ua
429 $ rm -r ua
430
430
431
431
432 Testing -r <branch>:
432 Testing -r <branch>:
433
433
434 $ hg clone -r stable a ua
434 $ hg clone -r stable a ua
435 adding changesets
435 adding changesets
436 adding manifests
436 adding manifests
437 adding file changes
437 adding file changes
438 added 14 changesets with 14 changes to 3 files
438 added 14 changesets with 14 changes to 3 files
439 updating to branch stable
439 updating to branch stable
440 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
440 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
441
441
442 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
442 Repo ua has branch 'stable' and 'default' (was changed in fd511e9eeea6):
443
443
444 $ hg -R ua heads
444 $ hg -R ua heads
445 changeset: 13:0aae7cf88f0d
445 changeset: 13:0aae7cf88f0d
446 branch: stable
446 branch: stable
447 tag: tip
447 tag: tip
448 user: test
448 user: test
449 date: Thu Jan 01 00:00:00 1970 +0000
449 date: Thu Jan 01 00:00:00 1970 +0000
450 summary: another change for branch stable
450 summary: another change for branch stable
451
451
452 changeset: 10:a7949464abda
452 changeset: 10:a7949464abda
453 user: test
453 user: test
454 date: Thu Jan 01 00:00:00 1970 +0000
454 date: Thu Jan 01 00:00:00 1970 +0000
455 summary: test
455 summary: test
456
456
457
457
458 Branch 'stable' is checked out:
458 Branch 'stable' is checked out:
459
459
460 $ hg -R ua parents
460 $ hg -R ua parents
461 changeset: 13:0aae7cf88f0d
461 changeset: 13:0aae7cf88f0d
462 branch: stable
462 branch: stable
463 tag: tip
463 tag: tip
464 user: test
464 user: test
465 date: Thu Jan 01 00:00:00 1970 +0000
465 date: Thu Jan 01 00:00:00 1970 +0000
466 summary: another change for branch stable
466 summary: another change for branch stable
467
467
468
468
469 $ rm -r ua
469 $ rm -r ua
470
470
471
471
472 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
472 Issue2267: Error in 1.6 hg.py: TypeError: 'NoneType' object is not
473 iterable in addbranchrevs()
473 iterable in addbranchrevs()
474
474
475 $ cat <<EOF > simpleclone.py
475 $ cat <<EOF > simpleclone.py
476 > from mercurial import ui, hg
476 > from mercurial import ui, hg
477 > myui = ui.ui()
477 > myui = ui.ui()
478 > repo = hg.repository(myui, 'a')
478 > repo = hg.repository(myui, 'a')
479 > hg.clone(myui, {}, repo, dest="ua")
479 > hg.clone(myui, {}, repo, dest="ua")
480 > EOF
480 > EOF
481
481
482 $ python simpleclone.py
482 $ python simpleclone.py
483 updating to branch default
483 updating to branch default
484 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
484 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
485
485
486 $ rm -r ua
486 $ rm -r ua
487
487
488 $ cat <<EOF > branchclone.py
488 $ cat <<EOF > branchclone.py
489 > from mercurial import ui, hg, extensions
489 > from mercurial import ui, hg, extensions
490 > myui = ui.ui()
490 > myui = ui.ui()
491 > extensions.loadall(myui)
491 > extensions.loadall(myui)
492 > repo = hg.repository(myui, 'a')
492 > repo = hg.repository(myui, 'a')
493 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
493 > hg.clone(myui, {}, repo, dest="ua", branch=["stable",])
494 > EOF
494 > EOF
495
495
496 $ python branchclone.py
496 $ python branchclone.py
497 adding changesets
497 adding changesets
498 adding manifests
498 adding manifests
499 adding file changes
499 adding file changes
500 added 14 changesets with 14 changes to 3 files
500 added 14 changesets with 14 changes to 3 files
501 updating to branch stable
501 updating to branch stable
502 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
502 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
503 $ rm -r ua
503 $ rm -r ua
504
504
505
505
506 Test clone with special '@' bookmark:
506 Test clone with special '@' bookmark:
507 $ cd a
507 $ cd a
508 $ hg bookmark -r a7949464abda @ # branch point of stable from default
508 $ hg bookmark -r a7949464abda @ # branch point of stable from default
509 $ hg clone . ../i
509 $ hg clone . ../i
510 updating to bookmark @
510 updating to bookmark @
511 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
511 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 $ hg id -i ../i
512 $ hg id -i ../i
513 a7949464abda
513 a7949464abda
514 $ rm -r ../i
514 $ rm -r ../i
515
515
516 $ hg bookmark -f -r stable @
516 $ hg bookmark -f -r stable @
517 $ hg bookmarks
517 $ hg bookmarks
518 @ 15:0aae7cf88f0d
518 @ 15:0aae7cf88f0d
519 $ hg clone . ../i
519 $ hg clone . ../i
520 updating to bookmark @ on branch stable
520 updating to bookmark @ on branch stable
521 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
521 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
522 $ hg id -i ../i
522 $ hg id -i ../i
523 0aae7cf88f0d
523 0aae7cf88f0d
524 $ cd "$TESTTMP"
524 $ cd "$TESTTMP"
525
525
526
526
527 Testing failures:
527 Testing failures:
528
528
529 $ mkdir fail
529 $ mkdir fail
530 $ cd fail
530 $ cd fail
531
531
532 No local source
532 No local source
533
533
534 $ hg clone a b
534 $ hg clone a b
535 abort: repository a not found!
535 abort: repository a not found!
536 [255]
536 [255]
537
537
538 No remote source
538 No remote source
539
539
540 $ hg clone http://127.0.0.1:3121/a b
540 $ hg clone http://127.0.0.1:3121/a b
541 abort: error: *refused* (glob)
541 abort: error: *refused* (glob)
542 [255]
542 [255]
543 $ rm -rf b # work around bug with http clone
543 $ rm -rf b # work around bug with http clone
544
544
545
545
546 #if unix-permissions
546 #if unix-permissions
547
547
548 Inaccessible source
548 Inaccessible source
549
549
550 $ mkdir a
550 $ mkdir a
551 $ chmod 000 a
551 $ chmod 000 a
552 $ hg clone a b
552 $ hg clone a b
553 abort: repository a not found!
553 abort: repository a not found!
554 [255]
554 [255]
555
555
556 Inaccessible destination
556 Inaccessible destination
557
557
558 $ hg init b
558 $ hg init b
559 $ cd b
559 $ cd b
560 $ hg clone . ../a
560 $ hg clone . ../a
561 abort: Permission denied: ../a
561 abort: Permission denied: '../a'
562 [255]
562 [255]
563 $ cd ..
563 $ cd ..
564 $ chmod 700 a
564 $ chmod 700 a
565 $ rm -r a b
565 $ rm -r a b
566
566
567 #endif
567 #endif
568
568
569
569
570 #if fifo
570 #if fifo
571
571
572 Source of wrong type
572 Source of wrong type
573
573
574 $ mkfifo a
574 $ mkfifo a
575 $ hg clone a b
575 $ hg clone a b
576 abort: repository a not found!
576 abort: repository a not found!
577 [255]
577 [255]
578 $ rm a
578 $ rm a
579
579
580 #endif
580 #endif
581
581
582 Default destination, same directory
582 Default destination, same directory
583
583
584 $ hg init q
584 $ hg init q
585 $ hg clone q
585 $ hg clone q
586 destination directory: q
586 destination directory: q
587 abort: destination 'q' is not empty
587 abort: destination 'q' is not empty
588 [255]
588 [255]
589
589
590 destination directory not empty
590 destination directory not empty
591
591
592 $ mkdir a
592 $ mkdir a
593 $ echo stuff > a/a
593 $ echo stuff > a/a
594 $ hg clone q a
594 $ hg clone q a
595 abort: destination 'a' is not empty
595 abort: destination 'a' is not empty
596 [255]
596 [255]
597
597
598
598
599 #if unix-permissions
599 #if unix-permissions
600
600
601 leave existing directory in place after clone failure
601 leave existing directory in place after clone failure
602
602
603 $ hg init c
603 $ hg init c
604 $ cd c
604 $ cd c
605 $ echo c > c
605 $ echo c > c
606 $ hg commit -A -m test
606 $ hg commit -A -m test
607 adding c
607 adding c
608 $ chmod -rx .hg/store/data
608 $ chmod -rx .hg/store/data
609 $ cd ..
609 $ cd ..
610 $ mkdir d
610 $ mkdir d
611 $ hg clone c d 2> err
611 $ hg clone c d 2> err
612 [255]
612 [255]
613 $ test -d d
613 $ test -d d
614 $ test -d d/.hg
614 $ test -d d/.hg
615 [1]
615 [1]
616
616
617 re-enable perm to allow deletion
617 re-enable perm to allow deletion
618
618
619 $ chmod +rx c/.hg/store/data
619 $ chmod +rx c/.hg/store/data
620
620
621 #endif
621 #endif
622
622
623 $ cd ..
623 $ cd ..
@@ -1,455 +1,455 b''
1 $ cat >> $HGRCPATH <<EOF
1 $ cat >> $HGRCPATH <<EOF
2 > [extensions]
2 > [extensions]
3 > convert=
3 > convert=
4 > [convert]
4 > [convert]
5 > hg.saverev=False
5 > hg.saverev=False
6 > EOF
6 > EOF
7 $ hg help convert
7 $ hg help convert
8 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
8 hg convert [OPTION]... SOURCE [DEST [REVMAP]]
9
9
10 convert a foreign SCM repository to a Mercurial one.
10 convert a foreign SCM repository to a Mercurial one.
11
11
12 Accepted source formats [identifiers]:
12 Accepted source formats [identifiers]:
13
13
14 - Mercurial [hg]
14 - Mercurial [hg]
15 - CVS [cvs]
15 - CVS [cvs]
16 - Darcs [darcs]
16 - Darcs [darcs]
17 - git [git]
17 - git [git]
18 - Subversion [svn]
18 - Subversion [svn]
19 - Monotone [mtn]
19 - Monotone [mtn]
20 - GNU Arch [gnuarch]
20 - GNU Arch [gnuarch]
21 - Bazaar [bzr]
21 - Bazaar [bzr]
22 - Perforce [p4]
22 - Perforce [p4]
23
23
24 Accepted destination formats [identifiers]:
24 Accepted destination formats [identifiers]:
25
25
26 - Mercurial [hg]
26 - Mercurial [hg]
27 - Subversion [svn] (history on branches is not preserved)
27 - Subversion [svn] (history on branches is not preserved)
28
28
29 If no revision is given, all revisions will be converted. Otherwise,
29 If no revision is given, all revisions will be converted. Otherwise,
30 convert will only import up to the named revision (given in a format
30 convert will only import up to the named revision (given in a format
31 understood by the source).
31 understood by the source).
32
32
33 If no destination directory name is specified, it defaults to the basename
33 If no destination directory name is specified, it defaults to the basename
34 of the source with "-hg" appended. If the destination repository doesn't
34 of the source with "-hg" appended. If the destination repository doesn't
35 exist, it will be created.
35 exist, it will be created.
36
36
37 By default, all sources except Mercurial will use --branchsort. Mercurial
37 By default, all sources except Mercurial will use --branchsort. Mercurial
38 uses --sourcesort to preserve original revision numbers order. Sort modes
38 uses --sourcesort to preserve original revision numbers order. Sort modes
39 have the following effects:
39 have the following effects:
40
40
41 --branchsort convert from parent to child revision when possible, which
41 --branchsort convert from parent to child revision when possible, which
42 means branches are usually converted one after the other.
42 means branches are usually converted one after the other.
43 It generates more compact repositories.
43 It generates more compact repositories.
44 --datesort sort revisions by date. Converted repositories have good-
44 --datesort sort revisions by date. Converted repositories have good-
45 looking changelogs but are often an order of magnitude
45 looking changelogs but are often an order of magnitude
46 larger than the same ones generated by --branchsort.
46 larger than the same ones generated by --branchsort.
47 --sourcesort try to preserve source revisions order, only supported by
47 --sourcesort try to preserve source revisions order, only supported by
48 Mercurial sources.
48 Mercurial sources.
49
49
50 If "REVMAP" isn't given, it will be put in a default location
50 If "REVMAP" isn't given, it will be put in a default location
51 ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
51 ("<dest>/.hg/shamap" by default). The "REVMAP" is a simple text file that
52 maps each source commit ID to the destination ID for that revision, like
52 maps each source commit ID to the destination ID for that revision, like
53 so:
53 so:
54
54
55 <source ID> <destination ID>
55 <source ID> <destination ID>
56
56
57 If the file doesn't exist, it's automatically created. It's updated on
57 If the file doesn't exist, it's automatically created. It's updated on
58 each commit copied, so "hg convert" can be interrupted and can be run
58 each commit copied, so "hg convert" can be interrupted and can be run
59 repeatedly to copy new commits.
59 repeatedly to copy new commits.
60
60
61 The authormap is a simple text file that maps each source commit author to
61 The authormap is a simple text file that maps each source commit author to
62 a destination commit author. It is handy for source SCMs that use unix
62 a destination commit author. It is handy for source SCMs that use unix
63 logins to identify authors (e.g.: CVS). One line per author mapping and
63 logins to identify authors (e.g.: CVS). One line per author mapping and
64 the line format is:
64 the line format is:
65
65
66 source author = destination author
66 source author = destination author
67
67
68 Empty lines and lines starting with a "#" are ignored.
68 Empty lines and lines starting with a "#" are ignored.
69
69
70 The filemap is a file that allows filtering and remapping of files and
70 The filemap is a file that allows filtering and remapping of files and
71 directories. Each line can contain one of the following directives:
71 directories. Each line can contain one of the following directives:
72
72
73 include path/to/file-or-dir
73 include path/to/file-or-dir
74
74
75 exclude path/to/file-or-dir
75 exclude path/to/file-or-dir
76
76
77 rename path/to/source path/to/destination
77 rename path/to/source path/to/destination
78
78
79 Comment lines start with "#". A specified path matches if it equals the
79 Comment lines start with "#". A specified path matches if it equals the
80 full relative name of a file or one of its parent directories. The
80 full relative name of a file or one of its parent directories. The
81 "include" or "exclude" directive with the longest matching path applies,
81 "include" or "exclude" directive with the longest matching path applies,
82 so line order does not matter.
82 so line order does not matter.
83
83
84 The "include" directive causes a file, or all files under a directory, to
84 The "include" directive causes a file, or all files under a directory, to
85 be included in the destination repository, and the exclusion of all other
85 be included in the destination repository, and the exclusion of all other
86 files and directories not explicitly included. The "exclude" directive
86 files and directories not explicitly included. The "exclude" directive
87 causes files or directories to be omitted. The "rename" directive renames
87 causes files or directories to be omitted. The "rename" directive renames
88 a file or directory if it is converted. To rename from a subdirectory into
88 a file or directory if it is converted. To rename from a subdirectory into
89 the root of the repository, use "." as the path to rename to.
89 the root of the repository, use "." as the path to rename to.
90
90
91 The splicemap is a file that allows insertion of synthetic history,
91 The splicemap is a file that allows insertion of synthetic history,
92 letting you specify the parents of a revision. This is useful if you want
92 letting you specify the parents of a revision. This is useful if you want
93 to e.g. give a Subversion merge two parents, or graft two disconnected
93 to e.g. give a Subversion merge two parents, or graft two disconnected
94 series of history together. Each entry contains a key, followed by a
94 series of history together. Each entry contains a key, followed by a
95 space, followed by one or two comma-separated values:
95 space, followed by one or two comma-separated values:
96
96
97 key parent1, parent2
97 key parent1, parent2
98
98
99 The key is the revision ID in the source revision control system whose
99 The key is the revision ID in the source revision control system whose
100 parents should be modified (same format as a key in .hg/shamap). The
100 parents should be modified (same format as a key in .hg/shamap). The
101 values are the revision IDs (in either the source or destination revision
101 values are the revision IDs (in either the source or destination revision
102 control system) that should be used as the new parents for that node. For
102 control system) that should be used as the new parents for that node. For
103 example, if you have merged "release-1.0" into "trunk", then you should
103 example, if you have merged "release-1.0" into "trunk", then you should
104 specify the revision on "trunk" as the first parent and the one on the
104 specify the revision on "trunk" as the first parent and the one on the
105 "release-1.0" branch as the second.
105 "release-1.0" branch as the second.
106
106
107 The branchmap is a file that allows you to rename a branch when it is
107 The branchmap is a file that allows you to rename a branch when it is
108 being brought in from whatever external repository. When used in
108 being brought in from whatever external repository. When used in
109 conjunction with a splicemap, it allows for a powerful combination to help
109 conjunction with a splicemap, it allows for a powerful combination to help
110 fix even the most badly mismanaged repositories and turn them into nicely
110 fix even the most badly mismanaged repositories and turn them into nicely
111 structured Mercurial repositories. The branchmap contains lines of the
111 structured Mercurial repositories. The branchmap contains lines of the
112 form:
112 form:
113
113
114 original_branch_name new_branch_name
114 original_branch_name new_branch_name
115
115
116 where "original_branch_name" is the name of the branch in the source
116 where "original_branch_name" is the name of the branch in the source
117 repository, and "new_branch_name" is the name of the branch is the
117 repository, and "new_branch_name" is the name of the branch is the
118 destination repository. No whitespace is allowed in the branch names. This
118 destination repository. No whitespace is allowed in the branch names. This
119 can be used to (for instance) move code in one repository from "default"
119 can be used to (for instance) move code in one repository from "default"
120 to a named branch.
120 to a named branch.
121
121
122 Mercurial Source
122 Mercurial Source
123 ################
123 ################
124
124
125 The Mercurial source recognizes the following configuration options, which
125 The Mercurial source recognizes the following configuration options, which
126 you can set on the command line with "--config":
126 you can set on the command line with "--config":
127
127
128 convert.hg.ignoreerrors
128 convert.hg.ignoreerrors
129 ignore integrity errors when reading. Use it to fix
129 ignore integrity errors when reading. Use it to fix
130 Mercurial repositories with missing revlogs, by converting
130 Mercurial repositories with missing revlogs, by converting
131 from and to Mercurial. Default is False.
131 from and to Mercurial. Default is False.
132 convert.hg.saverev
132 convert.hg.saverev
133 store original revision ID in changeset (forces target IDs
133 store original revision ID in changeset (forces target IDs
134 to change). It takes a boolean argument and defaults to
134 to change). It takes a boolean argument and defaults to
135 False.
135 False.
136 convert.hg.startrev
136 convert.hg.startrev
137 convert start revision and its descendants. It takes a hg
137 convert start revision and its descendants. It takes a hg
138 revision identifier and defaults to 0.
138 revision identifier and defaults to 0.
139
139
140 CVS Source
140 CVS Source
141 ##########
141 ##########
142
142
143 CVS source will use a sandbox (i.e. a checked-out copy) from CVS to
143 CVS source will use a sandbox (i.e. a checked-out copy) from CVS to
144 indicate the starting point of what will be converted. Direct access to
144 indicate the starting point of what will be converted. Direct access to
145 the repository files is not needed, unless of course the repository is
145 the repository files is not needed, unless of course the repository is
146 ":local:". The conversion uses the top level directory in the sandbox to
146 ":local:". The conversion uses the top level directory in the sandbox to
147 find the CVS repository, and then uses CVS rlog commands to find files to
147 find the CVS repository, and then uses CVS rlog commands to find files to
148 convert. This means that unless a filemap is given, all files under the
148 convert. This means that unless a filemap is given, all files under the
149 starting directory will be converted, and that any directory
149 starting directory will be converted, and that any directory
150 reorganization in the CVS sandbox is ignored.
150 reorganization in the CVS sandbox is ignored.
151
151
152 The following options can be used with "--config":
152 The following options can be used with "--config":
153
153
154 convert.cvsps.cache
154 convert.cvsps.cache
155 Set to False to disable remote log caching, for testing and
155 Set to False to disable remote log caching, for testing and
156 debugging purposes. Default is True.
156 debugging purposes. Default is True.
157 convert.cvsps.fuzz
157 convert.cvsps.fuzz
158 Specify the maximum time (in seconds) that is allowed
158 Specify the maximum time (in seconds) that is allowed
159 between commits with identical user and log message in a
159 between commits with identical user and log message in a
160 single changeset. When very large files were checked in as
160 single changeset. When very large files were checked in as
161 part of a changeset then the default may not be long enough.
161 part of a changeset then the default may not be long enough.
162 The default is 60.
162 The default is 60.
163 convert.cvsps.mergeto
163 convert.cvsps.mergeto
164 Specify a regular expression to which commit log messages
164 Specify a regular expression to which commit log messages
165 are matched. If a match occurs, then the conversion process
165 are matched. If a match occurs, then the conversion process
166 will insert a dummy revision merging the branch on which
166 will insert a dummy revision merging the branch on which
167 this log message occurs to the branch indicated in the
167 this log message occurs to the branch indicated in the
168 regex. Default is "{{mergetobranch ([-\w]+)}}"
168 regex. Default is "{{mergetobranch ([-\w]+)}}"
169 convert.cvsps.mergefrom
169 convert.cvsps.mergefrom
170 Specify a regular expression to which commit log messages
170 Specify a regular expression to which commit log messages
171 are matched. If a match occurs, then the conversion process
171 are matched. If a match occurs, then the conversion process
172 will add the most recent revision on the branch indicated in
172 will add the most recent revision on the branch indicated in
173 the regex as the second parent of the changeset. Default is
173 the regex as the second parent of the changeset. Default is
174 "{{mergefrombranch ([-\w]+)}}"
174 "{{mergefrombranch ([-\w]+)}}"
175 convert.localtimezone
175 convert.localtimezone
176 use local time (as determined by the TZ environment
176 use local time (as determined by the TZ environment
177 variable) for changeset date/times. The default is False
177 variable) for changeset date/times. The default is False
178 (use UTC).
178 (use UTC).
179 hook.cvslog Specify a Python function to be called at the end of
179 hook.cvslog Specify a Python function to be called at the end of
180 gathering the CVS log. The function is passed a list with
180 gathering the CVS log. The function is passed a list with
181 the log entries, and can modify the entries in-place, or add
181 the log entries, and can modify the entries in-place, or add
182 or delete them.
182 or delete them.
183 hook.cvschangesets
183 hook.cvschangesets
184 Specify a Python function to be called after the changesets
184 Specify a Python function to be called after the changesets
185 are calculated from the CVS log. The function is passed a
185 are calculated from the CVS log. The function is passed a
186 list with the changeset entries, and can modify the
186 list with the changeset entries, and can modify the
187 changesets in-place, or add or delete them.
187 changesets in-place, or add or delete them.
188
188
189 An additional "debugcvsps" Mercurial command allows the builtin changeset
189 An additional "debugcvsps" Mercurial command allows the builtin changeset
190 merging code to be run without doing a conversion. Its parameters and
190 merging code to be run without doing a conversion. Its parameters and
191 output are similar to that of cvsps 2.1. Please see the command help for
191 output are similar to that of cvsps 2.1. Please see the command help for
192 more details.
192 more details.
193
193
194 Subversion Source
194 Subversion Source
195 #################
195 #################
196
196
197 Subversion source detects classical trunk/branches/tags layouts. By
197 Subversion source detects classical trunk/branches/tags layouts. By
198 default, the supplied "svn://repo/path/" source URL is converted as a
198 default, the supplied "svn://repo/path/" source URL is converted as a
199 single branch. If "svn://repo/path/trunk" exists it replaces the default
199 single branch. If "svn://repo/path/trunk" exists it replaces the default
200 branch. If "svn://repo/path/branches" exists, its subdirectories are
200 branch. If "svn://repo/path/branches" exists, its subdirectories are
201 listed as possible branches. If "svn://repo/path/tags" exists, it is
201 listed as possible branches. If "svn://repo/path/tags" exists, it is
202 looked for tags referencing converted branches. Default "trunk",
202 looked for tags referencing converted branches. Default "trunk",
203 "branches" and "tags" values can be overridden with following options. Set
203 "branches" and "tags" values can be overridden with following options. Set
204 them to paths relative to the source URL, or leave them blank to disable
204 them to paths relative to the source URL, or leave them blank to disable
205 auto detection.
205 auto detection.
206
206
207 The following options can be set with "--config":
207 The following options can be set with "--config":
208
208
209 convert.svn.branches
209 convert.svn.branches
210 specify the directory containing branches. The default is
210 specify the directory containing branches. The default is
211 "branches".
211 "branches".
212 convert.svn.tags
212 convert.svn.tags
213 specify the directory containing tags. The default is
213 specify the directory containing tags. The default is
214 "tags".
214 "tags".
215 convert.svn.trunk
215 convert.svn.trunk
216 specify the name of the trunk branch. The default is
216 specify the name of the trunk branch. The default is
217 "trunk".
217 "trunk".
218 convert.localtimezone
218 convert.localtimezone
219 use local time (as determined by the TZ environment
219 use local time (as determined by the TZ environment
220 variable) for changeset date/times. The default is False
220 variable) for changeset date/times. The default is False
221 (use UTC).
221 (use UTC).
222
222
223 Source history can be retrieved starting at a specific revision, instead
223 Source history can be retrieved starting at a specific revision, instead
224 of being integrally converted. Only single branch conversions are
224 of being integrally converted. Only single branch conversions are
225 supported.
225 supported.
226
226
227 convert.svn.startrev
227 convert.svn.startrev
228 specify start Subversion revision number. The default is 0.
228 specify start Subversion revision number. The default is 0.
229
229
230 Perforce Source
230 Perforce Source
231 ###############
231 ###############
232
232
233 The Perforce (P4) importer can be given a p4 depot path or a client
233 The Perforce (P4) importer can be given a p4 depot path or a client
234 specification as source. It will convert all files in the source to a flat
234 specification as source. It will convert all files in the source to a flat
235 Mercurial repository, ignoring labels, branches and integrations. Note
235 Mercurial repository, ignoring labels, branches and integrations. Note
236 that when a depot path is given you then usually should specify a target
236 that when a depot path is given you then usually should specify a target
237 directory, because otherwise the target may be named "...-hg".
237 directory, because otherwise the target may be named "...-hg".
238
238
239 It is possible to limit the amount of source history to be converted by
239 It is possible to limit the amount of source history to be converted by
240 specifying an initial Perforce revision:
240 specifying an initial Perforce revision:
241
241
242 convert.p4.startrev
242 convert.p4.startrev
243 specify initial Perforce revision (a Perforce changelist
243 specify initial Perforce revision (a Perforce changelist
244 number).
244 number).
245
245
246 Mercurial Destination
246 Mercurial Destination
247 #####################
247 #####################
248
248
249 The following options are supported:
249 The following options are supported:
250
250
251 convert.hg.clonebranches
251 convert.hg.clonebranches
252 dispatch source branches in separate clones. The default is
252 dispatch source branches in separate clones. The default is
253 False.
253 False.
254 convert.hg.tagsbranch
254 convert.hg.tagsbranch
255 branch name for tag revisions, defaults to "default".
255 branch name for tag revisions, defaults to "default".
256 convert.hg.usebranchnames
256 convert.hg.usebranchnames
257 preserve branch names. The default is True.
257 preserve branch names. The default is True.
258
258
259 options:
259 options:
260
260
261 -s --source-type TYPE source repository type
261 -s --source-type TYPE source repository type
262 -d --dest-type TYPE destination repository type
262 -d --dest-type TYPE destination repository type
263 -r --rev REV import up to target revision REV
263 -r --rev REV import up to target revision REV
264 -A --authormap FILE remap usernames using this file
264 -A --authormap FILE remap usernames using this file
265 --filemap FILE remap file names using contents of file
265 --filemap FILE remap file names using contents of file
266 --splicemap FILE splice synthesized history into place
266 --splicemap FILE splice synthesized history into place
267 --branchmap FILE change branch names while converting
267 --branchmap FILE change branch names while converting
268 --branchsort try to sort changesets by branches
268 --branchsort try to sort changesets by branches
269 --datesort try to sort changesets by date
269 --datesort try to sort changesets by date
270 --sourcesort preserve source changesets order
270 --sourcesort preserve source changesets order
271
271
272 use "hg -v help convert" to show the global options
272 use "hg -v help convert" to show the global options
273 $ hg init a
273 $ hg init a
274 $ cd a
274 $ cd a
275 $ echo a > a
275 $ echo a > a
276 $ hg ci -d'0 0' -Ama
276 $ hg ci -d'0 0' -Ama
277 adding a
277 adding a
278 $ hg cp a b
278 $ hg cp a b
279 $ hg ci -d'1 0' -mb
279 $ hg ci -d'1 0' -mb
280 $ hg rm a
280 $ hg rm a
281 $ hg ci -d'2 0' -mc
281 $ hg ci -d'2 0' -mc
282 $ hg mv b a
282 $ hg mv b a
283 $ hg ci -d'3 0' -md
283 $ hg ci -d'3 0' -md
284 $ echo a >> a
284 $ echo a >> a
285 $ hg ci -d'4 0' -me
285 $ hg ci -d'4 0' -me
286 $ cd ..
286 $ cd ..
287 $ hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
287 $ hg convert a 2>&1 | grep -v 'subversion python bindings could not be loaded'
288 assuming destination a-hg
288 assuming destination a-hg
289 initializing destination a-hg repository
289 initializing destination a-hg repository
290 scanning source...
290 scanning source...
291 sorting...
291 sorting...
292 converting...
292 converting...
293 4 a
293 4 a
294 3 b
294 3 b
295 2 c
295 2 c
296 1 d
296 1 d
297 0 e
297 0 e
298 $ hg --cwd a-hg pull ../a
298 $ hg --cwd a-hg pull ../a
299 pulling from ../a
299 pulling from ../a
300 searching for changes
300 searching for changes
301 no changes found
301 no changes found
302
302
303 conversion to existing file should fail
303 conversion to existing file should fail
304
304
305 $ touch bogusfile
305 $ touch bogusfile
306 $ hg convert a bogusfile
306 $ hg convert a bogusfile
307 initializing destination bogusfile repository
307 initializing destination bogusfile repository
308 abort: cannot create new bundle repository
308 abort: cannot create new bundle repository
309 [255]
309 [255]
310
310
311 #if unix-permissions
311 #if unix-permissions
312
312
313 conversion to dir without permissions should fail
313 conversion to dir without permissions should fail
314
314
315 $ mkdir bogusdir
315 $ mkdir bogusdir
316 $ chmod 000 bogusdir
316 $ chmod 000 bogusdir
317
317
318 $ hg convert a bogusdir
318 $ hg convert a bogusdir
319 abort: Permission denied: bogusdir
319 abort: Permission denied: 'bogusdir'
320 [255]
320 [255]
321
321
322 user permissions should succeed
322 user permissions should succeed
323
323
324 $ chmod 700 bogusdir
324 $ chmod 700 bogusdir
325 $ hg convert a bogusdir
325 $ hg convert a bogusdir
326 initializing destination bogusdir repository
326 initializing destination bogusdir repository
327 scanning source...
327 scanning source...
328 sorting...
328 sorting...
329 converting...
329 converting...
330 4 a
330 4 a
331 3 b
331 3 b
332 2 c
332 2 c
333 1 d
333 1 d
334 0 e
334 0 e
335
335
336 #endif
336 #endif
337
337
338 test pre and post conversion actions
338 test pre and post conversion actions
339
339
340 $ echo 'include b' > filemap
340 $ echo 'include b' > filemap
341 $ hg convert --debug --filemap filemap a partialb | \
341 $ hg convert --debug --filemap filemap a partialb | \
342 > grep 'run hg'
342 > grep 'run hg'
343 run hg source pre-conversion action
343 run hg source pre-conversion action
344 run hg sink pre-conversion action
344 run hg sink pre-conversion action
345 run hg sink post-conversion action
345 run hg sink post-conversion action
346 run hg source post-conversion action
346 run hg source post-conversion action
347
347
348 converting empty dir should fail "nicely
348 converting empty dir should fail "nicely
349
349
350 $ mkdir emptydir
350 $ mkdir emptydir
351
351
352 override $PATH to ensure p4 not visible; use $PYTHON in case we're
352 override $PATH to ensure p4 not visible; use $PYTHON in case we're
353 running from a devel copy, not a temp installation
353 running from a devel copy, not a temp installation
354
354
355 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
355 $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg convert emptydir
356 assuming destination emptydir-hg
356 assuming destination emptydir-hg
357 initializing destination emptydir-hg repository
357 initializing destination emptydir-hg repository
358 emptydir does not look like a CVS checkout
358 emptydir does not look like a CVS checkout
359 emptydir does not look like a Git repository
359 emptydir does not look like a Git repository
360 emptydir does not look like a Subversion repository
360 emptydir does not look like a Subversion repository
361 emptydir is not a local Mercurial repository
361 emptydir is not a local Mercurial repository
362 emptydir does not look like a darcs repository
362 emptydir does not look like a darcs repository
363 emptydir does not look like a monotone repository
363 emptydir does not look like a monotone repository
364 emptydir does not look like a GNU Arch repository
364 emptydir does not look like a GNU Arch repository
365 emptydir does not look like a Bazaar repository
365 emptydir does not look like a Bazaar repository
366 cannot find required "p4" tool
366 cannot find required "p4" tool
367 abort: emptydir: missing or unsupported repository
367 abort: emptydir: missing or unsupported repository
368 [255]
368 [255]
369
369
370 convert with imaginary source type
370 convert with imaginary source type
371
371
372 $ hg convert --source-type foo a a-foo
372 $ hg convert --source-type foo a a-foo
373 initializing destination a-foo repository
373 initializing destination a-foo repository
374 abort: foo: invalid source repository type
374 abort: foo: invalid source repository type
375 [255]
375 [255]
376
376
377 convert with imaginary sink type
377 convert with imaginary sink type
378
378
379 $ hg convert --dest-type foo a a-foo
379 $ hg convert --dest-type foo a a-foo
380 abort: foo: invalid destination repository type
380 abort: foo: invalid destination repository type
381 [255]
381 [255]
382
382
383 testing: convert must not produce duplicate entries in fncache
383 testing: convert must not produce duplicate entries in fncache
384
384
385 $ hg convert a b
385 $ hg convert a b
386 initializing destination b repository
386 initializing destination b repository
387 scanning source...
387 scanning source...
388 sorting...
388 sorting...
389 converting...
389 converting...
390 4 a
390 4 a
391 3 b
391 3 b
392 2 c
392 2 c
393 1 d
393 1 d
394 0 e
394 0 e
395
395
396 contents of fncache file:
396 contents of fncache file:
397
397
398 $ cat b/.hg/store/fncache | sort
398 $ cat b/.hg/store/fncache | sort
399 data/a.i
399 data/a.i
400 data/b.i
400 data/b.i
401
401
402 test bogus URL
402 test bogus URL
403
403
404 $ hg convert -q bzr+ssh://foobar@selenic.com/baz baz
404 $ hg convert -q bzr+ssh://foobar@selenic.com/baz baz
405 abort: bzr+ssh://foobar@selenic.com/baz: missing or unsupported repository
405 abort: bzr+ssh://foobar@selenic.com/baz: missing or unsupported repository
406 [255]
406 [255]
407
407
408 test revset converted() lookup
408 test revset converted() lookup
409
409
410 $ hg --config convert.hg.saverev=True convert a c
410 $ hg --config convert.hg.saverev=True convert a c
411 initializing destination c repository
411 initializing destination c repository
412 scanning source...
412 scanning source...
413 sorting...
413 sorting...
414 converting...
414 converting...
415 4 a
415 4 a
416 3 b
416 3 b
417 2 c
417 2 c
418 1 d
418 1 d
419 0 e
419 0 e
420 $ echo f > c/f
420 $ echo f > c/f
421 $ hg -R c ci -d'0 0' -Amf
421 $ hg -R c ci -d'0 0' -Amf
422 adding f
422 adding f
423 created new head
423 created new head
424 $ hg -R c log -r "converted(09d945a62ce6)"
424 $ hg -R c log -r "converted(09d945a62ce6)"
425 changeset: 1:98c3dd46a874
425 changeset: 1:98c3dd46a874
426 user: test
426 user: test
427 date: Thu Jan 01 00:00:01 1970 +0000
427 date: Thu Jan 01 00:00:01 1970 +0000
428 summary: b
428 summary: b
429
429
430 $ hg -R c log -r "converted()"
430 $ hg -R c log -r "converted()"
431 changeset: 0:31ed57b2037c
431 changeset: 0:31ed57b2037c
432 user: test
432 user: test
433 date: Thu Jan 01 00:00:00 1970 +0000
433 date: Thu Jan 01 00:00:00 1970 +0000
434 summary: a
434 summary: a
435
435
436 changeset: 1:98c3dd46a874
436 changeset: 1:98c3dd46a874
437 user: test
437 user: test
438 date: Thu Jan 01 00:00:01 1970 +0000
438 date: Thu Jan 01 00:00:01 1970 +0000
439 summary: b
439 summary: b
440
440
441 changeset: 2:3b9ca06ef716
441 changeset: 2:3b9ca06ef716
442 user: test
442 user: test
443 date: Thu Jan 01 00:00:02 1970 +0000
443 date: Thu Jan 01 00:00:02 1970 +0000
444 summary: c
444 summary: c
445
445
446 changeset: 3:4e0debd37cf2
446 changeset: 3:4e0debd37cf2
447 user: test
447 user: test
448 date: Thu Jan 01 00:00:03 1970 +0000
448 date: Thu Jan 01 00:00:03 1970 +0000
449 summary: d
449 summary: d
450
450
451 changeset: 4:9de3bc9349c5
451 changeset: 4:9de3bc9349c5
452 user: test
452 user: test
453 date: Thu Jan 01 00:00:04 1970 +0000
453 date: Thu Jan 01 00:00:04 1970 +0000
454 summary: e
454 summary: e
455
455
@@ -1,57 +1,63 b''
1 test command parsing and dispatch
1 test command parsing and dispatch
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5
5
6 Redundant options used to crash (issue436):
6 Redundant options used to crash (issue436):
7 $ hg -v log -v
7 $ hg -v log -v
8 $ hg -v log -v x
8 $ hg -v log -v x
9
9
10 $ echo a > a
10 $ echo a > a
11 $ hg ci -Ama
11 $ hg ci -Ama
12 adding a
12 adding a
13
13
14 Missing arg:
14 Missing arg:
15
15
16 $ hg cat
16 $ hg cat
17 hg cat: invalid arguments
17 hg cat: invalid arguments
18 hg cat [OPTION]... FILE...
18 hg cat [OPTION]... FILE...
19
19
20 output the current or given revision of files
20 output the current or given revision of files
21
21
22 options:
22 options:
23
23
24 -o --output FORMAT print output to file with formatted name
24 -o --output FORMAT print output to file with formatted name
25 -r --rev REV print the given revision
25 -r --rev REV print the given revision
26 --decode apply any matching decode filter
26 --decode apply any matching decode filter
27 -I --include PATTERN [+] include names matching the given patterns
27 -I --include PATTERN [+] include names matching the given patterns
28 -X --exclude PATTERN [+] exclude names matching the given patterns
28 -X --exclude PATTERN [+] exclude names matching the given patterns
29
29
30 [+] marked option can be specified multiple times
30 [+] marked option can be specified multiple times
31
31
32 use "hg help cat" to show the full help text
32 use "hg help cat" to show the full help text
33 [255]
33 [255]
34
34
35 [defaults]
35 [defaults]
36
36
37 $ hg cat a
37 $ hg cat a
38 a
38 a
39 $ cat >> $HGRCPATH <<EOF
39 $ cat >> $HGRCPATH <<EOF
40 > [defaults]
40 > [defaults]
41 > cat = -r null
41 > cat = -r null
42 > EOF
42 > EOF
43 $ hg cat a
43 $ hg cat a
44 a: no such file in rev 000000000000
44 a: no such file in rev 000000000000
45 [1]
45 [1]
46
46
47 $ cd "$TESTTMP"
47 $ cd "$TESTTMP"
48
48
49 OSError ... and with filename even when it is empty
50
51 $ hg -R a archive ''
52 abort: No such file or directory: ''
53 [255]
54
49 #if no-outer-repo
55 #if no-outer-repo
50
56
51 No repo:
57 No repo:
52
58
53 $ hg cat
59 $ hg cat
54 abort: no repository found in '$TESTTMP' (.hg not found)!
60 abort: no repository found in '$TESTTMP' (.hg not found)!
55 [255]
61 [255]
56
62
57 #endif
63 #endif
General Comments 0
You need to be logged in to leave comments. Login now