Skip to content

Commit

Permalink
Don't require a name or version in "project" manifests. (#605)
Browse files Browse the repository at this point in the history
* Don't require a name or version in "project" manifests.

In resolving https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1494960 "[vcpkg ce] vcpkg-ce does not find vcpkg.json to find vcpkg-configuration.json" I ran into a problem for existing vcpkg artifacts-only customers, where today they can name artifact dependencies without needing to supply a name or version. I want to be able to provide a reasonable "how to fix it" message for these customers and it seems reasonable to be able to declare dependencies without having a name or version. After some discussion with @ras0219-msft and @vicroms , the requirement for a name and version seems to be a historical artifact of using the same code to parse both port manifests and consumer/project manifests.

include/vcpkg/sourceparagraph.h:
Rename parse_manifest_object to parse_port_manifest_object and add parse_project_manifest_object.

include/vcpkg/versiondeserializers.h:
Declare visit_optional_schemed_deserializer (with static removed in the versiondeserializers.cpp)

include/vcpkg/versions.h:
Add VersionScheme::Missing for the case that it isn't provided.

cmakevars.cpp:
Use "_manifest_" as the "port" name when a name wasn't supplied for purposes of vcpkg_get_dep_info.

add.ps1:
Add a new test of add port that uses an input manifest with no name or version information.

manifests.ps1:
Remove name and version from the prototype manifest. Note that some of the tests still use a manifest with a name; in particular the "self reference" ones so we still have coverage of that.

format-manifest.ps1:
Add project manifest examples in addition to the previous "reserialize all ports" test.

* Put the json entity type assert in the right place.

* Use JSON stuff rather than string stuff in the parsing tests.

* Invert template method pattern in manifest deserializer.

* Formatting

* Add overlay ports test.

* Add output asserts.
  • Loading branch information
BillyONeal committed Jun 30, 2022
1 parent 1e942c6 commit b4d664f
Show file tree
Hide file tree
Showing 46 changed files with 631 additions and 344 deletions.
1 change: 1 addition & 0 deletions azure-pipelines/e2e_assets/format-manifest/empty.json
@@ -0,0 +1 @@
{}
@@ -0,0 +1 @@
{}
@@ -0,0 +1,4 @@
{
"name": "name-and-version",
"version": "1.0"
}
3 changes: 3 additions & 0 deletions azure-pipelines/e2e_assets/format-manifest/expected/name.json
@@ -0,0 +1,3 @@
{
"name": "hello"
}
@@ -0,0 +1,3 @@
{
"version": "1.2"
}
@@ -0,0 +1 @@
{"name":"name-and-version", "version": "1.0"}
1 change: 1 addition & 0 deletions azure-pipelines/e2e_assets/format-manifest/name.json
@@ -0,0 +1 @@
{"name":"hello"}
1 change: 1 addition & 0 deletions azure-pipelines/e2e_assets/format-manifest/version.json
@@ -0,0 +1 @@
{"version":"1.2"}
@@ -0,0 +1 @@
set(VCPKG_POLICY_EMPTY_PACKAGE enabled)
3 changes: 3 additions & 0 deletions azure-pipelines/e2e_ports/overlays/broken-no-name/vcpkg.json
@@ -0,0 +1,3 @@
{
"version": "1.0"
}
@@ -0,0 +1 @@
set(VCPKG_POLICY_EMPTY_PACKAGE enabled)
@@ -0,0 +1,3 @@
{
"name": "hello"
}
26 changes: 26 additions & 0 deletions azure-pipelines/end-to-end-tests-dir/add.ps1
@@ -0,0 +1,26 @@
. "$PSScriptRoot/../end-to-end-tests-prelude.ps1"

$manifestDir = "$TestingRoot/add_port"
$manifestDirArgs = $commonArgs + @("--x-manifest-root=$manifestDir")
$manifestPath = "$manifestDir/vcpkg.json"
$vcpkgJson = @{}

