Install.vala 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using Invercargill;
  2. using Invercargill.DataStructures;
  3. private int install_main(string[] args) {
  4. if(args.length < 3) {
  5. return install_usage();
  6. }
  7. Usm.SystemState state = null;
  8. try {
  9. state = new Usm.SystemState(paths);
  10. }
  11. catch(Error e) {
  12. printerr(@"This system is not managed by usm: $(e.message)\n");
  13. return 245;
  14. }
  15. try {
  16. printerr("Refreshing repositories...\n");
  17. var local_finder = new Usm.ResourceFinder();
  18. var resolver = new Usm.Resolver(local_finder);
  19. var repos = state.get_repositories();
  20. foreach (var repo in repos) {
  21. state.refresh_list(repo, (f, c, t) => printerr(@"Refreshing list for $(repo.name): downloading $f $c/$t bytes\r"));
  22. var listing = state.get_latest_list(repo);
  23. if(listing != null) {
  24. resolver.load_listing(repo, listing);
  25. }
  26. printerr("\n");
  27. }
  28. // Cached packages can satisfy dependencies (and act as install targets
  29. // a repository no longer lists)
  30. resolver.load_cache(paths);
  31. var roots = new Vector<Usm.AbstractPackage>();
  32. for(int i = 2; i < args.length; i++) {
  33. var target = resolver.find_package(args[i]);
  34. if(target == null) {
  35. printerr(@"No package named \"$(args[i])\" found in any repository or the cache\n");
  36. return 254;
  37. }
  38. roots.add(target);
  39. }
  40. // Resolve the full closure first: local → system packages → USM
  41. // repositories/cache, with candidate-group selection
  42. var spm = new Usm.SystemPackageManager(state.config);
  43. Usm.ResolutionResult resolution;
  44. try {
  45. resolution = resolver.resolve(roots, spm);
  46. }
  47. catch(Usm.ResolverError e) {
  48. printerr("%s\n".printf(e.message));
  49. return 240;
  50. }
  51. // Download every repository-backed package in install order; supplied
  52. // cache packages are used in place and need no download, so they only
  53. // need collecting into the transaction set from their cache directories
  54. var cached_packages = new HashSet<Usm.CachedPackage>();
  55. foreach(var package in resolution.install_order) {
  56. if(package.repository == null) {
  57. if(package.package_path != null) {
  58. cached_packages.add(new Usm.CachedPackage(Path.get_dirname((!)package.package_path)));
  59. }
  60. continue;
  61. }
  62. var client = package.repository.get_client(state.config);
  63. var path = state.generate_cache_path(package.manifest);
  64. var cache_dir = File.new_for_path(path);
  65. if(!cache_dir.query_exists()) {
  66. cache_dir.make_directory();
  67. }
  68. var package_path = Path.build_filename(path, "package.usmc");
  69. client.download_package(package_path, package.repository_entry, (f, c, t) => printerr(@"Downloading $f $c/$t bytes\r"));
  70. client.verify_package(package_path, package.repository_entry, (f, c, t) => printerr(@"Verifying $f $c/$t bytes\r"));
  71. cached_packages.add(new Usm.CachedPackage(path));
  72. printerr("\n");
  73. }
  74. // Chosen system packages install first, as one transaction
  75. if(resolution.system_packages.any()) {
  76. if(!install_system_packages(spm, resolution.system_packages)) {
  77. return 239;
  78. }
  79. }
  80. var install_order = new Vector<string>();
  81. foreach(var package in resolution.install_order) {
  82. install_order.add(package.manifest.name);
  83. }
  84. var transaction = new Usm.Transaction() {
  85. paths = paths,
  86. resource_finder = new Usm.ResourceFinder(paths),
  87. to_remove = new HashSet<Usm.CachedPackage>(),
  88. to_install = cached_packages,
  89. install_order = install_order,
  90. state = state
  91. };
  92. printerr("\nRunning transaction...\n");
  93. transaction.progress_updated.connect(transaction.print_progress);
  94. transaction.run();
  95. // todo cleanup
  96. }
  97. catch(Error e) {
  98. printerr(@"Error: $(e.message)\n");
  99. return 238;
  100. }
  101. return 0;
  102. }
  103. /**
  104. * Installs the resolution's chosen system packages as one transaction,
  105. * surfacing progress through the manager's {@link Usm.InstallProgressDelegate}
  106. * events; returns false (after printing why) when the transaction failed.
  107. */
  108. private bool install_system_packages(Usm.SystemPackageManager spm, Vector<Usm.SystemPackageCandidate> packages) {
  109. printerr("Installing system packages...\n");
  110. var names = new Vector<string>();
  111. foreach(var package in packages) {
  112. names.add(package.name);
  113. }
  114. int installed = 0;
  115. int total = 0;
  116. string failure = "";
  117. var loop = new MainLoop();
  118. spm.install.begin(names, event => {
  119. switch(event.event_type) {
  120. case Usm.SystemInstallEventType.BEGIN:
  121. total = event.total;
  122. break;
  123. case Usm.SystemInstallEventType.PACKAGE:
  124. if(event.name != null) {
  125. printerr(@"\r installing $(event.name) ($((int)(event.progress * 100))%)");
  126. }
  127. break;
  128. case Usm.SystemInstallEventType.PACKAGE_COMPLETE:
  129. installed++;
  130. if(event.name != null) {
  131. printerr(@"\r [$installed/$total] installed system package $(event.name) \n");
  132. }
  133. break;
  134. case Usm.SystemInstallEventType.COMPLETE:
  135. break;
  136. case Usm.SystemInstallEventType.ERROR:
  137. failure = event.message ?? "unknown error";
  138. break;
  139. }
  140. }, (obj, res) => {
  141. try {
  142. if(!spm.install.end(res)) {
  143. failure = failure.length > 0 ? failure : "the system package manager reported a failure";
  144. }
  145. }
  146. catch(Error e) {
  147. failure = e.message;
  148. }
  149. loop.quit();
  150. });
  151. loop.run();
  152. if(failure.length > 0) {
  153. printerr(@"System package installation failed: $failure\n");
  154. return false;
  155. }
  156. printerr(@"Installed $installed system package(s).\n");
  157. return true;
  158. }
  159. private int install_usage() {
  160. printerr("USAGE:\n\tusm install <packages>\n");
  161. return 255;
  162. }