Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions toolsrc/include/vcpkg/packagespec.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <vcpkg/platform-expression.h>
#include <vcpkg/triplet.h>
#include <vcpkg/versions.h>

namespace vcpkg::Parse
{
Expand Down Expand Up @@ -133,18 +134,45 @@ namespace vcpkg
static ExpectedS<Features> from_string(const std::string& input);
};

struct DependencyConstraint
{
Versions::Constraint::Type type = Versions::Constraint::Type::None;
std::string value;
int port_version = 0;

friend bool operator==(const DependencyConstraint& lhs, const DependencyConstraint& rhs);
friend bool operator!=(const DependencyConstraint& lhs, const DependencyConstraint& rhs)
{
return !(lhs == rhs);
}
};

struct Dependency
{
std::string name;
std::vector<std::string> features;
PlatformExpression::Expr platform;
DependencyConstraint constraint;

Json::Object extra_info;

friend bool operator==(const Dependency& lhs, const Dependency& rhs);
friend bool operator!=(const Dependency& lhs, const Dependency& rhs) { return !(lhs == rhs); }
};

struct DependencyOverride
{
std::string name;
Versions::Scheme version_scheme = Versions::Scheme::String;
std::string version;
int port_version = 0;

Json::Object extra_info;

friend bool operator==(const DependencyOverride& lhs, const DependencyOverride& rhs);
friend bool operator!=(const DependencyOverride& lhs, const DependencyOverride& rhs) { return !(lhs == rhs); }
};

struct ParsedQualifiedSpecifier
{
std::string name;
Expand Down
17 changes: 7 additions & 10 deletions toolsrc/include/vcpkg/sourceparagraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <vcpkg/base/fwd/json.h>

#include <vcpkg/fwd/vcpkgcmdarguments.h>

#include <vcpkg/base/expected.h>
#include <vcpkg/base/span.h>
#include <vcpkg/base/system.h>
Expand Down Expand Up @@ -63,6 +65,7 @@ namespace vcpkg
std::string homepage;
std::string documentation;
std::vector<Dependency> dependencies;
std::vector<DependencyOverride> overrides;
std::vector<std::string> default_features;
std::string license; // SPDX license expression

Expand All @@ -80,16 +83,7 @@ namespace vcpkg
/// </summary>
struct SourceControlFile
{
SourceControlFile clone() const
{
SourceControlFile ret;
ret.core_paragraph = std::make_unique<SourceParagraph>(*core_paragraph);
for (const auto& feat_ptr : feature_paragraphs)
{
ret.feature_paragraphs.push_back(std::make_unique<FeatureParagraph>(*feat_ptr));
}
return ret;
}
SourceControlFile clone() const;

static Parse::ParseExpected<SourceControlFile> parse_manifest_object(const std::string& origin,
const Json::Object& object);
Expand All @@ -107,6 +101,9 @@ namespace vcpkg
Optional<const FeatureParagraph&> find_feature(const std::string& featurename) const;
Optional<const std::vector<Dependency>&> find_dependencies_for_feature(const std::string& featurename) const;

Optional<std::string> check_against_feature_flags(const fs::path& origin,
const FeatureFlagSettings& flags) const;

friend bool operator==(const SourceControlFile& lhs, const SourceControlFile& rhs);
friend bool operator!=(const SourceControlFile& lhs, const SourceControlFile& rhs) { return !(lhs == rhs); }
};
Expand Down
10 changes: 10 additions & 0 deletions toolsrc/include/vcpkg/versions.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,14 @@ namespace vcpkg::Versions
Date,
String
};

struct Constraint
{
enum class Type
{
None,
Minimum,
Exact
};
};
}
202 changes: 202 additions & 0 deletions toolsrc/src/vcpkg-test/manifests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ static Parse::ParseExpected<SourceControlFile> test_parse_manifest(StringView sv
return res;
}

static const FeatureFlagSettings feature_flags_with_versioning{false, false, false, true};
static const FeatureFlagSettings feature_flags_without_versioning{false, false, false, false};

TEST_CASE ("manifest construct minimum", "[manifests]")
{
auto m_pgh = test_parse_manifest(R"json({
Expand All @@ -59,6 +62,8 @@ TEST_CASE ("manifest construct minimum", "[manifests]")
REQUIRE(pgh.core_paragraph->maintainers.empty());
REQUIRE(pgh.core_paragraph->description.empty());
REQUIRE(pgh.core_paragraph->dependencies.empty());

REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning));
}

