Skip to content

Commit

Permalink
Detect changes in the 'ce' version and rebootstrap it if it doesn't m…
Browse files Browse the repository at this point in the history
…atch what vcpkg expects.

Note that the "VCPKG_BASE_VERSION" unset path will be substantially modified after microsoft#428 , this change always rebootstraps CE. (I can see an argument for it to never rebootstrap CE?)

Resolves https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems/edit/1494969
  • Loading branch information
BillyONeal committed Mar 17, 2022
1 parent 91494e3 commit fea0d39
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 35 deletions.
8 changes: 8 additions & 0 deletions include/vcpkg/base/checks.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ namespace vcpkg::Checks
msg_exit_with_message(line_info, msg::format(m, args...));
}

template<class Message, class... Args>
[[noreturn]] typename Message::is_message_type msg_exit_with_error(const LineInfo& line_info,
Message m,
const Args&... args)
{
msg_exit_with_message(line_info, msg::format(msg::msgErrorMessage).append(msg::format(m, args...)));
}

template<class Arg1, class... Args>
VCPKG_SAL_ANNOTATION(_Post_satisfies_(_Old_(expression)))
void check_exit(const LineInfo& line_info,
Expand Down
4 changes: 4 additions & 0 deletions locales/messages.en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
"ChecksUnreachableCode": "unreachable code was reached",
"ChecksUpdateVcpkg": "updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.",
"CouldNotDeduceNugetIdAndVersion": "Could not deduce nuget id and version from filename: {path}",
"DownloadingVcpkgCeBundle": "Downloading vcpkg-ce bundle {version}...",
"DownloadingVcpkgCeBundleLatest": "Downloading latest vcpkg-ce bundle...",
"EmptyLicenseExpression": "SPDX license expression was empty.",
"ErrorIndividualPackagesUnsupported": "Error: In manifest mode, `vcpkg install` does not support individual package arguments.\nTo install additional packages, edit vcpkg.json and then run `vcpkg install` without any package arguments.",
"ErrorInvalidClassicModeOption": "Error: The option --{option} is not supported in classic mode and no manifest was found.",
Expand All @@ -40,6 +42,7 @@
"ErrorRequirePackagesList": "Error: `vcpkg install` requires a list of packages to install in classic mode.",
"ErrorRequirePackagesToInstall": "Error: No packages were listed for installation and no manifest was found.",
"ErrorVcvarsUnsupported": "Error: in triplet {triplet}: Use of Visual Studio's Developer Prompt is unsupported on non-Windows hosts.\nDefine 'VCPKG_CMAKE_SYSTEM_NAME' or 'VCPKG_CHAINLOAD_TOOLCHAIN_FILE' in the triplet file.",
"FailedToProvisionCe": "Failed to provision vcpkg-ce.",
"ForceSystemBinariesOnWeirdPlatforms": "Environment variable VCPKG_FORCE_SYSTEM_BINARIES must be set on arm, s390x, and ppc64le platforms.",
"FormattedParseMessageExpression": " on expression: {value}",
"FormattedParseMessageLocation": "{path}:{row}:{column}: ",
Expand Down Expand Up @@ -88,6 +91,7 @@
"VSExaminedInstances": "The following Visual Studio instances were considered:",
"VSExaminedPaths": "The following paths were examined for Visual Studio instances:",
"VSNoInstances": "Could not locate a complete Visual Studio instance",
"VcpkgCeIsExperimental": "vcpkg-ce ('configure environment') is experimental and may change at any time.",
"VcpkgDisallowedClassicMode": "Error: Could not locate a manifest (vcpkg.json) above the current working directory.\nThis vcpkg distribution does not have a classic mode instance.",
"VcpkgHasCrashed": "vcpkg.exe has crashed.\nPlease send an email to:\n {email}\ncontaining a brief summary of what you were trying to do and the following data blob:",
"VcpkgHasCrashedArgument": "{value}|",
Expand Down
6 changes: 6 additions & 0 deletions locales/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
"ChecksUpdateVcpkg": "updating vcpkg by rerunning bootstrap-vcpkg may resolve this failure.",
"CouldNotDeduceNugetIdAndVersion": "Could not deduce nuget id and version from filename: {path}",
"_CouldNotDeduceNugetIdAndVersion.comment": "example of {path} is '/foo/bar'.\n",
"DownloadingVcpkgCeBundle": "Downloading vcpkg-ce bundle {version}...",
"_DownloadingVcpkgCeBundle.comment": "example of {version} is '1.3.8'.\n",
"DownloadingVcpkgCeBundleLatest": "Downloading latest vcpkg-ce bundle...",
"_DownloadingVcpkgCeBundleLatest.comment": "This message is normally displayed only in development.\n",
"EmptyLicenseExpression": "SPDX license expression was empty.",
"ErrorIndividualPackagesUnsupported": "Error: In manifest mode, `vcpkg install` does not support individual package arguments.\nTo install additional packages, edit vcpkg.json and then run `vcpkg install` without any package arguments.",
"ErrorInvalidClassicModeOption": "Error: The option --{option} is not supported in classic mode and no manifest was found.",
Expand All @@ -71,6 +75,7 @@
"ErrorRequirePackagesToInstall": "Error: No packages were listed for installation and no manifest was found.",
"ErrorVcvarsUnsupported": "Error: in triplet {triplet}: Use of Visual Studio's Developer Prompt is unsupported on non-Windows hosts.\nDefine 'VCPKG_CMAKE_SYSTEM_NAME' or 'VCPKG_CHAINLOAD_TOOLCHAIN_FILE' in the triplet file.",
"_ErrorVcvarsUnsupported.comment": "example of {triplet} is 'x64-windows'.\n",
"FailedToProvisionCe": "Failed to provision vcpkg-ce.",
"ForceSystemBinariesOnWeirdPlatforms": "Environment variable VCPKG_FORCE_SYSTEM_BINARIES must be set on arm, s390x, and ppc64le platforms.",
"FormattedParseMessageExpression": " on expression: {value}",
"_FormattedParseMessageExpression.comment": "Example of {value} is 'x64 & windows'\n",
Expand Down Expand Up @@ -147,6 +152,7 @@
"VSExaminedInstances": "The following Visual Studio instances were considered:",
"VSExaminedPaths": "The following paths were examined for Visual Studio instances:",
"VSNoInstances": "Could not locate a complete Visual Studio instance",
"VcpkgCeIsExperimental": "vcpkg-ce ('configure environment') is experimental and may change at any time.",
"VcpkgDisallowedClassicMode": "Error: Could not locate a manifest (vcpkg.json) above the current working directory.\nThis vcpkg distribution does not have a classic mode instance.",
"VcpkgHasCrashed": "vcpkg.exe has crashed.\nPlease send an email to:\n {email}\ncontaining a brief summary of what you were trying to do and the following data blob:",
"_VcpkgHasCrashed.comment": "example of {email} is '[email protected]'.\n",
Expand Down
120 changes: 85 additions & 35 deletions src/vcpkg/configure-environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,107 @@
#include <vcpkg/vcpkgcmdarguments.h>
#include <vcpkg/vcpkgpaths.h>

#if defined(VCPKG_CE_SHA)
#define VCPKG_CE_SHA_AS_STRING MACRO_TO_STRING(VCPKG_CE_SHA)
#endif // ^^^ VCPKG_CE_SHA

namespace
{
using namespace vcpkg;
DECLARE_AND_REGISTER_MESSAGE(FailedToProvisionCe, (), "", "Failed to provision vcpkg-ce.");
DECLARE_AND_REGISTER_MESSAGE(VcpkgCeIsExperimental,
(),
"",
"vcpkg-ce ('configure environment') is experimental and may change at any time.");
DECLARE_AND_REGISTER_MESSAGE(DownloadingVcpkgCeBundle,
(msg::version),
"",
"Downloading vcpkg-ce bundle {version}...");
DECLARE_AND_REGISTER_MESSAGE(DownloadingVcpkgCeBundleLatest,
(),
"This message is normally displayed only in development.",
"Downloading latest vcpkg-ce bundle...");

void extract_ce_tarball(const VcpkgPaths& paths,
const Path& ce_tarball,
const Path& node_path,
const Path& node_modules)
{
auto& fs = paths.get_filesystem();
fs.remove_all(node_modules, VCPKG_LINE_INFO);
Path node_root = node_path.parent_path();
auto npm_path = node_root / "node_modules" / "npm" / "bin" / "npm-cli.js";
if (!fs.exists(npm_path, VCPKG_LINE_INFO))
{
npm_path = Path(node_root.parent_path()) / "lib" / "node_modules" / "npm" / "bin" / "npm-cli.js";
}

Command cmd_provision(node_path);
cmd_provision.string_arg(npm_path);
cmd_provision.string_arg("--force");
cmd_provision.string_arg("install");
cmd_provision.string_arg("--no-save");
cmd_provision.string_arg("--no-lockfile");
cmd_provision.string_arg("--scripts-prepend-node-path=true");
cmd_provision.string_arg("--silent");
cmd_provision.string_arg(ce_tarball);
auto env = get_modified_clean_environment({}, node_root);
const auto provision_status = cmd_execute(cmd_provision, WorkingDirectory{paths.root}, env);
fs.remove(ce_tarball, VCPKG_LINE_INFO);
if (provision_status != 0)
{
fs.remove_all(node_modules, VCPKG_LINE_INFO);
Checks::msg_exit_with_error(VCPKG_LINE_INFO, msgFailedToProvisionCe);
}
}
}

namespace vcpkg
{
int run_configure_environment_command(const VcpkgPaths& paths, View<std::string> args)
{
print2(Color::warning, "vcpkg-ce ('configure environment') is experimental and may change at any time.\n");
msg::println(Color::warning, msg::format(msg::msgWarningMessage).append(msg::format(msgVcpkgCeIsExperimental)));

auto& fs = paths.get_filesystem();
auto& download_manager = paths.get_download_manager();
auto node_path = paths.get_tool_exe(Tools::NODE);
Path node_root = node_path.parent_path();
auto node_modules = paths.root / "node_modules";
auto ce_path = node_modules / "vcpkg-ce";
if (!fs.is_directory(ce_path))
{
auto env = get_modified_clean_environment({}, node_root);
auto ce_sha_path = node_modules / "ce-sha.txt";

#if defined(VCPKG_CE_SHA)
print2("Downloading vcpkg-ce bundle " VCPKG_BASE_VERSION_AS_STRING "\n");
bool needs_provisioning = !fs.is_directory(ce_path);
if (!needs_provisioning)
{
auto installed_ce_sha = fs.read_contents(ce_sha_path, IgnoreErrors{});
if (installed_ce_sha != VCPKG_CE_SHA_AS_STRING)
{
fs.remove(ce_sha_path, VCPKG_LINE_INFO);
fs.remove_all(ce_path, VCPKG_LINE_INFO);
needs_provisioning = true;
}
}

if (needs_provisioning)
{
msg::println(msgDownloadingVcpkgCeBundle, msg::version = VCPKG_BASE_VERSION_AS_STRING);
const auto ce_uri =
"https://github.com/microsoft/vcpkg-tool/releases/download/" VCPKG_BASE_VERSION_AS_STRING
"/vcpkg-ce.tgz";
const auto ce_tarball = paths.downloads / "vcpkg-ce-" VCPKG_BASE_VERSION_AS_STRING ".tgz";
download_manager.download_file(fs, ce_uri, ce_tarball, std::string(MACRO_TO_STRING(VCPKG_CE_SHA)));
#else // ^^^ VCPKG_CE_BUNDLE_SHA / !VCPKG_CE_BUNDLE_SHA vvv
print2(Color::warning, "Downloading latest vcpkg-ce bundle\n");
const auto ce_uri = "https://github.com/microsoft/vcpkg-tool/releases/latest/download/vcpkg-ce.tgz";
const auto ce_tarball = paths.downloads / "vcpkg-ce-latest.tgz";
download_manager.download_file(fs, ce_uri, ce_tarball, nullopt);
#endif // ^^^ !VCPKG_CE_BUNDLE_SHA
auto npm_path = node_root / "node_modules" / "npm" / "bin" / "npm-cli.js";
if (!fs.exists(npm_path, VCPKG_LINE_INFO))
{
npm_path = Path(node_root.parent_path()) / "lib" / "node_modules" / "npm" / "bin" / "npm-cli.js";
}

Command cmd_provision(node_path);
cmd_provision.string_arg(npm_path);
cmd_provision.string_arg("--force");
cmd_provision.string_arg("install");
cmd_provision.string_arg("--no-save");
cmd_provision.string_arg("--no-lockfile");
cmd_provision.string_arg("--scripts-prepend-node-path=true");
cmd_provision.string_arg("--silent");
cmd_provision.string_arg(ce_tarball);
const auto provision_status = cmd_execute(cmd_provision, WorkingDirectory{paths.root}, env);
fs.remove(ce_tarball, VCPKG_LINE_INFO);
if (provision_status != 0)
{
fs.remove_all(node_modules, VCPKG_LINE_INFO);
Checks::exit_with_message(VCPKG_LINE_INFO, "Failed to provision vcpkg-ce.");
}
download_manager.download_file(fs, ce_uri, ce_tarball, VCPKG_CE_SHA_AS_STRING);
extract_ce_tarball(paths, ce_tarball, node_path, node_modules);
fs.write_contents(ce_sha_path, VCPKG_CE_SHA_AS_STRING, VCPKG_LINE_INFO);
}
#else // ^^^ VCPKG_CE_SHA / !VCPKG_CE_SHA vvv
fs.remove(ce_sha_path, VCPKG_LINE_INFO);
fs.remove_all(ce_path, VCPKG_LINE_INFO);
msg::println(Color::warning, msgDownloadingVcpkgCeBundleLatest);
const auto ce_uri = "https://github.com/microsoft/vcpkg-tool/releases/latest/download/vcpkg-ce.tgz";
const auto ce_tarball = paths.downloads / "vcpkg-ce-latest.tgz";
download_manager.download_file(fs, ce_uri, ce_tarball, nullopt);
extract_ce_tarball(paths, ce_tarball, node_path, node_modules);
#endif // ^^^ !VCPKG_CE_SHA

Command cmd_run(node_path);
cmd_run.string_arg("--harmony");
Expand Down

0 comments on commit fea0d39

Please sign in to comment.