瀏覽代碼

feat(manifest): add validation for regular file path requirements

Make path and pathBase nullable in ManifestFile to properly handle different file types. Add validation logic to ensure path and pathBase are provided when type is "reg". Update property mapper to handle nullable values correctly and prevent null pointer exceptions during manifest processing.
clanker 1 月之前
父節點
當前提交
e73a175393
共有 2 個文件被更改,包括 29 次插入9 次删除
  1. 20 4
      src/lib/File.vala
  2. 9 5
      src/lib/Manifest.vala

+ 20 - 4
src/lib/File.vala

@@ -6,8 +6,8 @@ namespace Usm {
 
     public class ManifestFile {
 
-        public ManifestFilePathBase path_base { get; set; }
-        public string path { get; set; }
+        public ManifestFilePathBase? path_base { get; set; }
+        public string? path { get; set; }
         public ManifestFileType file_type { get; set; }
         public string? destination { get; set; }
         public Vector<RemoveType>? keep_on { get; set; }
@@ -15,8 +15,12 @@ namespace Usm {
 
         public static PropertyMapper<ManifestFile> get_mapper() {
             return PropertyMapper.build_for<ManifestFile>(cfg => {
-                cfg.map<string>("path", o => o.path, (o, v) => o.path = v); // TODO make nullable in some cases, add validtion (i.e. type != reg, and pathBase == as-expected)
-                cfg.map<string>("pathBase", o => o.path_base.to_string(), (o, v) => o.path_base = ManifestFilePathBase.from_string(v));
+                cfg.map<string>("path", o => o.path, (o, v) => o.path = v)
+                    .undefined_when(o => o.path == null)
+                    .when_undefined(o => o.path = null);
+                cfg.map<string>("pathBase", o => o.path_base != null ? o.path_base.to_string() : null, (o, v) => { if (v != null) o.path_base = ManifestFilePathBase.from_string(v); else o.path_base = null; })
+                    .undefined_when(o => o.path_base == null)
+                    .when_undefined(o => o.path_base = null);
                 cfg.map<string>("type", o => o.file_type.to_string(), (o, v) => o.file_type = ManifestFileType.from_string(v));
                 cfg.map<string>("dest", o => o.destination, (o, v) => o.destination = v)
                     .undefined_when(o => o.destination == null)
@@ -44,6 +48,18 @@ namespace Usm {
             }
             path = parts[1];
         }
+
+        public void validate() throws ManifestError {
+            // Validate that path and pathBase are provided when type is "reg"
+            if (file_type == ManifestFileType.REGULAR) {
+                if (path_base == null) {
+                    throw new ManifestError.INVALID_PATH_BASE("pathBase is required when type is 'reg'");
+                }
+                if (path == null && path_base != ManifestFilePathBase.AS_EXPECTED) {
+                    throw new ManifestError.INVALID_FILE_PATH("path is required when type is 'reg' and pathBase is not 'as-expected'");
+                }
+            }
+        }
         
     }
 

+ 9 - 5
src/lib/Manifest.vala

@@ -109,12 +109,16 @@ namespace Usm {
             provides = new Dictionary<ResourceRef, ManifestFile>();
             var mapper = ManifestFile.get_mapper();
             foreach (var pair in obj) {
+                ManifestFile file;
                 if(pair.value.assignable_to<string>()) {
-                    provides[new ResourceRef(pair.key)] = new ManifestFile.from_string(pair.value.as<string>());
+                    file = new ManifestFile.from_string(pair.value.as<string>());
                 }
                 else {
-                    provides[new ResourceRef(pair.key)] = mapper.materialise(pair.value.as<Properties>());
+                    file = mapper.materialise(pair.value.as<Properties>());
                 }
+                // Validate the ManifestFile after creation
+                file.validate();
+                provides[new ResourceRef(pair.key)] = file;
             }
         }
 
@@ -302,9 +306,9 @@ namespace Usm {
                             base_path = Path.build_filename(install_path, paths.get_suggested_path(resource.key));
                             break;
                         default:
-                            assert_not_reached();                            
+                            assert_not_reached();
                     }
-                    var src = File.new_build_filename(base_path, resource.value.path);
+                    var src = File.new_build_filename(base_path, resource.value.path ?? "");
                     var dest = File.new_for_path(path);
 
                     if(!src.query_exists()) {
@@ -324,7 +328,7 @@ namespace Usm {
                 else if(resource.value.file_type == Usm.ManifestFileType.SYMBOLIC_LINK) {
                     var dest = File.new_for_path(path);
                     if(!dry_run){
-                        dest.make_symbolic_link(resource.value.path);
+                        dest.make_symbolic_link(resource.value.path ?? "");
                     }
                 }
                 else {