1# This Source Code Form is subject to the terms of the Mozilla Public
2# License, v. 2.0. If a copy of the MPL was not distributed with this
3# file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5from __future__ import absolute_import, print_function
6
7from mozboot.base import BaseBootstrapper
8from mozboot.linux_common import StyloInstall
9
10
11MERCURIAL_INSTALL_PROMPT = '''
12Mercurial releases a new version every 3 months and your distro's package
13may become out of date. This may cause incompatibility with some
14Mercurial extensions that rely on new Mercurial features. As a result,
15you may not have an optimal version control experience.
16
17To have the best Mercurial experience possible, we recommend installing
18Mercurial via the "pip" Python packaging utility. This will likely result
19in files being placed in /usr/local/bin and /usr/local/lib.
20
21How would you like to continue?
22
231) Install a modern Mercurial via pip (recommended)
242) Install a legacy Mercurial via apt
253) Do not install Mercurial
26
27Choice:
28'''.strip()
29
30
31class DebianBootstrapper(StyloInstall, BaseBootstrapper):
32    # These are common packages for all Debian-derived distros (such as
33    # Ubuntu).
34    COMMON_PACKAGES = [
35        'autoconf2.13',
36        'build-essential',
37        'ccache',
38        'nodejs',
39        'python-dev',
40        'python-pip',
41        'python-setuptools',
42        'unzip',
43        'uuid',
44        'zip',
45    ]
46
47    # Subclasses can add packages to this variable to have them installed.
48    DISTRO_PACKAGES = []
49
50    # Ubuntu and Debian don't often differ, but they do for npm.
51    DEBIAN_PACKAGES = [
52        # Comment the npm package until Debian bring it back
53        # 'npm'
54    ]
55
56    # These are common packages for building Firefox for Desktop
57    # (browser) for all Debian-derived distros (such as Ubuntu).
58    BROWSER_COMMON_PACKAGES = [
59        'libasound2-dev',
60        'libcurl4-openssl-dev',
61        'libdbus-1-dev',
62        'libdbus-glib-1-dev',
63        'libgconf2-dev',
64        'libgtk-3-dev',
65        'libgtk2.0-dev',
66        'libpulse-dev',
67        'libx11-xcb-dev',
68        'libxt-dev',
69        'python-dbus',
70        'xvfb',
71        'yasm',
72    ]
73
74    # Subclasses can add packages to this variable to have them installed.
75    BROWSER_DISTRO_PACKAGES = []
76
77    # These are common packages for building Firefox for Android
78    # (mobile/android) for all Debian-derived distros (such as Ubuntu).
79    MOBILE_ANDROID_COMMON_PACKAGES = [
80        'default-jdk',
81        'wget',  # For downloading the Android SDK and NDK.
82        'libncurses5:i386',  # See comments about i386 below.
83        'libstdc++6:i386',
84    ]
85
86    # Subclasses can add packages to this variable to have them installed.
87    MOBILE_ANDROID_DISTRO_PACKAGES = []
88
89    def __init__(self, distro, version, dist_id, **kwargs):
90        BaseBootstrapper.__init__(self, **kwargs)
91
92        self.distro = distro
93        self.version = version
94        self.dist_id = dist_id
95
96        self.packages = self.COMMON_PACKAGES + self.DISTRO_PACKAGES
97        if self.distro == 'Debian' or self.distro == 'debian':
98            self.packages += self.DEBIAN_PACKAGES
99        self.browser_packages = self.BROWSER_COMMON_PACKAGES + self.BROWSER_DISTRO_PACKAGES
100        self.mobile_android_packages = self.MOBILE_ANDROID_COMMON_PACKAGES + \
101            self.MOBILE_ANDROID_DISTRO_PACKAGES
102
103    def install_system_packages(self):
104        self.apt_install(*self.packages)
105
106    def install_browser_packages(self):
107        self.ensure_browser_packages()
108
109    def install_browser_artifact_mode_packages(self):
110        self.ensure_browser_packages(artifact_mode=True)
111
112    def install_mobile_android_packages(self):
113        self.ensure_mobile_android_packages()
114
115    def install_mobile_android_artifact_mode_packages(self):
116        self.ensure_mobile_android_packages(artifact_mode=True)
117
118    def ensure_browser_packages(self, artifact_mode=False):
119        # TODO: Figure out what not to install for artifact mode
120        self.apt_install(*self.browser_packages)
121
122    def ensure_mobile_android_packages(self, artifact_mode=False):
123        # Multi-part process:
124        # 1. System packages.
125        # 2. Android SDK. Android NDK only if we are not in artifact mode. Android packages.
126
127        # 1. This is hard to believe, but the Android SDK binaries are 32-bit
128        # and that conflicts with 64-bit Debian and Ubuntu installations out of
129        # the box.  The solution is to add the i386 architecture.  See
130        # "Troubleshooting Ubuntu" at
131        # http://developer.android.com/sdk/installing/index.html?pkg=tools.
132        self.run_as_root(['dpkg', '--add-architecture', 'i386'])
133        # After adding a new arch, the list of packages has to be updated
134        self.apt_update()
135        self.apt_install(*self.mobile_android_packages)
136
137        # 2. Android pieces.
138        from mozboot import android
139        android.ensure_android('linux', artifact_mode=artifact_mode,
140                               no_interactive=self.no_interactive)
141
142    def suggest_mobile_android_mozconfig(self, artifact_mode=False):
143        from mozboot import android
144        android.suggest_mozconfig('linux', artifact_mode=artifact_mode)
145
146    def suggest_mobile_android_artifact_mode_mozconfig(self):
147        self.suggest_mobile_android_mozconfig(artifact_mode=True)
148
149    def _update_package_manager(self):
150        self.apt_update()
151
152    def upgrade_mercurial(self, current):
153        """Install Mercurial from pip because Debian packages typically lag."""
154        if self.no_interactive:
155            # Install via Apt in non-interactive mode because it is the more
156            # conservative option and less likely to make people upset.
157            self.apt_install('mercurial')
158            return
159
160        res = self.prompt_int(MERCURIAL_INSTALL_PROMPT, 1, 3)
161
162        # Apt.
163        if res == 2:
164            self.apt_install('mercurial')
165            return False
166
167        # No Mercurial.
168        if res == 3:
169            print('Not installing Mercurial.')
170            return False
171
172        # pip.
173        assert res == 1
174        self.run_as_root(['pip', 'install', '--upgrade', 'Mercurial'])
175