diff options
| author | Curtis J Bezault <curtbezault@gmail.com> | 2019-08-09 11:59:32 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-09 11:59:32 -0400 |
| commit | c4f1a91ef245ed3e44ea11f13040a77453126165 (patch) | |
| tree | 3e6c99d970fe8a5fcd1551bbcbf9fde4f0b0a3a4 /toolsrc/src | |
| parent | 9da7c5c99ee42e382895dbd0dafdd29beaa61075 (diff) | |
| parent | 743e168ef5c7705e44d1d5cab5b9cca22328345e (diff) | |
| download | vcpkg-c4f1a91ef245ed3e44ea11f13040a77453126165.tar.gz vcpkg-c4f1a91ef245ed3e44ea11f13040a77453126165.zip | |
Merge branch 'master' into external_file_abi
Diffstat (limited to 'toolsrc/src')
22 files changed, 849 insertions, 436 deletions
diff --git a/toolsrc/src/vcpkg-test/files.cpp b/toolsrc/src/vcpkg-test/files.cpp index 9e14cec0c..a2faf455c 100644 --- a/toolsrc/src/vcpkg-test/files.cpp +++ b/toolsrc/src/vcpkg-test/files.cpp @@ -9,29 +9,63 @@ #include <vector> -using vcpkg::Test::SYMLINKS_ALLOWED; -using vcpkg::Test::TEMPORARY_DIRECTORY; +using vcpkg::Test::AllowSymlinks; +using vcpkg::Test::base_temporary_directory; +using vcpkg::Test::can_create_symlinks; + +#define CHECK_EC_ON_FILE(file, ec) \ + do \ + { \ + if (ec) \ + { \ + FAIL(file << ": " << ec.message()); \ + } \ + } while (0) namespace { - using uid = std::uniform_int_distribution<std::uint64_t>; + using uid_t = std::uniform_int_distribution<std::uint64_t>; + using urbg_t = std::mt19937_64; - std::mt19937_64 get_urbg(std::uint64_t index) + urbg_t get_urbg(std::uint64_t index) { // smallest prime > 2**63 - 1 - return std::mt19937_64{index + 9223372036854775837ULL}; + return urbg_t{index + 9223372036854775837ULL}; } - std::string get_random_filename(std::mt19937_64& urbg) { return vcpkg::Strings::b32_encode(uid{}(urbg)); } + std::string get_random_filename(urbg_t& urbg) { return vcpkg::Strings::b32_encode(uid_t{}(urbg)); } - void create_directory_tree(std::mt19937_64& urbg, + struct MaxDepth + { + std::uint64_t i; + explicit MaxDepth(std::uint64_t i) : i(i) {} + operator uint64_t() const { return i; } + }; + + struct Width + { + std::uint64_t i; + explicit Width(std::uint64_t i) : i(i) {} + operator uint64_t() const { return i; } + }; + + struct CurrentDepth + { + std::uint64_t i; + explicit CurrentDepth(std::uint64_t i) : i(i) {} + operator uint64_t() const { return i; } + CurrentDepth incremented() const { return CurrentDepth{i + 1}; } + }; + + void create_directory_tree(urbg_t& urbg, vcpkg::Files::Filesystem& fs, - std::uint64_t depth, - const fs::path& base) + const fs::path& base, + MaxDepth max_depth, + AllowSymlinks allow_symlinks = AllowSymlinks::Yes, + Width width = Width{5}, + CurrentDepth current_depth = CurrentDepth{0}) { std::random_device rd; - constexpr std::uint64_t max_depth = 5; - constexpr std::uint64_t width = 5; // we want ~70% of our "files" to be directories, and then a third // each of the remaining ~30% to be regular files, directory symlinks, @@ -42,18 +76,24 @@ namespace constexpr std::uint64_t regular_symlink_tag = 8; constexpr std::uint64_t directory_symlink_tag = 9; + allow_symlinks = AllowSymlinks{allow_symlinks && can_create_symlinks()}; + // if we're at the max depth, we only want to build non-directories std::uint64_t file_type; - if (depth < max_depth) + if (current_depth >= max_depth) + { + file_type = uid_t{regular_file_tag, directory_symlink_tag}(urbg); + } + else if (current_depth < 2) { - file_type = uid{directory_min_tag, regular_symlink_tag}(urbg); + file_type = directory_min_tag; } else { - file_type = uid{regular_file_tag, regular_symlink_tag}(urbg); + file_type = uid_t{directory_min_tag, regular_symlink_tag}(urbg); } - if (!SYMLINKS_ALLOWED && file_type > regular_file_tag) + if (!allow_symlinks && file_type > regular_file_tag) { file_type = regular_file_tag; } @@ -62,14 +102,20 @@ namespace if (file_type <= directory_max_tag) { fs.create_directory(base, ec); - if (ec) { - INFO("File that failed: " << base); - REQUIRE_FALSE(ec); + if (ec) + { + CHECK_EC_ON_FILE(base, ec); } for (int i = 0; i < width; ++i) { - create_directory_tree(urbg, fs, depth + 1, base / get_random_filename(urbg)); + create_directory_tree(urbg, + fs, + base / get_random_filename(urbg), + max_depth, + allow_symlinks, + width, + current_depth.incremented()); } } else if (file_type == regular_file_tag) @@ -80,19 +126,34 @@ namespace else if (file_type == regular_symlink_tag) { // regular symlink - fs.write_contents(base, "", ec); - REQUIRE_FALSE(ec); auto base_link = base; - base_link.replace_filename(base.filename().u8string() + "-link"); - vcpkg::Test::create_symlink(base, base_link, ec); + base_link.replace_filename(base.filename().u8string() + "-orig"); + fs.write_contents(base_link, "", ec); + CHECK_EC_ON_FILE(base_link, ec); + vcpkg::Test::create_symlink(base_link, base, ec); } else // type == directory_symlink_tag { // directory symlink - vcpkg::Test::create_directory_symlink(base / "..", base, ec); + auto parent = base; + parent.remove_filename(); + vcpkg::Test::create_directory_symlink(parent, base, ec); } - REQUIRE_FALSE(ec); + CHECK_EC_ON_FILE(base, ec); + REQUIRE(fs::exists(fs.symlink_status(base, ec))); + CHECK_EC_ON_FILE(base, ec); + } + + vcpkg::Files::Filesystem& setup(urbg_t& urbg) + { + auto& fs = vcpkg::Files::get_real_filesystem(); + + std::error_code ec; + fs.create_directory(base_temporary_directory(), ec); + CHECK_EC_ON_FILE(base_temporary_directory(), ec); + + return fs; } } @@ -100,22 +161,83 @@ TEST_CASE ("remove all", "[files]") { auto urbg = get_urbg(0); - fs::path temp_dir = TEMPORARY_DIRECTORY / get_random_filename(urbg); + auto& fs = setup(urbg); - auto& fs = vcpkg::Files::get_real_filesystem(); + fs::path temp_dir = base_temporary_directory() / get_random_filename(urbg); + INFO("temp dir is: " << temp_dir); + + create_directory_tree(urbg, fs, temp_dir, MaxDepth{5}); std::error_code ec; - fs.create_directory(TEMPORARY_DIRECTORY, ec); + fs::path fp; + fs.remove_all(temp_dir, ec, fp); + CHECK_EC_ON_FILE(fp, ec); + + REQUIRE_FALSE(fs.exists(temp_dir, ec)); + CHECK_EC_ON_FILE(temp_dir, ec); +} - REQUIRE_FALSE(ec); +#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) +TEST_CASE ("remove all -- benchmarks", "[files][!benchmark]") +{ + auto urbg = get_urbg(1); + auto& fs = setup(urbg); - INFO("temp dir is: " << temp_dir); + struct + { + urbg_t& urbg; + vcpkg::Files::Filesystem& fs; - create_directory_tree(urbg, fs, 0, temp_dir); + void operator()(Catch::Benchmark::Chronometer& meter, MaxDepth max_depth, AllowSymlinks allow_symlinks) const + { + std::vector<fs::path> temp_dirs; + temp_dirs.resize(meter.runs()); - fs::path fp; - fs.remove_all(temp_dir, ec, fp); - REQUIRE_FALSE(ec); + std::generate(begin(temp_dirs), end(temp_dirs), [&] { + fs::path temp_dir = base_temporary_directory() / get_random_filename(urbg); + create_directory_tree(urbg, fs, temp_dir, max_depth, allow_symlinks); + return temp_dir; + }); + + meter.measure([&](int run) { + std::error_code ec; + fs::path fp; + const auto& temp_dir = temp_dirs[run]; + + fs.remove_all(temp_dir, ec, fp); + CHECK_EC_ON_FILE(fp, ec); + }); + + for (const auto& dir : temp_dirs) + { + std::error_code ec; + REQUIRE_FALSE(fs.exists(dir, ec)); + CHECK_EC_ON_FILE(dir, ec); + } + } + } do_benchmark = {urbg, fs}; + + BENCHMARK_ADVANCED("small directory, no symlinks")(Catch::Benchmark::Chronometer meter) + { + do_benchmark(meter, MaxDepth{2}, AllowSymlinks::No); + }; + + BENCHMARK_ADVANCED("large directory, no symlinks")(Catch::Benchmark::Chronometer meter) + { + do_benchmark(meter, MaxDepth{5}, AllowSymlinks::No); + }; - REQUIRE_FALSE(fs.exists(temp_dir)); + if (can_create_symlinks()) + { + BENCHMARK_ADVANCED("small directory, symlinks")(Catch::Benchmark::Chronometer meter) + { + do_benchmark(meter, MaxDepth{2}, AllowSymlinks::Yes); + }; + + BENCHMARK_ADVANCED("large directory, symlinks")(Catch::Benchmark::Chronometer meter) + { + do_benchmark(meter, MaxDepth{5}, AllowSymlinks::Yes); + }; + } } +#endif diff --git a/toolsrc/src/vcpkg-test/util.cpp b/toolsrc/src/vcpkg-test/util.cpp index a80ab36a0..384954b4e 100644 --- a/toolsrc/src/vcpkg-test/util.cpp +++ b/toolsrc/src/vcpkg-test/util.cpp @@ -74,14 +74,15 @@ namespace vcpkg::Test return m_ret.value_or_exit(VCPKG_LINE_INFO); } - static bool system_allows_symlinks() + static AllowSymlinks internal_can_create_symlinks() noexcept { -#if defined(_WIN32) - if (!__cpp_lib_filesystem) - { - return false; - } - +#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_NONE + return AllowSymlinks::No; +#elif FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_UNIX + return AllowSymlinks::Yes; +#elif !defined(_WIN32) // FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD + return AllowSymlinks::Yes; +#else HKEY key; bool allow_symlinks = true; @@ -96,13 +97,14 @@ namespace vcpkg::Test if (status == ERROR_SUCCESS) RegCloseKey(key); - return allow_symlinks; -#else - return true; + return allow_symlinks ? AllowSymlinks::Yes : AllowSymlinks::No; #endif } + const static AllowSymlinks CAN_CREATE_SYMLINKS = internal_can_create_symlinks(); + + AllowSymlinks can_create_symlinks() noexcept { return CAN_CREATE_SYMLINKS; } - static fs::path internal_temporary_directory() + static fs::path internal_base_temporary_directory() { #if defined(_WIN32) wchar_t* tmp = static_cast<wchar_t*>(std::calloc(32'767, 2)); @@ -122,18 +124,19 @@ namespace vcpkg::Test #endif } - const bool SYMLINKS_ALLOWED = system_allows_symlinks(); - const fs::path TEMPORARY_DIRECTORY = internal_temporary_directory(); + const static fs::path BASE_TEMPORARY_DIRECTORY = internal_base_temporary_directory(); -#if FILESYSTEM_SYMLINK == FILSYSTEM_SYMLINK_NONE - constexpr inline char no_filesystem_message[] = + const fs::path& base_temporary_directory() noexcept { return BASE_TEMPORARY_DIRECTORY; } + +#if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_NONE + constexpr char no_filesystem_message[] = "<filesystem> doesn't exist; on windows, we don't attempt to use the win32 calls to create symlinks"; #endif void create_symlink(const fs::path& target, const fs::path& file, std::error_code& ec) { #if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD - if (SYMLINKS_ALLOWED) + if (can_create_symlinks()) { std::filesystem::path targetp = target.native(); std::filesystem::path filep = file.native(); @@ -157,12 +160,12 @@ namespace vcpkg::Test void create_directory_symlink(const fs::path& target, const fs::path& file, std::error_code& ec) { #if FILESYSTEM_SYMLINK == FILESYSTEM_SYMLINK_STD - if (SYMLINKS_ALLOWED) + if (can_create_symlinks()) { std::filesystem::path targetp = target.native(); std::filesystem::path filep = file.native(); - std::filesystem::create_symlink(targetp, filep); + std::filesystem::create_directory_symlink(targetp, filep); } else { diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 46ec8c013..3fdbd0d3e 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -125,12 +125,8 @@ static void inner(const VcpkgCmdArguments& args) auto default_vs_path = System::get_environment_variable("VCPKG_VISUAL_STUDIO_PATH").value_or(""); - - - const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir, - vcpkg_scripts_root_dir, - default_vs_path, - args.overlay_triplets.get()); + const Expected<VcpkgPaths> expected_paths = + VcpkgPaths::create(vcpkg_root_dir, vcpkg_scripts_root_dir, default_vs_path, args.overlay_triplets.get()); Checks::check_exit(VCPKG_LINE_INFO, !expected_paths.error(), "Error: Invalid vcpkg root directory %s: %s", @@ -143,7 +139,11 @@ static void inner(const VcpkgCmdArguments& args) #else const int exit_code = chdir(paths.root.c_str()); #endif - Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working directory to the vcpkg root directory failed. Did you incorrectly define the VCPKG_ROOT environment variable, or did you mistakenly create a file named .vcpkg-root somewhere?"); + Checks::check_exit( + VCPKG_LINE_INFO, + exit_code == 0, + "Changing the working directory to the vcpkg root directory failed. Did you incorrectly define the VCPKG_ROOT " + "environment variable, or did you mistakenly create a file named .vcpkg-root somewhere?"); if (args.command == "install" || args.command == "remove" || args.command == "export" || args.command == "update") { diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 6c6945e44..4a0a52f06 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -23,29 +23,35 @@ namespace fs::detail { - file_status symlink_status_t::operator()(const path& p, std::error_code& ec) const noexcept + static file_status status_implementation(bool follow_symlinks, const path& p, std::error_code& ec) { #if defined(_WIN32) - static_cast<void>(ec); - - /* - do not find the permissions of the file -- it's unnecessary for the - things that vcpkg does. - if one were to add support for this in the future, one should look - into GetFileSecurityW - */ - perms permissions = perms::unknown; - WIN32_FILE_ATTRIBUTE_DATA file_attributes; file_type ft = file_type::unknown; + perms permissions = perms::unknown; if (!GetFileAttributesExW(p.c_str(), GetFileExInfoStandard, &file_attributes)) { - ft = file_type::not_found; + const auto err = GetLastError(); + if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) + { + ft = file_type::not_found; + } + else + { + ec.assign(err, std::system_category()); + } } - else if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) + else if (!follow_symlinks && file_attributes.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - // check for reparse point -- if yes, then symlink - ft = file_type::symlink; + // this also gives junctions file_type::directory_symlink + if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + ft = file_type::directory_symlink; + } + else + { + ft = file_type::symlink; + } } else if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { @@ -57,17 +63,60 @@ namespace fs::detail ft = file_type::regular; } + if (file_attributes.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + { + constexpr auto all_write = perms::group_write | perms::owner_write | perms::others_write; + permissions = perms::all & ~all_write; + } + else if (ft != file_type::none && ft != file_type::none) + { + permissions = perms::all; + } + return file_status(ft, permissions); #else - return stdfs::symlink_status(p, ec); + auto result = symlink ? stdfs::symlink_status(p, ec) : stdfs::status(p, ec); + // libstdc++ doesn't correctly not-set ec on nonexistent paths + if (ec.value() == ENOENT) + { + ec.clear(); + result = file_status(file_type::not_found, perms::unknown); + } + return result; +#endif + } + + file_status status_t::operator()(const path& p, std::error_code& ec) const noexcept + { + return status_implementation(false, p, ec); + } + file_status status_t::operator()(vcpkg::LineInfo li, const path& p) const noexcept + { + std::error_code ec; + auto result = (*this)(p, ec); + if (ec) vcpkg::Checks::exit_with_message(li, "error getting status of path %s: %s", p.string(), ec.message()); + + return result; + } + file_status status_t::operator()(const path& p) const + { +#if defined(_WIN32) + return (*this)(VCPKG_LINE_INFO, p); +#else + return fs::stdfs::status(p); #endif } - file_status symlink_status_t::operator()(const path& p, vcpkg::LineInfo li) const noexcept + file_status symlink_status_t::operator()(const path& p, std::error_code& ec) const noexcept + { + return status_implementation(true, p, ec); + } + + file_status symlink_status_t::operator()(vcpkg::LineInfo li, const path& p) const noexcept { std::error_code ec; - auto result = symlink_status(p, ec); + auto result = (*this)(p, ec); if (ec) vcpkg::Checks::exit_with_message(li, "error getting status of path %s: %s", p.string(), ec.message()); return result; @@ -78,6 +127,48 @@ namespace vcpkg::Files { static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])"); + namespace + { + // does _not_ follow symlinks + void set_writeable(const fs::path& path, std::error_code& ec) noexcept + { +#if defined(_WIN32) + auto const file_name = path.c_str(); + WIN32_FILE_ATTRIBUTE_DATA attributes; + if (!GetFileAttributesExW(file_name, GetFileExInfoStandard, &attributes)) + { + ec.assign(GetLastError(), std::system_category()); + return; + } + + auto dw_attributes = attributes.dwFileAttributes; + dw_attributes &= ~FILE_ATTRIBUTE_READONLY; + if (!SetFileAttributesW(file_name, dw_attributes)) + { + ec.assign(GetLastError(), std::system_category()); + } +#else + struct stat s; + if (lstat(path.c_str(), &s)) + { + ec.assign(errno, std::system_category()); + return; + } + + auto mode = s.st_mode; + // if the file is a symlink, perms don't matter + if (!(mode & S_IFLNK)) + { + mode |= S_IWUSR; + if (chmod(path.c_str(), mode)) + { + ec.assign(errno, std::system_category()); + } + } +#endif + } + } + std::string Filesystem::read_contents(const fs::path& path, LineInfo linfo) const { auto maybe_contents = this->read_contents(path); @@ -110,6 +201,25 @@ namespace vcpkg::Files return r; } + bool Filesystem::exists(const fs::path& path, std::error_code& ec) const + { + return fs::exists(this->symlink_status(path, ec)); + } + + bool Filesystem::exists(LineInfo li, const fs::path& path) const + { + std::error_code ec; + auto result = this->exists(path, ec); + if (ec) Checks::exit_with_message(li, "error checking existence of file %s: %s", path.u8string(), ec.message()); + return result; + } + bool Filesystem::exists(const fs::path& path) const + { + std::error_code ec; + // drop this on the floor, for compatibility with existing code + return exists(path, ec); + } + void Filesystem::write_lines(const fs::path& path, const std::vector<std::string>& lines, LineInfo linfo) { std::error_code ec; @@ -117,12 +227,12 @@ namespace vcpkg::Files if (ec) Checks::exit_with_message(linfo, "error writing lines: %s: %s", path.u8string(), ec.message()); } - std::uintmax_t Filesystem::remove_all(const fs::path& path, LineInfo li) + void Filesystem::remove_all(const fs::path& path, LineInfo li) { std::error_code ec; fs::path failure_point; - const auto result = this->remove_all(path, ec, failure_point); + this->remove_all(path, ec, failure_point); if (ec) { @@ -132,8 +242,6 @@ namespace vcpkg::Files failure_point.string(), ec.message()); } - - return result; } struct RealFilesystem final : Filesystem @@ -174,6 +282,9 @@ namespace vcpkg::Files std::string line; while (std::getline(file_stream, line)) { + // Remove the trailing \r to accomodate Windows line endings. + if ((!line.empty()) && (line.back() == '\r')) line.pop_back(); + output.push_back(line); } file_stream.close(); @@ -184,7 +295,7 @@ namespace vcpkg::Files const std::string& filename) const override { fs::path current_dir = starting_dir; - if (exists(current_dir / filename)) + if (exists(VCPKG_LINE_INFO, current_dir / filename)) { return current_dir; } @@ -209,7 +320,7 @@ namespace vcpkg::Files current_dir = std::move(parent); const fs::path candidate = current_dir / filename; - if (exists(candidate)) + if (exists(VCPKG_LINE_INFO, candidate)) { return current_dir; } @@ -327,146 +438,113 @@ namespace vcpkg::Files #endif } virtual bool remove(const fs::path& path, std::error_code& ec) override { return fs::stdfs::remove(path, ec); } - virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) override + virtual void remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) override { /* - does not use the std::filesystem call since it is buggy, and can - have spurious errors before VS 2017 update 6, and on later versions - (as well as on macOS and Linux), this is just as fast and will have - fewer spurious errors due to locks. + does not use the std::experimental::filesystem call since this is + quite a bit faster, and also supports symlinks */ - /* - `remove` doesn't actually remove anything -- it simply moves the - files into a parent directory (which ends up being at `path`), - and then inserts `actually_remove{current_path}` into the work - queue. - */ struct remove { - struct tld + struct ErrorInfo : Util::ResourceBase { - const fs::path& tmp_directory; - std::uint64_t index; - - std::atomic<std::uintmax_t>& files_deleted; - - std::mutex& ec_mutex; - std::error_code& ec; - fs::path& failure_point; + std::error_code ec; + fs::path failure_point; }; - - struct actually_remove; - using queue = WorkQueue<actually_remove, tld>; - /* if `current_path` is a directory, first `remove`s all - elements of the directory, then calls remove. + elements of the directory, then removes current_path. - else, just calls remove. + else if `current_path` exists, removes current_path + + else does nothing */ - struct actually_remove + static void do_remove(const fs::path& current_path, ErrorInfo& err) { - fs::path current_path; + std::error_code ec; + const auto path_status = fs::symlink_status(current_path, ec); + if (check_ec(ec, current_path, err)) return; + if (!fs::exists(path_status)) return; - void operator()(tld& info, const queue& queue) const - { - std::error_code ec; - const auto path_type = fs::symlink_status(current_path, ec).type(); + const auto path_type = path_status.type(); - if (check_ec(ec, info, queue, current_path)) return; + if ((path_status.permissions() & fs::perms::owner_write) != fs::perms::owner_write) + { + set_writeable(current_path, ec); + if (check_ec(ec, current_path, err)) return; + } - if (path_type == fs::file_type::directory) + if (path_type == fs::file_type::directory) + { + for (const auto& entry : fs::stdfs::directory_iterator(current_path)) { - for (const auto& entry : fs::stdfs::directory_iterator(current_path)) - { - remove{}(entry, info, queue); - } + do_remove(entry, err); + if (err.ec) return; } - - if (fs::stdfs::remove(current_path, ec)) +#if defined(_WIN32) + if (!RemoveDirectoryW(current_path.c_str())) { - info.files_deleted.fetch_add(1, std::memory_order_relaxed); + ec.assign(GetLastError(), std::system_category()); } - else +#else + if (rmdir(current_path.c_str())) { - check_ec(ec, info, queue, current_path); + ec.assign(errno, std::system_category()); } +#endif } - }; - - static bool check_ec(const std::error_code& ec, - tld& info, - const queue& queue, - const fs::path& failure_point) - { - if (ec) +#if defined(_WIN32) + else if (path_type == fs::file_type::directory_symlink) { - queue.terminate(); - - auto lck = std::unique_lock<std::mutex>(info.ec_mutex); - if (!info.ec) + if (!RemoveDirectoryW(current_path.c_str())) { - info.ec = ec; - info.failure_point = failure_point; + ec.assign(GetLastError(), std::system_category()); } - - return true; } else { - return false; + if (!DeleteFileW(current_path.c_str())) + { + ec.assign(GetLastError(), std::system_category()); + } } +#else + else + { + if (unlink(current_path.c_str())) + { + ec.assign(errno, std::system_category()); + } + } +#endif + + check_ec(ec, current_path, err); } - void operator()(const fs::path& current_path, tld& info, const queue& queue) const + static bool check_ec(const std::error_code& ec, const fs::path& current_path, ErrorInfo& err) { - std::error_code ec; - - const auto tmp_name = Strings::b32_encode(info.index++); - const auto tmp_path = info.tmp_directory / tmp_name; - - fs::stdfs::rename(current_path, tmp_path, ec); - if (check_ec(ec, info, queue, current_path)) return; + if (ec) + { + err.ec = ec; + err.failure_point = current_path; - queue.enqueue_action(actually_remove{std::move(tmp_path)}); + return true; + } + else + { + return false; + } } }; - const auto path_type = fs::symlink_status(path, ec).type(); - - std::atomic<std::uintmax_t> files_deleted{0}; - - if (path_type == fs::file_type::directory) - { - std::uint64_t index = 0; - std::mutex ec_mutex; - - auto const tld_gen = [&] { - index += static_cast<std::uint64_t>(1) << 32; - return remove::tld{path, index, files_deleted, ec_mutex, ec, failure_point}; - }; - - remove::queue queue{4, VCPKG_LINE_INFO, tld_gen}; - - // note: we don't actually start the queue running until the - // `join()`. This allows us to rename all the top-level files in - // peace, so that we don't get collisions. - auto main_tld = tld_gen(); - for (const auto& entry : fs::stdfs::directory_iterator(path)) - { - remove{}(entry, main_tld, queue); - } - - queue.join(VCPKG_LINE_INFO); - } - /* we need to do backoff on the removal of the top level directory, - since we need to place all moved files into that top level - directory, and so we can only delete the directory after all the + so we can only delete the directory after all the lower levels have been deleted. */ + + remove::ErrorInfo err; for (int backoff = 0; backoff < 5; ++backoff) { if (backoff) @@ -476,16 +554,16 @@ namespace vcpkg::Files std::this_thread::sleep_for(backoff_time); } - if (fs::stdfs::remove(path, ec)) + remove::do_remove(path, err); + if (!err.ec) { - files_deleted.fetch_add(1, std::memory_order_relaxed); break; } } - return files_deleted; + ec = std::move(err.ec); + failure_point = std::move(err.failure_point); } - virtual bool exists(const fs::path& path) const override { return fs::stdfs::exists(path); } virtual bool is_directory(const fs::path& path) const override { return fs::stdfs::is_directory(path); } virtual bool is_regular_file(const fs::path& path) const override { return fs::stdfs::is_regular_file(path); } virtual bool is_empty(const fs::path& path) const override { return fs::stdfs::is_empty(path); } @@ -563,7 +641,7 @@ namespace vcpkg::Files for (auto&& ext : EXTS) { auto p = fs::u8path(base + ext.c_str()); - if (Util::find(ret, p) == ret.end() && this->exists(p)) + if (Util::find(ret, p) == ret.end() && this->exists(VCPKG_LINE_INFO, p)) { ret.push_back(p); Debug::print("Found path: ", p.u8string(), '\n'); diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp index 9be2310c6..ef194f9f3 100644 --- a/toolsrc/src/vcpkg/binaryparagraph.cpp +++ b/toolsrc/src/vcpkg/binaryparagraph.cpp @@ -56,7 +56,7 @@ namespace vcpkg BinaryParagraph::BinaryParagraph() = default; - BinaryParagraph::BinaryParagraph(std::unordered_map<std::string, std::string> fields) + BinaryParagraph::BinaryParagraph(Parse::RawParagraph fields) { using namespace vcpkg::Parse; diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 69a313c1a..6f14f46f8 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -64,8 +64,7 @@ namespace vcpkg::Build::Command std::set<std::string> features_as_set(full_spec.features.begin(), full_spec.features.end());
features_as_set.emplace("core");
- const Build::BuildPackageConfig build_config{
- scfl, spec.triplet(), build_package_options, features_as_set};
+ const Build::BuildPackageConfig build_config{scfl, spec.triplet(), build_package_options, features_as_set};
const auto build_timer = Chrono::ElapsedTimer::create_started();
const auto result = Build::build_package(paths, build_config, status_db);
@@ -304,19 +303,17 @@ namespace vcpkg::Build const std::set<std::string>& feature_list,
const Triplet& triplet)
{
- return Util::fmap_flatten(
- feature_list,
- [&](std::string const& feature) -> std::vector<Features> {
- if (feature == "core")
- {
- return filter_dependencies_to_features(scf.core_paragraph->depends, triplet);
- }
+ return Util::fmap_flatten(feature_list, [&](std::string const& feature) -> std::vector<Features> {
+ if (feature == "core")
+ {
+ return filter_dependencies_to_features(scf.core_paragraph->depends, triplet);
+ }
- auto maybe_feature = scf.find_feature(feature);
- Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value());
+ auto maybe_feature = scf.find_feature(feature);
+ Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value());
- return filter_dependencies_to_features(maybe_feature.get()->depends, triplet);
- });
+ return filter_dependencies_to_features(maybe_feature.get()->depends, triplet);
+ });
}
static std::vector<std::string> get_dependency_names(const SourceControlFile& scf,
@@ -324,10 +321,7 @@ namespace vcpkg::Build const Triplet& triplet)
{
return Util::fmap(get_dependencies(scf, feature_list, triplet),
- [&](const Features& feat) {
- return feat.name;
- }
- );
+ [&](const Features& feat) { return feat.name; });
}
static std::vector<FeatureSpec> compute_required_feature_specs(const BuildPackageConfig& config,
@@ -335,8 +329,7 @@ namespace vcpkg::Build {
const Triplet& triplet = config.triplet;
- const std::vector<std::string> dep_strings =
- get_dependency_names(config.scf, config.feature_list, triplet);
+ const std::vector<std::string> dep_strings = get_dependency_names(config.scf, config.feature_list, triplet);
auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet);
Util::sort_unique_erase(dep_fspecs);
@@ -439,8 +432,7 @@ namespace vcpkg::Build {
const Toolset& toolset = paths.get_toolset(pre_build_info);
const fs::path& cmake_exe_path = paths.get_tool_exe(Tools::CMAKE);
- std::vector<System::CMakeVariable> variables =
- get_cmake_vars(paths, config, triplet, toolset);
+ std::vector<System::CMakeVariable> variables = get_cmake_vars(paths, config, triplet, toolset);
const std::string cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, paths.ports_cmake, variables);
@@ -571,13 +563,10 @@ namespace vcpkg::Build const auto timer = Chrono::ElapsedTimer::create_started();
- std::string command =
- make_build_cmd(paths, pre_build_info, config, triplet);
- std::unordered_map<std::string, std::string> env =
- make_env_passthrough(pre_build_info);
+ std::string command = make_build_cmd(paths, pre_build_info, config, triplet);
+ std::unordered_map<std::string, std::string> env = make_env_passthrough(pre_build_info);
- const int return_code =
- System::cmd_execute_clean(command, env);
+ const int return_code = System::cmd_execute_clean(command, env);
const auto buildtimeus = timer.microseconds();
const auto spec_string = spec.to_string();
@@ -864,8 +853,7 @@ namespace vcpkg::Build AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi});
}
- const auto pre_build_info =
- PreBuildInfo::from_triplet_file(paths, triplet, config.scfl);
+ const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet, config.scfl);
auto maybe_abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis);
@@ -1021,7 +1009,7 @@ namespace vcpkg::Build Commands::Version::version());
}
- static BuildInfo inner_create_buildinfo(std::unordered_map<std::string, std::string> pgh)
+ static BuildInfo inner_create_buildinfo(Parse::RawParagraph pgh)
{
Parse::ParagraphParser parser(std::move(pgh));
@@ -1078,8 +1066,7 @@ namespace vcpkg::Build BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath)
{
- const Expected<std::unordered_map<std::string, std::string>> pghs =
- Paragraphs::get_single_paragraph(fs, filepath);
+ const Expected<Parse::RawParagraph> pghs = Paragraphs::get_single_paragraph(fs, filepath);
Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package");
return inner_create_buildinfo(*pghs.get());
}
@@ -1098,14 +1085,11 @@ namespace vcpkg::Build if (port)
{
- args.emplace_back(
- "CMAKE_ENV_OVERRIDES_FILE",
- port.value_or_exit(VCPKG_LINE_INFO).source_location / "environment-overrides.cmake");
+ args.emplace_back("CMAKE_ENV_OVERRIDES_FILE",
+ port.value_or_exit(VCPKG_LINE_INFO).source_location / "environment-overrides.cmake");
}
- const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
- ports_cmake_script_path,
- args);
+ const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path, ports_cmake_script_path, args);
const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake);
Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, ec_data.output);
@@ -1137,51 +1121,49 @@ namespace vcpkg::Build {
switch (maybe_option->second)
{
- case VcpkgTripletVar::TARGET_ARCHITECTURE :
- pre_build_info.target_architecture = variable_value;
- break;
- case VcpkgTripletVar::CMAKE_SYSTEM_NAME :
- pre_build_info.cmake_system_name = variable_value;
- break;
- case VcpkgTripletVar::CMAKE_SYSTEM_VERSION :
- pre_build_info.cmake_system_version = variable_value;
- break;
- case VcpkgTripletVar::PLATFORM_TOOLSET :
- pre_build_info.platform_toolset =
- variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::VISUAL_STUDIO_PATH :
- pre_build_info.visual_studio_path =
- variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
- break;
- case VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE :
- pre_build_info.external_toolchain_file =
- variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
- break;
- case VcpkgTripletVar::BUILD_TYPE :
- if (variable_value.empty())
- pre_build_info.build_type = nullopt;
- else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
- pre_build_info.build_type = ConfigurationType::DEBUG;
- else if (Strings::case_insensitive_ascii_equals(variable_value, "release"))
- pre_build_info.build_type = ConfigurationType::RELEASE;
- else
- Checks::exit_with_message(
+ case VcpkgTripletVar::TARGET_ARCHITECTURE:
+ pre_build_info.target_architecture = variable_value;
+ break;
+ case VcpkgTripletVar::CMAKE_SYSTEM_NAME: pre_build_info.cmake_system_name = variable_value; break;
+ case VcpkgTripletVar::CMAKE_SYSTEM_VERSION:
+ pre_build_info.cmake_system_version = variable_value;
+ break;
+ case VcpkgTripletVar::PLATFORM_TOOLSET:
+ pre_build_info.platform_toolset =
+ variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ break;
+ case VcpkgTripletVar::VISUAL_STUDIO_PATH:
+ pre_build_info.visual_studio_path =
+ variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
+ break;
+ case VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE:
+ pre_build_info.external_toolchain_file =
+ variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ break;
+ case VcpkgTripletVar::BUILD_TYPE:
+ if (variable_value.empty())
+ pre_build_info.build_type = nullopt;
+ else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
+ pre_build_info.build_type = ConfigurationType::DEBUG;
+ else if (Strings::case_insensitive_ascii_equals(variable_value, "release"))
+ pre_build_info.build_type = ConfigurationType::RELEASE;
+ else
+ Checks::exit_with_message(
VCPKG_LINE_INFO, "Unknown setting for VCPKG_BUILD_TYPE: %s", variable_value);
- break;
- case VcpkgTripletVar::ENV_PASSTHROUGH :
- pre_build_info.passthrough_env_vars = Strings::split(variable_value, ";");
- break;
- case VcpkgTripletVar::EXTERNAL_FILES :
- pre_build_info.external_files =
- get_external_file_hashes(
- paths,
- Util::fmap(Strings::split(variable_value, ";"),
- [](const std::string& path)
- {
- return fs::path{path};
- }));
- break;
+ break;
+ case VcpkgTripletVar::ENV_PASSTHROUGH :
+ pre_build_info.passthrough_env_vars = Strings::split(variable_value, ";");
+ break;
+ case VcpkgTripletVar::EXTERNAL_FILES :
+ pre_build_info.external_files =
+ get_external_file_hashes(
+ paths,
+ Util::fmap(Strings::split(variable_value, ";"),
+ [](const std::string& path)
+ {
+ return fs::path{path};
+ }));
+ break;
}
}
else
@@ -1190,8 +1172,7 @@ namespace vcpkg::Build }
}
- pre_build_info.triplet_abi_tag =
- get_triplet_abi(paths, pre_build_info, triplet);
+ pre_build_info.triplet_abi_tag = get_triplet_abi(paths, pre_build_info, triplet);
return pre_build_info;
}
diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp index c321de3b5..4c49db004 100644 --- a/toolsrc/src/vcpkg/commands.cache.cpp +++ b/toolsrc/src/vcpkg/commands.cache.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Commands::Cache std::vector<BinaryParagraph> output; for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages)) { - const Expected<std::unordered_map<std::string, std::string>> pghs = + const Expected<Parse::RawParagraph> pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); if (const auto p = pghs.get()) { diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index b4290baab..f0f162f5c 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -236,12 +236,7 @@ namespace vcpkg::Commands::CI { auto triplet = p->spec.triplet(); - const Build::BuildPackageConfig build_config{ - *scfl, - triplet, - build_options, - p->feature_list - }; + const Build::BuildPackageConfig build_config{*scfl, triplet, build_options, p->feature_list}; auto dependency_abis = Util::fmap(p->computed_dependencies, [&](const PackageSpec& spec) -> Build::AbiEntry { @@ -253,14 +248,7 @@ namespace vcpkg::Commands::CI return {spec.name(), it->second}; }); const auto& pre_build_info = pre_build_info_cache.get_lazy( - triplet, - [&]() { - return Build::PreBuildInfo::from_triplet_file( - paths, - triplet, - *scfl); - } - ); + triplet, [&]() { return Build::PreBuildInfo::from_triplet_file(paths, triplet, *scfl); }); auto maybe_tag_and_file = Build::compute_abi_tag(paths, build_config, pre_build_info, dependency_abis); @@ -362,7 +350,7 @@ namespace vcpkg::Commands::CI } StatusParagraphs status_db = database_load_check(paths); - + Dependencies::PathsPortFileProvider provider(paths, args.overlay_ports.get()); const Build::BuildPackageOptions install_plan_options = { diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp index 8394e0166..7c04a5a2f 100644 --- a/toolsrc/src/vcpkg/commands.dependinfo.cpp +++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp @@ -5,12 +5,12 @@ #include <vcpkg/base/util.h>
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
-#include <vcpkg/paragraphs.h>
#include <vcpkg/packagespec.h>
+#include <vcpkg/paragraphs.h>
-#include <vector>
#include <memory>
#include <vcpkg/dependencies.h>
+#include <vector>
using vcpkg::Dependencies::PathsPortFileProvider;
@@ -171,14 +171,14 @@ namespace vcpkg::Commands::DependInfo {
if (requested_feature_name == "*")
{
- for (auto &&feature_paragraph : (*source_control_file)->feature_paragraphs)
+ for (auto&& feature_paragraph : (*source_control_file)->feature_paragraphs)
{
collected_features.insert(std::addressof(Util::as_const(*feature_paragraph)));
}
continue;
}
auto maybe_feature = (*source_control_file)->find_feature(requested_feature_name);
- if (auto &&feature_paragraph = maybe_feature.get())
+ if (auto&& feature_paragraph = maybe_feature.get())
{
collected_features.insert(std::addressof(Util::as_const(*feature_paragraph)));
}
@@ -197,7 +197,8 @@ namespace vcpkg::Commands::DependInfo {
for (const auto& dependency : feature_paragraph->depends)
{
- build_dependencies_list(packages_to_keep, dependency.depend.name, source_control_files, switches);
+ build_dependencies_list(
+ packages_to_keep, dependency.depend.name, source_control_files, switches);
}
}
}
@@ -214,9 +215,9 @@ namespace vcpkg::Commands::DependInfo // TODO: Optimize implementation, current implementation needs to load all ports from disk which is too slow.
PathsPortFileProvider provider(paths, args.overlay_ports.get());
- auto source_control_files = Util::fmap(provider.load_all_control_files(), [](auto&& scfl) -> const SourceControlFile * {
- return scfl->source_control_file.get();
- });
+ auto source_control_files =
+ Util::fmap(provider.load_all_control_files(),
+ [](auto&& scfl) -> const SourceControlFile* { return scfl->source_control_file.get(); });
if (args.command_arguments.size() >= 1)
{
diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp index 40f5a434c..c18d788c5 100644 --- a/toolsrc/src/vcpkg/commands.import.cpp +++ b/toolsrc/src/vcpkg/commands.import.cpp @@ -108,7 +108,7 @@ namespace vcpkg::Commands::Import const fs::path include_directory(args.command_arguments[1]); const fs::path project_directory(args.command_arguments[2]); - const Expected<std::unordered_map<std::string, std::string>> pghs = + const Expected<Parse::RawParagraph> pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path); Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp index 3d8387ee1..943233502 100644 --- a/toolsrc/src/vcpkg/commands.search.cpp +++ b/toolsrc/src/vcpkg/commands.search.cpp @@ -2,12 +2,12 @@ #include <vcpkg/base/system.print.h> #include <vcpkg/commands.h> +#include <vcpkg/dependencies.h> #include <vcpkg/globalstate.h> #include <vcpkg/help.h> #include <vcpkg/paragraphs.h> #include <vcpkg/sourceparagraph.h> #include <vcpkg/vcpkglib.h> -#include <vcpkg/dependencies.h> using vcpkg::Dependencies::PathsPortFileProvider; @@ -67,9 +67,9 @@ namespace vcpkg::Commands::Search const bool full_description = Util::Sets::contains(options.switches, OPTION_FULLDESC); PathsPortFileProvider provider(paths, args.overlay_ports.get()); - auto source_paragraphs = Util::fmap(provider.load_all_control_files(), [](auto&& port) -> const SourceControlFile * { - return port->source_control_file.get(); - }); + auto source_paragraphs = + Util::fmap(provider.load_all_control_files(), + [](auto&& port) -> const SourceControlFile* { return port->source_control_file.get(); }); if (args.command_arguments.empty()) { diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 50c310dbb..c175cc86f 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -108,9 +108,8 @@ namespace vcpkg::Dependencies static ClusterSource cluster_from_scf(const SourceControlFileLocation& scfl, Triplet t) { ClusterSource ret; - ret.build_edges.emplace("core", - filter_dependencies_to_specs(scfl.source_control_file->core_paragraph->depends, - t)); + ret.build_edges.emplace("core", + filter_dependencies_to_specs(scfl.source_control_file->core_paragraph->depends, t)); for (const auto& feature : scfl.source_control_file->feature_paragraphs) ret.build_edges.emplace(feature->name, filter_dependencies_to_specs(feature->depends, t)); @@ -123,22 +122,23 @@ namespace vcpkg::Dependencies const PortFileProvider& m_provider; }; - std::string to_output_string(RequestType request_type, - const CStringView s, - const Build::BuildPackageOptions& options, + std::string to_output_string(RequestType request_type, + const CStringView s, + const Build::BuildPackageOptions& options, const fs::path& install_port_path, const fs::path& default_port_path) { - if (!default_port_path.empty() - && !Strings::case_insensitive_ascii_starts_with(install_port_path.u8string(), - default_port_path.u8string())) + if (!default_port_path.empty() && + !Strings::case_insensitive_ascii_starts_with(install_port_path.u8string(), default_port_path.u8string())) { const char* const from_head = options.use_head_version == Build::UseHeadVersion::YES ? " (from HEAD)" : ""; switch (request_type) { - case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s -- %s", s, from_head, install_port_path.u8string()); - case RequestType::USER_REQUESTED: return Strings::format(" %s%s -- %s", s, from_head, install_port_path.u8string()); - default: Checks::unreachable(VCPKG_LINE_INFO); + case RequestType::AUTO_SELECTED: + return Strings::format(" * %s%s -- %s", s, from_head, install_port_path.u8string()); + case RequestType::USER_REQUESTED: + return Strings::format(" %s%s -- %s", s, from_head, install_port_path.u8string()); + default: Checks::unreachable(VCPKG_LINE_INFO); } } return to_output_string(request_type, s, options); @@ -152,7 +152,7 @@ namespace vcpkg::Dependencies switch (request_type) { - case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s", s, from_head); + case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s", s, from_head); case RequestType::USER_REQUESTED: return Strings::format(" %s%s", s, from_head); default: Checks::unreachable(VCPKG_LINE_INFO); } @@ -162,7 +162,7 @@ namespace vcpkg::Dependencies { switch (request_type) { - case RequestType::AUTO_SELECTED: return Strings::format(" * %s", s); + case RequestType::AUTO_SELECTED: return Strings::format(" * %s", s); case RequestType::USER_REQUESTED: return Strings::format(" %s", s); default: Checks::unreachable(VCPKG_LINE_INFO); } @@ -293,7 +293,8 @@ namespace vcpkg::Dependencies MapPortFileProvider::MapPortFileProvider(const std::unordered_map<std::string, SourceControlFileLocation>& map) : ports(map) - {} + { + } Optional<const SourceControlFileLocation&> MapPortFileProvider::get_control_file(const std::string& spec) const { @@ -304,11 +305,11 @@ namespace vcpkg::Dependencies std::vector<const SourceControlFileLocation*> MapPortFileProvider::load_all_control_files() const { - return Util::fmap(ports, [](auto&& kvpair) -> const SourceControlFileLocation * { return &kvpair.second; }); + return Util::fmap(ports, [](auto&& kvpair) -> const SourceControlFileLocation* { return &kvpair.second; }); } PathsPortFileProvider::PathsPortFileProvider(const vcpkg::VcpkgPaths& paths, - const std::vector<std::string>* ports_dirs_paths) + const std::vector<std::string>* ports_dirs_paths) : filesystem(paths.get_filesystem()) { if (ports_dirs_paths) @@ -325,7 +326,7 @@ namespace vcpkg::Dependencies overlay.string()); Checks::check_exit(VCPKG_LINE_INFO, - fs::stdfs::is_directory(overlay), + fs::is_directory(status(overlay)), "Error: Path \"%s\" must be a directory", overlay.string()); @@ -354,7 +355,7 @@ namespace vcpkg::Dependencies { if (scf->get()->core_paragraph->name == spec) { - SourceControlFileLocation scfl{ std::move(*scf), ports_dir }; + SourceControlFileLocation scfl{std::move(*scf), ports_dir}; auto it = cache.emplace(spec, std::move(scfl)); return it.first->second; } @@ -362,9 +363,8 @@ namespace vcpkg::Dependencies else { vcpkg::print_error_message(maybe_scf.error()); - Checks::exit_with_message(VCPKG_LINE_INFO, - "Error: Failed to load port from %s", - spec, ports_dir.u8string()); + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Failed to load port from %s", spec, ports_dir.u8string()); } } @@ -373,7 +373,7 @@ namespace vcpkg::Dependencies { if (scf->get()->core_paragraph->name == spec) { - SourceControlFileLocation scfl{ std::move(*scf), ports_dir / spec }; + SourceControlFileLocation scfl{std::move(*scf), ports_dir / spec}; auto it = cache.emplace(spec, std::move(scfl)); return it.first->second; } @@ -399,7 +399,7 @@ namespace vcpkg::Dependencies auto port_name = scf->get()->core_paragraph->name; if (cache.find(port_name) == cache.end()) { - SourceControlFileLocation scfl{ std::move(*scf), ports_dir }; + SourceControlFileLocation scfl{std::move(*scf), ports_dir}; auto it = cache.emplace(port_name, std::move(scfl)); ret.emplace_back(&it.first->second); } @@ -407,9 +407,8 @@ namespace vcpkg::Dependencies else { vcpkg::print_error_message(maybe_scf.error()); - Checks::exit_with_message(VCPKG_LINE_INFO, - "Error: Failed to load port from %s", - ports_dir.u8string()); + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Failed to load port from %s", ports_dir.u8string()); } continue; } @@ -421,7 +420,7 @@ namespace vcpkg::Dependencies auto port_name = scf->core_paragraph->name; if (cache.find(port_name) == cache.end()) { - SourceControlFileLocation scfl{ std::move(scf), ports_dir / port_name }; + SourceControlFileLocation scfl{std::move(scf), ports_dir / port_name}; auto it = cache.emplace(port_name, std::move(scfl)); ret.emplace_back(&it.first->second); } @@ -772,9 +771,10 @@ namespace vcpkg::Dependencies /// <param name="map">Map of all source control files in the current environment.</param> /// <param name="specs">Feature specifications to resolve dependencies for.</param> /// <param name="status_db">Status of installed packages in the current environment.</param> - std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFileLocation>& map, - const std::vector<FeatureSpec>& specs, - const StatusParagraphs& status_db) + std::vector<AnyAction> create_feature_install_plan( + const std::unordered_map<std::string, SourceControlFileLocation>& map, + const std::vector<FeatureSpec>& specs, + const StatusParagraphs& status_db) { MapPortFileProvider provider(map); return create_feature_install_plan(provider, specs, status_db); @@ -836,9 +836,8 @@ namespace vcpkg::Dependencies { // If it will be transiently uninstalled, we need to issue a full installation command auto* pscfl = p_cluster->source.value_or_exit(VCPKG_LINE_INFO).scfl; - Checks::check_exit(VCPKG_LINE_INFO, - pscfl != nullptr, - "Error: Expected a SourceControlFileLocation to exist"); + Checks::check_exit( + VCPKG_LINE_INFO, pscfl != nullptr, "Error: Expected a SourceControlFileLocation to exist"); auto&& scfl = *pscfl; auto dep_specs = Util::fmap(m_graph_plan->install_graph.adjacency_list(p_cluster), @@ -918,7 +917,9 @@ namespace vcpkg::Dependencies PackageGraph::~PackageGraph() = default; - void print_plan(const std::vector<AnyAction>& action_plan, const bool is_recursive, const fs::path& default_ports_dir) + void print_plan(const std::vector<AnyAction>& action_plan, + const bool is_recursive, + const fs::path& default_ports_dir) { std::vector<const RemovePlanAction*> remove_plans; std::vector<const InstallPlanAction*> rebuilt_plans; @@ -975,13 +976,10 @@ namespace vcpkg::Dependencies static auto actions_to_output_string = [&](const std::vector<const InstallPlanAction*>& v) { return Strings::join("\n", v, [&](const InstallPlanAction* p) { - if (auto * pscfl = p->source_control_file_location.get()) + if (auto* pscfl = p->source_control_file_location.get()) { - return to_output_string(p->request_type, - p->displayname(), - p->build_options, - pscfl->source_location, - default_ports_dir); + return to_output_string( + p->request_type, p->displayname(), p->build_options, pscfl->source_location, default_ports_dir); } return to_output_string(p->request_type, p->displayname(), p->build_options); diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 32af57b39..165f13126 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -331,10 +331,8 @@ namespace vcpkg::Install auto result = [&]() -> Build::ExtendedBuildResult { const auto& scfl = action.source_control_file_location.value_or_exit(VCPKG_LINE_INFO); - const Build::BuildPackageConfig build_config{scfl, - action.spec.triplet(), - action.build_options, - action.feature_list}; + const Build::BuildPackageConfig build_config{ + scfl, action.spec.triplet(), action.build_options, action.feature_list}; return Build::build_package(paths, build_config, status_db); }(); diff --git a/toolsrc/src/vcpkg/logicexpression.cpp b/toolsrc/src/vcpkg/logicexpression.cpp new file mode 100644 index 000000000..0cf08ee03 --- /dev/null +++ b/toolsrc/src/vcpkg/logicexpression.cpp @@ -0,0 +1,268 @@ + +#include "pch.h" + +#include <vcpkg/base/checks.h> +#include <vcpkg/base/system.print.h> +#include <vcpkg/logicexpression.h> + +#include <string> +#include <vector> + +namespace vcpkg +{ + struct ParseError + { + ParseError(int column, std::string line, std::string message) : column(column), line(line), message(message) {} + + const int column; + const std::string line; + const std::string message; + + void print_error() const + { + System::print2(System::Color::error, + "Error: ", + message, + "\n" + " on expression: \"", + line, + "\"\n", + " ", + std::string(column, ' '), + "^\n"); + Checks::exit_fail(VCPKG_LINE_INFO); + } + }; + + // logic expression supports the following : + // primary-expression: + // ( logic-expression ) + // identifier + // identifier: + // alpha-numeric string of characters + // logic-expression: <- this is the entry point + // not-expression + // not-expression | logic-expression + // not-expression & logic-expression + // not-expression: + // ! primary-expression + // primary-expression + // + // | and & have equal precidence and cannot be used together at the same nesting level + // for example a|b&c is not allowd but (a|b)&c and a|(b&c) are allowed. + class ExpressionParser + { + public: + ExpressionParser(const std::string& str, const std::string& evaluation_context) + : raw_text(str), evaluation_context(evaluation_context) + { + go_to_begin(); + + final_result = logic_expression(); + + if (current_iter != raw_text.end()) + { + add_error("Invalid logic expression"); + } + + if (err) + { + err->print_error(); + final_result = false; + } + } + + bool get_result() const { return final_result; } + + bool has_error() const { return err == nullptr; } + + private: + bool final_result; + + std::string::const_iterator current_iter; + const std::string& raw_text; + char current_char; + + const std::string& evaluation_context; + + std::unique_ptr<ParseError> err; + + void add_error(std::string message, int column = -1) + { + // avoid castcading errors by only saving the first + if (!err) + { + if (column < 0) + { + column = current_column(); + } + err = std::make_unique<ParseError>(column, raw_text, message); + } + + // Avoid error loops by skipping to the end + skip_to_end(); + } + + int current_column() const { return static_cast<int>(current_iter - raw_text.begin()); } + + void go_to_begin() + { + current_iter = raw_text.begin(); + current_char = (current_iter != raw_text.end() ? *current_iter : current_char); + + if (current_char == ' ' || current_char == '\t') + { + next_skip_whitespace(); + } + } + void skip_to_end() + { + current_iter = raw_text.end(); + current_char = '\0'; + } + char current() const { return current_char; } + char next() + { + if (current_char != '\0') + { + current_iter++; + current_char = (current_iter != raw_text.end() ? *current_iter : '\0'); + } + return current(); + } + void skip_whitespace() + { + while (current_char == ' ' || current_char == '\t') + { + current_char = next(); + } + } + char next_skip_whitespace() + { + next(); + skip_whitespace(); + return current_char; + } + + static bool is_alphanum(char ch) + { + return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '-'); + } + + bool evaluate_identifier(const std::string name) const + { + return evaluation_context.find(name) != std::string::npos; + } + + // identifier: + // alpha-numeric string of characters + bool identifier_expression() + { + auto curr = current(); + std::string name; + + for (curr = current(); is_alphanum(curr); curr = next()) + { + name += curr; + } + + if (name.empty()) + { + add_error("Invalid logic expression, unexpected character"); + return false; + } + + bool result = evaluate_identifier(name); + skip_whitespace(); + return result; + } + + // not-expression: + // ! primary-expression + // primary-expression + bool not_expression() + { + if (current() == '!') + { + next_skip_whitespace(); + return !primary_expression(); + } + + return primary_expression(); + } + + template<char oper, char other, bool operation(bool, bool)> + bool logic_expression_helper(bool seed) + { + do + { + // Support chains of the operator to avoid breaking backwards compatability + while (next() == oper) + { + }; + seed = operation(not_expression(), seed); + + } while (current() == oper); + + if (current() == other) + { + add_error("Mixing & and | is not allowed, Use () to specify order of operations."); + } + + skip_whitespace(); + return seed; + } + static bool and_helper(bool left, bool right) { return left && right; } + static bool or_helper(bool left, bool right) { return left || right; } + + // logic-expression: <- entry point + // not-expression + // not-expression | logic-expression + // not-expression & logic-expression + bool logic_expression() + { + auto result = not_expression(); + + switch (current()) + { + case '|': + { + return logic_expression_helper<'|', '&', or_helper>(result); + } + case '&': + { + return logic_expression_helper<'&', '|', and_helper>(result); + } + default: return result; + } + } + + // primary-expression: + // ( logic-expression ) + // identifier + bool primary_expression() + { + if (current() == '(') + { + next_skip_whitespace(); + bool result = logic_expression(); + if (current() != ')') + { + add_error("Error: missing closing )"); + return result; + } + next_skip_whitespace(); + return result; + } + + return identifier_expression(); + } + }; + + bool evaluate_expression(const std::string& expression, const std::string& evaluation_context) + { + ExpressionParser parser(expression, evaluation_context); + + return parser.get_result(); + } +} diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index 21ef2c4d9..1232b940a 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -116,7 +116,7 @@ namespace vcpkg::Paragraphs skip_spaces(ch); } - void get_paragraph(char& ch, std::unordered_map<std::string, std::string>& fields) + void get_paragraph(char& ch, RawParagraph& fields) { fields.clear(); std::string fieldname; @@ -141,9 +141,9 @@ namespace vcpkg::Paragraphs } public: - std::vector<std::unordered_map<std::string, std::string>> get_paragraphs() + std::vector<RawParagraph> get_paragraphs() { - std::vector<std::unordered_map<std::string, std::string>> paragraphs; + std::vector<RawParagraph> paragraphs; char ch; peek(ch); @@ -164,51 +164,48 @@ namespace vcpkg::Paragraphs } }; - Expected<std::unordered_map<std::string, std::string>> get_single_paragraph(const Files::Filesystem& fs, - const fs::path& control_path) + Expected<RawParagraph> parse_single_paragraph(const std::string& str) { - const Expected<std::string> contents = fs.read_contents(control_path); - if (auto spgh = contents.get()) + const std::vector<RawParagraph> p = Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + + if (p.size() == 1) { - return parse_single_paragraph(*spgh); + return p.at(0); } - return contents.error(); + return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH); } - Expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const Files::Filesystem& fs, - const fs::path& control_path) + Expected<RawParagraph> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path) { const Expected<std::string> contents = fs.read_contents(control_path); if (auto spgh = contents.get()) { - return parse_paragraphs(*spgh); + return parse_single_paragraph(*spgh); } return contents.error(); } - Expected<std::unordered_map<std::string, std::string>> parse_single_paragraph(const std::string& str) + Expected<std::vector<RawParagraph>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path) { - const std::vector<std::unordered_map<std::string, std::string>> p = - Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); - - if (p.size() == 1) + const Expected<std::string> contents = fs.read_contents(control_path); + if (auto spgh = contents.get()) { - return p.at(0); + return parse_paragraphs(*spgh); } - return std::error_code(ParagraphParseResult::EXPECTED_ONE_PARAGRAPH); + return contents.error(); } - Expected<std::vector<std::unordered_map<std::string, std::string>>> parse_paragraphs(const std::string& str) + Expected<std::vector<RawParagraph>> parse_paragraphs(const std::string& str) { return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); } ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& path) { - Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs = get_paragraphs(fs, path / "CONTROL"); + Expected<std::vector<RawParagraph>> pghs = get_paragraphs(fs, path / "CONTROL"); if (auto vector_pghs = pghs.get()) { return SourceControlFile::parse_control_file(std::move(*vector_pghs)); @@ -221,7 +218,7 @@ namespace vcpkg::Paragraphs Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) { - Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs = + Expected<std::vector<RawParagraph>> pghs = get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); if (auto p = pghs.get()) diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp index d50296cf8..9c9968249 100644 --- a/toolsrc/src/vcpkg/parse.cpp +++ b/toolsrc/src/vcpkg/parse.cpp @@ -6,8 +6,7 @@ namespace vcpkg::Parse { - static Optional<std::string> remove_field(std::unordered_map<std::string, std::string>* fields, - const std::string& fieldname) + static Optional<std::string> remove_field(RawParagraph* fields, const std::string& fieldname) { auto it = fields->find(fieldname); if (it == fields->end()) diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp index 84ec6c981..65e00668a 100644 --- a/toolsrc/src/vcpkg/remove.cpp +++ b/toolsrc/src/vcpkg/remove.cpp @@ -73,7 +73,7 @@ namespace vcpkg::Remove if (ec) { #if defined(_WIN32) - fs::stdfs::permissions(target, fs::stdfs::perms::owner_all | fs::stdfs::perms::group_all, ec); + fs::stdfs::permissions(target, fs::perms::owner_all | fs::perms::group_all, ec); fs.remove(target, ec); if (ec) { @@ -86,7 +86,7 @@ namespace vcpkg::Remove #endif } } - else if (!fs::stdfs::exists(status)) + else if (!fs::exists(status)) { System::printf(System::Color::warning, "Warning: %s: file not found\n", target.u8string()); } diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 5542ef923..ebb9cd4f4 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include <vcpkg/logicexpression.h> #include <vcpkg/packagespec.h> #include <vcpkg/sourceparagraph.h> #include <vcpkg/triplet.h> @@ -144,7 +145,7 @@ namespace vcpkg } ParseExpected<SourceControlFile> SourceControlFile::parse_control_file( - std::vector<std::unordered_map<std::string, std::string>>&& control_paragraphs) + std::vector<Parse::RawParagraph>&& control_paragraphs) { if (control_paragraphs.size() == 0) { @@ -224,15 +225,8 @@ namespace vcpkg std::vector<std::string> ret; for (auto&& dep : deps) { - auto qualifiers = Strings::split(dep.qualifier, "&"); - if (std::all_of(qualifiers.begin(), qualifiers.end(), [&](const std::string& qualifier) { - if (qualifier.empty()) return true; - if (qualifier[0] == '!') - { - return t.canonical_name().find(qualifier.substr(1)) == std::string::npos; - } - return t.canonical_name().find(qualifier) != std::string::npos; - })) + const auto& qualifier = dep.qualifier; + if (qualifier.empty() || evaluate_expression(qualifier, t.canonical_name())) { ret.emplace_back(dep.name()); } @@ -240,21 +234,13 @@ namespace vcpkg return ret; } - std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps, - const Triplet& t) + std::vector<Features> filter_dependencies_to_features(const std::vector<vcpkg::Dependency>& deps, const Triplet& t) { std::vector<Features> ret; for (auto&& dep : deps) { - auto qualifiers = Strings::split(dep.qualifier, "&"); - if (std::all_of(qualifiers.begin(), qualifiers.end(), [&](const std::string& qualifier) { - if (qualifier.empty()) return true; - if (qualifier[0] == '!') - { - return t.canonical_name().find(qualifier.substr(1)) == std::string::npos; - } - return t.canonical_name().find(qualifier) != std::string::npos; - })) + const auto& qualifier = dep.qualifier; + if (qualifier.empty() || evaluate_expression(qualifier, t.canonical_name())) { ret.emplace_back(dep.depend); } diff --git a/toolsrc/src/vcpkg/statusparagraph.cpp b/toolsrc/src/vcpkg/statusparagraph.cpp index 86946a31a..f7e00f21c 100644 --- a/toolsrc/src/vcpkg/statusparagraph.cpp +++ b/toolsrc/src/vcpkg/statusparagraph.cpp @@ -24,7 +24,7 @@ namespace vcpkg .push_back('\n'); } - StatusParagraph::StatusParagraph(std::unordered_map<std::string, std::string>&& fields) + StatusParagraph::StatusParagraph(Parse::RawParagraph&& fields) : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) { auto status_it = fields.find(BinaryParagraphRequiredField::STATUS); diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp index a7c4e2765..a3c019be7 100644 --- a/toolsrc/src/vcpkg/userconfig.cpp +++ b/toolsrc/src/vcpkg/userconfig.cpp @@ -51,7 +51,7 @@ namespace vcpkg { const auto& pghs = *p_pghs; - std::unordered_map<std::string, std::string> keys; + Parse::RawParagraph keys; if (pghs.size() > 0) keys = pghs[0]; for (size_t x = 1; x < pghs.size(); ++x) diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp index 7a28fb571..e48340df7 100644 --- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp +++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp @@ -148,9 +148,8 @@ namespace vcpkg } if (Strings::starts_with(arg, "--scripts-root=")) { - parse_cojoined_value(arg.substr(sizeof("--scripts-root=") - 1), - "--scripts-root", - args.scripts_root_dir); + parse_cojoined_value( + arg.substr(sizeof("--scripts-root=") - 1), "--scripts-root", args.scripts_root_dir); continue; } if (arg == "--triplet") @@ -161,16 +160,14 @@ namespace vcpkg } if (Strings::starts_with(arg, "--overlay-ports=")) { - parse_cojoined_multivalue(arg.substr(sizeof("--overlay-ports=") - 1), - "--overlay-ports", - args.overlay_ports); + parse_cojoined_multivalue( + arg.substr(sizeof("--overlay-ports=") - 1), "--overlay-ports", args.overlay_ports); continue; } if (Strings::starts_with(arg, "--overlay-triplets=")) { - parse_cojoined_multivalue(arg.substr(sizeof("--overlay-triplets=") - 1), - "--overlay-triplets", - args.overlay_triplets); + parse_cojoined_multivalue( + arg.substr(sizeof("--overlay-triplets=") - 1), "--overlay-triplets", args.overlay_triplets); continue; } if (arg == "--debug") @@ -224,11 +221,11 @@ namespace vcpkg { const auto& key = arg.substr(0, eq_pos); const auto& value = arg.substr(eq_pos + 1); - + auto it = args.optional_command_arguments.find(key); if (args.optional_command_arguments.end() == it) { - args.optional_command_arguments.emplace(key, std::vector<std::string> { value }); + args.optional_command_arguments.emplace(key, std::vector<std::string>{value}); } else { @@ -370,8 +367,9 @@ namespace vcpkg { if (v.empty()) { - System::printf( - System::Color::error, "Error: The option '%s' must be passed an argument.\n", option.name); + System::printf(System::Color::error, + "Error: The option '%s' must be passed an argument.\n", + option.name); failed = true; } else @@ -389,7 +387,7 @@ namespace vcpkg System::printf(System::Color::error, "Unknown option(s) for command '%s':\n", this->command); for (auto&& option : options_copy) { - System::print2(" ", option.first, "\n"); + System::print2(" '", option.first, "'\n"); } System::print2("\n"); failed = true; @@ -425,12 +423,9 @@ namespace vcpkg System::printf(" %-40s %s\n", (option.name + "=..."), option.short_help_text); } System::printf(" %-40s %s\n", "--triplet <t>", "Set the default triplet for unqualified packages"); - System::printf(" %-40s %s\n", - "--overlay-ports=<path>", - "Specify directories to be used when searching for ports"); - System::printf(" %-40s %s\n", - "--overlay-triplets=<path>", - "Specify directories containing triplets files"); + System::printf( + " %-40s %s\n", "--overlay-ports=<path>", "Specify directories to be used when searching for ports"); + System::printf(" %-40s %s\n", "--overlay-triplets=<path>", "Specify directories containing triplets files"); System::printf(" %-40s %s\n", "--vcpkg-root <path>", "Specify the vcpkg directory to use instead of current directory or tool directory"); diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index d16acf2e8..c5b5749ff 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -42,7 +42,7 @@ namespace vcpkg if (auto odp = overriddenDownloadsPath.get()) { auto asPath = fs::u8path(*odp); - if (!fs::stdfs::is_directory(asPath)) + if (!fs::is_directory(status(asPath))) { Metrics::g_metrics.lock()->track_property("error", "Invalid VCPKG_DOWNLOADS override directory."); Checks::exit_with_message( @@ -71,12 +71,12 @@ namespace vcpkg { if (scripts_dir->empty() || !fs::stdfs::is_directory(*scripts_dir)) { - Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory."); - Checks::exit_with_message( - VCPKG_LINE_INFO, - "Invalid scripts override directory: %s; " - "create that directory or unset --scripts-root to use the default scripts location.", - scripts_dir->u8string()); + Metrics::g_metrics.lock()->track_property("error", "Invalid scripts override directory."); + Checks::exit_with_message( + VCPKG_LINE_INFO, + "Invalid scripts override directory: %s; " + "create that directory or unset --scripts-root to use the default scripts location.", + scripts_dir->u8string()); } paths.scripts = *scripts_dir; @@ -147,26 +147,25 @@ namespace vcpkg } Util::sort_unique_erase(output); return output; - }); + }); } const fs::path VcpkgPaths::get_triplet_file_path(const Triplet& triplet) const { - return m_triplets_cache.get_lazy(triplet, [&]()-> auto { - for (auto&& triplet_dir : triplets_dirs) - { - auto&& path = triplet_dir / (triplet.canonical_name() + ".cmake"); - if (this->get_filesystem().exists(path)) + return m_triplets_cache.get_lazy( + triplet, [&]() -> auto { + for (auto&& triplet_dir : triplets_dirs) { - return path; + auto&& path = triplet_dir / (triplet.canonical_name() + ".cmake"); + if (this->get_filesystem().exists(path)) + { + return path; + } } - } - Checks::exit_with_message(VCPKG_LINE_INFO, - "Error: Triplet file %s.cmake not found", - triplet.canonical_name()); - }); - + Checks::exit_with_message( + VCPKG_LINE_INFO, "Error: Triplet file %s.cmake not found", triplet.canonical_name()); + }); } const fs::path& VcpkgPaths::get_tool_exe(const std::string& tool) const |
