Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow filesystem registry from git repository #1544

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions docs/vcpkg-schema-definitions.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"enum": [
"builtin",
"git",
"filesystem-from-git",
"filesystem"
]
},
Expand All @@ -146,6 +147,9 @@
{
"$ref": "#/definitions/git-registry"
},
{
"$ref": "#/definitions/filesystem-from-git-registry"
},
{
"$ref": "#/definitions/filesystem-registry"
}
Expand Down Expand Up @@ -650,6 +654,56 @@
},
"else": false
},
"filesystem-from-git-registry": {
"type": "object",
"description": "A port registry backed by a filesystem layout and a git repo.",
"if": {
"properties": {
"kind": {
"type": "string",
"enum": [
"filesystem-from-git"
]
}
},
"required": [
"kind"
]
},
"then": {
"properties": {
"kind": {
"type": "string",
"enum": [
"filesystem-from-git"
]
},
"repository": {
"type": "string",
"description": "The URI or SSH entry to clone from. (as if by `git clone`)"
},
"baseline": {
"description": "The SHA that will be checked out to find default versions for ports from this registry.",
"$ref": "#/definitions/sha1"
},
"reference": {
"type": "string",
"description": "The ref to fetch when cloning this git registry."
},
"packages": true
},
"required": [
"kind",
"repository",
"baseline"
],
"patternProperties": {
"^\\$": {}
},
"additionalProperties": false
},
"else": false
},
"has-one-version": {
"type": "object",
"oneOf": [
Expand Down Expand Up @@ -846,6 +900,7 @@
"enum": [
"builtin",
"git",
"filesystem-from-git",
"filesystem",
"artifact"
]
Expand Down Expand Up @@ -880,6 +935,9 @@
{
"$ref": "#/definitions/git-registry"
},
{
"$ref": "#/definitions/filesystem-from-git-registry"
},
{
"$ref": "#/definitions/filesystem-registry"
}
Expand Down
1 change: 1 addition & 0 deletions include/vcpkg/base/contractual-constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace vcpkg
inline constexpr StringLiteral JsonIdFeatures = "features";
inline constexpr StringLiteral JsonIdFiles = "files";
inline constexpr StringLiteral JsonIdFilesystem = "filesystem";
inline constexpr StringLiteral JsonIdFilesystemFromGit = "filesystem-from-git";
inline constexpr StringLiteral JsonIdGit = "git";
inline constexpr StringLiteral JsonIdGitTree = "git-tree";
inline constexpr StringLiteral JsonIdHomepage = "homepage";
Expand Down
1 change: 1 addition & 0 deletions include/vcpkg/base/message-data.inc.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ DECLARE_MESSAGE(ADictionaryOfContacts, (), "", "a dictionary of contacts")
DECLARE_MESSAGE(AFeature, (), "", "a feature")
DECLARE_MESSAGE(AFeatureName, (), "", "a feature name")
DECLARE_MESSAGE(AFilesystemRegistry, (), "", "a filesystem registry")
DECLARE_MESSAGE(AFilesystemRegistryFromGit, (), "", "a filesystem registry from git")
DECLARE_MESSAGE(AGitObjectSha, (), "", "a git object SHA")
DECLARE_MESSAGE(AGitReference, (), "", "a git reference (for example, a branch)")
DECLARE_MESSAGE(AGitRegistry, (), "", "a git registry")
Expand Down
4 changes: 4 additions & 0 deletions include/vcpkg/registries.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ namespace vcpkg
std::string repo,
std::string reference,
std::string baseline);
std::unique_ptr<RegistryImplementation> make_filesystem_from_git_registry(const VcpkgPaths& paths,
std::string repo,
std::string reference,
std::string baseline);
std::unique_ptr<RegistryImplementation> make_filesystem_registry(const ReadOnlyFilesystem& fs,
Path path,
std::string baseline);
Expand Down
1 change: 1 addition & 0 deletions locales/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"AFeature": "a feature",
"AFeatureName": "a feature name",
"AFilesystemRegistry": "a filesystem registry",
"AFilesystemRegistryFromGit": "a filesystem registry from git",
"AGitObjectSha": "a git object SHA",
"AGitReference": "a git reference (for example, a branch)",
"AGitRegistry": "a git registry",
Expand Down
2 changes: 1 addition & 1 deletion src/vcpkg-test/configmetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ test: error: $ (a configuration object): The default registry cannot be an artif
}]
})json";
check_errors(raw_bad_kind, R"(
test: error: $.registries[0] (a registry): "kind" did not have an expected value: (expected one of: builtin, filesystem, git, artifact; found custom)
test: error: $.registries[0] (a registry): "kind" did not have an expected value: (expected one of: builtin, filesystem, filesystem-from-git, git, artifact; found custom)
test: error: $.registries[0]: mismatched type: expected a registry
)");

