diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2017-04-14 16:07:54 -0700 |
|---|---|---|
| committer | Robert Schumacher <roschuma@microsoft.com> | 2017-04-14 16:07:54 -0700 |
| commit | 20397fc845fac398a1aca2ee17ce5b932fc1a83b (patch) | |
| tree | 51235bc2602a81a89da9605272a37ca4fc1765a8 /toolsrc/src | |
| parent | 8183671a492aa21ec20780a77f923848b0aeca41 (diff) | |
| parent | 1c08a42091cb0addd1e0c1daf27d24bf4e9d237f (diff) | |
| download | vcpkg-20397fc845fac398a1aca2ee17ce5b932fc1a83b.tar.gz vcpkg-20397fc845fac398a1aca2ee17ce5b932fc1a83b.zip | |
Merge branch 'dev/roschuma/fs-testing'
Diffstat (limited to 'toolsrc/src')
28 files changed, 519 insertions, 415 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index 499ef54f7..99d7d230b 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -68,29 +68,23 @@ namespace vcpkg return Strings::format("%s_%s_%s", this->spec.name(), this->version, this->spec.triplet()); } - std::ostream& operator<<(std::ostream& os, const BinaryParagraph& p) + void serialize(const BinaryParagraph& pgh, std::string& out_str) { - os << "Package: " << p.spec.name() << "\n"; - os << "Version: " << p.version << "\n"; - if (!p.depends.empty()) + out_str.append("Package: ").append(pgh.spec.name()).push_back('\n'); + out_str.append("Version: ").append(pgh.version).push_back('\n'); + if (!pgh.depends.empty()) { - os << "Depends: " << p.depends.front(); + out_str.append("Depends: "); + out_str.append(Strings::join(", ", pgh.depends)); + out_str.push_back('\n'); + } - auto b = p.depends.begin() + 1; - auto e = p.depends.end(); - for (; b != e; ++b) - { - os << ", " << *b; - } + out_str.append("Architecture: ").append(pgh.spec.triplet().to_string()).push_back('\n'); + out_str.append("Multi-Arch: same\n"); - os << "\n"; - } - os << "Architecture: " << p.spec.triplet().to_string() << "\n"; - os << "Multi-Arch: same\n"; - if (!p.maintainer.empty()) - os << "Maintainer: " << p.maintainer << "\n"; - if (!p.description.empty()) - os << "Description: " << p.description << "\n"; - return os; + if (!pgh.maintainer.empty()) + out_str.append("Maintainer: ").append(pgh.maintainer).push_back('\n'); + if (!pgh.description.empty()) + out_str.append("Description: ").append(pgh.description).push_back('\n'); } } diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 010da6700..f14552169 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -172,9 +172,9 @@ namespace vcpkg::Paragraphs } }; - Expected<std::unordered_map<std::string, std::string>> get_single_paragraph(const fs::path& control_path) + Expected<std::unordered_map<std::string, std::string>> get_single_paragraph(const Files::Filesystem& fs, const fs::path& control_path) { - const Expected<std::string> contents = Files::read_contents(control_path); + const Expected<std::string> contents = fs.read_contents(control_path); if (auto spgh = contents.get()) { return parse_single_paragraph(*spgh); @@ -183,9 +183,9 @@ namespace vcpkg::Paragraphs return contents.error_code(); } - Expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const fs::path& control_path) + Expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const Files::Filesystem& fs, const fs::path& control_path) { - const Expected<std::string> contents = Files::read_contents(control_path); + const Expected<std::string> contents = fs.read_contents(control_path); if (auto spgh = contents.get()) { return parse_paragraphs(*spgh); @@ -211,9 +211,9 @@ namespace vcpkg::Paragraphs return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); } - Expected<SourceParagraph> try_load_port(const fs::path& path) + Expected<SourceParagraph> try_load_port(const Files::Filesystem& fs, const fs::path& path) { - Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(path / "CONTROL"); + Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(fs, path / "CONTROL"); if (auto p = pghs.get()) { return SourceParagraph(*p); @@ -224,7 +224,7 @@ namespace vcpkg::Paragraphs Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) { - Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(paths.package_dir(spec) / "CONTROL"); + Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); if (auto p = pghs.get()) { @@ -234,13 +234,12 @@ namespace vcpkg::Paragraphs return pghs.error_code(); } - std::vector<SourceParagraph> load_all_ports(const fs::path& ports_dir) + std::vector<SourceParagraph> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) { std::vector<SourceParagraph> output; - for (auto it = fs::directory_iterator(ports_dir); it != fs::directory_iterator(); ++it) + for (auto&& path : fs.get_files_non_recursive(ports_dir)) { - const fs::path& path = it->path(); - Expected<SourceParagraph> source_paragraph = try_load_port(path); + Expected<SourceParagraph> source_paragraph = try_load_port(fs, path); if (auto srcpgh = source_paragraph.get()) { output.emplace_back(std::move(*srcpgh)); diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index ace4918da..e165cf112 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -2,6 +2,7 @@ #include "VcpkgPaths.h" #include "PackageSpec.h" #include "vcpkg_Files.h" +#include "vcpkg_Util.h" #include "vcpkg_System.h" #include "coff_file_reader.h" #include "PostBuildLint_BuildInfo.h" @@ -10,6 +11,14 @@ namespace vcpkg::PostBuildLint { + static auto has_extension_pred(const Files::Filesystem& fs, const std::string& ext) + { + return [&fs, ext](const fs::path& path) + { + return !fs.is_directory(path) && path.extension() == ext; + }; + } + enum class LintStatus { SUCCESS = 0, @@ -64,7 +73,7 @@ namespace vcpkg::PostBuildLint return false; } - static LintStatus check_for_files_in_include_directory(const std::map<BuildPolicies::Type, OptBoolT>& policies, const fs::path& package_dir) + static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs, const std::map<BuildPolicies::Type, OptBoolT>& policies, const fs::path& package_dir) { if (contains_and_enabled(policies, BuildPolicies::EMPTY_INCLUDE_FOLDER)) { @@ -72,7 +81,7 @@ namespace vcpkg::PostBuildLint } const fs::path include_dir = package_dir / "include"; - if (!fs::exists(include_dir) || fs::is_empty(include_dir)) + if (!fs.exists(include_dir) || fs.is_empty(include_dir)) { System::println(System::Color::warning, "The folder /include is empty. This indicates the library was not correctly installed."); return LintStatus::ERROR_DETECTED; @@ -81,15 +90,16 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_for_files_in_debug_include_directory(const fs::path& package_dir) + static LintStatus check_for_files_in_debug_include_directory(const Files::Filesystem& fs, const fs::path& package_dir) { const fs::path debug_include_dir = package_dir / "debug" / "include"; - std::vector<fs::path> files_found; - Files::recursive_find_matching_paths_in_dir(debug_include_dir, [&](const fs::path& current) - { - return !fs::is_directory(current) && current.extension() != ".ifc"; - }, &files_found); + std::vector<fs::path> files_found = fs.get_files_recursive(debug_include_dir); + + Util::unstable_keep_if(files_found, [&fs](const fs::path& path) + { + return !fs.is_directory(path) && path.extension() != ".ifc"; + }); if (!files_found.empty()) { @@ -102,11 +112,11 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_for_files_in_debug_share_directory(const fs::path& package_dir) + static LintStatus check_for_files_in_debug_share_directory(const Files::Filesystem& fs, const fs::path& package_dir) { const fs::path debug_share = package_dir / "debug" / "share"; - if (fs::exists(debug_share) && !fs::is_empty(debug_share)) + if (fs.exists(debug_share)) { System::println(System::Color::warning, "/debug/share should not exist. Please reorganize any important files, then use\n" " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/share)"); @@ -116,25 +126,38 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_folder_lib_cmake(const fs::path& package_dir, const PackageSpec& spec) + static LintStatus check_folder_lib_cmake(const Files::Filesystem& fs, const fs::path& package_dir, const PackageSpec& spec) { const fs::path lib_cmake = package_dir / "lib" / "cmake"; - if (fs::exists(lib_cmake)) + if (fs.exists(lib_cmake)) { - System::println(System::Color::warning, "The /lib/cmake folder should be moved to /share/%s/cmake.", spec.name()); + System::println(System::Color::warning, "The /lib/cmake folder should be merged with /debug/lib/cmake and moved to /share/%s/cmake.", spec.name()); return LintStatus::ERROR_DETECTED; } return LintStatus::SUCCESS; } - static LintStatus check_for_misplaced_cmake_files(const fs::path& package_dir, const PackageSpec& spec) + static LintStatus check_for_misplaced_cmake_files(const Files::Filesystem& fs, const fs::path& package_dir, const PackageSpec& spec) { + std::vector<fs::path> dirs = + { + package_dir / "cmake", + package_dir / "debug" / "cmake", + package_dir / "lib" / "cmake", + package_dir / "debug" / "lib" / "cmake", + }; + std::vector<fs::path> misplaced_cmake_files; - Files::recursive_find_files_with_extension_in_dir(package_dir / "cmake", ".cmake", &misplaced_cmake_files); - Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "cmake", ".cmake", &misplaced_cmake_files); - Files::recursive_find_files_with_extension_in_dir(package_dir / "lib" / "cmake", ".cmake", &misplaced_cmake_files); - Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "lib" / "cmake", ".cmake", &misplaced_cmake_files); + for (auto&& dir : dirs) + { + auto files = fs.get_files_recursive(dir); + for (auto&& file : files) + { + if (!fs.is_directory(file) && file.extension() == ".cmake") + misplaced_cmake_files.push_back(std::move(file)); + } + } if (!misplaced_cmake_files.empty()) { @@ -146,27 +169,26 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_folder_debug_lib_cmake(const fs::path& package_dir) + static LintStatus check_folder_debug_lib_cmake(const Files::Filesystem& fs, const fs::path& package_dir, const PackageSpec& spec) { const fs::path lib_cmake_debug = package_dir / "debug" / "lib" / "cmake"; - if (fs::exists(lib_cmake_debug)) + if (fs.exists(lib_cmake_debug)) { - System::println(System::Color::warning, "The /debug/lib/cmake folder should be moved to just /debug/cmake"); + System::println(System::Color::warning, "The /debug/lib/cmake folder should be merged with /lib/cmake into /share/%s", spec.name()); return LintStatus::ERROR_DETECTED; } return LintStatus::SUCCESS; } - static LintStatus check_for_dlls_in_lib_dirs(const fs::path& package_dir) + static LintStatus check_for_dlls_in_lib_dir(const Files::Filesystem& fs, const fs::path& package_dir) { - std::vector<fs::path> dlls; - Files::recursive_find_files_with_extension_in_dir(package_dir / "lib", ".dll", &dlls); - Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "lib", ".dll", &dlls); + std::vector<fs::path> dlls = fs.get_files_recursive(package_dir / "lib"); + Util::unstable_keep_if(dlls, has_extension_pred(fs, ".dll")); if (!dlls.empty()) { - System::println(System::Color::warning, "\nThe following dlls were found in /lib and /debug/lib. Please move them to /bin or /debug/bin, respectively."); + System::println(System::Color::warning, "\nThe following dlls were found in /lib or /debug/lib. Please move them to /bin or /debug/bin, respectively."); Files::print_paths(dlls); return LintStatus::ERROR_DETECTED; } @@ -174,11 +196,11 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_for_copyright_file(const PackageSpec& spec, const VcpkgPaths& paths) + static LintStatus check_for_copyright_file(const Files::Filesystem& fs, const PackageSpec& spec, const VcpkgPaths& paths) { const fs::path packages_dir = paths.packages / spec.dir(); const fs::path copyright_file = packages_dir / "share" / spec.name() / "copyright"; - if (fs::exists(copyright_file)) + if (fs.exists(copyright_file)) { return LintStatus::SUCCESS; } @@ -186,22 +208,25 @@ namespace vcpkg::PostBuildLint const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src"; std::vector<fs::path> potential_copyright_files; - // Only searching one level deep - for (auto it = fs::recursive_directory_iterator(current_buildtrees_dir_src); it != fs::recursive_directory_iterator(); ++it) + // We only search in the root of each unpacked source archive to reduce false positives + auto src_dirs = fs.get_files_non_recursive(current_buildtrees_dir_src); + for (auto&& src_dir : src_dirs) { - if (it.depth() > 1) - { + if (!fs.is_directory(src_dir)) continue; - } - const std::string filename = it->path().filename().string(); - if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING") + for (auto&& src_file : fs.get_files_non_recursive(src_dir)) { - potential_copyright_files.push_back(it->path()); + const std::string filename = src_file.filename().string(); + + if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING") + { + potential_copyright_files.push_back(src_file); + } } } - System::println(System::Color::warning, "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright .", spec.name()); + System::println(System::Color::warning, "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright", spec.name()); if (potential_copyright_files.size() == 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location { const fs::path found_file = potential_copyright_files[0]; @@ -209,28 +234,23 @@ namespace vcpkg::PostBuildLint System::println("\n file(COPY ${CURRENT_BUILDTREES_DIR}/%s DESTINATION ${CURRENT_PACKAGES_DIR}/share/%s)\n" " file(RENAME ${CURRENT_PACKAGES_DIR}/share/%s/%s ${CURRENT_PACKAGES_DIR}/share/%s/copyright)", relative_path.generic_string(), spec.name(), spec.name(), found_file.filename().generic_string(), spec.name()); - return LintStatus::ERROR_DETECTED; } - - if (potential_copyright_files.size() > 1) + else if (potential_copyright_files.size() > 1) { System::println(System::Color::warning, "The following files are potential copyright files:"); Files::print_paths(potential_copyright_files); } - - System::println(" %s/share/%s/copyright", packages_dir.generic_string(), spec.name()); return LintStatus::ERROR_DETECTED; } - static LintStatus check_for_exes(const fs::path& package_dir) + static LintStatus check_for_exes(const Files::Filesystem& fs, const fs::path& package_dir) { - std::vector<fs::path> exes; - Files::recursive_find_files_with_extension_in_dir(package_dir / "bin", ".exe", &exes); - Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "bin", ".exe", &exes); + std::vector<fs::path> exes = fs.get_files_recursive(package_dir / "bin"); + Util::unstable_keep_if(exes, has_extension_pred(fs, ".exe")); if (!exes.empty()) { - System::println(System::Color::warning, "The following EXEs were found in /bin and /debug/bin. EXEs are not valid distribution targets."); + System::println(System::Color::warning, "The following EXEs were found in /bin or /debug/bin. EXEs are not valid distribution targets."); Files::print_paths(exes); return LintStatus::ERROR_DETECTED; } @@ -433,7 +453,7 @@ namespace vcpkg::PostBuildLint if (lib_count == 0 && dll_count != 0) { - System::println(System::Color::warning, "Import libs were not present in %s", lib_dir.generic_string()); + System::println(System::Color::warning, "Import libs were not present in %s", lib_dir.u8string()); System::println(System::Color::warning, "If this is intended, add the following line in the portfile:\n" " SET(%s enabled)", BuildPolicies::DLLS_WITHOUT_LIBS.cmake_variable()); @@ -443,24 +463,24 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_bin_folders_are_not_present_in_static_build(const fs::path& package_dir) + static LintStatus check_bin_folders_are_not_present_in_static_build(const Files::Filesystem& fs, const fs::path& package_dir) { const fs::path bin = package_dir / "bin"; const fs::path debug_bin = package_dir / "debug" / "bin"; - if (!fs::exists(bin) && !fs::exists(debug_bin)) + if (!fs.exists(bin) && !fs.exists(debug_bin)) { return LintStatus::SUCCESS; } - if (fs::exists(bin)) + if (fs.exists(bin)) { - System::println(System::Color::warning, R"(There should be no bin\ directory in a static build, but %s is present.)", bin.generic_string()); + System::println(System::Color::warning, R"(There should be no bin\ directory in a static build, but %s is present.)", bin.u8string()); } - if (fs::exists(debug_bin)) + if (fs.exists(debug_bin)) { - System::println(System::Color::warning, R"(There should be no debug\bin\ directory in a static build, but %s is present.)", debug_bin.generic_string()); + System::println(System::Color::warning, R"(There should be no debug\bin\ directory in a static build, but %s is present.)", debug_bin.u8string()); } System::println(System::Color::warning, R"(If the creation of bin\ and/or debug\bin\ cannot be disabled, use this in the portfile to remove them)" "\n" @@ -474,12 +494,14 @@ namespace vcpkg::PostBuildLint return LintStatus::ERROR_DETECTED; } - static LintStatus check_no_empty_folders(const fs::path& dir) + static LintStatus check_no_empty_folders(const Files::Filesystem& fs, const fs::path& dir) { - const std::vector<fs::path> empty_directories = Files::recursive_find_matching_paths_in_dir(dir, [](const fs::path& current) - { - return fs::is_directory(current) && fs::is_empty(current); - }); + std::vector<fs::path> empty_directories = fs.get_files_recursive(dir); + + Util::unstable_keep_if(empty_directories, [&fs](const fs::path& current) + { + return fs.is_directory(current) && fs.is_empty(current); + }); if (!empty_directories.empty()) { @@ -590,22 +612,20 @@ namespace vcpkg::PostBuildLint return LintStatus::SUCCESS; } - static LintStatus check_no_files_in_package_dir_and_debug_dir(const fs::path& package_dir) + static LintStatus check_no_files_in_dir(const Files::Filesystem& fs, const fs::path& dir) { - std::vector<fs::path> misplaced_files; - - Files::non_recursive_find_matching_paths_in_dir(package_dir, [](const fs::path& current) - { - const std::string filename = current.filename().generic_string(); - return !fs::is_directory(current) && !((_stricmp(filename.c_str(), "CONTROL") == 0 || _stricmp(filename.c_str(), "BUILD_INFO") == 0)); - }, &misplaced_files); - - const fs::path debug_dir = package_dir / "debug"; - Files::non_recursive_find_all_files_in_dir(debug_dir, &misplaced_files); + std::vector<fs::path> misplaced_files = fs.get_files_non_recursive(dir); + Util::unstable_keep_if(misplaced_files, [&fs](const fs::path& path) + { + const std::string filename = path.filename().generic_string(); + if (_stricmp(filename.c_str(), "CONTROL") == 0 || _stricmp(filename.c_str(), "BUILD_INFO") == 0) + return false; + return !fs.is_directory(path); + }); if (!misplaced_files.empty()) { - System::println(System::Color::warning, "The following files are placed in\n%s and\n%s: ", package_dir.generic_string(), debug_dir.generic_string()); + System::println(System::Color::warning, "The following files are placed in\n%s: ", dir.u8string()); Files::print_paths(misplaced_files); System::println(System::Color::warning, "Files cannot be present in those directories.\n"); return LintStatus::ERROR_DETECTED; @@ -621,10 +641,12 @@ namespace vcpkg::PostBuildLint static size_t perform_all_checks_and_return_error_count(const PackageSpec& spec, const VcpkgPaths& paths) { + const auto& fs = paths.get_filesystem(); + // for dumpbin const Toolset& toolset = paths.get_toolset(); - BuildInfo build_info = read_build_info(paths.build_info_file_path(spec)); + BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); const fs::path package_dir = paths.package_dir(spec); size_t error_count = 0; @@ -634,38 +656,46 @@ namespace vcpkg::PostBuildLint return error_count; } - error_count += check_for_files_in_include_directory(build_info.policies, package_dir); - error_count += check_for_files_in_debug_include_directory(package_dir); - error_count += check_for_files_in_debug_share_directory(package_dir); - error_count += check_folder_lib_cmake(package_dir, spec); - error_count += check_for_misplaced_cmake_files(package_dir, spec); - error_count += check_folder_debug_lib_cmake(package_dir); - error_count += check_for_dlls_in_lib_dirs(package_dir); - error_count += check_for_copyright_file(spec, paths); - error_count += check_for_exes(package_dir); + error_count += check_for_files_in_include_directory(fs, build_info.policies, package_dir); + error_count += check_for_files_in_debug_include_directory(fs, package_dir); + error_count += check_for_files_in_debug_share_directory(fs, package_dir); + error_count += check_folder_lib_cmake(fs, package_dir, spec); + error_count += check_for_misplaced_cmake_files(fs, package_dir, spec); + error_count += check_folder_debug_lib_cmake(fs, package_dir, spec); + error_count += check_for_dlls_in_lib_dir(fs, package_dir); + error_count += check_for_dlls_in_lib_dir(fs, package_dir / "debug"); + error_count += check_for_copyright_file(fs, spec, paths); + error_count += check_for_exes(fs, package_dir); + error_count += check_for_exes(fs, package_dir / "debug"); const fs::path debug_lib_dir = package_dir / "debug" / "lib"; const fs::path release_lib_dir = package_dir / "lib"; const fs::path debug_bin_dir = package_dir / "debug" / "bin"; const fs::path release_bin_dir = package_dir / "bin"; - const std::vector<fs::path> debug_libs = Files::recursive_find_files_with_extension_in_dir(debug_lib_dir, ".lib"); - const std::vector<fs::path> release_libs = Files::recursive_find_files_with_extension_in_dir(release_lib_dir, ".lib"); + std::vector<fs::path> debug_libs = fs.get_files_recursive(debug_lib_dir); + Util::unstable_keep_if(debug_libs, has_extension_pred(fs, ".lib")); + std::vector<fs::path> release_libs = fs.get_files_recursive(release_lib_dir); + Util::unstable_keep_if(release_libs, has_extension_pred(fs, ".lib")); error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs); - std::vector<fs::path> libs; - libs.insert(libs.cend(), debug_libs.cbegin(), debug_libs.cend()); - libs.insert(libs.cend(), release_libs.cbegin(), release_libs.cend()); + { + std::vector<fs::path> libs; + libs.insert(libs.cend(), debug_libs.cbegin(), debug_libs.cend()); + libs.insert(libs.cend(), release_libs.cbegin(), release_libs.cend()); - error_count += check_lib_architecture(spec.triplet().architecture(), libs); + error_count += check_lib_architecture(spec.triplet().architecture(), libs); + } switch (build_info.library_linkage) { case LinkageType::BackingEnum::DYNAMIC: { - const std::vector<fs::path> debug_dlls = Files::recursive_find_files_with_extension_in_dir(debug_bin_dir, ".dll"); - const std::vector<fs::path> release_dlls = Files::recursive_find_files_with_extension_in_dir(release_bin_dir, ".dll"); + std::vector<fs::path> debug_dlls = fs.get_files_recursive(debug_bin_dir); + Util::unstable_keep_if(debug_dlls, has_extension_pred(fs, ".dll")); + std::vector<fs::path> release_dlls = fs.get_files_recursive(release_bin_dir); + Util::unstable_keep_if(release_dlls, has_extension_pred(fs, ".dll")); error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls); @@ -685,11 +715,11 @@ namespace vcpkg::PostBuildLint } case LinkageType::BackingEnum::STATIC: { - std::vector<fs::path> dlls; - Files::recursive_find_files_with_extension_in_dir(package_dir, ".dll", &dlls); + std::vector<fs::path> dlls = fs.get_files_recursive(package_dir); + Util::unstable_keep_if(dlls, has_extension_pred(fs, ".dll")); error_count += check_no_dlls_present(dlls); - error_count += check_bin_folders_are_not_present_in_static_build(package_dir); + error_count += check_bin_folders_are_not_present_in_static_build(fs, package_dir); if (!contains_and_enabled(build_info.policies, BuildPolicies::ONLY_RELEASE_CRT)) { @@ -703,8 +733,9 @@ namespace vcpkg::PostBuildLint Checks::unreachable(VCPKG_LINE_INFO); } - error_count += check_no_empty_folders(package_dir); - error_count += check_no_files_in_package_dir_and_debug_dir(package_dir); + error_count += check_no_empty_folders(fs, package_dir); + error_count += check_no_files_in_dir(fs, package_dir); + error_count += check_no_files_in_dir(fs, package_dir / "debug"); return error_count; } diff --git a/toolsrc/src/PostBuildLint_BuildInfo.cpp b/toolsrc/src/PostBuildLint_BuildInfo.cpp index c7f0781b7..c129cedca 100644 --- a/toolsrc/src/PostBuildLint_BuildInfo.cpp +++ b/toolsrc/src/PostBuildLint_BuildInfo.cpp @@ -37,9 +37,9 @@ namespace vcpkg::PostBuildLint return build_info; } - BuildInfo read_build_info(const fs::path& filepath) + 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(filepath); + const Expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(fs, filepath); Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid BUILD_INFO file for package"); return BuildInfo::create(*pghs.get()); } diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index c23e220d7..11b83aedf 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -138,9 +138,8 @@ namespace vcpkg return ret; } - std::ostream & operator<<(std::ostream & os, const Dependency & p) + const std::string& to_string(const Dependency& dep) { - os << p.name; - return os; + return dep.name; } } diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp index 88b4fb854..63bfb2f9b 100644 --- a/toolsrc/src/StatusParagraph.cpp +++ b/toolsrc/src/StatusParagraph.cpp @@ -16,11 +16,10 @@ namespace vcpkg { } - std::ostream& operator<<(std::ostream& os, const StatusParagraph& p) + void serialize(const StatusParagraph& pgh, std::string& out_str) { - os << p.package; - os << "Status: " << to_string(p.want) << " ok " << to_string(p.state) << "\n"; - return os; + serialize(pgh.package, out_str); + out_str.append("Status: ").append(to_string(pgh.want)).append(" ok ").append(to_string(pgh.state)).push_back('\n'); } StatusParagraph::StatusParagraph(const std::unordered_map<std::string, std::string>& fields) diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index 7d09b30e9..f41630132 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -57,13 +57,12 @@ namespace vcpkg return ptr; } - std::ostream& vcpkg::operator<<(std::ostream& os, const StatusParagraphs& l) + void serialize(const StatusParagraphs& pghs, std::string& out_str) { - for (auto& pgh : l.paragraphs) + for (auto& pgh : pghs.paragraphs) { - os << *pgh; - os << "\n"; + serialize(*pgh, out_str); + out_str.push_back('\n'); } - return os; } } diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 6fc0538fd..ec4bb2dce 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -6,6 +6,7 @@ #include "PackageSpec.h" #include "vcpkg_Files.h" #include "vcpkg_Util.h" +#include "..\include\VcpkgPaths.h" namespace vcpkg { @@ -155,7 +156,7 @@ namespace vcpkg Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir) { std::error_code ec; - const fs::path canonical_vcpkg_root_dir = fs::canonical(vcpkg_root_dir, ec); + const fs::path canonical_vcpkg_root_dir = fs::stdfs::canonical(vcpkg_root_dir, ec); if (ec) { return ec; @@ -213,10 +214,9 @@ namespace vcpkg bool VcpkgPaths::is_valid_triplet(const Triplet& t) const { - auto it = fs::directory_iterator(this->triplets); - for (; it != fs::directory_iterator(); ++it) + for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets)) { - std::string triplet_file_name = it->path().stem().generic_u8string(); + std::string triplet_file_name = path.stem().generic_u8string(); if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare { //t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare @@ -264,6 +264,8 @@ namespace vcpkg static Toolset find_toolset_instance(const VcpkgPaths& paths) { + const auto& fs = paths.get_filesystem(); + const std::vector<std::string> vs2017_installation_instances = get_VS2017_installation_instances(paths); // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector<fs::path> paths_examined; @@ -276,16 +278,15 @@ namespace vcpkg // Skip any instances that do not have vcvarsall. const fs::path vcvarsall_bat = vc_dir / "Auxiliary" / "Build" / "vcvarsall.bat"; paths_examined.push_back(vcvarsall_bat); - if (!fs::exists(vcvarsall_bat)) + if (!fs.exists(vcvarsall_bat)) continue; // Locate the "best" MSVC toolchain version const fs::path msvc_path = vc_dir / "Tools" / "MSVC"; - std::vector<fs::path> msvc_subdirectories; - Files::non_recursive_find_matching_paths_in_dir(msvc_path, [](const fs::path& current) - { - return fs::is_directory(current); - }, &msvc_subdirectories); + std::vector<fs::path> msvc_subdirectories = fs.get_files_non_recursive(msvc_path); + Util::unstable_keep_if(msvc_subdirectories, [&fs](const fs::path& path) { + return fs.is_directory(path); + }); // Sort them so that latest comes first std::sort(msvc_subdirectories.begin(), msvc_subdirectories.end(), [](const fs::path& left, const fs::path& right) @@ -297,7 +298,7 @@ namespace vcpkg { const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe"; paths_examined.push_back(dumpbin_path); - if (fs::exists(dumpbin_path)) + if (fs.exists(dumpbin_path)) { return { dumpbin_path, vcvarsall_bat , L"v141" }; } @@ -311,11 +312,11 @@ namespace vcpkg const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; paths_examined.push_back(vs2015_vcvarsall_bat); - if (fs::exists(vs2015_vcvarsall_bat)) + if (fs.exists(vs2015_vcvarsall_bat)) { const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; paths_examined.push_back(vs2015_dumpbin_exe); - if (fs::exists(vs2015_dumpbin_exe)) + if (fs.exists(vs2015_dumpbin_exe)) { return { vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140" }; } @@ -335,4 +336,8 @@ namespace vcpkg { return this->toolset.get_lazy([this]() { return find_toolset_instance(*this); }); } + Files::Filesystem & VcpkgPaths::get_filesystem() const + { + return Files::get_real_filesystem(); + } } diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 710e108b0..ab792f1bc 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -23,7 +23,7 @@ namespace vcpkg::Commands::Build { const BinaryParagraph bpgh = BinaryParagraph(source_paragraph, triplet); const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL"; - std::ofstream(binary_control_file) << bpgh; + paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh)); } std::wstring make_build_env_cmd(const Triplet& triplet, const Toolset& toolset) @@ -141,7 +141,7 @@ namespace vcpkg::Commands::Build Checks::exit_success(VCPKG_LINE_INFO); } - const Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(port_dir); + const Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), port_dir); Checks::check_exit(VCPKG_LINE_INFO, !maybe_spgh.error_code(), "Could not find package named %s: %s", spec, maybe_spgh.error_code().message()); const SourceParagraph& spgh = *maybe_spgh.get(); diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index eae1d8fe3..cb26c6ef9 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -10,10 +10,9 @@ namespace vcpkg::Commands::Cache static std::vector<BinaryParagraph> read_all_binary_paragraphs(const VcpkgPaths& paths) { std::vector<BinaryParagraph> output; - for (auto it = fs::directory_iterator(paths.packages); it != fs::directory_iterator(); ++it) + for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.packages)) { - const fs::path& path = it->path(); - const Expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(path / "CONTROL"); + const Expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL"); if (auto p = pghs.get()) { const BinaryParagraph binary_paragraph = BinaryParagraph(*p); diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index 6c6cd8751..a40a7ed32 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -14,9 +14,9 @@ namespace vcpkg::Commands::CI using Dependencies::InstallPlanType; using Build::BuildResult; - static std::vector<PackageSpec> load_all_package_specs(const fs::path& ports_directory, const Triplet& triplet) + static std::vector<PackageSpec> load_all_package_specs(Files::Filesystem& fs, const fs::path& ports_directory, const Triplet& triplet) { - std::vector<SourceParagraph> ports = Paragraphs::load_all_ports(ports_directory); + std::vector<SourceParagraph> ports = Paragraphs::load_all_ports(fs, ports_directory); std::vector<PackageSpec> specs; for (const SourceParagraph& p : ports) { @@ -33,7 +33,7 @@ namespace vcpkg::Commands::CI const Triplet triplet = args.command_arguments.size() == 1 ? Triplet::from_canonical_name(args.command_arguments.at(0)) : default_triplet; Input::check_triplet(triplet, paths); args.check_and_get_optional_command_arguments({}); - const std::vector<PackageSpec> specs = load_all_package_specs(paths.ports, triplet); + const std::vector<PackageSpec> specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet); StatusParagraphs status_db = database_load_check(paths); const std::vector<InstallPlanAction> install_plan = Dependencies::create_install_plan(paths, specs, status_db); diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index a61ac534e..0f0509614 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -12,7 +12,7 @@ namespace vcpkg::Commands::DependInfo args.check_exact_arg_count(0, example); args.check_and_get_optional_command_arguments({}); - const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.ports); + const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); for (const SourceParagraph& source_paragraph : source_paragraphs) { diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index 8549f5073..4679a2465 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -7,13 +7,15 @@ namespace vcpkg::Commands::Edit { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { + auto& fs = paths.get_filesystem(); + static const std::string example = Commands::Help::create_example_string("edit zlib"); args.check_exact_arg_count(1, example); args.check_and_get_optional_command_arguments({}); const std::string port_name = args.command_arguments.at(0); const fs::path portpath = paths.ports / port_name; - Checks::check_exit(VCPKG_LINE_INFO, fs::is_directory(portpath), R"(Could not find port named "%s")", port_name); + Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name); // Find the user's selected editor std::wstring env_EDITOR; @@ -30,7 +32,7 @@ namespace vcpkg::Commands::Edit if (env_EDITOR.empty()) { const fs::path CODE_EXE_PATH = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; - if (fs::exists(CODE_EXE_PATH)) + if (fs.exists(CODE_EXE_PATH)) { env_EDITOR = CODE_EXE_PATH; } @@ -50,13 +52,13 @@ namespace vcpkg::Commands::Edit if (auto c = code_installpath.get()) { auto p = fs::path(*c) / "Code.exe"; - if (fs::exists(p)) + if (fs.exists(p)) { env_EDITOR = p.native(); break; } auto p_insiders = fs::path(*c) / "Code - Insiders.exe"; - if (fs::exists(p_insiders)) + if (fs.exists(p_insiders)) { env_EDITOR = p_insiders.native(); break; diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp index e3c489a9d..0c6b0c766 100644 --- a/toolsrc/src/commands_help.cpp +++ b/toolsrc/src/commands_help.cpp @@ -7,10 +7,9 @@ namespace vcpkg::Commands::Help void help_topic_valid_triplet(const VcpkgPaths& paths) { System::println("Available architecture triplets:"); - auto it = fs::directory_iterator(paths.triplets); - for (; it != fs::directory_iterator(); ++it) + for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.triplets)) { - System::println(" %s", it->path().stem().filename().string()); + System::println(" %s", path.stem().filename().string()); } } diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index eb140604a..95e23302d 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -13,59 +13,73 @@ namespace vcpkg::Commands::Import }; - void check_is_directory(const LineInfo& line_info, const fs::path& dirpath) + static void check_is_directory(const LineInfo& line_info, const Files::Filesystem& fs, const fs::path& dirpath) { - Checks::check_exit(line_info, fs::is_directory(dirpath), "The path %s is not a directory", dirpath.string()); + Checks::check_exit(line_info, fs.is_directory(dirpath), "The path %s is not a directory", dirpath.string()); } - static Binaries find_binaries_in_dir(const fs::path& path) + static Binaries find_binaries_in_dir(const Files::Filesystem& fs, const fs::path& path) { - check_is_directory(VCPKG_LINE_INFO, path); + auto files = fs.get_files_recursive(path); + + check_is_directory(VCPKG_LINE_INFO, fs, path); Binaries binaries; - binaries.dlls = Files::recursive_find_files_with_extension_in_dir(path, ".dll"); - binaries.libs = Files::recursive_find_files_with_extension_in_dir(path, ".lib"); + for (auto&& file : files) + { + if (fs.is_directory(file)) + continue; + auto ext = file.extension(); + if (ext == ".dll") + binaries.dlls.push_back(std::move(file)); + else if (ext == ".lib") + binaries.libs.push_back(std::move(file)); + } return binaries; } - static void copy_files_into_directory(const std::vector<fs::path>& files, const fs::path& destination_folder) + static void copy_files_into_directory(Files::Filesystem& fs, const std::vector<fs::path>& files, const fs::path& destination_folder) { - fs::create_directory(destination_folder); + std::error_code ec; + fs.create_directory(destination_folder, ec); for (auto const& src_path : files) { fs::path dest_path = destination_folder / src_path.filename(); - fs::copy(src_path, dest_path, fs::copy_options::overwrite_existing); + fs.copy(src_path, dest_path, fs::copy_options::overwrite_existing); } } - static void place_library_files_in(const fs::path& include_directory, const fs::path& project_directory, const fs::path& destination_path) + static void place_library_files_in(Files::Filesystem& fs, const fs::path& include_directory, const fs::path& project_directory, const fs::path& destination_path) { - check_is_directory(VCPKG_LINE_INFO, include_directory); - check_is_directory(VCPKG_LINE_INFO, project_directory); - check_is_directory(VCPKG_LINE_INFO, destination_path); - Binaries debug_binaries = find_binaries_in_dir(project_directory / "Debug"); - Binaries release_binaries = find_binaries_in_dir(project_directory / "Release"); + check_is_directory(VCPKG_LINE_INFO, fs, include_directory); + check_is_directory(VCPKG_LINE_INFO, fs, project_directory); + check_is_directory(VCPKG_LINE_INFO, fs, destination_path); + Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug"); + Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release"); fs::path destination_include_directory = destination_path / "include"; - fs::copy(include_directory, destination_include_directory, fs::copy_options::recursive | fs::copy_options::overwrite_existing); + fs.copy(include_directory, destination_include_directory, fs::copy_options::recursive | fs::copy_options::overwrite_existing); - copy_files_into_directory(release_binaries.dlls, destination_path / "bin"); - copy_files_into_directory(release_binaries.libs, destination_path / "lib"); + copy_files_into_directory(fs, release_binaries.dlls, destination_path / "bin"); + copy_files_into_directory(fs, release_binaries.libs, destination_path / "lib"); - fs::create_directory(destination_path / "debug"); - copy_files_into_directory(debug_binaries.dlls, destination_path / "debug" / "bin"); - copy_files_into_directory(debug_binaries.libs, destination_path / "debug" / "lib"); + std::error_code ec; + fs.create_directory(destination_path / "debug", ec); + copy_files_into_directory(fs, debug_binaries.dlls, destination_path / "debug" / "bin"); + copy_files_into_directory(fs, debug_binaries.libs, destination_path / "debug" / "lib"); } static void do_import(const VcpkgPaths& paths, const fs::path& include_directory, const fs::path& project_directory, const BinaryParagraph& control_file_data) { + auto& fs = paths.get_filesystem(); fs::path library_destination_path = paths.package_dir(control_file_data.spec); - fs::create_directory(library_destination_path); - place_library_files_in(include_directory, project_directory, library_destination_path); + std::error_code ec; + fs.create_directory(library_destination_path, ec); + place_library_files_in(paths.get_filesystem(), include_directory, project_directory, library_destination_path); fs::path control_file_path = library_destination_path / "CONTROL"; - std::ofstream(control_file_path) << control_file_data; + fs.write_contents(control_file_path, Strings::serialize(control_file_data)); } void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) @@ -78,7 +92,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 = Paragraphs::get_single_paragraph(control_file_path); + const Expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(paths.get_filesystem(), control_file_path); Checks::check_exit(VCPKG_LINE_INFO, pghs.get() != nullptr, "Invalid control file %s for package", control_file_path.generic_string()); StatusParagraph spgh; diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index a02137e40..cd35854bc 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -17,77 +17,79 @@ namespace vcpkg::Commands::Install static void install_and_write_listfile(const VcpkgPaths& paths, const BinaryParagraph& bpgh) { + auto&& fs = paths.get_filesystem(); + std::vector<std::string> output; const fs::path package_prefix_path = paths.package_dir(bpgh.spec); const size_t prefix_length = package_prefix_path.native().size(); - const Triplet& triplet = bpgh.spec.triplet(); - const std::string& triplet_subfolder = triplet.canonical_name(); - const fs::path triplet_subfolder_path = paths.installed / triplet_subfolder; + const std::string& triplet_string = bpgh.spec.triplet().canonical_name(); + const fs::path installed_subfolder_path = paths.installed / triplet_string; std::error_code ec; - fs::create_directory(triplet_subfolder_path, ec); - output.push_back(Strings::format(R"(%s/)", triplet_subfolder)); + fs.create_directory(installed_subfolder_path, ec); + output.push_back(Strings::format(R"(%s/)", triplet_string)); - for (auto it = fs::recursive_directory_iterator(package_prefix_path); it != fs::recursive_directory_iterator(); ++it) + auto files = fs.get_files_recursive(package_prefix_path); + for (auto&& file : files) { - const std::string filename = it->path().filename().generic_string(); - if (fs::is_regular_file(it->status()) && (_stricmp(filename.c_str(), "CONTROL") == 0 || _stricmp(filename.c_str(), "BUILD_INFO") == 0)) + auto status = fs.status(file, ec); + if (ec) { - // Do not copy the control file + System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message()); continue; } - const std::string suffix = it->path().generic_u8string().substr(prefix_length + 1); - const fs::path target = triplet_subfolder_path / suffix; - - auto status = it->status(ec); - if (ec) + const std::string filename = file.filename().generic_string(); + if (fs::is_regular_file(status) && (_stricmp(filename.c_str(), "CONTROL") == 0 || _stricmp(filename.c_str(), "BUILD_INFO") == 0)) { - System::println(System::Color::error, "failed: %s: %s", it->path().u8string(), ec.message()); + // Do not copy the control file continue; } + const std::string suffix = file.generic_u8string().substr(prefix_length + 1); + const fs::path target = installed_subfolder_path / suffix; + if (fs::is_directory(status)) { - fs::create_directory(target, ec); + fs.create_directory(target, ec); if (ec) { System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); } // Trailing backslash for directories - output.push_back(Strings::format(R"(%s/%s/)", triplet_subfolder, suffix)); + output.push_back(Strings::format(R"(%s/%s/)", triplet_string, suffix)); continue; } if (fs::is_regular_file(status)) { - if (fs::exists(target)) + if (fs.exists(target)) { System::println(System::Color::warning, "File %s was already present and will be overwritten", target.u8string(), ec.message()); } - fs::copy_file(*it, target, fs::copy_options::overwrite_existing, ec); + fs.copy_file(file, target, fs::copy_options::overwrite_existing, ec); if (ec) { System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); } - output.push_back(Strings::format(R"(%s/%s)", triplet_subfolder, suffix)); + output.push_back(Strings::format(R"(%s/%s)", triplet_string, suffix)); continue; } if (!fs::status_known(status)) { - System::println(System::Color::error, "failed: %s: unknown status", it->path().u8string()); + System::println(System::Color::error, "failed: %s: unknown status", file.u8string()); continue; } - System::println(System::Color::error, "failed: %s: cannot handle file type", it->path().u8string()); + System::println(System::Color::error, "failed: %s: cannot handle file type", file.u8string()); } std::sort(output.begin(), output.end()); - Files::write_all_lines(paths.listfile_path(bpgh), output); + fs.write_lines(paths.listfile_path(bpgh), output); } static void remove_first_n_chars(std::vector<std::string>* strings, const size_t n) @@ -115,9 +117,9 @@ namespace vcpkg::Commands::Install return output; } - static SortedVector<std::string> build_list_of_package_files(const fs::path& package_dir) + static SortedVector<std::string> build_list_of_package_files(const Files::Filesystem& fs, const fs::path& package_dir) { - const std::vector<fs::path> package_file_paths = Files::recursive_find_all_files_in_dir(package_dir); + const std::vector<fs::path> package_file_paths = fs.get_files_recursive(package_dir); const size_t package_remove_char_count = package_dir.generic_string().size() + 1; // +1 for the slash auto package_files = Util::fmap(package_file_paths, [package_remove_char_count](const fs::path& path) { @@ -183,7 +185,7 @@ namespace vcpkg::Commands::Install const Triplet& triplet = binary_paragraph.spec.triplet(); const std::vector<StatusParagraphAndAssociatedFiles> pgh_and_files = get_installed_files(paths, *status_db); - const SortedVector<std::string> package_files = build_list_of_package_files(package_dir); + const SortedVector<std::string> package_files = build_list_of_package_files(paths.get_filesystem(), package_dir); const SortedVector<std::string> installed_files = build_list_of_installed_files(pgh_and_files, triplet); std::vector<std::string> intersection; diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index ea0682e1f..5772843df 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -139,10 +139,12 @@ namespace vcpkg::Commands::Integrate static void integrate_install(const VcpkgPaths& paths) { + 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) { - if (fs::exists(old_system_wide_targets_file)) + if (fs.exists(old_system_wide_targets_file)) { const std::string param = Strings::format(R"(/c DEL "%s" /Q > nul)", old_system_wide_targets_file.string()); ElevationPromptChoice user_choice = elevated_cmd_execute(param); @@ -159,12 +161,13 @@ namespace vcpkg::Commands::Integrate } } + std::error_code ec; const fs::path tmp_dir = paths.buildsystems / "tmp"; - fs::create_directory(paths.buildsystems); - fs::create_directory(tmp_dir); + 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 = Files::read_contents(system_wide_targets_file); + const Expected<std::string> system_wide_file_contents = fs.read_contents(system_wide_targets_file); if (auto contents_data = system_wide_file_contents.get()) { std::regex re(R"###(<!-- version (\d+) -->)###"); @@ -181,7 +184,7 @@ namespace vcpkg::Commands::Integrate if (should_install_system) { const fs::path sys_src_path = tmp_dir / "vcpkg.system.targets"; - std::ofstream(sys_src_path) << create_system_targets_shortcut(); + fs.write_contents(sys_src_path, create_system_targets_shortcut()); const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", system_wide_targets_file.parent_path().string(), sys_src_path.string(), system_wide_targets_file.string()); ElevationPromptChoice user_choice = elevated_cmd_execute(param); @@ -196,14 +199,16 @@ namespace vcpkg::Commands::Integrate Checks::unreachable(VCPKG_LINE_INFO); } - Checks::check_exit(VCPKG_LINE_INFO, fs::exists(system_wide_targets_file), "Error: failed to copy targets file to %s", system_wide_targets_file.string()); + Checks::check_exit(VCPKG_LINE_INFO, fs.exists(system_wide_targets_file), "Error: failed to copy targets file to %s", system_wide_targets_file.string()); } const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets"; - std::ofstream(appdata_src_path) << create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string()); + fs.write_contents(appdata_src_path, create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string())); auto appdata_dst_path = get_appdata_targets_path(); - if (!fs::copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing)) + 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); @@ -220,12 +225,12 @@ namespace vcpkg::Commands::Integrate Checks::exit_success(VCPKG_LINE_INFO); } - static void integrate_remove() + static void integrate_remove(Files::Filesystem& fs) { const fs::path path = get_appdata_targets_path(); std::error_code ec; - bool was_deleted = fs::remove(path, ec); + bool was_deleted = fs.remove(path, ec); Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message()); @@ -243,12 +248,15 @@ namespace vcpkg::Commands::Integrate static void integrate_project(const VcpkgPaths& paths) { + auto& fs = paths.get_filesystem(); + const fs::path& nuget_exe = paths.get_nuget_exe(); const fs::path& buildsystems_dir = paths.buildsystems; const fs::path tmp_dir = buildsystems_dir / "tmp"; - fs::create_directory(buildsystems_dir); - fs::create_directory(tmp_dir); + std::error_code ec; + fs.create_directory(buildsystems_dir, ec); + fs.create_directory(tmp_dir, ec); const fs::path targets_file_path = tmp_dir / "vcpkg.nuget.targets"; const fs::path props_file_path = tmp_dir / "vcpkg.nuget.props"; @@ -256,9 +264,9 @@ namespace vcpkg::Commands::Integrate const std::string nuget_id = get_nuget_id(paths.root); const std::string nupkg_version = "1.0.0"; - std::ofstream(targets_file_path) << create_nuget_targets_file(paths.buildsystems_msbuild_targets); - std::ofstream(props_file_path) << create_nuget_props_file(); - std::ofstream(nuspec_file_path) << create_nuspec_file(paths.root, nuget_id, nupkg_version); + fs.write_contents(targets_file_path, create_nuget_targets_file(paths.buildsystems_msbuild_targets)); + fs.write_contents(props_file_path, create_nuget_props_file()); + fs.write_contents(nuspec_file_path, create_nuspec_file(paths.root, nuget_id, nupkg_version)); // Using all forward slashes for the command line const std::wstring cmd_line = Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" > nul)", nuget_exe.native(), buildsystems_dir.native(), nuspec_file_path.native()); @@ -266,7 +274,7 @@ namespace vcpkg::Commands::Integrate const int exit_code = System::cmd_execute_clean(cmd_line); const fs::path nuget_package = buildsystems_dir / Strings::format("%s.%s.nupkg", nuget_id, nupkg_version); - Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0 && fs::exists(nuget_package), "Error: NuGet package creation failed"); + Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0 && fs.exists(nuget_package), "Error: NuGet package creation failed"); System::println(System::Color::success, "Created nupkg: %s", nuget_package.string()); System::println(R"( @@ -295,7 +303,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console } if (args.command_arguments[0] == "remove") { - return integrate_remove(); + return integrate_remove(paths.get_filesystem()); } if (args.command_arguments[0] == "project") { diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index f4b828ecd..e262a8338 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -69,11 +69,13 @@ namespace vcpkg::Commands::PortsDiff static std::map<std::string, VersionT> read_ports_from_commit(const VcpkgPaths& paths, const std::wstring& git_commit_id) { + std::error_code ec; + auto& fs = paths.get_filesystem(); const fs::path& git_exe = paths.get_git_exe(); const fs::path dot_git_dir = paths.root / ".git"; const std::wstring ports_dir_name_as_string = paths.ports.filename().native(); const fs::path temp_checkout_path = paths.root / Strings::wformat(L"%s-%s", ports_dir_name_as_string, git_commit_id); - fs::create_directory(temp_checkout_path); + fs.create_directory(temp_checkout_path, ec); const std::wstring checkout_this_dir = Strings::wformat(LR"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository const std::wstring cmd = Strings::wformat(LR"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)", @@ -85,9 +87,9 @@ namespace vcpkg::Commands::PortsDiff L".vcpkg-root", git_exe.native()); System::cmd_execute_clean(cmd); - const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(temp_checkout_path / ports_dir_name_as_string); + const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string); const std::map<std::string, VersionT> names_and_versions = Paragraphs::extract_port_names_and_versions(source_paragraphs); - fs::remove_all(temp_checkout_path); + fs.remove_all(temp_checkout_path, ec); return names_and_versions; } diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index 6a9f67f65..a54eda45e 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -13,15 +13,15 @@ namespace vcpkg::Commands::Remove using Dependencies::RequestType; using Update::OutdatedPackage; - static void delete_directory(const fs::path& directory) + static void delete_directory(Files::Filesystem& fs, const fs::path& directory) { std::error_code ec; - fs::remove_all(directory, ec); + fs.remove_all(directory, ec); if (!ec) { System::println(System::Color::success, "Cleaned up %s", directory.string()); } - if (fs::exists(directory)) + if (fs.exists(directory)) { System::println(System::Color::warning, "Some files in %s were unable to be removed. Close any editors operating in this directory and retry.", directory.string()); } @@ -29,18 +29,19 @@ namespace vcpkg::Commands::Remove static void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db) { + auto& fs = paths.get_filesystem(); StatusParagraph& pkg = **status_db->find(spec.name(), spec.triplet()); pkg.want = Want::PURGE; pkg.state = InstallState::HALF_INSTALLED; write_update(paths, pkg); - std::fstream listfile(paths.listfile_path(pkg.package), std::ios_base::in | std::ios_base::binary); - if (listfile) + auto maybe_lines = fs.read_lines(paths.listfile_path(pkg.package)); + + if (auto lines = maybe_lines.get()) { std::vector<fs::path> dirs_touched; - std::string suffix; - while (std::getline(listfile, suffix)) + for (auto&& suffix : *lines) { if (!suffix.empty() && suffix.back() == '\r') suffix.pop_back(); @@ -49,7 +50,7 @@ namespace vcpkg::Commands::Remove auto target = paths.installed / suffix; - auto status = fs::status(target, ec); + auto status = fs.status(target, ec); if (ec) { System::println(System::Color::error, "failed: %s", ec.message()); @@ -62,7 +63,7 @@ namespace vcpkg::Commands::Remove } else if (fs::is_regular_file(status)) { - fs::remove(target, ec); + fs.remove(target, ec); if (ec) { System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message()); @@ -82,10 +83,10 @@ namespace vcpkg::Commands::Remove auto e = dirs_touched.rend(); for (; b != e; ++b) { - if (fs::directory_iterator(*b) == fs::directory_iterator()) + if (fs.is_empty(*b)) { std::error_code ec; - fs::remove(*b, ec); + fs.remove(*b, ec); if (ec) { System::println(System::Color::error, "failed: %s", ec.message()); @@ -93,8 +94,7 @@ namespace vcpkg::Commands::Remove } } - listfile.close(); - fs::remove(paths.listfile_path(pkg.package)); + fs.remove(paths.listfile_path(pkg.package)); } pkg.state = InstallState::NOT_INSTALLED; @@ -221,7 +221,7 @@ namespace vcpkg::Commands::Remove if (alsoRemoveFolderFromPackages) { System::println("Purging package %s... ", display_name); - delete_directory(paths.packages / action.spec.dir()); + delete_directory(paths.get_filesystem(), paths.packages / action.spec.dir()); System::println(System::Color::success, "Purging package %s... done", display_name); } } diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 478f53a76..691a66289 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -59,7 +59,7 @@ namespace vcpkg::Commands::Search args.check_max_arg_count(1, example); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({ OPTION_GRAPH }); - const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.ports); + const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); if (options.find(OPTION_GRAPH) != options.cend()) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index fc03c0084..6fc8b1171 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -14,7 +14,7 @@ namespace vcpkg::Commands::Update std::vector<OutdatedPackage> find_outdated_packages(const VcpkgPaths& paths, const StatusParagraphs& status_db) { - const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.ports); + const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); const std::map<std::string, VersionT> src_names_to_versions = Paragraphs::extract_port_names_and_versions(source_paragraphs); const std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_db); @@ -64,7 +64,7 @@ namespace vcpkg::Commands::Update " vcpkg install <pkgs>..."); } - auto version_file = Files::read_contents(paths.root / "toolsrc" / "VERSION.txt"); + auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt"); if (auto version_contents = version_file.get()) { int maj1, min1, rev1; diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 515d7e574..baefc3c35 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -3,6 +3,7 @@ #include "filesystem_fs.h" #include "vcpkg_Strings.h" #include "vcpkg_System.h" +#include "vcpkg_Files.h" namespace vcpkg::Metrics { @@ -385,30 +386,32 @@ true const fs::path temp_folder_path = temp_folder; const fs::path temp_folder_path_exe = temp_folder_path / "vcpkgmetricsuploader.exe"; + auto& fs = Files::get_real_filesystem(); + if (true) { - const fs::path exe_path = []() -> fs::path + const fs::path exe_path = [&fs]() -> fs::path { auto vcpkgdir = get_bindir().parent_path(); auto path = vcpkgdir / "vcpkgmetricsuploader.exe"; - if (fs::exists(path)) + if (fs.exists(path)) return path; path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe"; - if (fs::exists(path)) + if (fs.exists(path)) return path; return L""; }(); std::error_code ec; - fs::copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); + fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec); if (ec) return; } const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt"); - std::ofstream(vcpkg_metrics_txt_path) << payload; + fs.write_contents(vcpkg_metrics_txt_path, payload); const std::wstring cmdLine = Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native()); System::cmd_execute_clean(cmdLine); diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index 58e4121a8..20bacf170 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -1,6 +1,7 @@ #include "CppUnitTest.h" #include "Paragraphs.h" #include "BinaryParagraph.h" +#include "vcpkg_Strings.h" #pragma comment(lib,"version") #pragma comment(lib,"winhttp") @@ -16,6 +17,8 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework } } +namespace Strings = vcpkg::Strings; + namespace UnitTest1 { TEST_CLASS(ControlParsing) @@ -289,27 +292,26 @@ namespace UnitTest1 Assert::AreEqual("v4", pghs[1]["f4"].c_str()); } - TEST_METHOD(parse_comment_before_single_slashN) - { - const char* str = - "f1: v1\r\n" - "#comment\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); - Assert::AreEqual(size_t(1), pghs[0].size()); - Assert::AreEqual("v1", pghs[0]["f1"].c_str()); - } + TEST_METHOD(parse_comment_before_single_slashN) + { + const char* str = + "f1: v1\r\n" + "#comment\n"; + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).value_or_exit(VCPKG_LINE_INFO); + Assert::AreEqual(size_t(1), pghs[0].size()); + Assert::AreEqual("v1", pghs[0]["f1"].c_str()); + } TEST_METHOD(BinaryParagraph_serialize_min) { - std::stringstream ss; vcpkg::BinaryParagraph pgh({ { "Package", "zlib" }, { "Version", "1.2.8" }, { "Architecture", "x86-windows" }, { "Multi-Arch", "same" }, }); - ss << pgh; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()).value_or_exit(VCPKG_LINE_INFO); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(4), pghs[0].size()); Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); @@ -320,7 +322,6 @@ namespace UnitTest1 TEST_METHOD(BinaryParagraph_serialize_max) { - std::stringstream ss; vcpkg::BinaryParagraph pgh({ { "Package", "zlib" }, { "Version", "1.2.8" }, @@ -330,8 +331,8 @@ namespace UnitTest1 { "Depends", "dep" }, { "Multi-Arch", "same" }, }); - ss << pgh; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()).value_or_exit(VCPKG_LINE_INFO); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(7), pghs[0].size()); Assert::AreEqual("zlib", pghs[0]["Package"].c_str()); @@ -344,7 +345,6 @@ namespace UnitTest1 TEST_METHOD(BinaryParagraph_serialize_multiple_deps) { - std::stringstream ss; vcpkg::BinaryParagraph pgh({ { "Package", "zlib" }, { "Version", "1.2.8" }, @@ -352,8 +352,8 @@ namespace UnitTest1 { "Multi-Arch", "same" }, { "Depends", "a, b, c" }, }); - ss << pgh; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()).value_or_exit(VCPKG_LINE_INFO); + std::string ss = Strings::serialize(pgh); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str()); } diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 74e11c3d4..cb7c3f76d 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -41,18 +41,18 @@ static void inner(const VcpkgCmdArguments& args) fs::path vcpkg_root_dir; if (args.vcpkg_root_dir != nullptr) { - vcpkg_root_dir = fs::absolute(Strings::utf8_to_utf16(*args.vcpkg_root_dir)); + vcpkg_root_dir = fs::stdfs::absolute(Strings::utf8_to_utf16(*args.vcpkg_root_dir)); } else { const Optional<std::wstring> vcpkg_root_dir_env = System::get_environmental_variable(L"VCPKG_ROOT"); if (auto v = vcpkg_root_dir_env.get()) { - vcpkg_root_dir = fs::absolute(*v); + vcpkg_root_dir = fs::stdfs::absolute(*v); } else { - vcpkg_root_dir = Files::find_file_recursively_up(fs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); + vcpkg_root_dir = Files::get_real_filesystem().find_file_recursively_up(fs::stdfs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root"); } } @@ -111,7 +111,7 @@ static void loadConfig() try { - auto maybe_pghs = Paragraphs::get_paragraphs(localappdata / "vcpkg" / "config"); + auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config"); if (auto p_pghs = maybe_pghs.get()) { const auto& pghs = *p_pghs; @@ -144,10 +144,12 @@ static void loadConfig() try { std::error_code ec; - fs::create_directory(localappdata / "vcpkg", ec); - std::ofstream(localappdata / "vcpkg" / "config", std::ios_base::out | std::ios_base::trunc) - << "User-Id: " << user_id << "\n" - << "User-Since: " << user_time << "\n"; + auto& fs = Files::get_real_filesystem(); + fs.create_directory(localappdata / "vcpkg", ec); + fs.write_contents(localappdata / "vcpkg" / "config", + Strings::format( + "User-Id: %s\n" + "User-Since: %s\n", user_id, user_time)); } catch (...) { } } diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index d1a2a69c1..9514184ff 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -133,7 +133,7 @@ namespace vcpkg::Dependencies if (auto bpgh = maybe_bpgh.get()) return InstallPlanAction{ spec, { nullopt, *bpgh, nullopt }, request_type }; - Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.port_dir(spec)); + Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); if (auto spgh = maybe_spgh.get()) return InstallPlanAction{ spec, { nullopt, nullopt, *spgh }, request_type }; diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 2669a9333..21896a53d 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -6,123 +6,171 @@ namespace vcpkg::Files { static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])"); - bool has_invalid_chars_for_filesystem(const std::string& s) - { - return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX); - } - - Expected<std::string> read_contents(const fs::path& file_path) noexcept + struct RealFilesystem final : Filesystem { - std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); - if (file_stream.fail()) + virtual Expected<std::string> read_contents(const fs::path& file_path) const override { - return std::errc::no_such_file_or_directory; + std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); + if (file_stream.fail()) + { + return std::errc::no_such_file_or_directory; + } + + file_stream.seekg(0, file_stream.end); + auto length = file_stream.tellg(); + file_stream.seekg(0, file_stream.beg); + + if (length > SIZE_MAX) + { + return std::errc::file_too_large; + } + + std::string output; + output.resize(static_cast<size_t>(length)); + file_stream.read(&output[0], length); + file_stream.close(); + + return std::move(output); } + virtual Expected<std::vector<std::string>> read_lines(const fs::path& file_path) const override + { + std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); + if (file_stream.fail()) + { + return std::errc::no_such_file_or_directory; + } - file_stream.seekg(0, file_stream.end); - auto length = file_stream.tellg(); - file_stream.seekg(0, file_stream.beg); + std::vector<std::string> output; + std::string line; + while (std::getline(file_stream, line)) + { + output.push_back(line); + } + file_stream.close(); - if (length > SIZE_MAX) + return std::move(output); + } + virtual fs::path find_file_recursively_up(const fs::path & starting_dir, const std::string & filename) const override { - return std::errc::file_too_large; + fs::path current_dir = starting_dir; + for (; !current_dir.empty(); current_dir = current_dir.parent_path()) + { + const fs::path candidate = current_dir / filename; + if (exists(candidate)) + { + break; + } + } + + return current_dir; } - std::string output; - output.resize(static_cast<size_t>(length)); - file_stream.read(&output[0], length); - file_stream.close(); + virtual std::vector<fs::path> get_files_recursive(const fs::path & dir) const override + { + std::vector<fs::path> ret; - return std::move(output); - } + fs::stdfs::recursive_directory_iterator b(dir), e{}; + for (; b != e; ++b) + { + ret.push_back(b->path()); + } - Expected<std::vector<std::string>> read_all_lines(const fs::path& file_path) - { - std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); - if (file_stream.fail()) - { - return std::errc::no_such_file_or_directory; + return ret; } - std::vector<std::string> output; - std::string line; - while (std::getline(file_stream, line)) + virtual std::vector<fs::path> get_files_non_recursive(const fs::path & dir) const override { - output.push_back(line); - } - file_stream.close(); + std::vector<fs::path> ret; - return std::move(output); - } + fs::stdfs::directory_iterator b(dir), e{}; + for (; b != e; ++b) + { + ret.push_back(b->path()); + } - void write_all_lines(const fs::path& file_path, const std::vector<std::string>& lines) - { - std::fstream output(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); - for (const std::string& line : lines) - { - output << line << "\n"; + return ret; } - output.close(); - } - fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename) - { - fs::path current_dir = starting_dir; - for (; !current_dir.empty(); current_dir = current_dir.parent_path()) + virtual void write_lines(const fs::path & file_path, const std::vector<std::string>& lines) override { - const fs::path candidate = current_dir / filename; - if (fs::exists(candidate)) + std::fstream output(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); + for (const std::string& line : lines) { - break; + output << line << "\n"; } + output.close(); } - return current_dir; - } - - void recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension, std::vector<fs::path>* output) - { - recursive_find_matching_paths_in_dir(dir, [&extension](const fs::path& current) - { - return !fs::is_directory(current) && current.extension() == extension; - }, output); - } - - std::vector<fs::path> recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension) - { - std::vector<fs::path> v; - recursive_find_files_with_extension_in_dir(dir, extension, &v); - return v; - } + virtual void rename(const fs::path & oldpath, const fs::path & newpath) override + { + fs::stdfs::rename(oldpath, newpath); + } + virtual bool remove(const fs::path & path) override + { + return fs::stdfs::remove(path); + } + 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) override + { + return fs::stdfs::remove_all(path, ec); + } + 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); + } + virtual bool create_directory(const fs::path & path, std::error_code & ec) override + { + return fs::stdfs::create_directory(path, ec); + } + virtual void copy(const fs::path & oldpath, const fs::path & newpath, fs::copy_options opts) override + { + fs::stdfs::copy(oldpath, newpath, opts); + } + virtual bool copy_file(const fs::path & oldpath, const fs::path & newpath, fs::copy_options opts, std::error_code & ec) override + { + return fs::stdfs::copy_file(oldpath, newpath, opts, ec); + } - void recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output) - { - recursive_find_matching_paths_in_dir(dir, [](const fs::path& current) - { - return !fs::is_directory(current); - }, output); - } + virtual fs::file_status status(const fs::path& path, std::error_code& ec) const override + { + return fs::stdfs::status(path, ec); + } + virtual void write_contents(const fs::path& file_path, const std::string& data) override + { + FILE* f = nullptr; + auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb"); + Checks::check_exit(VCPKG_LINE_INFO, ec == 0); + auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f); + fclose(f); - std::vector<fs::path> recursive_find_all_files_in_dir(const fs::path& dir) - { - std::vector<fs::path> v; - recursive_find_all_files_in_dir(dir, &v); - return v; - } + Checks::check_exit(VCPKG_LINE_INFO, count == data.size()); + } + }; - void non_recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output) + Filesystem & get_real_filesystem() { - non_recursive_find_matching_paths_in_dir(dir, [](const fs::path& current) - { - return !fs::is_directory(current); - }, output); + static RealFilesystem real_fs; + return real_fs; } - std::vector<fs::path> non_recursive_find_all_files_in_dir(const fs::path& dir) + bool has_invalid_chars_for_filesystem(const std::string& s) { - std::vector<fs::path> v; - non_recursive_find_all_files_in_dir(dir, &v); - return v; + return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX); } void print_paths(const std::vector<fs::path>& paths) diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp index 9dbdc1fee..d0fc5179c 100644 --- a/toolsrc/src/vcpkg_metrics_uploader.cpp +++ b/toolsrc/src/vcpkg_metrics_uploader.cpp @@ -11,5 +11,5 @@ int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) LPWSTR * szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount); Checks::check_exit(VCPKG_LINE_INFO, argCount == 2, "Requires exactly one argument, the path to the payload file"); - Metrics::upload(Files::read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO)); + Metrics::upload(Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO)); } diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 253c0c7ea..90d3e99b9 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -3,6 +3,7 @@ #include "vcpkg_Files.h" #include "Paragraphs.h" #include "metrics.h" +#include "vcpkg_Util.h" #include "vcpkg_Strings.h" #include "vcpkg_Util.h" @@ -10,20 +11,20 @@ namespace vcpkg { bool g_debugging = false; - static StatusParagraphs load_current_database(const fs::path& vcpkg_dir_status_file, const fs::path& vcpkg_dir_status_file_old) + static StatusParagraphs load_current_database(Files::Filesystem& fs, const fs::path& vcpkg_dir_status_file, const fs::path& vcpkg_dir_status_file_old) { - if (!fs::exists(vcpkg_dir_status_file)) + if (!fs.exists(vcpkg_dir_status_file)) { - if (!fs::exists(vcpkg_dir_status_file_old)) + if (!fs.exists(vcpkg_dir_status_file_old)) { // no status file, use empty db return StatusParagraphs(); } - fs::rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file); + fs.rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file); } - auto pghs = Paragraphs::get_paragraphs(vcpkg_dir_status_file).value_or_exit(VCPKG_LINE_INFO); + auto pghs = Paragraphs::get_paragraphs(fs, vcpkg_dir_status_file).value_or_exit(VCPKG_LINE_INFO); std::vector<std::unique_ptr<StatusParagraph>> status_pghs; for (auto&& p : pghs) @@ -36,57 +37,52 @@ namespace vcpkg StatusParagraphs database_load_check(const VcpkgPaths& paths) { + auto& fs = paths.get_filesystem(); + auto updates_dir = paths.vcpkg_dir_updates; std::error_code ec; - fs::create_directory(paths.installed, ec); - fs::create_directory(paths.vcpkg_dir, ec); - fs::create_directory(paths.vcpkg_dir_info, ec); - fs::create_directory(updates_dir, ec); + fs.create_directory(paths.installed, ec); + fs.create_directory(paths.vcpkg_dir, ec); + fs.create_directory(paths.vcpkg_dir_info, ec); + fs.create_directory(updates_dir, ec); const fs::path& status_file = paths.vcpkg_dir_status_file; const fs::path status_file_old = status_file.parent_path() / "status-old"; const fs::path status_file_new = status_file.parent_path() / "status-new"; - StatusParagraphs current_status_db = load_current_database(status_file, status_file_old); + StatusParagraphs current_status_db = load_current_database(fs, status_file, status_file_old); - auto b = fs::directory_iterator(updates_dir); - auto e = fs::directory_iterator(); - if (b == e) + auto update_files = fs.get_files_non_recursive(updates_dir); + if (update_files.empty()) { // updates directory is empty, control file is up-to-date. return current_status_db; } - - for (; b != e; ++b) + for (auto&& file : update_files) { - if (!fs::is_regular_file(b->status())) + if (!fs.is_regular_file(file)) continue; - if (b->path().filename() == "incomplete") + if (file.filename() == "incomplete") continue; - auto pghs = Paragraphs::get_paragraphs(b->path()).value_or_exit(VCPKG_LINE_INFO); + auto pghs = Paragraphs::get_paragraphs(fs, file).value_or_exit(VCPKG_LINE_INFO); for (auto&& p : pghs) { current_status_db.insert(std::make_unique<StatusParagraph>(p)); } } - std::fstream(status_file_new, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc) << current_status_db; + fs.write_contents(status_file_new, Strings::serialize(current_status_db)); - if (fs::exists(status_file_old)) - fs::remove(status_file_old); - if (fs::exists(status_file)) - fs::rename(status_file, status_file_old); - fs::rename(status_file_new, status_file); - fs::remove(status_file_old); + fs.rename(status_file_new, status_file); - b = fs::directory_iterator(updates_dir); - for (; b != e; ++b) + for (auto&& file : update_files) { - if (!fs::is_regular_file(b->status())) + if (!fs.is_regular_file(file)) continue; - fs::remove(b->path()); + + fs.remove(file); } return current_status_db; @@ -95,16 +91,17 @@ namespace vcpkg void write_update(const VcpkgPaths& paths, const StatusParagraph& p) { static int update_id = 0; + auto& fs = paths.get_filesystem(); + auto my_update_id = update_id++; auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete"; auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id); - std::fstream fs(tmp_update_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); - fs << p; - fs.close(); - fs::rename(tmp_update_filename, update_filename); + + fs.write_contents(tmp_update_filename, Strings::serialize(p)); + fs.rename(tmp_update_filename, update_filename); } - static void upgrade_to_slash_terminated_sorted_format(std::vector<std::string>* lines, const fs::path& listfile_path) + static void upgrade_to_slash_terminated_sorted_format(Files::Filesystem& fs, std::vector<std::string>* lines, const fs::path& listfile_path) { static bool was_tracked = false; @@ -168,8 +165,8 @@ namespace vcpkg // Replace the listfile on disk const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated"; - Files::write_all_lines(updated_listfile_path, *lines); - fs::rename(updated_listfile_path, listfile_path); + fs.write_lines(updated_listfile_path, *lines); + fs.rename(updated_listfile_path, listfile_path); } std::vector<StatusParagraph*> get_installed_ports(const StatusParagraphs& status_db) @@ -187,6 +184,8 @@ namespace vcpkg std::vector<StatusParagraphAndAssociatedFiles> get_installed_files(const VcpkgPaths& paths, const StatusParagraphs& status_db) { + auto& fs = paths.get_filesystem(); + std::vector<StatusParagraphAndAssociatedFiles> installed_files; for (const std::unique_ptr<StatusParagraph>& pgh : status_db) @@ -197,9 +196,9 @@ namespace vcpkg } const fs::path listfile_path = paths.listfile_path(pgh->package); - std::vector<std::string> installed_files_of_current_pgh = Files::read_all_lines(listfile_path).value_or_exit(VCPKG_LINE_INFO); + std::vector<std::string> installed_files_of_current_pgh = fs.read_lines(listfile_path).value_or_exit(VCPKG_LINE_INFO); Strings::trim_all_and_remove_whitespace_strings(&installed_files_of_current_pgh); - upgrade_to_slash_terminated_sorted_format(&installed_files_of_current_pgh, listfile_path); + upgrade_to_slash_terminated_sorted_format(fs, &installed_files_of_current_pgh, listfile_path); // Remove the directories Util::erase_remove_if(installed_files_of_current_pgh, [](const std::string& file) { return file.back() == '/'; }); |
