Ver Fonte

Draft up new specification for repositories and complete packages. Add basic models (unused) for these specifications

Billy Barrow há 7 meses atrás
pai
commit
574fbef674
7 ficheiros alterados com 400 adições e 272 exclusões
  1. 44 2
      README.md
  2. 7 270
      src/cli/Cli.vala
  3. 289 0
      src/cli/Manifest.vala
  4. 1 0
      src/cli/meson.build
  5. 23 0
      src/lib/Repository.vala
  6. 34 0
      src/lib/RepositoryListing.vala
  7. 2 0
      src/lib/meson.build

+ 44 - 2
README.md

@@ -35,7 +35,7 @@
 }
 ```
 
-## Optional extended properties
+### Optional extended properties
 
 ```json
 {
@@ -55,4 +55,46 @@
 - "bin": Binary executable: file name locatable in `$PATH`
 - "lib": Shared library: file name locatable by LD
 - "app": Desktop entry: file name in /usr/share/applications
-- "inc": Include: file name in /usr/include
+- "inc": Include: file name in /usr/include
+
+## Source Repositories (Repo.usmr)
+
+```json
+{
+  "name": "my-repo",
+  "summary": "My software repository",
+  "url": "https://my.software/repository",
+  "key": "EDXLsUvOZEne+xcv+huvSaqNBs8TTldCv6hd69GdmYw="
+}
+```
+
+## Source Repository listing (PACKAGES.usml)
+
+Entries in JSON lines format:
+
+```json
+{
+  "type": "usmc",
+  "manifest": {}, // Manifest object from MANIFEST.usm
+  "path": "my-package.usmc", // Relative path to the package
+  "sha512": "0+6QpQ5Wst2bPmAPYKO/RKrFYuq93rcaRs7tqt9lCo9zu8v6jpJsDqd7yPIqCWDt0KpOQ3uLK64Tmn9FYNw3eQ=="
+}
+```
+
+Last line consists of the signatures for the repository
+
+```json
+{
+  "type": "signatures",
+  "signatures": [
+    {
+      "key": "EDXLsUvOZEne+xcv+huvSaqNBs8TTldCv6hd69GdmYw=",
+      "signature": "0rHQiDGKgumMK2S3B6D9jjU3NLnLLjijYJRvaB5vLbp4zxzjlixfyX8yfvvJUCCd34CC1STzyzawDtb9ZammCTE4zFHFdpnO8eseDS5OY+aKgAyL13oBGizvy/V0zGHVCdv83GQ7QUtgSWje0RKKk1zPGDAIF/prkurlFDgd3Vg="
+    }
+  ]
+}
+```
+
+## Complete package (package.usmc)
+
+Complete package is simply a tar.xz file containing a MANIFEST.usm file and all the requisite files that would be acquired if the acquire script was run. That is to say, a USMC file could be created by simply running `usm manifest acquire` followed by `tar -cJf ../package.usmc .`.

+ 7 - 270
src/cli/Cli.vala

@@ -1,6 +1,4 @@
-Usm.Manifest manifest = null;
 Usm.Paths paths;
-string? build_path = null;
 
 
 public static int main(string[] args) {
@@ -11,55 +9,12 @@ public static int main(string[] args) {
         return 255;
     }
 
-    var verb = args[1];
-
-    if(verb != "remove" && verb != "acquire" && verb != "install") {
-        if(args.length < 3) {
-            usage();
-            return 255;
-        }
-        build_path = args[2];
-    }
-
-    if(!File.new_for_path("MANIFEST.usm").query_exists()) {
-        printerr("No MANIFEST.usm file found in current directory.\n");
-        return 254;
-    }
-
-    try {
-        var element = new InvercargillJson.JsonElement.from_file("MANIFEST.usm");
-        manifest = Usm.Manifest.get_mapper().materialise(element.as<Invercargill.Properties>());
-    }
-    catch (Error e) {
-        printerr(@"Could not read MANIFEST.usm: $(e.message)\n");
-        return 253;
-    }
-
-    if(verb == "build") {
-        return build();
-    }
-
-    if(verb == "install") {
-        if(build_path == null) {
-            var dir = File.new_build_filename("/tmp", Uuid.string_random());
-            try {
-                dir.make_directory();
-            }
-            catch(Error e) {
-                printerr(@"Could not create temporary build directory, try specifying one instead: $(e.message)\n");
-                return 255;
-            }
-            build_path = dir.get_path();
-        }
-        return install();
-    }
-
-    if(verb == "acquire") {
-        return acquire();
-    }
-
-    if(verb == "remove") {
-        return uininstall();
+    var command = args[1];
+    if(command == "manifest") {
+        var m_args = new Invercargill.Vector<string>();
+        m_args.add_all(Invercargill.Convert.ate(args));
+        m_args.remove(1);
+        return manifest_main(m_args.to_array());
     }
 
 
@@ -68,223 +23,5 @@ public static int main(string[] args) {
 }
 
 private void usage() {
-    printerr("USAGE:\n\tusm build <build path>\n\tusm install <build path>\n\tusm remove\nusm acquire\n");
-}
-
-
-private int build() {
-    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 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(!sane) {
-        printerr("Could not build manifest, missing dependencies\n");
-        return 252;
-    }
-
-    try {
-        var proc = manifest.run_build(build_path, paths, SubprocessFlags.INHERIT_FDS);
-        proc.wait_check();
-    }
-    catch(Error e) {
-        printerr(@"Error running build exec: $(e.message)\n");
-        return 251;
-    }
-
-    return 0;
-}
-
-private int install() {
-    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());
-
-    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_build_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.INHERIT_FDS);
-        proc.wait_check();
-    }
-    catch(Error e) {
-        printerr(@"Error running build exec: $(e.message)\n");
-        return 251;
-    }
-
-    foreach (var resource in manifest.provides) {
-        var path = paths.get_suggested_path(resource.key);
-        printerr(@"Installing $(resource.key) to $path...");
-        try {
-            if(resource.value.file_type == Usm.ManifestFileType.REGULAR) {
-                var src = File.new_build_filename(build_path, resource.value.path);
-                var dest = File.new_for_path(path);
-                src.copy(dest, FileCopyFlags.OVERWRITE);
-            }
-            else if(resource.value.file_type == Usm.ManifestFileType.DIRECTORY) {
-                var dest = File.new_for_path(path);
-                dest.make_directory();
-            }
-            else if(resource.value.file_type == Usm.ManifestFileType.SYMBOLIC_LINK) {
-                var dest = File.new_for_path(path);
-                dest.make_symbolic_link(resource.value.path);
-            }
-            else {
-                printerr(@" File type not implemented\n");
-                return 250;
-            }
-        }
-        catch(Error e) {
-            printerr(@" $(e.message)\n");
-            return 250;
-        }
-        printerr(" done\n");
-    }
-
-    try {
-        var proc = manifest.run_install(build_path, Usm.InstallType.FRESH, SubprocessFlags.INHERIT_FDS);
-        if(proc != null) {
-            proc.wait_check();
-        }
-    }
-    catch(Error e) {
-        printerr(@"Error running install exec: $(e.message)\n");
-        return 249;
-    }
-
-    return 0;
+    printerr("USAGE:\n\tusm manifest\n");
 }
