|
@@ -2,13 +2,14 @@ using Invercargill;
|
|
|
using Invercargill.DataStructures;
|
|
using Invercargill.DataStructures;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * `usm update [-y|--yes] [<package>]` — bring installed packages up to
|
|
|
|
|
|
|
+ * `usm update [-y|--yes] [<packages>]` — bring installed packages up to
|
|
|
* the newest version their repositories offer.
|
|
* the newest version their repositories offer.
|
|
|
*
|
|
*
|
|
|
- * Without a package name every installed package with a newer repository
|
|
|
|
|
- * version becomes a resolution root — one resolution, one
|
|
|
|
|
- * {@link Usm.TransactionSummary}, one confirm. With a package name only
|
|
|
|
|
- * that package updates (an already-current package reports "up to date").
|
|
|
|
|
|
|
+ * Without package names every installed package with a newer repository
|
|
|
|
|
+ * version becomes a resolution root; with names exactly those packages
|
|
|
|
|
+ * do (already-current names are skipped with a note). Either way there
|
|
|
|
|
+ * is one resolution, one {@link Usm.TransactionSummary}, one confirm —
|
|
|
|
|
+ * and the downloads happen only once the plan is accepted.
|
|
|
*
|
|
*
|
|
|
* Dependencies already installed at the resolved version are left alone;
|
|
* Dependencies already installed at the resolved version are left alone;
|
|
|
* an installed package moving to a different version is removed
|
|
* an installed package moving to a different version is removed
|
|
@@ -19,7 +20,7 @@ using Invercargill.DataStructures;
|
|
|
private int update_main(string[] args) {
|
|
private int update_main(string[] args) {
|
|
|
|
|
|
|
|
var assume_yes = false;
|
|
var assume_yes = false;
|
|
|
- string? package_name = null;
|
|
|
|
|
|
|
+ var package_names = new Vector<string>();
|
|
|
for(int i = 2; i < args.length; i++) {
|
|
for(int i = 2; i < args.length; i++) {
|
|
|
var argument = args[i];
|
|
var argument = args[i];
|
|
|
if(argument == "-y" || argument == "--yes") {
|
|
if(argument == "-y" || argument == "--yes") {
|
|
@@ -29,11 +30,8 @@ private int update_main(string[] args) {
|
|
|
printerr(@"Unknown option \"$argument\"\n");
|
|
printerr(@"Unknown option \"$argument\"\n");
|
|
|
return update_usage();
|
|
return update_usage();
|
|
|
}
|
|
}
|
|
|
- else if(package_name != null) {
|
|
|
|
|
- return update_usage();
|
|
|
|
|
- }
|
|
|
|
|
else {
|
|
else {
|
|
|
- package_name = argument;
|
|
|
|
|
|
|
+ package_names.add(argument);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -75,24 +73,29 @@ private int update_main(string[] args) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
var roots = new Vector<Usm.AbstractPackage>();
|
|
var roots = new Vector<Usm.AbstractPackage>();
|
|
|
- if(package_name != null) {
|
|
|
|
|
- Usm.CachedPackage installed;
|
|
|
|
|
- if(!installed_by_name.try_get(package_name, out installed)) {
|
|
|
|
|
- printerr(@"No installed package named \"$package_name\"\n");
|
|
|
|
|
- return 254;
|
|
|
|
|
- }
|
|
|
|
|
- var target = resolver.find_package(package_name);
|
|
|
|
|
- if(target == null) {
|
|
|
|
|
- printerr(@"No package named \"$package_name\" found in any repository or the cache\n");
|
|
|
|
|
- return 254;
|
|
|
|
|
|
|
+ if(package_names.length > 0) {
|
|
|
|
|
+ foreach(var package_name in package_names) {
|
|
|
|
|
+ Usm.CachedPackage installed;
|
|
|
|
|
+ if(!installed_by_name.try_get(package_name, out installed)) {
|
|
|
|
|
+ printerr(@"No installed package named \"$package_name\"\n");
|
|
|
|
|
+ return 254;
|
|
|
|
|
+ }
|
|
|
|
|
+ var target = resolver.find_package(package_name);
|
|
|
|
|
+ if(target == null) {
|
|
|
|
|
+ printerr(@"No package named \"$package_name\" found in any repository or the cache\n");
|
|
|
|
|
+ return 254;
|
|
|
|
|
+ }
|
|
|
|
|
+ Usm.Version installed_version;
|
|
|
|
|
+ installed_versions.try_get(package_name, out installed_version);
|
|
|
|
|
+ if(!target.manifest.version.greater_than(installed_version)) {
|
|
|
|
|
+ print(@"\"$package_name\" is already up to date.\n");
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ roots.add(target);
|
|
|
}
|
|
}
|
|
|
- Usm.Version installed_version;
|
|
|
|
|
- installed_versions.try_get(package_name, out installed_version);
|
|
|
|
|
- if(!target.manifest.version.greater_than(installed_version)) {
|
|
|
|
|
- print(@"\"$package_name\" is already up to date.\n");
|
|
|
|
|
|
|
+ if(roots.length == 0) {
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
- roots.add(target);
|
|
|
|
|
}
|
|
}
|
|
|
else {
|
|
else {
|
|
|
foreach(var pair in installed_by_name) {
|
|
foreach(var pair in installed_by_name) {
|
|
@@ -117,15 +120,26 @@ private int update_main(string[] args) {
|
|
|
return 240;
|
|
return 240;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Download and collect every changed package; a dependency already
|
|
|
|
|
- // installed at the resolved version stays as-is, so an update plan
|
|
|
|
|
- // names only what actually moves
|
|
|
|
|
- var cached_packages = new HashSet<Usm.CachedPackage>();
|
|
|
|
|
|
|
+ // Build the transaction set WITHOUT downloading: dependencies
|
|
|
|
|
+ // already installed at the resolved version stay as-is (so an
|
|
|
|
|
+ // update plan names only what actually moves), and repository
|
|
|
|
|
+ // packages join as their cache directories carrying the listing
|
|
|
|
|
+ // manifest — the plan is confirmed before a single byte moves
|
|
|
|
|
+ var current_names = new HashSet<string>();
|
|
|
foreach(var package in resolution.install_order) {
|
|
foreach(var package in resolution.install_order) {
|
|
|
Usm.Version installed_version;
|
|
Usm.Version installed_version;
|
|
|
- var already_current = installed_versions.try_get(package.manifest.name, out installed_version)
|
|
|
|
|
- && installed_version.compare(package.manifest.version) == 0;
|
|
|
|
|
- if(already_current) {
|
|
|
|
|
|
|
+ if(installed_versions.try_get(package.manifest.name, out installed_version)
|
|
|
|
|
+ && installed_version.compare(package.manifest.version) == 0) {
|
|
|
|
|
+ current_names.add(package.manifest.name);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var cached_packages = new HashSet<Usm.CachedPackage>();
|
|
|
|
|
+ uint download_count = 0;
|
|
|
|
|
+ int64 download_bytes = 0;
|
|
|
|
|
+ var download_sizes_known = true;
|
|
|
|
|
+ foreach(var package in resolution.install_order) {
|
|
|
|
|
+ if(current_names.contains(package.manifest.name)) {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
if(package.repository == null) {
|
|
if(package.repository == null) {
|
|
@@ -134,17 +148,21 @@ private int update_main(string[] args) {
|
|
|
}
|
|
}
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
- var client = package.repository.get_client(state.config);
|
|
|
|
|
var path = state.generate_cache_path(package.manifest);
|
|
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();
|
|
|
|
|
|
|
+ cached_packages.add(new Usm.CachedPackage(path) {
|
|
|
|
|
+ known_manifest = package.manifest
|
|
|
|
|
+ });
|
|
|
|
|
+ if(File.new_for_path(Path.build_filename(path, "package.usmc")).query_exists()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ download_count++;
|
|
|
|
|
+ var size = install_package_download_size(package.repository, package.repository_entry);
|
|
|
|
|
+ if(size == null) {
|
|
|
|
|
+ download_sizes_known = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ download_bytes += size;
|
|
|
}
|
|
}
|
|
|
- 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");
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// The installed versions being replaced by a different version
|
|
// The installed versions being replaced by a different version
|
|
@@ -195,13 +213,18 @@ private int update_main(string[] args) {
|
|
|
var summary = new Usm.TransactionSummary() {
|
|
var summary = new Usm.TransactionSummary() {
|
|
|
to_install = cached_packages.to_vector(),
|
|
to_install = cached_packages.to_vector(),
|
|
|
to_remove = to_remove.to_vector(),
|
|
to_remove = to_remove.to_vector(),
|
|
|
- to_rebuild = transaction.rebuilds
|
|
|
|
|
|
|
+ to_rebuild = transaction.rebuilds,
|
|
|
|
|
+ download_count = download_count,
|
|
|
|
|
+ download_bytes = download_sizes_known ? download_bytes : -1
|
|
|
};
|
|
};
|
|
|
if(!Usm.Cli.confirm_transaction(summary, assume_yes)) {
|
|
if(!Usm.Cli.confirm_transaction(summary, assume_yes)) {
|
|
|
print("Aborted.\n");
|
|
print("Aborted.\n");
|
|
|
return 1;
|
|
return 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // Only now that the plan is confirmed do the packages transfer
|
|
|
|
|
+ install_download_packages(state, resolution, current_names);
|
|
|
|
|
+
|
|
|
if(resolution.system_packages.any()) {
|
|
if(resolution.system_packages.any()) {
|
|
|
if(!install_system_packages(spm, resolution.system_packages)) {
|
|
if(!install_system_packages(spm, resolution.system_packages)) {
|
|
|
return 239;
|
|
return 239;
|
|
@@ -221,6 +244,6 @@ private int update_main(string[] args) {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private int update_usage() {
|
|
private int update_usage() {
|
|
|
- printerr("USAGE:\n\tusm update [-y|--yes] [<package>]\n");
|
|
|
|
|
|
|
+ printerr("USAGE:\n\tusm update [-y|--yes] [<packages>]\n");
|
|
|
return 255;
|
|
return 255;
|
|
|
}
|
|
}
|