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 263152 7923a0c837b56efcd1376b95318fe4cdce03d5e8
parent 263143 1c91f5d39dea877e84bf75f38d7772c8893c1933
child 263153 aaa61c18c5d28046739d599bb37110dea241cb7b
push idunknown
push userunknown
push dateunknown
reviewersgps
bugs1058923
milestone41.0a1
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