Refactor apart 'config data' from 'behavior object' for registries (#275)
* Refactor apart 'config data' from 'behavior object' for registries * Fix relative path in filesystem registry config * Address review comments * Review comments
This commit is contained in:
Родитель
48b94a6946
Коммит
e7cb06347c
|
@ -229,6 +229,52 @@ finally
|
|||
Pop-Location
|
||||
}
|
||||
|
||||
# test the filesystem registry with a relative path
|
||||
Write-Trace "test the filesystem registry with a relative path"
|
||||
$manifestDir = "$TestingRoot/filesystem-registry-test-manifest-dir"
|
||||
Remove-Item -Recurse -Force $manifestDir -ErrorAction SilentlyContinue
|
||||
|
||||
New-Item -Path $manifestDir -ItemType Directory
|
||||
$manifestDir = (Get-Item $manifestDir).FullName
|
||||
|
||||
Push-Location $manifestDir
|
||||
try
|
||||
{
|
||||
$vcpkgJson = @{
|
||||
"name" = "manifest-test";
|
||||
"version-string" = "1.0.0";
|
||||
"dependencies" = @(
|
||||
"vcpkg-internal-e2e-test-port"
|
||||
);
|
||||
# Use versioning features without a builtin-baseline
|
||||
"overrides" = @(@{
|
||||
"name" = "unused";
|
||||
"version" = "0";
|
||||
})
|
||||
}
|
||||
$vcpkgConfigurationJson = @{
|
||||
"default-registry" = $null;
|
||||
"registries" = @(
|
||||
@{
|
||||
"kind" = "filesystem";
|
||||
"path" = "../filesystem-registry";
|
||||
"packages" = @( "vcpkg-internal-e2e-test-port" )
|
||||
}
|
||||
)
|
||||
}
|
||||
New-Item -Path 'vcpkg.json' -ItemType File `
|
||||
-Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgJson)
|
||||
New-Item -Path 'vcpkg-configuration.json' -ItemType File `
|
||||
-Value (ConvertTo-Json -Depth 5 -InputObject $vcpkgConfigurationJson)
|
||||
|
||||
Run-Vcpkg install @builtinRegistryArgs '--feature-flags=registries,manifests'
|
||||
Throw-IfFailed
|
||||
}
|
||||
finally
|
||||
{
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
# test the git registry
|
||||
Write-Trace "test the git registry"
|
||||
$manifestDir = "$TestingRoot/git-registry-test-manifest-dir"
|
||||
|
|
|
@ -121,5 +121,9 @@ namespace vcpkg::Test
|
|||
}
|
||||
}
|
||||
|
||||
void check_json_eq(const Json::Value& l, const Json::Value& r);
|
||||
void check_json_eq(const Json::Object& l, const Json::Object& r);
|
||||
void check_json_eq(const Json::Array& l, const Json::Array& r);
|
||||
|
||||
const Path& base_temporary_directory() noexcept;
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ namespace vcpkg::Json
|
|||
virtual StringView type_name() const override { return type_name_; }
|
||||
virtual Optional<std::string> visit_string(Reader&, StringView sv) override { return sv.to_string(); }
|
||||
|
||||
explicit StringDeserializer(StringLiteral type_name_) : type_name_(type_name_) { }
|
||||
constexpr explicit StringDeserializer(StringLiteral type_name_) : type_name_(type_name_) { }
|
||||
|
||||
private:
|
||||
StringLiteral type_name_;
|
||||
|
@ -327,7 +327,7 @@ namespace vcpkg::Json
|
|||
|
||||
virtual StringView type_name() const override { return m_type_name; }
|
||||
|
||||
ArrayDeserializer(StringLiteral type_name_, Underlying&& t = {})
|
||||
constexpr ArrayDeserializer(StringLiteral type_name_, Underlying&& t = {})
|
||||
: m_type_name(type_name_), m_underlying_visitor(static_cast<Underlying&&>(t))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -253,6 +253,12 @@ namespace vcpkg
|
|||
|
||||
constexpr explicit operator bool() const { return this->m_base.has_value(); }
|
||||
|
||||
T& emplace()
|
||||
{
|
||||
this->m_base = T{};
|
||||
return this->m_base.value();
|
||||
}
|
||||
|
||||
constexpr bool has_value() const { return this->m_base.has_value(); }
|
||||
|
||||
template<class U>
|
||||
|
|
|
@ -10,21 +10,43 @@
|
|||
|
||||
namespace vcpkg
|
||||
{
|
||||
struct RegistryConfig
|
||||
{
|
||||
// Missing kind means "null"
|
||||
Optional<std::string> kind;
|
||||
Optional<std::string> baseline;
|
||||
Optional<std::string> location;
|
||||
Optional<std::string> name;
|
||||
Optional<Path> path;
|
||||
Optional<std::string> reference;
|
||||
Optional<std::string> repo;
|
||||
Optional<std::vector<std::string>> packages;
|
||||
|
||||
Json::Value serialize() const;
|
||||
};
|
||||
|
||||
struct Configuration
|
||||
{
|
||||
// This member is set up via two different configuration options,
|
||||
// `registries` and `default_registry`. The fall back logic is
|
||||
// taken care of in RegistrySet.
|
||||
RegistrySet registry_set;
|
||||
Optional<RegistryConfig> default_reg;
|
||||
std::vector<RegistryConfig> registries;
|
||||
Json::Object ce_metadata;
|
||||
Json::Object extra_info;
|
||||
|
||||
void validate_feature_flags(const FeatureFlagSettings& flags);
|
||||
Json::Object serialize() const;
|
||||
void validate_as_active();
|
||||
|
||||
std::unique_ptr<RegistrySet> instantiate_registry_set(const Path& config_dir) const;
|
||||
|
||||
static View<StringView> known_fields();
|
||||
};
|
||||
|
||||
std::unique_ptr<Json::IDeserializer<Configuration>> make_configuration_deserializer(const Path& config_directory);
|
||||
Json::Object serialize_configuration(const Configuration& config);
|
||||
struct ManifestConfiguration
|
||||
{
|
||||
Optional<std::string> builtin_baseline;
|
||||
Optional<Configuration> config;
|
||||
};
|
||||
|
||||
Json::IDeserializer<Configuration>& get_configuration_deserializer();
|
||||
Json::IDeserializer<ManifestConfiguration>& get_manifest_configuration_deserializer();
|
||||
std::vector<std::string> find_unknown_fields(const Configuration& config);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include <vcpkg/base/stringliteral.h>
|
||||
|
||||
namespace vcpkg
|
||||
{
|
||||
namespace docs
|
||||
{
|
||||
static constexpr StringLiteral registries_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/registries.md";
|
||||
static constexpr StringLiteral manifests_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/manifest.md";
|
||||
static constexpr StringLiteral assetcaching_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/assetcaching.md";
|
||||
static constexpr StringLiteral binarycaching_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/binarycaching.md";
|
||||
static constexpr StringLiteral versioning_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/versioning.md";
|
||||
static constexpr StringLiteral vcpkg_visual_studio_path_url =
|
||||
"https://github.com/microsoft/vcpkg/blob/master/docs/users/triplets.md#VCPKG_VISUAL_STUDIO_PATH";
|
||||
}
|
||||
}
|
|
@ -3,4 +3,5 @@
|
|||
namespace vcpkg
|
||||
{
|
||||
struct Configuration;
|
||||
struct RegistryConfig;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,6 @@ namespace vcpkg
|
|||
|
||||
virtual Optional<Path> get_path_to_baseline_version(const VcpkgPaths& paths, StringView port_name) const;
|
||||
|
||||
virtual Json::Object serialize() const;
|
||||
|
||||
virtual ~RegistryImplementation() = default;
|
||||
};
|
||||
|
||||
|
@ -104,7 +102,10 @@ namespace vcpkg
|
|||
// configuration fields.
|
||||
struct RegistrySet
|
||||
{
|
||||
RegistrySet();
|
||||
RegistrySet(std::unique_ptr<RegistryImplementation>&& x, std::vector<Registry>&& y)
|
||||
: default_registry_(std::move(x)), registries_(std::move(y))
|
||||
{
|
||||
}
|
||||
|
||||
// finds the correct registry for the port name
|
||||
// Returns the null pointer if there is no registry set up for that name
|
||||
|
@ -115,12 +116,7 @@ namespace vcpkg
|
|||
|
||||
const RegistryImplementation* default_registry() const { return default_registry_.get(); }
|
||||
|
||||
// TODO: figure out how to get this to return an error (or maybe it should be a warning?)
|
||||
void add_registry(Registry&& r);
|
||||
void set_default_registry(std::unique_ptr<RegistryImplementation>&& r);
|
||||
void set_default_registry(std::nullptr_t r);
|
||||
bool is_default_builtin_registry() const;
|
||||
void set_default_builtin_registry_baseline(StringView baseline);
|
||||
|
||||
// returns whether the registry set has any modifications to the default
|
||||
// (i.e., whether `default_registry` was set, or `registries` had any entries)
|
||||
|
@ -132,13 +128,13 @@ namespace vcpkg
|
|||
std::vector<Registry> registries_;
|
||||
};
|
||||
|
||||
Json::Object serialize_registry_set(const RegistrySet& config);
|
||||
|
||||
std::unique_ptr<Json::IDeserializer<std::unique_ptr<RegistryImplementation>>>
|
||||
get_registry_implementation_deserializer(const Path& configuration_directory);
|
||||
|
||||
std::unique_ptr<Json::IDeserializer<std::vector<Registry>>> get_registry_array_deserializer(
|
||||
const Path& configuration_directory);
|
||||
std::unique_ptr<RegistryImplementation> make_builtin_registry();
|
||||
std::unique_ptr<RegistryImplementation> make_builtin_registry(std::string baseline);
|
||||
std::unique_ptr<RegistryImplementation> make_git_registry(std::string repo,
|
||||
std::string reference,
|
||||
std::string baseline);
|
||||
std::unique_ptr<RegistryImplementation> make_filesystem_registry(Path path, std::string baseline);
|
||||
std::unique_ptr<RegistryImplementation> make_artifact_registry(std::string name, std::string location);
|
||||
|
||||
ExpectedS<std::vector<std::pair<SchemedVersion, std::string>>> get_builtin_versions(const VcpkgPaths& paths,
|
||||
StringView port_name);
|
||||
|
|
|
@ -128,6 +128,9 @@ namespace vcpkg
|
|||
Json::Object serialize_manifest(const SourceControlFile& scf);
|
||||
Json::Object serialize_debug_manifest(const SourceControlFile& scf);
|
||||
|
||||
ExpectedS<struct ManifestConfiguration> parse_manifest_configuration(StringView origin,
|
||||
const Json::Object& manifest);
|
||||
|
||||
/// <summary>
|
||||
/// Named pair of a SourceControlFile and the location of this file
|
||||
/// </summary>
|
||||
|
|
|
@ -109,7 +109,6 @@ namespace vcpkg
|
|||
Path original_cwd;
|
||||
Path root;
|
||||
Path manifest_root_dir;
|
||||
Path config_root_dir;
|
||||
Path downloads;
|
||||
Path triplets;
|
||||
Path community_triplets;
|
||||
|
@ -159,8 +158,7 @@ namespace vcpkg
|
|||
|
||||
Optional<const Json::Object&> get_manifest() const;
|
||||
Optional<const Path&> get_manifest_path() const;
|
||||
const Configuration& get_configuration() const;
|
||||
void set_builtin_baseline(const std::string& baseline) const;
|
||||
const RegistrySet& get_registry_set() const;
|
||||
|
||||
// Retrieve a toolset matching the requirements in prebuildinfo
|
||||
const Toolset& get_toolset(const Build::PreBuildInfo& prebuildinfo) const;
|
||||
|
|
|
@ -56,8 +56,7 @@ static Configuration parse_test_configuration(StringView text)
|
|||
auto object = parse_json_object(text);
|
||||
|
||||
Json::Reader reader;
|
||||
auto deserializer = make_configuration_deserializer("");
|
||||
auto parsed_config_opt = reader.visit(object, *deserializer);
|
||||
auto parsed_config_opt = reader.visit(object, get_configuration_deserializer());
|
||||
REQUIRE(reader.errors().empty());
|
||||
|
||||
return std::move(parsed_config_opt).value_or_exit(VCPKG_LINE_INFO);
|
||||
|
@ -71,19 +70,12 @@ static void check_string(const Json::Object& obj, StringView key, StringView exp
|
|||
REQUIRE(value->string() == expected);
|
||||
}
|
||||
|
||||
static void compare_json_objects(const Json::Object& expected, const Json::Object& actual)
|
||||
{
|
||||
REQUIRE(Json::stringify(expected, Json::JsonStyle::with_spaces(4)) ==
|
||||
Json::stringify(actual, Json::JsonStyle::with_spaces(4)));
|
||||
}
|
||||
|
||||
static void check_errors(const std::string& config_text, const std::string& expected_errors)
|
||||
{
|
||||
auto object = parse_json_object(config_text);
|
||||
|
||||
Json::Reader reader;
|
||||
auto deserializer = make_configuration_deserializer("");
|
||||
auto parsed_config_opt = reader.visit(object, *deserializer);
|
||||
auto parsed_config_opt = reader.visit(object, get_configuration_deserializer());
|
||||
REQUIRE(!reader.errors().empty());
|
||||
|
||||
CHECK_LINES(Strings::join("\n", reader.errors()), expected_errors);
|
||||
|
@ -114,6 +106,11 @@ TEST_CASE ("config registries only", "[ce-metadata]")
|
|||
"kind": "artifact",
|
||||
"name": "vcpkg-artifacts",
|
||||
"location": "https://github.com/microsoft/vcpkg-artifacts"
|
||||
},
|
||||
{
|
||||
"kind": "filesystem",
|
||||
"path": "path/to/registry",
|
||||
"packages": [ ]
|
||||
}
|
||||
]
|
||||
})json";
|
||||
|
@ -121,39 +118,46 @@ TEST_CASE ("config registries only", "[ce-metadata]")
|
|||
auto config = parse_test_configuration(raw_config);
|
||||
REQUIRE(config.ce_metadata.is_empty());
|
||||
REQUIRE(config.extra_info.is_empty());
|
||||
REQUIRE(config.registry_set.default_registry() != nullptr);
|
||||
|
||||
auto default_registry = config.registry_set.default_registry()->serialize();
|
||||
REQUIRE(config.default_reg.has_value());
|
||||
|
||||
auto default_registry = config.default_reg.get()->serialize().object();
|
||||
check_string(default_registry, KIND, "builtin");
|
||||
check_string(default_registry, BASELINE, "843e0ba0d8f9c9c572e45564263eedfc7745e74f");
|
||||
|
||||
REQUIRE(config.registry_set.registries().size() == 3);
|
||||
REQUIRE(config.registries.size() == 4);
|
||||
|
||||
const auto& git_registry = config.registry_set.registries()[0];
|
||||
auto serialized_git_registry = git_registry.implementation().serialize();
|
||||
const auto& git_registry = config.registries[0];
|
||||
auto serialized_git_registry = git_registry.serialize().object();
|
||||
check_string(serialized_git_registry, KIND, "git");
|
||||
check_string(serialized_git_registry, REPOSITORY, "https://github.com/northwindtraders/vcpkg-registry");
|
||||
check_string(serialized_git_registry, BASELINE, "dacf4de488094a384ca2c202b923ccc097956e0c");
|
||||
REQUIRE(git_registry.packages().size() == 2);
|
||||
REQUIRE(git_registry.packages()[0] == "beicode");
|
||||
REQUIRE(git_registry.packages()[1] == "beison");
|
||||
REQUIRE(git_registry.packages);
|
||||
auto&& p = *git_registry.packages.get();
|
||||
REQUIRE(p.size() == 2);
|
||||
REQUIRE(p[0] == "beicode");
|
||||
REQUIRE(p[1] == "beison");
|
||||
|
||||
const auto& fs_registry = config.registry_set.registries()[1];
|
||||
auto serialized_fs_registry = fs_registry.implementation().serialize();
|
||||
const auto& fs_registry = config.registries[1];
|
||||
auto serialized_fs_registry = fs_registry.serialize().object();
|
||||
check_string(serialized_fs_registry, KIND, "filesystem");
|
||||
check_string(serialized_fs_registry, PATH, "path/to/registry");
|
||||
REQUIRE(fs_registry.packages().size() == 1);
|
||||
REQUIRE(fs_registry.packages()[0] == "zlib");
|
||||
REQUIRE(fs_registry.packages);
|
||||
REQUIRE(fs_registry.packages.get()->size() == 1);
|
||||
REQUIRE((*fs_registry.packages.get())[0] == "zlib");
|
||||
|
||||
const auto& artifact_registry = config.registry_set.registries()[2];
|
||||
auto serialized_art_registry = artifact_registry.implementation().serialize();
|
||||
const auto& artifact_registry = config.registries[2];
|
||||
auto serialized_art_registry = artifact_registry.serialize().object();
|
||||
check_string(serialized_art_registry, KIND, "artifact");
|
||||
check_string(serialized_art_registry, NAME, "vcpkg-artifacts");
|
||||
check_string(serialized_art_registry, LOCATION, "https://github.com/microsoft/vcpkg-artifacts");
|
||||
REQUIRE(!artifact_registry.packages);
|
||||
|
||||
REQUIRE(config.registries[3].packages);
|
||||
|
||||
auto raw_obj = parse_json_object(raw_config);
|
||||
auto serialized_obj = serialize_configuration(config);
|
||||
compare_json_objects(raw_obj, serialized_obj);
|
||||
auto serialized_obj = config.serialize();
|
||||
Test::check_json_eq(raw_obj, serialized_obj);
|
||||
}
|
||||
|
||||
SECTION ("default invalid json")
|
||||
|
@ -165,7 +169,6 @@ TEST_CASE ("config registries only", "[ce-metadata]")
|
|||
})json";
|
||||
check_errors(raw_no_baseline, R"(
|
||||
$.default-registry (a builtin registry): missing required field 'baseline' (a baseline)
|
||||
$.default-registry (a builtin registry): The baseline field of builtin registries must be a git commit SHA (40 lowercase hex characters)
|
||||
)");
|
||||
|
||||
std::string raw_with_packages = R"json({
|
||||
|
@ -187,7 +190,7 @@ $.default-registry (a registry): unexpected field 'packages', did you mean 'path
|
|||
}
|
||||
})json";
|
||||
check_errors(raw_default_artifact, R"(
|
||||
$ (a configuration object): default-registry cannot be of "artifact" kind
|
||||
$ (a configuration object): default-registry cannot be of kind "artifact"
|
||||
)");
|
||||
std::string raw_bad_kind = R"json({
|
||||
"registries": [{
|
||||
|
@ -223,9 +226,9 @@ $.registries[0] (a registry): missing required field 'packages' (an array of pac
|
|||
})json";
|
||||
check_errors(raw_bad_git_registry, R"(
|
||||
$.registries[0] (a registry): unexpected field 'no-repository', did you mean 'repository'?
|
||||
$.registries[0] (a git registry): unexpected field 'no-repository', did you mean 'repository'?
|
||||
$.registries[0] (a git registry): missing required field 'repository' (a git repository URL)
|
||||
$.registries[0].reference: mismatched type: expected a git reference (for example, a branch)
|
||||
$.registries[0] (a git registry): unexpected field 'no-repository', did you mean 'repository'?
|
||||
$.registries[0].packages: mismatched type: expected an array of package names
|
||||
)");
|
||||
|
||||
|
@ -239,11 +242,11 @@ $.registries[0].packages: mismatched type: expected an array of package names
|
|||
})json";
|
||||
check_errors(raw_bad_artifact_registry, R"(
|
||||
$.registries[0] (a registry): unexpected field 'no-location', did you mean 'location'?
|
||||
$.registries[0] (an artifacts registry): missing required field 'name' (an identifier)
|
||||
$.registries[0] (an artifacts registry): missing required field 'location' (an artifacts git repository URL)
|
||||
$.registries[0] (an artifacts registry): unexpected field 'no-location', did you mean 'location'?
|
||||
$.registries[0] (an artifacts registry): unexpected field 'baseline', did you mean 'kind'?
|
||||
$.registries[0] (an artifacts registry): unexpected field 'packages', did you mean 'name'?
|
||||
$.registries[0] (an artifact registry): missing required field 'name' (an identifier)
|
||||
$.registries[0] (an artifacts registry): missing required field 'location' (an artifacts git repository URL)
|
||||
)");
|
||||
}
|
||||
}
|
||||
|
@ -268,8 +271,8 @@ TEST_CASE ("config ce metadata only", "[ce-metadata]")
|
|||
})json";
|
||||
|
||||
auto config = parse_test_configuration(raw_config);
|
||||
REQUIRE(!config.registry_set.registries().size());
|
||||
REQUIRE(config.registry_set.is_default_builtin_registry());
|
||||
REQUIRE(!config.registries.size());
|
||||
REQUIRE(config.instantiate_registry_set({})->is_default_builtin_registry());
|
||||
|
||||
REQUIRE(!config.extra_info.is_empty());
|
||||
REQUIRE(config.extra_info.size() == 1);
|
||||
|
@ -299,8 +302,8 @@ TEST_CASE ("config ce metadata only", "[ce-metadata]")
|
|||
REQUIRE(nested.contains("unexpected"));
|
||||
|
||||
auto raw_obj = parse_json_object(raw_config);
|
||||
auto serialized_obj = serialize_configuration(config);
|
||||
compare_json_objects(raw_obj, serialized_obj);
|
||||
auto serialized_obj = config.serialize();
|
||||
Test::check_json_eq(raw_obj, serialized_obj);
|
||||
}
|
||||
|
||||
TEST_CASE ("metadata strings", "[ce-metadata]")
|
||||
|
@ -320,7 +323,7 @@ TEST_CASE ("metadata strings", "[ce-metadata]")
|
|||
check_string(valid_config.ce_metadata, CE_ERROR, "this is a valid error");
|
||||
|
||||
auto raw_obj = parse_json_object(valid_raw);
|
||||
compare_json_objects(raw_obj, serialize_configuration(valid_config));
|
||||
Test::check_json_eq(raw_obj, valid_config.serialize());
|
||||
}
|
||||
|
||||
SECTION ("invalid json")
|
||||
|
@ -383,7 +386,7 @@ TEST_CASE ("metadata dictionaries", "[ce-metadata]")
|
|||
check_string(settings, "SETTING_2", "value2");
|
||||
|
||||
auto raw_obj = parse_json_object(valid_raw);
|
||||
compare_json_objects(raw_obj, serialize_configuration(valid_config));
|
||||
Test::check_json_eq(raw_obj, valid_config.serialize());
|
||||
}
|
||||
|
||||
SECTION ("invalid json")
|
||||
|
@ -466,7 +469,7 @@ TEST_CASE ("metadata demands", "[ce-metadata]")
|
|||
check_string(level1, CE_MESSAGE, "this is level 1");
|
||||
|
||||
auto raw_obj = parse_json_object(simple_raw);
|
||||
compare_json_objects(raw_obj, serialize_configuration(config));
|
||||
Test::check_json_eq(raw_obj, config.serialize());
|
||||
}
|
||||
|
||||
SECTION ("invalid json")
|
||||
|
@ -517,7 +520,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]")
|
|||
})json";
|
||||
// parsing of configuration is tested elsewhere
|
||||
auto config = parse_test_configuration(raw);
|
||||
compare_json_objects(parse_json_object(raw), serialize_configuration(config));
|
||||
Test::check_json_eq(parse_json_object(raw), config.serialize());
|
||||
}
|
||||
|
||||
SECTION ("overriden default registry and registries")
|
||||
|
@ -538,7 +541,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]")
|
|||
})json";
|
||||
// parsing of configuration is tested elsewhere
|
||||
auto config = parse_test_configuration(raw);
|
||||
compare_json_objects(parse_json_object(raw), serialize_configuration(config));
|
||||
Test::check_json_eq(parse_json_object(raw), config.serialize());
|
||||
}
|
||||
|
||||
SECTION ("only registries")
|
||||
|
@ -555,7 +558,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]")
|
|||
})json";
|
||||
// parsing of configuration is tested elsewhere
|
||||
auto config = parse_test_configuration(raw);
|
||||
compare_json_objects(parse_json_object(raw), serialize_configuration(config));
|
||||
Test::check_json_eq(parse_json_object(raw), config.serialize());
|
||||
}
|
||||
|
||||
SECTION ("preserve comments and unexpected fields")
|
||||
|
@ -580,7 +583,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]")
|
|||
})json";
|
||||
|
||||
auto config = parse_test_configuration(raw);
|
||||
compare_json_objects(parse_json_object(raw), serialize_configuration(config));
|
||||
Test::check_json_eq(parse_json_object(raw), config.serialize());
|
||||
|
||||
auto extra_fields = find_unknown_fields(config);
|
||||
CHECK(extra_fields.size() == 4);
|
||||
|
@ -681,7 +684,7 @@ TEST_CASE ("serialize configuration", "[ce-metadata]")
|
|||
// demands
|
||||
// Object values in `demands` are also sorted recursively.
|
||||
auto config = parse_test_configuration(raw);
|
||||
compare_json_objects(parse_json_object(formatted), serialize_configuration(config));
|
||||
Test::check_json_eq(parse_json_object(formatted), config.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -749,21 +752,22 @@ TEST_CASE ("config with ce metadata full example", "[ce-metadata]")
|
|||
"}");
|
||||
|
||||
auto config = parse_test_configuration(raw_config);
|
||||
REQUIRE(config.registry_set.default_registry() != nullptr);
|
||||
REQUIRE(config.default_reg.has_value());
|
||||
|
||||
auto default_registry = config.registry_set.default_registry()->serialize();
|
||||
auto default_registry = config.default_reg.get()->serialize().object();
|
||||
check_string(default_registry, KIND, "builtin");
|
||||
check_string(default_registry, BASELINE, "843e0ba0d8f9c9c572e45564263eedfc7745e74f");
|
||||
|
||||
REQUIRE(config.registry_set.registries().size() == 1);
|
||||
const auto& registry = *config.registry_set.registries().begin();
|
||||
auto serialized_registry = registry.implementation().serialize();
|
||||
REQUIRE(config.registries.size() == 1);
|
||||
const auto& registry = *config.registries.begin();
|
||||
auto serialized_registry = registry.serialize().object();
|
||||
check_string(serialized_registry, KIND, "git");
|
||||
check_string(serialized_registry, REPOSITORY, "https://github.com/northwindtraders/vcpkg-registry");
|
||||
check_string(serialized_registry, BASELINE, "dacf4de488094a384ca2c202b923ccc097956e0c");
|
||||
REQUIRE(registry.packages().size() == 2);
|
||||
REQUIRE(registry.packages()[0] == "beicode");
|
||||
REQUIRE(registry.packages()[1] == "beison");
|
||||
REQUIRE(registry.packages);
|
||||
REQUIRE(registry.packages.get()->size() == 2);
|
||||
REQUIRE(registry.packages.get()->at(0) == "beicode");
|
||||
REQUIRE(registry.packages.get()->at(1) == "beison");
|
||||
|
||||
REQUIRE(!config.extra_info.is_empty());
|
||||
REQUIRE(config.extra_info.size() == 2);
|
||||
|
@ -913,6 +917,6 @@ TEST_CASE ("config with ce metadata full example", "[ce-metadata]")
|
|||
|
||||
// finally test serialization is OK
|
||||
auto raw_obj = parse_json_object(raw_config);
|
||||
auto serialized_obj = serialize_configuration(config);
|
||||
compare_json_objects(raw_obj, serialized_obj);
|
||||
auto serialized_obj = config.serialize();
|
||||
Test::check_json_eq(raw_obj, serialized_obj);
|
||||
}
|
||||
|
|
|
@ -681,10 +681,7 @@ TEST_CASE ("manifest embed configuration", "[manifests]")
|
|||
auto maybe_as_json = Json::parse(raw);
|
||||
REQUIRE(maybe_as_json.has_value());
|
||||
auto as_json = *maybe_as_json.get();
|
||||
REQUIRE(as_json.first.is_object());
|
||||
auto as_json_obj = as_json.first.object();
|
||||
REQUIRE(Json::stringify(serialize_manifest(pgh), Json::JsonStyle::with_spaces(4)) ==
|
||||
Json::stringify(as_json_obj, Json::JsonStyle::with_spaces(4)));
|
||||
check_json_eq(Json::Value::object(serialize_manifest(pgh)), as_json.first);
|
||||
|
||||
REQUIRE(pgh.core_paragraph->builtin_baseline == "089fa4de7dca22c67dcab631f618d5cd0697c8d4");
|
||||
REQUIRE(pgh.core_paragraph->dependencies.size() == 3);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <vcpkg/base/jsonreader.h>
|
||||
|
||||
#include <vcpkg/configuration.h>
|
||||
#include <vcpkg/registries.h>
|
||||
|
||||
using namespace vcpkg;
|
||||
|
@ -46,37 +47,48 @@ namespace
|
|||
|
||||
TEST_CASE ("registry_set_selects_registry", "[registries]")
|
||||
{
|
||||
RegistrySet set;
|
||||
set.set_default_registry(std::make_unique<TestRegistryImplementation>(0));
|
||||
{
|
||||
std::vector<Registry> rs;
|
||||
rs.push_back(make_registry(1, {"p1", "q1", "r1"}));
|
||||
rs.push_back(make_registry(2, {"p2", "q2", "r2"}));
|
||||
RegistrySet set(std::make_unique<TestRegistryImplementation>(0), std::move(rs));
|
||||
|
||||
set.add_registry(make_registry(1, {"p1", "q1", "r1"}));
|
||||
set.add_registry(make_registry(2, {"p2", "q2", "r2"}));
|
||||
auto reg = set.registry_for_port("p1");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 1);
|
||||
reg = set.registry_for_port("r2");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 2);
|
||||
reg = set.registry_for_port("a");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 0);
|
||||
}
|
||||
{
|
||||
std::vector<Registry> rs;
|
||||
rs.push_back(make_registry(1, {"p1", "q1", "r1"}));
|
||||
rs.push_back(make_registry(2, {"p2", "q2", "r2"}));
|
||||
RegistrySet set(nullptr, std::move(rs));
|
||||
|
||||
auto reg = set.registry_for_port("p1");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 1);
|
||||
reg = set.registry_for_port("r2");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 2);
|
||||
reg = set.registry_for_port("a");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 0);
|
||||
auto reg = set.registry_for_port("q1");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 1);
|
||||
reg = set.registry_for_port("p2");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 2);
|
||||
reg = set.registry_for_port("a");
|
||||
CHECK_FALSE(reg);
|
||||
}
|
||||
}
|
||||
|
||||
set.set_default_registry(nullptr);
|
||||
|
||||
reg = set.registry_for_port("q1");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 1);
|
||||
reg = set.registry_for_port("p2");
|
||||
REQUIRE(reg);
|
||||
CHECK(get_tri_num(*reg) == 2);
|
||||
reg = set.registry_for_port("a");
|
||||
CHECK_FALSE(reg);
|
||||
static vcpkg::Optional<Configuration> visit_default_registry(Json::Reader& r, Json::Value&& reg)
|
||||
{
|
||||
Json::Object config;
|
||||
config.insert("default-registry", std::move(reg));
|
||||
return r.visit(config, get_configuration_deserializer());
|
||||
}
|
||||
|
||||
TEST_CASE ("registry_parsing", "[registries]")
|
||||
{
|
||||
auto registry_impl_des = get_registry_implementation_deserializer({});
|
||||
{
|
||||
Json::Reader r;
|
||||
auto test_json = parse_json(R"json(
|
||||
|
@ -84,7 +96,7 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
"kind": "builtin"
|
||||
}
|
||||
)json");
|
||||
r.visit(test_json, *registry_impl_des);
|
||||
visit_default_registry(r, std::move(test_json));
|
||||
CHECK(!r.errors().empty());
|
||||
}
|
||||
{
|
||||
|
@ -95,8 +107,9 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
"baseline": "hi"
|
||||
}
|
||||
)json");
|
||||
r.visit(test_json, *registry_impl_des);
|
||||
CHECK(!r.errors().empty());
|
||||
visit_default_registry(r, std::move(test_json));
|
||||
// Non-SHA strings are allowed and will be diagnosed later
|
||||
CHECK(r.errors().empty());
|
||||
}
|
||||
{
|
||||
Json::Reader r;
|
||||
|
@ -106,9 +119,8 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
"baseline": "1234567890123456789012345678901234567890"
|
||||
}
|
||||
)json");
|
||||
auto registry_impl = r.visit(test_json, *registry_impl_des);
|
||||
auto registry_impl = visit_default_registry(r, std::move(test_json));
|
||||
REQUIRE(registry_impl);
|
||||
CHECK(*registry_impl.get());
|
||||
CHECK(r.errors().empty());
|
||||
}
|
||||
{
|
||||
|
@ -120,7 +132,7 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
"path": "a/b"
|
||||
}
|
||||
)json");
|
||||
r.visit(test_json, *registry_impl_des);
|
||||
visit_default_registry(r, std::move(test_json));
|
||||
CHECK(!r.errors().empty());
|
||||
}
|
||||
{
|
||||
|
@ -131,9 +143,8 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
"path": "a/b/c"
|
||||
}
|
||||
)json");
|
||||
auto registry_impl = r.visit(test_json, *registry_impl_des);
|
||||
auto registry_impl = visit_default_registry(r, std::move(test_json));
|
||||
REQUIRE(registry_impl);
|
||||
CHECK(*registry_impl.get());
|
||||
CHECK(r.errors().empty());
|
||||
|
||||
test_json = parse_json(R"json(
|
||||
|
@ -142,9 +153,8 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
"path": "/a/b/c"
|
||||
}
|
||||
)json");
|
||||
registry_impl = r.visit(test_json, *registry_impl_des);
|
||||
registry_impl = visit_default_registry(r, std::move(test_json));
|
||||
REQUIRE(registry_impl);
|
||||
CHECK(*registry_impl.get());
|
||||
CHECK(r.errors().empty());
|
||||
}
|
||||
|
||||
|
@ -155,7 +165,7 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
)json");
|
||||
{
|
||||
Json::Reader r;
|
||||
r.visit(test_json, *registry_impl_des);
|
||||
visit_default_registry(r, std::move(test_json));
|
||||
CHECK(!r.errors().empty());
|
||||
}
|
||||
test_json = parse_json(R"json(
|
||||
|
@ -166,7 +176,7 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
)json");
|
||||
{
|
||||
Json::Reader r;
|
||||
r.visit(test_json, *registry_impl_des);
|
||||
visit_default_registry(r, std::move(test_json));
|
||||
CHECK(!r.errors().empty());
|
||||
}
|
||||
|
||||
|
@ -178,7 +188,7 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
)json");
|
||||
{
|
||||
Json::Reader r;
|
||||
r.visit(test_json, *registry_impl_des);
|
||||
visit_default_registry(r, std::move(test_json));
|
||||
CHECK(!r.errors().empty());
|
||||
}
|
||||
|
||||
|
@ -192,9 +202,8 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
)json");
|
||||
{
|
||||
Json::Reader r;
|
||||
auto registry_impl = r.visit(test_json, *registry_impl_des);
|
||||
auto registry_impl = visit_default_registry(r, std::move(test_json));
|
||||
REQUIRE(registry_impl);
|
||||
CHECK(*registry_impl.get());
|
||||
INFO(Strings::join("\n", r.errors()));
|
||||
CHECK(r.errors().empty());
|
||||
}
|
||||
|
@ -207,9 +216,8 @@ TEST_CASE ("registry_parsing", "[registries]")
|
|||
}
|
||||
)json");
|
||||
Json::Reader r;
|
||||
auto registry_impl = r.visit(test_json, *registry_impl_des);
|
||||
auto registry_impl = visit_default_registry(r, std::move(test_json));
|
||||
REQUIRE(registry_impl);
|
||||
CHECK(*registry_impl.get());
|
||||
INFO(Strings::join("\n", r.errors()));
|
||||
CHECK(r.errors().empty());
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include <vcpkg-test/util.h>
|
||||
|
@ -105,4 +106,84 @@ namespace vcpkg::Test
|
|||
const static Path BASE_TEMPORARY_DIRECTORY = internal_base_temporary_directory();
|
||||
return BASE_TEMPORARY_DIRECTORY;
|
||||
}
|
||||
|
||||
static void check_json_eq(const Json::Value& l, const Json::Value& r, std::string& path);
|
||||
|
||||
static void check_json_eq(const Json::Object& l, const Json::Object& r, std::string& path)
|
||||
{
|
||||
std::set<std::string> keys_l;
|
||||
for (auto&& kv : l)
|
||||
{
|
||||
keys_l.insert(kv.first.to_string());
|
||||
}
|
||||
std::set<std::string> keys_r;
|
||||
for (auto&& kv : r)
|
||||
{
|
||||
keys_r.insert(kv.first.to_string());
|
||||
}
|
||||
{
|
||||
INFO(path)
|
||||
CHECK(keys_l == keys_r);
|
||||
}
|
||||
const size_t orig_path_len = path.size();
|
||||
for (auto&& key : keys_l)
|
||||
{
|
||||
auto vl = l.get(key);
|
||||
auto vr = r.get(key);
|
||||
if (vl && vr)
|
||||
{
|
||||
path.push_back('.');
|
||||
path.append(key);
|
||||
check_json_eq(*vl, *vr, path);
|
||||
path.resize(orig_path_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void check_json_eq(const Json::Array& l, const Json::Array& r, std::string& path)
|
||||
{
|
||||
{
|
||||
INFO(path)
|
||||
CHECK(l.size() == r.size());
|
||||
}
|
||||
const size_t orig_path_len = path.size();
|
||||
for (size_t i = 0; i < l.size() && i < r.size(); ++i)
|
||||
{
|
||||
Strings::append(path, '[', i, ']');
|
||||
check_json_eq(r[i], l[i], path);
|
||||
path.resize(orig_path_len);
|
||||
}
|
||||
}
|
||||
static void check_json_eq(const Json::Value& l, const Json::Value& r, std::string& path)
|
||||
{
|
||||
if (l.is_object() && r.is_object())
|
||||
{
|
||||
check_json_eq(l.object(), r.object(), path);
|
||||
}
|
||||
else if (l.is_array() && r.is_array())
|
||||
{
|
||||
check_json_eq(l.array(), r.array(), path);
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO(path);
|
||||
REQUIRE(l == r);
|
||||
}
|
||||
}
|
||||
|
||||
void check_json_eq(const Json::Value& l, const Json::Value& r)
|
||||
{
|
||||
std::string path = "$";
|
||||
check_json_eq(l, r, path);
|
||||
}
|
||||
void check_json_eq(const Json::Object& l, const Json::Object& r)
|
||||
{
|
||||
std::string path = "$";
|
||||
check_json_eq(l, r, path);
|
||||
}
|
||||
void check_json_eq(const Json::Array& l, const Json::Array& r)
|
||||
{
|
||||
std::string path = "$";
|
||||
check_json_eq(l, r, path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <vcpkg/base/system.print.h>
|
||||
#include <vcpkg/base/unicode.h>
|
||||
|
||||
#include <vcpkg/documentation.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
namespace vcpkg::Json
|
||||
|
@ -1425,9 +1427,9 @@ namespace vcpkg::Json
|
|||
if (!is_ident(sv))
|
||||
{
|
||||
r.add_generic_error(type_name(),
|
||||
"must be lowercase alphanumeric+hyphens and not reserved (see "
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/specifications/manifests.md for "
|
||||
"more information)");
|
||||
Strings::concat("must be lowercase alphanumeric+hyphens and not reserved (see ",
|
||||
vcpkg::docs::manifests_url,
|
||||
" for more information)"));
|
||||
}
|
||||
return sv.to_string();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <vcpkg/binarycaching.private.h>
|
||||
#include <vcpkg/build.h>
|
||||
#include <vcpkg/dependencies.h>
|
||||
#include <vcpkg/documentation.h>
|
||||
#include <vcpkg/metrics.h>
|
||||
#include <vcpkg/tools.h>
|
||||
|
||||
|
@ -21,11 +22,6 @@ using namespace vcpkg;
|
|||
|
||||
namespace
|
||||
{
|
||||
static constexpr StringLiteral s_assetcaching_doc_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/assetcaching.md";
|
||||
static constexpr StringLiteral s_binarycaching_doc_url =
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/binarycaching.md";
|
||||
|
||||
struct ConfigSegmentsParser : Parse::ParserBase
|
||||
{
|
||||
using Parse::ParserBase::ParserBase;
|
||||
|
@ -633,9 +629,9 @@ namespace
|
|||
res.exit_code != 0)
|
||||
{
|
||||
print2(Color::warning,
|
||||
"One or more NuGet credential providers failed to authenticate. See "
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/binarycaching.md for "
|
||||
"more details on how to provide credentials.\n");
|
||||
"One or more NuGet credential providers failed to authenticate. See ",
|
||||
docs::binarycaching_url,
|
||||
" for more details on how to provide credentials.\n");
|
||||
}
|
||||
else if (res.output.find("for example \"-ApiKey AzureDevOps\"") != std::string::npos)
|
||||
{
|
||||
|
@ -1802,21 +1798,21 @@ ExpectedS<Downloads::DownloadManagerConfig> vcpkg::parse_download_configuration(
|
|||
parser.parse();
|
||||
if (auto err = parser.get_error())
|
||||
{
|
||||
return Strings::concat(err->format(), "For more information, see ", s_assetcaching_doc_url, "\n");
|
||||
return Strings::concat(err->format(), "For more information, see ", docs::assetcaching_url, "\n");
|
||||
}
|
||||
|
||||
if (s.azblob_templates_to_put.size() > 1)
|
||||
{
|
||||
return Strings::concat("Error: a maximum of one asset write url can be specified\n"
|
||||
"For more information, see ",
|
||||
s_assetcaching_doc_url,
|
||||
docs::assetcaching_url,
|
||||
"\n");
|
||||
}
|
||||
if (s.url_templates_to_get.size() > 1)
|
||||
{
|
||||
return Strings::concat("Error: a maximum of one asset read url can be specified\n"
|
||||
"For more information, see ",
|
||||
s_assetcaching_doc_url,
|
||||
docs::assetcaching_url,
|
||||
"\n");
|
||||
}
|
||||
|
||||
|
@ -2108,7 +2104,7 @@ void vcpkg::help_topic_asset_caching(const VcpkgPaths&)
|
|||
tbl.blank();
|
||||
print2(tbl.m_str);
|
||||
|
||||
print2("\nExtended documentation is available at ", s_assetcaching_doc_url, "\n");
|
||||
print2("\nExtended documentation is available at ", docs::assetcaching_url, "\n");
|
||||
}
|
||||
|
||||
void vcpkg::help_topic_binary_caching(const VcpkgPaths&)
|
||||
|
@ -2175,7 +2171,7 @@ void vcpkg::help_topic_binary_caching(const VcpkgPaths&)
|
|||
"\nThis consults %LOCALAPPDATA%/%APPDATA% on Windows and $XDG_CACHE_HOME or $HOME on other platforms.\n");
|
||||
}
|
||||
|
||||
print2("\nExtended documentation is available at ", s_binarycaching_doc_url, "\n");
|
||||
print2("\nExtended documentation is available at ", docs::binarycaching_url, "\n");
|
||||
}
|
||||
|
||||
std::string vcpkg::generate_nuget_packages_config(const Dependencies::ActionPlan& action)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <vcpkg/commands.h>
|
||||
#include <vcpkg/commands.version.h>
|
||||
#include <vcpkg/dependencies.h>
|
||||
#include <vcpkg/documentation.h>
|
||||
#include <vcpkg/globalstate.h>
|
||||
#include <vcpkg/help.h>
|
||||
#include <vcpkg/input.h>
|
||||
|
@ -352,10 +353,7 @@ namespace vcpkg::Build
|
|||
msg::value = target_architecture,
|
||||
msg::path = toolset.visual_studio_root_path,
|
||||
msg::list = toolset_list);
|
||||
msg::println(
|
||||
msg::msgSeeURL,
|
||||
msg::url = StringLiteral(
|
||||
"https://github.com/microsoft/vcpkg/blob/master/docs/users/triplets.md#VCPKG_VISUAL_STUDIO_PATH"));
|
||||
msg::println(msg::msgSeeURL, msg::url = docs::vcpkg_visual_studio_path_url);
|
||||
Checks::exit_maybe_upgrade(VCPKG_LINE_INFO);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -9,6 +9,204 @@ namespace
|
|||
{
|
||||
using namespace vcpkg;
|
||||
|
||||
struct RegistryConfigDeserializer : Json::IDeserializer<RegistryConfig>
|
||||
{
|
||||
constexpr static StringLiteral KIND = "kind";
|
||||
constexpr static StringLiteral BASELINE = "baseline";
|
||||
constexpr static StringLiteral PATH = "path";
|
||||
constexpr static StringLiteral REPO = "repository";
|
||||
constexpr static StringLiteral REFERENCE = "reference";
|
||||
constexpr static StringLiteral NAME = "name";
|
||||
constexpr static StringLiteral LOCATION = "location";
|
||||
|
||||
constexpr static StringLiteral KIND_BUILTIN = "builtin";
|
||||
constexpr static StringLiteral KIND_FILESYSTEM = "filesystem";
|
||||
constexpr static StringLiteral KIND_GIT = "git";
|
||||
constexpr static StringLiteral KIND_ARTIFACT = "artifact";
|
||||
|
||||
virtual StringView type_name() const override { return "a registry"; }
|
||||
virtual View<StringView> valid_fields() const override;
|
||||
|
||||
virtual Optional<RegistryConfig> visit_null(Json::Reader&) override;
|
||||
virtual Optional<RegistryConfig> visit_object(Json::Reader&, const Json::Object&) override;
|
||||
|
||||
static RegistryConfigDeserializer instance;
|
||||
};
|
||||
RegistryConfigDeserializer RegistryConfigDeserializer::instance;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::KIND;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::BASELINE;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::PATH;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::REPO;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::REFERENCE;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::NAME;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::LOCATION;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::KIND_BUILTIN;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::KIND_FILESYSTEM;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::KIND_GIT;
|
||||
constexpr StringLiteral RegistryConfigDeserializer::KIND_ARTIFACT;
|
||||
|
||||
struct RegistryDeserializer final : Json::IDeserializer<RegistryConfig>
|
||||
{
|
||||
constexpr static StringLiteral PACKAGES = "packages";
|
||||
|
||||
virtual StringView type_name() const override { return "a registry"; }
|
||||
virtual View<StringView> valid_fields() const override;
|
||||
|
||||
virtual Optional<RegistryConfig> visit_object(Json::Reader&, const Json::Object&) override;
|
||||
|
||||
static RegistryDeserializer instance;
|
||||
};
|
||||
RegistryDeserializer RegistryDeserializer::instance;
|
||||
constexpr StringLiteral RegistryDeserializer::PACKAGES;
|
||||
|
||||
View<StringView> RegistryConfigDeserializer::valid_fields() const
|
||||
{
|
||||
static const StringView t[] = {KIND, BASELINE, PATH, REPO, REFERENCE, NAME, LOCATION};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_builtin_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryConfigDeserializer::KIND,
|
||||
RegistryConfigDeserializer::BASELINE,
|
||||
RegistryDeserializer::PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_filesystem_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryConfigDeserializer::KIND,
|
||||
RegistryConfigDeserializer::BASELINE,
|
||||
RegistryConfigDeserializer::PATH,
|
||||
RegistryDeserializer::PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_git_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryConfigDeserializer::KIND,
|
||||
RegistryConfigDeserializer::BASELINE,
|
||||
RegistryConfigDeserializer::REPO,
|
||||
RegistryConfigDeserializer::REFERENCE,
|
||||
RegistryDeserializer::PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_artifact_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryConfigDeserializer::KIND,
|
||||
RegistryConfigDeserializer::NAME,
|
||||
RegistryConfigDeserializer::LOCATION,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
||||
Optional<RegistryConfig> RegistryConfigDeserializer::visit_null(Json::Reader&) { return RegistryConfig(); }
|
||||
|
||||
Optional<RegistryConfig> RegistryConfigDeserializer::visit_object(Json::Reader& r, const Json::Object& obj)
|
||||
{
|
||||
static Json::StringDeserializer kind_deserializer{"a registry implementation kind"};
|
||||
static Json::StringDeserializer baseline_deserializer{"a baseline"};
|
||||
|
||||
RegistryConfig res;
|
||||
auto& kind = res.kind.emplace();
|
||||
r.required_object_field(type_name(), obj, KIND, kind, kind_deserializer);
|
||||
|
||||
if (kind == KIND_BUILTIN)
|
||||
{
|
||||
auto& baseline = res.baseline.emplace();
|
||||
r.required_object_field("a builtin registry", obj, BASELINE, baseline, baseline_deserializer);
|
||||
r.check_for_unexpected_fields(obj, valid_builtin_fields(), "a builtin registry");
|
||||
}
|
||||
else if (kind == KIND_FILESYSTEM)
|
||||
{
|
||||
std::string baseline;
|
||||
if (r.optional_object_field(obj, BASELINE, baseline, baseline_deserializer))
|
||||
{
|
||||
res.baseline = std::move(baseline);
|
||||
}
|
||||
|
||||
r.required_object_field(
|
||||
"a filesystem registry", obj, PATH, res.path.emplace(), Json::PathDeserializer::instance);
|
||||
|
||||
r.check_for_unexpected_fields(obj, valid_filesystem_fields(), "a filesystem registry");
|
||||
}
|
||||
else if (kind == KIND_GIT)
|
||||
{
|
||||
static Json::StringDeserializer repo_des{"a git repository URL"};
|
||||
r.required_object_field("a git registry", obj, REPO, res.repo.emplace(), repo_des);
|
||||
|
||||
static Json::StringDeserializer ref_des{"a git reference (for example, a branch)"};
|
||||
if (!r.optional_object_field(obj, REFERENCE, res.reference.emplace(), ref_des))
|
||||
{
|
||||
res.reference = nullopt;
|
||||
}
|
||||
|
||||
r.required_object_field("a git registry", obj, BASELINE, res.baseline.emplace(), baseline_deserializer);
|
||||
|
||||
r.check_for_unexpected_fields(obj, valid_git_fields(), "a git registry");
|
||||
}
|
||||
else if (kind == KIND_ARTIFACT)
|
||||
{
|
||||
r.required_object_field(
|
||||
"an artifacts registry", obj, NAME, res.name.emplace(), Json::IdentifierDeserializer::instance);
|
||||
|
||||
static Json::StringDeserializer location_des{"an artifacts git repository URL"};
|
||||
r.required_object_field("an artifacts registry", obj, LOCATION, res.location.emplace(), location_des);
|
||||
|
||||
r.check_for_unexpected_fields(obj, valid_artifact_fields(), "an artifacts registry");
|
||||
}
|
||||
else
|
||||
{
|
||||
StringLiteral valid_kinds[] = {KIND_BUILTIN, KIND_FILESYSTEM, KIND_GIT, KIND_ARTIFACT};
|
||||
r.add_generic_error(type_name(),
|
||||
"Field \"kind\" did not have an expected value (expected one of: \"",
|
||||
Strings::join("\", \"", valid_kinds),
|
||||
"\"; found \"",
|
||||
kind,
|
||||
"\")");
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
return std::move(res); // gcc-7 bug workaround redundant move
|
||||
}
|
||||
|
||||
View<StringView> RegistryDeserializer::valid_fields() const
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryConfigDeserializer::KIND,
|
||||
RegistryConfigDeserializer::BASELINE,
|
||||
RegistryConfigDeserializer::PATH,
|
||||
RegistryConfigDeserializer::REPO,
|
||||
RegistryConfigDeserializer::REFERENCE,
|
||||
RegistryConfigDeserializer::NAME,
|
||||
RegistryConfigDeserializer::LOCATION,
|
||||
PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
||||
Optional<RegistryConfig> RegistryDeserializer::visit_object(Json::Reader& r, const Json::Object& obj)
|
||||
{
|
||||
auto impl = RegistryConfigDeserializer::instance.visit_object(r, obj);
|
||||
|
||||
if (auto config = impl.get())
|
||||
{
|
||||
static Json::ArrayDeserializer<Json::PackageNameDeserializer> package_names_deserializer{
|
||||
"an array of package names"};
|
||||
|
||||
if (config->kind && *config->kind.get() != RegistryConfigDeserializer::KIND_ARTIFACT)
|
||||
{
|
||||
r.required_object_field(
|
||||
type_name(), obj, PACKAGES, config->packages.emplace(), package_names_deserializer);
|
||||
}
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
struct DictionaryDeserializer final : Json::IDeserializer<Json::Object>
|
||||
{
|
||||
virtual StringView type_name() const override { return "a `string: string` dictionary"; }
|
||||
|
@ -66,11 +264,9 @@ namespace
|
|||
|
||||
virtual Optional<Configuration> visit_object(Json::Reader& r, const Json::Object& obj) override;
|
||||
|
||||
ConfigurationDeserializer(const Path& configuration_directory);
|
||||
|
||||
private:
|
||||
Path configuration_directory;
|
||||
static ConfigurationDeserializer instance;
|
||||
};
|
||||
ConfigurationDeserializer ConfigurationDeserializer::instance;
|
||||
constexpr StringLiteral ConfigurationDeserializer::DEFAULT_REGISTRY;
|
||||
constexpr StringLiteral ConfigurationDeserializer::REGISTRIES;
|
||||
|
||||
|
@ -186,9 +382,8 @@ namespace
|
|||
|
||||
Optional<Configuration> ConfigurationDeserializer::visit_object(Json::Reader& r, const Json::Object& obj)
|
||||
{
|
||||
static const StringView ARTIFACT = "artifact";
|
||||
|
||||
Json::Object extra_info;
|
||||
Configuration ret;
|
||||
Json::Object& extra_info = ret.extra_info;
|
||||
|
||||
std::vector<std::string> comment_keys;
|
||||
for (const auto& el : obj)
|
||||
|
@ -201,30 +396,24 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
RegistrySet registries;
|
||||
|
||||
auto impl_des = get_registry_implementation_deserializer(configuration_directory);
|
||||
|
||||
std::unique_ptr<RegistryImplementation> default_registry;
|
||||
if (r.optional_object_field(obj, DEFAULT_REGISTRY, default_registry, *impl_des))
|
||||
RegistryConfig default_registry;
|
||||
if (r.optional_object_field(obj, DEFAULT_REGISTRY, default_registry, RegistryConfigDeserializer::instance))
|
||||
{
|
||||
if (default_registry && default_registry->kind() == ARTIFACT)
|
||||
if (default_registry.kind.value_or("") == RegistryConfigDeserializer::KIND_ARTIFACT)
|
||||
{
|
||||
r.add_generic_error(type_name(), DEFAULT_REGISTRY, " cannot be of \"", ARTIFACT, "\" kind");
|
||||
r.add_generic_error(type_name(),
|
||||
DEFAULT_REGISTRY,
|
||||
" cannot be of kind \"",
|
||||
RegistryConfigDeserializer::KIND_ARTIFACT,
|
||||
"\"");
|
||||
}
|
||||
registries.set_default_registry(std::move(default_registry));
|
||||
ret.default_reg = std::move(default_registry);
|
||||
}
|
||||
|
||||
auto reg_des = get_registry_array_deserializer(configuration_directory);
|
||||
std::vector<Registry> regs;
|
||||
r.optional_object_field(obj, REGISTRIES, regs, *reg_des);
|
||||
static Json::ArrayDeserializer<RegistryDeserializer> regs_des("an array of registries");
|
||||
r.optional_object_field(obj, REGISTRIES, ret.registries, regs_des);
|
||||
|
||||
for (Registry& reg : regs)
|
||||
{
|
||||
registries.add_registry(std::move(reg));
|
||||
}
|
||||
|
||||
Json::Object ce_metadata_obj;
|
||||
Json::Object& ce_metadata_obj = ret.ce_metadata;
|
||||
auto maybe_ce_metadata = r.visit(obj, CeMetadataDeserializer::instance);
|
||||
if (maybe_ce_metadata.has_value())
|
||||
{
|
||||
|
@ -243,12 +432,7 @@ namespace
|
|||
ce_metadata_obj.remove(comment_key);
|
||||
}
|
||||
|
||||
return Configuration{std::move(registries), ce_metadata_obj, extra_info};
|
||||
}
|
||||
|
||||
ConfigurationDeserializer::ConfigurationDeserializer(const Path& configuration_directory)
|
||||
: configuration_directory(configuration_directory)
|
||||
{
|
||||
return std::move(ret);
|
||||
}
|
||||
|
||||
static void serialize_ce_metadata(const Json::Object& ce_metadata, Json::Object& put_into)
|
||||
|
@ -307,56 +491,6 @@ namespace
|
|||
serialize_demands(ce_metadata, put_into);
|
||||
}
|
||||
|
||||
static Json::Object serialize_configuration_impl(const Configuration& config)
|
||||
{
|
||||
constexpr static StringLiteral REGISTRY_PACKAGES = "packages";
|
||||
|
||||
Json::Object obj;
|
||||
|
||||
for (const auto& el : config.extra_info)
|
||||
{
|
||||
obj.insert(el.first.to_string(), el.second);
|
||||
}
|
||||
|
||||
if (!config.registry_set.is_default_builtin_registry())
|
||||
{
|
||||
if (auto default_registry = config.registry_set.default_registry())
|
||||
{
|
||||
obj.insert(ConfigurationDeserializer::DEFAULT_REGISTRY, default_registry->serialize());
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.insert(ConfigurationDeserializer::DEFAULT_REGISTRY, Json::Value::null(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
auto reg_view = config.registry_set.registries();
|
||||
if (reg_view.size() > 0)
|
||||
{
|
||||
auto& reg_arr = obj.insert(ConfigurationDeserializer::REGISTRIES, Json::Array());
|
||||
for (const auto& reg : reg_view)
|
||||
{
|
||||
auto reg_obj = reg.implementation().serialize();
|
||||
if (reg.packages().size())
|
||||
{
|
||||
auto& packages = reg_obj.insert(REGISTRY_PACKAGES, Json::Array{});
|
||||
for (const auto& pkg : reg.packages())
|
||||
{
|
||||
packages.push_back(Json::Value::string(pkg));
|
||||
}
|
||||
}
|
||||
reg_arr.push_back(std::move(reg_obj));
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.ce_metadata.is_empty())
|
||||
{
|
||||
serialize_ce_metadata(config.ce_metadata, obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void find_unknown_fields_impl(const Json::Object& obj, std::vector<std::string>& out, StringView path)
|
||||
{
|
||||
std::vector<StringView> ret;
|
||||
|
@ -420,19 +554,8 @@ namespace vcpkg
|
|||
return known_fields;
|
||||
}
|
||||
|
||||
void Configuration::validate_feature_flags(const FeatureFlagSettings& flags)
|
||||
void Configuration::validate_as_active()
|
||||
{
|
||||
if (!flags.registries && registry_set.has_modifications())
|
||||
{
|
||||
LockGuardPtr<Metrics>(g_metrics)->track_property(
|
||||
"registries-error-registry-modification-without-feature-flag", "defined");
|
||||
vcpkg::printf(Color::warning,
|
||||
"Warning: configuration specified the \"registries\" or \"default-registries\" field, but "
|
||||
"the %s feature flag was not enabled.\n",
|
||||
VcpkgCmdArguments::REGISTRIES_FEATURE);
|
||||
registry_set = RegistrySet();
|
||||
}
|
||||
|
||||
if (!ce_metadata.is_empty())
|
||||
{
|
||||
auto unknown_fields = find_unknown_fields(*this);
|
||||
|
@ -447,12 +570,114 @@ namespace vcpkg
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Json::IDeserializer<Configuration>> make_configuration_deserializer(const Path& config_directory)
|
||||
Json::IDeserializer<Configuration>& get_configuration_deserializer() { return ConfigurationDeserializer::instance; }
|
||||
|
||||
static std::unique_ptr<RegistryImplementation> instantiate_rconfig(const RegistryConfig& config,
|
||||
const Path& config_dir)
|
||||
{
|
||||
return std::make_unique<ConfigurationDeserializer>(config_directory);
|
||||
if (auto k = config.kind.get())
|
||||
{
|
||||
if (*k == RegistryConfigDeserializer::KIND_BUILTIN)
|
||||
{
|
||||
return make_builtin_registry(config.baseline.value_or_exit(VCPKG_LINE_INFO));
|
||||
}
|
||||
else if (*k == RegistryConfigDeserializer::KIND_GIT)
|
||||
{
|
||||
return make_git_registry(config.repo.value_or_exit(VCPKG_LINE_INFO),
|
||||
config.reference.value_or("HEAD"),
|
||||
config.baseline.value_or_exit(VCPKG_LINE_INFO));
|
||||
}
|
||||
else if (*k == RegistryConfigDeserializer::KIND_ARTIFACT)
|
||||
{
|
||||
return make_artifact_registry(config.name.value_or_exit(VCPKG_LINE_INFO),
|
||||
config.location.value_or_exit(VCPKG_LINE_INFO));
|
||||
}
|
||||
else if (*k == RegistryConfigDeserializer::KIND_FILESYSTEM)
|
||||
{
|
||||
return make_filesystem_registry(config_dir / config.path.value_or_exit(VCPKG_LINE_INFO),
|
||||
config.baseline.value_or(""));
|
||||
}
|
||||
else
|
||||
{
|
||||
Checks::unreachable(VCPKG_LINE_INFO);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Json::Object serialize_configuration(const Configuration& config) { return serialize_configuration_impl(config); }
|
||||
std::unique_ptr<RegistrySet> Configuration::instantiate_registry_set(const Path& config_dir) const
|
||||
{
|
||||
std::vector<Registry> r_impls;
|
||||
for (auto&& reg : registries)
|
||||
{
|
||||
// packages will be null for artifact registries
|
||||
if (auto p = reg.packages.get())
|
||||
{
|
||||
r_impls.emplace_back(std::vector<std::string>(*p), instantiate_rconfig(reg, config_dir));
|
||||
}
|
||||
}
|
||||
auto reg1 = default_reg ? instantiate_rconfig(*default_reg.get(), config_dir) : make_builtin_registry();
|
||||
return std::make_unique<RegistrySet>(std::move(reg1), std::move(r_impls));
|
||||
}
|
||||
|
||||
Json::Object Configuration::serialize() const
|
||||
{
|
||||
Json::Object obj;
|
||||
|
||||
for (const auto& el : extra_info)
|
||||
{
|
||||
obj.insert(el.first.to_string(), el.second);
|
||||
}
|
||||
|
||||
if (auto default_registry = default_reg.get())
|
||||
{
|
||||
obj.insert(ConfigurationDeserializer::DEFAULT_REGISTRY, default_registry->serialize());
|
||||
}
|
||||
|
||||
if (!registries.empty())
|
||||
{
|
||||
auto& reg_arr = obj.insert(ConfigurationDeserializer::REGISTRIES, Json::Array());
|
||||
for (const auto& reg : registries)
|
||||
{
|
||||
reg_arr.push_back(reg.serialize());
|
||||
}
|
||||
}
|
||||
|
||||
if (!ce_metadata.is_empty())
|
||||
{
|
||||
serialize_ce_metadata(ce_metadata, obj);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
Json::Value RegistryConfig::serialize() const
|
||||
{
|
||||
if (!kind)
|
||||
{
|
||||
return Json::Value::null(nullptr);
|
||||
}
|
||||
Json::Object obj;
|
||||
obj.insert(RegistryConfigDeserializer::KIND, Json::Value::string(*kind.get()));
|
||||
if (auto p = baseline.get()) obj.insert(RegistryConfigDeserializer::BASELINE, Json::Value::string(*p));
|
||||
if (auto p = location.get()) obj.insert(RegistryConfigDeserializer::LOCATION, Json::Value::string(*p));
|
||||
if (auto p = name.get()) obj.insert(RegistryConfigDeserializer::NAME, Json::Value::string(*p));
|
||||
if (auto p = path.get()) obj.insert(RegistryConfigDeserializer::PATH, Json::Value::string(p->native()));
|
||||
if (auto p = reference.get()) obj.insert(RegistryConfigDeserializer::REFERENCE, Json::Value::string(*p));
|
||||
if (auto p = repo.get()) obj.insert(RegistryConfigDeserializer::REPO, Json::Value::string(*p));
|
||||
if (packages)
|
||||
{
|
||||
auto& arr = obj.insert(RegistryDeserializer::PACKAGES, Json::Array());
|
||||
for (auto&& p : *packages.get())
|
||||
{
|
||||
arr.push_back(Json::Value::string(p));
|
||||
}
|
||||
}
|
||||
return Json::Value::object(std::move(obj));
|
||||
}
|
||||
|
||||
std::vector<std::string> find_unknown_fields(const Configuration& config)
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <vcpkg/commands.list.h>
|
||||
#include <vcpkg/commands.owns.h>
|
||||
#include <vcpkg/commands.search.h>
|
||||
#include <vcpkg/documentation.h>
|
||||
#include <vcpkg/export.h>
|
||||
#include <vcpkg/help.h>
|
||||
#include <vcpkg/install.h>
|
||||
|
@ -112,9 +113,7 @@ namespace vcpkg::Help
|
|||
{ "name": "rapidjson", "version": "2020-09-14" }
|
||||
]
|
||||
})");
|
||||
print2(tbl.m_str,
|
||||
"\nExtended documentation is available at "
|
||||
"https://github.com/Microsoft/vcpkg/tree/master/docs/users/versioning.md\n");
|
||||
print2(tbl.m_str, "\nExtended documentation is available at ", docs::versioning_url, "\n");
|
||||
}
|
||||
|
||||
static constexpr std::array<Topic, 17> topics = {{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <vcpkg/commands.setinstalled.h>
|
||||
#include <vcpkg/configuration.h>
|
||||
#include <vcpkg/dependencies.h>
|
||||
#include <vcpkg/documentation.h>
|
||||
#include <vcpkg/globalstate.h>
|
||||
#include <vcpkg/help.h>
|
||||
#include <vcpkg/input.h>
|
||||
|
@ -851,17 +852,14 @@ namespace vcpkg::Install
|
|||
if (!maybe_manifest_scf)
|
||||
{
|
||||
print_error_message(maybe_manifest_scf.error());
|
||||
print2("See https://github.com/Microsoft/vcpkg/tree/master/docs/users/manifests.md for "
|
||||
"more information.\n");
|
||||
print2("See ", docs::manifests_url, " for 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(),
|
||||
paths.get_configuration().registry_set.is_default_builtin_registry()))
|
||||
manifest_path, paths.get_feature_flags(), paths.get_registry_set().is_default_builtin_registry()))
|
||||
{
|
||||
Checks::exit_with_message(VCPKG_LINE_INFO, maybe_error.value_or_exit(VCPKG_LINE_INFO));
|
||||
}
|
||||
|
@ -928,8 +926,7 @@ namespace vcpkg::Install
|
|||
extended_overlay_ports.reserve(args.overlay_ports.size() + 2);
|
||||
extended_overlay_ports.push_back(manifest_path.parent_path().to_string());
|
||||
Util::Vectors::append(&extended_overlay_ports, args.overlay_ports);
|
||||
if (paths.get_configuration().registry_set.is_default_builtin_registry() &&
|
||||
!paths.use_git_default_registry())
|
||||
if (paths.get_registry_set().is_default_builtin_registry() && !paths.use_git_default_registry())
|
||||
{
|
||||
extended_overlay_ports.push_back(paths.builtin_ports_directory().native());
|
||||
}
|
||||
|
|
|
@ -412,7 +412,7 @@ namespace vcpkg::Paragraphs
|
|||
|
||||
std::vector<std::string> ports;
|
||||
|
||||
const auto& registries = paths.get_configuration().registry_set;
|
||||
const auto& registries = paths.get_registry_set();
|
||||
|
||||
for (const auto& registry : registries.registries())
|
||||
{
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace vcpkg::PortFileProvider
|
|||
}
|
||||
else
|
||||
{
|
||||
auto version = paths.get_configuration().registry_set.baseline_for_port(paths, port_name);
|
||||
auto version = paths.get_registry_set().baseline_for_port(paths, port_name);
|
||||
m_baseline_cache.emplace(port_name.to_string(), version);
|
||||
return version;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ namespace vcpkg::PortFileProvider
|
|||
auto entry_it = m_entry_cache.find(name);
|
||||
if (entry_it == m_entry_cache.end())
|
||||
{
|
||||
if (auto reg = paths.get_configuration().registry_set.registry_for_port(name))
|
||||
if (auto reg = paths.get_registry_set().registry_for_port(name))
|
||||
{
|
||||
if (auto entry = reg->get_port_entry(paths, name))
|
||||
{
|
||||
|
|
|
@ -64,8 +64,6 @@ namespace
|
|||
|
||||
Optional<VersionT> get_baseline_version(const VcpkgPaths&, StringView) const override;
|
||||
|
||||
Json::Object serialize() const override;
|
||||
|
||||
private:
|
||||
friend struct GitRegistryEntry;
|
||||
|
||||
|
@ -231,8 +229,6 @@ namespace
|
|||
return paths.builtin_ports_directory() / port_name;
|
||||
}
|
||||
|
||||
Json::Object serialize() const override;
|
||||
|
||||
~BuiltinFilesRegistry() = default;
|
||||
|
||||
DelayedInit<Baseline> m_baseline;
|
||||
|
@ -266,8 +262,6 @@ namespace
|
|||
|
||||
Optional<VersionT> get_baseline_version(const VcpkgPaths& paths, StringView port_name) const override;
|
||||
|
||||
Json::Object serialize() const override;
|
||||
|
||||
~BuiltinGitRegistry() = default;
|
||||
|
||||
std::string m_baseline_identifier;
|
||||
|
@ -292,7 +286,7 @@ namespace
|
|||
struct FilesystemRegistry final : RegistryImplementation
|
||||
{
|
||||
FilesystemRegistry(Path&& path, std::string&& baseline)
|
||||
: m_path(std::move(path)), m_baseline_identifier(baseline)
|
||||
: m_path(std::move(path)), m_baseline_identifier(std::move(baseline))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -304,8 +298,6 @@ namespace
|
|||
|
||||
Optional<VersionT> get_baseline_version(const VcpkgPaths&, StringView) const override;
|
||||
|
||||
Json::Object serialize() const override;
|
||||
|
||||
private:
|
||||
Path m_path;
|
||||
std::string m_baseline_identifier;
|
||||
|
@ -336,8 +328,6 @@ namespace
|
|||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
Json::Object serialize() const override;
|
||||
|
||||
~ArtifactRegistry() = default;
|
||||
|
||||
private:
|
||||
|
@ -922,228 +912,6 @@ namespace
|
|||
};
|
||||
BaselineDeserializer BaselineDeserializer::instance;
|
||||
|
||||
struct RegistryImplDeserializer : Json::IDeserializer<std::unique_ptr<RegistryImplementation>>
|
||||
{
|
||||
constexpr static StringLiteral KIND = "kind";
|
||||
constexpr static StringLiteral BASELINE = "baseline";
|
||||
constexpr static StringLiteral PATH = "path";
|
||||
constexpr static StringLiteral REPO = "repository";
|
||||
constexpr static StringLiteral REFERENCE = "reference";
|
||||
constexpr static StringLiteral NAME = "name";
|
||||
constexpr static StringLiteral LOCATION = "location";
|
||||
|
||||
constexpr static StringLiteral KIND_BUILTIN = "builtin";
|
||||
constexpr static StringLiteral KIND_FILESYSTEM = "filesystem";
|
||||
constexpr static StringLiteral KIND_GIT = "git";
|
||||
constexpr static StringLiteral KIND_ARTIFACT = "artifact";
|
||||
|
||||
virtual StringView type_name() const override { return "a registry"; }
|
||||
virtual View<StringView> valid_fields() const override;
|
||||
|
||||
virtual Optional<std::unique_ptr<RegistryImplementation>> visit_null(Json::Reader&) override;
|
||||
virtual Optional<std::unique_ptr<RegistryImplementation>> visit_object(Json::Reader&,
|
||||
const Json::Object&) override;
|
||||
|
||||
RegistryImplDeserializer(const Path& configuration_directory) : config_directory(configuration_directory) { }
|
||||
|
||||
Path config_directory;
|
||||
};
|
||||
constexpr StringLiteral RegistryImplDeserializer::KIND;
|
||||
constexpr StringLiteral RegistryImplDeserializer::BASELINE;
|
||||
constexpr StringLiteral RegistryImplDeserializer::PATH;
|
||||
constexpr StringLiteral RegistryImplDeserializer::REPO;
|
||||
constexpr StringLiteral RegistryImplDeserializer::REFERENCE;
|
||||
constexpr StringLiteral RegistryImplDeserializer::NAME;
|
||||
constexpr StringLiteral RegistryImplDeserializer::LOCATION;
|
||||
constexpr StringLiteral RegistryImplDeserializer::KIND_BUILTIN;
|
||||
constexpr StringLiteral RegistryImplDeserializer::KIND_FILESYSTEM;
|
||||
constexpr StringLiteral RegistryImplDeserializer::KIND_GIT;
|
||||
constexpr StringLiteral RegistryImplDeserializer::KIND_ARTIFACT;
|
||||
|
||||
struct RegistryDeserializer final : Json::IDeserializer<Registry>
|
||||
{
|
||||
constexpr static StringLiteral PACKAGES = "packages";
|
||||
|
||||
virtual StringView type_name() const override { return "a registry"; }
|
||||
virtual View<StringView> valid_fields() const override;
|
||||
|
||||
virtual Optional<Registry> visit_object(Json::Reader&, const Json::Object&) override;
|
||||
|
||||
explicit RegistryDeserializer(const Path& configuration_directory) : impl_des(configuration_directory) { }
|
||||
|
||||
RegistryImplDeserializer impl_des;
|
||||
};
|
||||
constexpr StringLiteral RegistryDeserializer::PACKAGES;
|
||||
|
||||
View<StringView> RegistryImplDeserializer::valid_fields() const
|
||||
{
|
||||
static const StringView t[] = {KIND, BASELINE, PATH, REPO, REFERENCE, NAME, LOCATION};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_builtin_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryImplDeserializer::KIND,
|
||||
RegistryImplDeserializer::BASELINE,
|
||||
RegistryDeserializer::PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_filesystem_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryImplDeserializer::KIND,
|
||||
RegistryImplDeserializer::BASELINE,
|
||||
RegistryImplDeserializer::PATH,
|
||||
RegistryDeserializer::PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_git_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryImplDeserializer::KIND,
|
||||
RegistryImplDeserializer::BASELINE,
|
||||
RegistryImplDeserializer::REPO,
|
||||
RegistryImplDeserializer::REFERENCE,
|
||||
RegistryDeserializer::PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
View<StringView> valid_artifact_fields()
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryImplDeserializer::KIND,
|
||||
RegistryImplDeserializer::NAME,
|
||||
RegistryImplDeserializer::LOCATION,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
||||
Optional<std::unique_ptr<RegistryImplementation>> RegistryImplDeserializer::visit_null(Json::Reader&)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Optional<std::unique_ptr<RegistryImplementation>> RegistryImplDeserializer::visit_object(Json::Reader& r,
|
||||
const Json::Object& obj)
|
||||
{
|
||||
static Json::StringDeserializer kind_deserializer{"a registry implementation kind"};
|
||||
static Json::StringDeserializer baseline_deserializer{"a baseline"};
|
||||
std::string kind;
|
||||
|
||||
r.required_object_field(type_name(), obj, KIND, kind, kind_deserializer);
|
||||
|
||||
std::unique_ptr<RegistryImplementation> res;
|
||||
|
||||
if (kind == KIND_BUILTIN)
|
||||
{
|
||||
std::string baseline;
|
||||
r.required_object_field("a builtin registry", obj, BASELINE, baseline, baseline_deserializer);
|
||||
if (!is_git_commit_sha(baseline))
|
||||
{
|
||||
r.add_generic_error(
|
||||
"a builtin registry",
|
||||
"The baseline field of builtin registries must be a git commit SHA (40 lowercase hex characters)");
|
||||
}
|
||||
r.check_for_unexpected_fields(obj, valid_builtin_fields(), "a builtin registry");
|
||||
res = std::make_unique<BuiltinGitRegistry>(std::move(baseline));
|
||||
}
|
||||
else if (kind == KIND_FILESYSTEM)
|
||||
{
|
||||
std::string baseline;
|
||||
r.optional_object_field(obj, BASELINE, baseline, baseline_deserializer);
|
||||
r.check_for_unexpected_fields(obj, valid_filesystem_fields(), "a filesystem registry");
|
||||
|
||||
Path p;
|
||||
r.required_object_field("a filesystem registry", obj, PATH, p, Json::PathDeserializer::instance);
|
||||
|
||||
res = std::make_unique<FilesystemRegistry>(config_directory / p, std::move(baseline));
|
||||
}
|
||||
else if (kind == KIND_GIT)
|
||||
{
|
||||
r.check_for_unexpected_fields(obj, valid_git_fields(), "a git registry");
|
||||
|
||||
std::string repo;
|
||||
Json::StringDeserializer repo_des{"a git repository URL"};
|
||||
r.required_object_field("a git registry", obj, REPO, repo, repo_des);
|
||||
|
||||
std::string ref;
|
||||
Json::StringDeserializer ref_des{"a git reference (for example, a branch)"};
|
||||
if (!r.optional_object_field(obj, REFERENCE, ref, ref_des))
|
||||
{
|
||||
ref = "HEAD";
|
||||
}
|
||||
|
||||
std::string baseline;
|
||||
r.required_object_field("a git registry", obj, BASELINE, baseline, baseline_deserializer);
|
||||
|
||||
res = std::make_unique<GitRegistry>(std::move(repo), std::move(ref), std::move(baseline));
|
||||
}
|
||||
else if (kind == KIND_ARTIFACT)
|
||||
{
|
||||
r.check_for_unexpected_fields(obj, valid_artifact_fields(), "an artifacts registry");
|
||||
|
||||
std::string name;
|
||||
r.required_object_field("an artifact registry", obj, NAME, name, Json::IdentifierDeserializer::instance);
|
||||
|
||||
std::string location;
|
||||
Json::StringDeserializer location_des{"an artifacts git repository URL"};
|
||||
r.required_object_field("an artifacts registry", obj, LOCATION, location, location_des);
|
||||
|
||||
res = std::make_unique<ArtifactRegistry>(std::move(name), std::move(location));
|
||||
}
|
||||
else
|
||||
{
|
||||
StringLiteral valid_kinds[] = {KIND_BUILTIN, KIND_FILESYSTEM, KIND_GIT, KIND_ARTIFACT};
|
||||
r.add_generic_error(type_name(),
|
||||
"Field \"kind\" did not have an expected value (expected one of: \"",
|
||||
Strings::join("\", \"", valid_kinds),
|
||||
"\"; found \"",
|
||||
kind,
|
||||
"\")");
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
return std::move(res); // gcc-7 bug workaround redundant move
|
||||
}
|
||||
|
||||
View<StringView> RegistryDeserializer::valid_fields() const
|
||||
{
|
||||
static const StringView t[] = {
|
||||
RegistryImplDeserializer::KIND,
|
||||
RegistryImplDeserializer::BASELINE,
|
||||
RegistryImplDeserializer::PATH,
|
||||
RegistryImplDeserializer::REPO,
|
||||
RegistryImplDeserializer::REFERENCE,
|
||||
RegistryImplDeserializer::NAME,
|
||||
RegistryImplDeserializer::LOCATION,
|
||||
PACKAGES,
|
||||
};
|
||||
return t;
|
||||
}
|
||||
|
||||
Optional<Registry> RegistryDeserializer::visit_object(Json::Reader& r, const Json::Object& obj)
|
||||
{
|
||||
auto impl = impl_des.visit_object(r, obj);
|
||||
|
||||
if (!impl.has_value())
|
||||
{
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
static Json::ArrayDeserializer<Json::PackageNameDeserializer> package_names_deserializer{
|
||||
"an array of package names"};
|
||||
|
||||
std::vector<std::string> packages;
|
||||
if (impl.get()->get()->kind() != RegistryImplDeserializer::KIND_ARTIFACT)
|
||||
{
|
||||
r.required_object_field(type_name(), obj, PACKAGES, packages, package_names_deserializer);
|
||||
}
|
||||
|
||||
return Registry{std::move(packages), std::move(impl).value_or_exit(VCPKG_LINE_INFO)};
|
||||
}
|
||||
|
||||
Path relative_path_to_versions(StringView port_name)
|
||||
{
|
||||
char prefix[] = {port_name.byte_at_index(0), '-', '\0'};
|
||||
|
@ -1285,57 +1053,6 @@ Optional<Path> RegistryImplementation::get_path_to_baseline_version(const VcpkgP
|
|||
return nullopt;
|
||||
}
|
||||
|
||||
// serializers
|
||||
|
||||
Json::Object RegistryImplementation::serialize() const
|
||||
{
|
||||
Json::Object obj;
|
||||
obj.insert(RegistryImplDeserializer::KIND, Json::Value::string(kind()));
|
||||
return obj;
|
||||
}
|
||||
|
||||
Json::Object BuiltinGitRegistry::serialize() const
|
||||
{
|
||||
Json::Object obj;
|
||||
obj.insert(RegistryImplDeserializer::KIND, Json::Value::string("builtin"));
|
||||
obj.insert(RegistryImplDeserializer::BASELINE, Json::Value::string(m_baseline_identifier));
|
||||
return obj;
|
||||
}
|
||||
|
||||
Json::Object BuiltinFilesRegistry::serialize() const
|
||||
{
|
||||
Json::Object obj;
|
||||
obj.insert(RegistryImplDeserializer::KIND, Json::Value::string("builtin"));
|
||||
return obj;
|
||||
}
|
||||
|
||||
Json::Object GitRegistry::serialize() const
|
||||
{
|
||||
Json::Object obj{RegistryImplementation::serialize()};
|
||||
obj.insert(RegistryImplDeserializer::REPO, Json::Value::string(m_repo));
|
||||
obj.insert(RegistryImplDeserializer::BASELINE, Json::Value::string(m_baseline_identifier));
|
||||
return obj;
|
||||
}
|
||||
|
||||
Json::Object FilesystemRegistry::serialize() const
|
||||
{
|
||||
Json::Object obj{RegistryImplementation::serialize()};
|
||||
obj.insert(RegistryImplDeserializer::PATH, Json::Value::string(m_path.generic_u8string()));
|
||||
if (!m_baseline_identifier.empty())
|
||||
{
|
||||
obj.insert(RegistryImplDeserializer::BASELINE, Json::Value::string(m_baseline_identifier));
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
Json::Object ArtifactRegistry::serialize() const
|
||||
{
|
||||
Json::Object obj{RegistryImplementation::serialize()};
|
||||
obj.insert(RegistryImplDeserializer::NAME, Json::Value::string(m_name));
|
||||
obj.insert(RegistryImplDeserializer::LOCATION, Json::Value::string(m_location));
|
||||
return obj;
|
||||
}
|
||||
|
||||
namespace vcpkg
|
||||
{
|
||||
constexpr StringLiteral VersionDbEntryDeserializer::GIT_TREE;
|
||||
|
@ -1486,26 +1203,12 @@ namespace vcpkg
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Json::IDeserializer<std::unique_ptr<RegistryImplementation>>>
|
||||
get_registry_implementation_deserializer(const Path& configuration_directory)
|
||||
{
|
||||
return std::make_unique<RegistryImplDeserializer>(configuration_directory);
|
||||
}
|
||||
std::unique_ptr<Json::IDeserializer<std::vector<Registry>>> get_registry_array_deserializer(
|
||||
const Path& configuration_directory)
|
||||
{
|
||||
return std::make_unique<Json::ArrayDeserializer<RegistryDeserializer>>(
|
||||
"an array of registries", RegistryDeserializer(configuration_directory));
|
||||
}
|
||||
|
||||
Registry::Registry(std::vector<std::string>&& packages, std::unique_ptr<RegistryImplementation>&& impl)
|
||||
: packages_(std::move(packages)), implementation_(std::move(impl))
|
||||
{
|
||||
Checks::check_exit(VCPKG_LINE_INFO, implementation_ != nullptr);
|
||||
}
|
||||
|
||||
RegistrySet::RegistrySet() : default_registry_(std::make_unique<BuiltinFilesRegistry>()) { }
|
||||
|
||||
const RegistryImplementation* RegistrySet::registry_for_port(StringView name) const
|
||||
{
|
||||
for (const auto& registry : registries())
|
||||
|
@ -1526,50 +1229,10 @@ namespace vcpkg
|
|||
return impl->get_baseline_version(paths, port_name);
|
||||
}
|
||||
|
||||
void RegistrySet::add_registry(Registry&& r) { registries_.push_back(std::move(r)); }
|
||||
|
||||
void RegistrySet::set_default_registry(std::unique_ptr<RegistryImplementation>&& r)
|
||||
{
|
||||
default_registry_ = std::move(r);
|
||||
}
|
||||
void RegistrySet::set_default_registry(std::nullptr_t) { default_registry_.reset(); }
|
||||
|
||||
bool RegistrySet::is_default_builtin_registry() const
|
||||
{
|
||||
return default_registry_ && default_registry_->kind() == BuiltinFilesRegistry::s_kind;
|
||||
}
|
||||
void RegistrySet::set_default_builtin_registry_baseline(StringView baseline)
|
||||
{
|
||||
if (auto default_registry = default_registry_.get())
|
||||
{
|
||||
const auto k = default_registry->kind();
|
||||
if (k == BuiltinFilesRegistry::s_kind)
|
||||
{
|
||||
default_registry_ = std::make_unique<BuiltinGitRegistry>(baseline.to_string());
|
||||
}
|
||||
else if (k == BuiltinGitRegistry::s_kind)
|
||||
{
|
||||
print2(Color::warning,
|
||||
R"(warning: attempting to set builtin baseline in both vcpkg.json and vcpkg-configuration.json
|
||||
(only one of these should be used; the baseline from vcpkg-configuration.json will be used))");
|
||||
}
|
||||
else
|
||||
{
|
||||
vcpkg::printf(
|
||||
Color::warning,
|
||||
"warning: the default registry has been replaced with a %s registry, but `builtin-baseline` "
|
||||
"is specified in vcpkg.json. This field will have no effect.\n",
|
||||
k);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print2(Color::warning,
|
||||
"warning: the default registry has been disabled, but `builtin-baseline` is specified in "
|
||||
"vcpkg.json. This field will have no effect.\n");
|
||||
}
|
||||
}
|
||||
|
||||
bool RegistrySet::has_modifications() const { return !registries_.empty() || !is_default_builtin_registry(); }
|
||||
|
||||
ExpectedS<std::vector<std::pair<SchemedVersion, std::string>>> get_builtin_versions(const VcpkgPaths& paths,
|
||||
|
@ -1610,4 +1273,25 @@ namespace vcpkg
|
|||
|
||||
return sv.size() == 40 && std::all_of(sv.begin(), sv.end(), is_lcase_ascii_hex);
|
||||
}
|
||||
|
||||
std::unique_ptr<RegistryImplementation> make_builtin_registry() { return std::make_unique<BuiltinFilesRegistry>(); }
|
||||
std::unique_ptr<RegistryImplementation> make_builtin_registry(std::string baseline)
|
||||
{
|
||||
return std::make_unique<BuiltinGitRegistry>(std::move(baseline));
|
||||
}
|
||||
std::unique_ptr<RegistryImplementation> make_git_registry(std::string repo,
|
||||
std::string reference,
|
||||
std::string baseline)
|
||||
{
|
||||
return std::make_unique<GitRegistry>(std::move(repo), std::move(reference), std::move(baseline));
|
||||
}
|
||||
std::unique_ptr<RegistryImplementation> make_filesystem_registry(Path path, std::string baseline)
|
||||
{
|
||||
return std::make_unique<FilesystemRegistry>(std::move(path), std::move(baseline));
|
||||
}
|
||||
std::unique_ptr<RegistryImplementation> make_artifact_registry(std::string name, std::string location)
|
||||
{
|
||||
return std::make_unique<ArtifactRegistry>(std::move(name), std::move(location));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <vcpkg/base/util.h>
|
||||
|
||||
#include <vcpkg/configuration.h>
|
||||
#include <vcpkg/documentation.h>
|
||||
#include <vcpkg/metrics.h>
|
||||
#include <vcpkg/packagespec.h>
|
||||
#include <vcpkg/platform-expression.h>
|
||||
|
@ -993,6 +994,61 @@ namespace vcpkg
|
|||
constexpr StringLiteral ManifestDeserializer::BUILTIN_BASELINE;
|
||||
constexpr StringLiteral ManifestDeserializer::VCPKG_CONFIGURATION;
|
||||
|
||||
// Extracts just the configuration information from a manifest object
|
||||
struct ManifestConfigurationDeserializer final : Json::IDeserializer<ManifestConfiguration>
|
||||
{
|
||||
virtual StringView type_name() const override { return "a manifest"; }
|
||||
|
||||
virtual Optional<ManifestConfiguration> visit_object(Json::Reader& r, const Json::Object& obj) override
|
||||
{
|
||||
Optional<ManifestConfiguration> x;
|
||||
ManifestConfiguration& ret = x.emplace();
|
||||
if (!r.optional_object_field(obj,
|
||||
ManifestDeserializer::VCPKG_CONFIGURATION,
|
||||
ret.config.emplace(),
|
||||
get_configuration_deserializer()))
|
||||
{
|
||||
ret.config = nullopt;
|
||||
}
|
||||
if (!r.optional_object_field(obj,
|
||||
ManifestDeserializer::BUILTIN_BASELINE,
|
||||
ret.builtin_baseline.emplace(),
|
||||
BaselineCommitDeserializer::instance))
|
||||
{
|
||||
ret.builtin_baseline = nullopt;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
static ManifestConfigurationDeserializer instance;
|
||||
};
|
||||
ManifestConfigurationDeserializer ManifestConfigurationDeserializer::instance;
|
||||
|
||||
ExpectedS<struct ManifestConfiguration> parse_manifest_configuration(StringView origin,
|
||||
const Json::Object& manifest)
|
||||
{
|
||||
Json::Reader reader;
|
||||
|
||||
auto res = reader.visit(manifest, ManifestConfigurationDeserializer::instance);
|
||||
|
||||
if (!reader.errors().empty())
|
||||
{
|
||||
std::string ret = "Error: in the manifest ";
|
||||
Strings::append(ret, origin, "\nwhile obtaining configuration information from the manifest:\n");
|
||||
for (auto&& err : reader.errors())
|
||||
{
|
||||
Strings::append(ret, " ", err, "\n");
|
||||
}
|
||||
print2("See ", docs::registries_url, " for more information.\n");
|
||||
print2("See ", docs::manifests_url, " for more information.\n");
|
||||
return std::move(ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::move(res).value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
}
|
||||
|
||||
SourceControlFile SourceControlFile::clone() const
|
||||
{
|
||||
SourceControlFile ret;
|
||||
|
@ -1370,19 +1426,18 @@ namespace vcpkg
|
|||
if (auto configuration = scf.core_paragraph->vcpkg_configuration.get())
|
||||
{
|
||||
Json::Reader reader;
|
||||
auto maybe_configuration = reader.visit(*configuration, *vcpkg::make_configuration_deserializer(""));
|
||||
auto maybe_configuration = reader.visit(*configuration, get_configuration_deserializer());
|
||||
if (!reader.errors().empty())
|
||||
{
|
||||
print2(Color::error, "Errors occurred while parsing ", ManifestDeserializer::VCPKG_CONFIGURATION, "\n");
|
||||
for (auto&& msg : reader.errors())
|
||||
print2(" ", msg, '\n');
|
||||
|
||||
print2("See https://github.com/Microsoft/vcpkg/tree/master/docs/users/registries.md for "
|
||||
"more information.\n");
|
||||
print2("See ", docs::registries_url, " for more information.\n");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
obj.insert(ManifestDeserializer::VCPKG_CONFIGURATION,
|
||||
serialize_configuration(maybe_configuration.value_or_exit(VCPKG_LINE_INFO)));
|
||||
maybe_configuration.value_or_exit(VCPKG_LINE_INFO).serialize());
|
||||
}
|
||||
|
||||
obj.insert(ManifestDeserializer::NAME, Json::Value::string(scf.core_paragraph->name));
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <vcpkg/commands.h>
|
||||
#include <vcpkg/commands.version.h>
|
||||
#include <vcpkg/configuration.h>
|
||||
#include <vcpkg/documentation.h>
|
||||
#include <vcpkg/globalstate.h>
|
||||
#include <vcpkg/metrics.h>
|
||||
#include <vcpkg/packagespec.h>
|
||||
|
@ -57,36 +58,6 @@ namespace
|
|||
|
||||
namespace vcpkg
|
||||
{
|
||||
static Configuration deserialize_configuration(const Json::Object& obj,
|
||||
const VcpkgCmdArguments& args,
|
||||
const Path& filepath)
|
||||
{
|
||||
Json::Reader reader;
|
||||
auto deserializer = make_configuration_deserializer(filepath.parent_path());
|
||||
|
||||
auto parsed_config_opt = reader.visit(obj, *deserializer);
|
||||
if (!reader.errors().empty())
|
||||
{
|
||||
print2(Color::error, "Errors occurred while parsing ", filepath, "\n");
|
||||
for (auto&& msg : reader.errors())
|
||||
print2(" ", msg, '\n');
|
||||
|
||||
print2("See https://github.com/Microsoft/vcpkg/tree/master/docs/users/registries.md for "
|
||||
"more information.\n");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
parsed_config_opt.get()->validate_feature_flags(args.feature_flag_settings());
|
||||
|
||||
return std::move(parsed_config_opt).value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
struct ManifestAndConfig
|
||||
{
|
||||
Path config_directory;
|
||||
Configuration config;
|
||||
};
|
||||
|
||||
static std::pair<Json::Object, Json::JsonStyle> load_manifest(const Filesystem& fs, const Path& manifest_dir)
|
||||
{
|
||||
std::error_code ec;
|
||||
|
@ -116,69 +87,129 @@ namespace vcpkg
|
|||
return {std::move(manifest_value.first.object()), std::move(manifest_value.second)};
|
||||
}
|
||||
|
||||
struct ConfigAndPath
|
||||
static Optional<ManifestConfiguration> config_from_manifest(
|
||||
const Path& manifest_path, const Optional<std::pair<Json::Object, Json::JsonStyle>>& manifest_doc)
|
||||
{
|
||||
Path config_directory;
|
||||
Configuration config;
|
||||
};
|
||||
if (auto manifest = manifest_doc.get())
|
||||
{
|
||||
return parse_manifest_configuration(manifest_path, manifest->first).value_or_exit(VCPKG_LINE_INFO);
|
||||
}
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
// doesn't yet implement searching upwards for configurations, nor inheritance of configurations
|
||||
static ConfigAndPath load_configuration(const Filesystem& fs,
|
||||
const VcpkgCmdArguments& args,
|
||||
const Path& vcpkg_root,
|
||||
const Path& manifest_dir,
|
||||
const Optional<Json::Object>& configuration_from_manifest)
|
||||
static Optional<Configuration> config_from_json(const Path& config_path, const Filesystem& fs)
|
||||
{
|
||||
Path config_dir;
|
||||
if (manifest_dir.empty())
|
||||
if (!fs.exists(config_path, VCPKG_LINE_INFO))
|
||||
{
|
||||
// classic mode
|
||||
config_dir = vcpkg_root;
|
||||
}
|
||||
else
|
||||
{
|
||||
// manifest mode
|
||||
config_dir = manifest_dir;
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
auto path_to_config = config_dir / "vcpkg-configuration.json";
|
||||
if (!fs.exists(path_to_config, IgnoreErrors{}))
|
||||
{
|
||||
if (!configuration_from_manifest.has_value())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return {std::move(config_dir),
|
||||
deserialize_configuration(
|
||||
configuration_from_manifest.value_or_exit(VCPKG_LINE_INFO), args, manifest_dir / "vcpkg.json")};
|
||||
}
|
||||
|
||||
if (configuration_from_manifest.has_value())
|
||||
{
|
||||
print2(Color::error,
|
||||
"Ambiguous vcpkg configuration provided by both manifest and configuration file.\n"
|
||||
"-- Delete configuration file \"",
|
||||
path_to_config,
|
||||
"\"\n"
|
||||
"-- Or remove \"vcpkg-configuration\" from the manifest file \"",
|
||||
manifest_dir / "vcpkg.json",
|
||||
"\".");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
auto parsed_config = Json::parse_file(VCPKG_LINE_INFO, fs, path_to_config);
|
||||
auto parsed_config = Json::parse_file(VCPKG_LINE_INFO, fs, config_path);
|
||||
if (!parsed_config.first.is_object())
|
||||
{
|
||||
print2(Color::error,
|
||||
"Failed to parse ",
|
||||
path_to_config,
|
||||
": configuration files must have a top-level object\n");
|
||||
print2(
|
||||
Color::error, "Failed to parse ", config_path, ": configuration files must have a top-level object\n");
|
||||
msg::println(Color::error, msg::msgSeeURL, msg::url = docs::registries_url);
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
auto config_obj = std::move(parsed_config.first.object());
|
||||
const auto& obj = parsed_config.first.object();
|
||||
|
||||
return {std::move(config_dir), deserialize_configuration(config_obj, args, path_to_config)};
|
||||
Json::Reader reader;
|
||||
auto parsed_config_opt = reader.visit(obj, get_configuration_deserializer());
|
||||
if (!reader.errors().empty())
|
||||
{
|
||||
print2(Color::error, "Error: while parsing ", config_path, "\n");
|
||||
for (auto&& msg : reader.errors())
|
||||
print2(" ", msg, '\n');
|
||||
|
||||
print2("See ", docs::registries_url, " for more information.\n");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
return parsed_config_opt;
|
||||
}
|
||||
|
||||
static Configuration merge_validate_configs(Optional<ManifestConfiguration>&& manifest_data,
|
||||
const Path& manifest_dir,
|
||||
Optional<Configuration>&& config_data,
|
||||
const Path& config_dir,
|
||||
const VcpkgPaths& paths)
|
||||
{
|
||||
Configuration ret;
|
||||
|
||||
if (auto manifest = manifest_data.get())
|
||||
{
|
||||
if (auto config = manifest->config.get())
|
||||
{
|
||||
print2(Color::warning,
|
||||
"Embedding `vcpkg-configuration` in a manifest file is an EXPERIMENTAL feature.\n");
|
||||
|
||||
if (manifest->builtin_baseline && config->default_reg)
|
||||
{
|
||||
print2(Color::error,
|
||||
"Error: Specifying vcpkg-configuration.default-registry in a manifest file conflicts with "
|
||||
"builtin-baseline.\nPlease remove one of these conflicting settings.\n");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
config->validate_as_active();
|
||||
|
||||
if (config_data.has_value())
|
||||
{
|
||||
print2(Color::error,
|
||||
"Ambiguous vcpkg configuration provided by both manifest and configuration file.\n"
|
||||
"-- Delete configuration file \"",
|
||||
config_dir / "vcpkg-configuration.json",
|
||||
"\"\n"
|
||||
"-- Or remove \"vcpkg-configuration\" from the manifest file \"",
|
||||
manifest_dir / "vcpkg.json",
|
||||
"\".");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
|
||||
ret = std::move(*config);
|
||||
}
|
||||
}
|
||||
|
||||
if (auto config = config_data.get())
|
||||
{
|
||||
config->validate_as_active();
|
||||
|
||||
ret = std::move(*config);
|
||||
}
|
||||
|
||||
if (auto manifest = manifest_data.get())
|
||||
{
|
||||
if (auto p_baseline = manifest->builtin_baseline.get())
|
||||
{
|
||||
LockGuardPtr<Metrics>(g_metrics)->track_property("manifest_baseline", "defined");
|
||||
if (!is_git_commit_sha(*p_baseline))
|
||||
{
|
||||
LockGuardPtr<Metrics>(g_metrics)->track_property("versioning-error-baseline", "defined");
|
||||
Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
|
||||
"Error: the top-level builtin-baseline%s was not a valid commit sha: "
|
||||
"expected 40 lowercase hexadecimal characters.\n%s\n",
|
||||
Strings::concat(" (", *p_baseline, ')'),
|
||||
paths.get_current_git_sha_baseline_message());
|
||||
}
|
||||
|
||||
if (ret.default_reg)
|
||||
{
|
||||
print2(Color::warning,
|
||||
"warning: attempting to set builtin-baseline in vcpkg.json while overriding the "
|
||||
"default-registry in vcpkg-configuration.json.\n The default-registry from "
|
||||
"vcpkg-configuration.json will be used.");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& default_reg = ret.default_reg.emplace();
|
||||
default_reg.kind = "builtin";
|
||||
default_reg.baseline = std::move(*p_baseline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace details
|
||||
|
@ -265,7 +296,9 @@ namespace vcpkg
|
|||
|
||||
Optional<std::pair<Json::Object, Json::JsonStyle>> m_manifest_doc;
|
||||
Path m_manifest_path;
|
||||
Path m_config_dir;
|
||||
Configuration m_config;
|
||||
std::unique_ptr<RegistrySet> m_registry_set;
|
||||
|
||||
Downloads::DownloadManager m_download_manager;
|
||||
|
||||
|
@ -448,6 +481,7 @@ namespace vcpkg
|
|||
|
||||
if (manifest_root_dir.empty())
|
||||
{
|
||||
m_pimpl->m_config_dir = root;
|
||||
if (!m_pimpl->m_readonly)
|
||||
{
|
||||
m_pimpl->installed =
|
||||
|
@ -458,6 +492,7 @@ namespace vcpkg
|
|||
{
|
||||
Debug::print("Using manifest-root: ", manifest_root_dir, '\n');
|
||||
|
||||
m_pimpl->m_config_dir = manifest_root_dir;
|
||||
m_pimpl->installed = process_output_directory(
|
||||
filesystem, args.install_root_dir.get(), manifest_root_dir / "vcpkg_installed");
|
||||
|
||||
|
@ -486,59 +521,23 @@ namespace vcpkg
|
|||
m_pimpl->m_manifest_path = manifest_root_dir / "vcpkg.json";
|
||||
}
|
||||
|
||||
vcpkg::Optional<Json::Object> configuration_from_manifest;
|
||||
if (auto manifest = m_pimpl->m_manifest_doc.get())
|
||||
{
|
||||
auto manifest_obj = manifest->first;
|
||||
if (auto config_obj = manifest_obj.get("vcpkg-configuration"))
|
||||
{
|
||||
print2(Color::warning,
|
||||
"Embedding `vcpkg-configuration` in a manifest file is an EXPERIMENTAL feature.\n"
|
||||
"Loading configuration from: ",
|
||||
m_pimpl->m_manifest_path,
|
||||
"\n");
|
||||
auto maybe_manifest_config = config_from_manifest(m_pimpl->m_manifest_path, m_pimpl->m_manifest_doc);
|
||||
auto maybe_config_json = config_from_json(m_pimpl->m_config_dir / "vcpkg-configuration.json", filesystem);
|
||||
|
||||
if (!config_obj->is_object())
|
||||
{
|
||||
print2(Color::error,
|
||||
"Failed to parse ",
|
||||
m_pimpl->m_manifest_path,
|
||||
": vcpkg-configuration must be an object\n");
|
||||
Checks::exit_fail(VCPKG_LINE_INFO);
|
||||
}
|
||||
m_pimpl->m_config = merge_validate_configs(std::move(maybe_manifest_config),
|
||||
manifest_root_dir,
|
||||
std::move(maybe_config_json),
|
||||
m_pimpl->m_config_dir,
|
||||
*this);
|
||||
|
||||
configuration_from_manifest = make_optional(config_obj->object());
|
||||
}
|
||||
}
|
||||
auto config_file = load_configuration(filesystem, args, root, manifest_root_dir, configuration_from_manifest);
|
||||
if (auto manifest = m_pimpl->m_manifest_doc.get())
|
||||
{
|
||||
if (auto p_baseline = manifest->first.get("builtin-baseline"))
|
||||
{
|
||||
LockGuardPtr<Metrics>(g_metrics)->track_property("manifest_baseline", "defined");
|
||||
if (!p_baseline->is_string() || !is_git_commit_sha(p_baseline->string()))
|
||||
{
|
||||
std::string baseline_in_error;
|
||||
if (p_baseline->is_string())
|
||||
{
|
||||
baseline_in_error = Strings::concat(" (", p_baseline->string(), ')');
|
||||
}
|
||||
LockGuardPtr<Metrics>(g_metrics)->track_property("versioning-error-baseline", "defined");
|
||||
Checks::exit_maybe_upgrade(VCPKG_LINE_INFO,
|
||||
"Error: the top-level builtin-baseline%s was not a valid commit sha: "
|
||||
"expected 40 lowercase hexadecimal characters.\n%s\n",
|
||||
baseline_in_error,
|
||||
get_current_git_sha_baseline_message());
|
||||
}
|
||||
|
||||
config_file.config.registry_set.set_default_builtin_registry_baseline(p_baseline->string());
|
||||
}
|
||||
m_pimpl->m_registry_set = m_pimpl->m_config.instantiate_registry_set(m_pimpl->m_config_dir);
|
||||
}
|
||||
|
||||
// metrics from configuration
|
||||
{
|
||||
auto default_registry = config_file.config.registry_set.default_registry();
|
||||
auto other_registries = config_file.config.registry_set.registries();
|
||||
auto default_registry = m_pimpl->m_registry_set->default_registry();
|
||||
auto other_registries = m_pimpl->m_registry_set->registries();
|
||||
LockGuardPtr<Metrics> metrics(g_metrics);
|
||||
if (default_registry)
|
||||
{
|
||||
|
@ -561,9 +560,6 @@ namespace vcpkg
|
|||
}
|
||||
}
|
||||
|
||||
config_root_dir = std::move(config_file.config_directory);
|
||||
m_pimpl->m_config = std::move(config_file.config);
|
||||
|
||||
m_pimpl->buildtrees = maybe_get_tmp_path(args.buildtrees_root_dir.get(), "buildtrees", "blds", VCPKG_LINE_INFO);
|
||||
m_pimpl->packages = maybe_get_tmp_path(args.packages_root_dir.get(), "packages", "pkgs", VCPKG_LINE_INFO);
|
||||
|
||||
|
@ -1242,10 +1238,10 @@ namespace vcpkg
|
|||
}
|
||||
}
|
||||
|
||||
const Configuration& VcpkgPaths::get_configuration() const { return m_pimpl->m_config; }
|
||||
void VcpkgPaths::set_builtin_baseline(const std::string& baseline) const
|
||||
const RegistrySet& VcpkgPaths::get_registry_set() const
|
||||
{
|
||||
m_pimpl->m_config.registry_set.set_default_builtin_registry_baseline(baseline);
|
||||
Checks::check_exit(VCPKG_LINE_INFO, m_pimpl->m_registry_set != nullptr);
|
||||
return *m_pimpl->m_registry_set;
|
||||
}
|
||||
const Downloads::DownloadManager& VcpkgPaths::get_download_manager() const { return m_pimpl->m_download_manager; }
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче