|
1 | 1 | package com.benjamin538.project; |
| 2 | + |
2 | 3 | // net stuff |
3 | 4 | import java.net.http.HttpClient; |
4 | 5 | import java.net.http.HttpRequest; |
|
18 | 19 | import org.json.JSONArray; |
19 | 20 | import org.json.JSONException; |
20 | 21 |
|
21 | | -// getting url |
22 | | -import com.benjamin538.config.ConfigGet; |
| 22 | +// getting versions |
| 23 | +import com.benjamin538.index.GetVersions; |
23 | 24 |
|
24 | 25 | // logging |
25 | 26 | import com.benjamin538.util.Logging; |
|
33 | 34 | import java.util.Set; |
34 | 35 | import java.util.HashSet; |
35 | 36 | import java.util.Enumeration; |
| 37 | +import java.util.HashMap; |
36 | 38 | import java.util.Iterator; |
| 39 | +import java.util.Map; |
37 | 40 | import java.util.zip.ZipEntry; |
38 | 41 | import java.util.zip.ZipFile; |
39 | 42 |
|
| 43 | +// semver |
| 44 | +import org.semver4j.Semver; |
| 45 | + |
40 | 46 | @Command( |
41 | 47 | name = "check", |
42 | 48 | description = "Check & install the dependencies for this project" |
43 | 49 | ) |
44 | 50 | public class CheckDeps implements Runnable { |
45 | 51 | private Logging logger = new Logging(); |
| 52 | + private boolean errors = false; |
46 | 53 | @Option(names = {"-h", "--help"}, description = "Print help", usageHelp = true) |
47 | 54 | boolean help; |
48 | 55 | @Option(names = {"-p", "--platform"}, description = "The platform checked used for platform-specific dependencies. If not specified, uses current host platform if possible") |
@@ -72,34 +79,106 @@ public void run() { |
72 | 79 | } catch(JSONException ex) { |
73 | 80 | logger.fatal("Dependencies not found"); |
74 | 81 | } |
75 | | - if(dependencies.isEmpty()) { |
| 82 | + if (modJSON.has("gd")) { |
| 83 | + if (modJSON.get("gd") instanceof JSONObject) { |
| 84 | + JSONObject gdVer = modJSON.getJSONObject("gd"); |
| 85 | + switch (platform) { |
| 86 | + case OS.win: |
| 87 | + case OS.windows: |
| 88 | + case OS.linux: |
| 89 | + if (!(gdVer.get("win") instanceof String)) { |
| 90 | + logger.fatal("Geometry Dash version not specified for Windows, please specify one in mod.json"); |
| 91 | + } |
| 92 | + break; |
| 93 | + case OS.mac_os: |
| 94 | + case OS.mac_intel: |
| 95 | + case OS.mac_arm: |
| 96 | + if (!(gdVer.get("mac") instanceof String)) { |
| 97 | + logger.fatal("Geometry Dash version not specified for macOS, please specify one in mod.json"); |
| 98 | + } |
| 99 | + break; |
| 100 | + case OS.android: |
| 101 | + case OS.android64: |
| 102 | + case OS.android32: |
| 103 | + if (!(gdVer.get("android") instanceof String)) { |
| 104 | + logger.fatal("Geometry Dash version not specified for Android, please specify one in mod.json"); |
| 105 | + } |
| 106 | + break; |
| 107 | + case OS.ios: |
| 108 | + if (!(gdVer.get("ios") instanceof String)) { |
| 109 | + logger.fatal("Geometry Dash version not specified for iOS, please specify one in mod.json"); |
| 110 | + } |
| 111 | + break; |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + if (dependencies.isEmpty()) { |
76 | 116 | return; |
77 | 117 | } |
| 118 | + Path buildFolder = Paths.get(folder, "geode-deps"); |
| 119 | + Map<String, String> externalMap = new HashMap<>(); |
| 120 | + for(String ext : externals) { |
| 121 | + if(ext.contains(":")) { |
| 122 | + String[] parts = ext.split(":"); |
| 123 | + externalMap.put(parts[0], parts[1]); |
| 124 | + } else { |
| 125 | + externalMap.put(ext, null); |
| 126 | + } |
| 127 | + } |
78 | 128 | try { |
| 129 | + if (!Files.exists(buildFolder)) { |
| 130 | + Files.createDirectories(buildFolder); |
| 131 | + } |
79 | 132 | Iterator<String> keys = dependencies.keys(); |
80 | 133 | HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build(); |
81 | 134 | while(keys.hasNext()) { |
82 | 135 | String mod = keys.next(); |
83 | 136 | String modVersion = dependencies.getString(mod); |
84 | | - if(externals.contains(mod + ":" + modVersion)) { |
85 | | - continue; |
| 137 | + if(externalMap.containsKey(mod)) { |
| 138 | + String extVersion = externalMap.get(mod); |
| 139 | + if (extVersion != null) { |
| 140 | + try { |
| 141 | + boolean matches = new Semver(extVersion.replace("v", "")).satisfies(modVersion.replace("v", "")); |
| 142 | + if(!matches) { |
| 143 | + logger.fail("External dependency '" + mod + "' version '" + extVersion + "' does not match required '" + modVersion + "'"); |
| 144 | + errors = true; |
| 145 | + } else { |
| 146 | + logger.info("Dependency '" + mod + "' found as external"); |
| 147 | + } |
| 148 | + } catch(Exception ex) { |
| 149 | + logger.fatal("Unable to get version: " + ex.getMessage()); |
| 150 | + if(!extVersion.equals(modVersion)) { |
| 151 | + logger.fail("External dependency '" + mod + "' version '" + extVersion + "' does not match required '" + modVersion + "' (note: optionality is ignored when verifying external dependencies)"); |
| 152 | + errors = true; |
| 153 | + } else { |
| 154 | + logger.info("Dependency '" + mod + "' found as external"); |
| 155 | + } |
| 156 | + } |
| 157 | + continue; |
| 158 | + } else { |
| 159 | + logger.info("Dependency '" + mod + "' marked as external"); |
| 160 | + continue; |
| 161 | + } |
86 | 162 | } |
87 | 163 | Path tempPath = Paths.get(System.getProperty("java.io.tmpdir"), mod + ".geode"); |
88 | 164 | Path buildPath = Paths.get(folder, "geode-deps", mod); |
89 | | - // netttttt |
90 | | - String url = ConfigGet.getIndexUrl() + "/v1/mods/" + mod + "/versions"; |
91 | 165 | if(!Files.exists(tempPath)) { |
92 | | - HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).header("User-Agent", "GeodeCLI").GET().build(); |
93 | | - HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); |
94 | | - if (response.statusCode() != 200) { |
95 | | - logger.fatal("Bad status code on " + url + " : " + response.statusCode()); |
| 166 | + JSONArray versions = GetVersions.getVersions(client, mod); |
| 167 | + JSONObject selectedVersion = null; |
| 168 | + for(int i = 0; i < versions.length(); i++) { |
| 169 | + JSONObject ver = versions.getJSONObject(i); |
| 170 | + if(new Semver(ver.getString("version")).satisfies(modVersion)) { |
| 171 | + selectedVersion = ver; |
| 172 | + break; |
| 173 | + } |
96 | 174 | } |
97 | | - JSONArray respJSON = new JSONObject(response.body()).getJSONObject("payload").getJSONArray("data"); |
98 | | - if(respJSON.isEmpty()) { |
99 | | - logger.fatal("Dependency not found"); |
| 175 | + if(selectedVersion == null) { |
| 176 | + logger.fail("Dependency '" + mod + "' version '" + modVersion + "' not found"); |
| 177 | + errors = true; |
| 178 | + continue; |
100 | 179 | } |
| 180 | + String downloadLink = selectedVersion.getString("download_link"); |
101 | 181 | logger.info("Downloading " + mod); |
102 | | - String downloadLink = respJSON.getJSONObject(0).getString("download_link"); |
103 | 182 | HttpRequest downloadReq = HttpRequest.newBuilder().uri(URI.create(downloadLink)).header("User-Agent", "GeodeCLI").GET().build(); |
104 | 183 | Files.createDirectories(buildPath); |
105 | 184 | client.send(downloadReq, HttpResponse.BodyHandlers.ofFile(tempPath)); |
@@ -133,13 +212,19 @@ public void run() { |
133 | 212 | Files.write(depOptionsPath, depJSON.toString().getBytes()); |
134 | 213 | } |
135 | 214 | client.close(); |
136 | | - logger.done("All dependencies resolved"); |
| 215 | + if (!errors) { |
| 216 | + logger.done("All dependencies resolved"); |
| 217 | + } else { |
| 218 | + logger.fatal("Some dependencies were not resolved"); |
| 219 | + } |
137 | 220 | } catch(JSONException ex) { |
138 | 221 | logger.fatal("JSON failed: " + ex.getMessage()); |
139 | 222 | } catch(InterruptedException ex) { |
140 | 223 | logger.fail("Interrupted"); |
141 | 224 | } catch(IOException ex) { |
142 | 225 | logger.fatal("Client error: " + ex.getMessage()); |
| 226 | + } catch(Exception ex) { |
| 227 | + logger.fatal("Unknown error: " + ex.getMessage()); |
143 | 228 | } |
144 | 229 | // i cant believe that it IS working ❤️🩹 |
145 | 230 | } |
|
0 commit comments