blob: 59596a8824553bfbd17525cd4bfc26a994094893 [file] [log] [blame]
Ian Zernyb2d27c42019-02-20 09:09:41 +01001// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4package tasks;
5
6import java.io.BufferedReader;
7import java.io.File;
8import java.io.IOException;
9import java.io.InputStreamReader;
10import java.nio.charset.StandardCharsets;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Collection;
14import java.util.List;
15import java.util.stream.Collectors;
Jake Whartona138d5b2019-09-17 11:53:52 -040016import javax.inject.Inject;
Ian Zernyb2d27c42019-02-20 09:09:41 +010017import org.gradle.api.DefaultTask;
18import org.gradle.api.tasks.InputFiles;
19import org.gradle.api.tasks.OutputDirectory;
20import org.gradle.api.tasks.TaskAction;
21import org.gradle.internal.os.OperatingSystem;
Jake Whartona138d5b2019-09-17 11:53:52 -040022import org.gradle.workers.IsolationMode;
23import org.gradle.workers.WorkerExecutor;
Ian Zernyb2d27c42019-02-20 09:09:41 +010024
25public class DownloadDependency extends DefaultTask {
26
27 public enum Type {
28 GOOGLE_STORAGE,
29 X20
30 }
31
Jake Whartona138d5b2019-09-17 11:53:52 -040032 private final WorkerExecutor workerExecutor;
33
Ian Zernyb2d27c42019-02-20 09:09:41 +010034 private Type type;
Ian Zernyb2d27c42019-02-20 09:09:41 +010035 private File outputDir;
36 private File tarGzFile;
37 private File sha1File;
38
Jake Whartona138d5b2019-09-17 11:53:52 -040039 @Inject
40 public DownloadDependency(WorkerExecutor workerExecutor) {
41 this.workerExecutor = workerExecutor;
42 }
43
Ian Zernyb2d27c42019-02-20 09:09:41 +010044 public void setType(Type type) {
45 this.type = type;
46 }
47
48 public void setDependency(String dependency) {
Ian Zernyb2d27c42019-02-20 09:09:41 +010049 outputDir = new File(dependency);
50 tarGzFile = new File(dependency + ".tar.gz");
51 sha1File = new File(dependency + ".tar.gz.sha1");
52 }
53
54 @InputFiles
55 public Collection<File> getInputFiles() {
56 return Arrays.asList(sha1File, tarGzFile);
57 }
58
59 @OutputDirectory
60 public File getOutputDir() {
61 return outputDir;
62 }
63
64 public File getSha1File() {
65 return sha1File;
66 }
67
68 public File getTarGzFile() {
69 return tarGzFile;
70 }
71
72 @TaskAction
73 public void execute() throws IOException, InterruptedException {
Rico Wind3abd49e2022-03-14 15:05:08 +010074 if (!sha1File.exists()) {
75 throw new RuntimeException("Missing sha1 file: " + sha1File);
76 }
77
Ian Zernyb2d27c42019-02-20 09:09:41 +010078 // First run will write the tar.gz file, causing the second run to still be out-of-date.
79 // Check if the modification time of the tar is newer than the sha in which case we are done.
80 // Also, check the contents of the out directory because gradle appears to create it for us...
81 if (outputDir.exists()
82 && outputDir.isDirectory()
83 && outputDir.list().length > 0
84 && tarGzFile.exists()
85 && sha1File.lastModified() <= tarGzFile.lastModified()) {
86 return;
87 }
88 if (outputDir.exists() && outputDir.isDirectory()) {
89 outputDir.delete();
90 }
Jake Whartona138d5b2019-09-17 11:53:52 -040091 workerExecutor.submit(RunDownload.class, config -> {
92 config.setIsolationMode(IsolationMode.NONE);
93 config.params(type, sha1File);
94 });
Ian Zernyb2d27c42019-02-20 09:09:41 +010095 }
96
Jake Whartona138d5b2019-09-17 11:53:52 -040097 public static class RunDownload implements Runnable {
98 private final Type type;
99 private final File sha1File;
100
101 @Inject
102 public RunDownload(Type type, File sha1File) {
103 this.type = type;
104 this.sha1File = sha1File;
105 }
106
107 @Override
108 public void run() {
109 try {
110 if (type == Type.GOOGLE_STORAGE) {
111 downloadFromGoogleStorage();
112 } else if (type == Type.X20) {
113 downloadFromX20();
114 } else {
115 throw new RuntimeException("Unexpected or missing dependency type: " + type);
116 }
117 } catch (Exception e) {
118 throw new RuntimeException(e);
119 }
120 }
121
122 private void downloadFromGoogleStorage() throws IOException, InterruptedException {
123 List<String> args = Arrays.asList("-n", "-b", "r8-deps", "-s", "-u", sha1File.toString());
124 if (OperatingSystem.current().isWindows()) {
125 List<String> command = new ArrayList<>();
126 command.add("download_from_google_storage.bat");
127 command.addAll(args);
128 runProcess(new ProcessBuilder().command(command));
129 } else {
130 runProcess(
131 new ProcessBuilder()
132 .command("bash", "-c", "download_from_google_storage " + String.join(" ", args)));
133 }
134 }
135
136 private void downloadFromX20() throws IOException, InterruptedException {
137 if (OperatingSystem.current().isWindows()) {
138 throw new RuntimeException("Downloading from x20 unsupported on windows");
139 }
Ian Zernyb2d27c42019-02-20 09:09:41 +0100140 runProcess(
141 new ProcessBuilder()
Jake Whartona138d5b2019-09-17 11:53:52 -0400142 .command("bash", "-c", "tools/download_from_x20.py " + sha1File.toString()));
Ian Zernyb2d27c42019-02-20 09:09:41 +0100143 }
Ian Zernyb2d27c42019-02-20 09:09:41 +0100144
Jake Whartona138d5b2019-09-17 11:53:52 -0400145 private static void runProcess(ProcessBuilder builder)
146 throws IOException, InterruptedException {
147 String command = String.join(" ", builder.command());
148 Process p = builder.start();
149 int exit = p.waitFor();
150 if (exit != 0) {
151 throw new IOException(
152 "Process failed for "
153 + command
154 + "\n"
155 + new BufferedReader(
156 new InputStreamReader(p.getErrorStream(), StandardCharsets.UTF_8))
157 .lines()
158 .collect(Collectors.joining("\n")));
159 }
Ian Zernyb2d27c42019-02-20 09:09:41 +0100160 }
161 }
162}