TEST_CASE ("manifest versioning", "[manifests]")
Expand Down Expand Up @@ -112,6 +117,201 @@ TEST_CASE ("manifest versioning", "[manifests]")
true);
}

TEST_CASE ("manifest constraints", "[manifests]")
{
std::string raw = R"json({
"name": "zlib",
"version-string": "abcd",
"dependencies": [
"a",
{
"name": "b",
"port-version": 12,
"version=": "5"
},
{
"$extra": null,
"name": "c"
},
{
"name": "d",
"version>=": "2018-09-01"
}
]
}
)json";
auto m_pgh = test_parse_manifest(raw);

REQUIRE(m_pgh.has_value());
auto& pgh = **m_pgh.get();
REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw);
REQUIRE(pgh.core_paragraph->dependencies.size() == 4);
REQUIRE(pgh.core_paragraph->dependencies[0].name == "a");
REQUIRE(pgh.core_paragraph->dependencies[0].constraint ==
DependencyConstraint{Versions::Constraint::Type::None, "", 0});
REQUIRE(pgh.core_paragraph->dependencies[1].name == "b");
REQUIRE(pgh.core_paragraph->dependencies[1].constraint ==
DependencyConstraint{Versions::Constraint::Type::Exact, "5", 12});
REQUIRE(pgh.core_paragraph->dependencies[2].name == "c");
REQUIRE(pgh.core_paragraph->dependencies[2].constraint ==
DependencyConstraint{Versions::Constraint::Type::None, "", 0});
REQUIRE(pgh.core_paragraph->dependencies[3].name == "d");
REQUIRE(pgh.core_paragraph->dependencies[3].constraint ==
DependencyConstraint{Versions::Constraint::Type::Minimum, "2018-09-01", 0});

test_parse_manifest(R"json({
"name": "zlib",
"version-string": "abcd",
"dependencies": [
{
"name": "d",
"version=": "2018-09-01",
"version>=": "2018-09-01"
}
]
})json",
true);

test_parse_manifest(R"json({
"name": "zlib",
"version-string": "abcd",
"dependencies": [
{
"name": "d",
"port-version": 5
}
]
})json",
true);
}

TEST_CASE ("manifest overrides", "[manifests]")
{
std::tuple<StringLiteral, Versions::Scheme, StringLiteral> data[] = {
{R"json({
"name": "zlib",
"version-date": "2020-01-01",
"overrides": [
{
"name": "abc",
"version-string": "abcd"
}
]
}
)json",
Versions::Scheme::String,
"abcd"},
{R"json({
"name": "zlib",
"version": "1.2.3.4.5",
"overrides": [
{
"name": "abc",
"version-date": "2020-01-01"
}
]
}
)json",
Versions::Scheme::Date,
"2020-01-01"},
{R"json({
"name": "zlib",
"version-date": "2020-01-01",
"overrides": [
{
"name": "abc",
"version": "1.2.3.4.5"
}
]
}
)json",
Versions::Scheme::Relaxed,
"1.2.3.4.5"},
{R"json({
"name": "zlib",
"version-date": "2020-01-01",
"overrides": [
{
"name": "abc",
"version-semver": "1.2.3-rc3"
}
]
}
)json",
Versions::Scheme::Semver,
"1.2.3-rc3"},
};
for (auto v : data)
{
auto m_pgh = test_parse_manifest(std::get<0>(v));

REQUIRE(m_pgh.has_value());
auto& pgh = **m_pgh.get();
REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == std::get<0>(v));
REQUIRE(pgh.core_paragraph->overrides.size() == 1);
REQUIRE(pgh.core_paragraph->overrides[0].version_scheme == std::get<1>(v));
REQUIRE(pgh.core_paragraph->overrides[0].version == std::get<2>(v));
REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
}

test_parse_manifest(R"json({
"name": "zlib",
"version-string": "abcd",
"overrides": [
{
"name": "abc",
"version-semver": "1.2.3-rc3",
"version-string": "1.2.3-rc3"
}
]})json",
true);

test_parse_manifest(R"json({
"name": "zlib",
"version-string": "abcd",
"overrides": [
{
"name": "abc",
"port-version": 5
}
]})json",
true);

