소스 검색

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 {