aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Schumacher <roschuma@microsoft.com>2017-06-08 00:36:17 -0700
committerRobert Schumacher <roschuma@microsoft.com>2017-06-08 04:32:57 -0700
commit247a6cec90004b8666d155eacc0f27d3a6c8fcf9 (patch)
treee63038044933f747161f94f52fc35f435573d08b
parent1b717d851fda51e03b98a18f5304e29b7876c8a3 (diff)
downloadvcpkg-247a6cec90004b8666d155eacc0f27d3a6c8fcf9.tar.gz
vcpkg-247a6cec90004b8666d155eacc0f27d3a6c8fcf9.zip
[vcpkg] Improve diagnostics upon port load failure
-rw-r--r--toolsrc/include/Paragraphs.h8
-rw-r--r--toolsrc/include/SourceParagraph.h9
-rw-r--r--toolsrc/include/Span.h38
-rw-r--r--toolsrc/include/pch.h1
-rw-r--r--toolsrc/include/vcpkg_Strings.h15
-rw-r--r--toolsrc/src/Paragraphs.cpp23
-rw-r--r--toolsrc/src/SourceParagraph.cpp64
-rw-r--r--toolsrc/src/commands_ci.cpp5
-rw-r--r--toolsrc/src/commands_depends.cpp5
-rw-r--r--toolsrc/src/commands_search.cpp25
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp6
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj1
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj.filters3
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