فهرست منبع

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

Billy Barrow 10 ماه پیش
والد
کامیت
574fbef674
7فایلهای تغییر یافته به همراه400 افزوده شده و 272 حذف شده
  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 = [