Expand Down
36 changes: 35 additions & 1 deletion src/vcpkg/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,28 @@ namespace

r.check_for_unexpected_fields(obj, valid_filesystem_fields, msg::format(msgAFilesystemRegistry));
}
else if (kind == JsonIdFilesystemFromGit)
{
r.required_object_field(msg::format(msgAFilesystemRegistryFromGit),
obj,
JsonIdRepository,
res.repo.emplace(),
GitUrlDeserializer::instance);

if (!r.optional_object_field(
obj, JsonIdReference, res.reference.emplace(), GitReferenceDeserializer::instance))
{
res.reference = nullopt;
}

r.required_object_field(msg::format(msgAFilesystemRegistryFromGit),
obj,
JsonIdBaseline,
res.baseline.emplace(),
BaselineShaDeserializer::instance);

r.check_for_unexpected_fields(obj, valid_git_fields, msg::format(msgAFilesystemRegistryFromGit));
}
else if (kind == JsonIdGit)
{
r.required_object_field(
Expand Down Expand Up @@ -272,7 +294,8 @@ namespace
}
else
{
StringLiteral valid_kinds[] = {JsonIdBuiltin, JsonIdFilesystem, JsonIdGit, JsonIdArtifact};
StringLiteral valid_kinds[] = {
JsonIdBuiltin, JsonIdFilesystem, JsonIdFilesystemFromGit, JsonIdGit, JsonIdArtifact};
r.add_generic_error(type_name(),
msg::format(msgFieldKindDidNotHaveExpectedValue,
msg::expected = Strings::join(", ", valid_kinds),
Expand Down Expand Up @@ -753,6 +776,10 @@ namespace vcpkg
{
return path.value_or_exit(VCPKG_LINE_INFO);
}
if (kind == JsonIdFilesystemFromGit)
{
return repo.value_or_exit(VCPKG_LINE_INFO);
}
if (kind == JsonIdGit)
{
return repo.value_or_exit(VCPKG_LINE_INFO);
Expand Down Expand Up @@ -902,6 +929,13 @@ namespace vcpkg
config.reference.value_or("HEAD"),
config.baseline.value_or_exit(VCPKG_LINE_INFO));
}
else if (*k == JsonIdFilesystemFromGit)
{
return make_filesystem_from_git_registry(paths,
config.repo.value_or_exit(VCPKG_LINE_INFO),
config.reference.value_or("HEAD"),
config.baseline.value_or_exit(VCPKG_LINE_INFO));
}
else if (*k == JsonIdFilesystem)
{
return make_filesystem_registry(paths.get_filesystem(),
Expand Down
57 changes: 52 additions & 5 deletions src/vcpkg/registries.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,14 @@ namespace
mutable PortVersionsGitTreesStructOfArrays last_loaded;
};

struct GitRegistry final : RegistryImplementation
struct GitRegistry : RegistryImplementation
{
GitRegistry(const VcpkgPaths& paths, std::string&& repo, std::string&& reference, std::string&& baseline)
: m_paths(paths)
, m_repo(std::move(repo))
, m_reference(std::move(reference))
, m_baseline_identifier(std::move(baseline))
, m_remote_root_path(FileVersions.to_string())
{
}

Expand All @@ -281,7 +282,7 @@ namespace

ExpectedL<Optional<Version>> get_baseline_version(StringView) const override;

private:
protected:
friend GitRegistryEntry;

const ExpectedL<LockFile::Entry>& get_lock_entry() const
Expand All @@ -290,7 +291,7 @@ namespace
[this]() { return m_paths.get_installed_lockfile().get_or_fetch(m_paths, m_repo, m_reference); });
}

const ExpectedL<Path>& get_versions_tree_path() const
virtual const ExpectedL<Path>& get_versions_tree_path() const
{
return m_versions_tree.get([this]() -> ExpectedL<Path> {
auto& maybe_lock_entry = get_lock_entry();
Expand All @@ -306,8 +307,8 @@ namespace
return std::move(maybe_up_to_date).error();
}

auto maybe_tree = m_paths.git_find_object_id_for_remote_registry_path(lock_entry->commit_id(),
FileVersions.to_string());
auto maybe_tree =
m_paths.git_find_object_id_for_remote_registry_path(lock_entry->commit_id(), m_remote_root_path);
auto tree = maybe_tree.get();
if (!tree)
{
Expand Down Expand Up @@ -397,6 +398,23 @@ namespace
mutable Optional<Path> m_stale_versions_tree;
DelayedInit<ExpectedL<Path>> m_versions_tree;
DelayedInit<ExpectedL<Baseline>> m_baseline;
std::string m_remote_root_path;
};

struct FilesystemFromGitRegistry final : GitRegistry
{
FilesystemFromGitRegistry(const VcpkgPaths& paths,
std::string&& repo,
std::string&& reference,
std::string&& baseline)
: GitRegistry(paths, std::move(repo), std::move(reference), std::move(baseline))
{
m_remote_root_path = "";
}

StringLiteral kind() const override { return "filesystem-from-git"; }

ExpectedL<std::unique_ptr<RegistryEntry>> get_port_entry(StringView) const override;
};

struct BuiltinPortTreeRegistryEntry final : RegistryEntry
Expand Down Expand Up @@ -877,6 +895,27 @@ namespace
}
// } FilesystemRegistry::RegistryImplementation

// { FilesystemFromGitRegistry::RegistryImplementation
ExpectedL<std::unique_ptr<RegistryEntry>> FilesystemFromGitRegistry::get_port_entry(StringView port_name) const
{
return get_versions_tree_path().then([this, &port_name](const Path& live_vcb) {
return load_filesystem_versions_file(
m_paths.get_filesystem(), live_vcb / Path(FileVersions), port_name, live_vcb)
.then([&](Optional<std::vector<FilesystemVersionDbEntry>>&& maybe_version_entries)
-> ExpectedL<std::unique_ptr<RegistryEntry>> {
auto version_entries = maybe_version_entries.get();
if (!version_entries)
{
return std::unique_ptr<RegistryEntry>{};
}

return std::make_unique<FilesystemRegistryEntry>(
m_paths.get_filesystem(), port_name, std::move(*version_entries));
});
});
}
// } FilesystemFromGitRegistry::RegistryImplementation

// { GitRegistry::RegistryImplementation
ExpectedL<std::unique_ptr<RegistryEntry>> GitRegistry::get_port_entry(StringView port_name) const
{
Expand Down Expand Up @@ -1744,6 +1783,14 @@ namespace vcpkg
{
return std::make_unique<GitRegistry>(paths, std::move(repo), std::move(reference), std::move(baseline));
}
std::unique_ptr<RegistryImplementation> make_filesystem_from_git_registry(const VcpkgPaths& paths,
std::string repo,
std::string reference,
std::string baseline)
{
return std::make_unique<FilesystemFromGitRegistry>(
paths, std::move(repo), std::move(reference), std::move(baseline));
}
std::unique_ptr<RegistryImplementation> make_filesystem_registry(const ReadOnlyFilesystem& fs,
Path path,
std::string baseline)
Expand Down
Loading