Changeset 9650ad98b240…
Parent 587825e1f709…
by
Changes to 3 files · Browse files at 9650ad98b240 Showing diff from parent 587825e1f709 Diff from another changeset...
@@ -51,7 +51,15 @@ mystderr.seek(0)
for l in mystderr.readlines():
if l.startswith(('Traceback', 'TypeError', 'NameError')):
- print error
+ from tortoisehg.hgqt.bugreport import run
+ from tortoisehg.hgqt.run import qtrun
+ error = 'Recoverable runtime error (stderr):\n'
+ error += mystderr.getvalue()
+ opts = {}
+ opts['cmd'] = ' '.join(sys.argv[1:])
+ opts['error'] = error
+ opts['nofork'] = True
+ qtrun(run, _ui, **opts)
break
sys.exit(ret)
except:
|
|
@@ -0,0 +1,89 @@ + # bugreport.py - Report Python tracebacks to the user
+#
+# Copyright 2010 Steve Borho <steve@borho.org>
+#
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+import os
+import sys
+
+from PyQt4 import QtCore, QtGui
+from PyQt4.QtCore import SIGNAL, SLOT
+
+from mercurial import extensions
+from tortoisehg.util import hglib, version
+from tortoisehg.util.i18n import _
+
+class BugReport(QtGui.QDialog):
+
+ def __init__(self, opts, parent=None):
+ super(BugReport, self).__init__(parent)
+
+ layout = QtGui.QVBoxLayout()
+
+ te = QtGui.QTextEdit()
+ te.setPlainText(self.gettext(opts))
+ te.setReadOnly(True)
+ te.setWordWrapMode(QtGui.QTextOption.NoWrap)
+ layout.addWidget(te)
+
+ # dialog buttons
+ BB = QtGui.QDialogButtonBox
+ bb = QtGui.QDialogButtonBox(BB.Ok|BB.Save)
+ self.connect(bb, SIGNAL("accepted()"), self, SLOT("accept()"))
+ self.connect(bb, SIGNAL("rejected()"), self, SLOT("reject()"))
+ self.connect(bb.button(BB.Save), SIGNAL("clicked()"), self.save)
+ bb.button(BB.Ok).setDefault(True)
+ layout.addWidget(bb)
+
+ self.setLayout(layout)
+ self.setWindowTitle(_('TortoiseHg Bug Report'))
+
+ def gettext(self, opts):
+ text = '{{{\n#!python\n' # Wrap in Bitbucket wiki preformat markers
+ text += _('** Please report this bug to'
+ ' http://bitbucket.org/tortoisehg/stable/issues\n')
+ text += '** Mercurial version (%s). TortoiseHg version (%s)\n' % (
+ hglib.hgversion, version.version())
+ text += '** Command: %s\n' % (opts.get('cmd', 'N/A'))
+ text += '** CWD: %s\n' % os.getcwd()
+ extlist = [x[0] for x in extensions.extensions()]
+ text += '** Extensions loaded: %s\n' % ', '.join(extlist)
+ if os.name == 'nt':
+ text += self.getarch()
+ text += opts.get('error', 'N/A')
+ text += '\n}}}'
+ return text
+
+ def getarch(self):
+ text += '** Windows version: %s\n' % str(sys.getwindowsversion())
+ arch = 'unknown (failed to import win32api)'
+ try:
+ import win32api
+ arch = 'unknown'
+ archval = win32api.GetNativeSystemInfo()[0]
+ if archval == 9:
+ arch = 'x64'
+ elif archval == 0:
+ arch = 'x86'
+ except (ImportError, AttributeError):
+ pass
+ text += '** Processor architecture: %s\n' % arch
+ return text
+
+ def save(self):
+ try:
+ fd = QtGui.QFileDialog(self)
+ open(fd.getOpenFileName()).write(self.text)
+ except (OSError, IOError), e:
+ print e
+
+def run(ui, *pats, **opts):
+ return BugReport(opts)
+
+if __name__ == "__main__":
+ app = QtGui.QApplication(sys.argv)
+ form = BugReport({'cmd':'cmd', 'error':'error'})
+ form.show()
+ app.exec_()
|
@@ -40,6 +40,7 @@ nonrepo_commands = '''userconfig shellconfig clone debugcomplete init
about help version thgstatus serve'''
+mainapp = None
def dispatch(args):
"""run the command specified in args"""
try:
@@ -54,7 +55,15 @@ except KeyboardInterrupt:
print _('\nCaught keyboard interrupt, aborting.\n')
except:
- print traceback.format_exc()
+ from tortoisehg.hgqt.bugreport import run
+ if '--debugger' in args:
+ pdb.post_mortem(sys.exc_info()[2])
+ error = traceback.format_exc()
+ opts = {}
+ opts['cmd'] = ' '.join(sys.argv[1:])
+ opts['error'] = error
+ opts['nofork'] = True
+ qtrun(run, u, **opts)
origwdir = os.getcwd()
def portable_fork(ui, opts):
@@ -287,12 +296,28 @@
def qtrun(dlgfunc, ui, *args, **opts):
portable_fork(ui, opts)
- app = QtGui.QApplication(sys.argv)
- dlg = dlgfunc(ui, *args, **opts)
- if not dlg:
+
+ global mainapp
+ if mainapp:
+ dlg = dlgfunc(ui, *args, **opts)
+ dlg.show()
return
- dlg.show()
- app.exec_()
+
+ mainapp = QtGui.QApplication(sys.argv)
+ try:
+ dlg = dlgfunc(ui, *args, **opts)
+ dlg.show()
+ except Exception, e:
+ from tortoisehg.hgqt.bugreport import run
+ error = _('Fatal error opening dialog\n')
+ error += traceback.format_exc()
+ opts = {}
+ opts['cmd'] = ' '.join(sys.argv[1:])
+ opts['error'] = error
+ opts['nofork'] = True
+ bugreport = run(ui, **opts)
+ bugreport.show()
+ mainapp.exec_()
def thgstatus(ui, *pats, **opts):
"""update TortoiseHg status cache"""
@@ -304,6 +329,15 @@ from tortoisehg.hgqt.clone import run
qtrun(run, ui, *pats, **opts)
+def bug(ui, *pats, **opts):
+ """bug report dialog"""
+ from tortoisehg.hgqt.bugreport import run
+ if len(pats) == 1:
+ opts['error'] = pats[0]
+ opts['cmd'] = sys.argv[1:]
+ opts['nofork'] = True
+ qtrun(run, ui, *pats, **opts)
+
def shellconfig(ui, *pats, **opts):
"""Explorer extension configuration editor"""
from tortoisehg.hgqt.shellconf import run
@@ -541,6 +575,7 @@ ('', 'uncompressed', None,
_('use uncompressed transfer (fast over LAN)')),],
_('thg clone [OPTION]... SOURCE [DEST]')),
+ "bug": (bug, [], _('thg bug [MESSAGE]')),
"help": (help_, [], _('thg help [COMMAND]')),
"^update|checkout|co":
(update,
|
Loading...