std::string raw = R"json({
"name": "zlib",
"version-string": "abcd",
"overrides": [
{
"name": "abc",
"port-version": 5,
"version-string": "hello"
},
{
"name": "abcd",
"port-version": 7,
"version-string": "hello"
}
]
}
)json";
auto m_pgh = test_parse_manifest(raw);

REQUIRE(m_pgh.has_value());
auto& pgh = **m_pgh.get();
REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) == raw);
REQUIRE(pgh.core_paragraph->overrides.size() == 2);
REQUIRE(pgh.core_paragraph->overrides[0].name == "abc");
REQUIRE(pgh.core_paragraph->overrides[0].port_version == 5);
REQUIRE(pgh.core_paragraph->overrides[1].name == "abcd");
REQUIRE(pgh.core_paragraph->overrides[1].port_version == 7);

REQUIRE(pgh.check_against_feature_flags({}, feature_flags_without_versioning));
REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_with_versioning));
}

TEST_CASE ("manifest construct maximum", "[manifests]")
{
auto m_pgh = test_parse_manifest(R"json({
Expand Down Expand Up @@ -181,6 +381,8 @@ TEST_CASE ("manifest construct maximum", "[manifests]")
REQUIRE(pgh.feature_paragraphs[1]->description.size() == 2);
REQUIRE(pgh.feature_paragraphs[1]->description[0] == "son of the fire lord");
REQUIRE(pgh.feature_paragraphs[1]->description[1] == "firebending 師父");

REQUIRE(!pgh.check_against_feature_flags({}, feature_flags_without_versioning));
}

TEST_CASE ("SourceParagraph manifest two dependencies", "[manifests]")
Expand Down
8 changes: 7 additions & 1 deletion toolsrc/src/vcpkg/install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ namespace vcpkg::Install
Metrics::g_metrics.lock()->track_property("x-write-nuget-packages-config", "defined");
pkgsconfig = fs::u8path(it_pkgsconfig->second);
}
auto manifest_path = paths.get_manifest_path().value_or_exit(VCPKG_LINE_INFO);
const auto& manifest_path = paths.get_manifest_path().value_or_exit(VCPKG_LINE_INFO);
auto maybe_manifest_scf = SourceControlFile::parse_manifest_file(manifest_path, *manifest);
if (!maybe_manifest_scf)
{
Expand All @@ -798,8 +798,14 @@ namespace vcpkg::Install
"more information.\n");
Checks::exit_fail(VCPKG_LINE_INFO);
}

auto& manifest_scf = *maybe_manifest_scf.value_or_exit(VCPKG_LINE_INFO);

if (auto maybe_error = manifest_scf.check_against_feature_flags(manifest_path, paths.get_feature_flags()))
{
Checks::exit_with_message(VCPKG_LINE_INFO, maybe_error.value_or_exit(VCPKG_LINE_INFO));
}

std::vector<std::string> features;
auto manifest_feature_it = options.multisettings.find(OPTION_MANIFEST_FEATURE);
if (manifest_feature_it != options.multisettings.end())
Expand Down
18 changes: 18 additions & 0 deletions toolsrc/src/vcpkg/packagespec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,14 @@ namespace vcpkg
return ret;
}

bool operator==(const DependencyConstraint& lhs, const DependencyConstraint& rhs)
{
if (lhs.type != rhs.type) return false;
if (lhs.value != rhs.value) return false;
return lhs.port_version == rhs.port_version;
}
bool operator!=(const DependencyConstraint& lhs, const DependencyConstraint& rhs);

bool operator==(const Dependency& lhs, const Dependency& rhs)
{
if (lhs.name != rhs.name) return false;
Expand All @@ -269,4 +277,14 @@ namespace vcpkg
return true;
}
bool operator!=(const Dependency& lhs, const Dependency& rhs);

bool operator==(const DependencyOverride& lhs, const DependencyOverride& rhs)
{
if (lhs.version_scheme != rhs.version_scheme) return false;
if (lhs.port_version != rhs.port_version) return false;
if (lhs.name != rhs.name) return false;
if (lhs.version != rhs.version) return false;
return lhs.extra_info == rhs.extra_info;
}
bool operator!=(const DependencyOverride& lhs, const DependencyOverride& rhs);
}
Loading