Make status line parsing testable. (#1528)
Removes Want::UNKNOWN as this was only ever referenced in to_string, and never otherwise used in the product.
This commit is contained in:
Родитель
360e5c64da
Коммит
84e2dcfb2e
|
@ -581,5 +581,4 @@ namespace vcpkg
|
|||
inline constexpr StringLiteral StatusInstalled = "installed";
|
||||
inline constexpr StringLiteral StatusNotInstalled = "not-installed";
|
||||
inline constexpr StringLiteral StatusPurge = "purge";
|
||||
inline constexpr StringLiteral StatusUnknown = "unknown";
|
||||
}
|
||||
|
|
|
@ -1172,6 +1172,10 @@ DECLARE_MESSAGE(ExpectedFailOrSkip, (), "", "expected 'fail', 'skip', or 'pass'
|
|||
DECLARE_MESSAGE(ExpectedFeatureListTerminal, (), "", "expected ',' or ']' in feature list")
|
||||
DECLARE_MESSAGE(ExpectedFeatureName, (), "", "expected feature name (must be lowercase, digits, '-')")
|
||||
DECLARE_MESSAGE(ExpectedExplicitTriplet, (), "", "expected an explicit triplet")
|
||||
DECLARE_MESSAGE(ExpectedInstallStateField,
|
||||
(),
|
||||
"The values in ''s are locale-invariant",
|
||||
"expected one of 'not-installed', 'half-installed', or 'installed'")
|
||||
DECLARE_MESSAGE(ExpectedOneSetOfTags,
|
||||
(msg::count, msg::old_value, msg::new_value, msg::value),
|
||||
"{old_value} is a left tag and {new_value} is the right tag. {value} is the input.",
|
||||
|
@ -1181,7 +1185,15 @@ DECLARE_MESSAGE(ExpectedPathToExist, (msg::path), "", "Expected {path} to exist
|
|||
DECLARE_MESSAGE(ExpectedPortName, (), "", "expected a port name here (must be lowercase, digits, '-')")
|
||||
DECLARE_MESSAGE(ExpectedReadWriteReadWrite, (), "", "unexpected argument: expected 'read', readwrite', or 'write'")
|
||||
DECLARE_MESSAGE(ExpectedStatusField, (), "", "Expected 'status' field in status paragraph")
|
||||
DECLARE_MESSAGE(ExpectedTextHere,
|
||||
(msg::expected),
|
||||
"{expected} is a locale-invariant string a parser was searching for",
|
||||
"expected '{expected}' here")
|
||||
DECLARE_MESSAGE(ExpectedTripletName, (), "", "expected a triplet name here (must be lowercase, digits, '-')")
|
||||
DECLARE_MESSAGE(ExpectedWantField,
|
||||
(),
|
||||
"The values in ''s are locale-invariant",
|
||||
"expected one of 'install', 'hold', 'deinstall', or 'purge' here")
|
||||
DECLARE_MESSAGE(ExportArchitectureReq,
|
||||
(),
|
||||
"",
|
||||
|
|
|
@ -90,6 +90,7 @@ namespace vcpkg
|
|||
}
|
||||
|
||||
bool require_character(char ch);
|
||||
bool require_text(StringLiteral keyword);
|
||||
|
||||
bool try_match_keyword(StringView keyword_content);
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ namespace vcpkg
|
|||
enum class Want
|
||||
{
|
||||
ERROR_STATE,
|
||||
UNKNOWN,
|
||||
INSTALL,
|
||||
HOLD,
|
||||
DEINSTALL,
|
||||
PURGE
|
||||
};
|
||||
|
||||
struct StatusLine;
|
||||
struct StatusParagraph;
|
||||
struct InstalledPackageView;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include <vcpkg/sourceparagraph.h>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
|
@ -24,6 +25,8 @@ namespace vcpkg::Paragraphs
|
|||
|
||||
ExpectedL<std::vector<Paragraph>> parse_paragraphs(StringView str, StringView origin);
|
||||
|
||||
void append_paragraph_field(StringView name, StringView field, std::string& out_str);
|
||||
|
||||
bool is_port_directory(const ReadOnlyFilesystem& fs, const Path& maybe_directory);
|
||||
|
||||
struct PortLoadResult
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <vcpkg/fwd/installedpaths.h>
|
||||
#include <vcpkg/fwd/statusparagraph.h>
|
||||
|
||||
#include <vcpkg/base/fmt.h>
|
||||
|
||||
#include <vcpkg/binaryparagraph.h>
|
||||
|
||||
#include <map>
|
||||
|
@ -13,18 +15,35 @@
|
|||
|
||||
namespace vcpkg
|
||||
{
|
||||
struct StatusLine
|
||||
{
|
||||
Want want = Want::ERROR_STATE;
|
||||
InstallState state = InstallState::ERROR_STATE;
|
||||
|
||||
bool is_installed() const noexcept { return want == Want::INSTALL && state == InstallState::INSTALLED; }
|
||||
void to_string(std::string& out) const;
|
||||
std::string to_string() const;
|
||||
|
||||
friend bool operator==(const StatusLine& lhs, const StatusLine& rhs)
|
||||
{
|
||||
return lhs.want == rhs.want && lhs.state == rhs.state;
|
||||
}
|
||||
|
||||
friend bool operator!=(const StatusLine& lhs, const StatusLine& rhs) { return !(lhs == rhs); }
|
||||
};
|
||||
|
||||
ExpectedL<StatusLine> parse_status_line(StringView text, Optional<StringView> origin, TextRowCol init_rowcol);
|
||||
|
||||
// metadata for a package's representation in the 'installed' tree
|
||||
struct StatusParagraph
|
||||
{
|
||||
StatusParagraph() noexcept;
|
||||
StatusParagraph() = default;
|
||||
StatusParagraph(StringView origin, Paragraph&& fields);
|
||||
|
||||
bool is_installed() const { return want == Want::INSTALL && state == InstallState::INSTALLED; }
|
||||
bool is_installed() const noexcept { return status.is_installed(); }
|
||||
|
||||
BinaryParagraph package;
|
||||
Want want;
|
||||
InstallState state;
|
||||
StatusLine status;
|
||||
};
|
||||
|
||||
void serialize(const StatusParagraph& pgh, std::string& out_str);
|
||||
|
@ -59,3 +78,4 @@ namespace vcpkg
|
|||
|
||||
VCPKG_FORMAT_WITH_TO_STRING_LITERAL_NONMEMBER(vcpkg::InstallState);
|
||||
VCPKG_FORMAT_WITH_TO_STRING_LITERAL_NONMEMBER(vcpkg::Want);
|
||||
VCPKG_FORMAT_WITH_TO_STRING(vcpkg::StatusLine);
|
||||
|
|
|
@ -691,6 +691,8 @@
|
|||
"ExpectedFailOrSkip": "expected 'fail', 'skip', or 'pass' here",
|
||||
"ExpectedFeatureListTerminal": "expected ',' or ']' in feature list",
|
||||
"ExpectedFeatureName": "expected feature name (must be lowercase, digits, '-')",
|
||||
"ExpectedInstallStateField": "expected one of 'not-installed', 'half-installed', or 'installed'",
|
||||
"_ExpectedInstallStateField.comment": "The values in ''s are locale-invariant",
|
||||
"ExpectedOneSetOfTags": "Found {count} sets of {old_value}.*{new_value} but expected exactly 1, in block:\n{value}",
|
||||
"_ExpectedOneSetOfTags.comment": "{old_value} is a left tag and {new_value} is the right tag. {value} is the input. An example of {count} is 42.",
|
||||
"ExpectedOneVersioningField": "expected only one versioning field",
|
||||
|
@ -699,7 +701,11 @@
|
|||
"ExpectedPortName": "expected a port name here (must be lowercase, digits, '-')",
|
||||
"ExpectedReadWriteReadWrite": "unexpected argument: expected 'read', readwrite', or 'write'",
|
||||
"ExpectedStatusField": "Expected 'status' field in status paragraph",
|
||||
"ExpectedTextHere": "expected '{expected}' here",
|
||||
"_ExpectedTextHere.comment": "{expected} is a locale-invariant string a parser was searching for",
|
||||
"ExpectedTripletName": "expected a triplet name here (must be lowercase, digits, '-')",
|
||||
"ExpectedWantField": "expected one of 'install', 'hold', 'deinstall', or 'purge' here",
|
||||
"_ExpectedWantField.comment": "The values in ''s are locale-invariant",
|
||||
"ExportArchitectureReq": "Export prefab requires targeting at least one of the following architectures arm64-v8a, armeabi-v7a, x86_64, x86 to be present.",
|
||||
"ExportPrefabRequiresAndroidTriplet": "export prefab requires an Android triplet.",
|
||||
"Exported7zipArchive": "7zip archive exported at: {path}",
|
||||
|
|
|
@ -9,6 +9,38 @@ using namespace vcpkg;
|
|||
using namespace vcpkg::Paragraphs;
|
||||
using namespace vcpkg::Test;
|
||||
|
||||
static constexpr StringLiteral test_origin = "test";
|
||||
static constexpr TextRowCol test_textrowcol = {42, 34};
|
||||
|
||||
TEST_CASE ("parse status lines", "[statusparagraphs]")
|
||||
{
|
||||
REQUIRE(parse_status_line("install ok installed", test_origin, test_textrowcol).value_or_exit(VCPKG_LINE_INFO) ==
|
||||
StatusLine{Want::INSTALL, InstallState::INSTALLED});
|
||||
REQUIRE(parse_status_line("hold ok installed", test_origin, test_textrowcol).value_or_exit(VCPKG_LINE_INFO) ==
|
||||
StatusLine{Want::HOLD, InstallState::INSTALLED});
|
||||
REQUIRE(parse_status_line("deinstall ok installed", test_origin, test_textrowcol).value_or_exit(VCPKG_LINE_INFO) ==
|
||||
StatusLine{Want::DEINSTALL, InstallState::INSTALLED});
|
||||
REQUIRE(parse_status_line("purge ok installed", test_origin, test_textrowcol).value_or_exit(VCPKG_LINE_INFO) ==
|
||||
StatusLine{Want::PURGE, InstallState::INSTALLED});
|
||||
|
||||
REQUIRE(
|
||||
parse_status_line("install ok not-installed", test_origin, test_textrowcol).value_or_exit(VCPKG_LINE_INFO) ==
|
||||
StatusLine{Want::INSTALL, InstallState::NOT_INSTALLED});
|
||||
REQUIRE(
|
||||
parse_status_line("install ok half-installed", test_origin, test_textrowcol).value_or_exit(VCPKG_LINE_INFO) ==
|
||||
StatusLine{Want::INSTALL, InstallState::HALF_INSTALLED});
|
||||
|
||||
REQUIRE(parse_status_line("meow ok installed", test_origin, test_textrowcol).error() ==
|
||||
LocalizedString::from_raw("test:42:34: error: expected one of 'install', 'hold', 'deinstall', or 'purge' "
|
||||
"here\n on expression: meow ok installed\n ^"));
|
||||
REQUIRE(parse_status_line("install ko half-installed", test_origin, test_textrowcol).error() ==
|
||||
LocalizedString::from_raw("test:42:41: error: expected ' ok ' here\n on expression: install ko "
|
||||
"half-installed\n ^"));
|
||||
REQUIRE(parse_status_line("install ok meow", test_origin, test_textrowcol).error() ==
|
||||
LocalizedString::from_raw("test:42:45: error: expected one of 'not-installed', 'half-installed', or "
|
||||
"'installed'\n on expression: install ok meow\n ^"));
|
||||
}
|
||||
|
||||
TEST_CASE ("find installed", "[statusparagraphs]")
|
||||
{
|
||||
auto pghs = parse_paragraphs(R"(
|
||||
|
@ -23,9 +55,8 @@ Status: install ok installed
|
|||
|
||||
REQUIRE(pghs);
|
||||
|
||||
StatusParagraphs status_db(Util::fmap(*pghs.get(), [](Paragraph& rpgh) {
|
||||
return std::make_unique<StatusParagraph>(StringLiteral{"test"}, std::move(rpgh));
|
||||
}));
|
||||
StatusParagraphs status_db(Util::fmap(
|
||||
*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(test_origin, std::move(rpgh)); }));
|
||||
|
||||
auto it = status_db.find_installed({"ffmpeg", Test::X64_WINDOWS});
|
||||
REQUIRE(it != status_db.end());
|
||||
|
@ -45,9 +76,8 @@ Status: purge ok not-installed
|
|||
|
||||
REQUIRE(pghs);
|
||||
|
||||
StatusParagraphs status_db(Util::fmap(*pghs.get(), [](Paragraph& rpgh) {
|
||||
return std::make_unique<StatusParagraph>(StringLiteral{"test"}, std::move(rpgh));
|
||||
}));
|
||||
StatusParagraphs status_db(Util::fmap(
|
||||
*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(test_origin, std::move(rpgh)); }));
|
||||
|
||||
auto it = status_db.find_installed({"ffmpeg", Test::X64_WINDOWS});
|
||||
REQUIRE(it == status_db.end());
|
||||
|
@ -75,9 +105,8 @@ Status: purge ok not-installed
|
|||
|
||||
REQUIRE(pghs);
|
||||
|
||||
StatusParagraphs status_db(Util::fmap(*pghs.get(), [](Paragraph& rpgh) {
|
||||
return std::make_unique<StatusParagraph>(StringLiteral{"test"}, std::move(rpgh));
|
||||
}));
|
||||
StatusParagraphs status_db(Util::fmap(
|
||||
*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(test_origin, std::move(rpgh)); }));
|
||||
|
||||
auto it = status_db.find_installed({"ffmpeg", Test::X64_WINDOWS});
|
||||
REQUIRE(it != status_db.end());
|
||||
|
@ -108,9 +137,8 @@ Status: install ok installed
|
|||
"test-origin");
|
||||
REQUIRE(pghs);
|
||||
|
||||
StatusParagraphs status_db(Util::fmap(*pghs.get(), [](Paragraph& rpgh) {
|
||||
return std::make_unique<StatusParagraph>(StringLiteral{"test"}, std::move(rpgh));
|
||||
}));
|
||||
StatusParagraphs status_db(Util::fmap(
|
||||
*pghs.get(), [](Paragraph& rpgh) { return std::make_unique<StatusParagraph>(test_origin, std::move(rpgh)); }));
|
||||
|
||||
// Feature "openssl" is installed and should therefore be found
|
||||
auto it = status_db.find_installed({{"ffmpeg", Test::X64_WINDOWS}, "openssl"});
|
||||
|
|
|
@ -64,8 +64,7 @@ TEST_CASE ("find outdated packages features 2", "[update]")
|
|||
|
||||
status_paragraphs.push_back(make_status_feature_pgh("a", "b"));
|
||||
status_paragraphs.back()->package.version = Version{"0", 0};
|
||||
status_paragraphs.back()->state = InstallState::NOT_INSTALLED;
|
||||
status_paragraphs.back()->want = Want::PURGE;
|
||||
status_paragraphs.back()->status = {Want::PURGE, InstallState::NOT_INSTALLED};
|
||||
|
||||
StatusParagraphs status_db(std::move(status_paragraphs));
|
||||
|
||||
|
|
|
@ -146,6 +146,27 @@ namespace vcpkg
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ParserBase::require_text(StringLiteral text)
|
||||
{
|
||||
auto encoded = m_it;
|
||||
// check that the encoded stream matches the keyword:
|
||||
for (const char ch : text)
|
||||
{
|
||||
if (encoded.is_eof() || *encoded != static_cast<char32_t>(ch))
|
||||
{
|
||||
add_error(msg::format(msgExpectedTextHere, msg::expected = text));
|
||||
return false;
|
||||
}
|
||||
|
||||
++encoded;
|
||||
}
|
||||
|
||||
// success
|
||||
m_it = encoded;
|
||||
m_column += static_cast<int>(text.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserBase::try_match_keyword(StringView keyword_content)
|
||||
{
|
||||
auto encoded = m_it;
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
#include <vcpkg/paragraphparser.h>
|
||||
#include <vcpkg/paragraphs.h>
|
||||
|
||||
using namespace vcpkg::Paragraphs;
|
||||
|
||||
namespace vcpkg
|
||||
{
|
||||
BinaryParagraph::BinaryParagraph(StringView origin, Paragraph&& fields)
|
||||
: spec(), version(), description(), maintainers(), feature(), default_features(), dependencies(), abi()
|
||||
{
|
||||
ParagraphParser parser(origin, std::move(fields));
|
||||
this->spec = PackageSpec(parser.required_field(ParagraphIdPackage),
|
||||
|
@ -177,15 +180,6 @@ namespace vcpkg
|
|||
|
||||
bool operator!=(const BinaryParagraph& lhs, const BinaryParagraph& rhs) { return !(lhs == rhs); }
|
||||
|
||||
static void serialize_string(StringView name, const std::string& field, std::string& out_str)
|
||||
{
|
||||
if (field.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
out_str.append(name.data(), name.size()).append(": ").append(field).push_back('\n');
|
||||
}
|
||||
static void serialize_array(StringView name,
|
||||
const std::vector<std::string>& array,
|
||||
std::string& out_str,
|
||||
|
@ -223,9 +217,8 @@ namespace vcpkg
|
|||
{
|
||||
const size_t initial_end = out_str.size();
|
||||
|
||||
serialize_string(ParagraphIdPackage, pgh.spec.name(), out_str);
|
||||
|
||||
serialize_string(ParagraphIdVersion, pgh.version.text, out_str);
|
||||
append_paragraph_field(ParagraphIdPackage, pgh.spec.name(), out_str);
|
||||
append_paragraph_field(ParagraphIdVersion, pgh.version.text, out_str);
|
||||
if (pgh.version.port_version != 0)
|
||||
{
|
||||
fmt::format_to(std::back_inserter(out_str), "{}: {}\n", ParagraphIdPortVersion, pgh.version.port_version);
|
||||
|
@ -233,23 +226,20 @@ namespace vcpkg
|
|||
|
||||
if (pgh.is_feature())
|
||||
{
|
||||
serialize_string(ParagraphIdFeature, pgh.feature, out_str);
|
||||
append_paragraph_field(ParagraphIdFeature, pgh.feature, out_str);
|
||||
}
|
||||
|
||||
if (!pgh.dependencies.empty())
|
||||
{
|
||||
serialize_string(ParagraphIdDepends, serialize_deps_list(pgh.dependencies, pgh.spec.triplet()), out_str);
|
||||
append_paragraph_field(
|
||||
ParagraphIdDepends, serialize_deps_list(pgh.dependencies, pgh.spec.triplet()), out_str);
|
||||
}
|
||||
|
||||
serialize_string(ParagraphIdArchitecture, pgh.spec.triplet().to_string(), out_str);
|
||||
serialize_string(ParagraphIdMultiArch, "same", out_str);
|
||||
|
||||
append_paragraph_field(ParagraphIdArchitecture, pgh.spec.triplet().to_string(), out_str);
|
||||
append_paragraph_field(ParagraphIdMultiArch, "same", out_str);
|
||||
serialize_paragraph(ParagraphIdMaintainer, pgh.maintainers, out_str);
|
||||
|
||||
serialize_string(ParagraphIdAbi, pgh.abi, out_str);
|
||||
|
||||
append_paragraph_field(ParagraphIdAbi, pgh.abi, out_str);
|
||||
serialize_paragraph(ParagraphIdDescription, pgh.description, out_str);
|
||||
|
||||
serialize_array(ParagraphIdDefaultFeatures, pgh.default_features, out_str);
|
||||
|
||||
// sanity check the serialized data
|
||||
|
|
|
@ -280,8 +280,7 @@ namespace vcpkg
|
|||
|
||||
StatusParagraph source_paragraph;
|
||||
source_paragraph.package = bcf.core_paragraph;
|
||||
source_paragraph.want = Want::INSTALL;
|
||||
source_paragraph.state = InstallState::HALF_INSTALLED;
|
||||
source_paragraph.status = StatusLine{Want::INSTALL, InstallState::HALF_INSTALLED};
|
||||
|
||||
write_update(fs, installed, source_paragraph);
|
||||
status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
|
||||
|
@ -291,8 +290,7 @@ namespace vcpkg
|
|||
{
|
||||
StatusParagraph& feature_paragraph = features_spghs.emplace_back();
|
||||
feature_paragraph.package = feature;
|
||||
feature_paragraph.want = Want::INSTALL;
|
||||
feature_paragraph.state = InstallState::HALF_INSTALLED;
|
||||
feature_paragraph.status = StatusLine{Want::INSTALL, InstallState::HALF_INSTALLED};
|
||||
|
||||
write_update(fs, installed, feature_paragraph);
|
||||
status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
|
||||
|
@ -303,13 +301,13 @@ namespace vcpkg
|
|||
|
||||
install_package_and_write_listfile(fs, package_dir, install_dir);
|
||||
|
||||
source_paragraph.state = InstallState::INSTALLED;
|
||||
source_paragraph.status.state = InstallState::INSTALLED;
|
||||
write_update(fs, installed, source_paragraph);
|
||||
status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
|
||||
|
||||
for (auto&& feature_paragraph : features_spghs)
|
||||
{
|
||||
feature_paragraph.state = InstallState::INSTALLED;
|
||||
feature_paragraph.status.state = InstallState::INSTALLED;
|
||||
write_update(fs, installed, feature_paragraph);
|
||||
status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
|
||||
}
|
||||
|
|
|
@ -30,8 +30,7 @@ namespace vcpkg
|
|||
|
||||
for (auto&& spgh : spghs)
|
||||
{
|
||||
spgh.want = Want::PURGE;
|
||||
spgh.state = InstallState::HALF_INSTALLED;
|
||||
spgh.status = {Want::PURGE, InstallState::HALF_INSTALLED};
|
||||
write_update(fs, installed, spgh);
|
||||
}
|
||||
|
||||
|
@ -93,9 +92,8 @@ namespace vcpkg
|
|||
|
||||
for (auto&& spgh : spghs)
|
||||
{
|
||||
spgh.state = InstallState::NOT_INSTALLED;
|
||||
spgh.status.state = InstallState::NOT_INSTALLED;
|
||||
write_update(fs, installed, spgh);
|
||||
|
||||
status_db.insert(std::make_unique<StatusParagraph>(std::move(spgh)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -352,6 +352,16 @@ namespace vcpkg::Paragraphs
|
|||
return PghParser(str, origin).get_paragraphs();
|
||||
}
|
||||
|
||||
void append_paragraph_field(StringView name, StringView field, std::string& out_str)
|
||||
{
|
||||
if (field.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
out_str.append(name.data(), name.size()).append(": ").append(field.data(), field.size()).push_back('\n');
|
||||
}
|
||||
|
||||
bool is_port_directory(const ReadOnlyFilesystem& fs, const Path& maybe_directory)
|
||||
{
|
||||
return fs.exists(maybe_directory / "CONTROL", IgnoreErrors{}) ||
|
||||
|
|
|
@ -1,60 +1,94 @@
|
|||
#include <vcpkg/base/contractual-constants.h>
|
||||
#include <vcpkg/base/util.h>
|
||||
|
||||
#include <vcpkg/paragraphs.h>
|
||||
#include <vcpkg/statusparagraph.h>
|
||||
|
||||
using namespace vcpkg::Paragraphs;
|
||||
|
||||
namespace vcpkg
|
||||
{
|
||||
StatusParagraph::StatusParagraph() noexcept : want(Want::ERROR_STATE), state(InstallState::ERROR_STATE) { }
|
||||
|
||||
void serialize(const StatusParagraph& pgh, std::string& out_str)
|
||||
void StatusLine::to_string(std::string& out) const
|
||||
{
|
||||
auto want_literal = to_string_literal(pgh.want);
|
||||
auto state_literal = to_string_literal(pgh.state);
|
||||
serialize(pgh.package, out_str);
|
||||
out_str.append("Status: ")
|
||||
.append(want_literal.data(), want_literal.size())
|
||||
.append(" ok ")
|
||||
.append(state_literal.data(), state_literal.size())
|
||||
.push_back('\n');
|
||||
fmt::format_to(std::back_inserter(out), "{} ok {}", want, state);
|
||||
}
|
||||
|
||||
std::string StatusLine::to_string() const { return adapt_to_string(*this); }
|
||||
|
||||
ExpectedL<StatusLine> parse_status_line(StringView text, Optional<StringView> origin, TextRowCol init_rowcol)
|
||||
{
|
||||
ParserBase parser{text, origin, init_rowcol};
|
||||
StatusLine result;
|
||||
const auto want_start = parser.cur_loc();
|
||||
auto want_text = parser.match_until(ParserBase::is_whitespace);
|
||||
if (want_text == StatusInstall)
|
||||
{
|
||||
result.want = Want::INSTALL;
|
||||
}
|
||||
else if (want_text == StatusHold)
|
||||
{
|
||||
result.want = Want::HOLD;
|
||||
}
|
||||
else if (want_text == StatusDeinstall)
|
||||
{
|
||||
result.want = Want::DEINSTALL;
|
||||
}
|
||||
else if (want_text == StatusPurge)
|
||||
{
|
||||
result.want = Want::PURGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.add_error(msg::format(msgExpectedWantField), want_start);
|
||||
return parser.extract_messages().error.value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
if (parser.require_text(" ok "))
|
||||
{
|
||||
auto state_start = parser.cur_loc();
|
||||
auto state_text = parser.match_until(ParserBase::is_whitespace);
|
||||
if (state_text == StatusNotInstalled)
|
||||
{
|
||||
result.state = InstallState::NOT_INSTALLED;
|
||||
}
|
||||
else if (state_text == StatusInstalled)
|
||||
{
|
||||
result.state = InstallState::INSTALLED;
|
||||
}
|
||||
else if (state_text == StatusHalfInstalled)
|
||||
{
|
||||
result.state = InstallState::HALF_INSTALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.add_error(msg::format(msgExpectedInstallStateField), state_start);
|
||||
return parser.extract_messages().error.value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
if (parser.messages().good())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return parser.extract_messages().error.value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
void serialize(const StatusParagraph& pgh, std::string& out)
|
||||
{
|
||||
serialize(pgh.package, out);
|
||||
append_paragraph_field(ParagraphIdStatus, pgh.status.to_string(), out);
|
||||
}
|
||||
|
||||
StatusParagraph::StatusParagraph(StringView origin, Paragraph&& fields)
|
||||
: want(Want::ERROR_STATE), state(InstallState::ERROR_STATE)
|
||||
{
|
||||
auto status_it = fields.find(ParagraphIdStatus);
|
||||
Checks::msg_check_maybe_upgrade(VCPKG_LINE_INFO, status_it != fields.end(), msgExpectedStatusField);
|
||||
std::string status_field = std::move(status_it->second.first);
|
||||
auto status_field = std::move(status_it->second);
|
||||
fields.erase(status_it);
|
||||
|
||||
this->package = BinaryParagraph(origin, std::move(fields));
|
||||
|
||||
auto b = status_field.begin();
|
||||
const auto mark = b;
|
||||
const auto e = status_field.end();
|
||||
|
||||
// Todo: improve error handling
|
||||
while (b != e && *b != ' ')
|
||||
++b;
|
||||
|
||||
want = [](const std::string& text) {
|
||||
if (text == StatusUnknown) return Want::UNKNOWN;
|
||||
if (text == StatusInstall) return Want::INSTALL;
|
||||
if (text == StatusHold) return Want::HOLD;
|
||||
if (text == StatusDeinstall) return Want::DEINSTALL;
|
||||
if (text == StatusPurge) return Want::PURGE;
|
||||
return Want::ERROR_STATE;
|
||||
}(std::string(mark, b));
|
||||
|
||||
if (std::distance(b, e) < 4) return;
|
||||
b += 4;
|
||||
|
||||
state = [](const std::string& text) {
|
||||
if (text == StatusNotInstalled) return InstallState::NOT_INSTALLED;
|
||||
if (text == StatusInstalled) return InstallState::INSTALLED;
|
||||
if (text == StatusHalfInstalled) return InstallState::HALF_INSTALLED;
|
||||
return InstallState::ERROR_STATE;
|
||||
}(std::string(b, e));
|
||||
this->status =
|
||||
parse_status_line(status_field.first, origin, status_field.second).value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
StringLiteral to_string_literal(InstallState f)
|
||||
|
@ -76,7 +110,6 @@ namespace vcpkg
|
|||
case Want::HOLD: return StatusHold;
|
||||
case Want::INSTALL: return StatusInstall;
|
||||
case Want::PURGE: return StatusPurge;
|
||||
case Want::UNKNOWN: return StatusUnknown;
|
||||
default: Checks::unreachable(VCPKG_LINE_INFO);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,16 @@ namespace vcpkg
|
|||
if (p->package.spec.name() == name && p->package.spec.triplet() == triplet)
|
||||
{
|
||||
if (p->package.is_feature())
|
||||
{
|
||||
spghs.emplace_back(&p);
|
||||
}
|
||||
else
|
||||
{
|
||||
spghs.emplace(spghs.begin(), &p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return spghs;
|
||||
}
|
||||
|
||||
|
@ -46,10 +51,13 @@ namespace vcpkg
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ipv.core != nullptr)
|
||||
{
|
||||
return ipv;
|
||||
else
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
StatusParagraphs::iterator StatusParagraphs::find(const std::string& name,
|
||||
|
@ -76,6 +84,7 @@ namespace vcpkg
|
|||
// The core feature maps to .feature == ""
|
||||
return find(name, triplet, "");
|
||||
}
|
||||
|
||||
return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
|
||||
const PackageSpec& spec = pgh->package.spec;
|
||||
return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature;
|
||||
|
@ -89,10 +98,8 @@ namespace vcpkg
|
|||
{
|
||||
return it;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
StatusParagraphs::const_iterator StatusParagraphs::find_installed(const FeatureSpec& spec) const
|
||||
|
@ -102,10 +109,8 @@ namespace vcpkg
|
|||
{
|
||||
return it;
|
||||
}
|
||||
else
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
bool vcpkg::StatusParagraphs::is_installed(const PackageSpec& spec) const
|
||||
|
|
Загрузка…
Ссылка в новой задаче