diff --git a/azure-pipelines/e2e-specs/autocomplete-posh-vcpkg.Tests.ps1 b/azure-pipelines/e2e-specs/autocomplete-posh-vcpkg.Tests.ps1 index d236274704..5d9aebe4e4 100644 --- a/azure-pipelines/e2e-specs/autocomplete-posh-vcpkg.Tests.ps1 +++ b/azure-pipelines/e2e-specs/autocomplete-posh-vcpkg.Tests.ps1 @@ -39,7 +39,7 @@ BeforeAll { '--clean-downloads-after-build', '--clean-packages-after-build', '--dry-run', '--editable' '--enforce-port-checks', '--head', '--keep-going', '--no-downloads', '--no-print-usage' '--only-binarycaching', '--only-downloads', '--recurse', '--x-feature', '--x-no-default-features' - '--x-prohibit-backcompat-features', '--x-write-nuget-packages-config', '--x-xunit' + '--x-prohibit-backcompat-features', '--x-write-nuget-packages-config', '--x-xunit', '--skip-install-if-cached' ) remove = @( '--dry-run', '--outdated', '--purge', '--recurse' diff --git a/include/vcpkg/base/contractual-constants.h b/include/vcpkg/base/contractual-constants.h index f5d6ad3870..8d40675b46 100644 --- a/include/vcpkg/base/contractual-constants.h +++ b/include/vcpkg/base/contractual-constants.h @@ -277,6 +277,7 @@ namespace vcpkg inline constexpr StringLiteral SwitchSingleFile = "single-file"; inline constexpr StringLiteral SwitchSkipFailures = "skip-failures"; inline constexpr StringLiteral SwitchSkipFormattingCheck = "skip-formatting-check"; + inline constexpr StringLiteral SwitchSkipInstallIfCached = "skip-install-if-cached"; inline constexpr StringLiteral SwitchSkipSha512 = "skip-sha512"; inline constexpr StringLiteral SwitchSkipVersionFormatCheck = "skip-version-format-check"; inline constexpr StringLiteral SwitchSort = "sort"; diff --git a/include/vcpkg/base/message-data.inc.h b/include/vcpkg/base/message-data.inc.h index f947f365ea..d17c903cae 100644 --- a/include/vcpkg/base/message-data.inc.h +++ b/include/vcpkg/base/message-data.inc.h @@ -1745,6 +1745,10 @@ DECLARE_MESSAGE(HelpTxtOptManifestNoDefault, "Does not install the default features from the top-level manifest (manifest mode)") DECLARE_MESSAGE(HelpTxtOptNoDownloads, (), "", "Does not download new sources") DECLARE_MESSAGE(HelpTxtOptNoUsage, (), "", "Does not print CMake usage information after install") +DECLARE_MESSAGE(HelpTxtOptSkipInstallIfCached, + (), + "", + "Skips the installation of packages if every package is already cached") DECLARE_MESSAGE(HelpTxtOptOnlyBinCache, (), "", "Fails if cached binaries are not available") DECLARE_MESSAGE(HelpTxtOptOnlyDownloads, (), "", "Makes best-effort attempt to download sources without building") DECLARE_MESSAGE(HelpTxtOptRecurse, (), "", "Allows removal of packages as part of installation") @@ -2342,6 +2346,7 @@ DECLARE_MESSAGE(PackageManipulationHeader, (), "", "Package Manipulation") DECLARE_MESSAGE(PackageInfoHelp, (), "", "Display detailed information on packages") DECLARE_MESSAGE(PackageInstallationHeader, (), "", "Package Installation") DECLARE_MESSAGE(PackageRootDir, (), "", "Packages directory (experimental)") +DECLARE_MESSAGE(PackagesCached, (), "", "All packages already exist in the binary cache. Installation skipped.") DECLARE_MESSAGE(PackagesToInstall, (), "", "The following packages will be built and installed:") DECLARE_MESSAGE(PackagesToModify, (), "", "Additional packages (*) will be modified to complete this operation.") DECLARE_MESSAGE(PackagesToRebuild, (), "", "The following packages will be rebuilt:") diff --git a/include/vcpkg/commands.set-installed.h b/include/vcpkg/commands.set-installed.h index a73dbcfffd..cfcbd0debc 100644 --- a/include/vcpkg/commands.set-installed.h +++ b/include/vcpkg/commands.set-installed.h @@ -44,7 +44,8 @@ namespace vcpkg DryRun dry_run, PrintUsage print_usage, const Optional& maybe_pkgconfig, - bool include_manifest_in_github_issue); + bool include_manifest_in_github_issue, + bool skip_install_if_cached); void command_set_installed_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet, diff --git a/locales/messages.json b/locales/messages.json index d69bcc531e..8aee0b1abc 100644 --- a/locales/messages.json +++ b/locales/messages.json @@ -963,6 +963,7 @@ "HelpTxtOptOnlyBinCache": "Fails if cached binaries are not available", "HelpTxtOptOnlyDownloads": "Makes best-effort attempt to download sources without building", "HelpTxtOptRecurse": "Allows removal of packages as part of installation", + "HelpTxtOptSkipInstallIfCached": "Skips the installation of packages if every package is already cached", "HelpTxtOptUseHeadVersion": "Installs the libraries on the command line using the latest upstream sources (classic mode)", "HelpTxtOptWritePkgConfig": "Writes a NuGet packages.config-formatted file for use with external binary caching. See `vcpkg help binarycaching` for more information", "_HelpTxtOptWritePkgConfig.comment": "'vcpkg help binarycaching' is a command line and should not be localized.", @@ -1289,6 +1290,7 @@ "PackageLicenseWarning": "Installed contents are licensed to you by owners. Microsoft is not responsible for, nor does it grant any licenses to, third-party packages.", "PackageManipulationHeader": "Package Manipulation", "PackageRootDir": "Packages directory (experimental)", + "PackagesCached": "All packages already exist in the binary cache. Installation skipped.", "PackagesToInstall": "The following packages will be built and installed:", "PackagesToModify": "Additional packages (*) will be modified to complete this operation.", "PackagesToRebuild": "The following packages will be rebuilt:", diff --git a/src/vcpkg/commands.install.cpp b/src/vcpkg/commands.install.cpp index e456234283..e2309df2c8 100644 --- a/src/vcpkg/commands.install.cpp +++ b/src/vcpkg/commands.install.cpp @@ -869,6 +869,7 @@ namespace vcpkg {SwitchXProhibitBackcompatFeatures, {}}, {SwitchAllowUnsupported, msgHelpTxtOptAllowUnsupportedPort}, {SwitchNoPrintUsage, msgHelpTxtOptNoUsage}, + {SwitchSkipInstallIfCached, msgHelpTxtOptSkipInstallIfCached}, }; static constexpr CommandSetting INSTALL_SETTINGS[] = { @@ -1318,6 +1319,7 @@ namespace vcpkg ? UnsupportedPortAction::Warn : UnsupportedPortAction::Error; const bool print_cmake_usage = !Util::Sets::contains(options.switches, SwitchNoPrintUsage); + const bool skip_install_if_cached = Util::Sets::contains(options.switches, SwitchSkipInstallIfCached); get_global_metrics_collector().track_bool(BoolMetric::InstallManifestMode, manifest); @@ -1360,6 +1362,11 @@ namespace vcpkg msg::println_error(msgErrorInvalidClassicModeOption, msg::option = SwitchXNoDefaultFeatures); failure = true; } + if (skip_install_if_cached) + { + msg::println_error(msgErrorInvalidClassicModeOption, msg::option = SwitchSkipInstallIfCached); + failure = true; + } if (Util::Sets::contains(options.multisettings, SwitchXFeature)) { msg::println_error(msgErrorInvalidClassicModeOption, msg::option = SwitchXFeature); @@ -1453,7 +1460,8 @@ namespace vcpkg dry_run ? DryRun::Yes : DryRun::No, print_cmake_usage ? PrintUsage::Yes : PrintUsage::No, pkgsconfig, - true); + true, + skip_install_if_cached); } PathsPortFileProvider provider(*registry_set, make_overlay_provider(fs, paths.overlay_ports)); diff --git a/src/vcpkg/commands.set-installed.cpp b/src/vcpkg/commands.set-installed.cpp index aa83a75a07..b4ea6443cc 100644 --- a/src/vcpkg/commands.set-installed.cpp +++ b/src/vcpkg/commands.set-installed.cpp @@ -27,6 +27,7 @@ namespace {SwitchKeepGoing, msgHelpTxtOptKeepGoing}, {SwitchEnforcePortChecks, msgHelpTxtOptEnforcePortChecks}, {SwitchAllowUnsupported, msgHelpTxtOptAllowUnsupportedPort}, + {SwitchSkipInstallIfCached, msgHelpTxtOptSkipInstallIfCached}, }; constexpr CommandSetting INSTALL_SETTINGS[] = { @@ -190,7 +191,8 @@ namespace vcpkg DryRun dry_run, PrintUsage print_usage, const Optional& maybe_pkgconfig, - bool include_manifest_in_github_issue) + bool include_manifest_in_github_issue, + bool skip_install_if_cached) { auto& fs = paths.get_filesystem(); @@ -254,7 +256,6 @@ namespace vcpkg paths.flush_lockfile(); track_install_plan(action_plan); - install_preclear_plan_packages(paths, action_plan); BinaryCache binary_cache(fs); if (build_options.only_downloads == OnlyDownloads::No) @@ -265,7 +266,21 @@ namespace vcpkg } } + if (skip_install_if_cached) + { + auto install_actions = + Util::fmap(action_plan.install_actions, [](const InstallPlanAction& action) { return &action; }); + auto availability = binary_cache.precheck(console_diagnostic_context, fs, install_actions); + if (Util::all_of(availability, + [](CacheAvailability state) { return state == CacheAvailability::available; })) + { + msg::println(msgPackagesCached); + Checks::exit_success(VCPKG_LINE_INFO); + } + } + install_preclear_plan_packages(paths, action_plan); binary_cache.fetch(console_diagnostic_context, fs, action_plan.install_actions); + const auto summary = install_execute_plan(args, paths, host_triplet, @@ -343,6 +358,7 @@ namespace vcpkg const auto prohibit_backcompat_features = Util::Sets::contains(options.switches, SwitchEnforcePortChecks) ? BackcompatFeatures::Prohibit : BackcompatFeatures::Allow; + const bool skip_install_if_cached = Util::Sets::contains(options.switches, SwitchSkipInstallIfCached); const BuildPackageOptions build_options{ BuildMissing::Yes, @@ -394,6 +410,7 @@ namespace vcpkg Util::Sets::contains(options.switches, SwitchDryRun) ? DryRun::Yes : DryRun::No, Util::Sets::contains(options.switches, SwitchNoPrintUsage) ? PrintUsage::No : PrintUsage::Yes, pkgsconfig, - false); + false, + skip_install_if_cached); } } // namespace vcpkg