Mercurial > public > mercurial-scm > hg
comparison mercurial/dispatch.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | 86e4daa2d54c |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
91 try: | 91 try: |
92 func(*args, **kwargs) | 92 func(*args, **kwargs) |
93 except: # re-raises below | 93 except: # re-raises below |
94 if exc is None: | 94 if exc is None: |
95 exc = sys.exc_info()[1] | 95 exc = sys.exc_info()[1] |
96 self.ui.warn('error in exit handlers:\n') | 96 self.ui.warn(b'error in exit handlers:\n') |
97 self.ui.traceback(force=True) | 97 self.ui.traceback(force=True) |
98 finally: | 98 finally: |
99 if exc is not None: | 99 if exc is not None: |
100 raise exc | 100 raise exc |
101 | 101 |
102 | 102 |
103 def run(): | 103 def run(): |
104 "run the command in sys.argv" | 104 b"run the command in sys.argv" |
105 initstdio() | 105 initstdio() |
106 with tracing.log('parse args into request'): | 106 with tracing.log(b'parse args into request'): |
107 req = request(pycompat.sysargv[1:]) | 107 req = request(pycompat.sysargv[1:]) |
108 err = None | 108 err = None |
109 try: | 109 try: |
110 status = dispatch(req) | 110 status = dispatch(req) |
111 except error.StdioError as e: | 111 except error.StdioError as e: |
112 err = e | 112 err = e |
113 status = -1 | 113 status = -1 |
114 | 114 |
115 # In all cases we try to flush stdio streams. | 115 # In all cases we try to flush stdio streams. |
116 if util.safehasattr(req.ui, 'fout'): | 116 if util.safehasattr(req.ui, b'fout'): |
117 try: | 117 try: |
118 req.ui.fout.flush() | 118 req.ui.fout.flush() |
119 except IOError as e: | 119 except IOError as e: |
120 err = e | 120 err = e |
121 status = -1 | 121 status = -1 |
122 | 122 |
123 if util.safehasattr(req.ui, 'ferr'): | 123 if util.safehasattr(req.ui, b'ferr'): |
124 try: | 124 try: |
125 if err is not None and err.errno != errno.EPIPE: | 125 if err is not None and err.errno != errno.EPIPE: |
126 req.ui.ferr.write( | 126 req.ui.ferr.write( |
127 'abort: %s\n' % encoding.strtolocal(err.strerror) | 127 b'abort: %s\n' % encoding.strtolocal(err.strerror) |
128 ) | 128 ) |
129 req.ui.ferr.flush() | 129 req.ui.ferr.flush() |
130 # There's not much we can do about an I/O error here. So (possibly) | 130 # There's not much we can do about an I/O error here. So (possibly) |
131 # change the status code and move on. | 131 # change the status code and move on. |
132 except IOError: | 132 except IOError: |
176 return [s for s in symbols if sim(s) > 0.6] | 176 return [s for s in symbols if sim(s) > 0.6] |
177 | 177 |
178 | 178 |
179 def _reportsimilar(write, similar): | 179 def _reportsimilar(write, similar): |
180 if len(similar) == 1: | 180 if len(similar) == 1: |
181 write(_("(did you mean %s?)\n") % similar[0]) | 181 write(_(b"(did you mean %s?)\n") % similar[0]) |
182 elif similar: | 182 elif similar: |
183 ss = ", ".join(sorted(similar)) | 183 ss = b", ".join(sorted(similar)) |
184 write(_("(did you mean one of %s?)\n") % ss) | 184 write(_(b"(did you mean one of %s?)\n") % ss) |
185 | 185 |
186 | 186 |
187 def _formatparse(write, inst): | 187 def _formatparse(write, inst): |
188 similar = [] | 188 similar = [] |
189 if isinstance(inst, error.UnknownIdentifier): | 189 if isinstance(inst, error.UnknownIdentifier): |
190 # make sure to check fileset first, as revset can invoke fileset | 190 # make sure to check fileset first, as revset can invoke fileset |
191 similar = _getsimilar(inst.symbols, inst.function) | 191 similar = _getsimilar(inst.symbols, inst.function) |
192 if len(inst.args) > 1: | 192 if len(inst.args) > 1: |
193 write( | 193 write( |
194 _("hg: parse error at %s: %s\n") | 194 _(b"hg: parse error at %s: %s\n") |
195 % (pycompat.bytestr(inst.args[1]), inst.args[0]) | 195 % (pycompat.bytestr(inst.args[1]), inst.args[0]) |
196 ) | 196 ) |
197 if inst.args[0].startswith(' '): | 197 if inst.args[0].startswith(b' '): |
198 write(_("unexpected leading whitespace\n")) | 198 write(_(b"unexpected leading whitespace\n")) |
199 else: | 199 else: |
200 write(_("hg: parse error: %s\n") % inst.args[0]) | 200 write(_(b"hg: parse error: %s\n") % inst.args[0]) |
201 _reportsimilar(write, similar) | 201 _reportsimilar(write, similar) |
202 if inst.hint: | 202 if inst.hint: |
203 write(_("(%s)\n") % inst.hint) | 203 write(_(b"(%s)\n") % inst.hint) |
204 | 204 |
205 | 205 |
206 def _formatargs(args): | 206 def _formatargs(args): |
207 return ' '.join(procutil.shellquote(a) for a in args) | 207 return b' '.join(procutil.shellquote(a) for a in args) |
208 | 208 |
209 | 209 |
210 def dispatch(req): | 210 def dispatch(req): |
211 """run the command specified in req.args; returns an integer status code""" | 211 """run the command specified in req.args; returns an integer status code""" |
212 with tracing.log('dispatch.dispatch'): | 212 with tracing.log(b'dispatch.dispatch'): |
213 if req.ferr: | 213 if req.ferr: |
214 ferr = req.ferr | 214 ferr = req.ferr |
215 elif req.ui: | 215 elif req.ui: |
216 ferr = req.ui.ferr | 216 ferr = req.ui.ferr |
217 else: | 217 else: |
219 | 219 |
220 try: | 220 try: |
221 if not req.ui: | 221 if not req.ui: |
222 req.ui = uimod.ui.load() | 222 req.ui = uimod.ui.load() |
223 req.earlyoptions.update(_earlyparseopts(req.ui, req.args)) | 223 req.earlyoptions.update(_earlyparseopts(req.ui, req.args)) |
224 if req.earlyoptions['traceback']: | 224 if req.earlyoptions[b'traceback']: |
225 req.ui.setconfig('ui', 'traceback', 'on', '--traceback') | 225 req.ui.setconfig(b'ui', b'traceback', b'on', b'--traceback') |
226 | 226 |
227 # set ui streams from the request | 227 # set ui streams from the request |
228 if req.fin: | 228 if req.fin: |
229 req.ui.fin = req.fin | 229 req.ui.fin = req.fin |
230 if req.fout: | 230 if req.fout: |
232 if req.ferr: | 232 if req.ferr: |
233 req.ui.ferr = req.ferr | 233 req.ui.ferr = req.ferr |
234 if req.fmsg: | 234 if req.fmsg: |
235 req.ui.fmsg = req.fmsg | 235 req.ui.fmsg = req.fmsg |
236 except error.Abort as inst: | 236 except error.Abort as inst: |
237 ferr.write(_("abort: %s\n") % inst) | 237 ferr.write(_(b"abort: %s\n") % inst) |
238 if inst.hint: | 238 if inst.hint: |
239 ferr.write(_("(%s)\n") % inst.hint) | 239 ferr.write(_(b"(%s)\n") % inst.hint) |
240 return -1 | 240 return -1 |
241 except error.ParseError as inst: | 241 except error.ParseError as inst: |
242 _formatparse(ferr.write, inst) | 242 _formatparse(ferr.write, inst) |
243 return -1 | 243 return -1 |
244 | 244 |
246 starttime = util.timer() | 246 starttime = util.timer() |
247 ret = 1 # default of Python exit code on unhandled exception | 247 ret = 1 # default of Python exit code on unhandled exception |
248 try: | 248 try: |
249 ret = _runcatch(req) or 0 | 249 ret = _runcatch(req) or 0 |
250 except error.ProgrammingError as inst: | 250 except error.ProgrammingError as inst: |
251 req.ui.error(_('** ProgrammingError: %s\n') % inst) | 251 req.ui.error(_(b'** ProgrammingError: %s\n') % inst) |
252 if inst.hint: | 252 if inst.hint: |
253 req.ui.error(_('** (%s)\n') % inst.hint) | 253 req.ui.error(_(b'** (%s)\n') % inst.hint) |
254 raise | 254 raise |
255 except KeyboardInterrupt as inst: | 255 except KeyboardInterrupt as inst: |
256 try: | 256 try: |
257 if isinstance(inst, error.SignalInterrupt): | 257 if isinstance(inst, error.SignalInterrupt): |
258 msg = _("killed!\n") | 258 msg = _(b"killed!\n") |
259 else: | 259 else: |
260 msg = _("interrupted!\n") | 260 msg = _(b"interrupted!\n") |
261 req.ui.error(msg) | 261 req.ui.error(msg) |
262 except error.SignalInterrupt: | 262 except error.SignalInterrupt: |
263 # maybe pager would quit without consuming all the output, and | 263 # maybe pager would quit without consuming all the output, and |
264 # SIGPIPE was raised. we cannot print anything in this case. | 264 # SIGPIPE was raised. we cannot print anything in this case. |
265 pass | 265 pass |
269 ret = -1 | 269 ret = -1 |
270 finally: | 270 finally: |
271 duration = util.timer() - starttime | 271 duration = util.timer() - starttime |
272 req.ui.flush() | 272 req.ui.flush() |
273 if req.ui.logblockedtimes: | 273 if req.ui.logblockedtimes: |
274 req.ui._blockedtimes['command_duration'] = duration * 1000 | 274 req.ui._blockedtimes[b'command_duration'] = duration * 1000 |
275 req.ui.log( | 275 req.ui.log( |
276 'uiblocked', | 276 b'uiblocked', |
277 'ui blocked ms\n', | 277 b'ui blocked ms\n', |
278 **pycompat.strkwargs(req.ui._blockedtimes) | 278 **pycompat.strkwargs(req.ui._blockedtimes) |
279 ) | 279 ) |
280 return_code = ret & 255 | 280 return_code = ret & 255 |
281 req.ui.log( | 281 req.ui.log( |
282 "commandfinish", | 282 b"commandfinish", |
283 "%s exited %d after %0.2f seconds\n", | 283 b"%s exited %d after %0.2f seconds\n", |
284 msg, | 284 msg, |
285 return_code, | 285 return_code, |
286 duration, | 286 duration, |
287 return_code=return_code, | 287 return_code=return_code, |
288 duration=duration, | 288 duration=duration, |
294 ret = ret or -1 | 294 ret = ret or -1 |
295 return ret | 295 return ret |
296 | 296 |
297 | 297 |
298 def _runcatch(req): | 298 def _runcatch(req): |
299 with tracing.log('dispatch._runcatch'): | 299 with tracing.log(b'dispatch._runcatch'): |
300 | 300 |
301 def catchterm(*args): | 301 def catchterm(*args): |
302 raise error.SignalInterrupt | 302 raise error.SignalInterrupt |
303 | 303 |
304 ui = req.ui | 304 ui = req.ui |
305 try: | 305 try: |
306 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM': | 306 for name in b'SIGBREAK', b'SIGHUP', b'SIGTERM': |
307 num = getattr(signal, name, None) | 307 num = getattr(signal, name, None) |
308 if num: | 308 if num: |
309 signal.signal(num, catchterm) | 309 signal.signal(num, catchterm) |
310 except ValueError: | 310 except ValueError: |
311 pass # happens if called in a thread | 311 pass # happens if called in a thread |
328 # Don't handle this here. We know the command is | 328 # Don't handle this here. We know the command is |
329 # invalid, but all we're worried about for now is that | 329 # invalid, but all we're worried about for now is that |
330 # it's not a command that server operators expect to | 330 # it's not a command that server operators expect to |
331 # be safe to offer to users in a sandbox. | 331 # be safe to offer to users in a sandbox. |
332 pass | 332 pass |
333 if realcmd == 'serve' and '--stdio' in cmdargs: | 333 if realcmd == b'serve' and b'--stdio' in cmdargs: |
334 # We want to constrain 'hg serve --stdio' instances pretty | 334 # We want to constrain 'hg serve --stdio' instances pretty |
335 # closely, as many shared-ssh access tools want to grant | 335 # closely, as many shared-ssh access tools want to grant |
336 # access to run *only* 'hg -R $repo serve --stdio'. We | 336 # access to run *only* 'hg -R $repo serve --stdio'. We |
337 # restrict to exactly that set of arguments, and prohibit | 337 # restrict to exactly that set of arguments, and prohibit |
338 # any repo name that starts with '--' to prevent | 338 # any repo name that starts with '--' to prevent |
339 # shenanigans wherein a user does something like pass | 339 # shenanigans wherein a user does something like pass |
340 # --debugger or --config=ui.debugger=1 as a repo | 340 # --debugger or --config=ui.debugger=1 as a repo |
341 # name. This used to actually run the debugger. | 341 # name. This used to actually run the debugger. |
342 if ( | 342 if ( |
343 len(req.args) != 4 | 343 len(req.args) != 4 |
344 or req.args[0] != '-R' | 344 or req.args[0] != b'-R' |
345 or req.args[1].startswith('--') | 345 or req.args[1].startswith(b'--') |
346 or req.args[2] != 'serve' | 346 or req.args[2] != b'serve' |
347 or req.args[3] != '--stdio' | 347 or req.args[3] != b'--stdio' |
348 ): | 348 ): |
349 raise error.Abort( | 349 raise error.Abort( |
350 _('potentially unsafe serve --stdio invocation: %s') | 350 _(b'potentially unsafe serve --stdio invocation: %s') |
351 % (stringutil.pprint(req.args),) | 351 % (stringutil.pprint(req.args),) |
352 ) | 352 ) |
353 | 353 |
354 try: | 354 try: |
355 debugger = 'pdb' | 355 debugger = b'pdb' |
356 debugtrace = {'pdb': pdb.set_trace} | 356 debugtrace = {b'pdb': pdb.set_trace} |
357 debugmortem = {'pdb': pdb.post_mortem} | 357 debugmortem = {b'pdb': pdb.post_mortem} |
358 | 358 |
359 # read --config before doing anything else | 359 # read --config before doing anything else |
360 # (e.g. to change trust settings for reading .hg/hgrc) | 360 # (e.g. to change trust settings for reading .hg/hgrc) |
361 cfgs = _parseconfig(req.ui, req.earlyoptions['config']) | 361 cfgs = _parseconfig(req.ui, req.earlyoptions[b'config']) |
362 | 362 |
363 if req.repo: | 363 if req.repo: |
364 # copy configs that were passed on the cmdline (--config) to | 364 # copy configs that were passed on the cmdline (--config) to |
365 # the repo ui | 365 # the repo ui |
366 for sec, name, val in cfgs: | 366 for sec, name, val in cfgs: |
367 req.repo.ui.setconfig(sec, name, val, source='--config') | 367 req.repo.ui.setconfig( |
368 sec, name, val, source=b'--config' | |
369 ) | |
368 | 370 |
369 # developer config: ui.debugger | 371 # developer config: ui.debugger |
370 debugger = ui.config("ui", "debugger") | 372 debugger = ui.config(b"ui", b"debugger") |
371 debugmod = pdb | 373 debugmod = pdb |
372 if not debugger or ui.plain(): | 374 if not debugger or ui.plain(): |
373 # if we are in HGPLAIN mode, then disable custom debugging | 375 # if we are in HGPLAIN mode, then disable custom debugging |
374 debugger = 'pdb' | 376 debugger = b'pdb' |
375 elif req.earlyoptions['debugger']: | 377 elif req.earlyoptions[b'debugger']: |
376 # This import can be slow for fancy debuggers, so only | 378 # This import can be slow for fancy debuggers, so only |
377 # do it when absolutely necessary, i.e. when actual | 379 # do it when absolutely necessary, i.e. when actual |
378 # debugging has been requested | 380 # debugging has been requested |
379 with demandimport.deactivated(): | 381 with demandimport.deactivated(): |
380 try: | 382 try: |
384 | 386 |
385 debugtrace[debugger] = debugmod.set_trace | 387 debugtrace[debugger] = debugmod.set_trace |
386 debugmortem[debugger] = debugmod.post_mortem | 388 debugmortem[debugger] = debugmod.post_mortem |
387 | 389 |
388 # enter the debugger before command execution | 390 # enter the debugger before command execution |
389 if req.earlyoptions['debugger']: | 391 if req.earlyoptions[b'debugger']: |
390 ui.warn( | 392 ui.warn( |
391 _( | 393 _( |
392 "entering debugger - " | 394 b"entering debugger - " |
393 "type c to continue starting hg or h for help\n" | 395 b"type c to continue starting hg or h for help\n" |
394 ) | 396 ) |
395 ) | 397 ) |
396 | 398 |
397 if ( | 399 if ( |
398 debugger != 'pdb' | 400 debugger != b'pdb' |
399 and debugtrace[debugger] == debugtrace['pdb'] | 401 and debugtrace[debugger] == debugtrace[b'pdb'] |
400 ): | 402 ): |
401 ui.warn( | 403 ui.warn( |
402 _( | 404 _( |
403 "%s debugger specified " | 405 b"%s debugger specified " |
404 "but its module was not found\n" | 406 b"but its module was not found\n" |
405 ) | 407 ) |
406 % debugger | 408 % debugger |
407 ) | 409 ) |
408 with demandimport.deactivated(): | 410 with demandimport.deactivated(): |
409 debugtrace[debugger]() | 411 debugtrace[debugger]() |
411 return _dispatch(req) | 413 return _dispatch(req) |
412 finally: | 414 finally: |
413 ui.flush() | 415 ui.flush() |
414 except: # re-raises | 416 except: # re-raises |
415 # enter the debugger when we hit an exception | 417 # enter the debugger when we hit an exception |
416 if req.earlyoptions['debugger']: | 418 if req.earlyoptions[b'debugger']: |
417 traceback.print_exc() | 419 traceback.print_exc() |
418 debugmortem[debugger](sys.exc_info()[2]) | 420 debugmortem[debugger](sys.exc_info()[2]) |
419 raise | 421 raise |
420 | 422 |
421 return _callcatch(ui, _runcatchfunc) | 423 return _callcatch(ui, _runcatchfunc) |
428 """ | 430 """ |
429 try: | 431 try: |
430 return scmutil.callcatch(ui, func) | 432 return scmutil.callcatch(ui, func) |
431 except error.AmbiguousCommand as inst: | 433 except error.AmbiguousCommand as inst: |
432 ui.warn( | 434 ui.warn( |
433 _("hg: command '%s' is ambiguous:\n %s\n") | 435 _(b"hg: command '%s' is ambiguous:\n %s\n") |
434 % (inst.args[0], " ".join(inst.args[1])) | 436 % (inst.args[0], b" ".join(inst.args[1])) |
435 ) | 437 ) |
436 except error.CommandError as inst: | 438 except error.CommandError as inst: |
437 if inst.args[0]: | 439 if inst.args[0]: |
438 ui.pager('help') | 440 ui.pager(b'help') |
439 msgbytes = pycompat.bytestr(inst.args[1]) | 441 msgbytes = pycompat.bytestr(inst.args[1]) |
440 ui.warn(_("hg %s: %s\n") % (inst.args[0], msgbytes)) | 442 ui.warn(_(b"hg %s: %s\n") % (inst.args[0], msgbytes)) |
441 commands.help_(ui, inst.args[0], full=False, command=True) | 443 commands.help_(ui, inst.args[0], full=False, command=True) |
442 else: | 444 else: |
443 ui.warn(_("hg: %s\n") % inst.args[1]) | 445 ui.warn(_(b"hg: %s\n") % inst.args[1]) |
444 ui.warn(_("(use 'hg help -v' for a list of global options)\n")) | 446 ui.warn(_(b"(use 'hg help -v' for a list of global options)\n")) |
445 except error.ParseError as inst: | 447 except error.ParseError as inst: |
446 _formatparse(ui.warn, inst) | 448 _formatparse(ui.warn, inst) |
447 return -1 | 449 return -1 |
448 except error.UnknownCommand as inst: | 450 except error.UnknownCommand as inst: |
449 nocmdmsg = _("hg: unknown command '%s'\n") % inst.args[0] | 451 nocmdmsg = _(b"hg: unknown command '%s'\n") % inst.args[0] |
450 try: | 452 try: |
451 # check if the command is in a disabled extension | 453 # check if the command is in a disabled extension |
452 # (but don't check for extensions themselves) | 454 # (but don't check for extensions themselves) |
453 formatted = help.formattedhelp( | 455 formatted = help.formattedhelp( |
454 ui, commands, inst.args[0], unknowncmd=True | 456 ui, commands, inst.args[0], unknowncmd=True |
463 ui.warn(nocmdmsg) | 465 ui.warn(nocmdmsg) |
464 _reportsimilar(ui.warn, sim) | 466 _reportsimilar(ui.warn, sim) |
465 suggested = True | 467 suggested = True |
466 if not suggested: | 468 if not suggested: |
467 ui.warn(nocmdmsg) | 469 ui.warn(nocmdmsg) |
468 ui.warn(_("(use 'hg help' for a list of commands)\n")) | 470 ui.warn(_(b"(use 'hg help' for a list of commands)\n")) |
469 except IOError: | 471 except IOError: |
470 raise | 472 raise |
471 except KeyboardInterrupt: | 473 except KeyboardInterrupt: |
472 raise | 474 raise |
473 except: # probably re-raises | 475 except: # probably re-raises |
478 | 480 |
479 | 481 |
480 def aliasargs(fn, givenargs): | 482 def aliasargs(fn, givenargs): |
481 args = [] | 483 args = [] |
482 # only care about alias 'args', ignore 'args' set by extensions.wrapfunction | 484 # only care about alias 'args', ignore 'args' set by extensions.wrapfunction |
483 if not util.safehasattr(fn, '_origfunc'): | 485 if not util.safehasattr(fn, b'_origfunc'): |
484 args = getattr(fn, 'args', args) | 486 args = getattr(fn, 'args', args) |
485 if args: | 487 if args: |
486 cmd = ' '.join(map(procutil.shellquote, args)) | 488 cmd = b' '.join(map(procutil.shellquote, args)) |
487 | 489 |
488 nums = [] | 490 nums = [] |
489 | 491 |
490 def replacer(m): | 492 def replacer(m): |
491 num = int(m.group(1)) - 1 | 493 num = int(m.group(1)) - 1 |
492 nums.append(num) | 494 nums.append(num) |
493 if num < len(givenargs): | 495 if num < len(givenargs): |
494 return givenargs[num] | 496 return givenargs[num] |
495 raise error.Abort(_('too few arguments for command alias')) | 497 raise error.Abort(_(b'too few arguments for command alias')) |
496 | 498 |
497 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd) | 499 cmd = re.sub(br'\$(\d+|\$)', replacer, cmd) |
498 givenargs = [x for i, x in enumerate(givenargs) if i not in nums] | 500 givenargs = [x for i, x in enumerate(givenargs) if i not in nums] |
499 args = pycompat.shlexsplit(cmd) | 501 args = pycompat.shlexsplit(cmd) |
500 return args + givenargs | 502 return args + givenargs |
505 | 507 |
506 This also handles $0, $@ and "$@". | 508 This also handles $0, $@ and "$@". |
507 ''' | 509 ''' |
508 # util.interpolate can't deal with "$@" (with quotes) because it's only | 510 # util.interpolate can't deal with "$@" (with quotes) because it's only |
509 # built to match prefix + patterns. | 511 # built to match prefix + patterns. |
510 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args)) | 512 replacemap = dict((b'$%d' % (i + 1), arg) for i, arg in enumerate(args)) |
511 replacemap['$0'] = name | 513 replacemap[b'$0'] = name |
512 replacemap['$$'] = '$' | 514 replacemap[b'$$'] = b'$' |
513 replacemap['$@'] = ' '.join(args) | 515 replacemap[b'$@'] = b' '.join(args) |
514 # Typical Unix shells interpolate "$@" (with quotes) as all the positional | 516 # Typical Unix shells interpolate "$@" (with quotes) as all the positional |
515 # parameters, separated out into words. Emulate the same behavior here by | 517 # parameters, separated out into words. Emulate the same behavior here by |
516 # quoting the arguments individually. POSIX shells will then typically | 518 # quoting the arguments individually. POSIX shells will then typically |
517 # tokenize each argument into exactly one word. | 519 # tokenize each argument into exactly one word. |
518 replacemap['"$@"'] = ' '.join(procutil.shellquote(arg) for arg in args) | 520 replacemap[b'"$@"'] = b' '.join(procutil.shellquote(arg) for arg in args) |
519 # escape '\$' for regex | 521 # escape '\$' for regex |
520 regex = '|'.join(replacemap.keys()).replace('$', br'\$') | 522 regex = b'|'.join(replacemap.keys()).replace(b'$', br'\$') |
521 r = re.compile(regex) | 523 r = re.compile(regex) |
522 return r.sub(lambda x: replacemap[x.group()], cmd) | 524 return r.sub(lambda x: replacemap[x.group()], cmd) |
523 | 525 |
524 | 526 |
525 class cmdalias(object): | 527 class cmdalias(object): |
526 def __init__(self, ui, name, definition, cmdtable, source): | 528 def __init__(self, ui, name, definition, cmdtable, source): |
527 self.name = self.cmd = name | 529 self.name = self.cmd = name |
528 self.cmdname = '' | 530 self.cmdname = b'' |
529 self.definition = definition | 531 self.definition = definition |
530 self.fn = None | 532 self.fn = None |
531 self.givenargs = [] | 533 self.givenargs = [] |
532 self.opts = [] | 534 self.opts = [] |
533 self.help = '' | 535 self.help = b'' |
534 self.badalias = None | 536 self.badalias = None |
535 self.unknowncmd = False | 537 self.unknowncmd = False |
536 self.source = source | 538 self.source = source |
537 | 539 |
538 try: | 540 try: |
544 self.shadows = True | 546 self.shadows = True |
545 except error.UnknownCommand: | 547 except error.UnknownCommand: |
546 self.shadows = False | 548 self.shadows = False |
547 | 549 |
548 if not self.definition: | 550 if not self.definition: |
549 self.badalias = _("no definition for alias '%s'") % self.name | 551 self.badalias = _(b"no definition for alias '%s'") % self.name |
550 return | 552 return |
551 | 553 |
552 if self.definition.startswith('!'): | 554 if self.definition.startswith(b'!'): |
553 shdef = self.definition[1:] | 555 shdef = self.definition[1:] |
554 self.shell = True | 556 self.shell = True |
555 | 557 |
556 def fn(ui, *args): | 558 def fn(ui, *args): |
557 env = {'HG_ARGS': ' '.join((self.name,) + args)} | 559 env = {b'HG_ARGS': b' '.join((self.name,) + args)} |
558 | 560 |
559 def _checkvar(m): | 561 def _checkvar(m): |
560 if m.groups()[0] == '$': | 562 if m.groups()[0] == b'$': |
561 return m.group() | 563 return m.group() |
562 elif int(m.groups()[0]) <= len(args): | 564 elif int(m.groups()[0]) <= len(args): |
563 return m.group() | 565 return m.group() |
564 else: | 566 else: |
565 ui.debug( | 567 ui.debug( |
566 "No argument found for substitution " | 568 b"No argument found for substitution " |
567 "of %i variable in alias '%s' definition.\n" | 569 b"of %i variable in alias '%s' definition.\n" |
568 % (int(m.groups()[0]), self.name) | 570 % (int(m.groups()[0]), self.name) |
569 ) | 571 ) |
570 return '' | 572 return b'' |
571 | 573 |
572 cmd = re.sub(br'\$(\d+|\$)', _checkvar, shdef) | 574 cmd = re.sub(br'\$(\d+|\$)', _checkvar, shdef) |
573 cmd = aliasinterpolate(self.name, args, cmd) | 575 cmd = aliasinterpolate(self.name, args, cmd) |
574 return ui.system( | 576 return ui.system( |
575 cmd, environ=env, blockedtag='alias_%s' % self.name | 577 cmd, environ=env, blockedtag=b'alias_%s' % self.name |
576 ) | 578 ) |
577 | 579 |
578 self.fn = fn | 580 self.fn = fn |
579 self.alias = True | 581 self.alias = True |
580 self._populatehelp(ui, name, shdef, self.fn) | 582 self._populatehelp(ui, name, shdef, self.fn) |
581 return | 583 return |
582 | 584 |
583 try: | 585 try: |
584 args = pycompat.shlexsplit(self.definition) | 586 args = pycompat.shlexsplit(self.definition) |
585 except ValueError as inst: | 587 except ValueError as inst: |
586 self.badalias = _("error in definition for alias '%s': %s") % ( | 588 self.badalias = _(b"error in definition for alias '%s': %s") % ( |
587 self.name, | 589 self.name, |
588 stringutil.forcebytestr(inst), | 590 stringutil.forcebytestr(inst), |
589 ) | 591 ) |
590 return | 592 return |
591 earlyopts, args = _earlysplitopts(args) | 593 earlyopts, args = _earlysplitopts(args) |
592 if earlyopts: | 594 if earlyopts: |
593 self.badalias = _( | 595 self.badalias = _( |
594 "error in definition for alias '%s': %s may " | 596 b"error in definition for alias '%s': %s may " |
595 "only be given on the command line" | 597 b"only be given on the command line" |
596 ) % (self.name, '/'.join(pycompat.ziplist(*earlyopts)[0])) | 598 ) % (self.name, b'/'.join(pycompat.ziplist(*earlyopts)[0])) |
597 return | 599 return |
598 self.cmdname = cmd = args.pop(0) | 600 self.cmdname = cmd = args.pop(0) |
599 self.givenargs = args | 601 self.givenargs = args |
600 | 602 |
601 try: | 603 try: |
608 | 610 |
609 self.alias = True | 611 self.alias = True |
610 self._populatehelp(ui, name, cmd, self.fn, cmdhelp) | 612 self._populatehelp(ui, name, cmd, self.fn, cmdhelp) |
611 | 613 |
612 except error.UnknownCommand: | 614 except error.UnknownCommand: |
613 self.badalias = _("alias '%s' resolves to unknown command '%s'") % ( | 615 self.badalias = _( |
614 self.name, | 616 b"alias '%s' resolves to unknown command '%s'" |
615 cmd, | 617 ) % (self.name, cmd,) |
616 ) | |
617 self.unknowncmd = True | 618 self.unknowncmd = True |
618 except error.AmbiguousCommand: | 619 except error.AmbiguousCommand: |
619 self.badalias = _( | 620 self.badalias = _( |
620 "alias '%s' resolves to ambiguous command '%s'" | 621 b"alias '%s' resolves to ambiguous command '%s'" |
621 ) % (self.name, cmd) | 622 ) % (self.name, cmd) |
622 | 623 |
623 def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None): | 624 def _populatehelp(self, ui, name, cmd, fn, defaulthelp=None): |
624 # confine strings to be passed to i18n.gettext() | 625 # confine strings to be passed to i18n.gettext() |
625 cfg = {} | 626 cfg = {} |
626 for k in ('doc', 'help', 'category'): | 627 for k in (b'doc', b'help', b'category'): |
627 v = ui.config('alias', '%s:%s' % (name, k), None) | 628 v = ui.config(b'alias', b'%s:%s' % (name, k), None) |
628 if v is None: | 629 if v is None: |
629 continue | 630 continue |
630 if not encoding.isasciistr(v): | 631 if not encoding.isasciistr(v): |
631 self.badalias = _( | 632 self.badalias = _( |
632 "non-ASCII character in alias definition " "'%s:%s'" | 633 b"non-ASCII character in alias definition " b"'%s:%s'" |
633 ) % (name, k) | 634 ) % (name, k) |
634 return | 635 return |
635 cfg[k] = v | 636 cfg[k] = v |
636 | 637 |
637 self.help = cfg.get('help', defaulthelp or '') | 638 self.help = cfg.get(b'help', defaulthelp or b'') |
638 if self.help and self.help.startswith("hg " + cmd): | 639 if self.help and self.help.startswith(b"hg " + cmd): |
639 # drop prefix in old-style help lines so hg shows the alias | 640 # drop prefix in old-style help lines so hg shows the alias |
640 self.help = self.help[4 + len(cmd) :] | 641 self.help = self.help[4 + len(cmd) :] |
641 | 642 |
642 self.owndoc = 'doc' in cfg | 643 self.owndoc = b'doc' in cfg |
643 doc = cfg.get('doc', pycompat.getdoc(fn)) | 644 doc = cfg.get(b'doc', pycompat.getdoc(fn)) |
644 if doc is not None: | 645 if doc is not None: |
645 doc = pycompat.sysstr(doc) | 646 doc = pycompat.sysstr(doc) |
646 self.__doc__ = doc | 647 self.__doc__ = doc |
647 | 648 |
648 self.helpcategory = cfg.get('category', registrar.command.CATEGORY_NONE) | 649 self.helpcategory = cfg.get( |
650 b'category', registrar.command.CATEGORY_NONE | |
651 ) | |
649 | 652 |
650 @property | 653 @property |
651 def args(self): | 654 def args(self): |
652 args = pycompat.maplist(util.expandpath, self.givenargs) | 655 args = pycompat.maplist(util.expandpath, self.givenargs) |
653 return aliasargs(self.fn, args) | 656 return aliasargs(self.fn, args) |
659 r'optionalrepo': False, | 662 r'optionalrepo': False, |
660 r'inferrepo': False, | 663 r'inferrepo': False, |
661 } | 664 } |
662 if name not in adefaults: | 665 if name not in adefaults: |
663 raise AttributeError(name) | 666 raise AttributeError(name) |
664 if self.badalias or util.safehasattr(self, 'shell'): | 667 if self.badalias or util.safehasattr(self, b'shell'): |
665 return adefaults[name] | 668 return adefaults[name] |
666 return getattr(self.fn, name) | 669 return getattr(self.fn, name) |
667 | 670 |
668 def __call__(self, ui, *args, **opts): | 671 def __call__(self, ui, *args, **opts): |
669 if self.badalias: | 672 if self.badalias: |
670 hint = None | 673 hint = None |
671 if self.unknowncmd: | 674 if self.unknowncmd: |
672 try: | 675 try: |
673 # check if the command is in a disabled extension | 676 # check if the command is in a disabled extension |
674 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2] | 677 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2] |
675 hint = _("'%s' is provided by '%s' extension") % (cmd, ext) | 678 hint = _(b"'%s' is provided by '%s' extension") % (cmd, ext) |
676 except error.UnknownCommand: | 679 except error.UnknownCommand: |
677 pass | 680 pass |
678 raise error.Abort(self.badalias, hint=hint) | 681 raise error.Abort(self.badalias, hint=hint) |
679 if self.shadows: | 682 if self.shadows: |
680 ui.debug( | 683 ui.debug( |
681 "alias '%s' shadows command '%s'\n" % (self.name, self.cmdname) | 684 b"alias '%s' shadows command '%s'\n" % (self.name, self.cmdname) |
682 ) | 685 ) |
683 | 686 |
684 ui.log( | 687 ui.log( |
685 'commandalias', | 688 b'commandalias', |
686 "alias '%s' expands to '%s'\n", | 689 b"alias '%s' expands to '%s'\n", |
687 self.name, | 690 self.name, |
688 self.definition, | 691 self.definition, |
689 ) | 692 ) |
690 if util.safehasattr(self, 'shell'): | 693 if util.safehasattr(self, b'shell'): |
691 return self.fn(ui, *args, **opts) | 694 return self.fn(ui, *args, **opts) |
692 else: | 695 else: |
693 try: | 696 try: |
694 return util.checksignature(self.fn)(ui, *args, **opts) | 697 return util.checksignature(self.fn)(ui, *args, **opts) |
695 except error.SignatureError: | 698 except error.SignatureError: |
696 args = ' '.join([self.cmdname] + self.args) | 699 args = b' '.join([self.cmdname] + self.args) |
697 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args)) | 700 ui.debug(b"alias '%s' expands to '%s'\n" % (self.name, args)) |
698 raise | 701 raise |
699 | 702 |
700 | 703 |
701 class lazyaliasentry(object): | 704 class lazyaliasentry(object): |
702 """like a typical command entry (func, opts, help), but is lazy""" | 705 """like a typical command entry (func, opts, help), but is lazy""" |
736 | 739 |
737 def addaliases(ui, cmdtable): | 740 def addaliases(ui, cmdtable): |
738 # aliases are processed after extensions have been loaded, so they | 741 # aliases are processed after extensions have been loaded, so they |
739 # may use extension commands. Aliases can also use other alias definitions, | 742 # may use extension commands. Aliases can also use other alias definitions, |
740 # but only if they have been defined prior to the current definition. | 743 # but only if they have been defined prior to the current definition. |
741 for alias, definition in ui.configitems('alias', ignoresub=True): | 744 for alias, definition in ui.configitems(b'alias', ignoresub=True): |
742 try: | 745 try: |
743 if cmdtable[alias].definition == definition: | 746 if cmdtable[alias].definition == definition: |
744 continue | 747 continue |
745 except (KeyError, AttributeError): | 748 except (KeyError, AttributeError): |
746 # definition might not exist or it might not be a cmdalias | 749 # definition might not exist or it might not be a cmdalias |
747 pass | 750 pass |
748 | 751 |
749 source = ui.configsource('alias', alias) | 752 source = ui.configsource(b'alias', alias) |
750 entry = lazyaliasentry(ui, alias, definition, cmdtable, source) | 753 entry = lazyaliasentry(ui, alias, definition, cmdtable, source) |
751 cmdtable[alias] = entry | 754 cmdtable[alias] = entry |
752 | 755 |
753 | 756 |
754 def _parse(ui, args): | 757 def _parse(ui, args): |
761 raise error.CommandError(None, stringutil.forcebytestr(inst)) | 764 raise error.CommandError(None, stringutil.forcebytestr(inst)) |
762 | 765 |
763 if args: | 766 if args: |
764 cmd, args = args[0], args[1:] | 767 cmd, args = args[0], args[1:] |
765 aliases, entry = cmdutil.findcmd( | 768 aliases, entry = cmdutil.findcmd( |
766 cmd, commands.table, ui.configbool("ui", "strict") | 769 cmd, commands.table, ui.configbool(b"ui", b"strict") |
767 ) | 770 ) |
768 cmd = aliases[0] | 771 cmd = aliases[0] |
769 args = aliasargs(entry[0], args) | 772 args = aliasargs(entry[0], args) |
770 defaults = ui.config("defaults", cmd) | 773 defaults = ui.config(b"defaults", cmd) |
771 if defaults: | 774 if defaults: |
772 args = ( | 775 args = ( |
773 pycompat.maplist(util.expandpath, pycompat.shlexsplit(defaults)) | 776 pycompat.maplist(util.expandpath, pycompat.shlexsplit(defaults)) |
774 + args | 777 + args |
775 ) | 778 ) |
800 """parse the --config options from the command line""" | 803 """parse the --config options from the command line""" |
801 configs = [] | 804 configs = [] |
802 | 805 |
803 for cfg in config: | 806 for cfg in config: |
804 try: | 807 try: |
805 name, value = [cfgelem.strip() for cfgelem in cfg.split('=', 1)] | 808 name, value = [cfgelem.strip() for cfgelem in cfg.split(b'=', 1)] |
806 section, name = name.split('.', 1) | 809 section, name = name.split(b'.', 1) |
807 if not section or not name: | 810 if not section or not name: |
808 raise IndexError | 811 raise IndexError |
809 ui.setconfig(section, name, value, '--config') | 812 ui.setconfig(section, name, value, b'--config') |
810 configs.append((section, name, value)) | 813 configs.append((section, name, value)) |
811 except (IndexError, ValueError): | 814 except (IndexError, ValueError): |
812 raise error.Abort( | 815 raise error.Abort( |
813 _( | 816 _( |
814 'malformed --config option: %r ' | 817 b'malformed --config option: %r ' |
815 '(use --config section.name=value)' | 818 b'(use --config section.name=value)' |
816 ) | 819 ) |
817 % pycompat.bytestr(cfg) | 820 % pycompat.bytestr(cfg) |
818 ) | 821 ) |
819 | 822 |
820 return configs | 823 return configs |
824 options = {} | 827 options = {} |
825 fancyopts.fancyopts( | 828 fancyopts.fancyopts( |
826 args, | 829 args, |
827 commands.globalopts, | 830 commands.globalopts, |
828 options, | 831 options, |
829 gnu=not ui.plain('strictflags'), | 832 gnu=not ui.plain(b'strictflags'), |
830 early=True, | 833 early=True, |
831 optaliases={'repository': ['repo']}, | 834 optaliases={b'repository': [b'repo']}, |
832 ) | 835 ) |
833 return options | 836 return options |
834 | 837 |
835 | 838 |
836 def _earlysplitopts(args): | 839 def _earlysplitopts(args): |
837 """Split args into a list of possible early options and remainder args""" | 840 """Split args into a list of possible early options and remainder args""" |
838 shortoptions = 'R:' | 841 shortoptions = b'R:' |
839 # TODO: perhaps 'debugger' should be included | 842 # TODO: perhaps 'debugger' should be included |
840 longoptions = ['cwd=', 'repository=', 'repo=', 'config='] | 843 longoptions = [b'cwd=', b'repository=', b'repo=', b'config='] |
841 return fancyopts.earlygetopt( | 844 return fancyopts.earlygetopt( |
842 args, shortoptions, longoptions, gnu=True, keepsep=True | 845 args, shortoptions, longoptions, gnu=True, keepsep=True |
843 ) | 846 ) |
844 | 847 |
845 | 848 |
846 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): | 849 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): |
847 # run pre-hook, and abort if it fails | 850 # run pre-hook, and abort if it fails |
848 hook.hook( | 851 hook.hook( |
849 lui, | 852 lui, |
850 repo, | 853 repo, |
851 "pre-%s" % cmd, | 854 b"pre-%s" % cmd, |
852 True, | 855 True, |
853 args=" ".join(fullargs), | 856 args=b" ".join(fullargs), |
854 pats=cmdpats, | 857 pats=cmdpats, |
855 opts=cmdoptions, | 858 opts=cmdoptions, |
856 ) | 859 ) |
857 try: | 860 try: |
858 ret = _runcommand(ui, options, cmd, d) | 861 ret = _runcommand(ui, options, cmd, d) |
859 # run post-hook, passing command result | 862 # run post-hook, passing command result |
860 hook.hook( | 863 hook.hook( |
861 lui, | 864 lui, |
862 repo, | 865 repo, |
863 "post-%s" % cmd, | 866 b"post-%s" % cmd, |
864 False, | 867 False, |
865 args=" ".join(fullargs), | 868 args=b" ".join(fullargs), |
866 result=ret, | 869 result=ret, |
867 pats=cmdpats, | 870 pats=cmdpats, |
868 opts=cmdoptions, | 871 opts=cmdoptions, |
869 ) | 872 ) |
870 except Exception: | 873 except Exception: |
871 # run failure hook and re-raise | 874 # run failure hook and re-raise |
872 hook.hook( | 875 hook.hook( |
873 lui, | 876 lui, |
874 repo, | 877 repo, |
875 "fail-%s" % cmd, | 878 b"fail-%s" % cmd, |
876 False, | 879 False, |
877 args=" ".join(fullargs), | 880 args=b" ".join(fullargs), |
878 pats=cmdpats, | 881 pats=cmdpats, |
879 opts=cmdoptions, | 882 opts=cmdoptions, |
880 ) | 883 ) |
881 raise | 884 raise |
882 return ret | 885 return ret |
890 if wd is None: | 893 if wd is None: |
891 try: | 894 try: |
892 wd = encoding.getcwd() | 895 wd = encoding.getcwd() |
893 except OSError as e: | 896 except OSError as e: |
894 raise error.Abort( | 897 raise error.Abort( |
895 _("error getting current working directory: %s") | 898 _(b"error getting current working directory: %s") |
896 % encoding.strtolocal(e.strerror) | 899 % encoding.strtolocal(e.strerror) |
897 ) | 900 ) |
898 path = cmdutil.findrepo(wd) or "" | 901 path = cmdutil.findrepo(wd) or b"" |
899 if not path: | 902 if not path: |
900 lui = ui | 903 lui = ui |
901 else: | 904 else: |
902 lui = ui.copy() | 905 lui = ui.copy() |
903 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path) | 906 lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) |
904 | 907 |
905 if rpath: | 908 if rpath: |
906 path = lui.expandpath(rpath) | 909 path = lui.expandpath(rpath) |
907 lui = ui.copy() | 910 lui = ui.copy() |
908 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path) | 911 lui.readconfig(os.path.join(path, b".hg", b"hgrc"), path) |
909 | 912 |
910 return path, lui | 913 return path, lui |
911 | 914 |
912 | 915 |
913 def _checkshellalias(lui, ui, args): | 916 def _checkshellalias(lui, ui, args): |
924 | 927 |
925 cmdtable = commands.table | 928 cmdtable = commands.table |
926 | 929 |
927 cmd = args[0] | 930 cmd = args[0] |
928 try: | 931 try: |
929 strict = ui.configbool("ui", "strict") | 932 strict = ui.configbool(b"ui", b"strict") |
930 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict) | 933 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict) |
931 except (error.AmbiguousCommand, error.UnknownCommand): | 934 except (error.AmbiguousCommand, error.UnknownCommand): |
932 return | 935 return |
933 | 936 |
934 cmd = aliases[0] | 937 cmd = aliases[0] |
935 fn = entry[0] | 938 fn = entry[0] |
936 | 939 |
937 if cmd and util.safehasattr(fn, 'shell'): | 940 if cmd and util.safehasattr(fn, b'shell'): |
938 # shell alias shouldn't receive early options which are consumed by hg | 941 # shell alias shouldn't receive early options which are consumed by hg |
939 _earlyopts, args = _earlysplitopts(args) | 942 _earlyopts, args = _earlysplitopts(args) |
940 d = lambda: fn(ui, *args[1:]) | 943 d = lambda: fn(ui, *args[1:]) |
941 return lambda: runcommand( | 944 return lambda: runcommand( |
942 lui, None, cmd, args[:1], ui, options, d, [], {} | 945 lui, None, cmd, args[:1], ui, options, d, [], {} |
946 def _dispatch(req): | 949 def _dispatch(req): |
947 args = req.args | 950 args = req.args |
948 ui = req.ui | 951 ui = req.ui |
949 | 952 |
950 # check for cwd | 953 # check for cwd |
951 cwd = req.earlyoptions['cwd'] | 954 cwd = req.earlyoptions[b'cwd'] |
952 if cwd: | 955 if cwd: |
953 os.chdir(cwd) | 956 os.chdir(cwd) |
954 | 957 |
955 rpath = req.earlyoptions['repository'] | 958 rpath = req.earlyoptions[b'repository'] |
956 path, lui = _getlocal(ui, rpath) | 959 path, lui = _getlocal(ui, rpath) |
957 | 960 |
958 uis = {ui, lui} | 961 uis = {ui, lui} |
959 | 962 |
960 if req.repo: | 963 if req.repo: |
961 uis.add(req.repo.ui) | 964 uis.add(req.repo.ui) |
962 | 965 |
963 if ( | 966 if ( |
964 req.earlyoptions['verbose'] | 967 req.earlyoptions[b'verbose'] |
965 or req.earlyoptions['debug'] | 968 or req.earlyoptions[b'debug'] |
966 or req.earlyoptions['quiet'] | 969 or req.earlyoptions[b'quiet'] |
967 ): | 970 ): |
968 for opt in ('verbose', 'debug', 'quiet'): | 971 for opt in (b'verbose', b'debug', b'quiet'): |
969 val = pycompat.bytestr(bool(req.earlyoptions[opt])) | 972 val = pycompat.bytestr(bool(req.earlyoptions[opt])) |
970 for ui_ in uis: | 973 for ui_ in uis: |
971 ui_.setconfig('ui', opt, val, '--' + opt) | 974 ui_.setconfig(b'ui', opt, val, b'--' + opt) |
972 | 975 |
973 if req.earlyoptions['profile']: | 976 if req.earlyoptions[b'profile']: |
974 for ui_ in uis: | 977 for ui_ in uis: |
975 ui_.setconfig('profiling', 'enabled', 'true', '--profile') | 978 ui_.setconfig(b'profiling', b'enabled', b'true', b'--profile') |
976 | 979 |
977 profile = lui.configbool('profiling', 'enabled') | 980 profile = lui.configbool(b'profiling', b'enabled') |
978 with profiling.profile(lui, enabled=profile) as profiler: | 981 with profiling.profile(lui, enabled=profile) as profiler: |
979 # Configure extensions in phases: uisetup, extsetup, cmdtable, and | 982 # Configure extensions in phases: uisetup, extsetup, cmdtable, and |
980 # reposetup | 983 # reposetup |
981 extensions.loadall(lui) | 984 extensions.loadall(lui) |
982 # Propagate any changes to lui.__class__ by extensions | 985 # Propagate any changes to lui.__class__ by extensions |
996 for ui_ in uis: | 999 for ui_ in uis: |
997 extensions.populateui(ui_) | 1000 extensions.populateui(ui_) |
998 return shellaliasfn() | 1001 return shellaliasfn() |
999 | 1002 |
1000 # check for fallback encoding | 1003 # check for fallback encoding |
1001 fallback = lui.config('ui', 'fallbackencoding') | 1004 fallback = lui.config(b'ui', b'fallbackencoding') |
1002 if fallback: | 1005 if fallback: |
1003 encoding.fallbackencoding = fallback | 1006 encoding.fallbackencoding = fallback |
1004 | 1007 |
1005 fullargs = args | 1008 fullargs = args |
1006 cmd, func, args, options, cmdoptions = _parse(lui, args) | 1009 cmd, func, args, options, cmdoptions = _parse(lui, args) |
1007 | 1010 |
1008 # store the canonical command name in request object for later access | 1011 # store the canonical command name in request object for later access |
1009 req.canonical_command = cmd | 1012 req.canonical_command = cmd |
1010 | 1013 |
1011 if options["config"] != req.earlyoptions["config"]: | 1014 if options[b"config"] != req.earlyoptions[b"config"]: |
1012 raise error.Abort(_("option --config may not be abbreviated!")) | 1015 raise error.Abort(_(b"option --config may not be abbreviated!")) |
1013 if options["cwd"] != req.earlyoptions["cwd"]: | 1016 if options[b"cwd"] != req.earlyoptions[b"cwd"]: |
1014 raise error.Abort(_("option --cwd may not be abbreviated!")) | 1017 raise error.Abort(_(b"option --cwd may not be abbreviated!")) |
1015 if options["repository"] != req.earlyoptions["repository"]: | 1018 if options[b"repository"] != req.earlyoptions[b"repository"]: |
1016 raise error.Abort( | 1019 raise error.Abort( |
1017 _( | 1020 _( |
1018 "option -R has to be separated from other options (e.g. not " | 1021 b"option -R has to be separated from other options (e.g. not " |
1019 "-qR) and --repository may only be abbreviated as --repo!" | 1022 b"-qR) and --repository may only be abbreviated as --repo!" |
1020 ) | 1023 ) |
1021 ) | 1024 ) |
1022 if options["debugger"] != req.earlyoptions["debugger"]: | 1025 if options[b"debugger"] != req.earlyoptions[b"debugger"]: |
1023 raise error.Abort(_("option --debugger may not be abbreviated!")) | 1026 raise error.Abort(_(b"option --debugger may not be abbreviated!")) |
1024 # don't validate --profile/--traceback, which can be enabled from now | 1027 # don't validate --profile/--traceback, which can be enabled from now |
1025 | 1028 |
1026 if options["encoding"]: | 1029 if options[b"encoding"]: |
1027 encoding.encoding = options["encoding"] | 1030 encoding.encoding = options[b"encoding"] |
1028 if options["encodingmode"]: | 1031 if options[b"encodingmode"]: |
1029 encoding.encodingmode = options["encodingmode"] | 1032 encoding.encodingmode = options[b"encodingmode"] |
1030 if options["time"]: | 1033 if options[b"time"]: |
1031 | 1034 |
1032 def get_times(): | 1035 def get_times(): |
1033 t = os.times() | 1036 t = os.times() |
1034 if t[4] == 0.0: | 1037 if t[4] == 0.0: |
1035 # Windows leaves this as zero, so use time.clock() | 1038 # Windows leaves this as zero, so use time.clock() |
1039 s = get_times() | 1042 s = get_times() |
1040 | 1043 |
1041 def print_time(): | 1044 def print_time(): |
1042 t = get_times() | 1045 t = get_times() |
1043 ui.warn( | 1046 ui.warn( |
1044 _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") | 1047 _(b"time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") |
1045 % ( | 1048 % ( |
1046 t[4] - s[4], | 1049 t[4] - s[4], |
1047 t[0] - s[0], | 1050 t[0] - s[0], |
1048 t[2] - s[2], | 1051 t[2] - s[2], |
1049 t[1] - s[1], | 1052 t[1] - s[1], |
1050 t[3] - s[3], | 1053 t[3] - s[3], |
1051 ) | 1054 ) |
1052 ) | 1055 ) |
1053 | 1056 |
1054 ui.atexit(print_time) | 1057 ui.atexit(print_time) |
1055 if options["profile"]: | 1058 if options[b"profile"]: |
1056 profiler.start() | 1059 profiler.start() |
1057 | 1060 |
1058 # if abbreviated version of this were used, take them in account, now | 1061 # if abbreviated version of this were used, take them in account, now |
1059 if options['verbose'] or options['debug'] or options['quiet']: | 1062 if options[b'verbose'] or options[b'debug'] or options[b'quiet']: |
1060 for opt in ('verbose', 'debug', 'quiet'): | 1063 for opt in (b'verbose', b'debug', b'quiet'): |
1061 if options[opt] == req.earlyoptions[opt]: | 1064 if options[opt] == req.earlyoptions[opt]: |
1062 continue | 1065 continue |
1063 val = pycompat.bytestr(bool(options[opt])) | 1066 val = pycompat.bytestr(bool(options[opt])) |
1064 for ui_ in uis: | 1067 for ui_ in uis: |
1065 ui_.setconfig('ui', opt, val, '--' + opt) | 1068 ui_.setconfig(b'ui', opt, val, b'--' + opt) |
1066 | 1069 |
1067 if options['traceback']: | 1070 if options[b'traceback']: |
1068 for ui_ in uis: | 1071 for ui_ in uis: |
1069 ui_.setconfig('ui', 'traceback', 'on', '--traceback') | 1072 ui_.setconfig(b'ui', b'traceback', b'on', b'--traceback') |
1070 | 1073 |
1071 if options['noninteractive']: | 1074 if options[b'noninteractive']: |
1072 for ui_ in uis: | 1075 for ui_ in uis: |
1073 ui_.setconfig('ui', 'interactive', 'off', '-y') | 1076 ui_.setconfig(b'ui', b'interactive', b'off', b'-y') |
1074 | 1077 |
1075 if cmdoptions.get('insecure', False): | 1078 if cmdoptions.get(b'insecure', False): |
1076 for ui_ in uis: | 1079 for ui_ in uis: |
1077 ui_.insecureconnections = True | 1080 ui_.insecureconnections = True |
1078 | 1081 |
1079 # setup color handling before pager, because setting up pager | 1082 # setup color handling before pager, because setting up pager |
1080 # might cause incorrect console information | 1083 # might cause incorrect console information |
1081 coloropt = options['color'] | 1084 coloropt = options[b'color'] |
1082 for ui_ in uis: | 1085 for ui_ in uis: |
1083 if coloropt: | 1086 if coloropt: |
1084 ui_.setconfig('ui', 'color', coloropt, '--color') | 1087 ui_.setconfig(b'ui', b'color', coloropt, b'--color') |
1085 color.setup(ui_) | 1088 color.setup(ui_) |
1086 | 1089 |
1087 if stringutil.parsebool(options['pager']): | 1090 if stringutil.parsebool(options[b'pager']): |
1088 # ui.pager() expects 'internal-always-' prefix in this case | 1091 # ui.pager() expects 'internal-always-' prefix in this case |
1089 ui.pager('internal-always-' + cmd) | 1092 ui.pager(b'internal-always-' + cmd) |
1090 elif options['pager'] != 'auto': | 1093 elif options[b'pager'] != b'auto': |
1091 for ui_ in uis: | 1094 for ui_ in uis: |
1092 ui_.disablepager() | 1095 ui_.disablepager() |
1093 | 1096 |
1094 # configs are fully loaded, set up the ui instances | 1097 # configs are fully loaded, set up the ui instances |
1095 for ui_ in uis: | 1098 for ui_ in uis: |
1096 extensions.populateui(ui_) | 1099 extensions.populateui(ui_) |
1097 | 1100 |
1098 if options['version']: | 1101 if options[b'version']: |
1099 return commands.version_(ui) | 1102 return commands.version_(ui) |
1100 if options['help']: | 1103 if options[b'help']: |
1101 return commands.help_(ui, cmd, command=cmd is not None) | 1104 return commands.help_(ui, cmd, command=cmd is not None) |
1102 elif not cmd: | 1105 elif not cmd: |
1103 return commands.help_(ui, 'shortlist') | 1106 return commands.help_(ui, b'shortlist') |
1104 | 1107 |
1105 repo = None | 1108 repo = None |
1106 cmdpats = args[:] | 1109 cmdpats = args[:] |
1107 if not func.norepo: | 1110 if not func.norepo: |
1108 # use the repo from the request only if we don't have -R | 1111 # use the repo from the request only if we don't have -R |
1123 presetupfuncs=req.prereposetups, | 1126 presetupfuncs=req.prereposetups, |
1124 intents=func.intents, | 1127 intents=func.intents, |
1125 ) | 1128 ) |
1126 if not repo.local(): | 1129 if not repo.local(): |
1127 raise error.Abort( | 1130 raise error.Abort( |
1128 _("repository '%s' is not local") % path | 1131 _(b"repository '%s' is not local") % path |
1129 ) | 1132 ) |
1130 repo.ui.setconfig( | 1133 repo.ui.setconfig( |
1131 "bundle", "mainreporoot", repo.root, 'repo' | 1134 b"bundle", b"mainreporoot", repo.root, b'repo' |
1132 ) | 1135 ) |
1133 except error.RequirementError: | 1136 except error.RequirementError: |
1134 raise | 1137 raise |
1135 except error.RepoError: | 1138 except error.RepoError: |
1136 if rpath: # invalid -R path | 1139 if rpath: # invalid -R path |
1139 if func.inferrepo and args and not path: | 1142 if func.inferrepo and args and not path: |
1140 # try to infer -R from command args | 1143 # try to infer -R from command args |
1141 repos = pycompat.maplist(cmdutil.findrepo, args) | 1144 repos = pycompat.maplist(cmdutil.findrepo, args) |
1142 guess = repos[0] | 1145 guess = repos[0] |
1143 if guess and repos.count(guess) == len(repos): | 1146 if guess and repos.count(guess) == len(repos): |
1144 req.args = ['--repository', guess] + fullargs | 1147 req.args = [b'--repository', guess] + fullargs |
1145 req.earlyoptions['repository'] = guess | 1148 req.earlyoptions[b'repository'] = guess |
1146 return _dispatch(req) | 1149 return _dispatch(req) |
1147 if not path: | 1150 if not path: |
1148 raise error.RepoError( | 1151 raise error.RepoError( |
1149 _( | 1152 _( |
1150 "no repository found in" | 1153 b"no repository found in" |
1151 " '%s' (.hg not found)" | 1154 b" '%s' (.hg not found)" |
1152 ) | 1155 ) |
1153 % encoding.getcwd() | 1156 % encoding.getcwd() |
1154 ) | 1157 ) |
1155 raise | 1158 raise |
1156 if repo: | 1159 if repo: |
1157 ui = repo.ui | 1160 ui = repo.ui |
1158 if options['hidden']: | 1161 if options[b'hidden']: |
1159 repo = repo.unfiltered() | 1162 repo = repo.unfiltered() |
1160 args.insert(0, repo) | 1163 args.insert(0, repo) |
1161 elif rpath: | 1164 elif rpath: |
1162 ui.warn(_("warning: --repository ignored\n")) | 1165 ui.warn(_(b"warning: --repository ignored\n")) |
1163 | 1166 |
1164 msg = _formatargs(fullargs) | 1167 msg = _formatargs(fullargs) |
1165 ui.log("command", '%s\n', msg) | 1168 ui.log(b"command", b'%s\n', msg) |
1166 strcmdopt = pycompat.strkwargs(cmdoptions) | 1169 strcmdopt = pycompat.strkwargs(cmdoptions) |
1167 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt) | 1170 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt) |
1168 try: | 1171 try: |
1169 return runcommand( | 1172 return runcommand( |
1170 lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions | 1173 lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions |
1175 | 1178 |
1176 | 1179 |
1177 def _runcommand(ui, options, cmd, cmdfunc): | 1180 def _runcommand(ui, options, cmd, cmdfunc): |
1178 """Run a command function, possibly with profiling enabled.""" | 1181 """Run a command function, possibly with profiling enabled.""" |
1179 try: | 1182 try: |
1180 with tracing.log("Running %s command" % cmd): | 1183 with tracing.log(b"Running %s command" % cmd): |
1181 return cmdfunc() | 1184 return cmdfunc() |
1182 except error.SignatureError: | 1185 except error.SignatureError: |
1183 raise error.CommandError(cmd, _('invalid arguments')) | 1186 raise error.CommandError(cmd, _(b'invalid arguments')) |
1184 | 1187 |
1185 | 1188 |
1186 def _exceptionwarning(ui): | 1189 def _exceptionwarning(ui): |
1187 """Produce a warning message for the current active exception""" | 1190 """Produce a warning message for the current active exception""" |
1188 | 1191 |
1192 # probably built from fairly close to a tag and anyone with a | 1195 # probably built from fairly close to a tag and anyone with a |
1193 # 'make local' copy of hg (where the version number can be out | 1196 # 'make local' copy of hg (where the version number can be out |
1194 # of date) will be clueful enough to notice the implausible | 1197 # of date) will be clueful enough to notice the implausible |
1195 # version number and try updating. | 1198 # version number and try updating. |
1196 ct = util.versiontuple(n=2) | 1199 ct = util.versiontuple(n=2) |
1197 worst = None, ct, '' | 1200 worst = None, ct, b'' |
1198 if ui.config('ui', 'supportcontact') is None: | 1201 if ui.config(b'ui', b'supportcontact') is None: |
1199 for name, mod in extensions.extensions(): | 1202 for name, mod in extensions.extensions(): |
1200 # 'testedwith' should be bytes, but not all extensions are ported | 1203 # 'testedwith' should be bytes, but not all extensions are ported |
1201 # to py3 and we don't want UnicodeException because of that. | 1204 # to py3 and we don't want UnicodeException because of that. |
1202 testedwith = stringutil.forcebytestr(getattr(mod, 'testedwith', '')) | 1205 testedwith = stringutil.forcebytestr( |
1203 report = getattr(mod, 'buglink', _('the extension author.')) | 1206 getattr(mod, 'testedwith', b'') |
1207 ) | |
1208 report = getattr(mod, 'buglink', _(b'the extension author.')) | |
1204 if not testedwith.strip(): | 1209 if not testedwith.strip(): |
1205 # We found an untested extension. It's likely the culprit. | 1210 # We found an untested extension. It's likely the culprit. |
1206 worst = name, 'unknown', report | 1211 worst = name, b'unknown', report |
1207 break | 1212 break |
1208 | 1213 |
1209 # Never blame on extensions bundled with Mercurial. | 1214 # Never blame on extensions bundled with Mercurial. |
1210 if extensions.ismoduleinternal(mod): | 1215 if extensions.ismoduleinternal(mod): |
1211 continue | 1216 continue |
1219 if worst[0] is None or nearest < worst[1]: | 1224 if worst[0] is None or nearest < worst[1]: |
1220 worst = name, nearest, report | 1225 worst = name, nearest, report |
1221 if worst[0] is not None: | 1226 if worst[0] is not None: |
1222 name, testedwith, report = worst | 1227 name, testedwith, report = worst |
1223 if not isinstance(testedwith, (bytes, str)): | 1228 if not isinstance(testedwith, (bytes, str)): |
1224 testedwith = '.'.join( | 1229 testedwith = b'.'.join( |
1225 [stringutil.forcebytestr(c) for c in testedwith] | 1230 [stringutil.forcebytestr(c) for c in testedwith] |
1226 ) | 1231 ) |
1227 warning = _( | 1232 warning = _( |
1228 '** Unknown exception encountered with ' | 1233 b'** Unknown exception encountered with ' |
1229 'possibly-broken third-party extension %s\n' | 1234 b'possibly-broken third-party extension %s\n' |
1230 '** which supports versions %s of Mercurial.\n' | 1235 b'** which supports versions %s of Mercurial.\n' |
1231 '** Please disable %s and try your action again.\n' | 1236 b'** Please disable %s and try your action again.\n' |
1232 '** If that fixes the bug please report it to %s\n' | 1237 b'** If that fixes the bug please report it to %s\n' |
1233 ) % (name, testedwith, name, stringutil.forcebytestr(report)) | 1238 ) % (name, testedwith, name, stringutil.forcebytestr(report)) |
1234 else: | 1239 else: |
1235 bugtracker = ui.config('ui', 'supportcontact') | 1240 bugtracker = ui.config(b'ui', b'supportcontact') |
1236 if bugtracker is None: | 1241 if bugtracker is None: |
1237 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker") | 1242 bugtracker = _(b"https://mercurial-scm.org/wiki/BugTracker") |
1238 warning = ( | 1243 warning = ( |
1239 _( | 1244 _( |
1240 "** unknown exception encountered, " | 1245 b"** unknown exception encountered, " |
1241 "please report by visiting\n** " | 1246 b"please report by visiting\n** " |
1242 ) | 1247 ) |
1243 + bugtracker | 1248 + bugtracker |
1244 + '\n' | 1249 + b'\n' |
1245 ) | 1250 ) |
1246 sysversion = pycompat.sysbytes(sys.version).replace('\n', '') | 1251 sysversion = pycompat.sysbytes(sys.version).replace(b'\n', b'') |
1247 warning += ( | 1252 warning += ( |
1248 (_("** Python %s\n") % sysversion) | 1253 (_(b"** Python %s\n") % sysversion) |
1249 + (_("** Mercurial Distributed SCM (version %s)\n") % util.version()) | 1254 + (_(b"** Mercurial Distributed SCM (version %s)\n") % util.version()) |
1250 + ( | 1255 + ( |
1251 _("** Extensions loaded: %s\n") | 1256 _(b"** Extensions loaded: %s\n") |
1252 % ", ".join([x[0] for x in extensions.extensions()]) | 1257 % b", ".join([x[0] for x in extensions.extensions()]) |
1253 ) | 1258 ) |
1254 ) | 1259 ) |
1255 return warning | 1260 return warning |
1256 | 1261 |
1257 | 1262 |
1261 Called when handling an exception; the exception is reraised if | 1266 Called when handling an exception; the exception is reraised if |
1262 this function returns False, ignored otherwise. | 1267 this function returns False, ignored otherwise. |
1263 """ | 1268 """ |
1264 warning = _exceptionwarning(ui) | 1269 warning = _exceptionwarning(ui) |
1265 ui.log( | 1270 ui.log( |
1266 "commandexception", | 1271 b"commandexception", |
1267 "%s\n%s\n", | 1272 b"%s\n%s\n", |
1268 warning, | 1273 warning, |
1269 pycompat.sysbytes(traceback.format_exc()), | 1274 pycompat.sysbytes(traceback.format_exc()), |
1270 ) | 1275 ) |
1271 ui.warn(warning) | 1276 ui.warn(warning) |
1272 return False # re-raise the exception | 1277 return False # re-raise the exception |