DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Mercurial (23c4fa49cc5c)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
#!/bin/sh
# 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/.

# The beginning of this script is both valid POSIX shell and valid Python,
# such that the script starts with the shell and is reexecuted with
# the right Python.

# Embeds a shell script inside a Python triple quote. This pattern is valid
# shell because `''':'`, `':'` and `:` are all equivalent, and `:` is a no-op.
''':'
py2commands="
    addtest
    analyze
    android
    android-emulator
    artifact
    awsy-test
    bootstrap
    browsertime
    build
    build-backend
    buildsymbols
    busted
    cargo
    check-spidermonkey
    clang-format
    compare-locales
    compileflags
    configure
    cppunittest
    cramtest
    crashtest
    devtools-css-db
    doc
    doctor
    empty-makefiles
    environment
    eslint
    file-info
    firefox-ui-functional
    fluent-migration-test
    geckodriver
    geckodriver-test
    geckoview-junit
    gradle
    gtest
    ide
    import-pr
    install
    install-android
    install-desktop
    jsapi-tests
    jsshell-bench
    jstestbrowser
    jstests
    lint
    mach-commands
    mach-completion
    mach-debug-commands
    marionette-test
    mochitest
    mozbuild-reference
    mozharness
    mozregression
    package
    package-multi-locale
    pastebin
    power
    prettier-format
    puppeteer-test
    python
    python-safety
    python-test
    raptor
    raptor-test
    reftest
    release
    release-history
    remote
    repackage
    resource-usage
    robocop
    run
    run-android
    run-desktop
    rusttests
    settings
    show-log
    static-analysis
    talos-test
    taskcluster-build-image
    taskcluster-load-image
    taskgraph
    telemetry-tests-client
    test
    test-info
    tps-build
    try
    uuid
    valgrind-test
    vcs-setup
    vendor
    visualmetrics
    warnings-list
    warnings-summary
    watch
    web-platform-tests
    web-platform-tests-update
    webidl-example
    webidl-parser-test
    webrtc-gtest
    wpt
    wpt-manifest-update
    wpt-metadata-merge
    wpt-metadata-summary
    wpt-serve
    wpt-unittest
    wpt-update
    xpcshell-test
"

run_py() {
    # Try to run a specific Python interpreter. Fall back to the system
    # default Python if the specific interpreter couldn't be found.
    py_executable="$1"
    shift
    if which "$py_executable" > /dev/null
    then
        exec "$py_executable" "$0" "$@"
    elif [ "$py_executable" = "python2.7" ]; then
        exec python "$0" "$@"
    else
        echo "This mach command requires $py_executable, which wasn't found on the system!"
        exit 1
    fi
}

first_arg=$1
if [ -z "$first_arg" ]; then
    run_py python3
fi

case "${first_arg}" in
    "-"*)
        # We have global arguments which are tricky to parse from this shell
        # script. So invoke `mach` with a special --print-command argument to
        # return the name of the command. This adds extra overhead when using
        # global arguments, but global arguments are an edge case and this hack
        # is only needed temporarily for the Python 3 migration. We use Python
        # 2.7 because using Python 3 hits this error in build tasks:
        # https://searchfox.org/mozilla-central/rev/c7e8bc4996f9/build/moz.configure/init.configure#319
        command=`run_py python2.7 --print-command "$@" | tail -n1`
        ;;
    *)
        # In the common case, the first argument is the command.
        command=${first_arg};
        ;;
esac

# Check for the mach subcommand in the Python 2 commands list and run it
# with the correct interpreter.
case " $(echo $py2commands) " in
    *\ $command\ *)
        run_py python2.7 "$@"
        ;;
    *)
        run_py python3 "$@"
        ;;
esac

# Run Python 3 for everything else.
run_py python3 "$@"
'''

from __future__ import absolute_import, print_function, unicode_literals

import os
import sys

def ancestors(path):
    while path:
        yield path
        (path, child) = os.path.split(path)
        if child == "":
            break

def load_mach(dir_path, mach_path):
    if sys.version_info < (3, 5):
        import imp
        mach_bootstrap = imp.load_source('mach_bootstrap', mach_path)
    else:
        import importlib.util
        spec = importlib.util.spec_from_file_location('mach_bootstrap', mach_path)
        mach_bootstrap = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(mach_bootstrap)

    return mach_bootstrap.bootstrap(dir_path)


def check_and_get_mach(dir_path):
    bootstrap_paths = (
        'build/mach_bootstrap.py',
        # test package bootstrap
        'tools/mach_bootstrap.py',
    )
    for bootstrap_path in bootstrap_paths:
        mach_path = os.path.join(dir_path, bootstrap_path)
        if os.path.isfile(mach_path):
            return load_mach(dir_path, mach_path)
    return None


def get_mach():
    # Check whether the current directory is within a mach src or obj dir.
    for dir_path in ancestors(os.getcwd()):
        # If we find a "config.status" and "mozinfo.json" file, we are in the objdir.
        config_status_path = os.path.join(dir_path, 'config.status')
        mozinfo_path = os.path.join(dir_path, 'mozinfo.json')
        if os.path.isfile(config_status_path) and os.path.isfile(mozinfo_path):
            import json
            info = json.load(open(mozinfo_path))
            if 'mozconfig' in info and 'MOZCONFIG' not in os.environ:
                # If the MOZCONFIG environment variable is not already set, set it
                # to the value from mozinfo.json.  This will tell the build system
                # to look for a config file at the path in $MOZCONFIG rather than
                # its default locations.
                #
                # Note: subprocess requires native strings in os.environ on Windows
                os.environ[b'MOZCONFIG'] = str(info['mozconfig'])

            if 'topsrcdir' in info:
                # Continue searching for mach_bootstrap in the source directory.
                dir_path = info['topsrcdir']

        mach = check_and_get_mach(dir_path)
        if mach:
            return mach

    # If we didn't find a source path by scanning for a mozinfo.json, check
    # whether the directory containing this script is a source directory. We
    # follow symlinks so mach can be run even if cwd is outside the srcdir.
    return check_and_get_mach(os.path.dirname(os.path.realpath(__file__)))

def main(args):
    mach = get_mach()
    if not mach:
        print('Could not run mach: No mach source directory found.')
        sys.exit(1)
    sys.exit(mach.run(args))


if __name__ == '__main__':
    main(sys.argv[1:])