-
-
-private int acquire() {
-    if(manifest.executables.acquire == null) {
-        printerr(@"Manifest does not reference an acquire script\n");
-        return 248;
-    }
-
-    if(manifest.dependencies.acquire != null) {
-        var missing_acquire_deps = manifest.dependencies.manage.where(d => !d.is_satisfied());
-        if(missing_acquire_deps.any()) {
-            foreach (var item in missing_acquire_deps) {
-                printerr(@"Missing acquire dependency \"$item\".\n");
-            }
-            printerr("Could not build manifest, missing dependencies\n");
-            return 247;
-        }
-
-    }
-
-    try {
-        var proc = manifest.run_acquire(SubprocessFlags.INHERIT_FDS);
-        proc.wait_check();
-    }
-    catch(Error e) {
-        printerr(@"Error running build exec: $(e.message)\n");
-        return 251;
-    }
-
-    return 0;
-}
-
-private int uininstall() {
-    var missing_management_deps = manifest.dependencies.manage.where(d => !d.is_satisfied());
-
-    if(missing_management_deps.any()) {
-        foreach (var item in missing_management_deps) {
-            printerr(@"Missing management dependency \"$item\".\n");
-        }
-
-        printerr("Could not remove manifest, missing dependencies\n");
-        return 252;
-    }
-
-    try {
-        var proc = manifest.run_remove(Usm.RemoveType.FINAL, SubprocessFlags.INHERIT_FDS);
-        if(proc != null) {
-            proc.wait_check();
-        }
-    }
-    catch(Error e) {
-        printerr(@"Error running remove exec: $(e.message)\n");
-        return 249;
-    }
-
-    // Do files and symlinks first
-    foreach (var resource in manifest.provides.where(r => r.value.file_type != Usm.ManifestFileType.DIRECTORY)) {
-        var path = paths.get_suggested_path(resource.key);
-        printerr(@"Deleting resource $(resource.key) from $path...");
-        try {
-            var file = File.new_for_path(path);
-            if(file.query_exists()) {
-                file.delete();
-                printerr(" done\n");
-            }
-            else {
-                printerr(" file missing\n");
-            }
-        }
-        catch(Error e) {
-            printerr(@" $(e.message)\n");
-            return 250;
-        }
-    }
-
-    // Do directories last
-    foreach (var resource in manifest.provides.where(r => r.value.file_type == Usm.ManifestFileType.DIRECTORY)) {
-        var path = paths.get_suggested_path(resource.key);
-        printerr(@"Deleting resource $(resource.key) from $path...");
-        try {
-            var file = File.new_for_path(path);
-            if(file.query_exists()) {
-                file.delete();
-                printerr(" done\n");
-            }
-            else {
-                printerr(" file missing\n");
-            }
-        }
-        catch(IOError.NOT_EMPTY e) {
-            printerr(" directory not empty\n");
-        }
-        catch(Error e) {
-            printerr(@" $(e.message)\n");
-            return 250;
-        }
-    }
-
-    return 0;
-}

