diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2017-06-08 00:36:17 -0700 |
|---|---|---|
| committer | Robert Schumacher <roschuma@microsoft.com> | 2017-06-08 04:32:57 -0700 |
| commit | 247a6cec90004b8666d155eacc0f27d3a6c8fcf9 (patch) | |
| tree | e63038044933f747161f94f52fc35f435573d08b | |
| parent | 1b717d851fda51e03b98a18f5304e29b7876c8a3 (diff) | |
| download | vcpkg-247a6cec90004b8666d155eacc0f27d3a6c8fcf9.tar.gz vcpkg-247a6cec90004b8666d155eacc0f27d3a6c8fcf9.zip | |
[vcpkg] Improve diagnostics upon port load failure
| -rw-r--r-- | toolsrc/include/Paragraphs.h | 8 | ||||
| -rw-r--r-- | toolsrc/include/SourceParagraph.h | 9 | ||||
| -rw-r--r-- | toolsrc/include/Span.h | 38 | ||||
| -rw-r--r-- | toolsrc/include/pch.h | 1 | ||||
| -rw-r--r-- | toolsrc/include/vcpkg_Strings.h | 15 | ||||
| -rw-r--r-- | toolsrc/src/Paragraphs.cpp | 23 | ||||
| -rw-r--r-- | toolsrc/src/SourceParagraph.cpp | 64 | ||||
| -rw-r--r-- | toolsrc/src/commands_ci.cpp | 5 | ||||
| -rw-r--r-- | toolsrc/src/commands_depends.cpp | 5 | ||||
| -rw-r--r-- | toolsrc/src/commands_search.cpp | 25 | ||||
| -rw-r--r-- | toolsrc/src/vcpkg_Dependencies.cpp | 6 | ||||
| -rw-r--r-- | toolsrc/vcpkglib/vcpkglib.vcxproj | 1 | ||||
| -rw-r--r-- | toolsrc/vcpkglib/vcpkglib.vcxproj.filters | 3 |
13 files changed, 147 insertions, 56 deletions
diff --git a/toolsrc/include/Paragraphs.h b/toolsrc/include/Paragraphs.h index 59f0eefc8..04f9fb879 100644 --- a/toolsrc/include/Paragraphs.h +++ b/toolsrc/include/Paragraphs.h @@ -21,6 +21,14 @@ namespace vcpkg::Paragraphs Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); + struct LoadResults + { + std::vector<SourceParagraph> paragraphs; + std::vector<ParseControlErrorInfo> errors; + }; + + LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir); + std::vector<SourceParagraph> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir); std::map<std::string, VersionT> extract_port_names_and_versions( diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h index a53158f3f..47ad5b830 100644 --- a/toolsrc/include/SourceParagraph.h +++ b/toolsrc/include/SourceParagraph.h @@ -1,5 +1,6 @@ #pragma once +#include "Span.h" #include "vcpkg_System.h" #include "vcpkg_expected.h" @@ -23,7 +24,6 @@ namespace vcpkg { std::string name; std::string remaining_fields_as_string; - std::string valid_fields_as_string; std::error_code error; }; @@ -45,8 +45,11 @@ namespace vcpkg std::vector<Dependency> depends; }; - void print_error_message(const ParseControlErrorInfo& info); - void print_error_message(std::vector<ParseControlErrorInfo> error_info_list); + void print_error_message(span<const ParseControlErrorInfo> error_info_list); + inline void print_error_message(const ParseControlErrorInfo& error_info_list) + { + return print_error_message({&error_info_list, 1}); + } std::vector<std::string> filter_dependencies(const std::vector<Dependency>& deps, const Triplet& t); diff --git a/toolsrc/include/Span.h b/toolsrc/include/Span.h new file mode 100644 index 000000000..b16af2cef --- /dev/null +++ b/toolsrc/include/Span.h @@ -0,0 +1,38 @@ +#pragma once
+
+#include <array>
+#include <cstddef>
+#include <vector>
+
+template<class T>
+struct span
+{
+public:
+ using element_type = T;
+ using pointer = T*;
+ using reference = T&;
+ using iterator = T*;
+
+ constexpr span() noexcept : m_ptr(nullptr), m_count(0) {}
+ constexpr span(std::nullptr_t) noexcept : span() {}
+ constexpr span(T* ptr, size_t count) noexcept : m_ptr(ptr), m_count(count) {}
+ constexpr span(T* ptr_begin, T* ptr_end) noexcept : m_ptr(ptr_begin), m_count(ptr_end - ptr_begin) {}
+
+ template<size_t N>
+ constexpr span(T (&arr)[N]) noexcept : span(arr, N)
+ {
+ }
+
+ span(std::vector<T>& v) noexcept : span(v.data(), v.size()) {}
+ span(const std::vector<std::remove_const_t<T>>& v) noexcept : span(v.data(), v.size()) {}
+
+ constexpr iterator begin() const { return m_ptr; }
+ constexpr iterator end() const { return m_ptr + m_count; }
+
+ constexpr reference operator[](size_t i) const { return m_ptr[i]; }
+ constexpr size_t size() const { return m_count; }
+
+private:
+ pointer m_ptr;
+ size_t m_count;
+};
diff --git a/toolsrc/include/pch.h b/toolsrc/include/pch.h index c58c30ea3..406d0741e 100644 --- a/toolsrc/include/pch.h +++ b/toolsrc/include/pch.h @@ -12,6 +12,7 @@ #include <chrono> #include <codecvt> #include <cstdarg> +#include <cstddef> #include <cstdint> #include <filesystem> #include <fstream> diff --git a/toolsrc/include/vcpkg_Strings.h b/toolsrc/include/vcpkg_Strings.h index 3f8f4562e..cab8071aa 100644 --- a/toolsrc/include/vcpkg_Strings.h +++ b/toolsrc/include/vcpkg_Strings.h @@ -58,8 +58,8 @@ namespace vcpkg::Strings std::string ascii_to_lowercase(const std::string& input); - template<class T, class Transformer, class CharType> - std::basic_string<CharType> join(const CharType* delimiter, const std::vector<T>& v, Transformer transformer) + template<class Container, class Transformer, class CharType> + std::basic_string<CharType> join(const CharType* delimiter, const Container& v, Transformer transformer) { if (v.empty()) { @@ -69,20 +69,21 @@ namespace vcpkg::Strings std::basic_string<CharType> output; size_t size = v.size(); - output.append(transformer(v.at(0))); + output.append(transformer(v[0])); for (size_t i = 1; i < size; ++i) { output.append(delimiter); - output.append(transformer(v.at(i))); + output.append(transformer(v[i])); } return output; } - template<class T, class CharType> - std::basic_string<CharType> join(const CharType* delimiter, const std::vector<T>& v) + template<class Container, class CharType> + std::basic_string<CharType> join(const CharType* delimiter, const Container& v) { - return join(delimiter, v, [](const T& x) -> const T& { return x; }); + using Element = decltype(v[0]); + return join(delimiter, v, [](const Element& x) -> const Element& { return x; }); } void trim(std::string* s); diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp index 13103d1f8..31e8f1da3 100644 --- a/toolsrc/src/Paragraphs.cpp +++ b/toolsrc/src/Paragraphs.cpp @@ -209,6 +209,7 @@ namespace vcpkg::Paragraphs { return SourceParagraph::parse_control_file(*p); } + error_info.name = path.filename().generic_u8string(); error_info.error = pghs.error(); return error_info; } @@ -226,25 +227,33 @@ namespace vcpkg::Paragraphs return pghs.error(); } - std::vector<SourceParagraph> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + LoadResults try_load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) { - std::vector<SourceParagraph> output; - std::vector<ParseControlErrorInfo> port_errors; + LoadResults ret; for (auto&& path : fs.get_files_non_recursive(ports_dir)) { ExpectedT<SourceParagraph, ParseControlErrorInfo> source_paragraph = try_load_port(fs, path); if (auto srcpgh = source_paragraph.get()) { - output.emplace_back(std::move(*srcpgh)); + ret.paragraphs.emplace_back(std::move(*srcpgh)); } else { - port_errors.emplace_back(source_paragraph.error()); + ret.errors.emplace_back(source_paragraph.error()); } } - print_error_message(port_errors); + return ret; + } - return output; + std::vector<SourceParagraph> load_all_ports(const Files::Filesystem& fs, const fs::path& ports_dir) + { + auto results = try_load_all_ports(fs, ports_dir); + if (!results.errors.empty()) + { + print_error_message(results.errors); + Checks::exit_fail(VCPKG_LINE_INFO); + } + return std::move(results.paragraphs); } std::map<std::string, VersionT> extract_port_names_and_versions( diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp index 2508af1e8..4001e891f 100644 --- a/toolsrc/src/SourceParagraph.cpp +++ b/toolsrc/src/SourceParagraph.cpp @@ -27,42 +27,52 @@ namespace vcpkg static const std::string SUPPORTS = "Supports"; } - static const std::vector<std::string>& get_list_of_valid_fields() + static span<const std::string> get_list_of_valid_fields() { - static const std::vector<std::string> valid_fields = {SourceParagraphRequiredField::SOURCE, - SourceParagraphRequiredField::VERSION, + static const std::string valid_fields[] = {SourceParagraphRequiredField::SOURCE, + SourceParagraphRequiredField::VERSION, - SourceParagraphOptionalField::DESCRIPTION, - SourceParagraphOptionalField::MAINTAINER, - SourceParagraphOptionalField::BUILD_DEPENDS, - SourceParagraphOptionalField::SUPPORTS}; + SourceParagraphOptionalField::DESCRIPTION, + SourceParagraphOptionalField::MAINTAINER, + SourceParagraphOptionalField::BUILD_DEPENDS, + SourceParagraphOptionalField::SUPPORTS}; return valid_fields; } - void print_error_message(const ParseControlErrorInfo& info) + void print_error_message(span<const ParseControlErrorInfo> error_info_list) { - System::println( - System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", info.name); - System::println("The following fields were not expected:\n\n %s\n\n", info.remaining_fields_as_string); - System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", info.valid_fields_as_string); - System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); - } + Checks::check_exit(VCPKG_LINE_INFO, error_info_list.size() > 0); - void print_error_message(std::vector<ParseControlErrorInfo> error_info_list) - { - if (error_info_list.size() == 0) return; - for (ParseControlErrorInfo error_info : error_info_list) + for (auto&& error_info : error_info_list) { - System::println( - System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", error_info.name); - System::println("The following fields were not expected:\n\n %s\n\n", - error_info.remaining_fields_as_string); + if (error_info.error) + { + System::println( + System::Color::error, "Error: while loading %s: %s", error_info.name, error_info.error.message()); + } } - System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", - error_info_list.front().valid_fields_as_string); - System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + bool have_remaining_fields = false; + for (auto&& error_info : error_info_list) + { + if (!error_info.remaining_fields_as_string.empty()) + { + System::println(System::Color::error, + "Error: There are invalid fields in the Source Paragraph of %s", + error_info.name); + System::println("The following fields were not expected:\n\n %s\n\n", + error_info.remaining_fields_as_string); + have_remaining_fields = true; + } + } + + if (have_remaining_fields) + { + System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", + Strings::join("\n ", get_list_of_valid_fields())); + System::println("Different source may be available for vcpkg. Use .\\bootstrap-vcpkg.bat to update.\n"); + } } ExpectedT<SourceParagraph, ParseControlErrorInfo> SourceParagraph::parse_control_file( @@ -83,12 +93,10 @@ namespace vcpkg if (!fields.empty()) { const std::vector<std::string> remaining_fields = Maps::extract_keys(fields); - const std::vector<std::string>& valid_fields = get_list_of_valid_fields(); const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields); - const std::string valid_fields_as_string = Strings::join("\n ", valid_fields); - return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string, valid_fields_as_string}; + return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string}; } return sparagraph; } diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp index bad1286f0..7e724f3ee 100644 --- a/toolsrc/src/commands_ci.cpp +++ b/toolsrc/src/commands_ci.cpp @@ -20,9 +20,10 @@ namespace vcpkg::Commands::CI const fs::path& ports_directory, const Triplet& triplet) { - std::vector<SourceParagraph> ports = Paragraphs::load_all_ports(fs, ports_directory); + auto sources = Paragraphs::load_all_ports(fs, ports_directory); + std::vector<PackageSpec> specs; - for (const SourceParagraph& p : ports) + for (const SourceParagraph& p : sources) { specs.push_back(PackageSpec::from_name_and_triplet(p.name, triplet).value_or_exit(VCPKG_LINE_INFO)); } diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp index ad33bbad4..9db4b7bb1 100644 --- a/toolsrc/src/commands_depends.cpp +++ b/toolsrc/src/commands_depends.cpp @@ -13,10 +13,9 @@ 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.get_filesystem(), paths.ports); + auto sources = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports); - for (const SourceParagraph& source_paragraph : source_paragraphs) + for (const SourceParagraph& source_paragraph : sources) { auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; }); System::println("%s: %s", source_paragraph.name, s); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 739aa0f43..4b7f49ba8 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -4,6 +4,7 @@ #include "SourceParagraph.h" #include "vcpkg_Commands.h" #include "vcpkg_System.h" +#include "vcpkglib.h" #include "vcpkglib_helpers.h" namespace vcpkg::Commands::Search @@ -61,8 +62,28 @@ 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.get_filesystem(), paths.ports); + auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports); + + if (!sources_and_errors.errors.empty()) + { + if (vcpkg::g_debugging) + { + print_error_message(sources_and_errors.errors); + } + else + { + for (auto&& error : sources_and_errors.errors) + { + System::println( + System::Color::warning, "Warning: an error occurred while parsing '%s'\n", error.name); + } + System::println(System::Color::warning, + "Use '--debug' to get more information about the parse failures.\n"); + } + } + + auto& source_paragraphs = sources_and_errors.paragraphs; + if (options.find(OPTION_GRAPH) != options.cend()) { const std::string graph_as_string = create_graph_as_string(source_paragraphs); diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index ea5832e46..f32d92f4c 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -179,10 +179,8 @@ namespace vcpkg::Dependencies if (auto spgh = maybe_spgh.get()) return InstallPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; - else - print_error_message(maybe_spgh.error()); - - Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec); + print_error_message(maybe_spgh.error()); + Checks::exit_fail(VCPKG_LINE_INFO); } }; diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj b/toolsrc/vcpkglib/vcpkglib.vcxproj index abc2e4a4e..487609cca 100644 --- a/toolsrc/vcpkglib/vcpkglib.vcxproj +++ b/toolsrc/vcpkglib/vcpkglib.vcxproj @@ -142,6 +142,7 @@ <ClInclude Include="..\include\LineInfo.h" /> <ClInclude Include="..\include\ParagraphParseResult.h" /> <ClInclude Include="..\include\PostBuildLint_BuildType.h" /> + <ClInclude Include="..\include\Span.h" /> <ClInclude Include="..\include\vcpkg_Build.h" /> <ClInclude Include="..\include\coff_file_reader.h" /> <ClInclude Include="..\include\vcpkg_expected.h" /> diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters index 599bfeafb..a901cebe7 100644 --- a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters +++ b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters @@ -299,5 +299,8 @@ <ClInclude Include="..\include\PostBuildLint_BuildType.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\include\Span.h"> + <Filter>Header Files</Filter> + </ClInclude> </ItemGroup> </Project>
\ No newline at end of file |
