[vcpkg] Remove calls to where.exe to improve startup performance
MODIFY
include/vcpkg/base/files.h
include/vcpkg/base/files.h
@@ -57,13 +57,9 @@ namespace vcpkg::Files
std::error_code& ec) = 0;
virtual fs::file_status status(const fs::path& path, std::error_code& ec) const = 0;
- inline void write_contents(const fs::path& file_path, const std::string& data)
- {
- std::error_code ec;
- write_contents(file_path, data, ec);
- Checks::check_exit(
- VCPKG_LINE_INFO, !ec, "error while writing file: %s: %s", file_path.u8string(), ec.message());
- }
+ virtual std::vector<fs::path> find_from_PATH(const std::string& name) const = 0;
+
+ void write_contents(const fs::path& file_path, const std::string& data);
};
Filesystem& get_real_filesystem();
@@ -73,6 +69,4 @@ namespace vcpkg::Files
bool has_invalid_chars_for_filesystem(const std::string& s);
void print_paths(const std::vector<fs::path>& paths);
-
- std::vector<fs::path> find_from_PATH(const std::string& name);
}

MODIFY
src/vcpkg/base/files.cpp
src/vcpkg/base/files.cpp
@@ -16,6 +16,14 @@ namespace vcpkg::Files
{
static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])");
+ void Filesystem::write_contents(const fs::path& file_path, const std::string& data)
+ {
+ std::error_code ec;
+ write_contents(file_path, data, ec);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, !ec, "error while writing file: %s: %s", file_path.u8string(), ec.message());
+ }
+
struct RealFilesystem final : Filesystem
{
virtual Expected<std::string> read_contents(const fs::path& file_path) const override
@@ -241,6 +249,40 @@ namespace vcpkg::Files
}
}
}
+
+ virtual std::vector<fs::path> find_from_PATH(const std::string& name) const override
+ {
+#if defined(_WIN32)
+ static constexpr StringLiteral EXTS[] = {".cmd", ".exe", ".bat"};
+ auto paths = Strings::split(System::get_environment_variable("PATH").value_or_exit(VCPKG_LINE_INFO), ";");
+
+ std::vector<fs::path> ret;
+ for (auto&& path : paths)
+ {
+ auto base = path + "/" + name;
+ for (auto&& ext : EXTS)
+ {
+ auto p = fs::u8path(base + ext.c_str());
+ if (Util::find(ret, p) != ret.end() && this->exists(p))
+ {
+ ret.push_back(p);
+ Debug::println("Found path: %s", p.u8string());
+ }
+ }
+ }
+
+ return ret;
+#else
+ const std::string cmd = Strings::format("which %s", name);
+ auto out = System::cmd_execute_and_capture_output(cmd);
+ if (out.exit_code != 0)
+ {
+ return {};
+ }
+
+ return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); });
+#endif
+ }
};
Filesystem& get_real_filesystem()
@@ -263,20 +305,4 @@ namespace vcpkg::Files
}
System::println();
}
-
- std::vector<fs::path> find_from_PATH(const std::string& name)
- {
-#if defined(_WIN32)
- const std::string cmd = Strings::format("where.exe %s", name);
-#else
- const std::string cmd = Strings::format("which %s", name);
-#endif
- auto out = System::cmd_execute_and_capture_output(cmd);
- if (out.exit_code != 0)
- {
- return {};
- }
-
- return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); });
- }
}

MODIFY
src/vcpkg/commands.fetch.cpp
src/vcpkg/commands.fetch.cpp
#include <vcpkg/base/util.h>
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
-#
namespace vcpkg::Commands::Fetch
{
@@ -151,15 +150,20 @@ namespace vcpkg::Commands::Fetch
std::vector<PathAndVersion> get_versions(const std::vector<fs::path>& candidate_paths) const
{
+ auto&& fs = Files::get_real_filesystem();
+
std::vector<PathAndVersion> output;
for (auto&& p : candidate_paths)
{
+ if (!fs.exists(p)) continue;
auto maybe_version = this->get_version(p);
if (const auto version = maybe_version.get())
{
output.emplace_back(PathAndVersion{p, *version});
+ return output;
}
}
+
return output;
}
};
@@ -254,7 +258,7 @@ namespace vcpkg::Commands::Fetch
#else
static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""};
#endif
- const std::vector<fs::path> from_path = Files::find_from_PATH("cmake");
+ const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("cmake");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const auto& program_files = System::get_program_files_platform_bitness();
@@ -315,7 +319,7 @@ namespace vcpkg::Commands::Fetch
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(TOOL_DATA.exe_path);
- const std::vector<fs::path> from_path = Files::find_from_PATH("ninja");
+ const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("ninja");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const NinjaVersionProvider version_provider{};
@@ -360,7 +364,7 @@ Type 'NuGet help <command>' for help on a specific command.
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(TOOL_DATA.exe_path);
- const std::vector<fs::path> from_path = Files::find_from_PATH("nuget");
+ const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("nuget");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const NugetVersionProvider version_provider{};
@@ -408,7 +412,7 @@ git version 2.17.1.windows.2
#if defined(_WIN32)
candidate_paths.push_back(TOOL_DATA.exe_path);
#endif
- const std::vector<fs::path> from_path = Files::find_from_PATH("git");
+ const std::vector<fs::path> from_path = paths.get_filesystem().find_from_PATH("git");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
const auto& program_files = System::get_program_files_platform_bitness();

[vcpkg] Remove calls to where.exe to improve startup performance