Bug 1058923 - Package mach in tests.zip; create bootstrap script for test package, r=gps
☠☠ backed out by 5a72e3728487 ☠ ☠
authorAndrew Halberstadt <ahalberstadt@mozilla.com>
Fri, 01 May 2015 12:20:55 -0400
changeset 243718 7923a0c837b56efcd1376b95318fe4cdce03d5e8
parent 243664 1c91f5d39dea877e84bf75f38d7772c8893c1933
child 243719 aaa61c18c5d28046739d599bb37110dea241cb7b
push id28753
push userkwierso@gmail.com
push dateThu, 14 May 2015 22:33:43 +0000
treeherdermozilla-central@07e2e15703cb [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
mach
testing/testsuite-targets.mk
testing/tools/mach_test_package_bootstrap.py
--- 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 \
@@ -439,24 +440,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