using Invercargill; using Invercargill.DataStructures; private int install_main(string[] args) { if(args.length < 3) { return install_usage(); } Usm.SystemState state = null; try { state = new Usm.SystemState(paths); } catch(Error e) { printerr(@"This system is not managed by usm: $(e.message)\n"); return 245; } try { printerr("Refreshing repositories...\n"); var local_finder = new Usm.ResourceFinder(); var resolver = new Usm.Resolver(local_finder); 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"); } // Cached packages can satisfy dependencies (and act as install targets // a repository no longer lists) resolver.load_cache(paths); var roots = new Vector(); for(int i = 2; i < args.length; i++) { var target = resolver.find_package(args[i]); if(target == null) { printerr(@"No package named \"$(args[i])\" found in any repository or the cache\n"); return 254; } roots.add(target); } // Resolve the full closure first: local → system packages → USM // repositories/cache, with candidate-group selection var spm = new Usm.SystemPackageManager(state.config); Usm.ResolutionResult resolution; try { resolution = resolver.resolve(roots, spm); } catch(Usm.ResolverError e) { printerr("%s\n".printf(e.message)); return 240; } // Download every repository-backed package in install order; supplied // cache packages are used in place and need no download, so they only // need collecting into the transaction set from their cache directories var cached_packages = new HashSet(); foreach(var package in resolution.install_order) { if(package.repository == null) { if(package.package_path != null) { cached_packages.add(new Usm.CachedPackage(Path.get_dirname((!)package.package_path))); } continue; } var client = package.repository.get_client(state.config); var path = state.generate_cache_path(package.manifest); var cache_dir = File.new_for_path(path); if(!cache_dir.query_exists()) { cache_dir.make_directory(); } var package_path = Path.build_filename(path, "package.usmc"); client.download_package(package_path, package.repository_entry, (f, c, t) => printerr(@"Downloading $f $c/$t bytes\r")); client.verify_package(package_path, package.repository_entry, (f, c, t) => printerr(@"Verifying $f $c/$t bytes\r")); cached_packages.add(new Usm.CachedPackage(path)); printerr("\n"); } // Chosen system packages install first, as one transaction if(resolution.system_packages.any()) { if(!install_system_packages(spm, resolution.system_packages)) { return 239; } } var install_order = new Vector(); foreach(var package in resolution.install_order) { install_order.add(package.manifest.name); } var transaction = new Usm.Transaction() { paths = paths, resource_finder = new Usm.ResourceFinder(paths), to_remove = new HashSet(), to_install = cached_packages, install_order = install_order, state = state }; printerr("\nRunning transaction...\n"); transaction.progress_updated.connect(transaction.print_progress); transaction.run(); // todo cleanup } catch(Error e) { printerr(@"Error: $(e.message)\n"); return 238; } return 0; } /** * Installs the resolution's chosen system packages as one transaction, * surfacing progress through the manager's {@link Usm.InstallProgressDelegate} * events; returns false (after printing why) when the transaction failed. */ private bool install_system_packages(Usm.SystemPackageManager spm, Vector packages) { printerr("Installing system packages...\n"); var names = new Vector(); foreach(var package in packages) { names.add(package.name); } int installed = 0; int total = 0; string failure = ""; var loop = new MainLoop(); spm.install.begin(names, event => { switch(event.event_type) { case Usm.SystemInstallEventType.BEGIN: total = event.total; break; case Usm.SystemInstallEventType.PACKAGE: if(event.name != null) { printerr(@"\r installing $(event.name) ($((int)(event.progress * 100))%)"); } break; case Usm.SystemInstallEventType.PACKAGE_COMPLETE: installed++; if(event.name != null) { printerr(@"\r [$installed/$total] installed system package $(event.name) \n"); } break; case Usm.SystemInstallEventType.COMPLETE: break; case Usm.SystemInstallEventType.ERROR: failure = event.message ?? "unknown error"; break; } }, (obj, res) => { try { if(!spm.install.end(res)) { failure = failure.length > 0 ? failure : "the system package manager reported a failure"; } } catch(Error e) { failure = e.message; } loop.quit(); }); loop.run(); if(failure.length > 0) { printerr(@"System package installation failed: $failure\n"); return false; } printerr(@"Installed $installed system package(s).\n"); return true; } private int install_usage() { printerr("USAGE:\n\tusm install \n"); return 255; }