Prechádzať zdrojové kódy

Very dirty happy path works

Billy Barrow 6 mesiacov pred
rodič
commit
e9f0fbff9b

+ 4 - 1
src/cli/Cli.vala

@@ -22,6 +22,9 @@ public static int main(string[] args) {
     if(command == "repository") {
         return repository_main(args);
     }
+    if(command == "install") {
+        return install_main(args);
+    }
 
 
     usage();
@@ -29,7 +32,7 @@ public static int main(string[] args) {
 }
 
 private void usage() {
-    printerr("USAGE:\n\tusm manifest\n");
+    printerr("USAGE:\n\tusm manifest\n\tusm info\n\tusm repository\n\tusm install\n");
 }
 
 

+ 62 - 0
src/cli/Install.vala

@@ -0,0 +1,62 @@
+using Invercargill;
+
+private int install_main(string[] args) {
+
+    if(args.length < 3) {
+        return install_usage();
+    }
+
+    var state = new Usm.SystemState(paths);
+    
+    printerr("Refreshing repositories...\n");
+    var resolver = new Usm.Resolver();
+    var repos = state.get_repositories();
+    foreach (var repo in repos) {
+        state.refresh_list(repo, (f, c, t) => printerr(@"Refreshing list for $(repo.name): downloading $f $c/$t bytes\r"));
+        var listing = state.get_latest_list(repo);
+        if(listing != null) {
+            resolver.load_listing(repo, listing);
+        }
+        printerr("\n");
+    }
+
+    var target = resolver.find_package(args[2]);
+    var client = target.repository.get_client();
+
+    printerr("3\n");
+    var path = state.generate_cache_path(target.manifest);
+    File.new_for_path(path).make_directory();
+    var package_path = Path.build_filename(path, "package.usmc");
+    var extract_path = Path.build_filename(path, "package");
+    File.new_for_path(extract_path).make_directory();
+    client.download_package(package_path, target.repository_entry, (f, c, t) => printerr(@"Downloading $f $c/$t bytes\r"));
+    client.verify_package(package_path, target.repository_entry, (f, c, t) => printerr(@"Verifying $f $c/$t bytes\r"));
+    var cached_package = new Usm.CachedPackage(path);
+
+    var proc = new Subprocess.newv(new string[] { "tar", "-xf", package_path, "-C", extract_path }, SubprocessFlags.INHERIT_FDS);
+    if(!proc.wait_check()) {
+        printerr("Failed to extract package\n");
+        return 20;
+    }
+
+    Environment.set_current_dir(extract_path);
+    manifest = new Usm.Manifest.from_file("MANIFEST.usm");
+    build_path = cached_package.create_build_directory();
+
+    var result = install();
+    if(result != 0) {
+        return result;
+    }
+
+    state.mark_installed(cached_package);
+    cached_package.get_build_archive();
+
+    // todo cleanup
+
+    return 0;
+}
+
+private int install_usage() {
+    printerr("USAGE:\n\tusm install <packages>\n");
+    return 255;
+}

+ 1 - 0
src/cli/meson.build

@@ -2,6 +2,7 @@
 sources = files('Cli.vala')
 sources += files('Manifest.vala')
 sources += files('Repository.vala')
+sources += files('Install.vala')
 
 deps = dependencies
 deps += usm_dep

+ 68 - 0
src/lib/Resolver.vala

@@ -0,0 +1,68 @@
+using Invercargill;
+
+namespace Usm {
+
+    public class Resolver {
+
+        private Dictionary<Repository, RepositoryListing> listings = new Dictionary<Repository, RepositoryListing>();
+
+        public void load_listing(Repository repo, RepositoryListing listing) {
+            listings.set(repo, listing);
+        }
+
+        public AbstractPackage? find_package(string search) {
+            return listings
+                .select_many<Pair<Repository, RepositoryListingEntry>>(l => l.value.entries.select_pairs<Repository, RepositoryListingEntry>(e => l.key, e => e))
+                .where(p => p.value2.manifest.name == search)
+                .select<AbstractPackage>(p => new AbstractPackage.from_repository(p.value1, p.value2))
+                .first_or_default();
+        }
+
+    }
+
+    public class PackageSet : Set<AbstractPackage> {
+
+        private Set<ResourceRef> provided_in_set = new Set<ResourceRef>();
+
+        public void add_from_file(string path) throws Error {
+            add(new AbstractPackage.from_package(path));
+        }
+
+        public void add_from_repo(Repository repository, RepositoryListingEntry entry) throws Error {
+            add(new AbstractPackage.from_repository(repository, entry));
+        }
+
+        public bool is_satisfied() {
+            return all(check_satisfied);
+        }
+
+        private bool check_satisfied(AbstractPackage package) {
+            return package.manifest.dependencies.build.all(d => provided_in_set.has(d) || d.is_satisfied()) &&
+                package.manifest.dependencies.manage.all(d => provided_in_set.has(d) || d.is_satisfied()) &&
+                package.manifest.dependencies.runtime.all(d => provided_in_set.has(d) || d.is_satisfied());
+
+        }
+
+    }
+
+    public class AbstractPackage {
+
+        public Manifest manifest { get; set; }
+        public Repository? repository { get; set; }
+        public RepositoryListingEntry? repository_entry { get; set; }
+        public string? package_path { get; set; }
+
+        public AbstractPackage.from_package(string path) throws Error {
+            package_path = path;
+            manifest = new Manifest.from_file(path);
+        }
+
+        public AbstractPackage.from_repository(Repository repository, RepositoryListingEntry entry) {
+            this.repository = repository;
+            this.repository_entry = entry;
+            this.manifest = entry.manifest;
+        }
+
+    }
+
+}

+ 20 - 0
src/lib/ResourceRef.vala

@@ -3,6 +3,7 @@ using Invercargill.Convert;
 namespace Usm {
 
     public enum ResourceType {
+        PACKAGE,
         ROOT_PATH,
         PATH,
         OPTIONAL,
@@ -25,6 +26,8 @@ namespace Usm {
 
         public string to_string() {
             switch (this) {
+                case ResourceType.PACKAGE:
+                    return "pkg";
                 case ResourceType.ROOT_PATH:
                     return "rootpath";
                 case ResourceType.PATH:
@@ -70,6 +73,8 @@ namespace Usm {
 
         public static ResourceType from_string(string str) throws ManifestError {
             switch (str) {
+                case "pkg":
+                    return ResourceType.PACKAGE;
                 case "rootpath":
                     return ResourceType.ROOT_PATH;
                 case "path":
@@ -136,6 +141,8 @@ namespace Usm {
         
         public bool is_satisfied() {
             switch (resource_type) {
+                case ResourceType.PACKAGE:
+                    return check_pkg();
                 case ResourceType.ROOT_PATH:
                     return check_rootpath();
                 case ResourceType.PATH:
@@ -179,6 +186,19 @@ namespace Usm {
             }
         }
 
+        private bool check_pkg() {
+            var state = new SystemState(new Paths.usm_environ());
+            try {
+                return state.get_installed_packages()
+                    .try_select<Manifest>(p => p.get_manifest())
+                    .results.any(m => m.name == resource);
+            }
+            catch(Error e) {
+                warning(@"Error checking for resource $this: $(e.message)");
+            }
+            return false;
+        }
+
         private bool check_lib() {
             try {
                 var proc = new Subprocess.newv(new string[] { "ldconfig", "-p" }, SubprocessFlags.STDOUT_PIPE);

+ 2 - 2
src/lib/State/CachedPackage.vala

@@ -61,11 +61,11 @@ namespace Usm {
             }
 
             var dir_path = build_directory_path();
-            if(!File.new_for_path(path).query_exists()) {
+            if(!File.new_for_path(dir_path).query_exists()) {
                 throw new StateError.NO_BUILD_ARTIFACT(@"The package \"$package_name\" has no build artifact");
             }
 
-            var proc = new Subprocess.newv(new string[] { "tar", "-cJf", path, dir_path }, SubprocessFlags.INHERIT_FDS);
+            var proc = new Subprocess.newv(new string[] { "tar", "-cJf", path, "--directory", dir_path, "." }, SubprocessFlags.INHERIT_FDS);
             if(!proc.wait_check()) {
                 throw new StateError.ARCHIVAL_FAILED(@"Could not archive \"$dir_path\": tar returned non-zero exit status $(proc.get_status())");
             }

+ 2 - 2
src/lib/State/State.vala

@@ -24,7 +24,7 @@ namespace Usm {
 
         public Enumerable<Repository> get_repositories() throws Error {
             return directory(Path.build_filename(config_path, "repos.d"))
-                .try_select<Repository>(d => new Repository.from_file(Path.build_filename(state_path, "repos.d", d)))
+                .try_select<Repository>(d => new Repository.from_file(Path.build_filename(config_path, "repos.d", d)))
                 .unwrap_to_series();
         }
 
@@ -40,7 +40,7 @@ namespace Usm {
                 .sort((a, b) => a.result.compare(b.result))
                 .first_or_default();
 
-            var stream = new DataInputStream(File.new_build_filename(list_path, latest).read());
+            var stream = new DataInputStream(File.new_build_filename(list_path, latest.origin).read());
             return new RepositoryListing.from_stream(stream);
         }
 

+ 1 - 0
src/lib/meson.build

@@ -10,6 +10,7 @@ sources += files('Licence.vala')
 sources += files('Paths.vala')
 sources += files('ResourceRef.vala')
 sources += files('Version.vala')
+sources += files('Resolver.vala')
 sources += files('Repository/Repository.vala')
 sources += files('Repository/RepositoryListing.vala')
 sources += files('Repository/RepositoryClient.vala')