# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import absolute_import, print_function, unicode_literals

import json
import logging
import mozpack.path as mozpath
import multiprocessing
import os
import subprocess
import sys
import which

from mach.mixin.logging import LoggingMixin
from mach.mixin.process import ProcessExecutionMixin

from mozfile.mozfile import rmtree

from .backend.configenvironment import ConfigEnvironment
from .controller.clobber import Clobberer
from .mozconfig import (
    MozconfigFindException,
    MozconfigLoadException,
    MozconfigLoader,
)
from .util import memoized_property
from .virtualenv import VirtualenvManager


_config_guess_output = []


def ancestors(path):
    """Emit the parent directories of a path."""
    while path:
        yield path
        newpath = os.path.dirname(path)
        if newpath == path:
            break
        path = newpath

def samepath(path1, path2):
    if hasattr(os.path, 'samefile'):
        return os.path.samefile(path1, path2)
    return os.path.normcase(os.path.realpath(path1)) == \
        os.path.normcase(os.path.realpath(path2))

class BadEnvironmentException(Exception):
    """Base class for errors raised when the build environment is not sane."""


class BuildEnvironmentNotFoundException(BadEnvironmentException):
    """Raised when we could not find a build environment."""


class ObjdirMismatchException(BadEnvironmentException):
    """Raised when the current dir is an objdir and doesn't match the mozconfig."""
    def __init__(self, objdir1, objdir2):
        self.objdir1 = objdir1
        self.objdir2 = objdir2

    def __str__(self):
        return "Objdir mismatch: %s != %s" % (self.objdir1, self.objdir2)


