# thg - mercurial extension for TortoiseHg repository browser
#
# Copyright (C) 2014 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.
"""browse the repository in a graphical way using tortoisehg

The 'tortoisehg' extension introduces a :hg:`view` command to spawn a light
version of the tortoisehg workbench.
"""


from __future__ import annotations

import os
import sys

from mercurial import (
    pycompat,
    registrar,
    ui as uimod,
    util,
)
from mercurial.utils import (
    procutil,
)

from tortoisehg.util.i18n import agettext as _

testedwith = b'4.3'

cmdtable = {}
command = registrar.command(cmdtable)

if hasattr(sys, "frozen"):
    if sys.frozen == 'windows_exe':
        # sys.stdin is invalid, should be None.  Fixes svn, git subrepos
        sys.stdin = None
        if 'THGDEBUG' in os.environ:
            import win32traceutil
            print('starting')
    # os.Popen() needs this, and Mercurial still uses os.Popen
    if 'COMSPEC' not in os.environ:
        comspec = os.path.join(os.environ.get('SystemRoot', r'C:\Windows'),
                               'system32', 'cmd.exe')
        os.environ['COMSPEC'] = comspec
else:
    thgpath = os.path.dirname(os.path.realpath(__file__))
    thgpath = os.path.dirname(thgpath)
    testpath = os.path.join(thgpath, 'tortoisehg')
    if os.path.isdir(testpath) and thgpath not in sys.path:
        sys.path.insert(0, thgpath)

    if 'HGPATH' in os.environ:
        hgpath = os.environ['HGPATH']
        testpath = os.path.join(hgpath, 'mercurial')
        if os.path.isdir(testpath) and hgpath not in sys.path:
            sys.path.insert(0, hgpath)

# Make sure to load threading by main thread; otherwise, _MainThread instance
# may have wrong thread id and results KeyError at exit.
import threading

from mercurial import demandimport
demandimport.IGNORES.update([
    'win32com.shell',
    'numpy',  # comtypes.npsupport does try-import
    'tortoisehg.util.config',
    'tortoisehg.hgqt.icons_rc',
    'tortoisehg.hgqt.translations_rc',
    # don't create troublesome demandmods for bunch of Q* attributes
    'tortoisehg.hgqt.qsci',
    'tortoisehg.hgqt.qtcore',
    'tortoisehg.hgqt.qtgui',
    'tortoisehg.hgqt.qtnetwork',
    # TODO: fix name resolution in demandimporter and remove these
    'qsci',
    'qtcore',
    'qtgui',
    'qtnetwork',
    # pygments seems to have trouble on loading plugins (see #4271, #4298)
    'pkgutil',
    'pkg_resources',
])
demandimport.enable()

# Verify we can reach TortoiseHg sources first
try:
    import tortoisehg.hgqt.run
except ImportError as e:
    sys.stderr.write(str(e)+'\n')
    sys.stderr.write("abort: couldn't find tortoisehg libraries in [%s]\n" %
                     os.pathsep.join(sys.path))
    sys.stderr.write("(check your install and PYTHONPATH)\n")
    sys.exit(-1)

def enforceversion():
    """Verify we have an acceptable version of Mercurial

    Display an error dialog in the contrary.
    """
    from tortoisehg.util.hgversion import hgversion, checkhgversion
    errmsg = checkhgversion(hgversion)
    if errmsg:
        from tortoisehg.hgqt.bugreport import run
        from tortoisehg.hgqt.run import qtrun
        opts = {
            'cmd': b' '.join(pycompat.sysargv),
            'error': b'\n' + errmsg + b'\n',
            'nofork': True,
        }
        qtrun(run, uimod.ui(), **opts)
        sys.exit(1)

@command(b'view', [], _("hg view"), inferrepo=True)
def cmdview(ui, repo, *pats, **opts):
    """start light interactive history viewer from tortoisehg"""
    enforceversion()

    origstderr = sys.stderr

    # TODO: Figure out if this hack for py2exe is still needed, and possibly
    #       wrap this to handle unicode on py3
    if not pycompat.ispy3:
        mystderr = util.bytesio()
        sys.stderr = mystderr
        sys.__stdout__ = sys.stdout
        sys.__stderr__ = sys.stderr
        procutil.stderr = sys.stderr

    ret = 0
    try:
        from tortoisehg.hgqt.run import qtrun
        from tortoisehg.hgqt.run import debuglighthg as startfunc
        opts['repository'] = repo.root
        qtrun(startfunc, ui, *pats, **opts)

        if not pycompat.ispy3:
            sys.stderr = origstderr
            stderrout = mystderr.getvalue()
        else:
            stderrout = ''  # TODO: handle stderr stream on py3

        errors = ('Traceback', 'TypeError', 'NameError', 'AttributeError',
                  'NotImplementedError')
        for l in stderrout.splitlines():
            if l.startswith(errors):
                from tortoisehg.hgqt.bugreport import run
                opts = {'cmd': ' '.join(sys.argv),
                        'error': 'Recoverable error (stderr):\n' + stderrout,
                        'nofork': True}
                qtrun(run, uimod.ui(), **opts)
                break
        sys.exit(ret)
    except SystemExit:
        raise
    except:
        procutil.stderr = sys.__stderr__ = sys.stderr = origstderr
        raise
