aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authoreao197 <eao197@gmail.com>2018-05-30 19:25:16 +0300
committereao197 <eao197@gmail.com>2018-05-30 19:25:16 +0300
commit99eb78cf2dd8b000ac195dd9ebba4fb344dc5baa (patch)
tree18072db815a8f417c4d63a00ae95286642f0dff3 /toolsrc/src
parent34257a50ceda0bfa05e59b532f71223b70f39d52 (diff)
parent842252373992a9c7b74f041607b47754d61cc0c8 (diff)
downloadvcpkg-99eb78cf2dd8b000ac195dd9ebba4fb344dc5baa.tar.gz
vcpkg-99eb78cf2dd8b000ac195dd9ebba4fb344dc5baa.zip
Merge https://github.com/Microsoft/vcpkg
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/tests.paragraph.cpp9
-rw-r--r--toolsrc/src/tests.utils.cpp30
-rw-r--r--toolsrc/src/vcpkg.cpp4
-rw-r--r--toolsrc/src/vcpkg/base/checks.cpp2
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp7
-rw-r--r--toolsrc/src/vcpkg/base/strings.cpp18
-rw-r--r--toolsrc/src/vcpkg/base/system.cpp103
-rw-r--r--toolsrc/src/vcpkg/binaryparagraph.cpp2
-rw-r--r--toolsrc/src/vcpkg/build.cpp36
-rw-r--r--toolsrc/src/vcpkg/commands.cache.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp6
-rw-r--r--toolsrc/src/vcpkg/commands.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.edit.cpp3
-rw-r--r--toolsrc/src/vcpkg/commands.fetch.cpp539
-rw-r--r--toolsrc/src/vcpkg/commands.hash.cpp12
-rw-r--r--toolsrc/src/vcpkg/commands.integrate.cpp125
-rw-r--r--toolsrc/src/vcpkg/commands.list.cpp2
-rw-r--r--toolsrc/src/vcpkg/export.cpp4
-rw-r--r--toolsrc/src/vcpkg/install.cpp43
-rw-r--r--toolsrc/src/vcpkg/paragraphs.cpp4
-rw-r--r--toolsrc/src/vcpkg/userconfig.cpp11
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp11
22 files changed, 609 insertions, 366 deletions
diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp
index dca89bc59..9a56ad9ee 100644
--- a/toolsrc/src/tests.paragraph.cpp
+++ b/toolsrc/src/tests.paragraph.cpp
@@ -5,15 +5,6 @@
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
-namespace Microsoft::VisualStudio::CppUnitTestFramework
-{
- template<>
- inline std::wstring ToString<vcpkg::PackageSpecParseResult>(const vcpkg::PackageSpecParseResult& t)
- {
- return ToString(static_cast<uint32_t>(t));
- }
-}
-
namespace Strings = vcpkg::Strings;
namespace UnitTest1
diff --git a/toolsrc/src/tests.utils.cpp b/toolsrc/src/tests.utils.cpp
index a3d8ffc7d..ac391f559 100644
--- a/toolsrc/src/tests.utils.cpp
+++ b/toolsrc/src/tests.utils.cpp
@@ -5,36 +5,6 @@
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace vcpkg;
-namespace Microsoft::VisualStudio::CppUnitTestFramework
-{
- std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t)
- {
- switch (t)
- {
- case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED";
- case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL";
- case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED";
- case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN";
- default: return ToString(static_cast<int>(t));
- }
- }
-
- std::wstring ToString(const vcpkg::Dependencies::RequestType& t)
- {
- switch (t)
- {
- case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED";
- case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED";
- case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN";
- default: return ToString(static_cast<int>(t));
- }
- }
-
- std::wstring ToString(const vcpkg::PackageSpecParseResult& t) { return ToString(static_cast<uint32_t>(t)); }
-
- std::wstring ToString(const vcpkg::PackageSpec& t) { return ToString(t.to_string()); }
-}
-
std::unique_ptr<StatusParagraph> make_status_pgh(const char* name,
const char* depends,
const char* default_features,
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index 06c99e9a8..ac2eec876 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -70,7 +70,7 @@ static void inner(const VcpkgCmdArguments& args)
fs::path vcpkg_root_dir;
if (args.vcpkg_root_dir != nullptr)
{
- vcpkg_root_dir = fs::stdfs::absolute(Strings::to_utf16(*args.vcpkg_root_dir));
+ vcpkg_root_dir = fs::stdfs::absolute(fs::u8path(*args.vcpkg_root_dir));
}
else
{
@@ -94,6 +94,8 @@ static void inner(const VcpkgCmdArguments& args)
Checks::check_exit(VCPKG_LINE_INFO, !vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root.");
+ Debug::println("Using vcpkg-root: %s", vcpkg_root_dir.u8string());
+
auto default_vs_path = System::get_environment_variable("VCPKG_DEFAULT_VS_PATH").value_or("");
const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir, default_vs_path);
diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp
index d96cb98ff..2ac5f9a15 100644
--- a/toolsrc/src/vcpkg/base/checks.cpp
+++ b/toolsrc/src/vcpkg/base/checks.cpp
@@ -16,6 +16,8 @@ namespace vcpkg::Checks
const auto elapsed_us = GlobalState::timer.lock()->microseconds();
+ Debug::println("Exiting after %d us", static_cast<int>(elapsed_us));
+
auto metrics = Metrics::g_metrics.lock();
metrics->track_metric("elapsed_us", elapsed_us);
GlobalState::debugging = false;
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index 1723b467e..3d96e834b 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -55,17 +55,18 @@ namespace vcpkg::Files
virtual fs::path find_file_recursively_up(const fs::path& starting_dir,
const std::string& filename) const override
{
+ static const fs::path UNIX_ROOT = "/";
fs::path current_dir = starting_dir;
- for (; !current_dir.empty(); current_dir = current_dir.parent_path())
+ for (; !current_dir.empty() && current_dir != UNIX_ROOT; current_dir = current_dir.parent_path())
{
const fs::path candidate = current_dir / filename;
if (exists(candidate))
{
- break;
+ return current_dir;
}
}
- return current_dir;
+ return fs::path();
}
virtual std::vector<fs::path> get_files_recursive(const fs::path& dir) const override
diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp
index fbc33ca42..8d43e7af7 100644
--- a/toolsrc/src/vcpkg/base/strings.cpp
+++ b/toolsrc/src/vcpkg/base/strings.cpp
@@ -49,33 +49,29 @@ namespace vcpkg::Strings::details
namespace vcpkg::Strings
{
+#if defined(_WIN32)
std::wstring to_utf16(const CStringView& s)
{
-#if defined(_WIN32)
std::wstring output;
const size_t size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0);
if (size == 0) return output;
output.resize(size - 1);
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), static_cast<int>(size) - 1);
return output;
-#else
- Checks::unreachable(VCPKG_LINE_INFO);
-#endif
}
+#endif
+#if defined(_WIN32)
std::string to_utf8(const wchar_t* w)
{
-#if defined(_WIN32)
std::string output;
const size_t size = WideCharToMultiByte(CP_UTF8, 0, w, -1, nullptr, 0, nullptr, nullptr);
if (size == 0) return output;
output.resize(size - 1);
WideCharToMultiByte(CP_UTF8, 0, w, -1, output.data(), static_cast<int>(size) - 1, nullptr, nullptr);
return output;
-#else
- Checks::unreachable(VCPKG_LINE_INFO);
-#endif
}
+#endif
std::string escape_string(const CStringView& s, char char_to_escape, char escape_char)
{
@@ -132,6 +128,12 @@ namespace vcpkg::Strings
#endif
}
+ bool ends_with(const std::string& s, StringLiteral pattern)
+ {
+ if (s.size() < pattern.size()) return false;
+ return std::equal(s.end() - pattern.size(), s.end(), pattern.c_str(), pattern.c_str() + pattern.size());
+ }
+
std::string replace_all(std::string&& s, const std::string& search, const std::string& rep)
{
size_t pos = 0;
diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp
index d4210fe6d..1aa12d0a4 100644
--- a/toolsrc/src/vcpkg/base/system.cpp
+++ b/toolsrc/src/vcpkg/base/system.cpp
@@ -40,8 +40,9 @@ namespace vcpkg::System
if (bytes == 0) std::abort();
return fs::path(buf, buf + bytes);
#elif defined(__APPLE__)
- uint32_t size = 1024 * 32;
- char buf[size] = {};
+ static constexpr const uint32_t buff_size = 1024 * 32;
+ uint32_t size = buff_size;
+ char buf[buff_size] = {};
bool result = _NSGetExecutablePath(buf, &size);
Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path.");
std::unique_ptr<char> canonicalPath(realpath(buf, NULL));
@@ -128,33 +129,9 @@ namespace vcpkg::System
R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string());
}
- PowershellParameter::PowershellParameter(const CStringView varname, const char* varvalue)
- : s(Strings::format(R"(-%s '%s')", varname, varvalue))
- {
- }
-
- PowershellParameter::PowershellParameter(const CStringView varname, const std::string& varvalue)
- : PowershellParameter(varname, varvalue.c_str())
- {
- }
-
- PowershellParameter::PowershellParameter(const CStringView varname, const fs::path& path)
- : PowershellParameter(varname, path.generic_u8string())
- {
- }
-
- static std::string make_powershell_cmd(const fs::path& script_path,
- const std::vector<PowershellParameter>& parameters)
- {
- const std::string args = Strings::join(" ", parameters, [](auto&& v) { return v.s; });
-
- // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
- return Strings::format(
- R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args);
- }
-
int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map<std::string, std::string>& extra_env)
{
+ auto timer = Chrono::ElapsedTimer::create_started();
#if defined(_WIN32)
static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO);
static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)";
@@ -271,11 +248,14 @@ namespace vcpkg::System
DWORD exit_code = 0;
GetExitCodeProcess(process_info.hProcess, &exit_code);
- Debug::println("CreateProcessW() returned %lu", exit_code);
+ Debug::println("CreateProcessW() returned %lu after %d us", exit_code, static_cast<int>(timer.microseconds()));
return static_cast<int>(exit_code);
#else
+ Debug::println("system(%s)", cmd_line.c_str());
fflush(nullptr);
- return system(cmd_line.c_str());
+ int rc = system(cmd_line.c_str());
+ Debug::println("system() returned %d", rc);
+ return rc;
#endif
}
@@ -366,71 +346,6 @@ namespace vcpkg::System
#endif
}
- void powershell_execute(const std::string& title,
- const fs::path& script_path,
- const std::vector<PowershellParameter>& parameters)
- {
- const std::string cmd = make_powershell_cmd(script_path, parameters);
- const int rc = System::cmd_execute(cmd);
-
- if (rc)
- {
- System::println(Color::error,
- "%s\n"
- "Could not run:\n"
- " '%s'",
- title,
- script_path.generic_string());
-
- {
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->track_property("error", "powershell script failed");
- locked_metrics->track_property("title", title);
- }
-
- Checks::exit_with_code(VCPKG_LINE_INFO, rc);
- }
- }
-
- std::string powershell_execute_and_capture_output(const std::string& title,
- const fs::path& script_path,
- const std::vector<PowershellParameter>& parameters)
- {
- const std::string cmd = make_powershell_cmd(script_path, parameters);
- auto rc = System::cmd_execute_and_capture_output(cmd);
-
- if (rc.exit_code)
- {
- System::println(Color::error,
- "%s\n"
- "Could not run:\n"
- " '%s'\n"
- "Error message was:\n"
- " %s",
- title,
- script_path.generic_string(),
- rc.output);
-
- {
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->track_property("error", "powershell script failed");
- locked_metrics->track_property("title", title);
- }
-
- Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code);
- }
-
- // Remove newline from all output.
- // Powershell returns newlines when it hits the column count of the console.
- // For example, this is 80 in cmd on Windows 7. If the expected output is longer than 80 lines, we get
- // newlines in-between the data.
- // To solve this, we design our interaction with powershell to not depend on newlines,
- // and then strip all newlines here.
- rc.output = Strings::replace_all(std::move(rc.output), "\n", "");
-
- return rc.output;
- }
-
void println() { putchar('\n'); }
void print(const CStringView message) { fputs(message.c_str(), stdout); }
diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp
index 126c7df97..73ca23df1 100644
--- a/toolsrc/src/vcpkg/binaryparagraph.cpp
+++ b/toolsrc/src/vcpkg/binaryparagraph.cpp
@@ -24,7 +24,7 @@ namespace vcpkg
static const std::string DEFAULTFEATURES = "Default-Features";
}
- BinaryParagraph::BinaryParagraph() noexcept = default;
+ BinaryParagraph::BinaryParagraph() = default;
BinaryParagraph::BinaryParagraph(std::unordered_map<std::string, std::string> fields)
{
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index 7a9d35667..b8ccb15bf 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -217,7 +217,12 @@ namespace vcpkg::Build
if (it != toolset.supported_architectures.end()) return it->name;
}
- Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture);
+ Checks::exit_with_message(VCPKG_LINE_INFO,
+ "Unsupported toolchain combination. Target was: %s but supported ones were:\n%s",
+ target_architecture,
+ Strings::join(",", toolset.supported_architectures, [](const ToolsetArchOption& t) {
+ return t.name.c_str();
+ }));
}
std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset)
@@ -357,7 +362,7 @@ namespace vcpkg::Build
{
{"CMD", "BUILD"},
{"PORT", config.scf.core_paragraph->name},
- {"CURRENT_PORT_DIR", config.port_dir / "/."},
+ {"CURRENT_PORT_DIR", config.port_dir},
{"TARGET_TRIPLET", spec.triplet().canonical_name()},
{"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
{"VCPKG_USE_HEAD_VERSION",
@@ -456,9 +461,9 @@ namespace vcpkg::Build
abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end());
abi_tag_entries.emplace_back(
- AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")});
+ AbiEntry{"portfile", Commands::Hash::get_file_hash(fs, config.port_dir / "portfile.cmake", "SHA1")});
abi_tag_entries.emplace_back(
- AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")});
+ AbiEntry{"control", Commands::Hash::get_file_hash(fs, config.port_dir / "CONTROL", "SHA1")});
abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag});
@@ -493,7 +498,7 @@ namespace vcpkg::Build
const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
fs.write_contents(abi_file_path, full_abi_info);
- return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path};
+ return AbiTagAndFile{Commands::Hash::get_file_hash(fs, abi_file_path, "SHA1"), abi_file_path};
}
System::println(
@@ -520,8 +525,8 @@ namespace vcpkg::Build
System::cmd_execute_clean(Strings::format(
R"("%s" x "%s" -o"%s" -y >nul)", seven_zip_exe.u8string(), archive_path.u8string(), pkg_path.u8string()));
#else
- System::cmd_execute_clean(Strings::format(
- R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string()));
+ System::cmd_execute_clean(
+ Strings::format(R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string()));
#endif
}
@@ -537,11 +542,10 @@ namespace vcpkg::Build
#if defined(_WIN32)
auto&& seven_zip_exe = paths.get_tool_exe(Tools::SEVEN_ZIP);
- System::cmd_execute_clean(Strings::format(
- R"("%s" a "%s" "%s\*" >nul)",
- seven_zip_exe.u8string(),
- tmp_archive_path.u8string(),
- paths.package_dir(spec).u8string()));
+ System::cmd_execute_clean(Strings::format(R"("%s" a "%s" "%s\*" >nul)",
+ seven_zip_exe.u8string(),
+ tmp_archive_path.u8string(),
+ paths.package_dir(spec).u8string()));
#else
System::cmd_execute_clean(Strings::format(
R"(cd '%s' && zip --quiet -r '%s' *)", paths.package_dir(spec).u8string(), tmp_archive_path.u8string()));
@@ -779,14 +783,12 @@ namespace vcpkg::Build
{
return it_hash->second;
}
- auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1");
+ auto hash = Commands::Hash::get_file_hash(paths.get_filesystem(), triplet_file_path, "SHA1");
s_hash_cache.emplace(triplet_file_path, hash);
return hash;
}
- else
- {
- return std::string();
- }
+
+ return std::string();
}();
const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp
index a9d8ba03c..464f4f9ee 100644
--- a/toolsrc/src/vcpkg/commands.cache.cpp
+++ b/toolsrc/src/vcpkg/commands.cache.cpp
@@ -61,7 +61,7 @@ namespace vcpkg::Commands::Cache
for (const BinaryParagraph& binary_paragraph : binary_paragraphs)
{
const std::string displayname = binary_paragraph.displayname();
- if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end())
+ if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0]))
{
continue;
}
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp
index 04b42ea00..e2b93dc7e 100644
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ b/toolsrc/src/vcpkg/commands.ci.cpp
@@ -154,8 +154,10 @@ namespace vcpkg::Commands::CI
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- Checks::check_exit(
- VCPKG_LINE_INFO, GlobalState::g_binary_caching, "The ci command requires binary caching to be enabled.");
+ if (!GlobalState::g_binary_caching)
+ {
+ System::println(System::Color::warning, "Warning: Running ci without binary caching!");
+ }
const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp
index 8b6ffb3d7..09da57705 100644
--- a/toolsrc/src/vcpkg/commands.cpp
+++ b/toolsrc/src/vcpkg/commands.cpp
@@ -43,7 +43,7 @@ namespace vcpkg::Commands
{"portsdiff", &PortsDiff::perform_and_exit},
{"autocomplete", &Autocomplete::perform_and_exit},
{"hash", &Hash::perform_and_exit},
- // {"fetch", &Fetch::perform_and_exit},
+ {"fetch", &Fetch::perform_and_exit},
};
return t;
}
diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp
index b6324565c..2569c2cea 100644
--- a/toolsrc/src/vcpkg/commands.edit.cpp
+++ b/toolsrc/src/vcpkg/commands.edit.cpp
@@ -78,7 +78,8 @@ namespace vcpkg::Commands::Edit
if (Util::Sets::contains(options.switches, OPTION_BUILDTREES))
{
return Util::fmap(ports, [&](const std::string& port_name) -> std::string {
- return (paths.buildtrees / port_name).u8string();
+ const auto buildtrees_current_dir = paths.buildtrees / port_name;
+ return Strings::format(R"###("%s")###", buildtrees_current_dir.u8string());
});
}
diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp
index 1e31e6bc4..33c5c1dcc 100644
--- a/toolsrc/src/vcpkg/commands.fetch.cpp
+++ b/toolsrc/src/vcpkg/commands.fetch.cpp
@@ -1,6 +1,7 @@
#include "pch.h"
#include <vcpkg/base/checks.h>
+#include <vcpkg/base/sortedvector.h>
#include <vcpkg/base/strings.h>
#include <vcpkg/base/system.h>
#include <vcpkg/base/util.h>
@@ -19,6 +20,7 @@ namespace vcpkg::Commands::Fetch
fs::path exe_path;
std::string url;
fs::path download_path;
+ bool is_archive;
fs::path tool_dir_path;
std::string sha512;
};
@@ -41,20 +43,85 @@ namespace vcpkg::Commands::Fetch
return result;
}
- static Optional<std::string> extract_string_between_delimiters(const std::string& input,
- const std::string& left_delim,
- const std::string& right_delim,
- const size_t& starting_offset = 0)
+ struct VcpkgStringRange
{
- const size_t from = input.find(left_delim, starting_offset);
- if (from == std::string::npos) return nullopt;
+ VcpkgStringRange() = default;
- const size_t substring_start = from + left_delim.length();
+ // Implicit by design
+ VcpkgStringRange(const std::string& s) : begin(s.cbegin()), end(s.cend()) {}
- const size_t to = input.find(right_delim, substring_start);
- if (from == std::string::npos) return nullopt;
+ VcpkgStringRange(const std::string::const_iterator begin, const std::string::const_iterator end)
+ : begin(begin), end(end)
+ {
+ }
+
+ std::string::const_iterator begin;
+ std::string::const_iterator end;
+
+ std::string to_string() const { return std::string(this->begin, this->end); }
+ };
- return input.substr(substring_start, to - substring_start);
+ static std::vector<VcpkgStringRange> find_all_enclosed(const VcpkgStringRange& input,
+ const std::string& left_delim,
+ const std::string& right_delim)
+ {
+ std::string::const_iterator it_left = input.begin;
+ std::string::const_iterator it_right = input.begin;
+
+ std::vector<VcpkgStringRange> output;
+
+ while (true)
+ {
+ it_left = std::search(it_right, input.end, left_delim.cbegin(), left_delim.cend());
+ if (it_left == input.end) break;
+
+ it_left += left_delim.length();
+
+ it_right = std::search(it_left, input.end, right_delim.cbegin(), right_delim.cend());
+ if (it_right == input.end) break;
+
+ output.emplace_back(it_left, it_right);
+
+ ++it_right;
+ }
+
+ return output;
+ }
+
+ static VcpkgStringRange find_exactly_one_enclosed(const VcpkgStringRange& input,
+ const std::string& left_tag,
+ const std::string& right_tag)
+ {
+ std::vector<VcpkgStringRange> result = find_all_enclosed(input, left_tag, right_tag);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ result.size() == 1,
+ "Found %d sets of %s.*%s but expected exactly 1, in block:\n%s",
+ result.size(),
+ left_tag,
+ right_tag,
+ input);
+ return std::move(result.front());
+ }
+
+ static Optional<VcpkgStringRange> find_at_most_one_enclosed(const VcpkgStringRange& input,
+ const std::string& left_tag,
+ const std::string& right_tag)
+ {
+ std::vector<VcpkgStringRange> result = find_all_enclosed(input, left_tag, right_tag);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ result.size() <= 1,
+ "Found %d sets of %s.*%s but expected at most 1, in block:\n%s",
+ result.size(),
+ left_tag,
+ right_tag,
+ input);
+
+ if (result.empty())
+ {
+ return nullopt;
+ }
+
+ return result.front();
}
static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool)
@@ -72,20 +139,6 @@ namespace vcpkg::Commands::Fetch
#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__)
static const std::string XML_VERSION = "2";
static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml";
-
- const auto get_string_inside_tags =
- [](const std::string& input, const std::string& left_delim, const std::string& right_delim) -> std::string {
- Optional<std::string> result = extract_string_between_delimiters(input, left_delim, right_delim);
- Checks::check_exit(VCPKG_LINE_INFO,
- result.has_value(),
- "Could not find tag <%s>.*<%s> in %s",
- left_delim,
- right_delim,
- XML_PATH.generic_string());
-
- return *result.get();
- };
-
static const std::regex XML_VERSION_REGEX{R"###(<tools[\s]+version="([^"]+)">)###"};
static const std::string XML = paths.get_filesystem().read_contents(XML_PATH).value_or_exit(VCPKG_LINE_INFO);
std::smatch match_xml_version;
@@ -111,14 +164,14 @@ namespace vcpkg::Commands::Fetch
tool,
XML_PATH.generic_string());
- const std::string tool_data = get_string_inside_tags(XML, match_tool_entry[0], R"(</tool>)");
-
- const std::string version_as_string = get_string_inside_tags(tool_data, "<version>", R"(</version>)");
+ const std::string tool_data = find_exactly_one_enclosed(XML, match_tool_entry[0], "</tool>").to_string();
+ const std::string version_as_string =
+ find_exactly_one_enclosed(tool_data, "<version>", "</version>").to_string();
const std::string exe_relative_path =
- get_string_inside_tags(tool_data, "<exeRelativePath>", R"(</exeRelativePath>)");
- const std::string url = get_string_inside_tags(tool_data, "<url>", R"(</url>)");
- const std::string sha512 = get_string_inside_tags(tool_data, "<sha512>", R"(</sha512>)");
- auto archive_name = extract_string_between_delimiters(tool_data, "<archiveName>", R"(</archiveName>)");
+ find_exactly_one_enclosed(tool_data, "<exeRelativePath>", "</exeRelativePath>").to_string();
+ const std::string url = find_exactly_one_enclosed(tool_data, "<url>", "</url>").to_string();
+ const std::string sha512 = find_exactly_one_enclosed(tool_data, "<sha512>", "</sha512>").to_string();
+ auto archive_name = find_at_most_one_enclosed(tool_data, "<archiveName>", "</archiveName>");
const Optional<std::array<int, 3>> version = parse_version_string(version_as_string);
Checks::check_exit(VCPKG_LINE_INFO,
@@ -128,13 +181,14 @@ namespace vcpkg::Commands::Fetch
version_as_string);
const std::string tool_dir_name = Strings::format("%s-%s-%s", tool, version_as_string, OS_STRING);
- const fs::path tool_dir_path = paths.downloads / "tools" / tool_dir_name;
+ const fs::path tool_dir_path = paths.tools / tool_dir_name;
const fs::path exe_path = tool_dir_path / exe_relative_path;
return ToolData{*version.get(),
exe_path,
url,
- paths.downloads / archive_name.value_or(exe_relative_path),
+ paths.downloads / archive_name.value_or(exe_relative_path).to_string(),
+ archive_name.has_value(),
tool_dir_path,
sha512};
#endif
@@ -162,51 +216,87 @@ namespace vcpkg::Commands::Fetch
actual_version[2] >= expected_version[2]));
}
- static Optional<fs::path> find_if_has_equal_or_greater_version(const std::vector<fs::path>& candidate_paths,
+ static Optional<fs::path> find_if_has_equal_or_greater_version(Files::Filesystem& fs,
+ const std::vector<fs::path>& candidate_paths,
const std::string& version_check_arguments,
const std::array<int, 3>& expected_version)
{
- auto it = Util::find_if(candidate_paths, [&](const fs::path& p) {
+ const auto it = Util::find_if(candidate_paths, [&](const fs::path& p) {
+ if (!fs.exists(p)) return false;
const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments);
return exists_and_has_equal_or_greater_version(cmd, expected_version);
});
if (it != candidate_paths.cend())
{
- return std::move(*it);
+ return *it;
}
return nullopt;
}
- static std::vector<std::string> keep_data_lines(const std::string& data_blob)
- {
- static const std::regex DATA_LINE_REGEX(R"(<sol>::(.+?)(?=::<eol>))");
-
- std::vector<std::string> data_lines;
-
- const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX);
- const std::sregex_iterator end;
- for (std::sregex_iterator i = it; i != end; ++i)
- {
- const std::smatch match = *i;
- data_lines.push_back(match[1].str());
- }
-
- return data_lines;
- }
-
-#if !defined(_WIN32)
static void extract_archive(const VcpkgPaths& paths, const fs::path& archive, const fs::path& to_path)
{
Files::Filesystem& fs = paths.get_filesystem();
const fs::path to_path_partial = to_path.u8string() + ".partial";
std::error_code ec;
+ fs.remove_all(to_path, ec);
fs.remove_all(to_path_partial, ec);
fs.create_directories(to_path_partial, ec);
-
const auto ext = archive.extension();
+#if defined(_WIN32)
+ if (ext == ".nupkg")
+ {
+ static bool recursion_limiter_sevenzip_old = false;
+ Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip_old);
+ recursion_limiter_sevenzip_old = true;
+ const auto nuget_exe = get_tool_path(paths, Tools::NUGET);
+
+ const std::string stem = archive.stem().u8string();
+ // assuming format of [name].[version in the form d.d.d]
+ // This assumption may not always hold
+ std::smatch match;
+ const bool has_match = std::regex_match(stem, match, std::regex{R"###(^(.+)\.(\d+\.\d+\.\d+)$)###"});
+ Checks::check_exit(VCPKG_LINE_INFO,
+ has_match,
+ "Could not deduce nuget id and version from filename: %s",
+ archive.u8string());
+
+ const std::string nugetid = match[1];
+ const std::string version = match[2];
+
+ const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
+ R"("%s" install %s -Version %s -OutputDirectory "%s" -Source "%s" -nocache -DirectDownload -NonInteractive -ForceEnglishOutput -PackageSaveMode nuspec)",
+ nuget_exe.u8string(),
+ nugetid,
+ version,
+ to_path_partial.u8string(),
+ paths.downloads.u8string()));
+
+ Checks::check_exit(VCPKG_LINE_INFO,
+ code_and_output.exit_code == 0,
+ "Failed to extract '%s' with message:\n%s",
+ archive.u8string(),
+ code_and_output.output);
+ recursion_limiter_sevenzip_old = false;
+ }
+ else
+ {
+ static bool recursion_limiter_sevenzip = false;
+ Checks::check_exit(VCPKG_LINE_INFO, !recursion_limiter_sevenzip);
+ recursion_limiter_sevenzip = true;
+ const auto seven_zip = get_tool_path(paths, Tools::SEVEN_ZIP);
+ const auto code_and_output = System::cmd_execute_and_capture_output(Strings::format(
+ R"("%s" x "%s" -o"%s" -y)", seven_zip.u8string(), archive.u8string(), to_path_partial.u8string()));
+ Checks::check_exit(VCPKG_LINE_INFO,
+ code_and_output.exit_code == 0,
+ "7zip failed while extracting '%s' with message:\n%s",
+ archive.u8string(),
+ code_and_output.output);
+ recursion_limiter_sevenzip = false;
+ }
+#else
if (ext == ".gz" && ext.extension() != ".tar")
{
const auto code = System::cmd_execute(
@@ -223,16 +313,23 @@ namespace vcpkg::Commands::Fetch
{
Checks::exit_with_message(VCPKG_LINE_INFO, "Unexpected archive extension: %s", ext.u8string());
}
+#endif
- fs.rename(to_path_partial, to_path);
+ fs.rename(to_path_partial, to_path, ec);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !ec,
+ "Failed to do post-extract rename-in-place.\nfs.rename(%s, %s, %s)",
+ to_path_partial.u8string(),
+ to_path.u8string(),
+ ec.message());
}
- static void verify_hash(const VcpkgPaths& paths,
+ static void verify_hash(const Files::Filesystem& fs,
const std::string& url,
const fs::path& path,
const std::string& sha512)
{
- const std::string actual_hash = Hash::get_file_hash(paths, path, "SHA512");
+ const std::string actual_hash = Hash::get_file_hash(fs, path, "SHA512");
Checks::check_exit(VCPKG_LINE_INFO,
sha512 == actual_hash,
"File does not have the expected hash:\n"
@@ -246,78 +343,165 @@ namespace vcpkg::Commands::Fetch
actual_hash);
}
- static void download_file(const VcpkgPaths& paths,
+#if defined(_WIN32)
+ static void winhttp_download_file(Files::Filesystem& fs,
+ CStringView target_file_path,
+ CStringView hostname,
+ CStringView url_path)
+ {
+ // Make sure the directories are present, otherwise fopen_s fails
+ const auto dir = fs::path(target_file_path.c_str()).parent_path();
+ std::error_code ec;
+ fs.create_directories(dir, ec);
+ Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not create directories %s", dir.u8string());
+
+ FILE* f = nullptr;
+ const errno_t err = fopen_s(&f, target_file_path.c_str(), "wb");
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !err,
+ "Could not download https://%s%s. Failed to open file %s. Error code was %s",
+ hostname,
+ url_path,
+ target_file_path,
+ std::to_string(err));
+
+ auto hSession = WinHttpOpen(
+ L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
+ Checks::check_exit(VCPKG_LINE_INFO, hSession, "WinHttpOpen() failed: %d", GetLastError());
+
+ // Use Windows 10 defaults on Windows 7
+ DWORD secure_protocols(WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 |
+ WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2);
+ WinHttpSetOption(hSession, WINHTTP_OPTION_SECURE_PROTOCOLS, &secure_protocols, sizeof(secure_protocols));
+
+ // Specify an HTTP server.
+ auto hConnect = WinHttpConnect(hSession, Strings::to_utf16(hostname).c_str(), INTERNET_DEFAULT_HTTPS_PORT, 0);
+ Checks::check_exit(VCPKG_LINE_INFO, hConnect, "WinHttpConnect() failed: %d", GetLastError());
+
+ // Create an HTTP request handle.
+ auto hRequest = WinHttpOpenRequest(hConnect,
+ L"GET",
+ Strings::to_utf16(url_path).c_str(),
+ nullptr,
+ WINHTTP_NO_REFERER,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ WINHTTP_FLAG_SECURE);
+ Checks::check_exit(VCPKG_LINE_INFO, hRequest, "WinHttpOpenRequest() failed: %d", GetLastError());
+
+ // Send a request.
+ auto bResults =
+ WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpSendRequest() failed: %d", GetLastError());
+
+ // End the request.
+ bResults = WinHttpReceiveResponse(hRequest, NULL);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReceiveResponse() failed: %d", GetLastError());
+
+ std::vector<char> buf;
+
+ size_t total_downloaded_size = 0;
+ DWORD dwSize = 0;
+ do
+ {
+ DWORD downloaded_size = 0;
+ bResults = WinHttpQueryDataAvailable(hRequest, &dwSize);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpQueryDataAvailable() failed: %d", GetLastError());
+
+ if (buf.size() < dwSize) buf.resize(dwSize * 2);
+
+ bResults = WinHttpReadData(hRequest, (LPVOID)buf.data(), dwSize, &downloaded_size);
+ Checks::check_exit(VCPKG_LINE_INFO, bResults, "WinHttpReadData() failed: %d", GetLastError());
+ fwrite(buf.data(), 1, downloaded_size, f);
+
+ total_downloaded_size += downloaded_size;
+ } while (dwSize > 0);
+
+ WinHttpCloseHandle(hSession);
+ WinHttpCloseHandle(hConnect);
+ WinHttpCloseHandle(hRequest);
+ fflush(f);
+ fclose(f);
+ }
+#endif
+
+ static void download_file(Files::Filesystem& fs,
const std::string& url,
const fs::path& download_path,
const std::string& sha512)
{
- Files::Filesystem& fs = paths.get_filesystem();
const std::string download_path_part = download_path.u8string() + ".part";
std::error_code ec;
+ fs.remove(download_path, ec);
fs.remove(download_path_part, ec);
- const auto code = System::cmd_execute(Strings::format(
- R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part));
+#if defined(_WIN32)
+ auto url_no_proto = url.substr(8); // drop https://
+ auto path_begin = Util::find(url_no_proto, '/');
+ std::string hostname(url_no_proto.begin(), path_begin);
+ std::string path(path_begin, url_no_proto.end());
+
+ winhttp_download_file(fs, download_path_part.c_str(), hostname, path);
+#else
+ const auto code = System::cmd_execute(
+ Strings::format(R"(curl -L '%s' --create-dirs --output '%s')", url, download_path_part));
Checks::check_exit(VCPKG_LINE_INFO, code == 0, "Could not download %s", url);
+#endif
- verify_hash(paths, url, download_path_part, sha512);
- fs.rename(download_path_part, download_path);
+ verify_hash(fs, url, download_path_part, sha512);
+ fs.rename(download_path_part, download_path, ec);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !ec,
+ "Failed to do post-download rename-in-place.\nfs.rename(%s, %s, %s)",
+ download_path_part,
+ download_path.u8string(),
+ ec.message());
}
-#endif
static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data)
{
const std::array<int, 3>& version = tool_data.version;
-
const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !tool_data.url.empty(),
+ "A suitable version of %s was not found (required v%s) and unable to automatically "
+ "download a portable one. Please install a newer version of git.",
+ tool_name,
+ version_as_string);
System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...",
tool_name,
version_as_string,
tool_name,
version_as_string);
-#if defined(_WIN32)
- const fs::path script = paths.scripts / "fetchtool.ps1";
- const std::string title = Strings::format(
- "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string);
- const System::PowershellParameter tool_param("tool", tool_name);
- const std::string output = System::powershell_execute_and_capture_output(title, script, {tool_param});
-
- const std::vector<std::string> tool_path = keep_data_lines(output);
- Checks::check_exit(VCPKG_LINE_INFO, tool_path.size() == 1, "Expected tool path, but got %s", output);
-
- const fs::path actual_downloaded_path = Strings::trim(std::string{tool_path.at(0)});
- const fs::path& expected_downloaded_path = tool_data.exe_path;
- std::error_code ec;
- const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec);
- Checks::check_exit(VCPKG_LINE_INFO,
- eq && !ec,
- "Expected tool downloaded path to be %s, but was %s",
- expected_downloaded_path.u8string(),
- actual_downloaded_path.u8string());
- return actual_downloaded_path;
-#else
- const auto& fs = paths.get_filesystem();
+ auto& fs = paths.get_filesystem();
if (!fs.exists(tool_data.download_path))
{
System::println("Downloading %s...", tool_name);
- download_file(paths, tool_data.url, tool_data.download_path, tool_data.sha512);
+ download_file(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
System::println("Downloading %s... done.", tool_name);
}
else
{
- verify_hash(paths, tool_data.url, tool_data.download_path, tool_data.sha512);
+ verify_hash(fs, tool_data.url, tool_data.download_path, tool_data.sha512);
}
- System::println("Extracting %s...", tool_name);
- extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
- System::println("Extracting %s... done.", tool_name);
+ if (tool_data.is_archive)
+ {
+ System::println("Extracting %s...", tool_name);
+ extract_archive(paths, tool_data.download_path, tool_data.tool_dir_path);
+ System::println("Extracting %s... done.", tool_name);
+ }
+ else
+ {
+ std::error_code ec;
+ fs.create_directories(tool_data.exe_path.parent_path(), ec);
+ fs.rename(tool_data.download_path, tool_data.exe_path, ec);
+ }
Checks::check_exit(VCPKG_LINE_INFO,
fs.exists(tool_data.exe_path),
- "Expected %s to exist after extracting",
- tool_data.exe_path);
+ "Expected %s to exist after fetching",
+ tool_data.exe_path.u8string());
return tool_data.exe_path;
-#endif
}
static fs::path get_cmake_path(const VcpkgPaths& paths)
@@ -339,8 +523,8 @@ namespace vcpkg::Commands::Fetch
const auto& program_files_32_bit = System::get_program_files_32_bit();
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe");
- const Optional<fs::path> path =
- find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
+ const Optional<fs::path> path = find_if_has_equal_or_greater_version(
+ paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
if (const auto p = path.get())
{
return *p;
@@ -372,7 +556,8 @@ namespace vcpkg::Commands::Fetch
const std::vector<fs::path> from_path = Files::find_from_PATH("ninja");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
- auto path = find_if_has_equal_or_greater_version(candidate_paths, "--version", TOOL_DATA.version);
+ auto path = find_if_has_equal_or_greater_version(
+ paths.get_filesystem(), candidate_paths, "--version", TOOL_DATA.version);
if (const auto p = path.get())
{
return *p;
@@ -390,7 +575,8 @@ namespace vcpkg::Commands::Fetch
const std::vector<fs::path> from_path = Files::find_from_PATH("nuget");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
- auto path = find_if_has_equal_or_greater_version(candidate_paths, "", TOOL_DATA.version);
+ auto path =
+ find_if_has_equal_or_greater_version(paths.get_filesystem(), candidate_paths, "", TOOL_DATA.version);
if (const auto p = path.get())
{
return *p;
@@ -401,11 +587,7 @@ namespace vcpkg::Commands::Fetch
static fs::path get_git_path(const VcpkgPaths& paths)
{
-#if defined(_WIN32)
static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "git");
-#else
- static const ToolData TOOL_DATA = ToolData{{2, 7, 4}, ""};
-#endif
static const std::string VERSION_CHECK_ARGUMENTS = "--version";
std::vector<fs::path> candidate_paths;
@@ -420,8 +602,8 @@ namespace vcpkg::Commands::Fetch
const auto& program_files_32_bit = System::get_program_files_32_bit();
if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe");
- const Optional<fs::path> path =
- find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
+ const Optional<fs::path> path = find_if_has_equal_or_greater_version(
+ paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
if (const auto p = path.get())
{
return *p;
@@ -446,8 +628,8 @@ namespace vcpkg::Commands::Fetch
// candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
// "QtIFW-3.1.0" / "bin" / "installerbase.exe");
- const Optional<fs::path> path =
- find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
+ const Optional<fs::path> path = find_if_has_equal_or_greater_version(
+ paths.get_filesystem(), candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.version);
if (const auto p = path.get())
{
return *p;
@@ -458,48 +640,114 @@ namespace vcpkg::Commands::Fetch
struct VisualStudioInstance
{
+ enum class ReleaseType
+ {
+ STABLE,
+ PRERELEASE,
+ LEGACY
+ };
+
+ static bool preferred_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right)
+ {
+ const auto get_preference_weight = [](const ReleaseType& type) -> int {
+ switch (type)
+ {
+ case ReleaseType::STABLE: return 3;
+ case ReleaseType::PRERELEASE: return 2;
+ case ReleaseType::LEGACY: return 1;
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+ };
+
+ if (left.release_type != right.release_type)
+ {
+ return get_preference_weight(left.release_type) > get_preference_weight(right.release_type);
+ }
+
+ return left.version > right.version;
+ }
+
+ VisualStudioInstance(fs::path&& root_path, std::string&& version, const ReleaseType& release_type)
+ : root_path(std::move(root_path)), version(std::move(version)), release_type(release_type)
+ {
+ }
+
fs::path root_path;
std::string version;
- std::string release_type;
- std::string preference_weight; // Mostly unused, just for verification that order is as intended
+ ReleaseType release_type;
std::string major_version() const { return version.substr(0, 2); }
};
static std::vector<VisualStudioInstance> get_visual_studio_instances(const VcpkgPaths& paths)
{
- const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1";
- const std::string output =
- System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script);
+ const auto& fs = paths.get_filesystem();
+ std::vector<VisualStudioInstance> instances;
- const std::vector<std::string> instances_as_strings = keep_data_lines(output);
- Checks::check_exit(VCPKG_LINE_INFO,
- !instances_as_strings.empty(),
- "Could not detect any Visual Studio instances.\n"
- "Powershell script:\n"
- " %s\n"
- "returned:\n"
- "%s",
- script.generic_string(),
- output);
+ const auto& program_files_32_bit = System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO);
- std::vector<VisualStudioInstance> instances;
- for (const std::string& instance_as_string : instances_as_strings)
+ // Instances from vswhere
+ const fs::path vswhere_exe = program_files_32_bit / "Microsoft Visual Studio" / "Installer" / "vswhere.exe";
+ if (fs.exists(vswhere_exe))
{
- const std::vector<std::string> split = Strings::split(instance_as_string, "::");
+ const auto code_and_output = System::cmd_execute_and_capture_output(
+ Strings::format(R"("%s" -prerelease -legacy -products * -format xml)", vswhere_exe.u8string()));
Checks::check_exit(VCPKG_LINE_INFO,
- split.size() == 4,
- "Invalid Visual Studio instance format.\n"
- "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n"
- "Actual : %s\n",
- instance_as_string);
- instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)});
+ code_and_output.exit_code == 0,
+ "Running vswhere.exe failed with message:\n%s",
+ code_and_output.output);
+
+ const auto instance_entries = find_all_enclosed(code_and_output.output, "<instance>", "</instance>");
+ for (const VcpkgStringRange& instance : instance_entries)
+ {
+ auto maybe_is_prerelease = find_at_most_one_enclosed(instance, "<isPrerelease>", "</isPrerelease>");
+
+ VisualStudioInstance::ReleaseType release_type = VisualStudioInstance::ReleaseType::LEGACY;
+ if (const auto p = maybe_is_prerelease.get())
+ {
+ const auto s = p->to_string();
+ if (s == "0")
+ release_type = VisualStudioInstance::ReleaseType::STABLE;
+ else if (s == "1")
+ release_type = VisualStudioInstance::ReleaseType::PRERELEASE;
+ else
+ Checks::unreachable(VCPKG_LINE_INFO);
+ }
+
+ instances.emplace_back(
+ find_exactly_one_enclosed(instance, "<installationPath>", "</installationPath>").to_string(),
+ find_exactly_one_enclosed(instance, "<installationVersion>", "</installationVersion>").to_string(),
+ release_type);
+ }
+ }
+
+ const auto append_if_has_cl = [&](fs::path&& path_root) {
+ const auto cl_exe = path_root / "VC" / "bin" / "cl.exe";
+ const auto vcvarsall_bat = path_root / "VC" / "vcvarsall.bat";
+
+ if (fs.exists(cl_exe) && fs.exists(vcvarsall_bat))
+ instances.emplace_back(std::move(path_root), "14.0", VisualStudioInstance::ReleaseType::LEGACY);
+ };
+
+ // VS2015 instance from environment variable
+ auto maybe_vs140_comntools = System::get_environment_variable("vs140comntools");
+ if (const auto path_as_string = maybe_vs140_comntools.get())
+ {
+ // We want lexically_normal(), but it is not available
+ // Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash. Try both.
+ auto common7_tools = fs::path{*path_as_string};
+ append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path());
+ append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path().parent_path());
}
+ // VS2015 instance from Program Files
+ append_if_has_cl(program_files_32_bit / "Microsoft Visual Studio 14.0");
+
return instances;
}
- std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths)
+#if defined(_WIN32)
+ std::vector<Toolset> find_toolset_instances_preferred_first(const VcpkgPaths& paths)
{
using CPU = System::CPUArchitecture;
@@ -511,12 +759,14 @@ namespace vcpkg::Commands::Fetch
std::vector<Toolset> found_toolsets;
std::vector<Toolset> excluded_toolsets;
- const std::vector<VisualStudioInstance> vs_instances = get_visual_studio_instances(paths);
- const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) {
+ const SortedVector<VisualStudioInstance> sorted{get_visual_studio_instances(paths),
+ VisualStudioInstance::preferred_first_comparator};
+
+ const bool v140_is_available = Util::find_if(sorted, [&](const VisualStudioInstance& vs_instance) {
return vs_instance.major_version() == "14";
- }) != vs_instances.cend();
+ }) != sorted.end();
- for (const VisualStudioInstance& vs_instance : vs_instances)
+ for (const VisualStudioInstance& vs_instance : sorted)
{
const std::string major_version = vs_instance.major_version();
if (major_version == "15")
@@ -566,7 +816,7 @@ namespace vcpkg::Commands::Fetch
paths_examined.push_back(dumpbin_path);
if (fs.exists(dumpbin_path))
{
- const Toolset v141toolset = Toolset{
+ const Toolset v141toolset{
vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures};
auto english_language_pack = dumpbin_path.parent_path() / "1033";
@@ -581,12 +831,12 @@ namespace vcpkg::Commands::Fetch
if (v140_is_available)
{
- const Toolset v140toolset = Toolset{vs_instance.root_path,
- dumpbin_path,
- vcvarsall_bat,
- {"-vcvars_ver=14.0"},
- V_140,
- supported_architectures};
+ const Toolset v140toolset{vs_instance.root_path,
+ dumpbin_path,
+ vcvarsall_bat,
+ {"-vcvars_ver=14.0"},
+ V_140,
+ supported_architectures};
found_toolsets.push_back(v140toolset);
}
@@ -670,6 +920,7 @@ namespace vcpkg::Commands::Fetch
return found_toolsets;
}
+#endif
fs::path get_tool_path(const VcpkgPaths& paths, const std::string& tool)
{
diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp
index 1f709f87b..0c7aa72c4 100644
--- a/toolsrc/src/vcpkg/commands.hash.cpp
+++ b/toolsrc/src/vcpkg/commands.hash.cpp
@@ -154,10 +154,9 @@ namespace vcpkg::Commands::Hash
};
}
- std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type)
+ std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type)
{
- Checks::check_exit(
- VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string());
+ Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string());
return BCryptHasher{hash_type}.hash_file(path);
}
@@ -202,11 +201,10 @@ namespace vcpkg::Commands::Hash
return split[0];
}
- std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type)
+ std::string get_file_hash(const Files::Filesystem& fs, const fs::path& path, const std::string& hash_type)
{
const std::string digest_size = get_digest_size(hash_type);
- Checks::check_exit(
- VCPKG_LINE_INFO, paths.get_filesystem().exists(path), "File %s does not exist", path.u8string());
+ Checks::check_exit(VCPKG_LINE_INFO, fs.exists(path), "File %s does not exist", path.u8string());
const std::string cmd_line = Strings::format(R"(shasum -a %s "%s")", digest_size, path.u8string());
return run_shasum_and_post_process(cmd_line);
}
@@ -239,7 +237,7 @@ namespace vcpkg::Commands::Hash
const fs::path file_to_hash = args.command_arguments[0];
const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512";
- const std::string hash = get_file_hash(paths, file_to_hash, algorithm);
+ const std::string hash = get_file_hash(paths.get_filesystem(), file_to_hash, algorithm);
System::println(hash);
Checks::exit_success(VCPKG_LINE_INFO);
}
diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp
index 7061a3984..82172e363 100644
--- a/toolsrc/src/vcpkg/commands.integrate.cpp
+++ b/toolsrc/src/vcpkg/commands.integrate.cpp
@@ -5,6 +5,8 @@
#include <vcpkg/base/system.h>
#include <vcpkg/base/util.h>
#include <vcpkg/commands.h>
+#include <vcpkg/metrics.h>
+#include <vcpkg/userconfig.h>
namespace vcpkg::Commands::Integrate
{
@@ -156,8 +158,10 @@ namespace vcpkg::Commands::Integrate
}
#endif
+ static fs::path get_path_txt_path() { return get_user_dir() / "vcpkg.path.txt"; }
+
#if defined(_WIN32)
- static void integrate_install(const VcpkgPaths& paths)
+ static void integrate_install_msbuild14(Files::Filesystem& fs, const fs::path& tmp_dir)
{
static const std::array<fs::path, 2> OLD_SYSTEM_TARGET_FILES = {
System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) /
@@ -168,8 +172,6 @@ namespace vcpkg::Commands::Integrate
System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) /
"MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props";
- auto& fs = paths.get_filesystem();
-
// TODO: This block of code should eventually be removed
for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES)
{
@@ -188,12 +190,6 @@ namespace vcpkg::Commands::Integrate
}
}
}
-
- std::error_code ec;
- const fs::path tmp_dir = paths.buildsystems / "tmp";
- fs.create_directory(paths.buildsystems, ec);
- fs.create_directory(tmp_dir, ec);
-
bool should_install_system = true;
const Expected<std::string> system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE);
static const std::regex RE(R"###(<!-- version (\d+) -->)###");
@@ -232,24 +228,52 @@ namespace vcpkg::Commands::Integrate
"Error: failed to copy targets file to %s",
SYSTEM_WIDE_TARGETS_FILE.string());
}
+ }
+#endif
- const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets";
- fs.write_contents(appdata_src_path,
- create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string()));
- auto appdata_dst_path = get_appdata_targets_path();
+ static void integrate_install(const VcpkgPaths& paths)
+ {
+ auto& fs = paths.get_filesystem();
- const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec);
+#if defined(_WIN32)
+ {
+ std::error_code ec;
+ const fs::path tmp_dir = paths.buildsystems / "tmp";
+ fs.create_directory(paths.buildsystems, ec);
+ fs.create_directory(tmp_dir, ec);
- if (!rc || ec)
+ integrate_install_msbuild14(fs, tmp_dir);
+
+ const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets";
+ fs.write_contents(appdata_src_path,
+ create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string()));
+ auto appdata_dst_path = get_appdata_targets_path();
+
+ const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec);
+
+ if (!rc || ec)
+ {
+ System::println(System::Color::error,
+ "Error: Failed to copy file: %s -> %s",
+ appdata_src_path.string(),
+ appdata_dst_path.string());
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ }
+#endif
+
+ const auto pathtxt = get_path_txt_path();
+ std::error_code ec;
+ fs.write_contents(pathtxt, paths.root.generic_u8string(), ec);
+ if (ec)
{
- System::println(System::Color::error,
- "Error: Failed to copy file: %s -> %s",
- appdata_src_path.string(),
- appdata_dst_path.string());
+ System::println(System::Color::error, "Error: Failed to write file: %s", pathtxt.string());
Checks::exit_fail(VCPKG_LINE_INFO);
}
+
System::println(System::Color::success, "Applied user-wide integration for this vcpkg root.");
const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake";
+#if defined(_WIN32)
System::println(
R"(
All MSBuild C++ projects can now #include any installed libraries.
@@ -258,17 +282,29 @@ Installing new libraries will make them instantly available.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
cmake_toolchain.generic_string());
+#else
+ System::println(
+ R"(
+CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
+ cmake_toolchain.generic_string());
+#endif
Checks::exit_success(VCPKG_LINE_INFO);
}
static void integrate_remove(Files::Filesystem& fs)
{
+ std::error_code ec;
+ bool was_deleted = false;
+
+#if defined(_WIN32)
const fs::path path = get_appdata_targets_path();
- std::error_code ec;
- const bool was_deleted = fs.remove(path, ec);
+ was_deleted |= fs.remove(path, ec);
+ Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message());
+#endif
+ was_deleted |= fs.remove(get_path_txt_path(), ec);
Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message());
if (was_deleted)
@@ -282,7 +318,6 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
Checks::exit_success(VCPKG_LINE_INFO);
}
-#endif
#if defined(WIN32)
static void integrate_project(const VcpkgPaths& paths)
@@ -335,6 +370,43 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
#endif
#if defined(_WIN32)
+ static void integrate_powershell(const VcpkgPaths& paths)
+ {
+ static constexpr StringLiteral TITLE = "PowerShell Tab-Completion";
+ const fs::path script_path = paths.scripts / "addPoshVcpkgToPowershellProfile.ps1";
+
+ // Console font corruption workaround
+ SetConsoleCP(437);
+ SetConsoleOutputCP(437);
+
+ const std::string cmd = Strings::format(
+ R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), "");
+ const int rc = System::cmd_execute(cmd);
+
+ SetConsoleCP(CP_UTF8);
+ SetConsoleOutputCP(CP_UTF8);
+
+ if (rc)
+ {
+ System::println(System::Color::error,
+ "%s\n"
+ "Could not run:\n"
+ " '%s'",
+ TITLE,
+ script_path.generic_string());
+
+ {
+ auto locked_metrics = Metrics::g_metrics.lock();
+ locked_metrics->track_property("error", "powershell script failed");
+ locked_metrics->track_property("title", TITLE);
+ }
+ }
+
+ Checks::exit_with_code(VCPKG_LINE_INFO, rc);
+ }
+#endif
+
+#if defined(_WIN32)
const char* const INTEGRATE_COMMAND_HELPSTRING =
" vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on "
"first use\n"
@@ -343,7 +415,8 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
" vcpkg integrate powershell Enable PowerShell Tab-Completion\n";
#else
const char* const INTEGRATE_COMMAND_HELPSTRING =
- "No user-wide integration methods are available on this platform\n";
+ " vcpkg integrate install Make installed packages available user-wide.\n"
+ " vcpkg integrate remove Remove user-wide integration\n";
#endif
namespace Subcommand
@@ -373,7 +446,6 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
{
Util::unused(args.parse_arguments(COMMAND_STRUCTURE));
-#if defined(_WIN32)
if (args.command_arguments[0] == Subcommand::INSTALL)
{
return integrate_install(paths);
@@ -382,15 +454,14 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
{
return integrate_remove(paths.get_filesystem());
}
+#if defined(_WIN32)
if (args.command_arguments[0] == Subcommand::PROJECT)
{
return integrate_project(paths);
}
if (args.command_arguments[0] == Subcommand::POWERSHELL)
{
- System::powershell_execute("PowerShell Tab-Completion",
- paths.scripts / "addPoshVcpkgToPowershellProfile.ps1");
- Checks::exit_success(VCPKG_LINE_INFO);
+ return integrate_powershell(paths);
}
#endif
diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp
index 1bfbc4247..cadc06ad3 100644
--- a/toolsrc/src/vcpkg/commands.list.cpp
+++ b/toolsrc/src/vcpkg/commands.list.cpp
@@ -76,7 +76,7 @@ namespace vcpkg::Commands::List
for (const StatusParagraph* status_paragraph : installed_packages)
{
const std::string displayname = status_paragraph->package.displayname();
- if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end())
+ if (!Strings::case_insensitive_ascii_contains(displayname, args.command_arguments[0]))
{
continue;
}
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
index 152252018..c444cf3d0 100644
--- a/toolsrc/src/vcpkg/export.cpp
+++ b/toolsrc/src/vcpkg/export.cpp
@@ -226,10 +226,6 @@ namespace vcpkg::Export
{fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"},
{fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"},
{fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"},
- {fs::path{"scripts"} / "getWindowsSDK.ps1"},
- {fs::path{"scripts"} / "getProgramFilesPlatformBitness.ps1"},
- {fs::path{"scripts"} / "getProgramFiles32bit.ps1"},
- {fs::path{"scripts"} / "VcpkgPowershellUtils.ps1"},
};
for (const fs::path& file : integration_files_relative_to_root)
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index fc336d6c7..40e696fa0 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -462,14 +462,14 @@ namespace vcpkg::Install
auto files = fs.read_lines(paths.listfile_path(bpgh));
if (auto p_lines = files.get())
{
+ std::map<std::string, std::string> config_files;
std::map<std::string, std::vector<std::string>> library_targets;
for (auto&& suffix : *p_lines)
{
- if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end() &&
- suffix.substr(suffix.size() - 6) == ".cmake")
+ if (Strings::case_insensitive_ascii_contains(suffix, "/share/") && Strings::ends_with(suffix, ".cmake"))
{
- // File is inside the share folder
+ // CMake file is inside the share folder
auto path = paths.installed / suffix;
auto maybe_contents = fs.read_contents(path);
auto find_package_name = path.parent_path().filename().u8string();
@@ -485,6 +485,21 @@ namespace vcpkg::Install
++next;
}
}
+
+ auto filename = fs::u8path(suffix).filename().u8string();
+
+ if (Strings::ends_with(filename, "Config.cmake"))
+ {
+ auto root = filename.substr(0, filename.size() - 12);
+ if (Strings::case_insensitive_ascii_equals(root, find_package_name))
+ config_files[find_package_name] = root;
+ }
+ else if (Strings::ends_with(filename, "-config.cmake"))
+ {
+ auto root = filename.substr(0, filename.size() - 13);
+ if (Strings::case_insensitive_ascii_equals(root, find_package_name))
+ config_files[find_package_name] = root;
+ }
}
}
@@ -497,11 +512,23 @@ namespace vcpkg::Install
for (auto&& library_target_pair : library_targets)
{
+ auto config_it = config_files.find(library_target_pair.first);
+ if (config_it != config_files.end())
+ System::println(" find_package(%s CONFIG REQUIRED)", config_it->second);
+ else
+ System::println(" find_package(%s CONFIG REQUIRED)", library_target_pair.first);
+
+ std::sort(library_target_pair.second.begin(),
+ library_target_pair.second.end(),
+ [](const std::string& l, const std::string& r) {
+ if (l.size() < r.size()) return true;
+ if (l.size() > r.size()) return false;
+ return l < r;
+ });
+
if (library_target_pair.second.size() <= 4)
{
- System::println(" find_package(%s REQUIRED)\n"
- " target_link_libraries(main PRIVATE %s)\n",
- library_target_pair.first,
+ System::println(" target_link_libraries(main PRIVATE %s)\n",
Strings::join(" ", library_target_pair.second));
}
else
@@ -509,10 +536,8 @@ namespace vcpkg::Install
auto omitted = library_target_pair.second.size() - 4;
library_target_pair.second.erase(library_target_pair.second.begin() + 4,
library_target_pair.second.end());
- System::println(" find_package(%s REQUIRED)\n"
- " # Note: %zd targets were omitted\n"
+ System::println(" # Note: %zd target(s) were omitted.\n"
" target_link_libraries(main PRIVATE %s)\n",
- library_target_pair.first,
omitted,
Strings::join(" ", library_target_pair.second));
}
diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp
index 41ffceec7..77c028937 100644
--- a/toolsrc/src/vcpkg/paragraphs.cpp
+++ b/toolsrc/src/vcpkg/paragraphs.cpp
@@ -253,6 +253,10 @@ namespace vcpkg::Paragraphs
LoadResults ret;
auto port_dirs = fs.get_files_non_recursive(ports_dir);
Util::sort(port_dirs);
+ Util::erase_remove_if(port_dirs, [&](auto&& port_dir_entry) {
+ return fs.is_regular_file(port_dir_entry) && port_dir_entry.filename() == ".DS_Store";
+ });
+
for (auto&& path : port_dirs)
{
auto maybe_spgh = try_load_port(fs, path);
diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp
index 574a97b64..4945fdaaa 100644
--- a/toolsrc/src/vcpkg/userconfig.cpp
+++ b/toolsrc/src/vcpkg/userconfig.cpp
@@ -29,16 +29,21 @@ namespace
namespace vcpkg
{
- static fs::path get_config_path()
+ fs::path get_user_dir()
{
#if defined(_WIN32)
- return get_localappdata() / "vcpkg" / "config";
+ return get_localappdata() / "vcpkg";
#else
auto maybe_home = System::get_environment_variable("HOME");
- return fs::path(maybe_home.value_or("/var")) / ".vcpkg" / "config";
+ return fs::path(maybe_home.value_or("/var")) / ".vcpkg";
#endif
}
+ static fs::path get_config_path()
+ {
+ return get_user_dir() / "config";
+ }
+
UserConfig UserConfig::try_read_data(const Files::Filesystem& fs)
{
UserConfig ret;
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index 0903c2d76..9b74bea74 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -39,6 +39,7 @@ namespace vcpkg
paths.triplets = paths.root / "triplets";
paths.scripts = paths.root / "scripts";
+ paths.tools = paths.downloads / "tools";
paths.buildsystems = paths.scripts / "buildsystems";
paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets";
@@ -113,9 +114,11 @@ namespace vcpkg
return external_toolset;
}
- // Invariant: toolsets are non-empty and sorted with newest at back()
- const std::vector<Toolset>& vs_toolsets =
- this->toolsets.get_lazy([this]() { return Commands::Fetch::find_toolset_instances(*this); });
+#if !defined(_WIN32)
+ Checks::exit_with_message(VCPKG_LINE_INFO, "Cannot build windows triplets from non-windows.");
+#else
+ const std::vector<Toolset>& vs_toolsets = this->toolsets.get_lazy(
+ [this]() { return Commands::Fetch::find_toolset_instances_preferred_first(*this); });
std::vector<const Toolset*> candidates = Util::element_pointers(vs_toolsets);
const auto tsv = prebuildinfo.platform_toolset.get();
@@ -159,6 +162,8 @@ namespace vcpkg
Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found");
return *candidates.front();
+
+#endif
}
Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); }