Procházet zdrojové kódy

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 před 1 měsícem
rodič
revize
d22a2655e9
1 změnil soubory, kde provedl 139 přidání a 161 odebrání
  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