浏览代码

Load the repository catalog for in-process manifest resolution

The usmrad ensure-deps rewrite built a bare Resolver: no listings, no
cache, so every repository-provided ref resolved as "no USM package
provides it" — deployments saw the system leg install and then fail
(usm-lcc: statum/spry/astralis/invercargill all unresolvable). usm
install and the manifest offer flow load the enrolled repositories
into the resolver first; now everyone does, through one shared
Resolver.load_state(state, paths, warning): every configured
repository's refreshed listing (refresh failures report through the
delegate and fall back to the cached listing — a deploy loop prefers
stale metadata to an abort) plus the package cache. usmrad derives the
SPM from the same SystemState, and the manifest verbs' offer path
drops its inline copy.

Verified inside the enrolled usmrad-fedora image with the locally
built usm overmounted: usm manifest build on usm-lcc now offers the
eight USM packages plus the native plan instead of failing them.
clanker 2 周之前
父节点
当前提交
0fea58233a
共有 3 个文件被更改,包括 86 次插入 和 33 次删除
  1. 6 18
      src/cli/Manifest.vala
  2. 51 0
      src/lib/Resolver.vala
  3. 29 15
      src/rad/System.vala

+ 6 - 18
src/cli/Manifest.vala

@@ -245,24 +245,12 @@ private bool offer_missing_dependencies(Usm.Manifest target) {
 
     var resolver = new Usm.Resolver(resfinder);
     if(state != null) {
-        try {
-            foreach(var repo in state.get_repositories()) {
-                try {
-                    state.refresh_list(repo);
-                }
-                catch(Error e) {
-                    printerr(@"Warning: could not refresh repository \"$(repo.name)\": $(e.message)\n");
-                }
-                var listing = state.get_latest_list(repo);
-                if(listing != null) {
-                    resolver.load_listing(repo, listing);
-                }
-            }
-            resolver.load_cache(paths);
-        }
-        catch(Error e) {
-            printerr(@"Warning: could not load USM repositories or the package cache: $(e.message)\n");
-        }
+        // The shared catalog loader: without it the resolver sees no
+        // USM packages and every repository-provided ref fails as
+        // "no USM package provides it"
+        resolver.load_state((!)state, paths, (repository_name, message) => {
+            printerr(@"Warning: could not refresh repository \"$repository_name\": $message\n");
+        });
     }
 
     Usm.ResolutionResult result = null;

+ 51 - 0
src/lib/Resolver.vala

@@ -164,6 +164,57 @@ namespace Usm {
             catalog_cache = null;
         }
 
+        /**
+         * Reports one repository whose listing refresh failed during
+         * {@link Resolver.load_state} — the caller decides whether a
+         * warning line, a log entry or an abort is appropriate.
+         */
+        public delegate void RepositoryLoadWarning(string repository_name, string message);
+
+        /**
+         * Populates the catalog the way a full `usm install` does:
+         * every configured repository's refreshed listing plus the
+         * package cache. WITHOUT this the resolver sees no USM packages
+         * at all — a bare `new Resolver(...)` resolves local presence
+         * and system packages only, and every repository-provided ref
+         * fails as "no USM package provides it" (the usmrad
+         * empty-catalog regression).
+         *
+         * A repository whose refresh fails reports through {@link
+         * warning} (when set) and falls back to its latest cached
+         * listing — deploy loops prefer continuing on stale metadata
+         * over aborting mid-deploy; `usm install` keeps its own
+         * stricter abort-on-refresh-failure flow with progress
+         * plumbing. Returns the number of listings loaded.
+         */
+        public uint load_state(SystemState state, Paths paths, owned RepositoryLoadWarning? warning = null) {
+            uint loaded = 0;
+            foreach(var repository in state.get_repositories()) {
+                try {
+                    state.refresh_list(repository);
+                }
+                catch(Error e) {
+                    if(warning != null) {
+                        ((!)warning)(repository.name, e.message);
+                    }
+                }
+                var listing = state.get_latest_list(repository);
+                if(listing != null) {
+                    load_listing(repository, (!)listing);
+                    loaded++;
+                }
+            }
+            try {
+                load_cache(paths);
+            }
+            catch(Error e) {
+                if(warning != null) {
+                    ((!)warning)("package cache", e.message);
+                }
+            }
+            return loaded;
+        }
+
         public void supply_package(string path) throws Error {
             supplied.add(new AbstractPackage.from_package(path));
             catalog_cache = null;

+ 29 - 15
src/rad/System.vala

@@ -134,16 +134,40 @@ public class System : Object {
         }
         Log.info(@"$(missing.length) dependency ref(s) of \"$(manifest.name)\" missing");
 
-        var spm = load_system_package_manager();
+        // The enrolled state drives BOTH legs: the system package
+        // manager configuration AND the repository listings the
+        // resolver resolves USM packages against. A bare resolver
+        // sees no USM packages at all — every repository-provided ref
+        // would fail as "no USM package provides it" — so the
+        // listings and cache are loaded exactly like `usm install`
+        // loads them.
+        var paths = new Usm.Paths();
+        Usm.SystemState? system_state = null;
+        try {
+            system_state = new Usm.SystemState(paths);
+        }
+        catch(Error e) {
+            Log.warning(@"Could not read the usm managed state, continuing without USM repositories: $(e.message)");
+        }
+
         Usm.SystemPackageManager? active_spm = null;
-        if(spm != null && spm.enabled) {
-            active_spm = spm;
+        if(system_state != null) {
+            var manager = new Usm.SystemPackageManager(((!)system_state).config);
+            if(manager.enabled) {
+                active_spm = manager;
+            }
         }
-        else {
+        if(active_spm == null) {
             Log.warning("No system package manager is configured; resolving missing dependencies from USM repositories alone");
         }
 
         var resolver = new Usm.Resolver(new Usm.ResourceFinder());
+        if(system_state != null) {
+            var loaded = resolver.load_state((!)system_state, paths, (repository_name, message) => {
+                Log.warning(@"Could not refresh USM repository \"$repository_name\": $message");
+            });
+            Log.info(@"Resolver catalog loaded ($loaded repository listing(s))");
+        }
         Usm.ResolutionResult resolution;
         try {
             resolution = resolver.resolve_manifest(manifest, active_spm);
@@ -180,7 +204,7 @@ public class System : Object {
             Log.info(@"Installing system packages: $(string.joinv(" ", Argv.from_vector(spm_names)))");
             var system_installed = false;
             try {
-                system_installed = yield spm.install(spm_names, event => log_install_progress(event));
+                system_installed = yield ((!)active_spm).install(spm_names, event => log_install_progress(event));
             }
             catch(Error e) {
                 throw new RadError.DEPLOY(@"Could not run the system package manager install: $(e.message)");
@@ -295,16 +319,6 @@ public class System : Object {
      * the configuration cannot be read — dependency resolution then runs
      * against USM repositories alone.
      */
-    private static Usm.SystemPackageManager? load_system_package_manager() {
-        try {
-            return new Usm.SystemPackageManager(new Usm.Configuration.from_paths(new Usm.Paths()));
-        }
-        catch(Error e) {
-            Log.warning(@"Could not read the usm configuration, continuing without a system package manager: $(e.message)");
-            return null;
-        }
-    }
-
     /**
      * One line per streamed system package install event; the per-package
      * progress fraction events stay unlogged to keep the supervisor's