Explorar el Código

Slightly more complete changes

Billy Barrow hace 6 meses
padre
commit
3895474878
Se han modificado 6 ficheros con 189 adiciones y 10 borrados
  1. 1 0
      MANIFEST.usm
  2. 136 8
      src/cli/Manifest.vala
  3. 2 1
      src/lib/Manifest.vala
  4. 12 0
      src/lib/Paths.vala
  5. 30 0
      src/lib/ResourceRef.vala
  6. 8 1
      src/lib/State/CachedPackage.vala

+ 1 - 0
MANIFEST.usm

@@ -3,6 +3,7 @@
   "version": "0.0.1",
   "summary": "Universal Source Manifest",
   "licences": [ {"name": "GPLv3", "category": "libre", "text": "src/LICENSE"} ],
+  "flags": [],
   "provides": {
     "bin:usm": "as-expected",
     "lib:libusm.so": "as-expected",

+ 136 - 8
src/cli/Manifest.vala

@@ -12,7 +12,7 @@ public static int manifest_main(string[] args) {
 
     var verb = args[1];
 
-    if(verb != "remove" && verb != "acquire" && verb != "install" && verb != "package") {
+    if(verb != "remove" && verb != "acquire" && verb != "install" && verb != "package" && verb != "autoprovides") {
         if(args.length < 3) {
             manifest_usage();
             return 255;
@@ -38,7 +38,7 @@ public static int manifest_main(string[] args) {
         return build();
     }
 
-    if(verb == "install") {
+    if(verb == "install" || verb == "autoprovides") {
         if(build_path == null) {
             var dir = File.new_build_filename("/tmp", Uuid.string_random());
             try {
@@ -50,6 +50,9 @@ public static int manifest_main(string[] args) {
             }
             build_path = dir.get_path();
         }
+    }
+
+    if(verb == "install") {
         return install();
     }
 
@@ -65,6 +68,10 @@ public static int manifest_main(string[] args) {
         return package();
     }
 
+    if(verb == "autoprovides") {
+        return autoprovides();
+    }
+
 
     manifest_usage();
     return 255;
@@ -312,14 +319,135 @@ private int package() {
 
     printerr("Writing archive...\n");
     var output = @"../$(manifest.name)-$(manifest.version).usmc";
-    var proc = new Subprocess.newv(new string[] { "tar", "-cJf", output, "."}, SubprocessFlags.INHERIT_FDS);
-    var result = proc.wait_check() ? 0 : 254;
-
-    if(result == 0) {
+    try {
+        var proc = new Subprocess.newv(new string[] { "tar", "-cJf", output, "."}, SubprocessFlags.INHERIT_FDS);
+        proc.wait_check();
         printerr(@"Wrote package to path \"$(output)\"\n");
+        return 0;
     }
-    else {
+    catch(Error e) {
         printerr("Failed to write package\n");
+        return 172;
+    }
+}
+
+private int autoprovides() {
+    var missing_management_deps = manifest.dependencies.manage.where(d => !d.is_satisfied());
+    var missing_build_deps = manifest.dependencies.build.where(d => !d.is_satisfied());
+    var missing_runtime_deps = manifest.dependencies.runtime.where(d => !d.is_satisfied());
+
+    if(manifest.executables.install == null) {
+        printerr(@"Autoprovides command only works with manifests that specify an installation executable.\n");
+        return 1;
+    }
+
+    var sane = true;
+    if(missing_management_deps.any()) {
+        sane = false;
+        foreach (var item in missing_management_deps) {
+            printerr(@"Missing management dependency \"$item\".\n");
+        }
+    }
+    if(missing_build_deps.any()) {
+        sane = false;
+        foreach (var item in missing_build_deps) {
+            printerr(@"Missing build dependency \"$item\".\n");
+        }
+    }
+    if(missing_runtime_deps.any()) {
+        sane = false;
+        foreach (var item in missing_runtime_deps) {
+            printerr(@"Missing runtime dependency \"$item\".\n");
+        }
+    }
+
+    if(!sane) {
+        printerr("Could not install manifest, missing dependencies\n");
+        return 252;
+    }
+
+    try {
+        var proc = manifest.run_build(build_path, paths, SubprocessFlags.STDOUT_SILENCE);
+        proc.wait_check();
+    }
+    catch(Error e) {
+        printerr(@"Error running build exec: $(e.message)\n");
+        return 251;
+    }
+
+    var install_dir = File.new_build_filename("/tmp", Uuid.string_random());
+    try {
+        install_dir.make_directory();
+    }
+    catch(Error e) {
+        printerr(@"Could not create temporary install directory: $(e.message)\n");
+        return 250;
+    }
+
+    try {
+        manifest.run_install(build_path, install_dir.get_path(), paths, Usm.InstallType.FRESH, SubprocessFlags.STDOUT_SILENCE).wait_check();
+    }
+    catch(Error e) {
+        printerr(@"Error running install exec: $(e.message)\n");
+        return 249;
+    }
+
+    try {
+        var provides = autoprovides_scan_tree(install_dir.get_path(), install_dir.get_path());
+
+        var json = "\"provides\": {\n";
+        foreach (var item in provides) {
+            json += @"    \"$item\": \"as-expected\",\n";
+        }
+        if(provides.any()) {
+            json = json.substring(0, json.length - 2);
+        }
+
+        print(@"$json\n}\n");
+        return 0;
+    }
+    catch(Error e) {
+        printerr(@"Error scanning installation result: $(e.message)\n");
+        return 249;
+    }
+}
+
+public static Invercargill.Vector<string> autoprovides_scan_tree(string install_root, string path) throws Error {
+    // Creating a new Directory object for the given folder path
+    var folder = File.new_for_path(path);
+
+    // Getting a list of all files and folders inside the directory
+    var enumerator = folder.enumerate_children("*", FileQueryInfoFlags.NONE);
+
+    var provides = new Invercargill.Vector<string>();
+
+    // Looping through each file/folder and removing them
+    while (true) {
+        FileInfo? info = enumerator.next_file();
+        if (info == null) {
+            break;
+        }
+
+        // Checking if the current item is a file or a folder
+        if (info.get_file_type() == FileType.REGULAR) {
+            // Removing the file
+            var file = folder.get_child(info.get_name());
+            var true_path = file.get_path().substring(install_root.length);
+            var type = paths.get_suggested_resource_type(true_path);
+            if(type == Usm.ResourceType.ROOT_PATH) {
+                provides.add("rootpath:" + true_path);
+            }
+            else {
+                provides.add(@"$type:$(file.get_basename())");
+            }
+
+        }
+        else if (info.get_file_type() == FileType.DIRECTORY) {
+            // Removing the folder recursively
+            var subfolder = folder.get_child(info.get_name());
+            provides.add_all(autoprovides_scan_tree(install_root, subfolder.get_path()));
+        }
     }
-    return result;
+    
+    return provides;
 }

+ 2 - 1
src/lib/Manifest.vala

@@ -24,7 +24,7 @@ namespace Usm {
         public Dictionary<ResourceRef, ManifestFile> provides { get; set; }
         public Dependencies dependencies { get; set; }
         public Executables executables { get; set; }
-        public Vector<ManifestFlag> flags { get; set; }
+        public Set<ManifestFlag> flags { get; set; }
 
         public string? markdown_path { get; set; }
         public string? url { get; set; }
@@ -43,6 +43,7 @@ namespace Usm {
                 cfg.map<Properties>("provides", o => o.map_from_provides_dict(), (o, v) => o.build_provides_dict(v));
                 cfg.map_with<Dependencies>("depends", o => o.dependencies, (o, v) => o.dependencies = v, Dependencies.get_mapper());
                 cfg.map_with<Executables>("execs", o => o.executables, (o, v) => o.executables = v, Executables.get_mapper());
+                cfg.map_many<string>("flags", o => o.flags.select<string>(f => f.to_string()), (o, v) => o.flags = v.try_select<ManifestFlag>(f => ManifestFlag.from_string(f)).unwrap_to_set());
                 cfg.map<string>("md", o => o.markdown_path, (o, v) => o.markdown_path = v, false);
                 cfg.map<string>("url", o => o.url, (o, v) => o.url = v, false);
                 cfg.map_many<string>("screenshots", o => o.screenshot_paths, (o, v) => o.screenshot_paths = v.to_vector(), false);

+ 12 - 0
src/lib/Paths.vala

@@ -86,6 +86,18 @@ namespace Usm {
             }
         }
 
+        public ResourceType get_suggested_resource_type(string path) {
+            var name = Path.get_basename(path);
+            var types = ResourceType.get_types()
+                .where(t => get_suggested_path(new ResourceRef.with_type(t, name)) == path)
+                .to_vector();
+
+            if(types.no()) {
+                return ResourceType.ROOT_PATH;
+            }
+            return types.first_or_default();
+        }
+
         public string get_tag_file_path(string tag) {
             var tag_path = tag.replace(".", "/");
             tag_path += ".tag";

+ 30 - 0
src/lib/ResourceRef.vala

@@ -117,6 +117,31 @@ namespace Usm {
                     throw new ManifestError.INVALID_RESOURCE_TYPE(@"Unknown resource type \"$str\".");
             }
         }
+
+        public static Enumerable<ResourceType> get_types() {
+            return ate(new ResourceType[] {
+                ROOT_PATH,
+                PATH,
+                OPTIONAL,
+                RESOURCE,
+                CONFIGURATION,
+                BINARY,
+                SUPER_BINARY,
+                LIBRARY,
+                LIBRARY_EXECUTABLE,
+                LIBRARY_RESOURCE,
+                INFO_PAGE,
+                MANUAL_PAGE,
+                LOCALE,
+                APPLICATION,
+                INCLUDE,
+                PKG_CONFIG,
+                VALA_API,
+                GOBJECT_IR,
+                TYPELIB,
+                TAG
+            });
+        }
     }
 
     public class ResourceRef : Hashable, Equatable<ResourceRef> {
@@ -128,6 +153,11 @@ namespace Usm {
             resource_type = ResourceType.from_string(parts[0]);
             resource = parts[1];
         }
+
+        public ResourceRef.with_type(ResourceType type, string name) {
+            resource_type = type;
+            resource = name;
+        }
         
         public uint hash_code() {
             return to_string().hash();

+ 8 - 1
src/lib/State/CachedPackage.vala

@@ -32,7 +32,14 @@ namespace Usm {
 
         public string create_build_directory() throws Error {
             var path = build_directory_path();
-            File.new_for_path(path).make_directory();
+            var manifest = get_manifest();
+            var file = File.new_for_path(path);
+            if(manifest.flags.has(ManifestFlag.BUILD_IN_SOURCE_TREE)) {
+                file.make_symbolic_link(source_directory_path());
+            }
+            else {
+                File.new_for_path(path).make_directory();
+            }
             return path;
         }