ExpectedT factory class

This commit is contained in:
Daniel Shaw 2017-06-05 15:58:47 -07:00
parent 7b4d83c444
commit 264cd050e6
16 changed files with 223 additions and 130 deletions

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <string>
namespace vcpkg namespace vcpkg
{ {
struct LineInfo struct LineInfo

View File

@ -7,9 +7,11 @@ namespace vcpkg
{ {
struct PackageSpec struct PackageSpec
{ {
static Expected<PackageSpec> from_string(const std::string& spec_as_string, const Triplet& default_triplet); static ExpectedT<PackageSpec, PackageSpecParseResult> from_string(const std::string& spec_as_string,
const Triplet& default_triplet);
static std::string to_string(const std::string& name, const Triplet& triplet); static std::string to_string(const std::string& name, const Triplet& triplet);
static Expected<PackageSpec> from_name_and_triplet(const std::string& name, const Triplet& triplet); static ExpectedT<PackageSpec, PackageSpecParseResult> from_name_and_triplet(const std::string& name,
const Triplet& triplet);
const std::string& name() const; const std::string& name() const;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <system_error>
#include "vcpkg_expected.h"
namespace vcpkg namespace vcpkg
{ {
@ -10,27 +11,21 @@ namespace vcpkg
INVALID_CHARACTERS INVALID_CHARACTERS
}; };
struct PackageSpecParseResultCategoryImpl final : std::error_category CStringView to_string(PackageSpecParseResult ev) noexcept;
{
virtual const char* name() const noexcept override;
virtual std::string message(int ev) const noexcept override;
};
const std::error_category& package_spec_parse_result_category();
std::error_code make_error_code(PackageSpecParseResult e);
PackageSpecParseResult to_package_spec_parse_result(int i);
PackageSpecParseResult to_package_spec_parse_result(std::error_code ec);
}
// Enable implicit conversion to std::error_code
namespace std
{
template<> template<>
struct is_error_code_enum<vcpkg::PackageSpecParseResult> : ::std::true_type struct ErrorHolder<PackageSpecParseResult>
{ {
ErrorHolder() : m_err(PackageSpecParseResult::SUCCESS) {}
ErrorHolder(PackageSpecParseResult err) : m_err(err) {}
constexpr bool has_error() const { return m_err != PackageSpecParseResult::SUCCESS; }
PackageSpecParseResult error() const { return m_err; }
CStringView to_string() const { return vcpkg::to_string(m_err); }
private:
PackageSpecParseResult m_err;
}; };
} }

View File

@ -16,7 +16,8 @@ namespace vcpkg::Paragraphs
Expected<ParagraphDataMap> parse_single_paragraph(const std::string& str); Expected<ParagraphDataMap> parse_single_paragraph(const std::string& str);
Expected<std::vector<ParagraphDataMap>> parse_paragraphs(const std::string& str); Expected<std::vector<ParagraphDataMap>> parse_paragraphs(const std::string& str);
Expected<SourceParagraph> try_load_port(const Files::Filesystem& fs, const fs::path& control_path); ExpectedT<SourceParagraph, ParseControlErrorInfo> try_load_port(const Files::Filesystem& fs,
const fs::path& control_path);
Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec);

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "vcpkg_expected.h"
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -15,14 +16,23 @@ namespace vcpkg
const std::string& to_string(const Dependency& dep); const std::string& to_string(const Dependency& dep);
struct ParseControlErrorInfo
{
std::string name;
std::string remaining_fields_as_string;
std::string valid_fields_as_string;
std::error_code error;
};
/// <summary> /// <summary>
/// Port metadata (CONTROL file) /// Port metadata (CONTROL file)
/// </summary> /// </summary>
struct SourceParagraph struct SourceParagraph
{ {
SourceParagraph(); static ExpectedT<SourceParagraph, ParseControlErrorInfo> parse_control_file(
std::unordered_map<std::string, std::string> fields);
explicit SourceParagraph(std::unordered_map<std::string, std::string> fields); SourceParagraph();
std::string name; std::string name;
std::string version; std::string version;
@ -31,6 +41,9 @@ namespace vcpkg
std::vector<Dependency> depends; std::vector<Dependency> depends;
}; };
void print_error_message(const ParseControlErrorInfo& info);
void print_error_message(std::vector<ParseControlErrorInfo> error_info_list);
std::vector<std::string> filter_dependencies(const std::vector<Dependency>& deps, const Triplet& t); std::vector<std::string> filter_dependencies(const std::vector<Dependency>& deps, const Triplet& t);
std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends); std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends);

View File

@ -5,27 +5,63 @@
namespace vcpkg namespace vcpkg
{ {
template<class T> template<class Err>
class Expected struct ErrorHolder
{
ErrorHolder() : m_is_error(false) {}
ErrorHolder(const Err& err) : m_is_error(true), m_err(err) {}
ErrorHolder(Err&& err) : m_is_error(true), m_err(std::move(err)) {}
constexpr bool has_error() const { return m_is_error; }
const Err& error() const { return m_err; }
Err& error() { return m_err; }
CStringView to_string() const { return "value was error"; }
private:
bool m_is_error;
Err m_err;
};
template<>
struct ErrorHolder<std::error_code>
{
ErrorHolder() = default;
ErrorHolder(const std::error_code& err) : m_err(err) {}
constexpr bool has_error() const { return bool(m_err); }
const std::error_code& error() const { return m_err; }
std::error_code& error() { return m_err; }
CStringView to_string() const { return "value was error"; }
private:
std::error_code m_err;
};
template<class T, class S>
class ExpectedT
{ {
public: public:
constexpr ExpectedT() = default;
// Constructors are intentionally implicit // Constructors are intentionally implicit
Expected(const std::error_code& ec) : m_error_code(ec), m_t() {}
Expected(std::errc ec) : Expected(std::make_error_code(ec)) {} ExpectedT(const S& s) : m_s(s) {}
ExpectedT(S&& s) : m_s(std::move(s)) {}
Expected(const T& t) : m_error_code(), m_t(t) {} ExpectedT(const T& t) : m_t(t) {}
ExpectedT(T&& t) : m_t(std::move(t)) {}
Expected(T&& t) : m_error_code(), m_t(std::move(t)) {} ExpectedT(const ExpectedT&) = default;
ExpectedT(ExpectedT&&) = default;
ExpectedT& operator=(const ExpectedT&) = default;
ExpectedT& operator=(ExpectedT&&) = default;
Expected() : Expected(std::error_code(), T()) {} explicit constexpr operator bool() const noexcept { return !m_s.has_error(); }
constexpr bool has_value() const noexcept { return !m_s.has_error(); }
Expected(const Expected&) = default;
Expected(Expected&&) = default;
Expected& operator=(const Expected&) = default;
Expected& operator=(Expected&&) = default;
std::error_code error_code() const { return this->m_error_code; }
T&& value_or_exit(const LineInfo& line_info) && T&& value_or_exit(const LineInfo& line_info) &&
{ {
@ -39,9 +75,13 @@ namespace vcpkg
return this->m_t; return this->m_t;
} }
const S& error() const & { return this->m_s.error(); }
S&& error() && { return std::move(this->m_s.error()); }
const T* get() const const T* get() const
{ {
if (m_error_code) if (!this->has_value())
{ {
return nullptr; return nullptr;
} }
@ -50,7 +90,7 @@ namespace vcpkg
T* get() T* get()
{ {
if (m_error_code) if (!this->has_value())
{ {
return nullptr; return nullptr;
} }
@ -60,10 +100,13 @@ namespace vcpkg
private: private:
void exit_if_error(const LineInfo& line_info) const void exit_if_error(const LineInfo& line_info) const
{ {
Checks::check_exit(line_info, !this->m_error_code, this->m_error_code.message()); Checks::check_exit(line_info, !m_s.has_error(), m_s.to_string());
} }
std::error_code m_error_code; ErrorHolder<S> m_s;
T m_t; T m_t;
}; };
template<class T>
using Expected = ExpectedT<T, std::error_code>;
} }

View File

@ -7,7 +7,8 @@ namespace vcpkg
{ {
static bool is_valid_package_spec_char(char c) { return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)); } static bool is_valid_package_spec_char(char c) { return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)); }
Expected<PackageSpec> PackageSpec::from_string(const std::string& spec_as_string, const Triplet& default_triplet) ExpectedT<PackageSpec, PackageSpecParseResult> PackageSpec::from_string(const std::string& spec_as_string,
const Triplet& default_triplet)
{ {
auto pos = spec_as_string.find(':'); auto pos = spec_as_string.find(':');
if (pos == std::string::npos) if (pos == std::string::npos)
@ -18,7 +19,7 @@ namespace vcpkg
auto pos2 = spec_as_string.find(':', pos + 1); auto pos2 = spec_as_string.find(':', pos + 1);
if (pos2 != std::string::npos) if (pos2 != std::string::npos)
{ {
return std::error_code(PackageSpecParseResult::TOO_MANY_COLONS); return PackageSpecParseResult::TOO_MANY_COLONS;
} }
const std::string name = spec_as_string.substr(0, pos); const std::string name = spec_as_string.substr(0, pos);
@ -26,11 +27,12 @@ namespace vcpkg
return from_name_and_triplet(name, triplet); return from_name_and_triplet(name, triplet);
} }
Expected<PackageSpec> PackageSpec::from_name_and_triplet(const std::string& name, const Triplet& triplet) ExpectedT<PackageSpec, PackageSpecParseResult> PackageSpec::from_name_and_triplet(const std::string& name,
const Triplet& triplet)
{ {
if (Util::find_if_not(name, is_valid_package_spec_char) != name.end()) if (Util::find_if_not(name, is_valid_package_spec_char) != name.end())
{ {
return std::error_code(PackageSpecParseResult::INVALID_CHARACTERS); return PackageSpecParseResult::INVALID_CHARACTERS;
} }
PackageSpec p; PackageSpec p;

View File

@ -5,11 +5,9 @@
namespace vcpkg namespace vcpkg
{ {
const char* PackageSpecParseResultCategoryImpl::name() const noexcept { return "PackageSpecParseResult"; } CStringView to_string(PackageSpecParseResult ev) noexcept
std::string PackageSpecParseResultCategoryImpl::message(int ev) const noexcept
{ {
switch (static_cast<PackageSpecParseResult>(ev)) switch (ev)
{ {
case PackageSpecParseResult::SUCCESS: return "OK"; case PackageSpecParseResult::SUCCESS: return "OK";
case PackageSpecParseResult::TOO_MANY_COLONS: return "Too many colons"; case PackageSpecParseResult::TOO_MANY_COLONS: return "Too many colons";
@ -19,22 +17,4 @@ namespace vcpkg
default: Checks::unreachable(VCPKG_LINE_INFO); default: Checks::unreachable(VCPKG_LINE_INFO);
} }
} }
const std::error_category& package_spec_parse_result_category()
{
static PackageSpecParseResultCategoryImpl instance;
return instance;
}
std::error_code make_error_code(PackageSpecParseResult e)
{
return std::error_code(static_cast<int>(e), package_spec_parse_result_category());
}
PackageSpecParseResult to_package_spec_parse_result(int i) { return static_cast<PackageSpecParseResult>(i); }
PackageSpecParseResult to_package_spec_parse_result(std::error_code ec)
{
return to_package_spec_parse_result(ec.value());
}
} }

View File

@ -168,7 +168,7 @@ namespace vcpkg::Paragraphs
return parse_single_paragraph(*spgh); return parse_single_paragraph(*spgh);
} }
return contents.error_code(); return contents.error();
} }
Expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const Files::Filesystem& fs, Expected<std::vector<std::unordered_map<std::string, std::string>>> get_paragraphs(const Files::Filesystem& fs,
@ -180,7 +180,7 @@ namespace vcpkg::Paragraphs
return parse_paragraphs(*spgh); return parse_paragraphs(*spgh);
} }
return contents.error_code(); return contents.error();
} }
Expected<std::unordered_map<std::string, std::string>> parse_single_paragraph(const std::string& str) Expected<std::unordered_map<std::string, std::string>> parse_single_paragraph(const std::string& str)
@ -201,15 +201,16 @@ namespace vcpkg::Paragraphs
return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs(); return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
} }
Expected<SourceParagraph> try_load_port(const Files::Filesystem& fs, const fs::path& path) ExpectedT<SourceParagraph, ParseControlErrorInfo> try_load_port(const Files::Filesystem& fs, const fs::path& path)
{ {
ParseControlErrorInfo error_info;
Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(fs, path / "CONTROL"); Expected<std::unordered_map<std::string, std::string>> pghs = get_single_paragraph(fs, path / "CONTROL");
if (auto p = pghs.get()) if (auto p = pghs.get())
{ {
return SourceParagraph(*p); return SourceParagraph::parse_control_file(*p);
} }
error_info.error = pghs.error();
return pghs.error_code(); return error_info;
} }
Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec)
@ -222,20 +223,26 @@ namespace vcpkg::Paragraphs
return BinaryParagraph(*p); return BinaryParagraph(*p);
} }
return pghs.error_code(); return pghs.error();
} }
std::vector<SourceParagraph> 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::vector<SourceParagraph> output; std::vector<SourceParagraph> output;
std::vector<ParseControlErrorInfo> port_errors;
for (auto&& path : fs.get_files_non_recursive(ports_dir)) for (auto&& path : fs.get_files_non_recursive(ports_dir))
{ {
Expected<SourceParagraph> source_paragraph = try_load_port(fs, path); ExpectedT<SourceParagraph, ParseControlErrorInfo> source_paragraph = try_load_port(fs, path);
if (auto srcpgh = source_paragraph.get()) if (auto srcpgh = source_paragraph.get())
{ {
output.emplace_back(std::move(*srcpgh)); output.emplace_back(std::move(*srcpgh));
} }
else
{
port_errors.emplace_back(source_paragraph.error());
}
} }
print_error_message(port_errors);
return output; return output;
} }

