Explorar o código

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 hai 1 mes
pai
achega
e73a175393
Modificáronse 2 ficheiros con 29 adicións e 9 borrados
  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 {