Bug 1058923 - Package mach in tests.zip; create bootstrap script for test package, r=gps
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Fri, 01 May 2015 12:20:55 -0400
changeset 244638 fec6ff864e3c636b9c6c72b9f3b0026338a66d8e
parent 244637 48fa8f0a227c6addfa39fbf29cd564d9015f6ab9
child 244639 b96da992cb63a3b40400613775a4912d0ec5691b
push id28786
push usercbook@mozilla.com
push dateWed, 20 May 2015 13:54:15 +0000
treeherdermozilla-central@8d8df22fe72d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs1058923
milestone41.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1058923 - Package mach in tests.zip; create bootstrap script for test package, r=gps
build/mach_bootstrap.py
mach
testing/testsuite-targets.mk
testing/tools/mach_test_package_bootstrap.py
--- 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 \
@@ -444,24 +445,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