##// END OF EJS Templates
dispatch: do not drop unpaired argument at _earlygetopt()...
Yuya Nishihara -
r35056:7384250e stable
parent child Browse files
Show More
@@ -1,1024 +1,1029 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 __future__ import absolute_import, print_function
8 from __future__ import absolute_import, print_function
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import getopt
12 import getopt
13 import os
13 import os
14 import pdb
14 import pdb
15 import re
15 import re
16 import signal
16 import signal
17 import sys
17 import sys
18 import time
18 import time
19 import traceback
19 import traceback
20
20
21
21
22 from .i18n import _
22 from .i18n import _
23
23
24 from . import (
24 from . import (
25 cmdutil,
25 cmdutil,
26 color,
26 color,
27 commands,
27 commands,
28 demandimport,
28 demandimport,
29 encoding,
29 encoding,
30 error,
30 error,
31 extensions,
31 extensions,
32 fancyopts,
32 fancyopts,
33 help,
33 help,
34 hg,
34 hg,
35 hook,
35 hook,
36 profiling,
36 profiling,
37 pycompat,
37 pycompat,
38 registrar,
38 registrar,
39 scmutil,
39 scmutil,
40 ui as uimod,
40 ui as uimod,
41 util,
41 util,
42 )
42 )
43
43
44 unrecoverablewrite = registrar.command.unrecoverablewrite
44 unrecoverablewrite = registrar.command.unrecoverablewrite
45
45
46 class request(object):
46 class request(object):
47 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
47 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
48 ferr=None, prereposetups=None):
48 ferr=None, prereposetups=None):
49 self.args = args
49 self.args = args
50 self.ui = ui
50 self.ui = ui
51 self.repo = repo
51 self.repo = repo
52
52
53 # input/output/error streams
53 # input/output/error streams
54 self.fin = fin
54 self.fin = fin
55 self.fout = fout
55 self.fout = fout
56 self.ferr = ferr
56 self.ferr = ferr
57
57
58 # reposetups which run before extensions, useful for chg to pre-fill
58 # reposetups which run before extensions, useful for chg to pre-fill
59 # low-level repo state (for example, changelog) before extensions.
59 # low-level repo state (for example, changelog) before extensions.
60 self.prereposetups = prereposetups or []
60 self.prereposetups = prereposetups or []
61
61
62 def _runexithandlers(self):
62 def _runexithandlers(self):
63 exc = None
63 exc = None
64 handlers = self.ui._exithandlers
64 handlers = self.ui._exithandlers
65 try:
65 try:
66 while handlers:
66 while handlers:
67 func, args, kwargs = handlers.pop()
67 func, args, kwargs = handlers.pop()
68 try:
68 try:
69 func(*args, **kwargs)
69 func(*args, **kwargs)
70 except: # re-raises below
70 except: # re-raises below
71 if exc is None:
71 if exc is None:
72 exc = sys.exc_info()[1]
72 exc = sys.exc_info()[1]
73 self.ui.warn(('error in exit handlers:\n'))
73 self.ui.warn(('error in exit handlers:\n'))
74 self.ui.traceback(force=True)
74 self.ui.traceback(force=True)
75 finally:
75 finally:
76 if exc is not None:
76 if exc is not None:
77 raise exc
77 raise exc
78
78
79 def run():
79 def run():
80 "run the command in sys.argv"
80 "run the command in sys.argv"
81 _initstdio()
81 _initstdio()
82 req = request(pycompat.sysargv[1:])
82 req = request(pycompat.sysargv[1:])
83 err = None
83 err = None
84 try:
84 try:
85 status = (dispatch(req) or 0) & 255
85 status = (dispatch(req) or 0) & 255
86 except error.StdioError as e:
86 except error.StdioError as e:
87 err = e
87 err = e
88 status = -1
88 status = -1
89 if util.safehasattr(req.ui, 'fout'):
89 if util.safehasattr(req.ui, 'fout'):
90 try:
90 try:
91 req.ui.fout.flush()
91 req.ui.fout.flush()
92 except IOError as e:
92 except IOError as e:
93 err = e
93 err = e
94 status = -1
94 status = -1
95 if util.safehasattr(req.ui, 'ferr'):
95 if util.safehasattr(req.ui, 'ferr'):
96 if err is not None and err.errno != errno.EPIPE:
96 if err is not None and err.errno != errno.EPIPE:
97 req.ui.ferr.write('abort: %s\n' %
97 req.ui.ferr.write('abort: %s\n' %
98 encoding.strtolocal(err.strerror))
98 encoding.strtolocal(err.strerror))
99 req.ui.ferr.flush()
99 req.ui.ferr.flush()
100 sys.exit(status & 255)
100 sys.exit(status & 255)
101
101
102 def _initstdio():
102 def _initstdio():
103 for fp in (sys.stdin, sys.stdout, sys.stderr):
103 for fp in (sys.stdin, sys.stdout, sys.stderr):
104 util.setbinary(fp)
104 util.setbinary(fp)
105
105
106 def _getsimilar(symbols, value):
106 def _getsimilar(symbols, value):
107 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
107 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
108 # The cutoff for similarity here is pretty arbitrary. It should
108 # The cutoff for similarity here is pretty arbitrary. It should
109 # probably be investigated and tweaked.
109 # probably be investigated and tweaked.
110 return [s for s in symbols if sim(s) > 0.6]
110 return [s for s in symbols if sim(s) > 0.6]
111
111
112 def _reportsimilar(write, similar):
112 def _reportsimilar(write, similar):
113 if len(similar) == 1:
113 if len(similar) == 1:
114 write(_("(did you mean %s?)\n") % similar[0])
114 write(_("(did you mean %s?)\n") % similar[0])
115 elif similar:
115 elif similar:
116 ss = ", ".join(sorted(similar))
116 ss = ", ".join(sorted(similar))
117 write(_("(did you mean one of %s?)\n") % ss)
117 write(_("(did you mean one of %s?)\n") % ss)
118
118
119 def _formatparse(write, inst):
119 def _formatparse(write, inst):
120 similar = []
120 similar = []
121 if isinstance(inst, error.UnknownIdentifier):
121 if isinstance(inst, error.UnknownIdentifier):
122 # make sure to check fileset first, as revset can invoke fileset
122 # make sure to check fileset first, as revset can invoke fileset
123 similar = _getsimilar(inst.symbols, inst.function)
123 similar = _getsimilar(inst.symbols, inst.function)
124 if len(inst.args) > 1:
124 if len(inst.args) > 1:
125 write(_("hg: parse error at %s: %s\n") %
125 write(_("hg: parse error at %s: %s\n") %
126 (inst.args[1], inst.args[0]))
126 (inst.args[1], inst.args[0]))
127 if (inst.args[0][0] == ' '):
127 if (inst.args[0][0] == ' '):
128 write(_("unexpected leading whitespace\n"))
128 write(_("unexpected leading whitespace\n"))
129 else:
129 else:
130 write(_("hg: parse error: %s\n") % inst.args[0])
130 write(_("hg: parse error: %s\n") % inst.args[0])
131 _reportsimilar(write, similar)
131 _reportsimilar(write, similar)
132 if inst.hint:
132 if inst.hint:
133 write(_("(%s)\n") % inst.hint)
133 write(_("(%s)\n") % inst.hint)
134
134
135 def _formatargs(args):
135 def _formatargs(args):
136 return ' '.join(util.shellquote(a) for a in args)
136 return ' '.join(util.shellquote(a) for a in args)
137
137
138 def dispatch(req):
138 def dispatch(req):
139 "run the command specified in req.args"
139 "run the command specified in req.args"
140 if req.ferr:
140 if req.ferr:
141 ferr = req.ferr
141 ferr = req.ferr
142 elif req.ui:
142 elif req.ui:
143 ferr = req.ui.ferr
143 ferr = req.ui.ferr
144 else:
144 else:
145 ferr = util.stderr
145 ferr = util.stderr
146
146
147 try:
147 try:
148 if not req.ui:
148 if not req.ui:
149 req.ui = uimod.ui.load()
149 req.ui = uimod.ui.load()
150 if '--traceback' in req.args:
150 if '--traceback' in req.args:
151 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
151 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
152
152
153 # set ui streams from the request
153 # set ui streams from the request
154 if req.fin:
154 if req.fin:
155 req.ui.fin = req.fin
155 req.ui.fin = req.fin
156 if req.fout:
156 if req.fout:
157 req.ui.fout = req.fout
157 req.ui.fout = req.fout
158 if req.ferr:
158 if req.ferr:
159 req.ui.ferr = req.ferr
159 req.ui.ferr = req.ferr
160 except error.Abort as inst:
160 except error.Abort as inst:
161 ferr.write(_("abort: %s\n") % inst)
161 ferr.write(_("abort: %s\n") % inst)
162 if inst.hint:
162 if inst.hint:
163 ferr.write(_("(%s)\n") % inst.hint)
163 ferr.write(_("(%s)\n") % inst.hint)
164 return -1
164 return -1
165 except error.ParseError as inst:
165 except error.ParseError as inst:
166 _formatparse(ferr.write, inst)
166 _formatparse(ferr.write, inst)
167 return -1
167 return -1
168
168
169 msg = _formatargs(req.args)
169 msg = _formatargs(req.args)
170 starttime = util.timer()
170 starttime = util.timer()
171 ret = None
171 ret = None
172 try:
172 try:
173 ret = _runcatch(req)
173 ret = _runcatch(req)
174 except error.ProgrammingError as inst:
174 except error.ProgrammingError as inst:
175 req.ui.warn(_('** ProgrammingError: %s\n') % inst)
175 req.ui.warn(_('** ProgrammingError: %s\n') % inst)
176 if inst.hint:
176 if inst.hint:
177 req.ui.warn(_('** (%s)\n') % inst.hint)
177 req.ui.warn(_('** (%s)\n') % inst.hint)
178 raise
178 raise
179 except KeyboardInterrupt as inst:
179 except KeyboardInterrupt as inst:
180 try:
180 try:
181 if isinstance(inst, error.SignalInterrupt):
181 if isinstance(inst, error.SignalInterrupt):
182 msg = _("killed!\n")
182 msg = _("killed!\n")
183 else:
183 else:
184 msg = _("interrupted!\n")
184 msg = _("interrupted!\n")
185 req.ui.warn(msg)
185 req.ui.warn(msg)
186 except error.SignalInterrupt:
186 except error.SignalInterrupt:
187 # maybe pager would quit without consuming all the output, and
187 # maybe pager would quit without consuming all the output, and
188 # SIGPIPE was raised. we cannot print anything in this case.
188 # SIGPIPE was raised. we cannot print anything in this case.
189 pass
189 pass
190 except IOError as inst:
190 except IOError as inst:
191 if inst.errno != errno.EPIPE:
191 if inst.errno != errno.EPIPE:
192 raise
192 raise
193 ret = -1
193 ret = -1
194 finally:
194 finally:
195 duration = util.timer() - starttime
195 duration = util.timer() - starttime
196 req.ui.flush()
196 req.ui.flush()
197 if req.ui.logblockedtimes:
197 if req.ui.logblockedtimes:
198 req.ui._blockedtimes['command_duration'] = duration * 1000
198 req.ui._blockedtimes['command_duration'] = duration * 1000
199 req.ui.log('uiblocked', 'ui blocked ms', **req.ui._blockedtimes)
199 req.ui.log('uiblocked', 'ui blocked ms', **req.ui._blockedtimes)
200 req.ui.log("commandfinish", "%s exited %d after %0.2f seconds\n",
200 req.ui.log("commandfinish", "%s exited %d after %0.2f seconds\n",
201 msg, ret or 0, duration)
201 msg, ret or 0, duration)
202 try:
202 try:
203 req._runexithandlers()
203 req._runexithandlers()
204 except: # exiting, so no re-raises
204 except: # exiting, so no re-raises
205 ret = ret or -1
205 ret = ret or -1
206 return ret
206 return ret
207
207
208 def _runcatch(req):
208 def _runcatch(req):
209 def catchterm(*args):
209 def catchterm(*args):
210 raise error.SignalInterrupt
210 raise error.SignalInterrupt
211
211
212 ui = req.ui
212 ui = req.ui
213 try:
213 try:
214 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
214 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
215 num = getattr(signal, name, None)
215 num = getattr(signal, name, None)
216 if num:
216 if num:
217 signal.signal(num, catchterm)
217 signal.signal(num, catchterm)
218 except ValueError:
218 except ValueError:
219 pass # happens if called in a thread
219 pass # happens if called in a thread
220
220
221 def _runcatchfunc():
221 def _runcatchfunc():
222 realcmd = None
222 realcmd = None
223 try:
223 try:
224 cmdargs = fancyopts.fancyopts(req.args[:], commands.globalopts, {})
224 cmdargs = fancyopts.fancyopts(req.args[:], commands.globalopts, {})
225 cmd = cmdargs[0]
225 cmd = cmdargs[0]
226 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
226 aliases, entry = cmdutil.findcmd(cmd, commands.table, False)
227 realcmd = aliases[0]
227 realcmd = aliases[0]
228 except (error.UnknownCommand, error.AmbiguousCommand,
228 except (error.UnknownCommand, error.AmbiguousCommand,
229 IndexError, getopt.GetoptError):
229 IndexError, getopt.GetoptError):
230 # Don't handle this here. We know the command is
230 # Don't handle this here. We know the command is
231 # invalid, but all we're worried about for now is that
231 # invalid, but all we're worried about for now is that
232 # it's not a command that server operators expect to
232 # it's not a command that server operators expect to
233 # be safe to offer to users in a sandbox.
233 # be safe to offer to users in a sandbox.
234 pass
234 pass
235 if realcmd == 'serve' and '--stdio' in cmdargs:
235 if realcmd == 'serve' and '--stdio' in cmdargs:
236 # We want to constrain 'hg serve --stdio' instances pretty
236 # We want to constrain 'hg serve --stdio' instances pretty
237 # closely, as many shared-ssh access tools want to grant
237 # closely, as many shared-ssh access tools want to grant
238 # access to run *only* 'hg -R $repo serve --stdio'. We
238 # access to run *only* 'hg -R $repo serve --stdio'. We
239 # restrict to exactly that set of arguments, and prohibit
239 # restrict to exactly that set of arguments, and prohibit
240 # any repo name that starts with '--' to prevent
240 # any repo name that starts with '--' to prevent
241 # shenanigans wherein a user does something like pass
241 # shenanigans wherein a user does something like pass
242 # --debugger or --config=ui.debugger=1 as a repo
242 # --debugger or --config=ui.debugger=1 as a repo
243 # name. This used to actually run the debugger.
243 # name. This used to actually run the debugger.
244 if (len(req.args) != 4 or
244 if (len(req.args) != 4 or
245 req.args[0] != '-R' or
245 req.args[0] != '-R' or
246 req.args[1].startswith('--') or
246 req.args[1].startswith('--') or
247 req.args[2] != 'serve' or
247 req.args[2] != 'serve' or
248 req.args[3] != '--stdio'):
248 req.args[3] != '--stdio'):
249 raise error.Abort(
249 raise error.Abort(
250 _('potentially unsafe serve --stdio invocation: %r') %
250 _('potentially unsafe serve --stdio invocation: %r') %
251 (req.args,))
251 (req.args,))
252
252
253 try:
253 try:
254 debugger = 'pdb'
254 debugger = 'pdb'
255 debugtrace = {
255 debugtrace = {
256 'pdb': pdb.set_trace
256 'pdb': pdb.set_trace
257 }
257 }
258 debugmortem = {
258 debugmortem = {
259 'pdb': pdb.post_mortem
259 'pdb': pdb.post_mortem
260 }
260 }
261
261
262 # read --config before doing anything else
262 # read --config before doing anything else
263 # (e.g. to change trust settings for reading .hg/hgrc)
263 # (e.g. to change trust settings for reading .hg/hgrc)
264 cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
264 cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
265
265
266 if req.repo:
266 if req.repo:
267 # copy configs that were passed on the cmdline (--config) to
267 # copy configs that were passed on the cmdline (--config) to
268 # the repo ui
268 # the repo ui
269 for sec, name, val in cfgs:
269 for sec, name, val in cfgs:
270 req.repo.ui.setconfig(sec, name, val, source='--config')
270 req.repo.ui.setconfig(sec, name, val, source='--config')
271
271
272 # developer config: ui.debugger
272 # developer config: ui.debugger
273 debugger = ui.config("ui", "debugger")
273 debugger = ui.config("ui", "debugger")
274 debugmod = pdb
274 debugmod = pdb
275 if not debugger or ui.plain():
275 if not debugger or ui.plain():
276 # if we are in HGPLAIN mode, then disable custom debugging
276 # if we are in HGPLAIN mode, then disable custom debugging
277 debugger = 'pdb'
277 debugger = 'pdb'
278 elif '--debugger' in req.args:
278 elif '--debugger' in req.args:
279 # This import can be slow for fancy debuggers, so only
279 # This import can be slow for fancy debuggers, so only
280 # do it when absolutely necessary, i.e. when actual
280 # do it when absolutely necessary, i.e. when actual
281 # debugging has been requested
281 # debugging has been requested
282 with demandimport.deactivated():
282 with demandimport.deactivated():
283 try:
283 try:
284 debugmod = __import__(debugger)
284 debugmod = __import__(debugger)
285 except ImportError:
285 except ImportError:
286 pass # Leave debugmod = pdb
286 pass # Leave debugmod = pdb
287
287
288 debugtrace[debugger] = debugmod.set_trace
288 debugtrace[debugger] = debugmod.set_trace
289 debugmortem[debugger] = debugmod.post_mortem
289 debugmortem[debugger] = debugmod.post_mortem
290
290
291 # enter the debugger before command execution
291 # enter the debugger before command execution
292 if '--debugger' in req.args:
292 if '--debugger' in req.args:
293 ui.warn(_("entering debugger - "
293 ui.warn(_("entering debugger - "
294 "type c to continue starting hg or h for help\n"))
294 "type c to continue starting hg or h for help\n"))
295
295
296 if (debugger != 'pdb' and
296 if (debugger != 'pdb' and
297 debugtrace[debugger] == debugtrace['pdb']):
297 debugtrace[debugger] == debugtrace['pdb']):
298 ui.warn(_("%s debugger specified "
298 ui.warn(_("%s debugger specified "
299 "but its module was not found\n") % debugger)
299 "but its module was not found\n") % debugger)
300 with demandimport.deactivated():
300 with demandimport.deactivated():
301 debugtrace[debugger]()
301 debugtrace[debugger]()
302 try:
302 try:
303 return _dispatch(req)
303 return _dispatch(req)
304 finally:
304 finally:
305 ui.flush()
305 ui.flush()
306 except: # re-raises
306 except: # re-raises
307 # enter the debugger when we hit an exception
307 # enter the debugger when we hit an exception
308 if '--debugger' in req.args:
308 if '--debugger' in req.args:
309 traceback.print_exc()
309 traceback.print_exc()
310 debugmortem[debugger](sys.exc_info()[2])
310 debugmortem[debugger](sys.exc_info()[2])
311 raise
311 raise
312
312
313 return _callcatch(ui, _runcatchfunc)
313 return _callcatch(ui, _runcatchfunc)
314
314
315 def _callcatch(ui, func):
315 def _callcatch(ui, func):
316 """like scmutil.callcatch but handles more high-level exceptions about
316 """like scmutil.callcatch but handles more high-level exceptions about
317 config parsing and commands. besides, use handlecommandexception to handle
317 config parsing and commands. besides, use handlecommandexception to handle
318 uncaught exceptions.
318 uncaught exceptions.
319 """
319 """
320 try:
320 try:
321 return scmutil.callcatch(ui, func)
321 return scmutil.callcatch(ui, func)
322 except error.AmbiguousCommand as inst:
322 except error.AmbiguousCommand as inst:
323 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
323 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
324 (inst.args[0], " ".join(inst.args[1])))
324 (inst.args[0], " ".join(inst.args[1])))
325 except error.CommandError as inst:
325 except error.CommandError as inst:
326 if inst.args[0]:
326 if inst.args[0]:
327 ui.pager('help')
327 ui.pager('help')
328 msgbytes = pycompat.bytestr(inst.args[1])
328 msgbytes = pycompat.bytestr(inst.args[1])
329 ui.warn(_("hg %s: %s\n") % (inst.args[0], msgbytes))
329 ui.warn(_("hg %s: %s\n") % (inst.args[0], msgbytes))
330 commands.help_(ui, inst.args[0], full=False, command=True)
330 commands.help_(ui, inst.args[0], full=False, command=True)
331 else:
331 else:
332 ui.pager('help')
332 ui.pager('help')
333 ui.warn(_("hg: %s\n") % inst.args[1])
333 ui.warn(_("hg: %s\n") % inst.args[1])
334 commands.help_(ui, 'shortlist')
334 commands.help_(ui, 'shortlist')
335 except error.ParseError as inst:
335 except error.ParseError as inst:
336 _formatparse(ui.warn, inst)
336 _formatparse(ui.warn, inst)
337 return -1
337 return -1
338 except error.UnknownCommand as inst:
338 except error.UnknownCommand as inst:
339 nocmdmsg = _("hg: unknown command '%s'\n") % inst.args[0]
339 nocmdmsg = _("hg: unknown command '%s'\n") % inst.args[0]
340 try:
340 try:
341 # check if the command is in a disabled extension
341 # check if the command is in a disabled extension
342 # (but don't check for extensions themselves)
342 # (but don't check for extensions themselves)
343 formatted = help.formattedhelp(ui, commands, inst.args[0],
343 formatted = help.formattedhelp(ui, commands, inst.args[0],
344 unknowncmd=True)
344 unknowncmd=True)
345 ui.warn(nocmdmsg)
345 ui.warn(nocmdmsg)
346 ui.write(formatted)
346 ui.write(formatted)
347 except (error.UnknownCommand, error.Abort):
347 except (error.UnknownCommand, error.Abort):
348 suggested = False
348 suggested = False
349 if len(inst.args) == 2:
349 if len(inst.args) == 2:
350 sim = _getsimilar(inst.args[1], inst.args[0])
350 sim = _getsimilar(inst.args[1], inst.args[0])
351 if sim:
351 if sim:
352 ui.warn(nocmdmsg)
352 ui.warn(nocmdmsg)
353 _reportsimilar(ui.warn, sim)
353 _reportsimilar(ui.warn, sim)
354 suggested = True
354 suggested = True
355 if not suggested:
355 if not suggested:
356 ui.pager('help')
356 ui.pager('help')
357 ui.warn(nocmdmsg)
357 ui.warn(nocmdmsg)
358 commands.help_(ui, 'shortlist')
358 commands.help_(ui, 'shortlist')
359 except IOError:
359 except IOError:
360 raise
360 raise
361 except KeyboardInterrupt:
361 except KeyboardInterrupt:
362 raise
362 raise
363 except: # probably re-raises
363 except: # probably re-raises
364 if not handlecommandexception(ui):
364 if not handlecommandexception(ui):
365 raise
365 raise
366
366
367 return -1
367 return -1
368
368
369 def aliasargs(fn, givenargs):
369 def aliasargs(fn, givenargs):
370 args = []
370 args = []
371 # only care about alias 'args', ignore 'args' set by extensions.wrapfunction
371 # only care about alias 'args', ignore 'args' set by extensions.wrapfunction
372 if not util.safehasattr(fn, '_origfunc'):
372 if not util.safehasattr(fn, '_origfunc'):
373 args = getattr(fn, 'args', args)
373 args = getattr(fn, 'args', args)
374 if args:
374 if args:
375 cmd = ' '.join(map(util.shellquote, args))
375 cmd = ' '.join(map(util.shellquote, args))
376
376
377 nums = []
377 nums = []
378 def replacer(m):
378 def replacer(m):
379 num = int(m.group(1)) - 1
379 num = int(m.group(1)) - 1
380 nums.append(num)
380 nums.append(num)
381 if num < len(givenargs):
381 if num < len(givenargs):
382 return givenargs[num]
382 return givenargs[num]
383 raise error.Abort(_('too few arguments for command alias'))
383 raise error.Abort(_('too few arguments for command alias'))
384 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd)
384 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd)
385 givenargs = [x for i, x in enumerate(givenargs)
385 givenargs = [x for i, x in enumerate(givenargs)
386 if i not in nums]
386 if i not in nums]
387 args = pycompat.shlexsplit(cmd)
387 args = pycompat.shlexsplit(cmd)
388 return args + givenargs
388 return args + givenargs
389
389
390 def aliasinterpolate(name, args, cmd):
390 def aliasinterpolate(name, args, cmd):
391 '''interpolate args into cmd for shell aliases
391 '''interpolate args into cmd for shell aliases
392
392
393 This also handles $0, $@ and "$@".
393 This also handles $0, $@ and "$@".
394 '''
394 '''
395 # util.interpolate can't deal with "$@" (with quotes) because it's only
395 # util.interpolate can't deal with "$@" (with quotes) because it's only
396 # built to match prefix + patterns.
396 # built to match prefix + patterns.
397 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
397 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
398 replacemap['$0'] = name
398 replacemap['$0'] = name
399 replacemap['$$'] = '$'
399 replacemap['$$'] = '$'
400 replacemap['$@'] = ' '.join(args)
400 replacemap['$@'] = ' '.join(args)
401 # Typical Unix shells interpolate "$@" (with quotes) as all the positional
401 # Typical Unix shells interpolate "$@" (with quotes) as all the positional
402 # parameters, separated out into words. Emulate the same behavior here by
402 # parameters, separated out into words. Emulate the same behavior here by
403 # quoting the arguments individually. POSIX shells will then typically
403 # quoting the arguments individually. POSIX shells will then typically
404 # tokenize each argument into exactly one word.
404 # tokenize each argument into exactly one word.
405 replacemap['"$@"'] = ' '.join(util.shellquote(arg) for arg in args)
405 replacemap['"$@"'] = ' '.join(util.shellquote(arg) for arg in args)
406 # escape '\$' for regex
406 # escape '\$' for regex
407 regex = '|'.join(replacemap.keys()).replace('$', r'\$')
407 regex = '|'.join(replacemap.keys()).replace('$', r'\$')
408 r = re.compile(regex)
408 r = re.compile(regex)
409 return r.sub(lambda x: replacemap[x.group()], cmd)
409 return r.sub(lambda x: replacemap[x.group()], cmd)
410
410
411 class cmdalias(object):
411 class cmdalias(object):
412 def __init__(self, name, definition, cmdtable, source):
412 def __init__(self, name, definition, cmdtable, source):
413 self.name = self.cmd = name
413 self.name = self.cmd = name
414 self.cmdname = ''
414 self.cmdname = ''
415 self.definition = definition
415 self.definition = definition
416 self.fn = None
416 self.fn = None
417 self.givenargs = []
417 self.givenargs = []
418 self.opts = []
418 self.opts = []
419 self.help = ''
419 self.help = ''
420 self.badalias = None
420 self.badalias = None
421 self.unknowncmd = False
421 self.unknowncmd = False
422 self.source = source
422 self.source = source
423
423
424 try:
424 try:
425 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
425 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
426 for alias, e in cmdtable.iteritems():
426 for alias, e in cmdtable.iteritems():
427 if e is entry:
427 if e is entry:
428 self.cmd = alias
428 self.cmd = alias
429 break
429 break
430 self.shadows = True
430 self.shadows = True
431 except error.UnknownCommand:
431 except error.UnknownCommand:
432 self.shadows = False
432 self.shadows = False
433
433
434 if not self.definition:
434 if not self.definition:
435 self.badalias = _("no definition for alias '%s'") % self.name
435 self.badalias = _("no definition for alias '%s'") % self.name
436 return
436 return
437
437
438 if self.definition.startswith('!'):
438 if self.definition.startswith('!'):
439 self.shell = True
439 self.shell = True
440 def fn(ui, *args):
440 def fn(ui, *args):
441 env = {'HG_ARGS': ' '.join((self.name,) + args)}
441 env = {'HG_ARGS': ' '.join((self.name,) + args)}
442 def _checkvar(m):
442 def _checkvar(m):
443 if m.groups()[0] == '$':
443 if m.groups()[0] == '$':
444 return m.group()
444 return m.group()
445 elif int(m.groups()[0]) <= len(args):
445 elif int(m.groups()[0]) <= len(args):
446 return m.group()
446 return m.group()
447 else:
447 else:
448 ui.debug("No argument found for substitution "
448 ui.debug("No argument found for substitution "
449 "of %i variable in alias '%s' definition."
449 "of %i variable in alias '%s' definition."
450 % (int(m.groups()[0]), self.name))
450 % (int(m.groups()[0]), self.name))
451 return ''
451 return ''
452 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
452 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
453 cmd = aliasinterpolate(self.name, args, cmd)
453 cmd = aliasinterpolate(self.name, args, cmd)
454 return ui.system(cmd, environ=env,
454 return ui.system(cmd, environ=env,
455 blockedtag='alias_%s' % self.name)
455 blockedtag='alias_%s' % self.name)
456 self.fn = fn
456 self.fn = fn
457 return
457 return
458
458
459 try:
459 try:
460 args = pycompat.shlexsplit(self.definition)
460 args = pycompat.shlexsplit(self.definition)
461 except ValueError as inst:
461 except ValueError as inst:
462 self.badalias = (_("error in definition for alias '%s': %s")
462 self.badalias = (_("error in definition for alias '%s': %s")
463 % (self.name, inst))
463 % (self.name, inst))
464 return
464 return
465 self.cmdname = cmd = args.pop(0)
465 self.cmdname = cmd = args.pop(0)
466 self.givenargs = args
466 self.givenargs = args
467
467
468 for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"):
468 for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"):
469 if _earlygetopt([invalidarg], args):
469 if _earlygetopt([invalidarg], args):
470 self.badalias = (_("error in definition for alias '%s': %s may "
470 self.badalias = (_("error in definition for alias '%s': %s may "
471 "only be given on the command line")
471 "only be given on the command line")
472 % (self.name, invalidarg))
472 % (self.name, invalidarg))
473 return
473 return
474
474
475 try:
475 try:
476 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
476 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
477 if len(tableentry) > 2:
477 if len(tableentry) > 2:
478 self.fn, self.opts, self.help = tableentry
478 self.fn, self.opts, self.help = tableentry
479 else:
479 else:
480 self.fn, self.opts = tableentry
480 self.fn, self.opts = tableentry
481
481
482 if self.help.startswith("hg " + cmd):
482 if self.help.startswith("hg " + cmd):
483 # drop prefix in old-style help lines so hg shows the alias
483 # drop prefix in old-style help lines so hg shows the alias
484 self.help = self.help[4 + len(cmd):]
484 self.help = self.help[4 + len(cmd):]
485 self.__doc__ = self.fn.__doc__
485 self.__doc__ = self.fn.__doc__
486
486
487 except error.UnknownCommand:
487 except error.UnknownCommand:
488 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
488 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
489 % (self.name, cmd))
489 % (self.name, cmd))
490 self.unknowncmd = True
490 self.unknowncmd = True
491 except error.AmbiguousCommand:
491 except error.AmbiguousCommand:
492 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
492 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
493 % (self.name, cmd))
493 % (self.name, cmd))
494
494
495 @property
495 @property
496 def args(self):
496 def args(self):
497 args = pycompat.maplist(util.expandpath, self.givenargs)
497 args = pycompat.maplist(util.expandpath, self.givenargs)
498 return aliasargs(self.fn, args)
498 return aliasargs(self.fn, args)
499
499
500 def __getattr__(self, name):
500 def __getattr__(self, name):
501 adefaults = {r'norepo': True, r'cmdtype': unrecoverablewrite,
501 adefaults = {r'norepo': True, r'cmdtype': unrecoverablewrite,
502 r'optionalrepo': False, r'inferrepo': False}
502 r'optionalrepo': False, r'inferrepo': False}
503 if name not in adefaults:
503 if name not in adefaults:
504 raise AttributeError(name)
504 raise AttributeError(name)
505 if self.badalias or util.safehasattr(self, 'shell'):
505 if self.badalias or util.safehasattr(self, 'shell'):
506 return adefaults[name]
506 return adefaults[name]
507 return getattr(self.fn, name)
507 return getattr(self.fn, name)
508
508
509 def __call__(self, ui, *args, **opts):
509 def __call__(self, ui, *args, **opts):
510 if self.badalias:
510 if self.badalias:
511 hint = None
511 hint = None
512 if self.unknowncmd:
512 if self.unknowncmd:
513 try:
513 try:
514 # check if the command is in a disabled extension
514 # check if the command is in a disabled extension
515 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
515 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
516 hint = _("'%s' is provided by '%s' extension") % (cmd, ext)
516 hint = _("'%s' is provided by '%s' extension") % (cmd, ext)
517 except error.UnknownCommand:
517 except error.UnknownCommand:
518 pass
518 pass
519 raise error.Abort(self.badalias, hint=hint)
519 raise error.Abort(self.badalias, hint=hint)
520 if self.shadows:
520 if self.shadows:
521 ui.debug("alias '%s' shadows command '%s'\n" %
521 ui.debug("alias '%s' shadows command '%s'\n" %
522 (self.name, self.cmdname))
522 (self.name, self.cmdname))
523
523
524 ui.log('commandalias', "alias '%s' expands to '%s'\n",
524 ui.log('commandalias', "alias '%s' expands to '%s'\n",
525 self.name, self.definition)
525 self.name, self.definition)
526 if util.safehasattr(self, 'shell'):
526 if util.safehasattr(self, 'shell'):
527 return self.fn(ui, *args, **opts)
527 return self.fn(ui, *args, **opts)
528 else:
528 else:
529 try:
529 try:
530 return util.checksignature(self.fn)(ui, *args, **opts)
530 return util.checksignature(self.fn)(ui, *args, **opts)
531 except error.SignatureError:
531 except error.SignatureError:
532 args = ' '.join([self.cmdname] + self.args)
532 args = ' '.join([self.cmdname] + self.args)
533 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
533 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
534 raise
534 raise
535
535
536 class lazyaliasentry(object):
536 class lazyaliasentry(object):
537 """like a typical command entry (func, opts, help), but is lazy"""
537 """like a typical command entry (func, opts, help), but is lazy"""
538
538
539 def __init__(self, name, definition, cmdtable, source):
539 def __init__(self, name, definition, cmdtable, source):
540 self.name = name
540 self.name = name
541 self.definition = definition
541 self.definition = definition
542 self.cmdtable = cmdtable.copy()
542 self.cmdtable = cmdtable.copy()
543 self.source = source
543 self.source = source
544
544
545 @util.propertycache
545 @util.propertycache
546 def _aliasdef(self):
546 def _aliasdef(self):
547 return cmdalias(self.name, self.definition, self.cmdtable, self.source)
547 return cmdalias(self.name, self.definition, self.cmdtable, self.source)
548
548
549 def __getitem__(self, n):
549 def __getitem__(self, n):
550 aliasdef = self._aliasdef
550 aliasdef = self._aliasdef
551 if n == 0:
551 if n == 0:
552 return aliasdef
552 return aliasdef
553 elif n == 1:
553 elif n == 1:
554 return aliasdef.opts
554 return aliasdef.opts
555 elif n == 2:
555 elif n == 2:
556 return aliasdef.help
556 return aliasdef.help
557 else:
557 else:
558 raise IndexError
558 raise IndexError
559
559
560 def __iter__(self):
560 def __iter__(self):
561 for i in range(3):
561 for i in range(3):
562 yield self[i]
562 yield self[i]
563
563
564 def __len__(self):
564 def __len__(self):
565 return 3
565 return 3
566
566
567 def addaliases(ui, cmdtable):
567 def addaliases(ui, cmdtable):
568 # aliases are processed after extensions have been loaded, so they
568 # aliases are processed after extensions have been loaded, so they
569 # may use extension commands. Aliases can also use other alias definitions,
569 # may use extension commands. Aliases can also use other alias definitions,
570 # but only if they have been defined prior to the current definition.
570 # but only if they have been defined prior to the current definition.
571 for alias, definition in ui.configitems('alias'):
571 for alias, definition in ui.configitems('alias'):
572 try:
572 try:
573 if cmdtable[alias].definition == definition:
573 if cmdtable[alias].definition == definition:
574 continue
574 continue
575 except (KeyError, AttributeError):
575 except (KeyError, AttributeError):
576 # definition might not exist or it might not be a cmdalias
576 # definition might not exist or it might not be a cmdalias
577 pass
577 pass
578
578
579 source = ui.configsource('alias', alias)
579 source = ui.configsource('alias', alias)
580 entry = lazyaliasentry(alias, definition, cmdtable, source)
580 entry = lazyaliasentry(alias, definition, cmdtable, source)
581 cmdtable[alias] = entry
581 cmdtable[alias] = entry
582
582
583 def _parse(ui, args):
583 def _parse(ui, args):
584 options = {}
584 options = {}
585 cmdoptions = {}
585 cmdoptions = {}
586
586
587 try:
587 try:
588 args = fancyopts.fancyopts(args, commands.globalopts, options)
588 args = fancyopts.fancyopts(args, commands.globalopts, options)
589 except getopt.GetoptError as inst:
589 except getopt.GetoptError as inst:
590 raise error.CommandError(None, inst)
590 raise error.CommandError(None, inst)
591
591
592 if args:
592 if args:
593 cmd, args = args[0], args[1:]
593 cmd, args = args[0], args[1:]
594 aliases, entry = cmdutil.findcmd(cmd, commands.table,
594 aliases, entry = cmdutil.findcmd(cmd, commands.table,
595 ui.configbool("ui", "strict"))
595 ui.configbool("ui", "strict"))
596 cmd = aliases[0]
596 cmd = aliases[0]
597 args = aliasargs(entry[0], args)
597 args = aliasargs(entry[0], args)
598 defaults = ui.config("defaults", cmd)
598 defaults = ui.config("defaults", cmd)
599 if defaults:
599 if defaults:
600 args = pycompat.maplist(
600 args = pycompat.maplist(
601 util.expandpath, pycompat.shlexsplit(defaults)) + args
601 util.expandpath, pycompat.shlexsplit(defaults)) + args
602 c = list(entry[1])
602 c = list(entry[1])
603 else:
603 else:
604 cmd = None
604 cmd = None
605 c = []
605 c = []
606
606
607 # combine global options into local
607 # combine global options into local
608 for o in commands.globalopts:
608 for o in commands.globalopts:
609 c.append((o[0], o[1], options[o[1]], o[3]))
609 c.append((o[0], o[1], options[o[1]], o[3]))
610
610
611 try:
611 try:
612 args = fancyopts.fancyopts(args, c, cmdoptions, gnu=True)
612 args = fancyopts.fancyopts(args, c, cmdoptions, gnu=True)
613 except getopt.GetoptError as inst:
613 except getopt.GetoptError as inst:
614 raise error.CommandError(cmd, inst)
614 raise error.CommandError(cmd, inst)
615
615
616 # separate global options back out
616 # separate global options back out
617 for o in commands.globalopts:
617 for o in commands.globalopts:
618 n = o[1]
618 n = o[1]
619 options[n] = cmdoptions[n]
619 options[n] = cmdoptions[n]
620 del cmdoptions[n]
620 del cmdoptions[n]
621
621
622 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
622 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
623
623
624 def _parseconfig(ui, config):
624 def _parseconfig(ui, config):
625 """parse the --config options from the command line"""
625 """parse the --config options from the command line"""
626 configs = []
626 configs = []
627
627
628 for cfg in config:
628 for cfg in config:
629 try:
629 try:
630 name, value = [cfgelem.strip()
630 name, value = [cfgelem.strip()
631 for cfgelem in cfg.split('=', 1)]
631 for cfgelem in cfg.split('=', 1)]
632 section, name = name.split('.', 1)
632 section, name = name.split('.', 1)
633 if not section or not name:
633 if not section or not name:
634 raise IndexError
634 raise IndexError
635 ui.setconfig(section, name, value, '--config')
635 ui.setconfig(section, name, value, '--config')
636 configs.append((section, name, value))
636 configs.append((section, name, value))
637 except (IndexError, ValueError):
637 except (IndexError, ValueError):
638 raise error.Abort(_('malformed --config option: %r '
638 raise error.Abort(_('malformed --config option: %r '
639 '(use --config section.name=value)') % cfg)
639 '(use --config section.name=value)') % cfg)
640
640
641 return configs
641 return configs
642
642
643 def _earlygetopt(aliases, args):
643 def _earlygetopt(aliases, args):
644 """Return list of values for an option (or aliases).
644 """Return list of values for an option (or aliases).
645
645
646 The values are listed in the order they appear in args.
646 The values are listed in the order they appear in args.
647 The options and values are removed from args.
647 The options and values are removed from args.
648
648
649 >>> args = [b'x', b'--cwd', b'foo', b'y']
649 >>> args = [b'x', b'--cwd', b'foo', b'y']
650 >>> _earlygetopt([b'--cwd'], args), args
650 >>> _earlygetopt([b'--cwd'], args), args
651 (['foo'], ['x', 'y'])
651 (['foo'], ['x', 'y'])
652
652
653 >>> args = [b'x', b'--cwd=bar', b'y']
653 >>> args = [b'x', b'--cwd=bar', b'y']
654 >>> _earlygetopt([b'--cwd'], args), args
654 >>> _earlygetopt([b'--cwd'], args), args
655 (['bar'], ['x', 'y'])
655 (['bar'], ['x', 'y'])
656
656
657 >>> args = [b'x', b'-R', b'foo', b'y']
657 >>> args = [b'x', b'-R', b'foo', b'y']
658 >>> _earlygetopt([b'-R'], args), args
658 >>> _earlygetopt([b'-R'], args), args
659 (['foo'], ['x', 'y'])
659 (['foo'], ['x', 'y'])
660
660
661 >>> args = [b'x', b'-Rbar', b'y']
661 >>> args = [b'x', b'-Rbar', b'y']
662 >>> _earlygetopt([b'-R'], args), args
662 >>> _earlygetopt([b'-R'], args), args
663 (['bar'], ['x', 'y'])
663 (['bar'], ['x', 'y'])
664
665 >>> args = [b'x', b'-R', b'--', b'y']
666 >>> _earlygetopt([b'-R'], args), args
667 ([], ['x', '-R', '--', 'y'])
664 """
668 """
665 try:
669 try:
666 argcount = args.index("--")
670 argcount = args.index("--")
667 except ValueError:
671 except ValueError:
668 argcount = len(args)
672 argcount = len(args)
669 shortopts = [opt for opt in aliases if len(opt) == 2]
673 shortopts = [opt for opt in aliases if len(opt) == 2]
670 values = []
674 values = []
671 pos = 0
675 pos = 0
672 while pos < argcount:
676 while pos < argcount:
673 fullarg = arg = args[pos]
677 fullarg = arg = args[pos]
674 equals = arg.find('=')
678 equals = arg.find('=')
675 if equals > -1:
679 if equals > -1:
676 arg = arg[:equals]
680 arg = arg[:equals]
677 if arg in aliases:
681 if arg in aliases:
678 del args[pos]
679 if equals > -1:
682 if equals > -1:
683 del args[pos]
680 values.append(fullarg[equals + 1:])
684 values.append(fullarg[equals + 1:])
681 argcount -= 1
685 argcount -= 1
682 else:
686 else:
683 if pos + 1 >= argcount:
687 if pos + 1 >= argcount:
684 # ignore and let getopt report an error if there is no value
688 # ignore and let getopt report an error if there is no value
685 break
689 break
690 del args[pos]
686 values.append(args.pop(pos))
691 values.append(args.pop(pos))
687 argcount -= 2
692 argcount -= 2
688 elif arg[:2] in shortopts:
693 elif arg[:2] in shortopts:
689 # short option can have no following space, e.g. hg log -Rfoo
694 # short option can have no following space, e.g. hg log -Rfoo
690 values.append(args.pop(pos)[2:])
695 values.append(args.pop(pos)[2:])
691 argcount -= 1
696 argcount -= 1
692 else:
697 else:
693 pos += 1
698 pos += 1
694 return values
699 return values
695
700
696 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
701 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
697 # run pre-hook, and abort if it fails
702 # run pre-hook, and abort if it fails
698 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
703 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
699 pats=cmdpats, opts=cmdoptions)
704 pats=cmdpats, opts=cmdoptions)
700 try:
705 try:
701 ret = _runcommand(ui, options, cmd, d)
706 ret = _runcommand(ui, options, cmd, d)
702 # run post-hook, passing command result
707 # run post-hook, passing command result
703 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
708 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
704 result=ret, pats=cmdpats, opts=cmdoptions)
709 result=ret, pats=cmdpats, opts=cmdoptions)
705 except Exception:
710 except Exception:
706 # run failure hook and re-raise
711 # run failure hook and re-raise
707 hook.hook(lui, repo, "fail-%s" % cmd, False, args=" ".join(fullargs),
712 hook.hook(lui, repo, "fail-%s" % cmd, False, args=" ".join(fullargs),
708 pats=cmdpats, opts=cmdoptions)
713 pats=cmdpats, opts=cmdoptions)
709 raise
714 raise
710 return ret
715 return ret
711
716
712 def _getlocal(ui, rpath, wd=None):
717 def _getlocal(ui, rpath, wd=None):
713 """Return (path, local ui object) for the given target path.
718 """Return (path, local ui object) for the given target path.
714
719
715 Takes paths in [cwd]/.hg/hgrc into account."
720 Takes paths in [cwd]/.hg/hgrc into account."
716 """
721 """
717 if wd is None:
722 if wd is None:
718 try:
723 try:
719 wd = pycompat.getcwd()
724 wd = pycompat.getcwd()
720 except OSError as e:
725 except OSError as e:
721 raise error.Abort(_("error getting current working directory: %s") %
726 raise error.Abort(_("error getting current working directory: %s") %
722 encoding.strtolocal(e.strerror))
727 encoding.strtolocal(e.strerror))
723 path = cmdutil.findrepo(wd) or ""
728 path = cmdutil.findrepo(wd) or ""
724 if not path:
729 if not path:
725 lui = ui
730 lui = ui
726 else:
731 else:
727 lui = ui.copy()
732 lui = ui.copy()
728 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
733 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
729
734
730 if rpath and rpath[-1]:
735 if rpath and rpath[-1]:
731 path = lui.expandpath(rpath[-1])
736 path = lui.expandpath(rpath[-1])
732 lui = ui.copy()
737 lui = ui.copy()
733 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
738 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
734
739
735 return path, lui
740 return path, lui
736
741
737 def _checkshellalias(lui, ui, args):
742 def _checkshellalias(lui, ui, args):
738 """Return the function to run the shell alias, if it is required"""
743 """Return the function to run the shell alias, if it is required"""
739 options = {}
744 options = {}
740
745
741 try:
746 try:
742 args = fancyopts.fancyopts(args, commands.globalopts, options)
747 args = fancyopts.fancyopts(args, commands.globalopts, options)
743 except getopt.GetoptError:
748 except getopt.GetoptError:
744 return
749 return
745
750
746 if not args:
751 if not args:
747 return
752 return
748
753
749 cmdtable = commands.table
754 cmdtable = commands.table
750
755
751 cmd = args[0]
756 cmd = args[0]
752 try:
757 try:
753 strict = ui.configbool("ui", "strict")
758 strict = ui.configbool("ui", "strict")
754 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
759 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
755 except (error.AmbiguousCommand, error.UnknownCommand):
760 except (error.AmbiguousCommand, error.UnknownCommand):
756 return
761 return
757
762
758 cmd = aliases[0]
763 cmd = aliases[0]
759 fn = entry[0]
764 fn = entry[0]
760
765
761 if cmd and util.safehasattr(fn, 'shell'):
766 if cmd and util.safehasattr(fn, 'shell'):
762 d = lambda: fn(ui, *args[1:])
767 d = lambda: fn(ui, *args[1:])
763 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
768 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
764 [], {})
769 [], {})
765
770
766 def _dispatch(req):
771 def _dispatch(req):
767 args = req.args
772 args = req.args
768 ui = req.ui
773 ui = req.ui
769
774
770 # check for cwd
775 # check for cwd
771 cwd = _earlygetopt(['--cwd'], args)
776 cwd = _earlygetopt(['--cwd'], args)
772 if cwd:
777 if cwd:
773 os.chdir(cwd[-1])
778 os.chdir(cwd[-1])
774
779
775 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
780 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
776 path, lui = _getlocal(ui, rpath)
781 path, lui = _getlocal(ui, rpath)
777
782
778 uis = {ui, lui}
783 uis = {ui, lui}
779
784
780 if req.repo:
785 if req.repo:
781 uis.add(req.repo.ui)
786 uis.add(req.repo.ui)
782
787
783 if '--profile' in args:
788 if '--profile' in args:
784 for ui_ in uis:
789 for ui_ in uis:
785 ui_.setconfig('profiling', 'enabled', 'true', '--profile')
790 ui_.setconfig('profiling', 'enabled', 'true', '--profile')
786
791
787 profile = lui.configbool('profiling', 'enabled')
792 profile = lui.configbool('profiling', 'enabled')
788 with profiling.profile(lui, enabled=profile) as profiler:
793 with profiling.profile(lui, enabled=profile) as profiler:
789 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
794 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
790 # reposetup
795 # reposetup
791 extensions.loadall(lui)
796 extensions.loadall(lui)
792 # Propagate any changes to lui.__class__ by extensions
797 # Propagate any changes to lui.__class__ by extensions
793 ui.__class__ = lui.__class__
798 ui.__class__ = lui.__class__
794
799
795 # (uisetup and extsetup are handled in extensions.loadall)
800 # (uisetup and extsetup are handled in extensions.loadall)
796
801
797 # (reposetup is handled in hg.repository)
802 # (reposetup is handled in hg.repository)
798
803
799 addaliases(lui, commands.table)
804 addaliases(lui, commands.table)
800
805
801 # All aliases and commands are completely defined, now.
806 # All aliases and commands are completely defined, now.
802 # Check abbreviation/ambiguity of shell alias.
807 # Check abbreviation/ambiguity of shell alias.
803 shellaliasfn = _checkshellalias(lui, ui, args)
808 shellaliasfn = _checkshellalias(lui, ui, args)
804 if shellaliasfn:
809 if shellaliasfn:
805 return shellaliasfn()
810 return shellaliasfn()
806
811
807 # check for fallback encoding
812 # check for fallback encoding
808 fallback = lui.config('ui', 'fallbackencoding')
813 fallback = lui.config('ui', 'fallbackencoding')
809 if fallback:
814 if fallback:
810 encoding.fallbackencoding = fallback
815 encoding.fallbackencoding = fallback
811
816
812 fullargs = args
817 fullargs = args
813 cmd, func, args, options, cmdoptions = _parse(lui, args)
818 cmd, func, args, options, cmdoptions = _parse(lui, args)
814
819
815 if options["config"]:
820 if options["config"]:
816 raise error.Abort(_("option --config may not be abbreviated!"))
821 raise error.Abort(_("option --config may not be abbreviated!"))
817 if options["cwd"]:
822 if options["cwd"]:
818 raise error.Abort(_("option --cwd may not be abbreviated!"))
823 raise error.Abort(_("option --cwd may not be abbreviated!"))
819 if options["repository"]:
824 if options["repository"]:
820 raise error.Abort(_(
825 raise error.Abort(_(
821 "option -R has to be separated from other options (e.g. not "
826 "option -R has to be separated from other options (e.g. not "
822 "-qR) and --repository may only be abbreviated as --repo!"))
827 "-qR) and --repository may only be abbreviated as --repo!"))
823
828
824 if options["encoding"]:
829 if options["encoding"]:
825 encoding.encoding = options["encoding"]
830 encoding.encoding = options["encoding"]
826 if options["encodingmode"]:
831 if options["encodingmode"]:
827 encoding.encodingmode = options["encodingmode"]
832 encoding.encodingmode = options["encodingmode"]
828 if options["time"]:
833 if options["time"]:
829 def get_times():
834 def get_times():
830 t = os.times()
835 t = os.times()
831 if t[4] == 0.0:
836 if t[4] == 0.0:
832 # Windows leaves this as zero, so use time.clock()
837 # Windows leaves this as zero, so use time.clock()
833 t = (t[0], t[1], t[2], t[3], time.clock())
838 t = (t[0], t[1], t[2], t[3], time.clock())
834 return t
839 return t
835 s = get_times()
840 s = get_times()
836 def print_time():
841 def print_time():
837 t = get_times()
842 t = get_times()
838 ui.warn(
843 ui.warn(
839 _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
844 _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
840 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
845 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
841 ui.atexit(print_time)
846 ui.atexit(print_time)
842 if options["profile"]:
847 if options["profile"]:
843 profiler.start()
848 profiler.start()
844
849
845 if options['verbose'] or options['debug'] or options['quiet']:
850 if options['verbose'] or options['debug'] or options['quiet']:
846 for opt in ('verbose', 'debug', 'quiet'):
851 for opt in ('verbose', 'debug', 'quiet'):
847 val = str(bool(options[opt]))
852 val = str(bool(options[opt]))
848 if pycompat.ispy3:
853 if pycompat.ispy3:
849 val = val.encode('ascii')
854 val = val.encode('ascii')
850 for ui_ in uis:
855 for ui_ in uis:
851 ui_.setconfig('ui', opt, val, '--' + opt)
856 ui_.setconfig('ui', opt, val, '--' + opt)
852
857
853 if options['traceback']:
858 if options['traceback']:
854 for ui_ in uis:
859 for ui_ in uis:
855 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
860 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
856
861
857 if options['noninteractive']:
862 if options['noninteractive']:
858 for ui_ in uis:
863 for ui_ in uis:
859 ui_.setconfig('ui', 'interactive', 'off', '-y')
864 ui_.setconfig('ui', 'interactive', 'off', '-y')
860
865
861 if cmdoptions.get('insecure', False):
866 if cmdoptions.get('insecure', False):
862 for ui_ in uis:
867 for ui_ in uis:
863 ui_.insecureconnections = True
868 ui_.insecureconnections = True
864
869
865 # setup color handling before pager, because setting up pager
870 # setup color handling before pager, because setting up pager
866 # might cause incorrect console information
871 # might cause incorrect console information
867 coloropt = options['color']
872 coloropt = options['color']
868 for ui_ in uis:
873 for ui_ in uis:
869 if coloropt:
874 if coloropt:
870 ui_.setconfig('ui', 'color', coloropt, '--color')
875 ui_.setconfig('ui', 'color', coloropt, '--color')
871 color.setup(ui_)
876 color.setup(ui_)
872
877
873 if util.parsebool(options['pager']):
878 if util.parsebool(options['pager']):
874 # ui.pager() expects 'internal-always-' prefix in this case
879 # ui.pager() expects 'internal-always-' prefix in this case
875 ui.pager('internal-always-' + cmd)
880 ui.pager('internal-always-' + cmd)
876 elif options['pager'] != 'auto':
881 elif options['pager'] != 'auto':
877 for ui_ in uis:
882 for ui_ in uis:
878 ui_.disablepager()
883 ui_.disablepager()
879
884
880 if options['version']:
885 if options['version']:
881 return commands.version_(ui)
886 return commands.version_(ui)
882 if options['help']:
887 if options['help']:
883 return commands.help_(ui, cmd, command=cmd is not None)
888 return commands.help_(ui, cmd, command=cmd is not None)
884 elif not cmd:
889 elif not cmd:
885 return commands.help_(ui, 'shortlist')
890 return commands.help_(ui, 'shortlist')
886
891
887 repo = None
892 repo = None
888 cmdpats = args[:]
893 cmdpats = args[:]
889 if not func.norepo:
894 if not func.norepo:
890 # use the repo from the request only if we don't have -R
895 # use the repo from the request only if we don't have -R
891 if not rpath and not cwd:
896 if not rpath and not cwd:
892 repo = req.repo
897 repo = req.repo
893
898
894 if repo:
899 if repo:
895 # set the descriptors of the repo ui to those of ui
900 # set the descriptors of the repo ui to those of ui
896 repo.ui.fin = ui.fin
901 repo.ui.fin = ui.fin
897 repo.ui.fout = ui.fout
902 repo.ui.fout = ui.fout
898 repo.ui.ferr = ui.ferr
903 repo.ui.ferr = ui.ferr
899 else:
904 else:
900 try:
905 try:
901 repo = hg.repository(ui, path=path,
906 repo = hg.repository(ui, path=path,
902 presetupfuncs=req.prereposetups)
907 presetupfuncs=req.prereposetups)
903 if not repo.local():
908 if not repo.local():
904 raise error.Abort(_("repository '%s' is not local")
909 raise error.Abort(_("repository '%s' is not local")
905 % path)
910 % path)
906 repo.ui.setconfig("bundle", "mainreporoot", repo.root,
911 repo.ui.setconfig("bundle", "mainreporoot", repo.root,
907 'repo')
912 'repo')
908 except error.RequirementError:
913 except error.RequirementError:
909 raise
914 raise
910 except error.RepoError:
915 except error.RepoError:
911 if rpath and rpath[-1]: # invalid -R path
916 if rpath and rpath[-1]: # invalid -R path
912 raise
917 raise
913 if not func.optionalrepo:
918 if not func.optionalrepo:
914 if func.inferrepo and args and not path:
919 if func.inferrepo and args and not path:
915 # try to infer -R from command args
920 # try to infer -R from command args
916 repos = map(cmdutil.findrepo, args)
921 repos = map(cmdutil.findrepo, args)
917 guess = repos[0]
922 guess = repos[0]
918 if guess and repos.count(guess) == len(repos):
923 if guess and repos.count(guess) == len(repos):
919 req.args = ['--repository', guess] + fullargs
924 req.args = ['--repository', guess] + fullargs
920 return _dispatch(req)
925 return _dispatch(req)
921 if not path:
926 if not path:
922 raise error.RepoError(_("no repository found in"
927 raise error.RepoError(_("no repository found in"
923 " '%s' (.hg not found)")
928 " '%s' (.hg not found)")
924 % pycompat.getcwd())
929 % pycompat.getcwd())
925 raise
930 raise
926 if repo:
931 if repo:
927 ui = repo.ui
932 ui = repo.ui
928 if options['hidden']:
933 if options['hidden']:
929 repo = repo.unfiltered()
934 repo = repo.unfiltered()
930 args.insert(0, repo)
935 args.insert(0, repo)
931 elif rpath:
936 elif rpath:
932 ui.warn(_("warning: --repository ignored\n"))
937 ui.warn(_("warning: --repository ignored\n"))
933
938
934 msg = _formatargs(fullargs)
939 msg = _formatargs(fullargs)
935 ui.log("command", '%s\n', msg)
940 ui.log("command", '%s\n', msg)
936 strcmdopt = pycompat.strkwargs(cmdoptions)
941 strcmdopt = pycompat.strkwargs(cmdoptions)
937 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
942 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
938 try:
943 try:
939 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
944 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
940 cmdpats, cmdoptions)
945 cmdpats, cmdoptions)
941 finally:
946 finally:
942 if repo and repo != req.repo:
947 if repo and repo != req.repo:
943 repo.close()
948 repo.close()
944
949
945 def _runcommand(ui, options, cmd, cmdfunc):
950 def _runcommand(ui, options, cmd, cmdfunc):
946 """Run a command function, possibly with profiling enabled."""
951 """Run a command function, possibly with profiling enabled."""
947 try:
952 try:
948 return cmdfunc()
953 return cmdfunc()
949 except error.SignatureError:
954 except error.SignatureError:
950 raise error.CommandError(cmd, _('invalid arguments'))
955 raise error.CommandError(cmd, _('invalid arguments'))
951
956
952 def _exceptionwarning(ui):
957 def _exceptionwarning(ui):
953 """Produce a warning message for the current active exception"""
958 """Produce a warning message for the current active exception"""
954
959
955 # For compatibility checking, we discard the portion of the hg
960 # For compatibility checking, we discard the portion of the hg
956 # version after the + on the assumption that if a "normal
961 # version after the + on the assumption that if a "normal
957 # user" is running a build with a + in it the packager
962 # user" is running a build with a + in it the packager
958 # probably built from fairly close to a tag and anyone with a
963 # probably built from fairly close to a tag and anyone with a
959 # 'make local' copy of hg (where the version number can be out
964 # 'make local' copy of hg (where the version number can be out
960 # of date) will be clueful enough to notice the implausible
965 # of date) will be clueful enough to notice the implausible
961 # version number and try updating.
966 # version number and try updating.
962 ct = util.versiontuple(n=2)
967 ct = util.versiontuple(n=2)
963 worst = None, ct, ''
968 worst = None, ct, ''
964 if ui.config('ui', 'supportcontact') is None:
969 if ui.config('ui', 'supportcontact') is None:
965 for name, mod in extensions.extensions():
970 for name, mod in extensions.extensions():
966 testedwith = getattr(mod, 'testedwith', '')
971 testedwith = getattr(mod, 'testedwith', '')
967 if pycompat.ispy3 and isinstance(testedwith, str):
972 if pycompat.ispy3 and isinstance(testedwith, str):
968 testedwith = testedwith.encode(u'utf-8')
973 testedwith = testedwith.encode(u'utf-8')
969 report = getattr(mod, 'buglink', _('the extension author.'))
974 report = getattr(mod, 'buglink', _('the extension author.'))
970 if not testedwith.strip():
975 if not testedwith.strip():
971 # We found an untested extension. It's likely the culprit.
976 # We found an untested extension. It's likely the culprit.
972 worst = name, 'unknown', report
977 worst = name, 'unknown', report
973 break
978 break
974
979
975 # Never blame on extensions bundled with Mercurial.
980 # Never blame on extensions bundled with Mercurial.
976 if extensions.ismoduleinternal(mod):
981 if extensions.ismoduleinternal(mod):
977 continue
982 continue
978
983
979 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
984 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
980 if ct in tested:
985 if ct in tested:
981 continue
986 continue
982
987
983 lower = [t for t in tested if t < ct]
988 lower = [t for t in tested if t < ct]
984 nearest = max(lower or tested)
989 nearest = max(lower or tested)
985 if worst[0] is None or nearest < worst[1]:
990 if worst[0] is None or nearest < worst[1]:
986 worst = name, nearest, report
991 worst = name, nearest, report
987 if worst[0] is not None:
992 if worst[0] is not None:
988 name, testedwith, report = worst
993 name, testedwith, report = worst
989 if not isinstance(testedwith, (bytes, str)):
994 if not isinstance(testedwith, (bytes, str)):
990 testedwith = '.'.join([str(c) for c in testedwith])
995 testedwith = '.'.join([str(c) for c in testedwith])
991 warning = (_('** Unknown exception encountered with '
996 warning = (_('** Unknown exception encountered with '
992 'possibly-broken third-party extension %s\n'
997 'possibly-broken third-party extension %s\n'
993 '** which supports versions %s of Mercurial.\n'
998 '** which supports versions %s of Mercurial.\n'
994 '** Please disable %s and try your action again.\n'
999 '** Please disable %s and try your action again.\n'
995 '** If that fixes the bug please report it to %s\n')
1000 '** If that fixes the bug please report it to %s\n')
996 % (name, testedwith, name, report))
1001 % (name, testedwith, name, report))
997 else:
1002 else:
998 bugtracker = ui.config('ui', 'supportcontact')
1003 bugtracker = ui.config('ui', 'supportcontact')
999 if bugtracker is None:
1004 if bugtracker is None:
1000 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
1005 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
1001 warning = (_("** unknown exception encountered, "
1006 warning = (_("** unknown exception encountered, "
1002 "please report by visiting\n** ") + bugtracker + '\n')
1007 "please report by visiting\n** ") + bugtracker + '\n')
1003 if pycompat.ispy3:
1008 if pycompat.ispy3:
1004 sysversion = sys.version.encode(u'utf-8')
1009 sysversion = sys.version.encode(u'utf-8')
1005 else:
1010 else:
1006 sysversion = sys.version
1011 sysversion = sys.version
1007 sysversion = sysversion.replace('\n', '')
1012 sysversion = sysversion.replace('\n', '')
1008 warning += ((_("** Python %s\n") % sysversion) +
1013 warning += ((_("** Python %s\n") % sysversion) +
1009 (_("** Mercurial Distributed SCM (version %s)\n") %
1014 (_("** Mercurial Distributed SCM (version %s)\n") %
1010 util.version()) +
1015 util.version()) +
1011 (_("** Extensions loaded: %s\n") %
1016 (_("** Extensions loaded: %s\n") %
1012 ", ".join([x[0] for x in extensions.extensions()])))
1017 ", ".join([x[0] for x in extensions.extensions()])))
1013 return warning
1018 return warning
1014
1019
1015 def handlecommandexception(ui):
1020 def handlecommandexception(ui):
1016 """Produce a warning message for broken commands
1021 """Produce a warning message for broken commands
1017
1022
1018 Called when handling an exception; the exception is reraised if
1023 Called when handling an exception; the exception is reraised if
1019 this function returns False, ignored otherwise.
1024 this function returns False, ignored otherwise.
1020 """
1025 """
1021 warning = _exceptionwarning(ui)
1026 warning = _exceptionwarning(ui)
1022 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
1027 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
1023 ui.warn(warning)
1028 ui.warn(warning)
1024 return False # re-raise the exception
1029 return False # re-raise the exception
@@ -1,909 +1,909 b''
1 #require serve
1 #require serve
2
2
3 $ cat << EOF >> $HGRCPATH
3 $ cat << EOF >> $HGRCPATH
4 > [ui]
4 > [ui]
5 > logtemplate={rev}:{node|short} {desc|firstline}
5 > logtemplate={rev}:{node|short} {desc|firstline}
6 > [phases]
6 > [phases]
7 > publish=False
7 > publish=False
8 > [experimental]
8 > [experimental]
9 > evolution.createmarkers=True
9 > evolution.createmarkers=True
10 > evolution.exchange=True
10 > evolution.exchange=True
11 > EOF
11 > EOF
12
12
13 $ cat > $TESTTMP/hook.sh <<'EOF'
13 $ cat > $TESTTMP/hook.sh <<'EOF'
14 > echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"
14 > echo "test-hook-bookmark: $HG_BOOKMARK: $HG_OLDNODE -> $HG_NODE"
15 > EOF
15 > EOF
16 $ TESTHOOK="hooks.txnclose-bookmark.test=sh $TESTTMP/hook.sh"
16 $ TESTHOOK="hooks.txnclose-bookmark.test=sh $TESTTMP/hook.sh"
17
17
18 initialize
18 initialize
19
19
20 $ hg init a
20 $ hg init a
21 $ cd a
21 $ cd a
22 $ echo 'test' > test
22 $ echo 'test' > test
23 $ hg commit -Am'test'
23 $ hg commit -Am'test'
24 adding test
24 adding test
25
25
26 set bookmarks
26 set bookmarks
27
27
28 $ hg bookmark X
28 $ hg bookmark X
29 $ hg bookmark Y
29 $ hg bookmark Y
30 $ hg bookmark Z
30 $ hg bookmark Z
31
31
32 import bookmark by name
32 import bookmark by name
33
33
34 $ hg init ../b
34 $ hg init ../b
35 $ cd ../b
35 $ cd ../b
36 $ hg book Y
36 $ hg book Y
37 $ hg book
37 $ hg book
38 * Y -1:000000000000
38 * Y -1:000000000000
39 $ hg pull ../a --config "$TESTHOOK"
39 $ hg pull ../a --config "$TESTHOOK"
40 pulling from ../a
40 pulling from ../a
41 requesting all changes
41 requesting all changes
42 adding changesets
42 adding changesets
43 adding manifests
43 adding manifests
44 adding file changes
44 adding file changes
45 added 1 changesets with 1 changes to 1 files
45 added 1 changesets with 1 changes to 1 files
46 adding remote bookmark X
46 adding remote bookmark X
47 updating bookmark Y
47 updating bookmark Y
48 adding remote bookmark Z
48 adding remote bookmark Z
49 new changesets 4e3505fd9583
49 new changesets 4e3505fd9583
50 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
50 test-hook-bookmark: X: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
51 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
51 test-hook-bookmark: Y: 0000000000000000000000000000000000000000 -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
52 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
52 test-hook-bookmark: Z: -> 4e3505fd95835d721066b76e75dbb8cc554d7f77
53 (run 'hg update' to get a working copy)
53 (run 'hg update' to get a working copy)
54 $ hg bookmarks
54 $ hg bookmarks
55 X 0:4e3505fd9583
55 X 0:4e3505fd9583
56 * Y 0:4e3505fd9583
56 * Y 0:4e3505fd9583
57 Z 0:4e3505fd9583
57 Z 0:4e3505fd9583
58 $ hg debugpushkey ../a namespaces
58 $ hg debugpushkey ../a namespaces
59 bookmarks
59 bookmarks
60 namespaces
60 namespaces
61 obsolete
61 obsolete
62 phases
62 phases
63 $ hg debugpushkey ../a bookmarks
63 $ hg debugpushkey ../a bookmarks
64 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
64 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
65 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
65 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
66 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
66 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
67
67
68 delete the bookmark to re-pull it
68 delete the bookmark to re-pull it
69
69
70 $ hg book -d X
70 $ hg book -d X
71 $ hg pull -B X ../a
71 $ hg pull -B X ../a
72 pulling from ../a
72 pulling from ../a
73 no changes found
73 no changes found
74 adding remote bookmark X
74 adding remote bookmark X
75
75
76 finally no-op pull
76 finally no-op pull
77
77
78 $ hg pull -B X ../a
78 $ hg pull -B X ../a
79 pulling from ../a
79 pulling from ../a
80 no changes found
80 no changes found
81 $ hg bookmark
81 $ hg bookmark
82 X 0:4e3505fd9583
82 X 0:4e3505fd9583
83 * Y 0:4e3505fd9583
83 * Y 0:4e3505fd9583
84 Z 0:4e3505fd9583
84 Z 0:4e3505fd9583
85
85
86 export bookmark by name
86 export bookmark by name
87
87
88 $ hg bookmark W
88 $ hg bookmark W
89 $ hg bookmark foo
89 $ hg bookmark foo
90 $ hg bookmark foobar
90 $ hg bookmark foobar
91 $ hg push -B W ../a
91 $ hg push -B W ../a
92 pushing to ../a
92 pushing to ../a
93 searching for changes
93 searching for changes
94 no changes found
94 no changes found
95 exporting bookmark W
95 exporting bookmark W
96 [1]
96 [1]
97 $ hg -R ../a bookmarks
97 $ hg -R ../a bookmarks
98 W -1:000000000000
98 W -1:000000000000
99 X 0:4e3505fd9583
99 X 0:4e3505fd9583
100 Y 0:4e3505fd9583
100 Y 0:4e3505fd9583
101 * Z 0:4e3505fd9583
101 * Z 0:4e3505fd9583
102
102
103 delete a remote bookmark
103 delete a remote bookmark
104
104
105 $ hg book -d W
105 $ hg book -d W
106 $ hg push -B W ../a --config "$TESTHOOK"
106 $ hg push -B W ../a --config "$TESTHOOK"
107 pushing to ../a
107 pushing to ../a
108 searching for changes
108 searching for changes
109 no changes found
109 no changes found
110 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
110 test-hook-bookmark: W: 0000000000000000000000000000000000000000 ->
111 deleting remote bookmark W
111 deleting remote bookmark W
112 [1]
112 [1]
113
113
114 export the active bookmark
114 export the active bookmark
115
115
116 $ hg bookmark V
116 $ hg bookmark V
117 $ hg push -B . ../a
117 $ hg push -B . ../a
118 pushing to ../a
118 pushing to ../a
119 searching for changes
119 searching for changes
120 no changes found
120 no changes found
121 exporting bookmark V
121 exporting bookmark V
122 [1]
122 [1]
123
123
124 exporting the active bookmark with 'push -B .'
124 exporting the active bookmark with 'push -B .'
125 demand that one of the bookmarks is activated
125 demand that one of the bookmarks is activated
126
126
127 $ hg update -r default
127 $ hg update -r default
128 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
128 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
129 (leaving bookmark V)
129 (leaving bookmark V)
130 $ hg push -B . ../a
130 $ hg push -B . ../a
131 abort: no active bookmark
131 abort: no active bookmark
132 [255]
132 [255]
133 $ hg update -r V
133 $ hg update -r V
134 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
134 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
135 (activating bookmark V)
135 (activating bookmark V)
136
136
137 delete the bookmark
137 delete the bookmark
138
138
139 $ hg book -d V
139 $ hg book -d V
140 $ hg push -B V ../a
140 $ hg push -B V ../a
141 pushing to ../a
141 pushing to ../a
142 searching for changes
142 searching for changes
143 no changes found
143 no changes found
144 deleting remote bookmark V
144 deleting remote bookmark V
145 [1]
145 [1]
146 $ hg up foobar
146 $ hg up foobar
147 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
147 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
148 (activating bookmark foobar)
148 (activating bookmark foobar)
149
149
150 push/pull name that doesn't exist
150 push/pull name that doesn't exist
151
151
152 $ hg push -B badname ../a
152 $ hg push -B badname ../a
153 pushing to ../a
153 pushing to ../a
154 searching for changes
154 searching for changes
155 bookmark badname does not exist on the local or remote repository!
155 bookmark badname does not exist on the local or remote repository!
156 no changes found
156 no changes found
157 [2]
157 [2]
158 $ hg pull -B anotherbadname ../a
158 $ hg pull -B anotherbadname ../a
159 pulling from ../a
159 pulling from ../a
160 abort: remote bookmark anotherbadname not found!
160 abort: remote bookmark anotherbadname not found!
161 [255]
161 [255]
162
162
163 divergent bookmarks
163 divergent bookmarks
164
164
165 $ cd ../a
165 $ cd ../a
166 $ echo c1 > f1
166 $ echo c1 > f1
167 $ hg ci -Am1
167 $ hg ci -Am1
168 adding f1
168 adding f1
169 $ hg book -f @
169 $ hg book -f @
170 $ hg book -f X
170 $ hg book -f X
171 $ hg book
171 $ hg book
172 @ 1:0d2164f0ce0d
172 @ 1:0d2164f0ce0d
173 * X 1:0d2164f0ce0d
173 * X 1:0d2164f0ce0d
174 Y 0:4e3505fd9583
174 Y 0:4e3505fd9583
175 Z 1:0d2164f0ce0d
175 Z 1:0d2164f0ce0d
176
176
177 $ cd ../b
177 $ cd ../b
178 $ hg up --config
178 $ hg up
179 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
180 updating bookmark foobar
180 updating bookmark foobar
181 $ echo c2 > f2
181 $ echo c2 > f2
182 $ hg ci -Am2
182 $ hg ci -Am2
183 adding f2
183 adding f2
184 $ hg book -if @
184 $ hg book -if @
185 $ hg book -if X
185 $ hg book -if X
186 $ hg book
186 $ hg book
187 @ 1:9b140be10808
187 @ 1:9b140be10808
188 X 1:9b140be10808
188 X 1:9b140be10808
189 Y 0:4e3505fd9583
189 Y 0:4e3505fd9583
190 Z 0:4e3505fd9583
190 Z 0:4e3505fd9583
191 foo -1:000000000000
191 foo -1:000000000000
192 * foobar 1:9b140be10808
192 * foobar 1:9b140be10808
193
193
194 $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
194 $ hg pull --config paths.foo=../a foo --config "$TESTHOOK"
195 pulling from $TESTTMP/a (glob)
195 pulling from $TESTTMP/a (glob)
196 searching for changes
196 searching for changes
197 adding changesets
197 adding changesets
198 adding manifests
198 adding manifests
199 adding file changes
199 adding file changes
200 added 1 changesets with 1 changes to 1 files (+1 heads)
200 added 1 changesets with 1 changes to 1 files (+1 heads)
201 divergent bookmark @ stored as @foo
201 divergent bookmark @ stored as @foo
202 divergent bookmark X stored as X@foo
202 divergent bookmark X stored as X@foo
203 updating bookmark Z
203 updating bookmark Z
204 new changesets 0d2164f0ce0d
204 new changesets 0d2164f0ce0d
205 test-hook-bookmark: @foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
205 test-hook-bookmark: @foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
206 test-hook-bookmark: X@foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
206 test-hook-bookmark: X@foo: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
207 test-hook-bookmark: Z: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
207 test-hook-bookmark: Z: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
208 (run 'hg heads' to see heads, 'hg merge' to merge)
208 (run 'hg heads' to see heads, 'hg merge' to merge)
209 $ hg book
209 $ hg book
210 @ 1:9b140be10808
210 @ 1:9b140be10808
211 @foo 2:0d2164f0ce0d
211 @foo 2:0d2164f0ce0d
212 X 1:9b140be10808
212 X 1:9b140be10808
213 X@foo 2:0d2164f0ce0d
213 X@foo 2:0d2164f0ce0d
214 Y 0:4e3505fd9583
214 Y 0:4e3505fd9583
215 Z 2:0d2164f0ce0d
215 Z 2:0d2164f0ce0d
216 foo -1:000000000000
216 foo -1:000000000000
217 * foobar 1:9b140be10808
217 * foobar 1:9b140be10808
218
218
219 (test that too many divergence of bookmark)
219 (test that too many divergence of bookmark)
220
220
221 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
221 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -r 000000000000 "X@${i}"; done
222 $ hg pull ../a
222 $ hg pull ../a
223 pulling from ../a
223 pulling from ../a
224 searching for changes
224 searching for changes
225 no changes found
225 no changes found
226 warning: failed to assign numbered name to divergent bookmark X
226 warning: failed to assign numbered name to divergent bookmark X
227 divergent bookmark @ stored as @1
227 divergent bookmark @ stored as @1
228 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
228 $ hg bookmarks | grep '^ X' | grep -v ':000000000000'
229 X 1:9b140be10808
229 X 1:9b140be10808
230 X@foo 2:0d2164f0ce0d
230 X@foo 2:0d2164f0ce0d
231
231
232 (test that remotely diverged bookmarks are reused if they aren't changed)
232 (test that remotely diverged bookmarks are reused if they aren't changed)
233
233
234 $ hg bookmarks | grep '^ @'
234 $ hg bookmarks | grep '^ @'
235 @ 1:9b140be10808
235 @ 1:9b140be10808
236 @1 2:0d2164f0ce0d
236 @1 2:0d2164f0ce0d
237 @foo 2:0d2164f0ce0d
237 @foo 2:0d2164f0ce0d
238 $ hg pull ../a
238 $ hg pull ../a
239 pulling from ../a
239 pulling from ../a
240 searching for changes
240 searching for changes
241 no changes found
241 no changes found
242 warning: failed to assign numbered name to divergent bookmark X
242 warning: failed to assign numbered name to divergent bookmark X
243 divergent bookmark @ stored as @1
243 divergent bookmark @ stored as @1
244 $ hg bookmarks | grep '^ @'
244 $ hg bookmarks | grep '^ @'
245 @ 1:9b140be10808
245 @ 1:9b140be10808
246 @1 2:0d2164f0ce0d
246 @1 2:0d2164f0ce0d
247 @foo 2:0d2164f0ce0d
247 @foo 2:0d2164f0ce0d
248
248
249 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
249 $ $PYTHON $TESTDIR/seq.py 1 100 | while read i; do hg bookmarks -d "X@${i}"; done
250 $ hg bookmarks -d "@1"
250 $ hg bookmarks -d "@1"
251
251
252 $ hg push -f ../a
252 $ hg push -f ../a
253 pushing to ../a
253 pushing to ../a
254 searching for changes
254 searching for changes
255 adding changesets
255 adding changesets
256 adding manifests
256 adding manifests
257 adding file changes
257 adding file changes
258 added 1 changesets with 1 changes to 1 files (+1 heads)
258 added 1 changesets with 1 changes to 1 files (+1 heads)
259 $ hg -R ../a book
259 $ hg -R ../a book
260 @ 1:0d2164f0ce0d
260 @ 1:0d2164f0ce0d
261 * X 1:0d2164f0ce0d
261 * X 1:0d2164f0ce0d
262 Y 0:4e3505fd9583
262 Y 0:4e3505fd9583
263 Z 1:0d2164f0ce0d
263 Z 1:0d2164f0ce0d
264
264
265 explicit pull should overwrite the local version (issue4439)
265 explicit pull should overwrite the local version (issue4439)
266
266
267 $ hg update -r X
267 $ hg update -r X
268 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
268 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
269 (activating bookmark X)
269 (activating bookmark X)
270 $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
270 $ hg pull --config paths.foo=../a foo -B . --config "$TESTHOOK"
271 pulling from $TESTTMP/a (glob)
271 pulling from $TESTTMP/a (glob)
272 no changes found
272 no changes found
273 divergent bookmark @ stored as @foo
273 divergent bookmark @ stored as @foo
274 importing bookmark X
274 importing bookmark X
275 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
275 test-hook-bookmark: @foo: 0d2164f0ce0d8f1d6f94351eba04b794909be66c -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
276 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
276 test-hook-bookmark: X: 9b140be1080824d768c5a4691a564088eede71f9 -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
277
277
278 reinstall state for further testing:
278 reinstall state for further testing:
279
279
280 $ hg book -fr 9b140be10808 X
280 $ hg book -fr 9b140be10808 X
281
281
282 revsets should not ignore divergent bookmarks
282 revsets should not ignore divergent bookmarks
283
283
284 $ hg bookmark -fr 1 Z
284 $ hg bookmark -fr 1 Z
285 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
285 $ hg log -r 'bookmark()' --template '{rev}:{node|short} {bookmarks}\n'
286 0:4e3505fd9583 Y
286 0:4e3505fd9583 Y
287 1:9b140be10808 @ X Z foobar
287 1:9b140be10808 @ X Z foobar
288 2:0d2164f0ce0d @foo X@foo
288 2:0d2164f0ce0d @foo X@foo
289 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
289 $ hg log -r 'bookmark("X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
290 2:0d2164f0ce0d @foo X@foo
290 2:0d2164f0ce0d @foo X@foo
291 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
291 $ hg log -r 'bookmark("re:X@foo")' --template '{rev}:{node|short} {bookmarks}\n'
292 2:0d2164f0ce0d @foo X@foo
292 2:0d2164f0ce0d @foo X@foo
293
293
294 update a remote bookmark from a non-head to a head
294 update a remote bookmark from a non-head to a head
295
295
296 $ hg up -q Y
296 $ hg up -q Y
297 $ echo c3 > f2
297 $ echo c3 > f2
298 $ hg ci -Am3
298 $ hg ci -Am3
299 adding f2
299 adding f2
300 created new head
300 created new head
301 $ hg push ../a --config "$TESTHOOK"
301 $ hg push ../a --config "$TESTHOOK"
302 pushing to ../a
302 pushing to ../a
303 searching for changes
303 searching for changes
304 adding changesets
304 adding changesets
305 adding manifests
305 adding manifests
306 adding file changes
306 adding file changes
307 added 1 changesets with 1 changes to 1 files (+1 heads)
307 added 1 changesets with 1 changes to 1 files (+1 heads)
308 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
308 test-hook-bookmark: Y: 4e3505fd95835d721066b76e75dbb8cc554d7f77 -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
309 updating bookmark Y
309 updating bookmark Y
310 $ hg -R ../a book
310 $ hg -R ../a book
311 @ 1:0d2164f0ce0d
311 @ 1:0d2164f0ce0d
312 * X 1:0d2164f0ce0d
312 * X 1:0d2164f0ce0d
313 Y 3:f6fc62dde3c0
313 Y 3:f6fc62dde3c0
314 Z 1:0d2164f0ce0d
314 Z 1:0d2164f0ce0d
315
315
316 update a bookmark in the middle of a client pulling changes
316 update a bookmark in the middle of a client pulling changes
317
317
318 $ cd ..
318 $ cd ..
319 $ hg clone -q a pull-race
319 $ hg clone -q a pull-race
320
320
321 We want to use http because it is stateless and therefore more susceptible to
321 We want to use http because it is stateless and therefore more susceptible to
322 race conditions
322 race conditions
323
323
324 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
324 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
325 $ cat pull-race.pid >> $DAEMON_PIDS
325 $ cat pull-race.pid >> $DAEMON_PIDS
326
326
327 $ cat <<EOF > $TESTTMP/out_makecommit.sh
327 $ cat <<EOF > $TESTTMP/out_makecommit.sh
328 > #!/bin/sh
328 > #!/bin/sh
329 > hg ci -Am5
329 > hg ci -Am5
330 > echo committed in pull-race
330 > echo committed in pull-race
331 > EOF
331 > EOF
332
332
333 $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
333 $ hg clone -q http://localhost:$HGPORT/ pull-race2 --config "$TESTHOOK"
334 test-hook-bookmark: @: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
334 test-hook-bookmark: @: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
335 test-hook-bookmark: X: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
335 test-hook-bookmark: X: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
336 test-hook-bookmark: Y: -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
336 test-hook-bookmark: Y: -> f6fc62dde3c0771e29704af56ba4d8af77abcc2f
337 test-hook-bookmark: Z: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
337 test-hook-bookmark: Z: -> 0d2164f0ce0d8f1d6f94351eba04b794909be66c
338 $ cd pull-race
338 $ cd pull-race
339 $ hg up -q Y
339 $ hg up -q Y
340 $ echo c4 > f2
340 $ echo c4 > f2
341 $ hg ci -Am4
341 $ hg ci -Am4
342 $ echo c5 > f3
342 $ echo c5 > f3
343 $ cat <<EOF > .hg/hgrc
343 $ cat <<EOF > .hg/hgrc
344 > [hooks]
344 > [hooks]
345 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
345 > outgoing.makecommit = sh $TESTTMP/out_makecommit.sh
346 > EOF
346 > EOF
347
347
348 (new config needs a server restart)
348 (new config needs a server restart)
349
349
350 $ cd ..
350 $ cd ..
351 $ killdaemons.py
351 $ killdaemons.py
352 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
352 $ hg serve -R pull-race -p $HGPORT -d --pid-file=pull-race.pid -E main-error.log
353 $ cat pull-race.pid >> $DAEMON_PIDS
353 $ cat pull-race.pid >> $DAEMON_PIDS
354 $ cd pull-race2
354 $ cd pull-race2
355 $ hg -R $TESTTMP/pull-race book
355 $ hg -R $TESTTMP/pull-race book
356 @ 1:0d2164f0ce0d
356 @ 1:0d2164f0ce0d
357 X 1:0d2164f0ce0d
357 X 1:0d2164f0ce0d
358 * Y 4:b0a5eff05604
358 * Y 4:b0a5eff05604
359 Z 1:0d2164f0ce0d
359 Z 1:0d2164f0ce0d
360 $ hg pull
360 $ hg pull
361 pulling from http://localhost:$HGPORT/
361 pulling from http://localhost:$HGPORT/
362 searching for changes
362 searching for changes
363 adding changesets
363 adding changesets
364 adding manifests
364 adding manifests
365 adding file changes
365 adding file changes
366 added 1 changesets with 1 changes to 1 files
366 added 1 changesets with 1 changes to 1 files
367 updating bookmark Y
367 updating bookmark Y
368 new changesets b0a5eff05604
368 new changesets b0a5eff05604
369 (run 'hg update' to get a working copy)
369 (run 'hg update' to get a working copy)
370 $ hg book
370 $ hg book
371 * @ 1:0d2164f0ce0d
371 * @ 1:0d2164f0ce0d
372 X 1:0d2164f0ce0d
372 X 1:0d2164f0ce0d
373 Y 4:b0a5eff05604
373 Y 4:b0a5eff05604
374 Z 1:0d2164f0ce0d
374 Z 1:0d2164f0ce0d
375
375
376 Update a bookmark right after the initial lookup -B (issue4689)
376 Update a bookmark right after the initial lookup -B (issue4689)
377
377
378 $ echo c6 > ../pull-race/f3 # to be committed during the race
378 $ echo c6 > ../pull-race/f3 # to be committed during the race
379 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
379 $ cat <<EOF > $TESTTMP/listkeys_makecommit.sh
380 > #!/bin/sh
380 > #!/bin/sh
381 > if hg st | grep -q M; then
381 > if hg st | grep -q M; then
382 > hg commit -m race
382 > hg commit -m race
383 > echo committed in pull-race
383 > echo committed in pull-race
384 > else
384 > else
385 > exit 0
385 > exit 0
386 > fi
386 > fi
387 > EOF
387 > EOF
388 $ cat <<EOF > ../pull-race/.hg/hgrc
388 $ cat <<EOF > ../pull-race/.hg/hgrc
389 > [hooks]
389 > [hooks]
390 > # If anything to commit, commit it right after the first key listing used
390 > # If anything to commit, commit it right after the first key listing used
391 > # during lookup. This makes the commit appear before the actual getbundle
391 > # during lookup. This makes the commit appear before the actual getbundle
392 > # call.
392 > # call.
393 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
393 > listkeys.makecommit= sh $TESTTMP/listkeys_makecommit.sh
394 > EOF
394 > EOF
395
395
396 (new config need server restart)
396 (new config need server restart)
397
397
398 $ killdaemons.py
398 $ killdaemons.py
399 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
399 $ hg serve -R ../pull-race -p $HGPORT -d --pid-file=../pull-race.pid -E main-error.log
400 $ cat ../pull-race.pid >> $DAEMON_PIDS
400 $ cat ../pull-race.pid >> $DAEMON_PIDS
401
401
402 $ hg -R $TESTTMP/pull-race book
402 $ hg -R $TESTTMP/pull-race book
403 @ 1:0d2164f0ce0d
403 @ 1:0d2164f0ce0d
404 X 1:0d2164f0ce0d
404 X 1:0d2164f0ce0d
405 * Y 5:35d1ef0a8d1b
405 * Y 5:35d1ef0a8d1b
406 Z 1:0d2164f0ce0d
406 Z 1:0d2164f0ce0d
407 $ hg update -r Y
407 $ hg update -r Y
408 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
408 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
409 (activating bookmark Y)
409 (activating bookmark Y)
410 $ hg pull -B .
410 $ hg pull -B .
411 pulling from http://localhost:$HGPORT/
411 pulling from http://localhost:$HGPORT/
412 searching for changes
412 searching for changes
413 adding changesets
413 adding changesets
414 adding manifests
414 adding manifests
415 adding file changes
415 adding file changes
416 added 1 changesets with 1 changes to 1 files
416 added 1 changesets with 1 changes to 1 files
417 updating bookmark Y
417 updating bookmark Y
418 new changesets 35d1ef0a8d1b
418 new changesets 35d1ef0a8d1b
419 (run 'hg update' to get a working copy)
419 (run 'hg update' to get a working copy)
420 $ hg book
420 $ hg book
421 @ 1:0d2164f0ce0d
421 @ 1:0d2164f0ce0d
422 X 1:0d2164f0ce0d
422 X 1:0d2164f0ce0d
423 * Y 5:35d1ef0a8d1b
423 * Y 5:35d1ef0a8d1b
424 Z 1:0d2164f0ce0d
424 Z 1:0d2164f0ce0d
425
425
426 (done with this section of the test)
426 (done with this section of the test)
427
427
428 $ killdaemons.py
428 $ killdaemons.py
429 $ cd ../b
429 $ cd ../b
430
430
431 diverging a remote bookmark fails
431 diverging a remote bookmark fails
432
432
433 $ hg up -q 4e3505fd9583
433 $ hg up -q 4e3505fd9583
434 $ echo c4 > f2
434 $ echo c4 > f2
435 $ hg ci -Am4
435 $ hg ci -Am4
436 adding f2
436 adding f2
437 created new head
437 created new head
438 $ echo c5 > f2
438 $ echo c5 > f2
439 $ hg ci -Am5
439 $ hg ci -Am5
440 $ hg log -G
440 $ hg log -G
441 @ 5:c922c0139ca0 5
441 @ 5:c922c0139ca0 5
442 |
442 |
443 o 4:4efff6d98829 4
443 o 4:4efff6d98829 4
444 |
444 |
445 | o 3:f6fc62dde3c0 3
445 | o 3:f6fc62dde3c0 3
446 |/
446 |/
447 | o 2:0d2164f0ce0d 1
447 | o 2:0d2164f0ce0d 1
448 |/
448 |/
449 | o 1:9b140be10808 2
449 | o 1:9b140be10808 2
450 |/
450 |/
451 o 0:4e3505fd9583 test
451 o 0:4e3505fd9583 test
452
452
453
453
454 $ hg book -f Y
454 $ hg book -f Y
455
455
456 $ cat <<EOF > ../a/.hg/hgrc
456 $ cat <<EOF > ../a/.hg/hgrc
457 > [web]
457 > [web]
458 > push_ssl = false
458 > push_ssl = false
459 > allow_push = *
459 > allow_push = *
460 > EOF
460 > EOF
461
461
462 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
462 $ hg serve -R ../a -p $HGPORT2 -d --pid-file=../hg2.pid
463 $ cat ../hg2.pid >> $DAEMON_PIDS
463 $ cat ../hg2.pid >> $DAEMON_PIDS
464
464
465 $ hg push http://localhost:$HGPORT2/
465 $ hg push http://localhost:$HGPORT2/
466 pushing to http://localhost:$HGPORT2/
466 pushing to http://localhost:$HGPORT2/
467 searching for changes
467 searching for changes
468 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
468 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
469 (merge or see 'hg help push' for details about pushing new heads)
469 (merge or see 'hg help push' for details about pushing new heads)
470 [255]
470 [255]
471 $ hg -R ../a book
471 $ hg -R ../a book
472 @ 1:0d2164f0ce0d
472 @ 1:0d2164f0ce0d
473 * X 1:0d2164f0ce0d
473 * X 1:0d2164f0ce0d
474 Y 3:f6fc62dde3c0
474 Y 3:f6fc62dde3c0
475 Z 1:0d2164f0ce0d
475 Z 1:0d2164f0ce0d
476
476
477
477
478 Unrelated marker does not alter the decision
478 Unrelated marker does not alter the decision
479
479
480 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
480 $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
481 $ hg push http://localhost:$HGPORT2/
481 $ hg push http://localhost:$HGPORT2/
482 pushing to http://localhost:$HGPORT2/
482 pushing to http://localhost:$HGPORT2/
483 searching for changes
483 searching for changes
484 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
484 abort: push creates new remote head c922c0139ca0 with bookmark 'Y'!
485 (merge or see 'hg help push' for details about pushing new heads)
485 (merge or see 'hg help push' for details about pushing new heads)
486 [255]
486 [255]
487 $ hg -R ../a book
487 $ hg -R ../a book
488 @ 1:0d2164f0ce0d
488 @ 1:0d2164f0ce0d
489 * X 1:0d2164f0ce0d
489 * X 1:0d2164f0ce0d
490 Y 3:f6fc62dde3c0
490 Y 3:f6fc62dde3c0
491 Z 1:0d2164f0ce0d
491 Z 1:0d2164f0ce0d
492
492
493 Update to a successor works
493 Update to a successor works
494
494
495 $ hg id --debug -r 3
495 $ hg id --debug -r 3
496 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
496 f6fc62dde3c0771e29704af56ba4d8af77abcc2f
497 $ hg id --debug -r 4
497 $ hg id --debug -r 4
498 4efff6d98829d9c824c621afd6e3f01865f5439f
498 4efff6d98829d9c824c621afd6e3f01865f5439f
499 $ hg id --debug -r 5
499 $ hg id --debug -r 5
500 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
500 c922c0139ca03858f655e4a2af4dd02796a63969 tip Y
501 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
501 $ hg debugobsolete f6fc62dde3c0771e29704af56ba4d8af77abcc2f cccccccccccccccccccccccccccccccccccccccc
502 obsoleted 1 changesets
502 obsoleted 1 changesets
503 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
503 $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc 4efff6d98829d9c824c621afd6e3f01865f5439f
504 $ hg push http://localhost:$HGPORT2/
504 $ hg push http://localhost:$HGPORT2/
505 pushing to http://localhost:$HGPORT2/
505 pushing to http://localhost:$HGPORT2/
506 searching for changes
506 searching for changes
507 remote: adding changesets
507 remote: adding changesets
508 remote: adding manifests
508 remote: adding manifests
509 remote: adding file changes
509 remote: adding file changes
510 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
510 remote: added 2 changesets with 2 changes to 1 files (+1 heads)
511 remote: 2 new obsolescence markers
511 remote: 2 new obsolescence markers
512 remote: obsoleted 1 changesets
512 remote: obsoleted 1 changesets
513 updating bookmark Y
513 updating bookmark Y
514 $ hg -R ../a book
514 $ hg -R ../a book
515 @ 1:0d2164f0ce0d
515 @ 1:0d2164f0ce0d
516 * X 1:0d2164f0ce0d
516 * X 1:0d2164f0ce0d
517 Y 5:c922c0139ca0
517 Y 5:c922c0139ca0
518 Z 1:0d2164f0ce0d
518 Z 1:0d2164f0ce0d
519
519
520 hgweb
520 hgweb
521
521
522 $ cat <<EOF > .hg/hgrc
522 $ cat <<EOF > .hg/hgrc
523 > [web]
523 > [web]
524 > push_ssl = false
524 > push_ssl = false
525 > allow_push = *
525 > allow_push = *
526 > EOF
526 > EOF
527
527
528 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
528 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
529 $ cat ../hg.pid >> $DAEMON_PIDS
529 $ cat ../hg.pid >> $DAEMON_PIDS
530 $ cd ../a
530 $ cd ../a
531
531
532 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
532 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
533 bookmarks
533 bookmarks
534 namespaces
534 namespaces
535 obsolete
535 obsolete
536 phases
536 phases
537 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
537 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
538 @ 9b140be1080824d768c5a4691a564088eede71f9
538 @ 9b140be1080824d768c5a4691a564088eede71f9
539 X 9b140be1080824d768c5a4691a564088eede71f9
539 X 9b140be1080824d768c5a4691a564088eede71f9
540 Y c922c0139ca03858f655e4a2af4dd02796a63969
540 Y c922c0139ca03858f655e4a2af4dd02796a63969
541 Z 9b140be1080824d768c5a4691a564088eede71f9
541 Z 9b140be1080824d768c5a4691a564088eede71f9
542 foo 0000000000000000000000000000000000000000
542 foo 0000000000000000000000000000000000000000
543 foobar 9b140be1080824d768c5a4691a564088eede71f9
543 foobar 9b140be1080824d768c5a4691a564088eede71f9
544 $ hg out -B http://localhost:$HGPORT/
544 $ hg out -B http://localhost:$HGPORT/
545 comparing with http://localhost:$HGPORT/
545 comparing with http://localhost:$HGPORT/
546 searching for changed bookmarks
546 searching for changed bookmarks
547 @ 0d2164f0ce0d
547 @ 0d2164f0ce0d
548 X 0d2164f0ce0d
548 X 0d2164f0ce0d
549 Z 0d2164f0ce0d
549 Z 0d2164f0ce0d
550 foo
550 foo
551 foobar
551 foobar
552 $ hg push -B Z http://localhost:$HGPORT/
552 $ hg push -B Z http://localhost:$HGPORT/
553 pushing to http://localhost:$HGPORT/
553 pushing to http://localhost:$HGPORT/
554 searching for changes
554 searching for changes
555 no changes found
555 no changes found
556 updating bookmark Z
556 updating bookmark Z
557 [1]
557 [1]
558 $ hg book -d Z
558 $ hg book -d Z
559 $ hg in -B http://localhost:$HGPORT/
559 $ hg in -B http://localhost:$HGPORT/
560 comparing with http://localhost:$HGPORT/
560 comparing with http://localhost:$HGPORT/
561 searching for changed bookmarks
561 searching for changed bookmarks
562 @ 9b140be10808
562 @ 9b140be10808
563 X 9b140be10808
563 X 9b140be10808
564 Z 0d2164f0ce0d
564 Z 0d2164f0ce0d
565 foo 000000000000
565 foo 000000000000
566 foobar 9b140be10808
566 foobar 9b140be10808
567 $ hg pull -B Z http://localhost:$HGPORT/
567 $ hg pull -B Z http://localhost:$HGPORT/
568 pulling from http://localhost:$HGPORT/
568 pulling from http://localhost:$HGPORT/
569 no changes found
569 no changes found
570 divergent bookmark @ stored as @1
570 divergent bookmark @ stored as @1
571 divergent bookmark X stored as X@1
571 divergent bookmark X stored as X@1
572 adding remote bookmark Z
572 adding remote bookmark Z
573 adding remote bookmark foo
573 adding remote bookmark foo
574 adding remote bookmark foobar
574 adding remote bookmark foobar
575 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
575 $ hg clone http://localhost:$HGPORT/ cloned-bookmarks
576 requesting all changes
576 requesting all changes
577 adding changesets
577 adding changesets
578 adding manifests
578 adding manifests
579 adding file changes
579 adding file changes
580 added 5 changesets with 5 changes to 3 files (+2 heads)
580 added 5 changesets with 5 changes to 3 files (+2 heads)
581 2 new obsolescence markers
581 2 new obsolescence markers
582 new changesets 4e3505fd9583:c922c0139ca0
582 new changesets 4e3505fd9583:c922c0139ca0
583 updating to bookmark @
583 updating to bookmark @
584 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
584 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
585 $ hg -R cloned-bookmarks bookmarks
585 $ hg -R cloned-bookmarks bookmarks
586 * @ 1:9b140be10808
586 * @ 1:9b140be10808
587 X 1:9b140be10808
587 X 1:9b140be10808
588 Y 4:c922c0139ca0
588 Y 4:c922c0139ca0
589 Z 2:0d2164f0ce0d
589 Z 2:0d2164f0ce0d
590 foo -1:000000000000
590 foo -1:000000000000
591 foobar 1:9b140be10808
591 foobar 1:9b140be10808
592
592
593 $ cd ..
593 $ cd ..
594
594
595 Test to show result of bookmarks comparison
595 Test to show result of bookmarks comparison
596
596
597 $ mkdir bmcomparison
597 $ mkdir bmcomparison
598 $ cd bmcomparison
598 $ cd bmcomparison
599
599
600 $ hg init source
600 $ hg init source
601 $ hg -R source debugbuilddag '+2*2*3*4'
601 $ hg -R source debugbuilddag '+2*2*3*4'
602 $ hg -R source log -G --template '{rev}:{node|short}'
602 $ hg -R source log -G --template '{rev}:{node|short}'
603 o 4:e7bd5218ca15
603 o 4:e7bd5218ca15
604 |
604 |
605 | o 3:6100d3090acf
605 | o 3:6100d3090acf
606 |/
606 |/
607 | o 2:fa942426a6fd
607 | o 2:fa942426a6fd
608 |/
608 |/
609 | o 1:66f7d451a68b
609 | o 1:66f7d451a68b
610 |/
610 |/
611 o 0:1ea73414a91b
611 o 0:1ea73414a91b
612
612
613 $ hg -R source bookmarks -r 0 SAME
613 $ hg -R source bookmarks -r 0 SAME
614 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
614 $ hg -R source bookmarks -r 0 ADV_ON_REPO1
615 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
615 $ hg -R source bookmarks -r 0 ADV_ON_REPO2
616 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
616 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO1
617 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
617 $ hg -R source bookmarks -r 0 DIFF_ADV_ON_REPO2
618 $ hg -R source bookmarks -r 1 DIVERGED
618 $ hg -R source bookmarks -r 1 DIVERGED
619
619
620 $ hg clone -U source repo1
620 $ hg clone -U source repo1
621
621
622 (test that incoming/outgoing exit with 1, if there is no bookmark to
622 (test that incoming/outgoing exit with 1, if there is no bookmark to
623 be exchanged)
623 be exchanged)
624
624
625 $ hg -R repo1 incoming -B
625 $ hg -R repo1 incoming -B
626 comparing with $TESTTMP/bmcomparison/source (glob)
626 comparing with $TESTTMP/bmcomparison/source (glob)
627 searching for changed bookmarks
627 searching for changed bookmarks
628 no changed bookmarks found
628 no changed bookmarks found
629 [1]
629 [1]
630 $ hg -R repo1 outgoing -B
630 $ hg -R repo1 outgoing -B
631 comparing with $TESTTMP/bmcomparison/source (glob)
631 comparing with $TESTTMP/bmcomparison/source (glob)
632 searching for changed bookmarks
632 searching for changed bookmarks
633 no changed bookmarks found
633 no changed bookmarks found
634 [1]
634 [1]
635
635
636 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
636 $ hg -R repo1 bookmarks -f -r 1 ADD_ON_REPO1
637 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
637 $ hg -R repo1 bookmarks -f -r 2 ADV_ON_REPO1
638 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
638 $ hg -R repo1 bookmarks -f -r 3 DIFF_ADV_ON_REPO1
639 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
639 $ hg -R repo1 bookmarks -f -r 3 DIFF_DIVERGED
640 $ hg -R repo1 -q --config extensions.mq= strip 4
640 $ hg -R repo1 -q --config extensions.mq= strip 4
641 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
641 $ hg -R repo1 log -G --template '{node|short} ({bookmarks})'
642 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
642 o 6100d3090acf (DIFF_ADV_ON_REPO1 DIFF_DIVERGED)
643 |
643 |
644 | o fa942426a6fd (ADV_ON_REPO1)
644 | o fa942426a6fd (ADV_ON_REPO1)
645 |/
645 |/
646 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
646 | o 66f7d451a68b (ADD_ON_REPO1 DIVERGED)
647 |/
647 |/
648 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
648 o 1ea73414a91b (ADV_ON_REPO2 DIFF_ADV_ON_REPO2 SAME)
649
649
650
650
651 $ hg clone -U source repo2
651 $ hg clone -U source repo2
652 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
652 $ hg -R repo2 bookmarks -f -r 1 ADD_ON_REPO2
653 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
653 $ hg -R repo2 bookmarks -f -r 1 ADV_ON_REPO2
654 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
654 $ hg -R repo2 bookmarks -f -r 2 DIVERGED
655 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
655 $ hg -R repo2 bookmarks -f -r 4 DIFF_ADV_ON_REPO2
656 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
656 $ hg -R repo2 bookmarks -f -r 4 DIFF_DIVERGED
657 $ hg -R repo2 -q --config extensions.mq= strip 3
657 $ hg -R repo2 -q --config extensions.mq= strip 3
658 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
658 $ hg -R repo2 log -G --template '{node|short} ({bookmarks})'
659 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
659 o e7bd5218ca15 (DIFF_ADV_ON_REPO2 DIFF_DIVERGED)
660 |
660 |
661 | o fa942426a6fd (DIVERGED)
661 | o fa942426a6fd (DIVERGED)
662 |/
662 |/
663 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
663 | o 66f7d451a68b (ADD_ON_REPO2 ADV_ON_REPO2)
664 |/
664 |/
665 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
665 o 1ea73414a91b (ADV_ON_REPO1 DIFF_ADV_ON_REPO1 SAME)
666
666
667
667
668 (test that difference of bookmarks between repositories are fully shown)
668 (test that difference of bookmarks between repositories are fully shown)
669
669
670 $ hg -R repo1 incoming -B repo2 -v
670 $ hg -R repo1 incoming -B repo2 -v
671 comparing with repo2
671 comparing with repo2
672 searching for changed bookmarks
672 searching for changed bookmarks
673 ADD_ON_REPO2 66f7d451a68b added
673 ADD_ON_REPO2 66f7d451a68b added
674 ADV_ON_REPO2 66f7d451a68b advanced
674 ADV_ON_REPO2 66f7d451a68b advanced
675 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
675 DIFF_ADV_ON_REPO2 e7bd5218ca15 changed
676 DIFF_DIVERGED e7bd5218ca15 changed
676 DIFF_DIVERGED e7bd5218ca15 changed
677 DIVERGED fa942426a6fd diverged
677 DIVERGED fa942426a6fd diverged
678 $ hg -R repo1 outgoing -B repo2 -v
678 $ hg -R repo1 outgoing -B repo2 -v
679 comparing with repo2
679 comparing with repo2
680 searching for changed bookmarks
680 searching for changed bookmarks
681 ADD_ON_REPO1 66f7d451a68b added
681 ADD_ON_REPO1 66f7d451a68b added
682 ADD_ON_REPO2 deleted
682 ADD_ON_REPO2 deleted
683 ADV_ON_REPO1 fa942426a6fd advanced
683 ADV_ON_REPO1 fa942426a6fd advanced
684 DIFF_ADV_ON_REPO1 6100d3090acf advanced
684 DIFF_ADV_ON_REPO1 6100d3090acf advanced
685 DIFF_ADV_ON_REPO2 1ea73414a91b changed
685 DIFF_ADV_ON_REPO2 1ea73414a91b changed
686 DIFF_DIVERGED 6100d3090acf changed
686 DIFF_DIVERGED 6100d3090acf changed
687 DIVERGED 66f7d451a68b diverged
687 DIVERGED 66f7d451a68b diverged
688
688
689 $ hg -R repo2 incoming -B repo1 -v
689 $ hg -R repo2 incoming -B repo1 -v
690 comparing with repo1
690 comparing with repo1
691 searching for changed bookmarks
691 searching for changed bookmarks
692 ADD_ON_REPO1 66f7d451a68b added
692 ADD_ON_REPO1 66f7d451a68b added
693 ADV_ON_REPO1 fa942426a6fd advanced
693 ADV_ON_REPO1 fa942426a6fd advanced
694 DIFF_ADV_ON_REPO1 6100d3090acf changed
694 DIFF_ADV_ON_REPO1 6100d3090acf changed
695 DIFF_DIVERGED 6100d3090acf changed
695 DIFF_DIVERGED 6100d3090acf changed
696 DIVERGED 66f7d451a68b diverged
696 DIVERGED 66f7d451a68b diverged
697 $ hg -R repo2 outgoing -B repo1 -v
697 $ hg -R repo2 outgoing -B repo1 -v
698 comparing with repo1
698 comparing with repo1
699 searching for changed bookmarks
699 searching for changed bookmarks
700 ADD_ON_REPO1 deleted
700 ADD_ON_REPO1 deleted
701 ADD_ON_REPO2 66f7d451a68b added
701 ADD_ON_REPO2 66f7d451a68b added
702 ADV_ON_REPO2 66f7d451a68b advanced
702 ADV_ON_REPO2 66f7d451a68b advanced
703 DIFF_ADV_ON_REPO1 1ea73414a91b changed
703 DIFF_ADV_ON_REPO1 1ea73414a91b changed
704 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
704 DIFF_ADV_ON_REPO2 e7bd5218ca15 advanced
705 DIFF_DIVERGED e7bd5218ca15 changed
705 DIFF_DIVERGED e7bd5218ca15 changed
706 DIVERGED fa942426a6fd diverged
706 DIVERGED fa942426a6fd diverged
707
707
708 $ cd ..
708 $ cd ..
709
709
710 Pushing a bookmark should only push the changes required by that
710 Pushing a bookmark should only push the changes required by that
711 bookmark, not all outgoing changes:
711 bookmark, not all outgoing changes:
712 $ hg clone http://localhost:$HGPORT/ addmarks
712 $ hg clone http://localhost:$HGPORT/ addmarks
713 requesting all changes
713 requesting all changes
714 adding changesets
714 adding changesets
715 adding manifests
715 adding manifests
716 adding file changes
716 adding file changes
717 added 5 changesets with 5 changes to 3 files (+2 heads)
717 added 5 changesets with 5 changes to 3 files (+2 heads)
718 2 new obsolescence markers
718 2 new obsolescence markers
719 new changesets 4e3505fd9583:c922c0139ca0
719 new changesets 4e3505fd9583:c922c0139ca0
720 updating to bookmark @
720 updating to bookmark @
721 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
721 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
722 $ cd addmarks
722 $ cd addmarks
723 $ echo foo > foo
723 $ echo foo > foo
724 $ hg add foo
724 $ hg add foo
725 $ hg commit -m 'add foo'
725 $ hg commit -m 'add foo'
726 $ echo bar > bar
726 $ echo bar > bar
727 $ hg add bar
727 $ hg add bar
728 $ hg commit -m 'add bar'
728 $ hg commit -m 'add bar'
729 $ hg co "tip^"
729 $ hg co "tip^"
730 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
730 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
731 (leaving bookmark @)
731 (leaving bookmark @)
732 $ hg book add-foo
732 $ hg book add-foo
733 $ hg book -r tip add-bar
733 $ hg book -r tip add-bar
734 Note: this push *must* push only a single changeset, as that's the point
734 Note: this push *must* push only a single changeset, as that's the point
735 of this test.
735 of this test.
736 $ hg push -B add-foo --traceback
736 $ hg push -B add-foo --traceback
737 pushing to http://localhost:$HGPORT/
737 pushing to http://localhost:$HGPORT/
738 searching for changes
738 searching for changes
739 remote: adding changesets
739 remote: adding changesets
740 remote: adding manifests
740 remote: adding manifests
741 remote: adding file changes
741 remote: adding file changes
742 remote: added 1 changesets with 1 changes to 1 files
742 remote: added 1 changesets with 1 changes to 1 files
743 exporting bookmark add-foo
743 exporting bookmark add-foo
744
744
745 pushing a new bookmark on a new head does not require -f if -B is specified
745 pushing a new bookmark on a new head does not require -f if -B is specified
746
746
747 $ hg up -q X
747 $ hg up -q X
748 $ hg book W
748 $ hg book W
749 $ echo c5 > f2
749 $ echo c5 > f2
750 $ hg ci -Am5
750 $ hg ci -Am5
751 created new head
751 created new head
752 $ hg push -B .
752 $ hg push -B .
753 pushing to http://localhost:$HGPORT/
753 pushing to http://localhost:$HGPORT/
754 searching for changes
754 searching for changes
755 remote: adding changesets
755 remote: adding changesets
756 remote: adding manifests
756 remote: adding manifests
757 remote: adding file changes
757 remote: adding file changes
758 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
758 remote: added 1 changesets with 1 changes to 1 files (+1 heads)
759 exporting bookmark W
759 exporting bookmark W
760 $ hg -R ../b id -r W
760 $ hg -R ../b id -r W
761 cc978a373a53 tip W
761 cc978a373a53 tip W
762
762
763 pushing an existing but divergent bookmark with -B still requires -f
763 pushing an existing but divergent bookmark with -B still requires -f
764
764
765 $ hg clone -q . ../r
765 $ hg clone -q . ../r
766 $ hg up -q X
766 $ hg up -q X
767 $ echo 1 > f2
767 $ echo 1 > f2
768 $ hg ci -qAml
768 $ hg ci -qAml
769
769
770 $ cd ../r
770 $ cd ../r
771 $ hg up -q X
771 $ hg up -q X
772 $ echo 2 > f2
772 $ echo 2 > f2
773 $ hg ci -qAmr
773 $ hg ci -qAmr
774 $ hg push -B X
774 $ hg push -B X
775 pushing to $TESTTMP/addmarks (glob)
775 pushing to $TESTTMP/addmarks (glob)
776 searching for changes
776 searching for changes
777 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
777 remote has heads on branch 'default' that are not known locally: a2a606d9ff1b
778 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
778 abort: push creates new remote head 54694f811df9 with bookmark 'X'!
779 (pull and merge or see 'hg help push' for details about pushing new heads)
779 (pull and merge or see 'hg help push' for details about pushing new heads)
780 [255]
780 [255]
781 $ cd ../addmarks
781 $ cd ../addmarks
782
782
783 Check summary output for incoming/outgoing bookmarks
783 Check summary output for incoming/outgoing bookmarks
784
784
785 $ hg bookmarks -d X
785 $ hg bookmarks -d X
786 $ hg bookmarks -d Y
786 $ hg bookmarks -d Y
787 $ hg summary --remote | grep '^remote:'
787 $ hg summary --remote | grep '^remote:'
788 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
788 remote: *, 2 incoming bookmarks, 1 outgoing bookmarks (glob)
789
789
790 $ cd ..
790 $ cd ..
791
791
792 pushing an unchanged bookmark should result in no changes
792 pushing an unchanged bookmark should result in no changes
793
793
794 $ hg init unchanged-a
794 $ hg init unchanged-a
795 $ hg init unchanged-b
795 $ hg init unchanged-b
796 $ cd unchanged-a
796 $ cd unchanged-a
797 $ echo initial > foo
797 $ echo initial > foo
798 $ hg commit -A -m initial
798 $ hg commit -A -m initial
799 adding foo
799 adding foo
800 $ hg bookmark @
800 $ hg bookmark @
801 $ hg push -B @ ../unchanged-b
801 $ hg push -B @ ../unchanged-b
802 pushing to ../unchanged-b
802 pushing to ../unchanged-b
803 searching for changes
803 searching for changes
804 adding changesets
804 adding changesets
805 adding manifests
805 adding manifests
806 adding file changes
806 adding file changes
807 added 1 changesets with 1 changes to 1 files
807 added 1 changesets with 1 changes to 1 files
808 exporting bookmark @
808 exporting bookmark @
809
809
810 $ hg push -B @ ../unchanged-b
810 $ hg push -B @ ../unchanged-b
811 pushing to ../unchanged-b
811 pushing to ../unchanged-b
812 searching for changes
812 searching for changes
813 no changes found
813 no changes found
814 [1]
814 [1]
815
815
816
816
817 Check hook preventing push (issue4455)
817 Check hook preventing push (issue4455)
818 ======================================
818 ======================================
819
819
820 $ hg bookmarks
820 $ hg bookmarks
821 * @ 0:55482a6fb4b1
821 * @ 0:55482a6fb4b1
822 $ hg log -G
822 $ hg log -G
823 @ 0:55482a6fb4b1 initial
823 @ 0:55482a6fb4b1 initial
824
824
825 $ hg init ../issue4455-dest
825 $ hg init ../issue4455-dest
826 $ hg push ../issue4455-dest # changesets only
826 $ hg push ../issue4455-dest # changesets only
827 pushing to ../issue4455-dest
827 pushing to ../issue4455-dest
828 searching for changes
828 searching for changes
829 adding changesets
829 adding changesets
830 adding manifests
830 adding manifests
831 adding file changes
831 adding file changes
832 added 1 changesets with 1 changes to 1 files
832 added 1 changesets with 1 changes to 1 files
833 $ cat >> .hg/hgrc << EOF
833 $ cat >> .hg/hgrc << EOF
834 > [paths]
834 > [paths]
835 > local=../issue4455-dest/
835 > local=../issue4455-dest/
836 > ssh=ssh://user@dummy/issue4455-dest
836 > ssh=ssh://user@dummy/issue4455-dest
837 > http=http://localhost:$HGPORT/
837 > http=http://localhost:$HGPORT/
838 > [ui]
838 > [ui]
839 > ssh=$PYTHON "$TESTDIR/dummyssh"
839 > ssh=$PYTHON "$TESTDIR/dummyssh"
840 > EOF
840 > EOF
841 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
841 $ cat >> ../issue4455-dest/.hg/hgrc << EOF
842 > [hooks]
842 > [hooks]
843 > prepushkey=false
843 > prepushkey=false
844 > [web]
844 > [web]
845 > push_ssl = false
845 > push_ssl = false
846 > allow_push = *
846 > allow_push = *
847 > EOF
847 > EOF
848 $ killdaemons.py
848 $ killdaemons.py
849 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
849 $ hg serve -R ../issue4455-dest -p $HGPORT -d --pid-file=../issue4455.pid -E ../issue4455-error.log
850 $ cat ../issue4455.pid >> $DAEMON_PIDS
850 $ cat ../issue4455.pid >> $DAEMON_PIDS
851
851
852 Local push
852 Local push
853 ----------
853 ----------
854
854
855 $ hg push -B @ local
855 $ hg push -B @ local
856 pushing to $TESTTMP/issue4455-dest (glob)
856 pushing to $TESTTMP/issue4455-dest (glob)
857 searching for changes
857 searching for changes
858 no changes found
858 no changes found
859 pushkey-abort: prepushkey hook exited with status 1
859 pushkey-abort: prepushkey hook exited with status 1
860 abort: exporting bookmark @ failed!
860 abort: exporting bookmark @ failed!
861 [255]
861 [255]
862 $ hg -R ../issue4455-dest/ bookmarks
862 $ hg -R ../issue4455-dest/ bookmarks
863 no bookmarks set
863 no bookmarks set
864
864
865 Using ssh
865 Using ssh
866 ---------
866 ---------
867
867
868 $ hg push -B @ ssh # bundle2+
868 $ hg push -B @ ssh # bundle2+
869 pushing to ssh://user@dummy/issue4455-dest
869 pushing to ssh://user@dummy/issue4455-dest
870 searching for changes
870 searching for changes
871 no changes found
871 no changes found
872 remote: pushkey-abort: prepushkey hook exited with status 1
872 remote: pushkey-abort: prepushkey hook exited with status 1
873 abort: exporting bookmark @ failed!
873 abort: exporting bookmark @ failed!
874 [255]
874 [255]
875 $ hg -R ../issue4455-dest/ bookmarks
875 $ hg -R ../issue4455-dest/ bookmarks
876 no bookmarks set
876 no bookmarks set
877
877
878 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
878 $ hg push -B @ ssh --config devel.legacy.exchange=bundle1
879 pushing to ssh://user@dummy/issue4455-dest
879 pushing to ssh://user@dummy/issue4455-dest
880 searching for changes
880 searching for changes
881 no changes found
881 no changes found
882 remote: pushkey-abort: prepushkey hook exited with status 1
882 remote: pushkey-abort: prepushkey hook exited with status 1
883 exporting bookmark @ failed!
883 exporting bookmark @ failed!
884 [1]
884 [1]
885 $ hg -R ../issue4455-dest/ bookmarks
885 $ hg -R ../issue4455-dest/ bookmarks
886 no bookmarks set
886 no bookmarks set
887
887
888 Using http
888 Using http
889 ----------
889 ----------
890
890
891 $ hg push -B @ http # bundle2+
891 $ hg push -B @ http # bundle2+
892 pushing to http://localhost:$HGPORT/
892 pushing to http://localhost:$HGPORT/
893 searching for changes
893 searching for changes
894 no changes found
894 no changes found
895 remote: pushkey-abort: prepushkey hook exited with status 1
895 remote: pushkey-abort: prepushkey hook exited with status 1
896 abort: exporting bookmark @ failed!
896 abort: exporting bookmark @ failed!
897 [255]
897 [255]
898 $ hg -R ../issue4455-dest/ bookmarks
898 $ hg -R ../issue4455-dest/ bookmarks
899 no bookmarks set
899 no bookmarks set
900
900
901 $ hg push -B @ http --config devel.legacy.exchange=bundle1
901 $ hg push -B @ http --config devel.legacy.exchange=bundle1
902 pushing to http://localhost:$HGPORT/
902 pushing to http://localhost:$HGPORT/
903 searching for changes
903 searching for changes
904 no changes found
904 no changes found
905 remote: pushkey-abort: prepushkey hook exited with status 1
905 remote: pushkey-abort: prepushkey hook exited with status 1
906 exporting bookmark @ failed!
906 exporting bookmark @ failed!
907 [1]
907 [1]
908 $ hg -R ../issue4455-dest/ bookmarks
908 $ hg -R ../issue4455-dest/ bookmarks
909 no bookmarks set
909 no bookmarks set
@@ -1,80 +1,92 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 ([+] can be repeated):
22 options ([+] can be repeated):
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 (use 'hg cat -h' to show more help)
30 (use 'hg cat -h' to show more help)
31 [255]
31 [255]
32
32
33 Missing parameter for early option:
34
35 $ hg log -R 2>&1 | grep 'hg log'
36 hg log: option -R requires argument
37 hg log [OPTION]... [FILE]
38 (use 'hg log -h' to show more help)
39
40 $ hg log -R -- 2>&1 | grep 'hg log'
41 hg log: option -R requires argument
42 hg log [OPTION]... [FILE]
43 (use 'hg log -h' to show more help)
44
33 [defaults]
45 [defaults]
34
46
35 $ hg cat a
47 $ hg cat a
36 a
48 a
37 $ cat >> $HGRCPATH <<EOF
49 $ cat >> $HGRCPATH <<EOF
38 > [defaults]
50 > [defaults]
39 > cat = -r null
51 > cat = -r null
40 > EOF
52 > EOF
41 $ hg cat a
53 $ hg cat a
42 a: no such file in rev 000000000000
54 a: no such file in rev 000000000000
43 [1]
55 [1]
44
56
45 $ cd "$TESTTMP"
57 $ cd "$TESTTMP"
46
58
47 OSError "No such file or directory" / "The system cannot find the path
59 OSError "No such file or directory" / "The system cannot find the path
48 specified" should include filename even when it is empty
60 specified" should include filename even when it is empty
49
61
50 $ hg -R a archive ''
62 $ hg -R a archive ''
51 abort: *: '' (glob)
63 abort: *: '' (glob)
52 [255]
64 [255]
53
65
54 #if no-outer-repo
66 #if no-outer-repo
55
67
56 No repo:
68 No repo:
57
69
58 $ hg cat
70 $ hg cat
59 abort: no repository found in '$TESTTMP' (.hg not found)!
71 abort: no repository found in '$TESTTMP' (.hg not found)!
60 [255]
72 [255]
61
73
62 #endif
74 #endif
63
75
64 #if rmcwd
76 #if rmcwd
65
77
66 Current directory removed:
78 Current directory removed:
67
79
68 $ mkdir $TESTTMP/repo1
80 $ mkdir $TESTTMP/repo1
69 $ cd $TESTTMP/repo1
81 $ cd $TESTTMP/repo1
70 $ rm -rf $TESTTMP/repo1
82 $ rm -rf $TESTTMP/repo1
71
83
72 The output could be one of the following and something else:
84 The output could be one of the following and something else:
73 chg: abort: failed to getcwd (errno = *) (glob)
85 chg: abort: failed to getcwd (errno = *) (glob)
74 abort: error getting current working directory: * (glob)
86 abort: error getting current working directory: * (glob)
75 sh: 0: getcwd() failed: No such file or directory
87 sh: 0: getcwd() failed: No such file or directory
76 Since the exact behavior depends on the shell, only check it returns non-zero.
88 Since the exact behavior depends on the shell, only check it returns non-zero.
77 $ HGDEMANDIMPORT=disable hg version -q 2>/dev/null || false
89 $ HGDEMANDIMPORT=disable hg version -q 2>/dev/null || false
78 [1]
90 [1]
79
91
80 #endif
92 #endif
@@ -1,413 +1,413 b''
1
1
2 Function to test discovery between two repos in both directions, using both the local shortcut
2 Function to test discovery between two repos in both directions, using both the local shortcut
3 (which is currently not activated by default) and the full remotable protocol:
3 (which is currently not activated by default) and the full remotable protocol:
4
4
5 $ testdesc() { # revs_a, revs_b, dagdesc
5 $ testdesc() { # revs_a, revs_b, dagdesc
6 > if [ -d foo ]; then rm -rf foo; fi
6 > if [ -d foo ]; then rm -rf foo; fi
7 > hg init foo
7 > hg init foo
8 > cd foo
8 > cd foo
9 > hg debugbuilddag "$3"
9 > hg debugbuilddag "$3"
10 > hg clone . a $1 --quiet
10 > hg clone . a $1 --quiet
11 > hg clone . b $2 --quiet
11 > hg clone . b $2 --quiet
12 > echo
12 > echo
13 > echo "% -- a -> b tree"
13 > echo "% -- a -> b tree"
14 > hg -R a debugdiscovery b --verbose --old
14 > hg -R a debugdiscovery b --verbose --old
15 > echo
15 > echo
16 > echo "% -- a -> b set"
16 > echo "% -- a -> b set"
17 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true
17 > hg -R a debugdiscovery b --verbose --debug --config progress.debug=true
18 > echo
18 > echo
19 > echo "% -- b -> a tree"
19 > echo "% -- b -> a tree"
20 > hg -R b debugdiscovery a --verbose --old --config
20 > hg -R b debugdiscovery a --verbose --old
21 > echo
21 > echo
22 > echo "% -- b -> a set"
22 > echo "% -- b -> a set"
23 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true
23 > hg -R b debugdiscovery a --verbose --debug --config progress.debug=true
24 > cd ..
24 > cd ..
25 > }
25 > }
26
26
27
27
28 Small superset:
28 Small superset:
29
29
30 $ testdesc '-ra1 -ra2' '-rb1 -rb2 -rb3' '
30 $ testdesc '-ra1 -ra2' '-rb1 -rb2 -rb3' '
31 > +2:f +1:a1:b1
31 > +2:f +1:a1:b1
32 > <f +4 :a2
32 > <f +4 :a2
33 > +5 :b2
33 > +5 :b2
34 > <f +3 :b3'
34 > <f +3 :b3'
35
35
36 % -- a -> b tree
36 % -- a -> b tree
37 comparing with b
37 comparing with b
38 searching for changes
38 searching for changes
39 unpruned common: 01241442b3c2 66f7d451a68b b5714e113bc0
39 unpruned common: 01241442b3c2 66f7d451a68b b5714e113bc0
40 common heads: 01241442b3c2 b5714e113bc0
40 common heads: 01241442b3c2 b5714e113bc0
41 local is subset
41 local is subset
42
42
43 % -- a -> b set
43 % -- a -> b set
44 comparing with b
44 comparing with b
45 query 1; heads
45 query 1; heads
46 searching for changes
46 searching for changes
47 all local heads known remotely
47 all local heads known remotely
48 common heads: 01241442b3c2 b5714e113bc0
48 common heads: 01241442b3c2 b5714e113bc0
49 local is subset
49 local is subset
50
50
51 % -- b -> a tree
51 % -- b -> a tree
52 comparing with a
52 comparing with a
53 searching for changes
53 searching for changes
54 unpruned common: 01241442b3c2 b5714e113bc0
54 unpruned common: 01241442b3c2 b5714e113bc0
55 common heads: 01241442b3c2 b5714e113bc0
55 common heads: 01241442b3c2 b5714e113bc0
56 remote is subset
56 remote is subset
57
57
58 % -- b -> a set
58 % -- b -> a set
59 comparing with a
59 comparing with a
60 query 1; heads
60 query 1; heads
61 searching for changes
61 searching for changes
62 all remote heads known locally
62 all remote heads known locally
63 common heads: 01241442b3c2 b5714e113bc0
63 common heads: 01241442b3c2 b5714e113bc0
64 remote is subset
64 remote is subset
65
65
66
66
67 Many new:
67 Many new:
68
68
69 $ testdesc '-ra1 -ra2' '-rb' '
69 $ testdesc '-ra1 -ra2' '-rb' '
70 > +2:f +3:a1 +3:b
70 > +2:f +3:a1 +3:b
71 > <f +30 :a2'
71 > <f +30 :a2'
72
72
73 % -- a -> b tree
73 % -- a -> b tree
74 comparing with b
74 comparing with b
75 searching for changes
75 searching for changes
76 unpruned common: bebd167eb94d
76 unpruned common: bebd167eb94d
77 common heads: bebd167eb94d
77 common heads: bebd167eb94d
78
78
79 % -- a -> b set
79 % -- a -> b set
80 comparing with b
80 comparing with b
81 query 1; heads
81 query 1; heads
82 searching for changes
82 searching for changes
83 taking initial sample
83 taking initial sample
84 searching: 2 queries
84 searching: 2 queries
85 query 2; still undecided: 29, sample size is: 29
85 query 2; still undecided: 29, sample size is: 29
86 2 total queries in *.????s (glob)
86 2 total queries in *.????s (glob)
87 common heads: bebd167eb94d
87 common heads: bebd167eb94d
88
88
89 % -- b -> a tree
89 % -- b -> a tree
90 comparing with a
90 comparing with a
91 searching for changes
91 searching for changes
92 unpruned common: 66f7d451a68b bebd167eb94d
92 unpruned common: 66f7d451a68b bebd167eb94d
93 common heads: bebd167eb94d
93 common heads: bebd167eb94d
94
94
95 % -- b -> a set
95 % -- b -> a set
96 comparing with a
96 comparing with a
97 query 1; heads
97 query 1; heads
98 searching for changes
98 searching for changes
99 taking initial sample
99 taking initial sample
100 searching: 2 queries
100 searching: 2 queries
101 query 2; still undecided: 2, sample size is: 2
101 query 2; still undecided: 2, sample size is: 2
102 2 total queries in *.????s (glob)
102 2 total queries in *.????s (glob)
103 common heads: bebd167eb94d
103 common heads: bebd167eb94d
104
104
105 Both sides many new with stub:
105 Both sides many new with stub:
106
106
107 $ testdesc '-ra1 -ra2' '-rb' '
107 $ testdesc '-ra1 -ra2' '-rb' '
108 > +2:f +2:a1 +30 :b
108 > +2:f +2:a1 +30 :b
109 > <f +30 :a2'
109 > <f +30 :a2'
110
110
111 % -- a -> b tree
111 % -- a -> b tree
112 comparing with b
112 comparing with b
113 searching for changes
113 searching for changes
114 unpruned common: 2dc09a01254d
114 unpruned common: 2dc09a01254d
115 common heads: 2dc09a01254d
115 common heads: 2dc09a01254d
116
116
117 % -- a -> b set
117 % -- a -> b set
118 comparing with b
118 comparing with b
119 query 1; heads
119 query 1; heads
120 searching for changes
120 searching for changes
121 taking initial sample
121 taking initial sample
122 searching: 2 queries
122 searching: 2 queries
123 query 2; still undecided: 29, sample size is: 29
123 query 2; still undecided: 29, sample size is: 29
124 2 total queries in *.????s (glob)
124 2 total queries in *.????s (glob)
125 common heads: 2dc09a01254d
125 common heads: 2dc09a01254d
126
126
127 % -- b -> a tree
127 % -- b -> a tree
128 comparing with a
128 comparing with a
129 searching for changes
129 searching for changes
130 unpruned common: 2dc09a01254d 66f7d451a68b
130 unpruned common: 2dc09a01254d 66f7d451a68b
131 common heads: 2dc09a01254d
131 common heads: 2dc09a01254d
132
132
133 % -- b -> a set
133 % -- b -> a set
134 comparing with a
134 comparing with a
135 query 1; heads
135 query 1; heads
136 searching for changes
136 searching for changes
137 taking initial sample
137 taking initial sample
138 searching: 2 queries
138 searching: 2 queries
139 query 2; still undecided: 29, sample size is: 29
139 query 2; still undecided: 29, sample size is: 29
140 2 total queries in *.????s (glob)
140 2 total queries in *.????s (glob)
141 common heads: 2dc09a01254d
141 common heads: 2dc09a01254d
142
142
143
143
144 Both many new:
144 Both many new:
145
145
146 $ testdesc '-ra' '-rb' '
146 $ testdesc '-ra' '-rb' '
147 > +2:f +30 :b
147 > +2:f +30 :b
148 > <f +30 :a'
148 > <f +30 :a'
149
149
150 % -- a -> b tree
150 % -- a -> b tree
151 comparing with b
151 comparing with b
152 searching for changes
152 searching for changes
153 unpruned common: 66f7d451a68b
153 unpruned common: 66f7d451a68b
154 common heads: 66f7d451a68b
154 common heads: 66f7d451a68b
155
155
156 % -- a -> b set
156 % -- a -> b set
157 comparing with b
157 comparing with b
158 query 1; heads
158 query 1; heads
159 searching for changes
159 searching for changes
160 taking quick initial sample
160 taking quick initial sample
161 searching: 2 queries
161 searching: 2 queries
162 query 2; still undecided: 31, sample size is: 31
162 query 2; still undecided: 31, sample size is: 31
163 2 total queries in *.????s (glob)
163 2 total queries in *.????s (glob)
164 common heads: 66f7d451a68b
164 common heads: 66f7d451a68b
165
165
166 % -- b -> a tree
166 % -- b -> a tree
167 comparing with a
167 comparing with a
168 searching for changes
168 searching for changes
169 unpruned common: 66f7d451a68b
169 unpruned common: 66f7d451a68b
170 common heads: 66f7d451a68b
170 common heads: 66f7d451a68b
171
171
172 % -- b -> a set
172 % -- b -> a set
173 comparing with a
173 comparing with a
174 query 1; heads
174 query 1; heads
175 searching for changes
175 searching for changes
176 taking quick initial sample
176 taking quick initial sample
177 searching: 2 queries
177 searching: 2 queries
178 query 2; still undecided: 31, sample size is: 31
178 query 2; still undecided: 31, sample size is: 31
179 2 total queries in *.????s (glob)
179 2 total queries in *.????s (glob)
180 common heads: 66f7d451a68b
180 common heads: 66f7d451a68b
181
181
182
182
183 Both many new skewed:
183 Both many new skewed:
184
184
185 $ testdesc '-ra' '-rb' '
185 $ testdesc '-ra' '-rb' '
186 > +2:f +30 :b
186 > +2:f +30 :b
187 > <f +50 :a'
187 > <f +50 :a'
188
188
189 % -- a -> b tree
189 % -- a -> b tree
190 comparing with b
190 comparing with b
191 searching for changes
191 searching for changes
192 unpruned common: 66f7d451a68b
192 unpruned common: 66f7d451a68b
193 common heads: 66f7d451a68b
193 common heads: 66f7d451a68b
194
194
195 % -- a -> b set
195 % -- a -> b set
196 comparing with b
196 comparing with b
197 query 1; heads
197 query 1; heads
198 searching for changes
198 searching for changes
199 taking quick initial sample
199 taking quick initial sample
200 searching: 2 queries
200 searching: 2 queries
201 query 2; still undecided: 51, sample size is: 51
201 query 2; still undecided: 51, sample size is: 51
202 2 total queries in *.????s (glob)
202 2 total queries in *.????s (glob)
203 common heads: 66f7d451a68b
203 common heads: 66f7d451a68b
204
204
205 % -- b -> a tree
205 % -- b -> a tree
206 comparing with a
206 comparing with a
207 searching for changes
207 searching for changes
208 unpruned common: 66f7d451a68b
208 unpruned common: 66f7d451a68b
209 common heads: 66f7d451a68b
209 common heads: 66f7d451a68b
210
210
211 % -- b -> a set
211 % -- b -> a set
212 comparing with a
212 comparing with a
213 query 1; heads
213 query 1; heads
214 searching for changes
214 searching for changes
215 taking quick initial sample
215 taking quick initial sample
216 searching: 2 queries
216 searching: 2 queries
217 query 2; still undecided: 31, sample size is: 31
217 query 2; still undecided: 31, sample size is: 31
218 2 total queries in *.????s (glob)
218 2 total queries in *.????s (glob)
219 common heads: 66f7d451a68b
219 common heads: 66f7d451a68b
220
220
221
221
222 Both many new on top of long history:
222 Both many new on top of long history:
223
223
224 $ testdesc '-ra' '-rb' '
224 $ testdesc '-ra' '-rb' '
225 > +1000:f +30 :b
225 > +1000:f +30 :b
226 > <f +50 :a'
226 > <f +50 :a'
227
227
228 % -- a -> b tree
228 % -- a -> b tree
229 comparing with b
229 comparing with b
230 searching for changes
230 searching for changes
231 unpruned common: 7ead0cba2838
231 unpruned common: 7ead0cba2838
232 common heads: 7ead0cba2838
232 common heads: 7ead0cba2838
233
233
234 % -- a -> b set
234 % -- a -> b set
235 comparing with b
235 comparing with b
236 query 1; heads
236 query 1; heads
237 searching for changes
237 searching for changes
238 taking quick initial sample
238 taking quick initial sample
239 searching: 2 queries
239 searching: 2 queries
240 query 2; still undecided: 1049, sample size is: 11
240 query 2; still undecided: 1049, sample size is: 11
241 sampling from both directions
241 sampling from both directions
242 searching: 3 queries
242 searching: 3 queries
243 query 3; still undecided: 31, sample size is: 31
243 query 3; still undecided: 31, sample size is: 31
244 3 total queries in *.????s (glob)
244 3 total queries in *.????s (glob)
245 common heads: 7ead0cba2838
245 common heads: 7ead0cba2838
246
246
247 % -- b -> a tree
247 % -- b -> a tree
248 comparing with a
248 comparing with a
249 searching for changes
249 searching for changes
250 unpruned common: 7ead0cba2838
250 unpruned common: 7ead0cba2838
251 common heads: 7ead0cba2838
251 common heads: 7ead0cba2838
252
252
253 % -- b -> a set
253 % -- b -> a set
254 comparing with a
254 comparing with a
255 query 1; heads
255 query 1; heads
256 searching for changes
256 searching for changes
257 taking quick initial sample
257 taking quick initial sample
258 searching: 2 queries
258 searching: 2 queries
259 query 2; still undecided: 1029, sample size is: 11
259 query 2; still undecided: 1029, sample size is: 11
260 sampling from both directions
260 sampling from both directions
261 searching: 3 queries
261 searching: 3 queries
262 query 3; still undecided: 15, sample size is: 15
262 query 3; still undecided: 15, sample size is: 15
263 3 total queries in *.????s (glob)
263 3 total queries in *.????s (glob)
264 common heads: 7ead0cba2838
264 common heads: 7ead0cba2838
265
265
266
266
267 One with >200 heads, which used to use up all of the sample:
267 One with >200 heads, which used to use up all of the sample:
268
268
269 $ hg init manyheads
269 $ hg init manyheads
270 $ cd manyheads
270 $ cd manyheads
271 $ echo "+300:r @a" >dagdesc
271 $ echo "+300:r @a" >dagdesc
272 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
272 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
273 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
273 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
274 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
274 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
275 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
275 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
276 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
276 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
277 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
277 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
278 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
278 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
279 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
279 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
280 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
280 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
281 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
281 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
282 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
282 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
283 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
283 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
284 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
284 $ echo "*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3 *r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3*r+3" >>dagdesc # 20 heads
285 $ echo "@b *r+3" >>dagdesc # one more head
285 $ echo "@b *r+3" >>dagdesc # one more head
286 $ hg debugbuilddag <dagdesc
286 $ hg debugbuilddag <dagdesc
287 reading DAG from stdin
287 reading DAG from stdin
288
288
289 $ hg heads -t --template . | wc -c
289 $ hg heads -t --template . | wc -c
290 \s*261 (re)
290 \s*261 (re)
291
291
292 $ hg clone -b a . a
292 $ hg clone -b a . a
293 adding changesets
293 adding changesets
294 adding manifests
294 adding manifests
295 adding file changes
295 adding file changes
296 added 1340 changesets with 0 changes to 0 files (+259 heads)
296 added 1340 changesets with 0 changes to 0 files (+259 heads)
297 new changesets 1ea73414a91b:1c51e2c80832
297 new changesets 1ea73414a91b:1c51e2c80832
298 updating to branch a
298 updating to branch a
299 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
299 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
300 $ hg clone -b b . b
300 $ hg clone -b b . b
301 adding changesets
301 adding changesets
302 adding manifests
302 adding manifests
303 adding file changes
303 adding file changes
304 added 304 changesets with 0 changes to 0 files
304 added 304 changesets with 0 changes to 0 files
305 new changesets 1ea73414a91b:513314ca8b3a
305 new changesets 1ea73414a91b:513314ca8b3a
306 updating to branch b
306 updating to branch b
307 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
307 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
308
308
309 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true
309 $ hg -R a debugdiscovery b --debug --verbose --config progress.debug=true
310 comparing with b
310 comparing with b
311 query 1; heads
311 query 1; heads
312 searching for changes
312 searching for changes
313 taking quick initial sample
313 taking quick initial sample
314 searching: 2 queries
314 searching: 2 queries
315 query 2; still undecided: 1240, sample size is: 100
315 query 2; still undecided: 1240, sample size is: 100
316 sampling from both directions
316 sampling from both directions
317 searching: 3 queries
317 searching: 3 queries
318 query 3; still undecided: 1140, sample size is: 200
318 query 3; still undecided: 1140, sample size is: 200
319 sampling from both directions
319 sampling from both directions
320 searching: 4 queries
320 searching: 4 queries
321 query 4; still undecided: \d+, sample size is: 200 (re)
321 query 4; still undecided: \d+, sample size is: 200 (re)
322 sampling from both directions
322 sampling from both directions
323 searching: 5 queries
323 searching: 5 queries
324 query 5; still undecided: \d+, sample size is: 200 (re)
324 query 5; still undecided: \d+, sample size is: 200 (re)
325 sampling from both directions
325 sampling from both directions
326 searching: 6 queries
326 searching: 6 queries
327 query 6; still undecided: \d+, sample size is: \d+ (re)
327 query 6; still undecided: \d+, sample size is: \d+ (re)
328 6 total queries in *.????s (glob)
328 6 total queries in *.????s (glob)
329 common heads: 3ee37d65064a
329 common heads: 3ee37d65064a
330
330
331 Test actual protocol when pulling one new head in addition to common heads
331 Test actual protocol when pulling one new head in addition to common heads
332
332
333 $ hg clone -U b c
333 $ hg clone -U b c
334 $ hg -R c id -ir tip
334 $ hg -R c id -ir tip
335 513314ca8b3a
335 513314ca8b3a
336 $ hg -R c up -qr default
336 $ hg -R c up -qr default
337 $ touch c/f
337 $ touch c/f
338 $ hg -R c ci -Aqm "extra head"
338 $ hg -R c ci -Aqm "extra head"
339 $ hg -R c id -i
339 $ hg -R c id -i
340 e64a39e7da8b
340 e64a39e7da8b
341
341
342 $ hg serve -R c -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
342 $ hg serve -R c -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
343 $ cat hg.pid >> $DAEMON_PIDS
343 $ cat hg.pid >> $DAEMON_PIDS
344
344
345 $ hg -R b incoming http://localhost:$HGPORT/ -T '{node|short}\n'
345 $ hg -R b incoming http://localhost:$HGPORT/ -T '{node|short}\n'
346 comparing with http://localhost:$HGPORT/
346 comparing with http://localhost:$HGPORT/
347 searching for changes
347 searching for changes
348 e64a39e7da8b
348 e64a39e7da8b
349
349
350 $ killdaemons.py
350 $ killdaemons.py
351 $ cut -d' ' -f6- access.log | grep -v cmd=known # cmd=known uses random sampling
351 $ cut -d' ' -f6- access.log | grep -v cmd=known # cmd=known uses random sampling
352 "GET /?cmd=capabilities HTTP/1.1" 200 -
352 "GET /?cmd=capabilities HTTP/1.1" 200 -
353 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D513314ca8b3ae4dac8eec56966265b00fcf866db x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
353 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D513314ca8b3ae4dac8eec56966265b00fcf866db x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
354 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=513314ca8b3ae4dac8eec56966265b00fcf866db&heads=e64a39e7da8b0d54bc63e81169aff001c13b3477 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
354 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Aphases%253Dheads%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=513314ca8b3ae4dac8eec56966265b00fcf866db&heads=e64a39e7da8b0d54bc63e81169aff001c13b3477 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
355 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
355 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
356 $ cat errors.log
356 $ cat errors.log
357
357
358 $ cd ..
358 $ cd ..
359
359
360
360
361 Issue 4438 - test coverage for 3ef893520a85 issues.
361 Issue 4438 - test coverage for 3ef893520a85 issues.
362
362
363 $ mkdir issue4438
363 $ mkdir issue4438
364 $ cd issue4438
364 $ cd issue4438
365 #if false
365 #if false
366 generate new bundles:
366 generate new bundles:
367 $ hg init r1
367 $ hg init r1
368 $ for i in `$PYTHON $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
368 $ for i in `$PYTHON $TESTDIR/seq.py 101`; do hg -R r1 up -qr null && hg -R r1 branch -q b$i && hg -R r1 ci -qmb$i; done
369 $ hg clone -q r1 r2
369 $ hg clone -q r1 r2
370 $ for i in `$PYTHON $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
370 $ for i in `$PYTHON $TESTDIR/seq.py 10`; do hg -R r1 up -qr null && hg -R r1 branch -q c$i && hg -R r1 ci -qmc$i; done
371 $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
371 $ hg -R r2 branch -q r2change && hg -R r2 ci -qmr2change
372 $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
372 $ hg -R r1 bundle -qa $TESTDIR/bundles/issue4438-r1.hg
373 $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
373 $ hg -R r2 bundle -qa $TESTDIR/bundles/issue4438-r2.hg
374 #else
374 #else
375 use existing bundles:
375 use existing bundles:
376 $ hg clone -q $TESTDIR/bundles/issue4438-r1.hg r1
376 $ hg clone -q $TESTDIR/bundles/issue4438-r1.hg r1
377 $ hg clone -q $TESTDIR/bundles/issue4438-r2.hg r2
377 $ hg clone -q $TESTDIR/bundles/issue4438-r2.hg r2
378 #endif
378 #endif
379
379
380 Set iteration order could cause wrong and unstable results - fixed in 73cfaa348650:
380 Set iteration order could cause wrong and unstable results - fixed in 73cfaa348650:
381
381
382 $ hg -R r1 outgoing r2 -T'{rev} '
382 $ hg -R r1 outgoing r2 -T'{rev} '
383 comparing with r2
383 comparing with r2
384 searching for changes
384 searching for changes
385 101 102 103 104 105 106 107 108 109 110 (no-eol)
385 101 102 103 104 105 106 107 108 109 110 (no-eol)
386
386
387 The case where all the 'initialsamplesize' samples already were common would
387 The case where all the 'initialsamplesize' samples already were common would
388 give 'all remote heads known locally' without checking the remaining heads -
388 give 'all remote heads known locally' without checking the remaining heads -
389 fixed in 86c35b7ae300:
389 fixed in 86c35b7ae300:
390
390
391 $ cat >> $TESTTMP/unrandomsample.py << EOF
391 $ cat >> $TESTTMP/unrandomsample.py << EOF
392 > import random
392 > import random
393 > def sample(population, k):
393 > def sample(population, k):
394 > return sorted(population)[:k]
394 > return sorted(population)[:k]
395 > random.sample = sample
395 > random.sample = sample
396 > EOF
396 > EOF
397
397
398 $ cat >> r1/.hg/hgrc << EOF
398 $ cat >> r1/.hg/hgrc << EOF
399 > [extensions]
399 > [extensions]
400 > unrandomsample = $TESTTMP/unrandomsample.py
400 > unrandomsample = $TESTTMP/unrandomsample.py
401 > EOF
401 > EOF
402
402
403 $ hg -R r1 outgoing r2 -T'{rev} ' --config extensions.blackbox=
403 $ hg -R r1 outgoing r2 -T'{rev} ' --config extensions.blackbox=
404 comparing with r2
404 comparing with r2
405 searching for changes
405 searching for changes
406 101 102 103 104 105 106 107 108 109 110 (no-eol)
406 101 102 103 104 105 106 107 108 109 110 (no-eol)
407 $ hg -R r1 --config extensions.blackbox= blackbox
407 $ hg -R r1 --config extensions.blackbox= blackbox
408 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> serve --cmdserver chgunix * (glob) (chg !)
408 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> serve --cmdserver chgunix * (glob) (chg !)
409 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> outgoing r2 *-T{rev} * (glob)
409 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> outgoing r2 *-T{rev} * (glob)
410 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> found 101 common and 1 unknown server heads, 2 roundtrips in *.????s (glob)
410 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> found 101 common and 1 unknown server heads, 2 roundtrips in *.????s (glob)
411 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* exited 0 after *.?? seconds (glob)
411 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> -R r1 outgoing r2 *-T{rev} * --config *extensions.blackbox=* exited 0 after *.?? seconds (glob)
412 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> blackbox (glob)
412 * @5d0b986a083e0d91f116de4691e2aaa54d5bbec0 (*)> blackbox (glob)
413 $ cd ..
413 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now