New-Item -Path $manifestDir -ItemType Directory
New-Item -Path $manifestPath -ItemType File `
-Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgJson)

Run-Vcpkg add port zlib @manifestDirArgs
Throw-IfFailed

$expected = @"
{
"dependencies": [
"zlib"
]
}
"@

$actual = (Get-Content -Path $manifestPath -Raw).TrimEnd()
if ($expected -ne $actual) {
throw "Add port didn't add zlib dependency correctly.`nExpected: $expected`nActual:$actual"
}
16 changes: 13 additions & 3 deletions azure-pipelines/end-to-end-tests-dir/build-test-ports.ps1
Expand Up @@ -8,12 +8,10 @@ Throw-IfFailed
$output = Run-Vcpkg @commonArgs --overlay-ports="$PSScriptRoot/../e2e_ports/vcpkg-internal-e2e-test-port2" install vcpkg-internal-e2e-test-port2
$output
Throw-IfFailed
if ($output -match "vcpkg-internal-e2e-test-port3") {
if ($output -match 'vcpkg-internal-e2e-test-port3') {
throw "Should not emit messages about -port3 while checking -port2"
}

return

Run-Vcpkg @commonArgs --overlay-ports="$PSScriptRoot/../e2e_ports/overlays" install vcpkg-empty-port
Throw-IfFailed
Run-Vcpkg @commonArgs --overlay-ports="$PSScriptRoot/../e2e_ports" install vcpkg-internal-e2e-test-port
Expand All @@ -22,3 +20,15 @@ if ($IsWindows) {
Run-Vcpkg @commonArgs --overlay-ports="$PSScriptRoot/../e2e_ports" install vcpkg-find-acquire-program
Throw-IfFailed
}

$output = Run-Vcpkg @commonArgs --overlay-ports="$PSScriptRoot/../e2e_ports/overlays" install broken-no-name
Throw-IfNotFailed
if (-not $output -match 'missing field') {
throw 'Did not detect missing field'
}

$output = Run-Vcpkg @commonArgs --overlay-ports="$PSScriptRoot/../e2e_ports/overlays" install broken-no-version
Throw-IfNotFailed
if (-not $output -match 'missing field') {
throw 'Did not detect missing field'
}
36 changes: 36 additions & 0 deletions azure-pipelines/end-to-end-tests-dir/format-manifest.ps1
@@ -0,0 +1,36 @@
. "$PSScriptRoot/../end-to-end-tests-prelude.ps1"

$formatManifestAssets = (Get-Item "$PSScriptRoot/../e2e_assets/format-manifest").FullName
$testProjects = Get-ChildItem "$formatManifestAssets/*.json" -File
$testProjects | % {
$asItem = Get-Item $_
$full = $asItem.FullName
$name = $asItem.Name
$expectedPath = "$formatManifestAssets/expected/$name"
$tempItemPath = "$TestingRoot/$name"
Write-Trace "test that format-manifest on $full produces $expectedPath"
[string]$expected = Get-Content $expectedPath -Raw
Copy-Item $asItem $tempItemPath
Run-Vcpkg format-manifest $tempItemPath
$actual = Get-Content $tempItemPath -Raw
if ($expected -ne $actual) {
throw "Expected formatting $full to produce $expectedPath but was $tempItemPath"
}
}

Write-Trace "test re-serializing every manifest"
$manifestDir = "$TestingRoot/manifest-dir"
New-Item -Path $manifestDir -ItemType Directory | Out-Null

$ports = Get-ChildItem "$env:VCPKG_ROOT/ports"

$ports | % {
Copy-Item "$_/vcpkg.json" "$manifestDir" | Out-Null
$x = Get-Content "$manifestDir/vcpkg.json" -Raw
Run-Vcpkg -EndToEndTestSilent format-manifest "$manifestDir/vcpkg.json" | Out-Null
Throw-IfFailed "$_/vcpkg.json"
$y = Get-Content "$manifestDir/vcpkg.json" -Raw
if ($x -ne $y) {
throw "Expected formatting manifest $_/vcpkg.json to cause no modifications"
}
}
20 changes: 0 additions & 20 deletions azure-pipelines/end-to-end-tests-dir/manifest-reserialize.ps1

This file was deleted.

3 changes: 0 additions & 3 deletions azure-pipelines/end-to-end-tests-dir/manifests.ps1
@@ -1,6 +1,5 @@
. "$PSScriptRoot/../end-to-end-tests-prelude.ps1"


Write-Trace "test manifest features"
$manifestDir = "$TestingRoot/manifest-dir"

Expand All @@ -15,8 +14,6 @@ function feature {
}

$vcpkgJson = @{
'name' = "manifest-test";
'version' = "1.0.0";
'default-features' = @( 'default-fail' );
'features' = @{
'default-fail' = feature 'vcpkg-fail-if-depended-upon';
Expand Down
28 changes: 14 additions & 14 deletions include/vcpkg/base/json.h
Expand Up @@ -103,18 +103,18 @@ namespace vcpkg::Json
bool is_object() const noexcept;

// a.x() asserts when !a.is_x()
bool boolean() const noexcept;
int64_t integer() const noexcept;
double number() const noexcept;
StringView string() const noexcept;
bool boolean(LineInfo li) const noexcept;
int64_t integer(LineInfo li) const noexcept;
double number(LineInfo li) const noexcept;
StringView string(LineInfo li) const noexcept;

const Array& array() const& noexcept;
Array& array() & noexcept;
Array&& array() && noexcept;
const Array& array(LineInfo li) const& noexcept;
Array& array(LineInfo li) & noexcept;
Array&& array(LineInfo li) && noexcept;

const Object& object() const& noexcept;
Object& object() & noexcept;
Object&& object() && noexcept;
const Object& object(LineInfo li) const& noexcept;
Object& object(LineInfo li) & noexcept;
Object&& object(LineInfo li) && noexcept;

static Value null(std::nullptr_t) noexcept;
static Value boolean(bool) noexcept;
Expand Down Expand Up @@ -318,10 +318,10 @@ namespace vcpkg::Json

ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<ParseError>> parse_file(const Filesystem&,
const Path&,
std::error_code& ec) noexcept;
ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<ParseError>> parse(StringView text,
StringView origin = {}) noexcept;
std::pair<Value, JsonStyle> parse_file(vcpkg::LineInfo li, const Filesystem&, const Path&) noexcept;
std::error_code& ec);
ExpectedT<std::pair<Value, JsonStyle>, std::unique_ptr<ParseError>> parse(StringView text, StringView origin = {});
std::pair<Value, JsonStyle> parse_file(LineInfo li, const Filesystem&, const Path&);
ExpectedS<Json::Object> parse_object(StringView text, StringView origin = {});

std::string stringify(const Value&, JsonStyle style);
std::string stringify(const Object&, JsonStyle style);
Expand Down
13 changes: 7 additions & 6 deletions include/vcpkg/base/jsonreader.h
Expand Up @@ -217,12 +217,13 @@ namespace vcpkg::Json
switch (value.kind())
{
case ValueKind::Null: return visit_null(r);
case ValueKind::Boolean: return visit_boolean(r, value.boolean());
case ValueKind::Integer: return visit_integer(r, value.integer());
case ValueKind::Number: return visit_number(r, value.number());
case ValueKind::String: return visit_string(r, value.string());
case ValueKind::Array: return visit_array(r, value.array());
case ValueKind::Object: return visit(r, value.object()); // Call `visit` to get unexpected fields checking
case ValueKind::Boolean: return visit_boolean(r, value.boolean(VCPKG_LINE_INFO));
case ValueKind::Integer: return visit_integer(r, value.integer(VCPKG_LINE_INFO));
case ValueKind::Number: return visit_number(r, value.number(VCPKG_LINE_INFO));
case ValueKind::String: return visit_string(r, value.string(VCPKG_LINE_INFO));
case ValueKind::Array: return visit_array(r, value.array(VCPKG_LINE_INFO));
case ValueKind::Object:
return visit(r, value.object(VCPKG_LINE_INFO)); // Call `visit` to get unexpected fields checking
default: vcpkg::Checks::unreachable(VCPKG_LINE_INFO);
}
}
Expand Down
9 changes: 6 additions & 3 deletions include/vcpkg/sourceparagraph.h
Expand Up @@ -100,10 +100,13 @@ namespace vcpkg
struct SourceControlFile
{
SourceControlFile clone() const;
static ParseExpected<SourceControlFile> parse_project_manifest_object(StringView origin,
const Json::Object& object,
MessageSink& warnings_sink);

static ParseExpected<SourceControlFile> parse_manifest_object(StringView origin,
const Json::Object& object,
MessageSink& warnings_sink);
static ParseExpected<SourceControlFile> parse_port_manifest_object(StringView origin,
const Json::Object& object,
MessageSink& warnings_sink);

static ParseExpected<SourceControlFile> parse_control_file(StringView origin,
std::vector<Paragraph>&& control_paragraphs);
Expand Down
5 changes: 5 additions & 0 deletions include/vcpkg/versiondeserializers.h
Expand Up @@ -17,6 +17,11 @@ namespace vcpkg
Version version;
};

Optional<SchemedVersion> visit_optional_schemed_deserializer(StringView parent_type,
Json::Reader& r,
const Json::Object& obj,
bool allow_hash_portversion);

SchemedVersion visit_required_schemed_deserializer(StringView parent_type,
Json::Reader& r,
const Json::Object& obj,
Expand Down
1 change: 1 addition & 0 deletions include/vcpkg/versions.h
Expand Up @@ -60,6 +60,7 @@ namespace vcpkg

enum class VersionScheme
{
Missing,
Relaxed,
Semver,
Date,
Expand Down
1 change: 1 addition & 0 deletions locales/messages.en.json
Expand Up @@ -148,6 +148,7 @@
"InvalidFormatString": "invalid format string: {actual}",
"JsonErrorFailedToParse": "failed to parse {path}:",
"JsonErrorFailedToRead": "failed to read {path}: {error_msg}",
"JsonErrorMustBeAnObject": "Expected {path} to be an object.",
"LaunchingProgramFailed": "Launching {tool_name}:",
"LicenseExpressionContainsExtraPlus": "SPDX license expression contains an extra '+'. These are only allowed directly after a license identifier.",
"LicenseExpressionContainsInvalidCharacter": "SPDX license expression contains an invalid character (0x{value:02X} '{value}').",
Expand Down
2 changes: 2 additions & 0 deletions locales/messages.json
Expand Up @@ -261,6 +261,8 @@
"_JsonErrorFailedToParse.comment": "An example of {path} is /foo/bar.",
"JsonErrorFailedToRead": "failed to read {path}: {error_msg}",
"_JsonErrorFailedToRead.comment": "An example of {path} is /foo/bar. An example of {error_msg} is File Not Found.",
"JsonErrorMustBeAnObject": "Expected {path} to be an object.",
"_JsonErrorMustBeAnObject.comment": "An example of {path} is /foo/bar.",
"LaunchingProgramFailed": "Launching {tool_name}:",
"_LaunchingProgramFailed.comment": "A platform API call failure message is appended after this An example of {tool_name} is aria2.",
"LicenseExpressionContainsExtraPlus": "SPDX license expression contains an extra '+'. These are only allowed directly after a license identifier.",
Expand Down

0 comments on commit b4d664f

Please sign in to comment.