class MozbuildObject(ProcessExecutionMixin):
    """Base class providing basic functionality useful to many modules.

    Modules in this package typically require common functionality such as
    accessing the current config, getting the location of the source directory,
    running processes, etc. This classes provides that functionality. Other
    modules can inherit from this class to obtain this functionality easily.
    """
    def __init__(self, topsrcdir, settings, log_manager, topobjdir=None):
        """Create a new Mozbuild object instance.

        Instances are bound to a source directory, a ConfigSettings instance,
        and a LogManager instance. The topobjdir may be passed in as well. If
        it isn't, it will be calculated from the active mozconfig.
        """
        self.topsrcdir = topsrcdir
        self.settings = settings

        self.populate_logger()
        self.log_manager = log_manager

        self._make = None
        self._topobjdir = topobjdir
        self._mozconfig = None
        self._config_guess_output = None
        self._config_environment = None
        self._virtualenv_manager = None

    @classmethod
    def from_environment(cls, cwd=None, detect_virtualenv_mozinfo=True):
        """Create a MozbuildObject by detecting the proper one from the env.

        This examines environment state like the current working directory and
        creates a MozbuildObject from the found source directory, mozconfig, etc.

        The role of this function is to identify a topsrcdir, topobjdir, and
        mozconfig file.

        If the current working directory is inside a known objdir, we always
        use the topsrcdir and mozconfig associated with that objdir. If no
        mozconfig is associated with that objdir, we fall back to looking for
        the mozconfig in the usual places.

        If the current working directory is inside a known srcdir, we use that
        topsrcdir and look for mozconfigs using the default mechanism, which
        looks inside environment variables.

        If the current Python interpreter is running from a virtualenv inside
        an objdir, we use that as our objdir.

        If we're not inside a srcdir or objdir, an exception is raised.

        detect_virtualenv_mozinfo determines whether we should look for a
        mozinfo.json file relative to the virtualenv directory. This was
        added to facilitate testing. Callers likely shouldn't change the
        default.
        """

        cwd = cwd or os.getcwd()
        topsrcdir = None
        topobjdir = None
        mozconfig = None

        def load_mozinfo(path):
            info = json.load(open(path, 'rt'))
            topsrcdir = info.get('topsrcdir')
            topobjdir = os.path.dirname(path)
            mozconfig = info.get('mozconfig')
            return topsrcdir, topobjdir, mozconfig

        for dir_path in ancestors(cwd):
            # If we find a mozinfo.json, we are in the objdir.
            mozinfo_path = os.path.join(dir_path, 'mozinfo.json')
            if os.path.isfile(mozinfo_path):
                topsrcdir, topobjdir, mozconfig = load_mozinfo(mozinfo_path)
                break

            # We choose an arbitrary file as an indicator that this is a
            # srcdir. We go with ourself because why not!
            our_path = os.path.join(dir_path, 'python', 'mozbuild', 'mozbuild', 'base.py')
            if os.path.isfile(our_path):
                topsrcdir = dir_path
                break

        # See if we're running from a Python virtualenv that's inside an objdir.
        mozinfo_path = os.path.join(os.path.dirname(sys.prefix), "mozinfo.json")
        if detect_virtualenv_mozinfo and os.path.isfile(mozinfo_path):
            topsrcdir, topobjdir, mozconfig = load_mozinfo(mozinfo_path)

        # If we were successful, we're only guaranteed to find a topsrcdir. If
        # we couldn't find that, there's nothing we can do.
        if not topsrcdir:
            raise BuildEnvironmentNotFoundException(
                'Could not find Mozilla source tree or build environment.')

        # Now we try to load the config for this environment. If mozconfig is
        # None, read_mozconfig() will attempt to find one in the existing
        # environment. If no mozconfig is present, the config will not have
        # much defined.
        loader = MozconfigLoader(topsrcdir)
        current_project = os.environ.get('MOZ_CURRENT_PROJECT')
        config = loader.read_mozconfig(mozconfig, moz_build_app=current_project)

        config_topobjdir = MozbuildObject.resolve_mozconfig_topobjdir(
            topsrcdir, config)

        # If we're inside a objdir and the found mozconfig resolves to
        # another objdir, we abort. The reasoning here is that if you are
        # inside an objdir you probably want to perform actions on that objdir,
        # not another one. This prevents accidental usage of the wrong objdir
        # when the current objdir is ambiguous.
        if topobjdir and config_topobjdir:
            if current_project:
                config_topobjdir = os.path.join(config_topobjdir, current_project)

            _config_topobjdir = config_topobjdir
            if not samepath(topobjdir, _config_topobjdir):
                raise ObjdirMismatchException(topobjdir, _config_topobjdir)

        topobjdir = topobjdir or config_topobjdir
        if topobjdir:
            topobjdir = os.path.normpath(topobjdir)

            if topsrcdir == topobjdir:
                raise BadEnvironmentException('The object directory appears '
                    'to be the same as your source directory (%s). This build '
                    'configuration is not supported.' % topsrcdir)

        # If we can't resolve topobjdir, oh well. The constructor will figure
        # it out via config.guess.
        return cls(topsrcdir, None, None, topobjdir=topobjdir)

    @staticmethod
    def resolve_mozconfig_topobjdir(topsrcdir, mozconfig, default=None):
        topobjdir = mozconfig['topobjdir'] or default
        if not topobjdir:
            return None

        if '@CONFIG_GUESS@' in topobjdir:
            topobjdir = topobjdir.replace('@CONFIG_GUESS@',
                MozbuildObject.resolve_config_guess(mozconfig, topsrcdir))

        if not os.path.isabs(topobjdir):
            topobjdir = os.path.abspath(os.path.join(topsrcdir, topobjdir))

        return os.path.normpath(topobjdir)

    @property
    def topobjdir(self):
        if self._topobjdir is None:
            self._topobjdir = MozbuildObject.resolve_mozconfig_topobjdir(
                self.topsrcdir, self.mozconfig, default='obj-@CONFIG_GUESS@')

        return self._topobjdir

    @property
    def virtualenv_manager(self):
        if self._virtualenv_manager is None:
            self._virtualenv_manager = VirtualenvManager(self.topsrcdir,
                self.topobjdir, os.path.join(self.topobjdir, '_virtualenv'),
                sys.stdout, os.path.join(self.topsrcdir, 'build',
                'virtualenv_packages.txt'))

        return self._virtualenv_manager

    @property
    def mozconfig(self):
        """Returns information about the current mozconfig file.

        This a dict as returned by MozconfigLoader.read_mozconfig()
        """
        if self._mozconfig is None:
            loader = MozconfigLoader(self.topsrcdir)
            self._mozconfig = loader.read_mozconfig(
                moz_build_app=os.environ.get('MOZ_CURRENT_PROJECT'))

        return self._mozconfig

    @property
    def config_environment(self):
        """Returns the ConfigEnvironment for the current build configuration.

        This property is only available once configure has executed.

        If configure's output is not available, this will raise.
        """
        if self._config_environment:
            return self._config_environment

        config_status = os.path.join(self.topobjdir, 'config.status')

        if not os.path.exists(config_status):
            raise Exception('config.status not available. Run configure.')

        self._config_environment = \
            ConfigEnvironment.from_config_status(config_status)

        return self._config_environment

    @property
    def defines(self):
        return self.config_environment.defines

    @property
    def substs(self):
        return self.config_environment.substs

    @property
    def distdir(self):
        return os.path.join(self.topobjdir, 'dist')

    @property
    def bindir(self):
        return os.path.join(self.topobjdir, 'dist', 'bin')

    @property
    def includedir(self):
        return os.path.join(self.topobjdir, 'dist', 'include')

    @property
    def statedir(self):
        return os.path.join(self.topobjdir, '.mozbuild')

    @memoized_property
    def extra_environment_variables(self):
        '''Some extra environment variables are stored in .mozconfig.mk.
        This functions extracts and returns them.'''
        from mozbuild import shellutil
        mozconfig_mk = os.path.join(self.topobjdir, '.mozconfig.mk')
        env = {}
        with open(mozconfig_mk) as fh:
            for line in fh:
                if line.startswith('export '):
                    exports = shellutil.split(line)[1:]
                    for e in exports:
                        if '=' in e:
                            key, value = e.split('=')
                            env[key] = value
        return env

    def is_clobber_needed(self):
        if not os.path.exists(self.topobjdir):
            return False
        return Clobberer(self.topsrcdir, self.topobjdir).clobber_needed()

    def have_winrm(self):
        # `winrm -h` should print 'winrm version ...' and exit 1
        try:
            p = subprocess.Popen(['winrm.exe', '-h'],
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT)
            return p.wait() == 1 and p.stdout.read().startswith('winrm')
        except:
            return False

    def remove_objdir(self):
        """Remove the entire object directory."""

        if sys.platform.startswith('win') and self.have_winrm():
            subprocess.check_call(['winrm', '-rf', self.topobjdir])
        else:
            # We use mozfile because it is faster than shutil.rmtree().
            # mozfile doesn't like unicode arguments (bug 818783).
            rmtree(self.topobjdir.encode('utf-8'))

    def get_binary_path(self, what='app', validate_exists=True, where='default'):
        """Obtain the path to a compiled binary for this build configuration.

        The what argument is the program or tool being sought after. See the
        code implementation for supported values.

        If validate_exists is True (the default), we will ensure the found path
        exists before returning, raising an exception if it doesn't.

        If where is 'staged-package', we will return the path to the binary in
        the package staging directory.

        If no arguments are specified, we will return the main binary for the
        configured XUL application.
        """

        if where not in ('default', 'staged-package'):
            raise Exception("Don't know location %s" % where)

        substs = self.substs

        stem = self.distdir
        if where == 'staged-package':
            stem = os.path.join(stem, substs['MOZ_APP_NAME'])

        if substs['OS_ARCH'] == 'Darwin':
            if substs['MOZ_BUILD_APP'] == 'xulrunner':
                stem = os.path.join(stem, 'XUL.framework');
            else:
                stem = os.path.join(stem, substs['MOZ_MACBUNDLE_NAME'], 'Contents',
                    'MacOS')
        elif where == 'default':
            stem = os.path.join(stem, 'bin')

        leaf = None

        leaf = (substs['MOZ_APP_NAME'] if what == 'app' else what) + substs['BIN_SUFFIX']
        path = os.path.join(stem, leaf)

        if validate_exists and not os.path.exists(path):
            raise Exception('Binary expected at %s does not exist.' % path)

        return path

    @staticmethod
    def resolve_config_guess(mozconfig, topsrcdir):
        make_extra = mozconfig['make_extra'] or []
        make_extra = dict(m.split('=', 1) for m in make_extra)

        config_guess = make_extra.get('CONFIG_GUESS', None)

        if config_guess:
            return config_guess

        # config.guess results should be constant for process lifetime. Cache
        # it.
        if _config_guess_output:
            return _config_guess_output[0]

        p = os.path.join(topsrcdir, 'build', 'autoconf', 'config.guess')

        # This is a little kludgy. We need access to the normalize_command
        # function. However, that's a method of a mach mixin, so we need a
        # class instance. Ideally the function should be accessible as a
        # standalone function.
        o = MozbuildObject(topsrcdir, None, None, None)
        args = o._normalize_command([p], True)

        _config_guess_output.append(
                subprocess.check_output(args, cwd=topsrcdir).strip())
        return _config_guess_output[0]

    def notify(self, msg):
        """Show a desktop notification with the supplied message

        On Linux and Mac, this will show a desktop notification with the message,
        but on Windows we can only flash the screen.
        """
        moz_nospam = os.environ.get('MOZ_NOSPAM')
        if moz_nospam:
            return

        try:
            if sys.platform.startswith('darwin'):
                try:
                    notifier = which.which('terminal-notifier')
                except which.WhichError:
                    raise Exception('Install terminal-notifier to get '
                        'a notification when the build finishes.')
                self.run_process([notifier, '-title',
                    'Mozilla Build System', '-group', 'mozbuild',
                    '-message', msg], ensure_exit_code=False)
            elif sys.platform.startswith('linux'):
                try:
                    import dbus
                except ImportError:
                    raise Exception('Install the python dbus module to '
                        'get a notification when the build finishes.')
                bus = dbus.SessionBus()
                notify = bus.get_object('org.freedesktop.Notifications',
                                        '/org/freedesktop/Notifications')
                method = notify.get_dbus_method('Notify',
                                                'org.freedesktop.Notifications')
                method('Mozilla Build System', 0, '', msg, '', [], [], -1)
            elif sys.platform.startswith('win'):
                from ctypes import Structure, windll, POINTER, sizeof
                from ctypes.wintypes import DWORD, HANDLE, WINFUNCTYPE, BOOL, UINT
                class FLASHWINDOW(Structure):
                    _fields_ = [("cbSize", UINT),
                                ("hwnd", HANDLE),
                                ("dwFlags", DWORD),
                                ("uCount", UINT),
                                ("dwTimeout", DWORD)]
                FlashWindowExProto = WINFUNCTYPE(BOOL, POINTER(FLASHWINDOW))
                FlashWindowEx = FlashWindowExProto(("FlashWindowEx", windll.user32))
                FLASHW_CAPTION = 0x01
                FLASHW_TRAY = 0x02
                FLASHW_TIMERNOFG = 0x0C
                params = FLASHWINDOW(sizeof(FLASHWINDOW),
                                    windll.kernel32.GetConsoleWindow(),
                                    FLASHW_CAPTION | FLASHW_TRAY | FLASHW_TIMERNOFG, 3, 0)
                FlashWindowEx(params)
        except Exception as e:
            self.log(logging.WARNING, 'notifier-failed', {'error':
                e.message}, 'Notification center failed: {error}')

    @property
    def _config_guess(self):
        if self._config_guess_output is None:
            self._config_guess_output = MozbuildObject.resolve_config_guess(
                self.mozconfig, self.topsrcdir)

        return self._config_guess_output

    def _ensure_objdir_exists(self):
        if os.path.isdir(self.statedir):
            return

        os.makedirs(self.statedir)

    def _ensure_state_subdir_exists(self, subdir):
        path = os.path.join(self.statedir, subdir)

        if os.path.isdir(path):
            return

        os.makedirs(path)

    def _get_state_filename(self, filename, subdir=None):
        path = self.statedir

        if subdir:
            path = os.path.join(path, subdir)

        return os.path.join(path, filename)

    def _wrap_path_argument(self, arg):
        return PathArgument(arg, self.topsrcdir, self.topobjdir)

    def _run_make(self, directory=None, filename=None, target=None, log=True,
            srcdir=False, allow_parallel=True, line_handler=None,
            append_env=None, explicit_env=None, ignore_errors=False,
            ensure_exit_code=0, silent=True, print_directory=True,
            pass_thru=False, num_jobs=0):
        """Invoke make.

        directory -- Relative directory to look for Makefile in.
        filename -- Explicit makefile to run.
        target -- Makefile target(s) to make. Can be a string or iterable of
            strings.
        srcdir -- If True, invoke make from the source directory tree.
            Otherwise, make will be invoked from the object directory.
        silent -- If True (the default), run make in silent mode.
        print_directory -- If True (the default), have make print directories
        while doing traversal.
        """
        self._ensure_objdir_exists()

        args = self._make_path()

        if directory:
            args.extend(['-C', directory.replace(os.sep, '/')])

        if filename:
            args.extend(['-f', filename])

        if num_jobs == 0 and self.mozconfig['make_flags']:
            flags = iter(self.mozconfig['make_flags'])
            for flag in flags:
                if flag == '-j':
                    try:
                        flag = flags.next()
                    except StopIteration:
                        break
                    try:
                        num_jobs = int(flag)
                    except ValueError:
                        args.append(flag)
                elif flag.startswith('-j'):
                    try:
                        num_jobs = int(flag[2:])
                    except (ValueError, IndexError):
                        break
                else:
                    args.append(flag)

        if allow_parallel:
            if num_jobs > 0:
                args.append('-j%d' % num_jobs)
            else:
                args.append('-j%d' % multiprocessing.cpu_count())
        elif num_jobs > 0:
            args.append('MOZ_PARALLEL_BUILD=%d' % num_jobs)

        if ignore_errors:
            args.append('-k')

        if silent:
            args.append('-s')

        # Print entering/leaving directory messages. Some consumers look at
        # these to measure progress.
        if print_directory:
            args.append('-w')

        if isinstance(target, list):
            args.extend(target)
        elif target:
            args.append(target)

        fn = self._run_command_in_objdir

        if srcdir:
            fn = self._run_command_in_srcdir

        append_env = dict(append_env or ())
        append_env[b'MACH'] = '1'

        params = {
            'args': args,
            'line_handler': line_handler,
            'append_env': append_env,
            'explicit_env': explicit_env,
            'log_level': logging.INFO,
            'require_unix_environment': False,
            'ensure_exit_code': ensure_exit_code,
            'pass_thru': pass_thru,

            # Make manages its children, so mozprocess doesn't need to bother.
            # Having mozprocess manage children can also have side-effects when
            # building on Windows. See bug 796840.
            'ignore_children': True,
        }

        if log:
            params['log_name'] = 'make'

        return fn(**params)

    def _make_path(self):
        baseconfig = os.path.join(self.topsrcdir, 'config', 'baseconfig.mk')

        def is_xcode_lisense_error(output):
            return self._is_osx() and 'Agreeing to the Xcode' in output

        def validate_make(make):
            if os.path.exists(baseconfig) and os.path.exists(make):
                cmd = [make, '-f', baseconfig]
                if self._is_windows():
                    cmd.append('HOST_OS_ARCH=WINNT')
                try:
                    subprocess.check_output(cmd, stderr=subprocess.STDOUT)
                except subprocess.CalledProcessError as e:
                    return False, is_xcode_lisense_error(e.output)
                return True, False
            return False, False

        xcode_lisense_error = False
        possible_makes = ['gmake', 'make', 'mozmake', 'gnumake']

        if 'MAKE' in os.environ:
            make = os.environ['MAKE']
            possible_makes.insert(0, make)

        for test in possible_makes:
            if os.path.isabs(test):
                make = test
            else:
                try:
                    make = which.which(test)
                except which.WhichError:
                    continue
            result, xcode_lisense_error_tmp = validate_make(make)
            if result:
                return [make]
            if xcode_lisense_error_tmp:
                xcode_lisense_error = True

        if xcode_lisense_error:
            raise Exception('Xcode requires accepting to the license agreement.\n'
                'Please run Xcode and accept the license agreement.')

        if self._is_windows():
            raise Exception('Could not find a suitable make implementation.\n'
                'Please use MozillaBuild 1.9 or newer')
        else:
            raise Exception('Could not find a suitable make implementation.')

    def _run_command_in_srcdir(self, **args):
        return self.run_process(cwd=self.topsrcdir, **args)

    def _run_command_in_objdir(self, **args):
        return self.run_process(cwd=self.topobjdir, **args)

    def _is_windows(self):
        return os.name in ('nt', 'ce')

    def _is_osx(self):
        return 'darwin' in str(sys.platform).lower()

    def _spawn(self, cls):
        """Create a new MozbuildObject-derived class instance from ourselves.

        This is used as a convenience method to create other
        MozbuildObject-derived class instances. It can only be used on
        classes that have the same constructor arguments as us.
        """

        return cls(self.topsrcdir, self.settings, self.log_manager,
            topobjdir=self.topobjdir)

    def _activate_virtualenv(self):
        self.virtualenv_manager.ensure()
        self.virtualenv_manager.activate()


