| // Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| package tasks; | |
| import java.io.BufferedReader; | |
| import java.io.File; | |
| import java.io.IOException; | |
| import java.io.InputStreamReader; | |
| import java.nio.charset.StandardCharsets; | |
| import java.util.ArrayList; | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import java.util.stream.Collectors; | |
| import javax.inject.Inject; | |
| import org.gradle.api.DefaultTask; | |
| import org.gradle.api.tasks.InputFiles; | |
| import org.gradle.api.tasks.OutputDirectory; | |
| import org.gradle.api.tasks.TaskAction; | |
| import org.gradle.internal.os.OperatingSystem; | |
| import org.gradle.workers.IsolationMode; | |
| import org.gradle.workers.WorkerExecutor; | |
| public class DownloadDependency extends DefaultTask { | |
| public enum Type { | |
| GOOGLE_STORAGE, | |
| X20 | |
| } | |
| private final WorkerExecutor workerExecutor; | |
| private Type type; | |
| private File outputDir; | |
| private File tarGzFile; | |
| private File sha1File; | |
| @Inject | |
| public DownloadDependency(WorkerExecutor workerExecutor) { | |
| this.workerExecutor = workerExecutor; | |
| } | |
| public void setType(Type type) { | |
| this.type = type; | |
| } | |
| public void setDependency(String dependency) { | |
| outputDir = new File(dependency); | |
| tarGzFile = new File(dependency + ".tar.gz"); | |
| sha1File = new File(dependency + ".tar.gz.sha1"); | |
| } | |
| @InputFiles | |
| public Collection<File> getInputFiles() { | |
| return Arrays.asList(sha1File, tarGzFile); | |
| } | |
| @OutputDirectory | |
| public File getOutputDir() { | |
| return outputDir; | |
| } | |
| public File getSha1File() { | |
| return sha1File; | |
| } | |
| public File getTarGzFile() { | |
| return tarGzFile; | |
| } | |
| @TaskAction | |
| public void execute() throws IOException, InterruptedException { | |
| // First run will write the tar.gz file, causing the second run to still be out-of-date. | |
| // Check if the modification time of the tar is newer than the sha in which case we are done. | |
| // Also, check the contents of the out directory because gradle appears to create it for us... | |
| if (outputDir.exists() | |
| && outputDir.isDirectory() | |
| && outputDir.list().length > 0 | |
| && tarGzFile.exists() | |
| && sha1File.lastModified() <= tarGzFile.lastModified()) { | |
| return; | |
| } | |
| if (outputDir.exists() && outputDir.isDirectory()) { | |
| outputDir.delete(); | |
| } | |
| workerExecutor.submit(RunDownload.class, config -> { | |
| config.setIsolationMode(IsolationMode.NONE); | |
| config.params(type, sha1File); | |
| }); | |
| } | |
| public static class RunDownload implements Runnable { | |
| private final Type type; | |
| private final File sha1File; | |
| @Inject | |
| public RunDownload(Type type, File sha1File) { | |
| this.type = type; | |
| this.sha1File = sha1File; | |
| } | |
| @Override | |
| public void run() { | |
| try { | |
| if (type == Type.GOOGLE_STORAGE) { | |
| downloadFromGoogleStorage(); | |
| } else if (type == Type.X20) { | |
| downloadFromX20(); | |
| } else { | |
| throw new RuntimeException("Unexpected or missing dependency type: " + type); | |
| } | |
| } catch (Exception e) { | |
| throw new RuntimeException(e); | |
| } | |
| } | |
| private void downloadFromGoogleStorage() throws IOException, InterruptedException { | |
| List<String> args = Arrays.asList("-n", "-b", "r8-deps", "-s", "-u", sha1File.toString()); | |
| if (OperatingSystem.current().isWindows()) { | |
| List<String> command = new ArrayList<>(); | |
| command.add("download_from_google_storage.bat"); | |
| command.addAll(args); | |
| runProcess(new ProcessBuilder().command(command)); | |
| } else { | |
| runProcess( | |
| new ProcessBuilder() | |
| .command("bash", "-c", "download_from_google_storage " + String.join(" ", args))); | |
| } | |
| } | |
| private void downloadFromX20() throws IOException, InterruptedException { | |
| if (OperatingSystem.current().isWindows()) { | |
| throw new RuntimeException("Downloading from x20 unsupported on windows"); | |
| } | |
| runProcess( | |
| new ProcessBuilder() | |
| .command("bash", "-c", "tools/download_from_x20.py " + sha1File.toString())); | |
| } | |
| private static void runProcess(ProcessBuilder builder) | |
| throws IOException, InterruptedException { | |
| String command = String.join(" ", builder.command()); | |
| Process p = builder.start(); | |
| int exit = p.waitFor(); | |
| if (exit != 0) { | |
| throw new IOException( | |
| "Process failed for " | |
| + command | |
| + "\n" | |
| + new BufferedReader( | |
| new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8)) | |
| .lines() | |
| .collect(Collectors.joining("\n"))); | |
| } | |
| } | |
| } | |
| } |