Skip to content

Commit 8bb1ca7

Browse files
committed
feat(deploader): warn user with a warning popup on dependency version mismatches
1 parent 2311ab0 commit 8bb1ca7

2 files changed

Lines changed: 101 additions & 8 deletions

File tree

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
group = "com.falsepattern"
66

77
//bump this after ANY change to the deploader!
8-
val deploaderVersion = 9
8+
val deploaderVersion = 10
99

1010
minecraft_fp {
1111
java {

src/deploader/java/com/falsepattern/deploader/DependencyLoaderImpl.java

Lines changed: 100 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
import java.util.Map;
7575
import java.util.Objects;
7676
import java.util.Set;
77+
import java.util.StringTokenizer;
7778
import java.util.concurrent.CompletableFuture;
7879
import java.util.concurrent.ConcurrentHashMap;
7980
import java.util.concurrent.ExecutorService;
@@ -119,6 +120,7 @@ public class DependencyLoaderImpl {
119120
private static final AtomicBoolean needReboot = new AtomicBoolean(false);
120121
private static final Set<String> downloadedMods = new ConcurrentSet<>();
121122
private static final Set<String> downloadFailed = new ConcurrentSet<>();
123+
private static final AtomicBoolean anyDownloadFailCausedByGradle = new AtomicBoolean(false);
122124

123125
private static void ensureExists(Path directory) {
124126
if (!Files.exists(directory)) {
@@ -498,6 +500,72 @@ public ModDependencyDownloaded(String message) {
498500
.flatMap(i -> i));
499501
}
500502

503+
private static final String[] MAVEN_PREFIXES = new String[]{
504+
"modules-2/files-2.1/",
505+
".m2/repository/"
506+
};
507+
private static void detectLocalDep(String str) {
508+
str = str.replace('\\', '/');
509+
if (detectLocalDepSingle(str, "modules-2/files-2.1/", true))
510+
return;
511+
detectLocalDepSingle(str, ".m2/repository/", false);
512+
}
513+
514+
private static boolean detectLocalDepSingle(String str, String prefix, boolean extraPathSegment) {
515+
val idx = str.indexOf(prefix);
516+
if (idx == -1) {
517+
return false;
518+
}
519+
val dep = str.substring(idx + prefix.length());
520+
val tok = new StringTokenizer(dep, "/");
521+
if (!tok.hasMoreTokens())
522+
return true;
523+
val group = tok.nextToken();
524+
if (!tok.hasMoreTokens())
525+
return true;
526+
val artifact = tok.nextToken();
527+
if (!tok.hasMoreTokens())
528+
return true;
529+
val version = tok.nextToken();
530+
if (extraPathSegment) {
531+
if (!tok.hasMoreTokens())
532+
return true;
533+
tok.nextToken();
534+
}
535+
if (!tok.hasMoreTokens())
536+
return true;
537+
val file = tok.nextToken();
538+
539+
val filePrefix = artifact + "-" + version;
540+
541+
if (!file.contains(filePrefix))
542+
return true;
543+
544+
val fileSuffix = file.substring(filePrefix.length());
545+
546+
if (!fileSuffix.endsWith(".jar"))
547+
return true;
548+
549+
String classifier = null;
550+
if (fileSuffix.startsWith("-")) {
551+
classifier = fileSuffix.substring(1, fileSuffix.length() - 4);
552+
}
553+
554+
val id = group + ":" + artifact + ":" + classifier;
555+
val versionParsed = Version.parse(version);
556+
557+
LOG.warn("Found dev dependency pulled in via Gradle {}:{}:{}{}", group, artifact, version, classifier == null ? "" : ":" + classifier);
558+
if (!loadedLibraries.containsKey(id)) {
559+
loadedLibraries.put(id, versionParsed);
560+
} else {
561+
LOG.warn("Duplicate gradle dependency {}:{}:{}{}", group, artifact, version, classifier == null ? "" : ":" + classifier);
562+
}
563+
if (!loadedLibraryMods.containsKey(id)) {
564+
loadedLibraryMods.put(id, "Gradle");
565+
}
566+
return true;
567+
}
568+
501569
private static @Nullable Set<ScopedSidedTask> scanDeps(Stream<URL> candidatesUnfiltered) {
502570
long start = System.currentTimeMillis();
503571
val urlsWithoutDeps = new HashSet<String>();
@@ -509,10 +577,16 @@ public ModDependencyDownloaded(String message) {
509577
LOG.error("Could not read dependency scanner cache", e);
510578
}
511579
}
512-
val candidates = candidatesUnfiltered
513-
.filter(Objects::nonNull)
514-
.filter((url) -> !urlsWithoutDeps.contains(url.toString()))
515-
.collect(Collectors.toList());
580+
val candidates = new ArrayList<URL>();
581+
candidatesUnfiltered.forEach(candidate -> {
582+
if (candidate == null)
583+
return;
584+
val str = candidate.toString();
585+
detectLocalDep(str);
586+
if (urlsWithoutDeps.contains(str))
587+
return;
588+
candidates.add(candidate);
589+
});
516590
val urls = new ArrayList<URL>();
517591
val jijURLs = new ArrayList<URL>();
518592
for (val candidate : candidates) {
@@ -832,14 +906,27 @@ static ScopeSide current() {
832906
if (downloadFailed.isEmpty()) {
833907
JOptionPane.showMessageDialog(null, "FP DepLoader has encountered an error while trying to download libraries.\nSee the log for more details.", "Dependency download error", JOptionPane.ERROR_MESSAGE);
834908
} else {
835-
var msgBuilder = new StringBuilder("FP DepLoader has encountered an error while trying to download the following libraries:");
909+
var msgBuilder = new StringBuilder("FP DepLoader has encountered an error while trying to download the following libraries:\n");
836910
for (val f: downloadFailed) {
837911
msgBuilder.append('\n').append(f);
838912
}
839913
msgBuilder.append("\n\nSee the log for more details.");
840914
JOptionPane.showMessageDialog(null, msgBuilder.toString(), "Dependency download error", JOptionPane.ERROR_MESSAGE);
841915
}
842916
throw err;
917+
} else if (!downloadFailed.isEmpty()) {
918+
var msgBuilder = new StringBuilder("FP DepLoader has encountered an error while trying to download the following libraries:\n");
919+
for (val f: downloadFailed) {
920+
msgBuilder.append('\n').append(f);
921+
}
922+
msgBuilder.append("\n\nSee the log for more details. Click OK to continue anyway (may cause issues!).\n\n");
923+
if (anyDownloadFailCausedByGradle.get() && scopeSide.scope == DependencyScope.DEV) {
924+
msgBuilder.append("One or more of these dependency version mismatches were caused by a gradle dependency being too old compared to a deploaded dependency!\n"
925+
+ "Try manually depending on the newer versions of the required libraries via runtimeOnly(...)!");
926+
}
927+
if (JOptionPane.showConfirmDialog(null, msgBuilder.toString(), "Dependency download error", JOptionPane.OK_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE) != JOptionPane.OK_OPTION) {
928+
throw new IllegalStateException("User terminated game after dependency load error");
929+
}
843930
}
844931
if (res.isEmpty()) {
845932
return null;
@@ -1040,16 +1127,22 @@ private void alreadyLoaded(boolean fromModId) {
10401127
for (int i = 0; i < 4; i++) {
10411128
LOG.fatal("ALERT VVVVVVVVVVVV ALERT");
10421129
}
1130+
val loader = fromModId ? loadedModIdMods.get(modId) : loadedLibraryMods.get(artifact);
1131+
val sfx = suffix != null ? ":" + suffix : "";
10431132
LOG.fatal("Library {}:{}{} already loaded with version {}, "
10441133
+ "but a version in the range {} was requested! Thing may go horribly wrong! "
10451134
+ "Requested by mod: {}, previously loaded by mod: {}",
10461135
groupId,
10471136
artifactId,
1048-
suffix != null ? ":" + suffix : "",
1137+
sfx,
10491138
currentVer,
10501139
rangeString,
10511140
loadingModId,
1052-
fromModId ? loadedModIdMods.get(modId) : loadedLibraryMods.get(artifact));
1141+
loader);
1142+
downloadFailed.add(String.format("%s:%s:%s%s already loaded by: %s, but mod %s requested version %s!", groupId, artifactId, currentVer, sfx, loader, loadingModId, rangeString));
1143+
if ("Gradle".equals(loader)) {
1144+
anyDownloadFailCausedByGradle.set(true);
1145+
}
10531146
for (int i = 0; i < 4; i++) {
10541147
LOG.fatal("ALERT ^^^^^^^^^^^^ ALERT");
10551148
}

0 commit comments

Comments
 (0)