View File

@ -5,6 +5,8 @@
#include "vcpkg_Checks.h" #include "vcpkg_Checks.h"
#include "vcpkg_Maps.h" #include "vcpkg_Maps.h"
#include "vcpkg_System.h" #include "vcpkg_System.h"
#include "vcpkg_expected.h"
#include "vcpkglib_helpers.h" #include "vcpkglib_helpers.h"
namespace vcpkg namespace vcpkg
@ -37,15 +39,41 @@ namespace vcpkg
SourceParagraph::SourceParagraph() = default; SourceParagraph::SourceParagraph() = default;
SourceParagraph::SourceParagraph(std::unordered_map<std::string, std::string> fields) void print_error_message(const ParseControlErrorInfo& info)
{ {
this->name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE); System::println(
this->version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION); System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", info.name);
this->description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION); System::println("The following fields were not expected:\n\n %s\n\n", info.remaining_fields_as_string);
this->maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER); 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");
}
void print_error_message(std::vector<ParseControlErrorInfo> error_info_list)
{
for (ParseControlErrorInfo 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);
}
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");
}
ExpectedT<SourceParagraph, ParseControlErrorInfo> SourceParagraph::parse_control_file(
std::unordered_map<std::string, std::string> fields)
{
SourceParagraph sparagraph;
sparagraph.name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE);
sparagraph.version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION);
sparagraph.description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION);
sparagraph.maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER);
std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS); std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS);
this->depends = expand_qualified_dependencies(parse_depends(deps)); sparagraph.depends = expand_qualified_dependencies(parse_depends(deps));
if (!fields.empty()) if (!fields.empty())
{ {
@ -55,12 +83,9 @@ namespace vcpkg
const std::string remaining_fields_as_string = Strings::join("\n ", remaining_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); const std::string valid_fields_as_string = Strings::join("\n ", valid_fields);
System::println( return ParseControlErrorInfo{sparagraph.name, remaining_fields_as_string, valid_fields_as_string};
System::Color::error, "Error: There are invalid fields in the Source Paragraph of %s", this->name);
System::println("The following fields were not expected:\n\n %s\n\n", remaining_fields_as_string);
System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", valid_fields_as_string);
Checks::exit_fail(VCPKG_LINE_INFO);
} }
return sparagraph;
} }
std::vector<Dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends) std::vector<Dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends)

