diff options
| author | Alexander Karatarakis <alkarata@microsoft.com> | 2017-03-24 10:46:49 -0700 |
|---|---|---|
| committer | Alexander Karatarakis <alkarata@microsoft.com> | 2017-03-27 12:43:14 -0700 |
| commit | d2bab3c370fca9fa5216d97495810faaeeaebc2d (patch) | |
| tree | 205fd2130c93e9fe40975a271dd11381b562fead | |
| parent | 90bb4a2eeb316fbc5055d507044229cbc8bc5337 (diff) | |
| download | vcpkg-d2bab3c370fca9fa5216d97495810faaeeaebc2d.tar.gz vcpkg-d2bab3c370fca9fa5216d97495810faaeeaebc2d.zip | |
Rework Paragraph parsing error handling. Add single paragraph functions
| -rw-r--r-- | toolsrc/include/Paragraphs.h | 6 | ||||
| -rw-r--r-- | toolsrc/include/paragraph_parse_result.h | 35 | ||||
| -rw-r--r-- | toolsrc/src/Paragraphs.cpp | 57 | ||||
| -rw-r--r-- | toolsrc/src/PostBuildLint_BuildInfo.cpp | 8 | ||||
| -rw-r--r-- | toolsrc/src/commands_cache.cpp | 19 | ||||
| -rw-r--r-- | toolsrc/src/commands_import.cpp | 6 | ||||
| -rw-r--r-- | toolsrc/src/paragraph_parse_result.cpp | 45 | ||||
| -rw-r--r-- | toolsrc/src/tests_paragraph.cpp | 24 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg.cpp | 4 | ||||
| -rw-r--r-- | toolsrc/src/vcpkglib.cpp | 6 | ||||
| -rw-r--r-- | toolsrc/vcpkglib/vcpkglib.vcxproj | 2 | ||||
| -rw-r--r-- | toolsrc/vcpkglib/vcpkglib.vcxproj.filters | 6 |
12 files changed, 153 insertions, 65 deletions
diff --git a/toolsrc/include/Paragraphs.h b/toolsrc/include/Paragraphs.h index 79b66a67f..74f8218ca 100644 --- a/toolsrc/include/Paragraphs.h +++ b/toolsrc/include/Paragraphs.h @@ -8,8 +8,10 @@ namespace vcpkg::Paragraphs { - std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path); - std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str); + expected<std::unordered_map<std::string, std::string>> get_single_paragraph(const fs::path& control_path); + expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const fs::path& control_path); + expected<std::unordered_map<std::string, std::string>> parse_single_paragraph(const std::string& str); + expected<std::vector<std::unordered_map<std::string, std::string>>> parse_paragraphs(const std::string& str); expected<SourceParagraph> try_load_port(const fs::path& control_path); diff --git a/toolsrc/include/paragraph_parse_result.h b/toolsrc/include/paragraph_parse_result.h new file mode 100644 index 000000000..47f20c08e --- /dev/null +++ b/toolsrc/include/paragraph_parse_result.h @@ -0,0 +1,35 @@ +#pragma once +#include <system_error> + +namespace vcpkg +{ + enum class paragraph_parse_result + { + SUCCESS = 0, + EXPECTED_ONE_PARAGRAPH + }; + + struct paragraph_parse_result_category_impl final : std::error_category + { + virtual const char* name() const noexcept override; + + virtual std::string message(int ev) const noexcept override; + }; + + const std::error_category& paragraph_parse_result_category(); + + std::error_code make_error_code(paragraph_parse_result e); + + paragraph_parse_result to_paragraph_parse_result(int i); + + paragraph_parse_result to_paragraph_parse_result(std::error_code ec); +} + +// Enable implicit conversion to std::error_code +namespace std +{ + template <> + struct is_error_code_enum<vcpkg::paragraph_parse_result> : ::std::true_type + { + }; +} diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index f1505698c..2bdddb58c 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "Paragraphs.h" #include "vcpkg_Files.h" +#include "paragraph_parse_result.h" namespace vcpkg::Paragraphs { @@ -150,7 +151,18 @@ namespace vcpkg::Paragraphs } }; - std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path) + expected<std::unordered_map<std::string, std::string>> get_single_paragraph(const fs::path& control_path) + { + const expected<std::string> contents = Files::read_contents(control_path); + if (auto spgh = contents.get()) + { + return parse_single_paragraph(*spgh); + } + + return contents.error_code(); + } + + expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const fs::path& control_path) { const expected<std::string> contents = Files::read_contents(control_path); if (auto spgh = contents.get()) @@ -158,44 +170,47 @@ namespace vcpkg::Paragraphs return parse_paragraphs(*spgh); } - Checks::exit_with_message(VCPKG_LINE_INFO, "Error while reading %s: %s", control_path.generic_string(), contents.error_code().message()); + return contents.error_code(); + } + + expected<std::unordered_map<std::string, std::string>> parse_single_paragraph(const std::string& str) + { + const std::vector<std::unordered_map<std::string, std::string>> p = Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); + + if (p.size() == 1) + { + return p.at(0); + } + + return std::error_code(paragraph_parse_result::EXPECTED_ONE_PARAGRAPH); } - std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str) + expected<std::vector<std::unordered_map<std::string, std::string>>> parse_paragraphs(const std::string& str) { return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); } expected<SourceParagraph> try_load_port(const fs::path& path) { - try + expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(path / "CONTROL"); + if (auto p = pghs.get()) { - auto pghs = get_paragraphs(path / "CONTROL"); - Checks::check_exit(VCPKG_LINE_INFO, pghs.size() == 1, "Invalid control file at %s\\CONTROL", path.string()); - return SourceParagraph(pghs[0]); + return SourceParagraph(*p); } - catch (std::runtime_error const&) {} - return std::errc::no_such_file_or_directory; + return pghs.error_code(); } expected<BinaryParagraph> try_load_cached_package(const vcpkg_paths& paths, const package_spec& spec) { - const fs::path path = paths.package_dir(spec) / "CONTROL"; + expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(paths.package_dir(spec) / "CONTROL"); - auto control_contents_maybe = Files::read_contents(path); - if (auto control_contents = control_contents_maybe.get()) + if (auto p = pghs.get()) { - std::vector<std::unordered_map<std::string, std::string>> pghs; - try - { - pghs = parse_paragraphs(*control_contents); - } - catch (std::runtime_error) {} - Checks::check_exit(VCPKG_LINE_INFO, pghs.size() == 1, "Invalid control file at %s", path.string()); - return BinaryParagraph(pghs[0]); + return BinaryParagraph(*p); } - return control_contents_maybe.error_code(); + + return pghs.error_code(); } std::vector<SourceParagraph> load_all_ports(const fs::path& ports_dir) diff --git a/toolsrc/src/PostBuildLint_BuildInfo.cpp b/toolsrc/src/PostBuildLint_BuildInfo.cpp index 5b475322a..7b7751e66 100644 --- a/toolsrc/src/PostBuildLint_BuildInfo.cpp +++ b/toolsrc/src/PostBuildLint_BuildInfo.cpp @@ -39,10 +39,8 @@ namespace vcpkg::PostBuildLint BuildInfo read_build_info(const fs::path& filepath) { - const std::vector<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_paragraphs(filepath); - Checks::check_exit(VCPKG_LINE_INFO, pghs.size() == 1, "Invalid BUILD_INFO file for package"); - - return BuildInfo::create(pghs[0]); + const expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(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/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index 417799abb..6504c8c4d 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -13,22 +13,11 @@ namespace vcpkg::Commands::Cache for (auto it = fs::directory_iterator(paths.packages); it != fs::directory_iterator(); ++it) { const fs::path& path = it->path(); - - try - { - auto file_contents = Files::read_contents(path / "CONTROL"); - if (auto text = file_contents.get()) - { - auto pghs = Paragraphs::parse_paragraphs(*text); - if (pghs.size() != 1) - continue; - - const BinaryParagraph binary_paragraph = BinaryParagraph(pghs[0]); - output.push_back(binary_paragraph); - } - } - catch (std::runtime_error const&) + const expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(path / "CONTROL"); + if (auto p = pghs.get()) { + const BinaryParagraph binary_paragraph = BinaryParagraph(*p); + output.push_back(binary_paragraph); } } diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index 69710765f..6be5c2fe1 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -72,11 +72,11 @@ namespace vcpkg::Commands::Import const fs::path include_directory(args.command_arguments[1]); const fs::path project_directory(args.command_arguments[2]); - auto pghs = Paragraphs::get_paragraphs(control_file_path); - Checks::check_exit(VCPKG_LINE_INFO, pghs.size() == 1, "Invalid control file %s for package", control_file_path.generic_string()); + const expected<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_single_paragraph(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; - spgh.package = BinaryParagraph(pghs[0]); + spgh.package = BinaryParagraph(*pghs.get()); auto& control_file_data = spgh.package; do_import(paths, include_directory, project_directory, control_file_data); diff --git a/toolsrc/src/paragraph_parse_result.cpp b/toolsrc/src/paragraph_parse_result.cpp new file mode 100644 index 000000000..4715f7a16 --- /dev/null +++ b/toolsrc/src/paragraph_parse_result.cpp @@ -0,0 +1,45 @@ +#include "pch.h" +#include "vcpkg_Checks.h" +#include "paragraph_parse_result.h" + +namespace vcpkg +{ + const char* paragraph_parse_result_category_impl::name() const noexcept + { + return "paragraph_parse_result"; + } + + std::string paragraph_parse_result_category_impl::message(int ev) const noexcept + { + switch (static_cast<paragraph_parse_result>(ev)) + { + case paragraph_parse_result::SUCCESS: + return "OK"; + case paragraph_parse_result::EXPECTED_ONE_PARAGRAPH: + return "There should be exactly one paragraph"; + default: + Checks::unreachable(VCPKG_LINE_INFO); + } + } + + const std::error_category& paragraph_parse_result_category() + { + static paragraph_parse_result_category_impl instance; + return instance; + } + + std::error_code make_error_code(paragraph_parse_result e) + { + return std::error_code(static_cast<int>(e), paragraph_parse_result_category()); + } + + paragraph_parse_result to_paragraph_parse_result(int i) + { + return static_cast<paragraph_parse_result>(i); + } + + paragraph_parse_result to_paragraph_parse_result(std::error_code ec) + { + return to_paragraph_parse_result(ec.value()); + } +} diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp index fb20eee82..b5e630aca 100644 --- a/toolsrc/src/tests_paragraph.cpp +++ b/toolsrc/src/tests_paragraph.cpp @@ -153,14 +153,14 @@ namespace UnitTest1 TEST_METHOD(parse_paragraphs_empty) { const char* str = ""; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::IsTrue(pghs.empty()); } TEST_METHOD(parse_paragraphs_one_field) { const char* str = "f1: v1"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(1), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -171,7 +171,7 @@ namespace UnitTest1 const char* str = "f1: v1\n" "f2: v2"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -186,7 +186,7 @@ namespace UnitTest1 "\n" "f3: v3\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(2), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -204,7 +204,7 @@ namespace UnitTest1 "F:\n" "0:\n" "F-2:\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(5), pghs[0].size()); } @@ -218,7 +218,7 @@ namespace UnitTest1 "\n" "f3: v3\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(2), pghs.size()); } @@ -227,7 +227,7 @@ namespace UnitTest1 const char* str = "f1:\n" "f2: "; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("", pghs[0]["f1"].c_str()); @@ -243,7 +243,7 @@ namespace UnitTest1 "f2:\r\n" " f2\r\n" " continue\r\n"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(1), pghs.size()); Assert::AreEqual("simple\n f1", pghs[0]["f1"].c_str()); Assert::AreEqual("\n f2\n continue", pghs[0]["f2"].c_str()); @@ -257,7 +257,7 @@ namespace UnitTest1 "\r\n" "f3: v3\r\n" "f4: v4"; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(str); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(str).get_or_throw(VCPKG_LINE_INFO); Assert::AreEqual(size_t(2), pghs.size()); Assert::AreEqual(size_t(2), pghs[0].size()); Assert::AreEqual("v1", pghs[0]["f1"].c_str()); @@ -277,7 +277,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, }); ss << pgh; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()).get_or_throw(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()); @@ -299,7 +299,7 @@ namespace UnitTest1 {"Multi-Arch", "same"}, }); ss << pgh; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()).get_or_throw(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()); @@ -321,7 +321,7 @@ namespace UnitTest1 {"Depends", "a, b, c"}, }); ss << pgh; - auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()); + auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str()).get_or_throw(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 f6acf07a0..4caeb93e1 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -111,10 +111,8 @@ static void loadConfig() try { - std::string config_contents = Files::read_contents(localappdata / "vcpkg" / "config").get_or_throw(VCPKG_LINE_INFO); - + auto pghs = Paragraphs::get_paragraphs(localappdata / "vcpkg" / "config").get_or_throw(VCPKG_LINE_INFO); std::unordered_map<std::string, std::string> keys; - auto pghs = Paragraphs::parse_paragraphs(config_contents); if (pghs.size() > 0) keys = pghs[0]; diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 932502d2d..204e1c0d7 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -22,8 +22,7 @@ namespace vcpkg fs::rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file); } - auto text = Files::read_contents(vcpkg_dir_status_file).get_or_throw(VCPKG_LINE_INFO); - auto pghs = Paragraphs::parse_paragraphs(text); + auto pghs = Paragraphs::get_paragraphs(vcpkg_dir_status_file).get_or_throw(VCPKG_LINE_INFO); std::vector<std::unique_ptr<StatusParagraph>> status_pghs; for (auto&& p : pghs) @@ -65,8 +64,7 @@ namespace vcpkg if (b->path().filename() == "incomplete") continue; - auto text = Files::read_contents(b->path()).get_or_throw(VCPKG_LINE_INFO); - auto pghs = Paragraphs::parse_paragraphs(text); + auto pghs = Paragraphs::get_paragraphs(b->path()).get_or_throw(VCPKG_LINE_INFO); for (auto&& p : pghs) { current_status_db.insert(std::make_unique<StatusParagraph>(p)); diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj b/toolsrc/vcpkglib/vcpkglib.vcxproj index 237af6543..9fb4641b9 100644 --- a/toolsrc/vcpkglib/vcpkglib.vcxproj +++ b/toolsrc/vcpkglib/vcpkglib.vcxproj @@ -139,6 +139,7 @@ <ClInclude Include="..\include\BinaryParagraph.h" /> <ClInclude Include="..\include\lazy.h" /> <ClInclude Include="..\include\LineInfo.h" /> + <ClInclude Include="..\include\paragraph_parse_result.h" /> <ClInclude Include="..\include\PostBuildLint_BuildInfo.h" /> <ClInclude Include="..\include\PostBuildLint_BuildPolicies.h" /> <ClInclude Include="..\include\coff_file_reader.h" /> @@ -183,6 +184,7 @@ <ClCompile Include="..\src\BinaryParagraph.cpp" /> <ClCompile Include="..\src\commands_ci.cpp" /> <ClCompile Include="..\src\LineInfo.cpp" /> + <ClCompile Include="..\src\paragraph_parse_result.cpp" /> <ClCompile Include="..\src\PostBuildLint_BuildInfo.cpp" /> <ClCompile Include="..\src\PostBuildLint_BuildPolicies.cpp" /> <ClCompile Include="..\src\coff_file_reader.cpp" /> diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters index 60eaa167a..3474e221b 100644 --- a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters +++ b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters @@ -174,6 +174,9 @@ <ClCompile Include="..\src\LineInfo.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\src\paragraph_parse_result.cpp"> + <Filter>Source Files</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\include\package_spec.h"> @@ -302,5 +305,8 @@ <ClInclude Include="..\include\LineInfo.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\include\paragraph_parse_result.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> </Project>
\ No newline at end of file |
