From 7a5bc5569b9f362054f995e81aad234adef1582d Mon Sep 17 00:00:00 2001
From: Isaac Turner <spacey_sooty@outlook.com>
Date: Thu, 29 Feb 2024 21:55:06 +0800
Subject: [PATCH] [vendordeps] handle null keysets better

---
 .../vendordeps/VendorParsingError.java        |  9 ++
 .../vendordeps/VendorParsingException.java    | 47 ++++++++++
 .../vendordeps/WPIVendorDepsExtension.java    | 85 ++++++++++++-------
 3 files changed, 109 insertions(+), 32 deletions(-)
 create mode 100644 src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingError.java
 create mode 100644 src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingException.java

diff --git a/src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingError.java b/src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingError.java
new file mode 100644
index 0000000..bbfefaf
--- /dev/null
+++ b/src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingError.java
@@ -0,0 +1,9 @@
+package edu.wpi.first.nativeutils.vendordeps;
+
+public enum VendorParsingError {
+    MissingName,
+    MissingCppDeps,
+    MissingJniDeps,
+    MissingJavaDeps,
+    NoMavenUrl,
+}
diff --git a/src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingException.java b/src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingException.java
new file mode 100644
index 0000000..b61a7f5
--- /dev/null
+++ b/src/main/java/edu/wpi/first/nativeutils/vendordeps/VendorParsingException.java
@@ -0,0 +1,47 @@
+package edu.wpi.first.nativeutils.vendordeps;
+
+import org.gradle.tooling.BuildException;
+
+public class VendorParsingException extends Exception {
+    public VendorParsingException(String file, VendorParsingError error) {
+        switch (error) {
+            case NoMavenUrl:
+                System.err.println("The vendordep " + file + " is missing the required maven url.");
+                break;
+
+            case MissingCppDeps:
+                System.err.println("The vendordep " + file + " is missing the required C++ dependencies key.");
+                System.err.println("If you would not like to declare any Cpp deps use an empty list.");
+                break;
+
+            case MissingJniDeps:
+                System.err.println("The vendordep " + file + " is missing the required Jni dependencies key.");
+                System.err.println("If you would not like to declare any Jni deps use an empty list.");
+                break;
+
+            case MissingJavaDeps:
+                System.err.println("The vendordep " + file + " is missing the required Java dependencies key.");
+                System.err.println("If you would not like to declare any Java deps use an empty list.");
+                break;
+
+            default:
+                throw new BuildException(
+                        "Unhandled case in VendorParsingException. This is a bug and should be reported",
+                        new Exception());
+        }
+    }
+
+    // should only be called if we don't have access to a name yet
+    public VendorParsingException(VendorParsingError error) {
+        switch (error) {
+            case MissingName:
+                System.err.println("One of the vendordep files does not have a name");
+                break;
+
+            default:
+                throw new BuildException(
+                        "Unhandled case in VendorParsingException. This is a bug and should be reported",
+                        new Exception());
+        }
+    }
+}
diff --git a/src/main/java/edu/wpi/first/nativeutils/vendordeps/WPIVendorDepsExtension.java b/src/main/java/edu/wpi/first/nativeutils/vendordeps/WPIVendorDepsExtension.java
index cb65536..51187fa 100644
--- a/src/main/java/edu/wpi/first/nativeutils/vendordeps/WPIVendorDepsExtension.java
+++ b/src/main/java/edu/wpi/first/nativeutils/vendordeps/WPIVendorDepsExtension.java
@@ -19,6 +19,7 @@
 import org.gradle.api.plugins.JavaPlugin;
 import org.gradle.api.provider.Property;
 import org.gradle.nativeplatform.plugins.NativeComponentPlugin;
+import org.gradle.tooling.BuildException;
 
 import com.google.gson.Gson;
 
@@ -165,7 +166,11 @@ public void loadFrom(File directory) {
         for (File f : vendorFiles(directory)) {
             JsonDependency dep = parse(f);
             if (dep != null) {
-                load(dep);
+                try {
+                    load(dep);
+                } catch(Exception e) {
+                    throw new BuildException("Failed to load dependency", e);
+                }
             }
         }
     }