View File

@ -33,13 +33,16 @@ namespace vcpkg::Commands::BuildCommand
Checks::exit_success(VCPKG_LINE_INFO); Checks::exit_success(VCPKG_LINE_INFO);
} }
const Expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.get_filesystem(), port_dir); const ExpectedT<SourceParagraph, ParseControlErrorInfo> maybe_spgh =
Checks::check_exit(VCPKG_LINE_INFO, Paragraphs::try_load_port(paths.get_filesystem(), port_dir);
!maybe_spgh.error_code(), // why do we add a const here
"Could not find package %s: %s", if (!maybe_spgh)
spec, {
maybe_spgh.error_code().message()); print_error_message(maybe_spgh.error());
const SourceParagraph& spgh = *maybe_spgh.get(); Checks::exit_fail(VCPKG_LINE_INFO);
}
const SourceParagraph& spgh = maybe_spgh.value_or_exit(VCPKG_LINE_INFO);
Checks::check_exit(VCPKG_LINE_INFO, Checks::check_exit(VCPKG_LINE_INFO,
spec.name() == spgh.name, spec.name() == spgh.name,
"The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'", "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'",

View File

@ -25,7 +25,10 @@ namespace UnitTest1
{ {
TEST_METHOD(SourceParagraph_Construct_Minimum) TEST_METHOD(SourceParagraph_Construct_Minimum)
{ {
vcpkg::SourceParagraph pgh({{"Source", "zlib"}, {"Version", "1.2.8"}}); auto m_pgh = vcpkg::SourceParagraph::parse_control_file({{"Source", "zlib"}, {"Version", "1.2.8"}});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
Assert::AreEqual("zlib", pgh.name.c_str()); Assert::AreEqual("zlib", pgh.name.c_str());
Assert::AreEqual("1.2.8", pgh.version.c_str()); Assert::AreEqual("1.2.8", pgh.version.c_str());
@ -36,11 +39,12 @@ namespace UnitTest1
TEST_METHOD(SourceParagraph_Construct_Maximum) TEST_METHOD(SourceParagraph_Construct_Maximum)
{ {
vcpkg::SourceParagraph pgh({{"Source", "s"}, auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
{"Version", "v"}, {"Source", "s"}, {"Version", "v"}, {"Maintainer", "m"}, {"Description", "d"}, {"Build-Depends", "bd"},
{"Maintainer", "m"}, });
{"Description", "d"}, Assert::IsTrue(m_pgh.has_value());
{"Build-Depends", "bd"}}); auto& pgh = *m_pgh.get();
Assert::AreEqual("s", pgh.name.c_str()); Assert::AreEqual("s", pgh.name.c_str());
Assert::AreEqual("v", pgh.version.c_str()); Assert::AreEqual("v", pgh.version.c_str());
Assert::AreEqual("m", pgh.maintainer.c_str()); Assert::AreEqual("m", pgh.maintainer.c_str());
@ -51,7 +55,11 @@ namespace UnitTest1
TEST_METHOD(SourceParagraph_Two_Depends) TEST_METHOD(SourceParagraph_Two_Depends)
{ {
vcpkg::SourceParagraph pgh({{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"}}); auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"},
});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
Assert::AreEqual(size_t(2), pgh.depends.size()); Assert::AreEqual(size_t(2), pgh.depends.size());
Assert::AreEqual("z", pgh.depends[0].name.c_str()); Assert::AreEqual("z", pgh.depends[0].name.c_str());
@ -60,8 +68,11 @@ namespace UnitTest1
TEST_METHOD(SourceParagraph_Three_Depends) TEST_METHOD(SourceParagraph_Three_Depends)
{ {
vcpkg::SourceParagraph pgh( auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
{{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"}}); {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"},
});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
Assert::AreEqual(size_t(3), pgh.depends.size()); Assert::AreEqual(size_t(3), pgh.depends.size());
Assert::AreEqual("z", pgh.depends[0].name.c_str()); Assert::AreEqual("z", pgh.depends[0].name.c_str());
@ -71,8 +82,11 @@ namespace UnitTest1
TEST_METHOD(SourceParagraph_Construct_Qualified_Depends) TEST_METHOD(SourceParagraph_Construct_Qualified_Depends)
{ {
vcpkg::SourceParagraph pgh( auto m_pgh = vcpkg::SourceParagraph::parse_control_file({
{{"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"}}); {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"},
});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
Assert::AreEqual("zlib", pgh.name.c_str()); Assert::AreEqual("zlib", pgh.name.c_str());
Assert::AreEqual("1.2.8", pgh.version.c_str()); Assert::AreEqual("1.2.8", pgh.version.c_str());
@ -101,13 +115,15 @@ namespace UnitTest1
TEST_METHOD(BinaryParagraph_Construct_Maximum) TEST_METHOD(BinaryParagraph_Construct_Maximum)
{ {
vcpkg::BinaryParagraph pgh({{"Package", "s"}, vcpkg::BinaryParagraph pgh({
{"Version", "v"}, {"Package", "s"},
{"Architecture", "x86-windows"}, {"Version", "v"},
{"Multi-Arch", "same"}, {"Architecture", "x86-windows"},
{"Maintainer", "m"}, {"Multi-Arch", "same"},
{"Description", "d"}, {"Maintainer", "m"},
{"Depends", "bd"}}); {"Description", "d"},
{"Depends", "bd"},
});
Assert::AreEqual("s", pgh.spec.name().c_str()); Assert::AreEqual("s", pgh.spec.name().c_str());
Assert::AreEqual("v", pgh.version.c_str()); Assert::AreEqual("v", pgh.version.c_str());
Assert::AreEqual("m", pgh.maintainer.c_str()); Assert::AreEqual("m", pgh.maintainer.c_str());
@ -327,28 +343,26 @@ namespace UnitTest1
TEST_METHOD(package_spec_parse) TEST_METHOD(package_spec_parse)
{ {
vcpkg::Expected<vcpkg::PackageSpec> spec = vcpkg::ExpectedT<vcpkg::PackageSpec, vcpkg::PackageSpecParseResult> spec =
vcpkg::PackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS); vcpkg::PackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS);
Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error());
vcpkg::to_package_spec_parse_result(spec.error_code()));
Assert::AreEqual("zlib", spec.get()->name().c_str()); Assert::AreEqual("zlib", spec.get()->name().c_str());
Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), spec.get()->triplet().canonical_name()); Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(), spec.get()->triplet().canonical_name());
} }
TEST_METHOD(package_spec_parse_with_arch) TEST_METHOD(package_spec_parse_with_arch)
{ {
vcpkg::Expected<vcpkg::PackageSpec> spec = vcpkg::ExpectedT<vcpkg::PackageSpec, vcpkg::PackageSpecParseResult> spec =
vcpkg::PackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS); vcpkg::PackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS);
Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error());
vcpkg::to_package_spec_parse_result(spec.error_code()));
Assert::AreEqual("zlib", spec.get()->name().c_str()); Assert::AreEqual("zlib", spec.get()->name().c_str());
Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), spec.get()->triplet().canonical_name()); Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(), spec.get()->triplet().canonical_name());
} }
TEST_METHOD(package_spec_parse_with_multiple_colon) TEST_METHOD(package_spec_parse_with_multiple_colon)
{ {
auto ec = vcpkg::PackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error_code(); auto ec = vcpkg::PackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error();
Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, vcpkg::to_package_spec_parse_result(ec)); Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec);
} }
TEST_METHOD(utf8_to_utf16) TEST_METHOD(utf8_to_utf16)

View File

@ -61,10 +61,10 @@ static void inner(const VcpkgCmdArguments& args)
const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir); const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir);
Checks::check_exit(VCPKG_LINE_INFO, Checks::check_exit(VCPKG_LINE_INFO,
!expected_paths.error_code(), !expected_paths.error(),
"Error: Invalid vcpkg root directory %s: %s", "Error: Invalid vcpkg root directory %s: %s",
vcpkg_root_dir.string(), vcpkg_root_dir.string(),
expected_paths.error_code().message()); expected_paths.error().message());
const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO); const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO);
int exit_code = _wchdir(paths.root.c_str()); int exit_code = _wchdir(paths.root.c_str());
Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed"); Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed");

View File

@ -174,11 +174,14 @@ namespace vcpkg::Dependencies
if (auto bpgh = maybe_bpgh.get()) if (auto bpgh = maybe_bpgh.get())
return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; return InstallPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type};
Expected<SourceParagraph> maybe_spgh = ExpectedT<SourceParagraph, ParseControlErrorInfo> maybe_spgh =
Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
if (auto spgh = maybe_spgh.get()) if (auto spgh = maybe_spgh.get())
return InstallPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; 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); Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec);
} }
}; };
@ -283,11 +286,14 @@ namespace vcpkg::Dependencies
if (auto bpgh = maybe_bpgh.get()) if (auto bpgh = maybe_bpgh.get())
return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type}; return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type};
Expected<SourceParagraph> maybe_spgh = ExpectedT<SourceParagraph, ParseControlErrorInfo> maybe_spgh =
Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec)); Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
if (auto spgh = maybe_spgh.get()) if (auto spgh = maybe_spgh.get())
return ExportPlanAction{spec, {nullopt, nullopt, *spgh}, request_type}; return ExportPlanAction{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); Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec);
} }
}; };

