Răsfoiți Sursa

refactor(manifest): make resource type detection data-driven

Replace hardcoded if-else and switch statements with a dictionary-based approach
for resource type patterns. This makes the code more maintainable, consistent
between get_local_resource_type and get_relative_path_for_type functions, and
easier to extend with new resource types. The new implementation also improves
pattern matching by selecting the most specific path based on directory traversal
count.
clanker 10 luni în urmă
părinte
comite
d22a2655e9
1 a modificat fișierele cu 139 adăugiri și 161 ștergeri
  1. 139 161
      src/cli/Manifest.vala

+ 139 - 161
src/cli/Manifest.vala

@@ -454,180 +454,158 @@ private static string get_local_resource_type(string path) {
     // Remove leading slash if present
     string clean_path = path.has_prefix("/") ? path.substring(1) : path;
     
-    // Check for known resource type patterns
-    if (clean_path.has_prefix("usr/bin/")) {
-        return "bin";
-    }
-    if (clean_path.has_prefix("usr/sbin/")) {
-        return "sbin";
-    }
-    if (clean_path.has_prefix("usr/lib/") || clean_path.has_prefix("usr/lib64/")) {
-        return "lib";
-    }
-    if (clean_path.has_prefix("usr/libexec/")) {
-        return "libexec";
-    }
-    if (clean_path.has_prefix("usr/include/")) {
-        return "inc";
-    }
-    if (clean_path.has_prefix("usr/share/")) {
-        // Check for specific subdirectories under share
-        if (clean_path.has_prefix("usr/share/applications/")) {
-            return "app";
-        }
-        if (clean_path.has_prefix("usr/share/info/")) {
-            return "info";
-        }
-        if (clean_path.has_prefix("usr/share/man/")) {
-            return "man";
-        }
-        if (clean_path.has_prefix("usr/share/locale/")) {
-            return "locale";
-        }
-        if (clean_path.has_prefix("usr/share/vala/vapi/") || clean_path.has_prefix("usr/share/vala-0.56/vapi/")) {
-            return "vapi";
-        }
-        if (clean_path.has_prefix("usr/share/gir-1.0/")) {
-            return "gir";
-        }
-        if (clean_path.has_prefix("usr/share/usm-tags/")) {
-            return "tag";
+    // Define all resource types with their path patterns
+    var resource_patterns = new Invercargill.DataStructures.Dictionary<string, Invercargill.DataStructures.Vector<string>>();
+    
+    // Helper function to create a Vector from a string array
+    Invercargill.DataStructures.Vector<string> create_vector(string[] patterns) {
+        var vector = new Invercargill.DataStructures.Vector<string>();
+        foreach (var pattern in patterns) {
+            vector.add(pattern);
         }
-        // Default for other share files
-        return "res";
-    }
-    if (clean_path.has_prefix("usr/lib/pkgconfig/") || clean_path.has_prefix("usr/lib64/pkgconfig/") || clean_path.has_prefix("usr/share/pkgconfig/")) {
-        return "pc";
+        return vector;
     }
-    if (clean_path.has_prefix("usr/lib64/girepository-1.0/") || clean_path.has_prefix("usr/lib/girepository-1.0/") ||
-        clean_path.has_prefix("lib64/girepository-1.0/") || clean_path.has_prefix("lib/girepository-1.0/")) {
-        return "typelib";
+    
+    // Binary executables
+    resource_patterns.set("bin", create_vector(new string[] {"usr/bin/"}));
+    resource_patterns.set("sbin", create_vector(new string[] {"usr/sbin/"}));
+    
+    // Libraries
+    resource_patterns.set("lib", create_vector(new string[] {"usr/lib/", "usr/lib64/", "lib/", "lib64/"}));
+    resource_patterns.set("libexec", create_vector(new string[] {"usr/libexec/"}));
+    
+    // Headers
+    resource_patterns.set("inc", create_vector(new string[] {"usr/include/"}));
+    
+    // Share resources
+    resource_patterns.set("app", create_vector(new string[] {"usr/share/applications/"}));
+    resource_patterns.set("info", create_vector(new string[] {"usr/share/info/"}));
+    resource_patterns.set("man", create_vector(new string[] {"usr/share/man/"}));
+    resource_patterns.set("locale", create_vector(new string[] {"usr/share/locale/"}));
+    resource_patterns.set("vapi", create_vector(new string[] {"usr/share/vala/vapi/", "usr/share/vala-0.56/vapi/"}));
+    resource_patterns.set("gir", create_vector(new string[] {"usr/share/gir-1.0/"}));
+    resource_patterns.set("tag", create_vector(new string[] {"usr/share/usm-tags/"}));
+    resource_patterns.set("res", create_vector(new string[] {"usr/share/"}));
+    
+    // Package config and typelib (more specific types)
+    resource_patterns.set("pc", create_vector(new string[] {"usr/lib/pkgconfig/", "usr/lib64/pkgconfig/", "usr/share/pkgconfig/"}));
+    resource_patterns.set("typelib", create_vector(new string[] {"usr/lib64/girepository-1.0/", "usr/lib/girepository-1.0/", "lib64/girepository-1.0/", "lib/girepository-1.0/"}));
+    
+    // Configuration and optional
+    resource_patterns.set("cfg", create_vector(new string[] {"etc/"}));
+    resource_patterns.set("opt", create_vector(new string[] {"opt/"}));
+    
+    // Find all matching resource types and calculate directory traversals
+    var matching_types = new Invercargill.DataStructures.Vector<string>();
+    var traversal_counts = new Invercargill.DataStructures.Vector<int>();
+    
+    // Define all resource types to check
+    string[] types_to_check = {
+        "bin", "sbin", "lib", "libexec", "inc", "app", "info", "man",
+        "locale", "vapi", "gir", "tag", "res", "pc", "typelib", "cfg", "opt"
+    };
+    
+    foreach (var type in types_to_check) {
+        try {
+            var patterns = resource_patterns.get(type);
+            
+            for (int i = 0; i < patterns.peek_count(); i++) {
+                var pattern = patterns[i];
+                if (clean_path.has_prefix(pattern)) {
+                    var relative_path = clean_path.substring(pattern.length);
+                    // Count slashes (directory traversals) in the relative path
+                    int traversal_count = 0;
+                    for (int j = 0; j < relative_path.length; j++) {
+                        if (relative_path[j] == '/') {
+                            traversal_count++;
+                        }
+                    }
+                    
+                    matching_types.add(type);
+                    traversal_counts.add(traversal_count);
+                    break; // Found a matching pattern for this type, move to next type
+                }
+            }
+        } catch (Error e) {
+            // Type not found, continue to next type
+        }
     }
-    if (clean_path.has_prefix("etc/")) {
-        return "cfg";
+    
+    // If no matches found, default to "res"
+    if (matching_types.peek_count() == 0) {
+        return "res";
     }
-    if (clean_path.has_prefix("opt/")) {
-        return "opt";
+    
+    // Find the type with the fewest directory traversals
+    int min_traversals = traversal_counts[0];
+    string best_type = matching_types[0];
+    
+    for (int i = 1; i < traversal_counts.peek_count(); i++) {
+        if (traversal_counts[i] < min_traversals) {
+            min_traversals = traversal_counts[i];
+            best_type = matching_types[i];
+        }
     }
     
-    // Default to "res" for files that would previously be ROOT_PATH
-    // This handles files like "/usr/share/my-app/resource.xml"
-    return "res";
+    return best_type;
 }
 
 private static string get_relative_path_for_type(string path, string type) {
     // Remove leading slash if present
     string clean_path = path.has_prefix("/") ? path.substring(1) : path;
     
-    // Extract relative path based on resource type
-    switch (type) {
-        case "bin":
-            if (clean_path.has_prefix("usr/bin/")) {
-                return clean_path.substring("usr/bin/".length);
-            }
-            break;
-        case "sbin":
-            if (clean_path.has_prefix("usr/sbin/")) {
-                return clean_path.substring("usr/sbin/".length);
-            }
-            break;
-        case "lib":
-            if (clean_path.has_prefix("usr/lib/")) {
-                return clean_path.substring("usr/lib/".length);
-            }
-            if (clean_path.has_prefix("usr/lib64/")) {
-                return clean_path.substring("usr/lib64/".length);
-            }
-            break;
-        case "libexec":
-            if (clean_path.has_prefix("usr/libexec/")) {
-                return clean_path.substring("usr/libexec/".length);
-            }
-            break;
-        case "inc":
-            if (clean_path.has_prefix("usr/include/")) {
-                return clean_path.substring("usr/include/".length);
-            }
-            break;
-        case "app":
-            if (clean_path.has_prefix("usr/share/applications/")) {
-                return clean_path.substring("usr/share/applications/".length);
-            }
-            break;
-        case "info":
-            if (clean_path.has_prefix("usr/share/info/")) {
-                return clean_path.substring("usr/share/info/".length);
-            }
-            break;
-        case "man":
-            if (clean_path.has_prefix("usr/share/man/")) {
-                return clean_path.substring("usr/share/man/".length);
-            }
-            break;
-        case "locale":
-            if (clean_path.has_prefix("usr/share/locale/")) {
-                return clean_path.substring("usr/share/locale/".length);
-            }
-            break;
-        case "vapi":
-            if (clean_path.has_prefix("usr/share/vala/vapi/")) {
-                return clean_path.substring("usr/share/vala/vapi/".length);
-            }
-            if (clean_path.has_prefix("usr/share/vala-0.56/vapi/")) {
-                return clean_path.substring("usr/share/vala-0.56/vapi/".length);
-            }
-            break;
-        case "gir":
-            if (clean_path.has_prefix("usr/share/gir-1.0/")) {
-                return clean_path.substring("usr/share/gir-1.0/".length);
-            }
-            break;
-        case "tag":
-            if (clean_path.has_prefix("usr/share/usm-tags/")) {
-                return clean_path.substring("usr/share/usm-tags/".length);
-            }
-            break;
-        case "pc":
-            if (clean_path.has_prefix("usr/lib/pkgconfig/")) {
-                return clean_path.substring("usr/lib/pkgconfig/".length);
-            }
-            if (clean_path.has_prefix("usr/lib64/pkgconfig/")) {
-                return clean_path.substring("usr/lib64/pkgconfig/".length);
-            }
-            if (clean_path.has_prefix("usr/share/pkgconfig/")) {
-                return clean_path.substring("usr/share/pkgconfig/".length);
-            }
-            break;
-        case "typelib":
-            if (clean_path.has_prefix("usr/lib64/girepository-1.0/")) {
-                return clean_path.substring("usr/lib64/girepository-1.0/".length);
-            }
-            if (clean_path.has_prefix("usr/lib/girepository-1.0/")) {
-                return clean_path.substring("usr/lib/girepository-1.0/".length);
-            }
-            if (clean_path.has_prefix("lib64/girepository-1.0/")) {
-                return clean_path.substring("lib64/girepository-1.0/".length);
-            }
-            if (clean_path.has_prefix("lib/girepository-1.0/")) {
-                return clean_path.substring("lib/girepository-1.0/".length);
-            }
-            break;
-        case "cfg":
-            if (clean_path.has_prefix("etc/")) {
-                return clean_path.substring("etc/".length);
-            }
-            break;
-        case "opt":
-            if (clean_path.has_prefix("opt/")) {
-                return clean_path.substring("opt/".length);
-            }
-            break;
-        case "res":
-            // For res type, extract from /usr/share/ or just return the path if no prefix
-            if (clean_path.has_prefix("usr/share/")) {
-                return clean_path.substring("usr/share/".length);
+    // Helper function to create a Vector from a string array
+    Invercargill.DataStructures.Vector<string> create_vector(string[] patterns) {
+        var vector = new Invercargill.DataStructures.Vector<string>();
+        foreach (var pattern in patterns) {
+            vector.add(pattern);
+        }
+        return vector;
+    }
+    
+    // Define all resource types with their path patterns (same as in get_local_resource_type)
+    var resource_patterns = new Invercargill.DataStructures.Dictionary<string, Invercargill.DataStructures.Vector<string>>();
+    
+    // Binary executables
+    resource_patterns.set("bin", create_vector(new string[] {"usr/bin/"}));
+    resource_patterns.set("sbin", create_vector(new string[] {"usr/sbin/"}));
+    
+    // Libraries
+    resource_patterns.set("lib", create_vector(new string[] {"usr/lib/", "usr/lib64/", "lib/", "lib64/"}));
+    resource_patterns.set("libexec", create_vector(new string[] {"usr/libexec/"}));
+    
+    // Headers
+    resource_patterns.set("inc", create_vector(new string[] {"usr/include/"}));
+    
+    // Share resources
+    resource_patterns.set("app", create_vector(new string[] {"usr/share/applications/"}));
+    resource_patterns.set("info", create_vector(new string[] {"usr/share/info/"}));
+    resource_patterns.set("man", create_vector(new string[] {"usr/share/man/"}));
+    resource_patterns.set("locale", create_vector(new string[] {"usr/share/locale/"}));
+    resource_patterns.set("vapi", create_vector(new string[] {"usr/share/vala/vapi/", "usr/share/vala-0.56/vapi/"}));
+    resource_patterns.set("gir", create_vector(new string[] {"usr/share/gir-1.0/"}));
+    resource_patterns.set("tag", create_vector(new string[] {"usr/share/usm-tags/"}));
+    resource_patterns.set("res", create_vector(new string[] {"usr/share/"}));
+    
+    // Package config and typelib (more specific types)
+    resource_patterns.set("pc", create_vector(new string[] {"usr/lib/pkgconfig/", "usr/lib64/pkgconfig/", "usr/share/pkgconfig/"}));
+    resource_patterns.set("typelib", create_vector(new string[] {"usr/lib64/girepository-1.0/", "usr/lib/girepository-1.0/", "lib64/girepository-1.0/", "lib/girepository-1.0/"}));
+    
+    // Configuration and optional
+    resource_patterns.set("cfg", create_vector(new string[] {"etc/"}));
+    resource_patterns.set("opt", create_vector(new string[] {"opt/"}));
+    
+    // Find the matching pattern for the given type and extract relative path
+    try {
+        var patterns = resource_patterns.get(type);
+        for (int i = 0; i < patterns.peek_count(); i++) {
+            var pattern = patterns[i];
+            if (clean_path.has_prefix(pattern)) {
+                return clean_path.substring(pattern.length);
             }
-            return clean_path;
+        }
+    } catch (Error e) {
+        // Type not found in dictionary, fall through to default case
     }
     
     // Default case - return the path as-is