| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- 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<Usm.AbstractPackage>();
- 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<Usm.CachedPackage>();
- 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<string>();
- 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<Usm.CachedPackage>(),
- 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<Usm.SystemPackageCandidate> packages) {
- printerr("Installing system packages...\n");
- var names = new Vector<string>();
- 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 <packages>\n");
- return 255;
- }
|