class MachCommandBase(MozbuildObject):
    """Base class for mach command providers that wish to be MozbuildObjects.

    This provides a level of indirection so MozbuildObject can be refactored
    without having to change everything that inherits from it.
    """

    def __init__(self, context):
        # Attempt to discover topobjdir through environment detection, as it is
        # more reliable than mozconfig when cwd is inside an objdir.
        topsrcdir = context.topdir
        topobjdir = None
        detect_virtualenv_mozinfo = True
        if hasattr(context, 'detect_virtualenv_mozinfo'):
            detect_virtualenv_mozinfo = getattr(context,
                'detect_virtualenv_mozinfo')
        try:
            dummy = MozbuildObject.from_environment(cwd=context.cwd,
                detect_virtualenv_mozinfo=detect_virtualenv_mozinfo)
            topsrcdir = dummy.topsrcdir
            topobjdir = dummy._topobjdir
        except BuildEnvironmentNotFoundException:
            pass
        except ObjdirMismatchException as e:
            print('Ambiguous object directory detected. We detected that '
                'both %s and %s could be object directories. This is '
                'typically caused by having a mozconfig pointing to a '
                'different object directory from the current working '
                'directory. To solve this problem, ensure you do not have a '
                'default mozconfig in searched paths.' % (e.objdir1,
                    e.objdir2))
            sys.exit(1)

        except MozconfigLoadException as e:
            print('Error loading mozconfig: ' + e.path)
            print('')
            print(e.message)
            if e.output:
                print('')
                print('mozconfig output:')
                print('')
                for line in e.output:
                    print(line)

            sys.exit(1)

        MozbuildObject.__init__(self, topsrcdir, context.settings,
            context.log_manager, topobjdir=topobjdir)

        self._mach_context = context

        # Incur mozconfig processing so we have unified error handling for
        # errors. Otherwise, the exceptions could bubble back to mach's error
        # handler.
        try:
            self.mozconfig

        except MozconfigFindException as e:
            print(e.message)
            sys.exit(1)

        except MozconfigLoadException as e:
            print('Error loading mozconfig: ' + e.path)
            print('')
            print(e.message)
            if e.output:
                print('')
                print('mozconfig output:')
                print('')
                for line in e.output:
                    print(line)

            sys.exit(1)

        # Always keep a log of the last command, but don't do that for mach
        # invokations from scripts (especially not the ones done by the build
        # system itself).
        if (self.log_manager and self.log_manager.terminal and
                not getattr(self, 'NO_AUTO_LOG', False)):
            self._ensure_state_subdir_exists('.')
            logfile = self._get_state_filename('last_log.json')
            try:
                fd = open(logfile, "wb")
                self.log_manager.add_json_handler(fd)
            except Exception as e:
                self.log(logging.WARNING, 'mach', {'error': e},
                         'Log will not be kept for this command: {error}.')