+ 289 - 0
src/cli/Manifest.vala

@@ -0,0 +1,289 @@
+Usm.Manifest manifest = null;
+string? build_path = null;
+
+
+public static int manifest_main(string[] args) {
+    paths = new Usm.Paths.usm_environ();
+
+    if(args.length < 2) {
+        manifest_usage();
+        return 255;
+    }
+
+    var verb = args[1];
+
+    if(verb != "remove" && verb != "acquire" && verb != "install") {
+        if(args.length < 3) {
+            manifest_usage();
+            return 255;
+        }
+        build_path = args[2];
+    }
+
+    if(!File.new_for_path("MANIFEST.usm").query_exists()) {
+        printerr("No MANIFEST.usm file found in current directory.\n");
+        return 254;
+    }
+
+    try {
+        var element = new InvercargillJson.JsonElement.from_file("MANIFEST.usm");
+        manifest = Usm.Manifest.get_mapper().materialise(element.as<Invercargill.Properties>());
+    }
+    catch (Error e) {
+        printerr(@"Could not read MANIFEST.usm: $(e.message)\n");
+        return 253;
+    }
+
+    if(verb == "build") {
+        return build();
+    }
+
+    if(verb == "install") {
+        if(build_path == null) {
+            var dir = File.new_build_filename("/tmp", Uuid.string_random());
+            try {
+                dir.make_directory();
+            }
+            catch(Error e) {
+                printerr(@"Could not create temporary build directory, try specifying one instead: $(e.message)\n");
+                return 255;
+            }
+            build_path = dir.get_path();
+        }
+        return install();
+    }
+
+    if(verb == "acquire") {
+        return acquire();
+    }
+
+    if(verb == "remove") {
+        return uininstall();
+    }
+
+
+    manifest_usage();
+    return 255;
+}
+
+private void manifest_usage() {
+    printerr("USAGE:\n\tusm manifest build <build path>\n\tusm manifest install <build path>\n\tusm manifest remove\nusm manifest acquire\n");
+}
+
+
+private int build() {
+    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 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(!sane) {
+        printerr("Could not build manifest, missing dependencies\n");
+        return 252;
+    }
+
+    try {
+        var proc = manifest.run_build(build_path, paths, SubprocessFlags.INHERIT_FDS);
+        proc.wait_check();
+    }
+    catch(Error e) {
+        printerr(@"Error running build exec: $(e.message)\n");
+        return 251;
+    }
+
+    return 0;
+}
+
+private int install() {
+    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());
+
+    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_build_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.INHERIT_FDS);
+        proc.wait_check();
+    }
+    catch(Error e) {
+        printerr(@"Error running build exec: $(e.message)\n");
+        return 251;
+    }
+
+    foreach (var resource in manifest.provides) {
+        var path = paths.get_suggested_path(resource.key);
+        printerr(@"Installing $(resource.key) to $path...");
+        try {
+            if(resource.value.file_type == Usm.ManifestFileType.REGULAR) {
+                var src = File.new_build_filename(build_path, resource.value.path);
+                var dest = File.new_for_path(path);
+                src.copy(dest, FileCopyFlags.OVERWRITE);
+            }
+            else if(resource.value.file_type == Usm.ManifestFileType.DIRECTORY) {
+                var dest = File.new_for_path(path);
+                dest.make_directory();
+            }
+            else if(resource.value.file_type == Usm.ManifestFileType.SYMBOLIC_LINK) {
+                var dest = File.new_for_path(path);
+                dest.make_symbolic_link(resource.value.path);
+            }
+            else {
+                printerr(@" File type not implemented\n");
+                return 250;
+            }
+        }
+        catch(Error e) {
+            printerr(@" $(e.message)\n");
+            return 250;
+        }
+        printerr(" done\n");
+    }
+
+    try {
+        var proc = manifest.run_install(build_path, Usm.InstallType.FRESH, SubprocessFlags.INHERIT_FDS);
+        if(proc != null) {
+            proc.wait_check();
+        }
+    }
+    catch(Error e) {
+        printerr(@"Error running install exec: $(e.message)\n");
+        return 249;
+    }
+
+    return 0;
+}
+
+
+private int acquire() {
+    if(manifest.executables.acquire == null) {
+        printerr(@"Manifest does not reference an acquire script\n");
+        return 248;
+    }
+
+    if(manifest.dependencies.acquire != null) {
+        var missing_acquire_deps = manifest.dependencies.manage.where(d => !d.is_satisfied());
+        if(missing_acquire_deps.any()) {
+            foreach (var item in missing_acquire_deps) {
+                printerr(@"Missing acquire dependency \"$item\".\n");
+            }
+            printerr("Could not build manifest, missing dependencies\n");
+            return 247;
+        }
+
+    }
+
+    try {
+        var proc = manifest.run_acquire(SubprocessFlags.INHERIT_FDS);
+        proc.wait_check();
+    }
+    catch(Error e) {
+        printerr(@"Error running build exec: $(e.message)\n");
+        return 251;
+    }
+
+    return 0;
+}
+
+private int uininstall() {
+    var missing_management_deps = manifest.dependencies.manage.where(d => !d.is_satisfied());
+
+    if(missing_management_deps.any()) {
+        foreach (var item in missing_management_deps) {
+            printerr(@"Missing management dependency \"$item\".\n");
+        }
+
+        printerr("Could not remove manifest, missing dependencies\n");
+        return 252;
+    }
+
+    try {
+        var proc = manifest.run_remove(Usm.RemoveType.FINAL, SubprocessFlags.INHERIT_FDS);
+        if(proc != null) {
+            proc.wait_check();
+        }
+    }
+    catch(Error e) {
+        printerr(@"Error running remove exec: $(e.message)\n");
+        return 249;
+    }
+
+    // Do files and symlinks first
+    foreach (var resource in manifest.provides.where(r => r.value.file_type != Usm.ManifestFileType.DIRECTORY)) {
+        var path = paths.get_suggested_path(resource.key);
+        printerr(@"Deleting resource $(resource.key) from $path...");
+        try {
+            var file = File.new_for_path(path);
+            if(file.query_exists()) {
+                file.delete();
+                printerr(" done\n");
+            }
+            else {
+                printerr(" file missing\n");
+            }
+        }
+        catch(Error e) {
+            printerr(@" $(e.message)\n");
+            return 250;
+        }
+    }
+
+    // Do directories last
+    foreach (var resource in manifest.provides.where(r => r.value.file_type == Usm.ManifestFileType.DIRECTORY)) {
+        var path = paths.get_suggested_path(resource.key);
+        printerr(@"Deleting resource $(resource.key) from $path...");
+        try {
+            var file = File.new_for_path(path);
+            if(file.query_exists()) {
+                file.delete();
+                printerr(" done\n");
+            }
+            else {
+                printerr(" file missing\n");
+            }
+        }
+        catch(IOError.NOT_EMPTY e) {
+            printerr(" directory not empty\n");
+        }
+        catch(Error e) {
+            printerr(@" $(e.message)\n");
+            return 250;
+        }
+    }
+
+    return 0;
+}

