Bug 1407872 - Use Python yes-like pipe for --no-interactive in |mach bootstrap|. r=gbrown draft
authorNick Alexander <nalexander@mozilla.com>
Fri, 13 Oct 2017 11:48:52 -0700
changeset 680302 86289e692d646181d545457fc953610e165ee2df
parent 680024 196dadb2fe500e75c6fbddcac78106648676cf10
child 680303 63824f309d216eab06ea34a6db244eb299139f58
push id84453
push usernalexander@mozilla.com
push dateFri, 13 Oct 2017 20:04:33 +0000
reviewersgbrown
bugs1407872
milestone58.0a1
Bug 1407872 - Use Python yes-like pipe for --no-interactive in |mach bootstrap|. r=gbrown The old system was simply in place because I couldn't figure out how to pipe `yes | ...` in Python. This is good enough to replace it, and much less fragile since the license hashes change frequently. MozReview-Commit-ID: AhJJPqMKfUh
python/mozboot/mozboot/android.py
--- a/python/mozboot/mozboot/android.py
+++ b/python/mozboot/mozboot/android.py
@@ -169,35 +169,20 @@ def ensure_android(os_name, artifact_mod
     sdk_url = 'https://dl.google.com/android/repository/sdk-tools-{0}-3859397.zip'.format(os_tag)
     ndk_url = android_ndk_url(os_name)
 
     ensure_android_sdk_and_ndk(mozbuild_path, os_name,
                                sdk_path=sdk_path, sdk_url=sdk_url,
                                ndk_path=ndk_path, ndk_url=ndk_url,
                                artifact_mode=artifact_mode)
 
-    if no_interactive:
-        # Cribbed from observation and https://stackoverflow.com/a/38381577.
-        path = os.path.join(mozbuild_path, 'android-sdk-{0}'.format(os_name), 'licenses')
-        ensure_dir(path)
-
-        licenses = {
-            'android-sdk-license': '8933bad161af4178b1185d1a37fbf41ea5269c55',
-            'android-sdk-preview-license': '84831b9409646a918e30573bab4c9c91346d8abd',
-        }
-        for license, tag in licenses.items():
-            lname = os.path.join(path, license)
-            if not os.path.isfile(lname):
-                open(lname, 'w').write('\n{0}\n'.format(tag))
-
-
     # We expect the |sdkmanager| tool to be at
     # ~/.mozbuild/android-sdk-$OS_NAME/tools/bin/sdkmanager.
     sdkmanager_tool = os.path.join(sdk_path, 'tools', 'bin', 'sdkmanager')
-    ensure_android_packages(sdkmanager_tool=sdkmanager_tool)
+    ensure_android_packages(sdkmanager_tool=sdkmanager_tool, no_interactive=no_interactive)
 
 
 def ensure_android_sdk_and_ndk(mozbuild_path, os_name, sdk_path, sdk_url, ndk_path, ndk_url, artifact_mode):
     '''
     Ensure the Android SDK and NDK are found at the given paths.  If not, fetch
     and unpack the SDK and/or NDK from the given URLs into |mozbuild_path/{android-sdk-$OS_NAME,android-ndk-$VER}|.
     '''
 
@@ -223,28 +208,49 @@ def ensure_android_sdk_and_ndk(mozbuild_
     else:
         # The SDK archive used to include a top-level
         # android-sdk-$OS_NAME directory; it no longer does so.  We
         # preserve the old convention to smooth detecting existing SDK
         # installations.
         install_mobile_android_sdk_or_ndk(sdk_url, os.path.join(mozbuild_path, 'android-sdk-{0}'.format(os_name)))
 
 
-def ensure_android_packages(sdkmanager_tool, packages=None):
+def ensure_android_packages(sdkmanager_tool, packages=None, no_interactive=False):
     '''
     Use the given sdkmanager tool (like 'sdkmanager') to install required
     Android packages.
     '''
 
     # This tries to install all the required Android packages.  The user
     # may be prompted to agree to the Android license.
     package_file_name = os.path.abspath(os.path.join(os.path.dirname(__file__), 'android-packages.txt'))
     print(INSTALLING_ANDROID_PACKAGES % open(package_file_name, 'rt').read())
-    subprocess.check_call([sdkmanager_tool,
-                           '--package_file={0}'.format(package_file_name)])
+
+    args = [sdkmanager_tool, '--package_file={0}'.format(package_file_name)]
+    if not no_interactive:
+        subprocess.check_call(args)
+        return
+
+    # Emulate yes.  For a discussion of passing input to check_output,
+    # see https://stackoverflow.com/q/10103551.
+    yes = '\n'.join(['y']*100)
+    proc = subprocess.Popen(args,
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.STDOUT,
+                            stdin=subprocess.PIPE)
+    output, unused_err = proc.communicate(yes)
+
+    retcode = proc.poll()
+    if retcode:
+        cmd = args[0]
+        e = subprocess.CalledProcessError(retcode, cmd)
+        e.output = output
+        raise e
+
+    print(output)
 
 
 def suggest_mozconfig(os_name, artifact_mode=False):
     _mozbuild_path, sdk_path, ndk_path = get_paths(os_name)
     if artifact_mode:
         print(MOBILE_ANDROID_ARTIFACT_MODE_MOZCONFIG_TEMPLATE % (sdk_path))
     else:
         print(MOBILE_ANDROID_MOZCONFIG_TEMPLATE % (sdk_path, ndk_path))