class MachCommandConditions(object):
    """A series of commonly used condition functions which can be applied to
    mach commands with providers deriving from MachCommandBase.
    """
    @staticmethod
    def is_firefox(cls):
        """Must have a Firefox build."""
        if hasattr(cls, 'substs'):
            return cls.substs.get('MOZ_BUILD_APP') == 'browser'
        return False

    @staticmethod
    def is_mulet(cls):
        """Must have a Mulet build."""
        if hasattr(cls, 'substs'):
            return cls.substs.get('MOZ_BUILD_APP') == 'b2g/dev'
        return False

    @staticmethod
    def is_b2g(cls):
        """Must have a B2G build."""
        if hasattr(cls, 'substs'):
            return cls.substs.get('MOZ_WIDGET_TOOLKIT') == 'gonk'
        return False

    @staticmethod
    def is_b2g_desktop(cls):
        """Must have a B2G desktop build."""
        if hasattr(cls, 'substs'):
            return cls.substs.get('MOZ_BUILD_APP') == 'b2g' and \
                   cls.substs.get('MOZ_WIDGET_TOOLKIT') != 'gonk'
        return False

    @staticmethod
    def is_emulator(cls):
        """Must have a B2G build with an emulator configured."""
        try:
            return MachCommandConditions.is_b2g(cls) and \
                   cls.device_name.startswith('emulator')
        except AttributeError:
            return False

    @staticmethod
    def is_android(cls):
        """Must have an Android build."""
        if hasattr(cls, 'substs'):
            return cls.substs.get('MOZ_WIDGET_TOOLKIT') == 'android'
        return False

    @staticmethod
    def is_hg(cls):
        """Must have a mercurial source checkout."""
        if hasattr(cls, 'substs'):
            top_srcdir = cls.substs.get('top_srcdir')
            return top_srcdir and os.path.isdir(os.path.join(top_srcdir, '.hg'))
        return False

    @staticmethod
    def is_git(cls):
        """Must have a git source checkout."""
        if hasattr(cls, 'substs'):
            top_srcdir = cls.substs.get('top_srcdir')
            return top_srcdir and os.path.isdir(os.path.join(top_srcdir, '.git'))
        return False