View File

@ -15,7 +15,7 @@ namespace vcpkg::Files
std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
if (file_stream.fail()) if (file_stream.fail())
{ {
return std::errc::no_such_file_or_directory; return std::make_error_code(std::errc::no_such_file_or_directory);
} }
file_stream.seekg(0, file_stream.end); file_stream.seekg(0, file_stream.end);
@ -24,7 +24,7 @@ namespace vcpkg::Files
if (length > SIZE_MAX) if (length > SIZE_MAX)
{ {
return std::errc::file_too_large; return std::make_error_code(std::errc::file_too_large);
} }
std::string output; std::string output;
@ -39,7 +39,7 @@ namespace vcpkg::Files
std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary); std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
if (file_stream.fail()) if (file_stream.fail())
{ {
return std::errc::no_such_file_or_directory; return std::make_error_code(std::errc::no_such_file_or_directory);
} }
std::vector<std::string> output; std::vector<std::string> output;

View File

@ -12,14 +12,14 @@ namespace vcpkg::Input
CStringView example_text) CStringView example_text)
{ {
const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string); const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string);
Expected<PackageSpec> expected_spec = PackageSpec::from_string(as_lowercase, default_triplet); auto expected_spec = PackageSpec::from_string(as_lowercase, default_triplet);
if (auto spec = expected_spec.get()) if (auto spec = expected_spec.get())
{ {
return *spec; return *spec;
} }
// Intentionally show the lowercased string // Intentionally show the lowercased string
System::println(System::Color::error, "Error: %s: %s", expected_spec.error_code().message(), as_lowercase); System::println(System::Color::error, "Error: %s: %s", vcpkg::to_string(expected_spec.error()), as_lowercase);
System::print(example_text); System::print(example_text);
Checks::exit_fail(VCPKG_LINE_INFO); Checks::exit_fail(VCPKG_LINE_INFO);
} }