@@ -182,7 +187,7 @@ private JsonDependency parse(File f) {
         }
     }
 
-    private void load(JsonDependency dep) {
+    private void load(JsonDependency dep) throws VendorParsingException {
         // Don"t double-add a dependency!
         if (dependencySet.findByName(dep.uuid) != null) {
             return;
@@ -191,40 +196,56 @@ private void load(JsonDependency dep) {
         NamedJsonDependency namedDep = new NamedJsonDependency(dep.uuid, dep);
         dependencySet.add(namedDep);
 
-        if (dep.mavenUrls != null) {
-            // Enumerate all group ids
-            Set<String> groupIds = new HashSet<>();
-            for (CppArtifact cpp : dep.cppDependencies) {
-                groupIds.add(cpp.groupId);
-            }
-            for (JniArtifact jni : dep.jniDependencies) {
-                groupIds.add(jni.groupId);
-            }
-            for (JavaArtifact java : dep.javaDependencies) {
-                groupIds.add(java.groupId);
-            }
-            if (dep.extraGroupIds != null) {
-                for (String groupId : dep.extraGroupIds) {
-                    groupIds.add(groupId);
-                }
+        if (dep.name == null) {
+            throw new VendorParsingException(VendorParsingError.MissingName);
+        }
+        String filename = dep.name;
+
+        if (dep.mavenUrls == null) {
+            throw new VendorParsingException(filename, VendorParsingError.NoMavenUrl);
+        }
+
+        // Enumerate all group ids
+        Set<String> groupIds = new HashSet<>();
+        if (dep.cppDependencies == null) {
+            throw new VendorParsingException(filename, VendorParsingError.MissingCppDeps);
+        }
+        for (CppArtifact cpp : dep.cppDependencies) {
+            groupIds.add(cpp.groupId);
+        }
+        if (dep.jniDependencies == null) {
+            throw new VendorParsingException(filename, VendorParsingError.MissingJniDeps);
+        }
+        for (JniArtifact jni : dep.jniDependencies) {
+            groupIds.add(jni.groupId);
+        }
+        if (dep.javaDependencies == null) {
+            throw new VendorParsingException(filename, VendorParsingError.MissingJavaDeps);
+        }
+        for (JavaArtifact java : dep.javaDependencies) {
+            groupIds.add(java.groupId);
+        }
+        if (dep.extraGroupIds != null) {
+            for (String groupId : dep.extraGroupIds) {
+                groupIds.add(groupId);
             }
+        }
 
-            int i = 0;
-            for (String url : dep.mavenUrls) {
-                boolean found = false;
+        int i = 0;
+        for (String url : dep.mavenUrls) {
+            boolean found = false;
 
-                for (VendorMavenRepo machingRepo : vendorRepos.matching(x -> x.getUrl().equals(url))) {
-                    found = true;
-                    machingRepo.getAllowedGroupIds().addAll(groupIds);
-                }
+            for (VendorMavenRepo machingRepo : vendorRepos.matching(x -> x.getUrl().equals(url))) {
+                found = true;
+                machingRepo.getAllowedGroupIds().addAll(groupIds);
+            }
 
-                // // Only add if the maven doesn"t yet exist.
-                if (!found) {
-                    String name = dep.uuid + "_" + i++;
-                    log.info("Registering vendor dep maven: " + name + " on project " + project.getPath());
-                    VendorMavenRepo repo = project.getObjects().newInstance(VendorMavenRepo.class, name, url, groupIds);
-                    vendorRepos.add(repo);
-                }
+            // // Only add if the maven doesn"t yet exist.
+            if (!found) {
+                String name = dep.uuid + "_" + i++;
+                log.info("Registering vendor dep maven: " + name + " on project " + project.getPath());
+                VendorMavenRepo repo = project.getObjects().newInstance(VendorMavenRepo.class, name, url, groupIds);
+                vendorRepos.add(repo);
             }
         }
     }