comparison mercurial/dispatch.py @ 28784:09750b1231c2

dispatch: factor out command failure handling into a function Moving the warning generation to a function allows for wrapping and alternative error handling.
author Martijn Pieters <mjpieters@fb.com>
date Mon, 04 Apr 2016 17:27:37 +0100
parents cc103bd0dbf9
children d3369dc6c1d0
comparison
equal deleted inserted replaced
28783:d9179856d732 28784:09750b1231c2
331 # Commands shouldn't sys.exit directly, but give a return code. 331 # Commands shouldn't sys.exit directly, but give a return code.
332 # Just in case catch this and and pass exit code to caller. 332 # Just in case catch this and and pass exit code to caller.
333 return inst.code 333 return inst.code
334 except socket.error as inst: 334 except socket.error as inst:
335 ui.warn(_("abort: %s\n") % inst.args[-1]) 335 ui.warn(_("abort: %s\n") % inst.args[-1])
336 except: # re-raises 336 except: # perhaps re-raises
337 # For compatibility checking, we discard the portion of the hg 337 if not handlecommandexception(ui):
338 # version after the + on the assumption that if a "normal 338 raise
339 # user" is running a build with a + in it the packager
340 # probably built from fairly close to a tag and anyone with a
341 # 'make local' copy of hg (where the version number can be out
342 # of date) will be clueful enough to notice the implausible
343 # version number and try updating.
344 ct = util.versiontuple(n=2)
345 worst = None, ct, ''
346 if ui.config('ui', 'supportcontact', None) is None:
347 for name, mod in extensions.extensions():
348 testedwith = getattr(mod, 'testedwith', '')
349 report = getattr(mod, 'buglink', _('the extension author.'))
350 if not testedwith.strip():
351 # We found an untested extension. It's likely the culprit.
352 worst = name, 'unknown', report
353 break
354
355 # Never blame on extensions bundled with Mercurial.
356 if testedwith == 'internal':
357 continue
358
359 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
360 if ct in tested:
361 continue
362
363 lower = [t for t in tested if t < ct]
364 nearest = max(lower or tested)
365 if worst[0] is None or nearest < worst[1]:
366 worst = name, nearest, report
367 if worst[0] is not None:
368 name, testedwith, report = worst
369 if not isinstance(testedwith, str):
370 testedwith = '.'.join([str(c) for c in testedwith])
371 warning = (_('** Unknown exception encountered with '
372 'possibly-broken third-party extension %s\n'
373 '** which supports versions %s of Mercurial.\n'
374 '** Please disable %s and try your action again.\n'
375 '** If that fixes the bug please report it to %s\n')
376 % (name, testedwith, name, report))
377 else:
378 bugtracker = ui.config('ui', 'supportcontact', None)
379 if bugtracker is None:
380 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
381 warning = (_("** unknown exception encountered, "
382 "please report by visiting\n** ") + bugtracker + '\n')
383 warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
384 (_("** Mercurial Distributed SCM (version %s)\n") %
385 util.version()) +
386 (_("** Extensions loaded: %s\n") %
387 ", ".join([x[0] for x in extensions.extensions()])))
388 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
389 ui.warn(warning)
390 raise
391 339
392 return -1 340 return -1
393 341
394 def aliasargs(fn, givenargs): 342 def aliasargs(fn, givenargs):
395 args = getattr(fn, 'args', []) 343 args = getattr(fn, 'args', [])
1064 val = val.replace('%', '%%') 1012 val = val.replace('%', '%%')
1065 ui.log('profile', val) 1013 ui.log('profile', val)
1066 fp.close() 1014 fp.close()
1067 else: 1015 else:
1068 return checkargs() 1016 return checkargs()
1017
1018 def handlecommandexception(ui):
1019 """Produce a warning message for broken commands
1020
1021 Called when handling an exception; the exception is reraised if
1022 this function returns False, ignored otherwise.
1023 """
1024 # For compatibility checking, we discard the portion of the hg
1025 # version after the + on the assumption that if a "normal
1026 # user" is running a build with a + in it the packager
1027 # probably built from fairly close to a tag and anyone with a
1028 # 'make local' copy of hg (where the version number can be out
1029 # of date) will be clueful enough to notice the implausible
1030 # version number and try updating.
1031 ct = util.versiontuple(n=2)
1032 worst = None, ct, ''
1033 if ui.config('ui', 'supportcontact', None) is None:
1034 for name, mod in extensions.extensions():
1035 testedwith = getattr(mod, 'testedwith', '')
1036 report = getattr(mod, 'buglink', _('the extension author.'))
1037 if not testedwith.strip():
1038 # We found an untested extension. It's likely the culprit.
1039 worst = name, 'unknown', report
1040 break
1041
1042 # Never blame on extensions bundled with Mercurial.
1043 if testedwith == 'internal':
1044 continue
1045
1046 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
1047 if ct in tested:
1048 continue
1049
1050 lower = [t for t in tested if t < ct]
1051 nearest = max(lower or tested)
1052 if worst[0] is None or nearest < worst[1]:
1053 worst = name, nearest, report
1054 if worst[0] is not None:
1055 name, testedwith, report = worst
1056 if not isinstance(testedwith, str):
1057 testedwith = '.'.join([str(c) for c in testedwith])
1058 warning = (_('** Unknown exception encountered with '
1059 'possibly-broken third-party extension %s\n'
1060 '** which supports versions %s of Mercurial.\n'
1061 '** Please disable %s and try your action again.\n'
1062 '** If that fixes the bug please report it to %s\n')
1063 % (name, testedwith, name, report))
1064 else:
1065 bugtracker = ui.config('ui', 'supportcontact', None)
1066 if bugtracker is None:
1067 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
1068 warning = (_("** unknown exception encountered, "
1069 "please report by visiting\n** ") + bugtracker + '\n')
1070 warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
1071 (_("** Mercurial Distributed SCM (version %s)\n") %
1072 util.version()) +
1073 (_("** Extensions loaded: %s\n") %
1074 ", ".join([x[0] for x in extensions.extensions()])))
1075 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
1076 ui.warn(warning)
1077 return False # re-raise the exception