diff options
Diffstat (limited to 'toolsrc/src')
28 files changed, 262 insertions, 107 deletions
diff --git a/toolsrc/src/BuildInfo.cpp b/toolsrc/src/BuildInfo.cpp index ddd44a1e6..f151a3ea5 100644 --- a/toolsrc/src/BuildInfo.cpp +++ b/toolsrc/src/BuildInfo.cpp @@ -151,7 +151,7 @@ namespace vcpkg { namespace PostBuildLint const OutdatedDynamicCrt OutdatedDynamicCrt::MSVCRT20_DLL = OutdatedDynamicCrt("msvcrt20.dll", R"(msvcrt20\.dll)");; const OutdatedDynamicCrt OutdatedDynamicCrt::MSVCRT40_DLL = OutdatedDynamicCrt("msvcrt40.dll", R"(msvcrt40\.dll)");; - const std::regex OutdatedDynamicCrt::crt_regex() const + std::regex OutdatedDynamicCrt::crt_regex() const { const std::regex r(this->m_crt_regex_as_string, std::regex_constants::icase); return r; diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 5efa9a7b3..823b4a85e 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -153,7 +153,7 @@ namespace vcpkg { namespace Paragraphs std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path) { - return parse_paragraphs(Files::get_contents(control_path).get_or_throw()); + return parse_paragraphs(Files::read_contents(control_path).get_or_throw()); } std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str) diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp index 3bf7922f5..1f30ea70b 100644 --- a/toolsrc/src/coff_file_reader.cpp +++ b/toolsrc/src/coff_file_reader.cpp @@ -223,7 +223,7 @@ namespace vcpkg { namespace COFFFileReader verify_equal_strings(FILE_START, file_start, FILE_START_SIZE, "LIB FILE_START"); } - dll_info read_dll(const fs::path path) + dll_info read_dll(const fs::path& path) { std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); Checks::check_exit(fs.is_open(), "Could not open file %s for reading", path.generic_string()); @@ -260,7 +260,7 @@ namespace vcpkg { namespace COFFFileReader fpos_t m_absolute_position = 0; }; - lib_info read_lib(const fs::path path) + lib_info read_lib(const fs::path& path) { std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate); Checks::check_exit(fs.is_open(), "Could not open file %s for reading", path.generic_string()); diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index 19c762caf..1a10b93cf 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -15,7 +15,7 @@ namespace vcpkg try { - auto file_contents = Files::get_contents(path / "CONTROL"); + auto file_contents = Files::read_contents(path / "CONTROL"); if (auto text = file_contents.get()) { auto pghs = Paragraphs::parse_paragraphs(*text); @@ -38,7 +38,7 @@ namespace vcpkg { static const std::string example = Strings::format( "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", create_example_string("cache png")); - args.check_max_arg_count(1, example.c_str()); + args.check_max_arg_count(1, example); const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths); if (binary_paragraphs.empty()) @@ -52,7 +52,7 @@ namespace vcpkg for (const BinaryParagraph& binary_paragraph : binary_paragraphs) { const std::string displayname = binary_paragraph.displayname(); - System::println(displayname.c_str()); + System::println(displayname); } } else @@ -66,7 +66,7 @@ namespace vcpkg continue; } - System::println(displayname.c_str()); + System::println(displayname); } } diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp index d1611eb5c..ad00cd676 100644 --- a/toolsrc/src/commands_create.cpp +++ b/toolsrc/src/commands_create.cpp @@ -9,8 +9,8 @@ namespace vcpkg void create_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { static const std::string example = create_example_string(R"###(create zlib2 http://zlib.net/zlib128.zip "zlib128-2.zip")###"); - args.check_max_arg_count(3, example.c_str()); - args.check_min_arg_count(2, example.c_str()); + args.check_max_arg_count(3, example); + args.check_min_arg_count(2, example); const std::string port_name = args.command_arguments.at(0); Environment::ensure_utilities_on_path(paths); diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index f07a15875..fbf4eab62 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -7,7 +7,7 @@ namespace vcpkg void edit_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { static const std::string example = create_example_string("edit zlib"); - args.check_exact_arg_count(1, example.c_str()); + args.check_exact_arg_count(1, example); const std::string port_name = args.command_arguments.at(0); const fs::path portpath = paths.ports / port_name; diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp index 17c191b78..0e3e8a77c 100644 --- a/toolsrc/src/commands_hash.cpp +++ b/toolsrc/src/commands_hash.cpp @@ -20,15 +20,15 @@ namespace vcpkg auto hash = output.substr(start, end - start); hash.erase(std::remove_if(hash.begin(), hash.end(), isspace), hash.end()); - System::println(hash.c_str()); + System::println(hash); } void hash_command(const vcpkg_cmd_arguments& args) { static const std::string example = Strings::format( "The argument should be a file path\n%s", create_example_string("hash boost_1_62_0.tar.bz2")); - args.check_min_arg_count(1, example.c_str()); - args.check_max_arg_count(2, example.c_str()); + args.check_min_arg_count(1, example); + args.check_max_arg_count(2, example); if (args.command_arguments.size() == 1) { diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index e5e731799..3832f0e7b 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -78,7 +78,7 @@ namespace vcpkg void import_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { static const std::string example = create_example_string(R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); - args.check_exact_arg_count(3, example.c_str()); + args.check_exact_arg_count(3, example); const fs::path control_file_path(args.command_arguments[0]); const fs::path include_directory(args.command_arguments[1]); diff --git a/toolsrc/src/commands_installation.cpp b/toolsrc/src/commands_installation.cpp index 1abd16796..8d940bc9d 100644 --- a/toolsrc/src/commands_installation.cpp +++ b/toolsrc/src/commands_installation.cpp @@ -69,16 +69,16 @@ namespace vcpkg static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryParagraph& bpgh) { - std::fstream listfile(paths.listfile_path(bpgh), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc); + std::vector<std::string> output; - auto package_prefix_path = paths.package_dir(bpgh.spec); - auto prefix_length = package_prefix_path.native().size(); + const fs::path package_prefix_path = paths.package_dir(bpgh.spec); + const size_t prefix_length = package_prefix_path.native().size(); const triplet& target_triplet = bpgh.spec.target_triplet(); const std::string& target_triplet_as_string = target_triplet.canonical_name(); std::error_code ec; fs::create_directory(paths.installed / target_triplet_as_string, ec); - listfile << target_triplet << "\n"; + output.push_back(Strings::format(R"(%s)", target_triplet_as_string)); for (auto it = fs::recursive_directory_iterator(package_prefix_path); it != fs::recursive_directory_iterator(); ++it) { @@ -89,8 +89,8 @@ namespace vcpkg continue; } - auto suffix = it->path().generic_u8string().substr(prefix_length + 1); - auto target = paths.installed / target_triplet_as_string / suffix; + const std::string suffix = it->path().generic_u8string().substr(prefix_length + 1); + const fs::path target = paths.installed / target_triplet_as_string / suffix; auto status = it->status(ec); if (ec) @@ -98,6 +98,7 @@ namespace vcpkg System::println(System::color::error, "failed: %s: %s", it->path().u8string(), ec.message()); continue; } + if (fs::is_directory(status)) { fs::create_directory(target, ec); @@ -106,26 +107,36 @@ namespace vcpkg System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message()); } - listfile << target_triplet << "/" << suffix << "\n"; + // Trailing backslash for directories + output.push_back(Strings::format(R"(%s/%s)", target_triplet_as_string, suffix)); + continue; } - else if (fs::is_regular_file(status)) + + if (fs::is_regular_file(status)) { - fs::copy_file(*it, target, ec); + 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); if (ec) { System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message()); } - listfile << target_triplet << "/" << suffix << "\n"; + output.push_back(Strings::format(R"(%s/%s)", target_triplet_as_string, suffix)); + continue; } - else if (!fs::status_known(status)) + + if (!fs::status_known(status)) { System::println(System::color::error, "failed: %s: unknown status", it->path().u8string()); + continue; } - else - 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", it->path().u8string()); } - listfile.close(); + Files::write_all_lines(paths.listfile_path(bpgh), output); } static void remove_first_n_chars(std::vector<std::string>* strings, const size_t n) @@ -161,7 +172,9 @@ namespace vcpkg const size_t package_remove_char_count = package_dir.generic_string().size() + 1; // +1 for the slash std::transform(package_file_paths.cbegin(), package_file_paths.cend(), std::back_inserter(package_files), [package_remove_char_count](const fs::path& path) { - return path.generic_string().erase(0, package_remove_char_count); + std::string as_string = path.generic_string(); + as_string.erase(0, package_remove_char_count); + return std::move(as_string); }); std::sort(package_files.begin(), package_files.end()); @@ -216,10 +229,10 @@ namespace vcpkg void install_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) { static const std::string example = create_example_string("install zlib zlib:x64-windows curl boost"); - args.check_min_arg_count(1, example.c_str()); + args.check_min_arg_count(1, example); StatusParagraphs status_db = database_load_check(paths); - std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example.c_str()); + std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example); Input::check_triplets(specs, paths); std::vector<package_spec_with_install_plan> install_plan = Dependencies::create_install_plan(paths, specs, status_db); Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty"); @@ -276,11 +289,11 @@ namespace vcpkg // Installing multiple packages leads to unintuitive behavior if one of them depends on another. // Allowing only 1 package for now. - args.check_exact_arg_count(1, example.c_str()); + args.check_exact_arg_count(1, example); StatusParagraphs status_db = database_load_check(paths); - const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example.c_str()); + const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example); Input::check_triplet(spec.target_triplet(), paths); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); @@ -332,7 +345,7 @@ namespace vcpkg void build_external_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) { static const std::string example = create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); - args.check_exact_arg_count(2, example.c_str()); + args.check_exact_arg_count(2, example); expected<package_spec> maybe_current_spec = package_spec::from_string(args.command_arguments[0], default_target_triplet); if (auto spec = maybe_current_spec.get()) @@ -349,7 +362,7 @@ namespace vcpkg } System::println(System::color::error, "Error: %s: %s", maybe_current_spec.error_code().message(), args.command_arguments[0]); - print_example(Strings::format("%s zlib:x64-windows", args.command).c_str()); + print_example(Strings::format("%s zlib:x64-windows", args.command)); exit(EXIT_FAILURE); } } diff --git a/toolsrc/src/commands_integration.cpp b/toolsrc/src/commands_integration.cpp index cd303c649..e7e5b2d8d 100644 --- a/toolsrc/src/commands_integration.cpp +++ b/toolsrc/src/commands_integration.cpp @@ -173,7 +173,7 @@ namespace vcpkg bool should_install_system = true; if (fs::exists(system_wide_targets_file)) { - auto system_wide_file_contents = Files::get_contents(system_wide_targets_file); + auto system_wide_file_contents = Files::read_contents(system_wide_targets_file); if (auto contents_data = system_wide_file_contents.get()) { std::regex re(R"###(<!-- version (\d+) -->)###"); @@ -297,7 +297,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console { static const std::string example = Strings::format("Commands:\n" "%s", INTEGRATE_COMMAND_HELPSTRING); - args.check_exact_arg_count(1, example.c_str()); + args.check_exact_arg_count(1, example); if (args.command_arguments[0] == "install") { diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 2d6b42008..cc51232e9 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -17,7 +17,7 @@ namespace vcpkg { static const std::string example = Strings::format( "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", create_example_string("list png")); - args.check_max_arg_count(1, example.c_str()); + args.check_max_arg_count(1, example); const StatusParagraphs status_paragraphs = database_load_check(paths); std::vector<StatusParagraph> installed_packages; diff --git a/toolsrc/src/commands_other.cpp b/toolsrc/src/commands_other.cpp index 5f4128bb1..6df325100 100644 --- a/toolsrc/src/commands_other.cpp +++ b/toolsrc/src/commands_other.cpp @@ -41,16 +41,16 @@ namespace vcpkg , INTEGRATE_COMMAND_HELPSTRING); } - std::string create_example_string(const char* command_and_arguments) + std::string create_example_string(const std::string& command_and_arguments) { std::string cs = Strings::format("Example:\n" " vcpkg %s", command_and_arguments); return cs; } - void print_example(const char* command_and_arguments) + void print_example(const std::string& command_and_arguments) { - System::println(create_example_string(command_and_arguments).c_str()); + System::println(create_example_string(command_and_arguments)); } void internal_test_command(const vcpkg_cmd_arguments& /*args*/, const vcpkg_paths& /*paths*/) @@ -74,6 +74,7 @@ namespace vcpkg const std::vector<package_name_and_function<command_type_b>>& get_available_commands_type_b() { static std::vector<package_name_and_function<command_type_b>> t = { + {"/?", help_command}, {"help", help_command}, {"search", search_command}, {"list", list_command}, diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp index 45f073304..62dac57eb 100644 --- a/toolsrc/src/commands_owns.cpp +++ b/toolsrc/src/commands_owns.cpp @@ -24,7 +24,7 @@ namespace vcpkg void owns_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { static const std::string example = Strings::format("The argument should be a pattern to search for. %s", create_example_string("owns zlib.dll")); - args.check_exact_arg_count(1, example.c_str()); + args.check_exact_arg_count(1, example); StatusParagraphs status_db = database_load_check(paths); search_file(paths, args.command_arguments[0], status_db); diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index b6b604e54..46c6c90c7 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -100,8 +100,8 @@ namespace vcpkg void portsdiff_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { static const std::string example = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", create_example_string("portsdiff mybranchname")); - args.check_min_arg_count(1, example.c_str()); - args.check_max_arg_count(2, example.c_str()); + args.check_min_arg_count(1, example); + args.check_max_arg_count(2, example); Environment::ensure_git_on_path(paths); const std::wstring git_commit_id_for_previous_snapshot = Strings::utf8_to_utf16(args.command_arguments.at(0)); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index 31331fc2f..445213fc2 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -169,12 +169,12 @@ namespace vcpkg void remove_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) { static const std::string example = create_example_string("remove zlib zlib:x64-windows curl boost"); - args.check_min_arg_count(1, example.c_str()); + args.check_min_arg_count(1, example); const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_PURGE}); auto status_db = database_load_check(paths); - std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example.c_str()); + std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example); Input::check_triplets(specs, paths); bool alsoRemoveFolderFromPackages = options.find(OPTION_PURGE) != options.end(); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index a604c5383..a4714477e 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -43,7 +43,7 @@ namespace vcpkg void search_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { static const std::string example = Strings::format("The argument should be a substring to search for, or no argument to display all libraries.\n%s", create_example_string("search png")); - args.check_max_arg_count(1, example.c_str()); + args.check_max_arg_count(1, example); const std::vector<SourceParagraph> source_paragraphs = read_all_source_paragraphs(paths); diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index 82e3b7e52..a4ab7c6e7 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -71,7 +71,7 @@ namespace vcpkg System::println("\nTo update these packages, run\n vcpkg remove --purge <pkgs>...\n vcpkg install <pkgs>..."); } - auto version_file = Files::get_contents(paths.root / "toolsrc" / "VERSION.txt"); + auto version_file = Files::read_contents(paths.root / "toolsrc" / "VERSION.txt"); if (auto version_contents = version_file.get()) { int maj1, min1, rev1; diff --git a/toolsrc/src/main.cpp b/toolsrc/src/main.cpp index f937be7f1..7703c541f 100644 --- a/toolsrc/src/main.cpp +++ b/toolsrc/src/main.cpp @@ -113,7 +113,7 @@ static void loadConfig() try { - std::string config_contents = Files::get_contents(localappdata / "vcpkg" / "config").get_or_throw(); + std::string config_contents = Files::read_contents(localappdata / "vcpkg" / "config").get_or_throw(); std::unordered_map<std::string, std::string> keys; auto pghs = Paragraphs::parse_paragraphs(config_contents); @@ -197,6 +197,7 @@ int wmain(const int argc, const wchar_t* const* const argv) const std::string trimmed_command_line = trim_path_from_command_line(Strings::utf16_to_utf8(GetCommandLineW())); TrackProperty("cmdline", trimmed_command_line); loadConfig(); + TrackProperty("sqmuser", GetSQMUser()); const vcpkg_cmd_arguments args = vcpkg_cmd_arguments::create_from_command_line(argc, argv); diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 23962bcfe..51c7179c8 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -235,6 +235,40 @@ true return DISABLE_METRICS == 0; } + std::wstring GetSQMUser() + { + LONG err = NULL; + + struct RAII_HKEY { + HKEY hkey = NULL; + ~RAII_HKEY() + { + if (hkey != NULL) + RegCloseKey(hkey); + } + } HKCU_SQMClient; + + err = RegOpenKeyExW(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", NULL, KEY_READ, &HKCU_SQMClient.hkey); + if (err != ERROR_SUCCESS) + { + return L"{}"; + } + + std::array<wchar_t,128> buffer; + DWORD lType = 0; + DWORD dwBufferSize = static_cast<DWORD>(buffer.size() * sizeof(wchar_t)); + err = RegQueryValueExW(HKCU_SQMClient.hkey, L"UserId", NULL, &lType, reinterpret_cast<LPBYTE>(buffer.data()), &dwBufferSize); + if (err == ERROR_SUCCESS && lType == REG_SZ && dwBufferSize >= sizeof(wchar_t)) + { + size_t sz = dwBufferSize / sizeof(wchar_t); + if (buffer[sz - 1] == '\0') + --sz; + return std::wstring(buffer.begin(), buffer.begin() + sz); + } + + return L"{}"; + } + void SetUserInformation(const std::string& user_id, const std::string& first_use_time) { g_metricmessage.user_id = user_id; diff --git a/toolsrc/src/post_build_lint.cpp b/toolsrc/src/post_build_lint.cpp index 3043bd4fa..4f0adf677 100644 --- a/toolsrc/src/post_build_lint.cpp +++ b/toolsrc/src/post_build_lint.cpp @@ -507,7 +507,7 @@ namespace vcpkg { namespace PostBuildLint static lint_status check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls) { - const std::vector<OutdatedDynamicCrt> outdated_crts = OutdatedDynamicCrt::values(); + const std::vector<OutdatedDynamicCrt>& outdated_crts = OutdatedDynamicCrt::values(); std::vector<OutdatedDynamicCrt_and_file> dlls_with_outdated_crt; diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 88b05b0a9..4748aeb54 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -10,6 +10,7 @@ #include "vcpkg_Files.h" #include "Paragraphs.h" #include <regex> +#include "metrics.h" using namespace vcpkg; @@ -26,7 +27,7 @@ static StatusParagraphs load_current_database(const fs::path& vcpkg_dir_status_f fs::rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file); } - auto text = Files::get_contents(vcpkg_dir_status_file).get_or_throw(); + auto text = Files::read_contents(vcpkg_dir_status_file).get_or_throw(); auto pghs = Paragraphs::parse_paragraphs(text); std::vector<std::unique_ptr<StatusParagraph>> status_pghs; @@ -69,7 +70,7 @@ StatusParagraphs vcpkg::database_load_check(const vcpkg_paths& paths) if (b->path().filename() == "incomplete") continue; - auto text = Files::get_contents(b->path()).get_or_throw(); + auto text = Files::read_contents(b->path()).get_or_throw(); auto pghs = Paragraphs::parse_paragraphs(text); for (auto&& p : pghs) { @@ -109,60 +110,102 @@ void vcpkg::write_update(const vcpkg_paths& paths, const StatusParagraph& p) fs::rename(tmp_update_filename, update_filename); } -std::vector<StatusParagraph_and_associated_files> vcpkg::get_installed_files(const vcpkg_paths& paths, const StatusParagraphs& status_db) +static void upgrade_to_slash_terminated_sorted_format(std::vector<std::string>* lines, const fs::path& listfile_path) { - static const std::string MARK_FOR_REMOVAL = ""; + static bool was_tracked = false; - std::vector<StatusParagraph_and_associated_files> installed_files; + if (lines->empty()) + { + return; + } - std::string line; + if (lines->at(0).back() == '/') + { + return; // File already in the new format + } - for (const std::unique_ptr<StatusParagraph>& pgh : status_db) + if (!was_tracked) { - if (pgh->state != install_state_t::installed) - { - continue; - } + was_tracked = true; + TrackProperty("listfile", "update to new format"); + } - std::fstream listfile(paths.listfile_path(pgh->package)); + // The files are sorted such that directories are placed just before the files they contain + // (They are not necessarily sorted alphabetically, e.g. libflac) + // Therefore we can detect the entries that represent directories by comparing every element with the next one + // and checking if the next has a slash immediately after the current one's length + for (size_t i = 0; i < lines->size() - 1; i++) + { + std::string& current_string = lines->at(i); + const std::string& next_string = lines->at(i + 1); - std::vector<std::string> installed_files_of_current_pgh; - while (std::getline(listfile, line)) + const size_t potential_slash_char_index = current_string.length(); + // Make sure the index exists first + if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/') { - if (line.empty()) - { - continue; - } - - installed_files_of_current_pgh.push_back(line); + current_string += '/'; // Mark as a directory } + } + + // After suffixing the directories with a slash, we can now sort. + // We cannot sort before adding the suffixes because the following (actual example): + /* + x86-windows/include/FLAC <<<<<< This would be separated from its group due to sorting + x86-windows/include/FLAC/all.h + x86-windows/include/FLAC/assert.h + x86-windows/include/FLAC/callback.h + x86-windows/include/FLAC++ + x86-windows/include/FLAC++/all.h + x86-windows/include/FLAC++/decoder.h + x86-windows/include/FLAC++/encoder.h + * + x86-windows/include/FLAC/ <<<<<< This will now be kept with its group when sorting + x86-windows/include/FLAC/all.h + x86-windows/include/FLAC/assert.h + x86-windows/include/FLAC/callback.h + x86-windows/include/FLAC++/ + x86-windows/include/FLAC++/all.h + x86-windows/include/FLAC++/decoder.h + x86-windows/include/FLAC++/encoder.h + */ + // Note that after sorting, the FLAC++/ group will be placed before the FLAC/ group + // The new format is lexicographically sorted + std::sort(lines->begin(), lines->end()); + +#if 0 + // 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); +#endif +} - // Should already be sorted - std::sort(installed_files_of_current_pgh.begin(), installed_files_of_current_pgh.end()); +std::vector<StatusParagraph_and_associated_files> vcpkg::get_installed_files(const vcpkg_paths& paths, const StatusParagraphs& status_db) +{ + std::vector<StatusParagraph_and_associated_files> installed_files; - // Since the files are sorted, we can detect the entries that represent directories - // by comparing every element with the next one and checking if the next has a slash immediately after the current one's length - for (int i = 1; i < installed_files_of_current_pgh.size(); i++) + for (const std::unique_ptr<StatusParagraph>& pgh : status_db) + { + if (pgh->state != install_state_t::installed) { - std::string& current_string = installed_files_of_current_pgh.at(i - 1); - const std::string& next_string = installed_files_of_current_pgh.at(i); - - const size_t potential_slash_char_index = current_string.length(); - // Make sure the index exists first - if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/') - { - current_string = MARK_FOR_REMOVAL; - } + continue; } - installed_files_of_current_pgh.erase(std::remove_if(installed_files_of_current_pgh.begin(), installed_files_of_current_pgh.end(), [](const std::string& file) - { - return file == MARK_FOR_REMOVAL; - }), - installed_files_of_current_pgh.end()); - - const StatusParagraph_and_associated_files pgh_and_files = {*pgh, std::move(installed_files_of_current_pgh)}; - installed_files.push_back(pgh_and_files); + 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).get_or_throw(); + 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); + + // Remove the directories + installed_files_of_current_pgh.erase( + std::remove_if(installed_files_of_current_pgh.begin(), installed_files_of_current_pgh.end(), [](const std::string& file) -> bool + { + return file.back() == '/'; + } + ), installed_files_of_current_pgh.end()); + + StatusParagraph_and_associated_files pgh_and_files = {*pgh, std::move(installed_files_of_current_pgh)}; + installed_files.push_back(std::move(pgh_and_files)); } return installed_files; @@ -187,7 +230,7 @@ expected<BinaryParagraph> vcpkg::try_load_cached_package(const vcpkg_paths& path { const fs::path path = paths.package_dir(spec) / "CONTROL"; - auto control_contents_maybe = Files::get_contents(path); + auto control_contents_maybe = Files::read_contents(path); if (auto control_contents = control_contents_maybe.get()) { std::vector<std::unordered_map<std::string, std::string>> pghs; diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 41172ba0f..ae7f697fa 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -58,7 +58,7 @@ namespace vcpkg { namespace Dependencies expected<SourceParagraph> maybe_spgh = try_load_port(paths, spec.name()); SourceParagraph* spgh = maybe_spgh.get(); - Checks::check_exit(spgh != nullptr, "Cannot find package"); + Checks::check_exit(spgh != nullptr, "Cannot find package %s", spec.name()); process_dependencies(filter_dependencies(spgh->depends, spec.target_triplet())); was_examined.emplace(spec, install_plan_action{install_plan_type::BUILD_AND_INSTALL, nullptr, std::make_unique<SourceParagraph>(std::move(*spgh))}); } diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 698579736..48283e43f 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -9,15 +9,15 @@ namespace vcpkg {namespace Files void check_is_directory(const fs::path& dirpath) { - Checks::check_throw(fs::is_directory(dirpath), "The path %s is not a directory", dirpath.string()); + Checks::check_exit(fs::is_directory(dirpath), "The path %s is not a directory", dirpath.string()); } - bool has_invalid_chars_for_filesystem(const std::string s) + bool has_invalid_chars_for_filesystem(const std::string& s) { return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX); } - expected<std::string> get_contents(const fs::path& file_path) noexcept + expected<std::string> read_contents(const fs::path& file_path) noexcept { std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); if (file_stream.fail()) @@ -42,6 +42,35 @@ namespace vcpkg {namespace Files return std::move(output); } + 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; + } + + std::vector<std::string> output; + std::string line; + while (std::getline(file_stream, line)) + { + output.push_back(line); + } + file_stream.close(); + + return std::move(output); + } + + 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"; + } + output.close(); + } + fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename) { fs::path current_dir = starting_dir; diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp index f7aae1929..29d487fdb 100644 --- a/toolsrc/src/vcpkg_Input.cpp +++ b/toolsrc/src/vcpkg_Input.cpp @@ -5,7 +5,7 @@ namespace vcpkg {namespace Input { - package_spec check_and_get_package_spec(const std::string& package_spec_as_string, const triplet& default_target_triplet, const char* example_text) + package_spec check_and_get_package_spec(const std::string& package_spec_as_string, const triplet& default_target_triplet, const std::string& example_text) { const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); expected<package_spec> expected_spec = package_spec::from_string(as_lowercase, default_target_triplet); @@ -20,7 +20,7 @@ namespace vcpkg {namespace Input exit(EXIT_FAILURE); } - std::vector<package_spec> check_and_get_package_specs(const std::vector<std::string>& package_specs_as_strings, const triplet& default_target_triplet, const char* example_text) + std::vector<package_spec> check_and_get_package_specs(const std::vector<std::string>& package_specs_as_strings, const triplet& default_target_triplet, const std::string& example_text) { std::vector<package_spec> specs; for (const std::string& spec : package_specs_as_strings) diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 19ba8595f..46a4b1855 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -4,9 +4,17 @@ #include <algorithm> #include <codecvt> #include <iterator> +#include <functional> +#include <cctype> namespace vcpkg {namespace Strings {namespace details { + // To disambiguate between two overloads + static const auto isspace = [](const char c) + { + return std::isspace(c); + }; + std::string format_internal(const char* fmtstr, ...) { va_list lst; @@ -85,4 +93,30 @@ namespace vcpkg {namespace Strings return output; } + + void trim(std::string* s) + { + s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end()); + s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace)); + } + + std::string trimmed(const std::string& s) + { + auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(); + auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace); + return std::string(whitespace_front, whitespace_back); + } + + void trim_all_and_remove_whitespace_strings(std::vector<std::string>* strings) + { + for (std::string& s : *strings) + { + trim(&s); + } + + strings->erase(std::remove_if(strings->begin(), strings->end(), [](const std::string& s)-> bool + { + return s == ""; + }), strings->end()); + } }} diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index cb3eb6584..43eae3412 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -56,7 +56,7 @@ namespace vcpkg {namespace System std::cout << "\n"; } - void print(color c, const char* message) + void print(const color c, const char* message) { HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); @@ -69,7 +69,7 @@ namespace vcpkg {namespace System SetConsoleTextAttribute(hConsole, original_color); } - void println(color c, const char* message) + void println(const color c, const char* message) { print(c, message); std::cout << "\n"; diff --git a/toolsrc/src/vcpkg_cmd_arguments.cpp b/toolsrc/src/vcpkg_cmd_arguments.cpp index d61e420ab..a3648668f 100644 --- a/toolsrc/src/vcpkg_cmd_arguments.cpp +++ b/toolsrc/src/vcpkg_cmd_arguments.cpp @@ -156,7 +156,7 @@ namespace vcpkg System::println(System::color::error, "Unknown option(s) for command '%s':", this->command); for (const std::string& option : options_copy) { - System::println(option.c_str()); + System::println(option); } exit(EXIT_FAILURE); } @@ -179,7 +179,7 @@ namespace vcpkg return check_exact_arg_count(expected_arg_count, ""); } - void vcpkg_cmd_arguments::check_max_arg_count(const size_t expected_arg_count, const char* example_text) const + void vcpkg_cmd_arguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const { const size_t actual_arg_count = command_arguments.size(); if (actual_arg_count > expected_arg_count) @@ -190,7 +190,7 @@ namespace vcpkg } } - void vcpkg_cmd_arguments::check_min_arg_count(const size_t expected_arg_count, const char* example_text) const + void vcpkg_cmd_arguments::check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const { const size_t actual_arg_count = command_arguments.size(); if (actual_arg_count < expected_arg_count) @@ -201,7 +201,7 @@ namespace vcpkg } } - void vcpkg_cmd_arguments::check_exact_arg_count(const size_t expected_arg_count, const char* example_text) const + void vcpkg_cmd_arguments::check_exact_arg_count(const size_t expected_arg_count, const std::string& example_text) const { const size_t actual_arg_count = command_arguments.size(); if (actual_arg_count != expected_arg_count) diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp index 63668d1d7..14fc9ae48 100644 --- a/toolsrc/src/vcpkg_metrics_uploader.cpp +++ b/toolsrc/src/vcpkg_metrics_uploader.cpp @@ -19,5 +19,5 @@ WinMain( szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount); Checks::check_exit(argCount == 2, "Requires exactly one argument, the path to the payload file"); - Upload(Files::get_contents(szArgList[1]).get_or_throw()); + Upload(Files::read_contents(szArgList[1]).get_or_throw()); } |
