From 3314845a92852d3461a86d15ca5d6b2a6ca859eb Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Wed, 27 Jun 2018 16:29:16 -0700 Subject: [PATCH] [vcpkg] Remove calls to where.exe to improve startup performance --- toolsrc/include/vcpkg/base/files.h | 12 ++---- toolsrc/src/vcpkg/base/files.cpp | 58 ++++++++++++++++++++-------- toolsrc/src/vcpkg/commands.fetch.cpp | 14 ++++--- 3 files changed, 54 insertions(+), 30 deletions(-) diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 1518d2b5c8..eee9108414 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/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 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& paths); - - std::vector find_from_PATH(const std::string& name); } diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 2f937dcdc7..a6fbfbd73b 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/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 read_contents(const fs::path& file_path) const override @@ -241,6 +249,40 @@ namespace vcpkg::Files } } } + + virtual std::vector 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 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 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); }); - } } diff --git a/toolsrc/src/vcpkg/commands.fetch.cpp b/toolsrc/src/vcpkg/commands.fetch.cpp index 0681e2324f..30aec74e5b 100644 --- a/toolsrc/src/vcpkg/commands.fetch.cpp +++ b/toolsrc/src/vcpkg/commands.fetch.cpp @@ -9,7 +9,6 @@ #include #include #include -# namespace vcpkg::Commands::Fetch { @@ -151,15 +150,20 @@ namespace vcpkg::Commands::Fetch std::vector get_versions(const std::vector& candidate_paths) const { + auto&& fs = Files::get_real_filesystem(); + std::vector 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 from_path = Files::find_from_PATH("cmake"); + const std::vector 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 candidate_paths; candidate_paths.push_back(TOOL_DATA.exe_path); - const std::vector from_path = Files::find_from_PATH("ninja"); + const std::vector 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 ' for help on a specific command. std::vector candidate_paths; candidate_paths.push_back(TOOL_DATA.exe_path); - const std::vector from_path = Files::find_from_PATH("nuget"); + const std::vector 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 from_path = Files::find_from_PATH("git"); + const std::vector 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();