|
@@ -0,0 +1,412 @@
|
|
|
+# HG changeset patch
|
|
|
+# User Ricky Stewart <rstewart@mozilla.com>
|
|
|
+# Date 1594309727 0
|
|
|
+# Node ID 7a29f8f30a7badfbb110952bb195c12f11fb0494
|
|
|
+# Parent c37c9629565cd065074c33ed110cf18702037853
|
|
|
+Bug 1651403 - Clean up `bootstrap` code post-Python 3 migration r=nalexander
|
|
|
+
|
|
|
+Since bug 1647865, we're no longer allowing `bootstrap` to be run with Python 2. Therefore we have leeway to make a bunch of simplifications.
|
|
|
+
|
|
|
+Differential Revision: https://phabricator.services.mozilla.com/D82737
|
|
|
+
|
|
|
+diff --git a/python/mozboot/mozboot/base.py b/python/mozboot/mozboot/base.py
|
|
|
+--- a/python/mozboot/mozboot/base.py
|
|
|
++++ b/python/mozboot/mozboot/base.py
|
|
|
+@@ -417,24 +417,16 @@ class BaseBootstrapper(object):
|
|
|
+ self.run_as_root(command)
|
|
|
+
|
|
|
+ def apt_add_architecture(self, arch):
|
|
|
+ command = ['dpkg', '--add-architecture']
|
|
|
+ command.extend(arch)
|
|
|
+
|
|
|
+ self.run_as_root(command)
|
|
|
+
|
|
|
+- def check_output(self, *args, **kwargs):
|
|
|
+- """Run subprocess.check_output even if Python doesn't provide it."""
|
|
|
+- # TODO Legacy Python 2.6 code, can be removed.
|
|
|
+- # We had a custom check_output() function for Python 2.6 backward
|
|
|
+- # compatibility. Since py2.6 support was dropped we can remove this
|
|
|
+- # method.
|
|
|
+- return subprocess.check_output(*args, **kwargs)
|
|
|
+-
|
|
|
+ def prompt_int(self, prompt, low, high, limit=5):
|
|
|
+ ''' Prompts the user with prompt and requires an integer between low and high. '''
|
|
|
+ valid = False
|
|
|
+ while not valid and limit > 0:
|
|
|
+ try:
|
|
|
+ choice = int(input(prompt))
|
|
|
+ if not low <= choice <= high:
|
|
|
+ print("ERROR! Please enter a valid option!")
|
|
|
+@@ -492,21 +484,21 @@ class BaseBootstrapper(object):
|
|
|
+ variable during the invocation to set options, PATH,
|
|
|
+ etc.
|
|
|
+ '''
|
|
|
+ if not name:
|
|
|
+ name = os.path.basename(path)
|
|
|
+ if name.endswith('.exe'):
|
|
|
+ name = name[:-4]
|
|
|
+
|
|
|
+- info = self.check_output([path, version_param],
|
|
|
+- env=env,
|
|
|
+- stderr=subprocess.STDOUT,
|
|
|
+- universal_newlines=True)
|
|
|
++ info = subprocess.check_output(
|
|
|
++ [path, version_param], env=env, stderr=subprocess.STDOUT,
|
|
|
++ universal_newlines=True)
|
|
|
+ match = re.search(name + ' ([a-z0-9\.]+)', info)
|
|
|
++
|
|
|
+ if not match:
|
|
|
+ print('ERROR! Unable to identify %s version.' % name)
|
|
|
+ return None
|
|
|
+
|
|
|
+ return LooseVersion(match.group(1))
|
|
|
+
|
|
|
+ def _parse_version(self, path, name=None, env=None):
|
|
|
+ return self._parse_version_impl(path, name, env, "--version")
|
|
|
+diff --git a/python/mozboot/mozboot/bootstrap.py b/python/mozboot/mozboot/bootstrap.py
|
|
|
+--- a/python/mozboot/mozboot/bootstrap.py
|
|
|
++++ b/python/mozboot/mozboot/bootstrap.py
|
|
|
+@@ -373,17 +373,16 @@ class Bootstrapper(object):
|
|
|
+ raise Exception('Please pick a valid application choice: (%s)' %
|
|
|
+ '/'.join(APPLICATIONS.keys()))
|
|
|
+
|
|
|
+ if self.instance.no_system_changes:
|
|
|
+ state_dir_available, state_dir = self.try_to_create_state_dir()
|
|
|
+ # We need to enable the loading of hgrc in case extensions are
|
|
|
+ # required to open the repo.
|
|
|
+ r = current_firefox_checkout(
|
|
|
+- check_output=self.instance.check_output,
|
|
|
+ env=self.instance._hg_cleanenv(load_hgrc=True),
|
|
|
+ hg=self.instance.which('hg'))
|
|
|
+ (checkout_type, checkout_root) = r
|
|
|
+ have_clone = bool(checkout_type)
|
|
|
+
|
|
|
+ self.maybe_install_private_packages_or_exit(state_dir,
|
|
|
+ state_dir_available,
|
|
|
+ have_clone,
|
|
|
+@@ -399,18 +398,17 @@ class Bootstrapper(object):
|
|
|
+ hg_installed, hg_modern = self.instance.ensure_mercurial_modern()
|
|
|
+ self.instance.ensure_python_modern()
|
|
|
+ self.instance.ensure_rust_modern()
|
|
|
+
|
|
|
+ state_dir_available, state_dir = self.try_to_create_state_dir()
|
|
|
+
|
|
|
+ # We need to enable the loading of hgrc in case extensions are
|
|
|
+ # required to open the repo.
|
|
|
+- r = current_firefox_checkout(check_output=self.instance.check_output,
|
|
|
+- env=self.instance._hg_cleanenv(load_hgrc=True),
|
|
|
++ r = current_firefox_checkout(env=self.instance._hg_cleanenv(load_hgrc=True),
|
|
|
+ hg=self.instance.which('hg'))
|
|
|
+ (checkout_type, checkout_root) = r
|
|
|
+
|
|
|
+ # If we didn't specify a VCS, and we aren't in an exiting clone,
|
|
|
+ # offer a choice
|
|
|
+ if not self.vcs:
|
|
|
+ if checkout_type and False:
|
|
|
+ vcs = checkout_type
|
|
|
+@@ -612,37 +610,36 @@ def hg_clone_firefox(hg, dest):
|
|
|
+ res = subprocess.call([hg, 'update', '-r', 'central'], cwd=dest)
|
|
|
+ if res:
|
|
|
+ print('error updating; you will need to `hg update` manually')
|
|
|
+
|
|
|
+ print('Firefox source code available at %s' % dest)
|
|
|
+ return True
|
|
|
+
|
|
|
+
|
|
|
+-def current_firefox_checkout(check_output, env, hg=None):
|
|
|
++def current_firefox_checkout(env, hg=None):
|
|
|
+ """Determine whether we're in a Firefox checkout.
|
|
|
+
|
|
|
+ Returns one of None, ``git``, or ``hg``.
|
|
|
+ """
|
|
|
+ HG_ROOT_REVISIONS = set([
|
|
|
+ # From mozilla-unified.
|
|
|
+ '8ba995b74e18334ab3707f27e9eb8f4e37ba3d29',
|
|
|
+ ])
|
|
|
+
|
|
|
+ path = os.getcwd()
|
|
|
+ while path:
|
|
|
+ hg_dir = os.path.join(path, '.hg')
|
|
|
+ git_dir = os.path.join(path, '.git')
|
|
|
+ if hg and os.path.exists(hg_dir):
|
|
|
+ # Verify the hg repo is a Firefox repo by looking at rev 0.
|
|
|
+ try:
|
|
|
+- node = check_output([hg, 'log', '-r', '0', '--template', '{node}'],
|
|
|
+- cwd=path,
|
|
|
+- env=env,
|
|
|
+- universal_newlines=True)
|
|
|
++ node = subprocess.check_output(
|
|
|
++ [hg, 'log', '-r', '0', '--template', '{node}'],
|
|
|
++ cwd=path, env=env, universal_newlines=True)
|
|
|
+ if node in HG_ROOT_REVISIONS:
|
|
|
+ return ('hg', path)
|
|
|
+ # Else the root revision is different. There could be nested
|
|
|
+ # repos. So keep traversing the parents.
|
|
|
+ except subprocess.CalledProcessError:
|
|
|
+ pass
|
|
|
+
|
|
|
+ # Just check for known-good files in the checkout, to prevent attempted
|
|
|
+diff --git a/python/mozboot/mozboot/debian.py b/python/mozboot/mozboot/debian.py
|
|
|
+--- a/python/mozboot/mozboot/debian.py
|
|
|
++++ b/python/mozboot/mozboot/debian.py
|
|
|
+@@ -1,14 +1,16 @@
|
|
|
+ # 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 absolute_import, print_function, unicode_literals
|
|
|
+
|
|
|
++import subprocess
|
|
|
++
|
|
|
+ from mozboot.base import BaseBootstrapper
|
|
|
+ from mozboot.linux_common import LinuxBootstrapper
|
|
|
+
|
|
|
+
|
|
|
+ MERCURIAL_INSTALL_PROMPT = '''
|
|
|
+ Mercurial releases a new version every 3 months and your distro's package
|
|
|
+ may become out of date. This may cause incompatibility with some
|
|
|
+ Mercurial extensions that rely on new Mercurial features. As a result,
|
|
|
+@@ -99,17 +101,17 @@ class DebianBootstrapper(
|
|
|
+ # Python 3 may not be present on all distros. Search for it and
|
|
|
+ # install if found.
|
|
|
+ packages = list(self.packages)
|
|
|
+
|
|
|
+ have_python3 = any([self.which('python3'), self.which('python3.6'),
|
|
|
+ self.which('python3.5')])
|
|
|
+
|
|
|
+ if not have_python3:
|
|
|
+- python3_packages = self.check_output(
|
|
|
++ python3_packages = subprocess.check_output(
|
|
|
+ ['apt-cache', 'pkgnames', 'python3'], universal_newlines=True)
|
|
|
+ python3_packages = python3_packages.splitlines()
|
|
|
+
|
|
|
+ if 'python3' in python3_packages:
|
|
|
+ packages.extend(['python3', 'python3-dev'])
|
|
|
+
|
|
|
+ self.apt_install(*packages)
|
|
|
+
|
|
|
+diff --git a/python/mozboot/mozboot/osx.py b/python/mozboot/mozboot/osx.py
|
|
|
+--- a/python/mozboot/mozboot/osx.py
|
|
|
++++ b/python/mozboot/mozboot/osx.py
|
|
|
+@@ -224,18 +224,18 @@ class OSXBootstrapper(BaseBootstrapper):
|
|
|
+ # OS X 10.7 have Xcode come from the app store. However, users can
|
|
|
+ # still install Xcode into any arbitrary location. We honor the
|
|
|
+ # location of Xcode as set by xcode-select. This should also pick up
|
|
|
+ # developer preview releases of Xcode, which can be installed into
|
|
|
+ # paths like /Applications/Xcode5-DP6.app.
|
|
|
+ elif self.os_version >= StrictVersion('10.7'):
|
|
|
+ select = self.which('xcode-select')
|
|
|
+ try:
|
|
|
+- output = self.check_output([select, '--print-path'],
|
|
|
+- stderr=subprocess.STDOUT)
|
|
|
++ output = subprocess.check_output([select, '--print-path'],
|
|
|
++ stderr=subprocess.STDOUT)
|
|
|
+ except subprocess.CalledProcessError as e:
|
|
|
+ # This seems to appear on fresh OS X machines before any Xcode
|
|
|
+ # has been installed. It may only occur on OS X 10.9 and later.
|
|
|
+ if b'unable to get active developer directory' in e.output:
|
|
|
+ print(XCODE_NO_DEVELOPER_DIRECTORY)
|
|
|
+ self._install_xcode_app_store()
|
|
|
+ assert False # Above should exit.
|
|
|
+
|
|
|
+diff --git a/python/mozboot/mozboot/osx.py.1651403.later b/python/mozboot/mozboot/osx.py.1651403.later
|
|
|
+new file mode 100644
|
|
|
+--- /dev/null
|
|
|
++++ b/python/mozboot/mozboot/osx.py.1651403.later
|
|
|
+@@ -0,0 +1,152 @@
|
|
|
++--- osx.py
|
|
|
+++++ osx.py
|
|
|
++Add https://bugzilla.mozilla.org/show_bug.cgi?id=1569046
|
|
|
++before fixing the .later file
|
|
|
++
|
|
|
++@@ -246,39 +246,39 @@ class OSXBootstrapper(BaseBootstrapper):
|
|
|
++ if b'.app/' not in output:
|
|
|
++ print(XCODE_REQUIRED)
|
|
|
++ self._install_xcode_app_store()
|
|
|
++ assert False # Above should exit.
|
|
|
++
|
|
|
++ # Once Xcode is installed, you need to agree to the license before you can
|
|
|
++ # use it.
|
|
|
++ try:
|
|
|
++- output = self.check_output(['/usr/bin/xcrun', 'clang'],
|
|
|
++- stderr=subprocess.STDOUT)
|
|
|
+++ output = subprocess.check_output(['/usr/bin/xcrun', 'clang'],
|
|
|
+++ stderr=subprocess.STDOUT)
|
|
|
++ except subprocess.CalledProcessError as e:
|
|
|
++ if b'license' in e.output:
|
|
|
++ xcodebuild = self.which('xcodebuild')
|
|
|
++ try:
|
|
|
++- self.check_output([xcodebuild, '-license'],
|
|
|
++- stderr=subprocess.STDOUT)
|
|
|
+++ subprocess.check_output([xcodebuild, '-license'],
|
|
|
+++ stderr=subprocess.STDOUT)
|
|
|
++ except subprocess.CalledProcessError as e:
|
|
|
++ if b'requires admin privileges' in e.output:
|
|
|
++ self.run_as_root([xcodebuild, '-license'])
|
|
|
++
|
|
|
++ # Even then we're not done! We need to install the Xcode command line tools.
|
|
|
++ # As of Mountain Lion, apparently the only way to do this is to go through a
|
|
|
++ # menu dialog inside Xcode itself. We're not making this up.
|
|
|
++ if self.os_version >= StrictVersion('10.7'):
|
|
|
++ if not os.path.exists('/usr/bin/clang'):
|
|
|
++ print(XCODE_COMMAND_LINE_TOOLS_MISSING)
|
|
|
++ print(INSTALL_XCODE_COMMAND_LINE_TOOLS_STEPS)
|
|
|
++ sys.exit(1)
|
|
|
++
|
|
|
++- output = self.check_output(['/usr/bin/clang', '--version'],
|
|
|
++- universal_newlines=True)
|
|
|
+++ output = subprocess.check_output(['/usr/bin/clang', '--version'],
|
|
|
+++ universal_newlines=True)
|
|
|
++ match = RE_CLANG_VERSION.search(output)
|
|
|
++ if match is None:
|
|
|
++ raise Exception('Could not determine Clang version.')
|
|
|
++
|
|
|
++ version = StrictVersion(match.group(1))
|
|
|
++
|
|
|
++ if version < APPLE_CLANG_MINIMUM_VERSION:
|
|
|
++ print(UPGRADE_XCODE_COMMAND_LINE_TOOLS)
|
|
|
++@@ -297,25 +297,25 @@ class OSXBootstrapper(BaseBootstrapper):
|
|
|
++ # which('brew') is found.
|
|
|
++ assert self.brew is not None
|
|
|
++
|
|
|
++ def _ensure_homebrew_packages(self, packages, extra_brew_args=[]):
|
|
|
++ self._ensure_homebrew_found()
|
|
|
++ self._ensure_package_manager_updated()
|
|
|
++ cmd = [self.brew] + extra_brew_args
|
|
|
++
|
|
|
++- installed = set(self.check_output(cmd + ['list'],
|
|
|
++- universal_newlines=True).split())
|
|
|
+++ installed = set(subprocess.check_output(
|
|
|
+++ cmd + ['list'], universal_newlines=True).split())
|
|
|
++ to_install = set(
|
|
|
++ package for package in packages if package not in installed)
|
|
|
++
|
|
|
++ # The "--quiet" tells "brew" to only list the package names, and not the
|
|
|
++ # comparison between current and new version.
|
|
|
++- outdated = set(self.check_output(cmd + ['outdated', '--quiet'],
|
|
|
++- universal_newlines=True).split())
|
|
|
+++ outdated = set(subprocess.check_output(cmd + ['outdated', '--quiet'],
|
|
|
+++ universal_newlines=True).split())
|
|
|
++ to_upgrade = set(package for package in packages if package in outdated)
|
|
|
++
|
|
|
++ if to_install or to_upgrade:
|
|
|
++ print(PACKAGE_MANAGER_PACKAGES % ('Homebrew',))
|
|
|
++ if 'python@2' in to_install:
|
|
|
++ # Special handling for Python 2 since brew can't install it
|
|
|
++ # out-of-the-box any more.
|
|
|
++ to_install.remove('python@2')
|
|
|
++@@ -327,28 +327,29 @@ class OSXBootstrapper(BaseBootstrapper):
|
|
|
++ if to_install:
|
|
|
++ subprocess.check_call(cmd + ['install'] + list(to_install))
|
|
|
++ if to_upgrade:
|
|
|
++ subprocess.check_call(cmd + ['upgrade'] + list(to_upgrade))
|
|
|
++
|
|
|
++ def _ensure_homebrew_casks(self, casks):
|
|
|
++ self._ensure_homebrew_found()
|
|
|
++
|
|
|
++- known_taps = self.check_output([self.brew, 'tap'])
|
|
|
+++ known_taps = subprocess.check_output([self.brew, 'tap'])
|
|
|
++
|
|
|
++ # Ensure that we can access old versions of packages.
|
|
|
++ if b'homebrew/cask-versions' not in known_taps:
|
|
|
++- self.check_output([self.brew, 'tap', 'homebrew/cask-versions'])
|
|
|
+++ subprocess.check_output([self.brew, 'tap',
|
|
|
+++ 'homebrew/cask-versions'])
|
|
|
++
|
|
|
++ # "caskroom/versions" has been renamed to "homebrew/cask-versions", so
|
|
|
++ # it is safe to remove the old tap. Removing the old tap is necessary
|
|
|
++ # to avoid the error "Cask [name of cask] exists in multiple taps".
|
|
|
++ # See https://bugzilla.mozilla.org/show_bug.cgi?id=1544981
|
|
|
++ if b'caskroom/versions' in known_taps:
|
|
|
++- self.check_output([self.brew, 'untap', 'caskroom/versions'])
|
|
|
+++ subprocess.check_output([self.brew, 'untap', 'caskroom/versions'])
|
|
|
++
|
|
|
++ # Change |brew install cask| into |brew cask install cask|.
|
|
|
++ self._ensure_homebrew_packages(casks, extra_brew_args=['cask'])
|
|
|
++
|
|
|
++ def ensure_homebrew_system_packages(self, install_mercurial):
|
|
|
++ # We need to install Python because Mercurial requires the
|
|
|
++ # Python development headers which are missing from OS X (at
|
|
|
++ # least on 10.8) and because the build system wants a version
|
|
|
++@@ -410,17 +411,17 @@ class OSXBootstrapper(BaseBootstrapper):
|
|
|
++ from mozboot import android
|
|
|
++ return android.generate_mozconfig('macosx', artifact_mode=artifact_mode)
|
|
|
++
|
|
|
++ def _ensure_macports_packages(self, packages):
|
|
|
++ self.port = self.which('port')
|
|
|
++ assert self.port is not None
|
|
|
++
|
|
|
++ installed = set(
|
|
|
++- self.check_output(
|
|
|
+++ subprocess.check_output(
|
|
|
++ [self.port, 'installed'],
|
|
|
++ universal_newlines=True).split())
|
|
|
++
|
|
|
++ missing = [package for package in packages if package not in installed]
|
|
|
++ if missing:
|
|
|
++ print(PACKAGE_MANAGER_PACKAGES % ('MacPorts',))
|
|
|
++ self.run_as_root([self.port, '-v', 'install'] + missing)
|
|
|
++
|
|
|
++@@ -435,17 +436,17 @@ class OSXBootstrapper(BaseBootstrapper):
|
|
|
++ 'nodejs8'
|
|
|
++ ]
|
|
|
++ if install_mercurial:
|
|
|
++ packages.append('mercurial')
|
|
|
++
|
|
|
++ self._ensure_macports_packages(packages)
|
|
|
++
|
|
|
++ pythons = set(
|
|
|
++- self.check_output(
|
|
|
+++ subprocess.check_output(
|
|
|
++ [self.port, 'select', '--list', 'python'],
|
|
|
++ universal_newlines=True).split('\n'))
|
|
|
++ active = ''
|
|
|
++ for python in pythons:
|
|
|
++ if 'active' in python:
|
|
|
++ active = python
|
|
|
++ if 'python27' not in active:
|
|
|
++ self.run_as_root([self.port, 'select', '--set', 'python', 'python27'])
|
|
|
+diff --git a/python/mozboot/mozboot/void.py b/python/mozboot/mozboot/void.py
|
|
|
+--- a/python/mozboot/mozboot/void.py
|
|
|
++++ b/python/mozboot/mozboot/void.py
|
|
|
+@@ -17,16 +17,17 @@ class VoidBootstrapper(
|
|
|
+ BaseBootstrapper):
|
|
|
+
|
|
|
+ PACKAGES = [
|
|
|
+ 'autoconf213',
|
|
|
+ 'clang',
|
|
|
+ 'make',
|
|
|
+ 'mercurial',
|
|
|
+ 'nodejs',
|
|
|
++ 'python3-pip',
|
|
|
+ 'unzip',
|
|
|
+ 'zip',
|
|
|
+ ]
|
|
|
+
|
|
|
+ BROWSER_PACKAGES = [
|
|
|
+ 'dbus-devel',
|
|
|
+ 'dbus-glib-devel',
|
|
|
+ 'gtk+3-devel',
|
|
|
+@@ -49,22 +50,16 @@ class VoidBootstrapper(
|
|
|
+ self.distro = "void"
|
|
|
+ self.version = version
|
|
|
+ self.dist_id = dist_id
|
|
|
+
|
|
|
+ self.packages = self.PACKAGES
|
|
|
+ self.browser_packages = self.BROWSER_PACKAGES
|
|
|
+ self.mobile_android_packages = self.MOBILE_ANDROID_PACKAGES
|
|
|
+
|
|
|
+- # Check if we need Python2 or Python3 pip.
|
|
|
+- if sys.version_info[0] == 3:
|
|
|
+- self.packages.append('python3-pip')
|
|
|
+- else:
|
|
|
+- self.packages.append('python-pip')
|
|
|
+-
|
|
|
+ def run_as_root(self, command):
|
|
|
+ # VoidLinux doesn't support users sudo'ing most commands by default because of the group
|
|
|
+ # configuration.
|
|
|
+ if os.geteuid() != 0:
|
|
|
+ command = ['su', 'root', '-c', ' '.join(command)]
|
|
|
+
|
|
|
+ print('Executing as root:', subprocess.list2cmdline(command))
|
|
|
+
|