Bug 1058923 - Package mach in tests.zip; create bootstrap script for test package. r=gps, a=test-only
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -32,16 +32,17 @@ SEARCH_PATHS = [
'python/blessings',
'python/compare-locales',
'python/configobj',
'python/jsmin',
'python/psutil',
'python/which',
'python/pystache',
'python/pyyaml/lib',
+ 'build',
'build/pymake',
'config',
'dom/bindings',
'dom/bindings/parser',
'layout/tools/reftest',
'other-licenses/ply',
'xpcom/idl-parser',
'testing',
--- a/mach
+++ b/mach
@@ -16,29 +16,38 @@ import sys
def ancestors(path):
while path:
yield path
(path, child) = os.path.split(path)
if child == "":
break
-def load_mach(topsrcdir):
- sys.path[0:0] = [os.path.join(topsrcdir, "build")]
+def load_mach(dir_path, mach_path):
+ import imp
+ with open(mach_path, 'r') as fh:
+ imp.load_module('mach_bootstrap', fh, mach_path,
+ ('.py', 'r', imp.PY_SOURCE))
import mach_bootstrap
- return mach_bootstrap.bootstrap(topsrcdir)
+ return mach_bootstrap.bootstrap(dir_path)
def check_and_get_mach(dir_path):
- # If we find the mach bootstrap module, we are in the srcdir.
- mach_path = os.path.join(dir_path, 'build/mach_bootstrap.py')
- if os.path.isfile(mach_path):
- return load_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 "mozinfo.json" file, we are in the objdir.
mozinfo_path = os.path.join(dir_path, 'mozinfo.json')
if os.path.isfile(mozinfo_path):
import json
info = json.load(open(mozinfo_path))
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -388,16 +388,17 @@ pgo-profile-run:
# Package up the tests and test harnesses
include $(topsrcdir)/toolkit/mozapps/installer/package-name.mk
ifndef UNIVERSAL_BINARY
PKG_STAGE = $(DIST)/test-stage
package-tests: \
stage-config \
+ stage-mach \
stage-mochitest \
stage-reftest \
stage-xpcshell \
stage-jstests \
stage-jetpack \
stage-mozbase \
stage-tps \
stage-modules \
@@ -447,24 +448,30 @@ make-stage-dir:
$(NSINSTALL) -D $(PKG_STAGE)
$(NSINSTALL) -D $(PKG_STAGE)/bin
$(NSINSTALL) -D $(PKG_STAGE)/bin/components
$(NSINSTALL) -D $(PKG_STAGE)/certs
$(NSINSTALL) -D $(PKG_STAGE)/config
$(NSINSTALL) -D $(PKG_STAGE)/jetpack
$(NSINSTALL) -D $(PKG_STAGE)/mozbase
$(NSINSTALL) -D $(PKG_STAGE)/modules
+ $(NSINSTALL) -D $(PKG_STAGE)/tools/mach
stage-b2g: make-stage-dir
$(NSINSTALL) $(topsrcdir)/b2g/test/b2g-unittest-requirements.txt $(PKG_STAGE)/b2g
stage-config: make-stage-dir
$(NSINSTALL) -D $(PKG_STAGE)/config
@(cd $(topsrcdir)/testing/config && tar $(TAR_CREATE_FLAGS) - *) | (cd $(PKG_STAGE)/config && tar -xf -)
+stage-mach: make-stage-dir
+ @(cd $(topsrcdir)/python/mach && tar $(TAR_CREATE_FLAGS) - *) | (cd $(PKG_STAGE)/tools/mach && tar -xf -)
+ cp $(topsrcdir)/testing/tools/mach_test_package_bootstrap.py $(PKG_STAGE)/tools/mach_bootstrap.py
+ cp $(topsrcdir)/mach $(PKG_STAGE)
+
stage-mochitest: make-stage-dir
$(MAKE) -C $(DEPTH)/testing/mochitest stage-package
ifeq ($(MOZ_BUILD_APP),mobile/android)
$(NSINSTALL) $(DEPTH)/mobile/android/base/fennec_ids.txt $(PKG_STAGE)/mochitest
endif
stage-reftest: make-stage-dir
$(MAKE) -C $(DEPTH)/layout/tools/reftest stage-package
new file mode 100644
--- /dev/null
+++ b/testing/tools/mach_test_package_bootstrap.py
@@ -0,0 +1,75 @@
+# 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 print_function, unicode_literals
+
+import os
+import platform
+import sys
+import time
+
+
+SEARCH_PATHS = [
+ 'tools/mach',
+]
+
+# Individual files providing mach commands.
+MACH_MODULES = [
+ 'tools/mach/mach/commands/commandinfo.py',
+]
+
+
+CATEGORIES = {
+ 'testing': {
+ 'short': 'Testing',
+ 'long': 'Run tests.',
+ 'priority': 30,
+ },
+ 'devenv': {
+ 'short': 'Development Environment',
+ 'long': 'Set up and configure your development environment.',
+ 'priority': 20,
+ },
+ 'misc': {
+ 'short': 'Potpourri',
+ 'long': 'Potent potables and assorted snacks.',
+ 'priority': 10,
+ },
+ 'disabled': {
+ 'short': 'Disabled',
+ 'long': 'The disabled commands are hidden by default. Use -v to display them. These commands are unavailable for your current context, run "mach <command>" to see why.',
+ 'priority': 0,
+ }
+}
+
+
+def bootstrap(test_package_root):
+ # Ensure we are running Python 2.7+. We put this check here so we generate a
+ # user-friendly error message rather than a cryptic stack trace on module
+ # import.
+ if sys.version_info[0] != 2 or sys.version_info[1] < 7:
+ print('Python 2.7 or above (but not Python 3) is required to run mach.')
+ print('You are running Python', platform.python_version())
+ sys.exit(1)
+
+ try:
+ import mach.main
+ except ImportError:
+ sys.path[0:0] = [os.path.join(test_package_root, path) for path in SEARCH_PATHS]
+ import mach.main
+
+ def populate_context(context, key=None):
+ return context
+
+ mach = mach.main.Mach(os.getcwd())
+ mach.populate_context_handler = populate_context
+
+ for category, meta in CATEGORIES.items():
+ mach.define_category(category, meta['short'], meta['long'],
+ meta['priority'])
+
+ for path in MACH_MODULES:
+ mach.load_commands_from_file(os.path.join(test_package_root, path))
+
+ return mach