class PathArgument(object):
    """Parse a filesystem path argument and transform it in various ways."""

    def __init__(self, arg, topsrcdir, topobjdir, cwd=None):
        self.arg = arg
        self.topsrcdir = topsrcdir
        self.topobjdir = topobjdir
        self.cwd = os.getcwd() if cwd is None else cwd

    def relpath(self):
        """Return a path relative to the topsrcdir or topobjdir.

        If the argument is a path to a location in one of the base directories
        (topsrcdir or topobjdir), then strip off the base directory part and
        just return the path within the base directory."""

        abspath = os.path.abspath(os.path.join(self.cwd, self.arg))

        # If that path is within topsrcdir or topobjdir, return an equivalent
        # path relative to that base directory.
        for base_dir in [self.topobjdir, self.topsrcdir]:
            if abspath.startswith(os.path.abspath(base_dir)):
                return mozpath.relpath(abspath, base_dir)

        return mozpath.normsep(self.arg)

    def srcdir_path(self):
        return mozpath.join(self.topsrcdir, self.relpath())

    def objdir_path(self):
        return mozpath.join(self.topobjdir, self.relpath())


class ExecutionSummary(dict):
    """Helper for execution summaries."""

    def __init__(self, summary_format, **data):
        self._summary_format = ''
        assert 'execution_time' in data
        self.extend(summary_format, **data)

    def extend(self, summary_format, **data):
        self._summary_format += summary_format
        self.update(data)

    def __str__(self):
        return self._summary_format.format(**self)

    def __getattr__(self, key):
        return self[key]