+ 1 - 0
src/cli/meson.build

@@ -1,5 +1,6 @@
 
 sources = files('Cli.vala')
+sources += files('Manifest.vala')
 
 deps = dependencies
 deps += usm_dep

+ 23 - 0
src/lib/Repository.vala

@@ -0,0 +1,23 @@
+using Invercargill;
+
+namespace Usm {
+
+    public class Repository {
+        public string name { get; set; }
+        public string summary { get; set; }
+        public string url { get; set; }
+        public BinaryData key { get; set; }
+
+
+        public static PropertyMapper<Repository> get_mapper() {
+            return PropertyMapper.build_for<Repository>(cfg => {
+                cfg.map<string>("name", o => o.name, (o, v) => o.name = v);
+                cfg.map<string>("summary", o => o.summary, (o, v) => o.summary = v);
+                cfg.map<string>("url", o => o.url, (o, v) => o.url = v, false);
+                cfg.map<string>("key", o => o.key.to_base64(), (o, v) => o.key = new BinaryData.from_base64(v));
+                cfg.set_constructor(() => new Repository());
+            });
+        }       
+
+    }
+}

+ 34 - 0
src/lib/RepositoryListing.vala

@@ -0,0 +1,34 @@
+using Invercargill;
+
+namespace Usm {
+
+    public class RepositoryListingEntry {
+        public string path { get; set; }
+        public Manifest manifest { get; set; }
+        public BinaryData sha512sum { get; set; }
+
+
+        public static PropertyMapper<RepositoryListingEntry> get_mapper() {
+            return PropertyMapper.build_for<RepositoryListingEntry>(cfg => {
+                cfg.map<string>("path", o => o.path, (o, v) => o.path = v);
+                cfg.map_with<Manifest>("manifest", o => o.manifest, (o, v) => o.manifest = v, Manifest.get_mapper());
+                cfg.map<string>("sha512", o => o.sha512sum.to_base64(), (o, v) => o.sha512sum = new BinaryData.from_base64(v));
+                cfg.set_constructor(() => new RepositoryListingEntry());
+            });
+        }       
+    }
+
+    public class RepositoryListingSignature {
+        public BinaryData key { get; set; }
+        public BinaryData signature { get; set; }
+
+
+        public static PropertyMapper<RepositoryListingSignature> get_mapper() {
+            return PropertyMapper.build_for<RepositoryListingSignature>(cfg => {
+                cfg.map<string>("key", o => o.key.to_base64(), (o, v) => o.key = new BinaryData.from_base64(v));
+                cfg.map<string>("signature", o => o.signature.to_base64(), (o, v) => o.signature = new BinaryData.from_base64(v));
+                cfg.set_constructor(() => new RepositoryListingSignature());
+            });
+        }       
+    }
+}

+ 2 - 0
src/lib/meson.build

@@ -10,6 +10,8 @@ sources += files('Licence.vala')
 sources += files('Paths.vala')
 sources += files('ResourceRef.vala')
 sources += files('Version.vala')
+sources += files('Repository.vala')
+sources += files('RepositoryListing.vala')
 
 
 dependencies = [