Skip to content

Commit f3c4104

Browse files
committed
feat(project): add deterministic dependency resolver
1 parent d84dd18 commit f3c4104

4 files changed

Lines changed: 1272 additions & 0 deletions

File tree

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/** @file Resolver.hpp
2+
* Pure deterministic resolution over caller-supplied immutable metadata.
3+
*/
4+
#ifndef VIX_CLI_PROJECT_NATIVE_RESOLVER_HPP
5+
#define VIX_CLI_PROJECT_NATIVE_RESOLVER_HPP
6+
7+
#include <optional>
8+
#include <string>
9+
#include <vector>
10+
11+
#include <vix/cli/project/native/Lockfile.hpp>
12+
#include <vix/cli/project/native/Models.hpp>
13+
14+
namespace vix::cli::project::native
15+
{
16+
struct RegistryCandidate
17+
{
18+
RegistryPackageIdentity identity;
19+
Version version;
20+
std::string contentDigest;
21+
PackageContract contract;
22+
};
23+
24+
struct GitResolution
25+
{
26+
std::string normalizedRepository;
27+
GitRevisionRequirement requestedRevision;
28+
std::string commit;
29+
std::string contentDigest;
30+
PackageContract contract;
31+
};
32+
33+
// Implementations are metadata-only adapters. This interface performs no
34+
// I/O itself; tests and later source adapters supply immutable records.
35+
class ResolutionMetadataProvider
36+
{
37+
public:
38+
virtual ~ResolutionMetadataProvider() = default;
39+
[[nodiscard]] virtual std::vector<RegistryCandidate> registry_candidates(
40+
const RegistryPackageIdentity &identity) const = 0;
41+
[[nodiscard]] virtual std::vector<GitResolution> git_resolutions(
42+
const std::string &normalizedRepository,
43+
const GitRevisionRequirement &revision) const = 0;
44+
};
45+
46+
enum class ResolverErrorCode
47+
{
48+
invalid_requirement,
49+
no_root_requirements,
50+
no_candidate,
51+
constraint_conflict,
52+
git_revision_unresolved,
53+
git_commit_conflict,
54+
package_contract_mismatch,
55+
dependency_cycle,
56+
resolution_depth_exceeded,
57+
invalid_provider_metadata
58+
};
59+
60+
struct ResolverConstraintContext
61+
{
62+
std::string alias;
63+
std::string requirement;
64+
std::string dependencyPath;
65+
};
66+
67+
struct ResolverIssue
68+
{
69+
ResolverErrorCode code{ResolverErrorCode::invalid_provider_metadata};
70+
std::string identity;
71+
std::string message;
72+
std::vector<ResolverConstraintContext> constraints;
73+
};
74+
75+
template <typename T>
76+
struct ResolverResult
77+
{
78+
std::optional<T> value;
79+
std::vector<ResolverIssue> issues;
80+
[[nodiscard]] bool valid() const noexcept { return value.has_value() && issues.empty(); }
81+
};
82+
83+
struct ResolvedDependency
84+
{
85+
std::string alias;
86+
PackageIdentity identity;
87+
};
88+
89+
struct ResolvedRegistryNode
90+
{
91+
RegistryPackageIdentity identity;
92+
Version version;
93+
std::string contentDigest;
94+
std::vector<ResolvedDependency> dependencies;
95+
};
96+
97+
struct ResolvedGitNode
98+
{
99+
std::string normalizedRepository;
100+
bool repositoryRoot{true};
101+
std::string commit;
102+
std::string contentDigest;
103+
std::vector<ResolvedDependency> dependencies;
104+
};
105+
106+
using ResolvedNode = std::variant<ResolvedRegistryNode, ResolvedGitNode>;
107+
108+
struct ResolvedRoot
109+
{
110+
std::string alias;
111+
std::variant<NormalizedDeclaredRegistry, NormalizedDeclaredGit> declared;
112+
PackageIdentity identity;
113+
};
114+
115+
struct ResolvedGraph
116+
{
117+
std::vector<ResolvedRoot> roots;
118+
std::vector<ResolvedNode> nodes;
119+
};
120+
121+
[[nodiscard]] ResolverResult<ResolvedGraph> resolve_packages(
122+
const std::vector<PackageRequirement> &rootRequirements,
123+
const ResolutionMetadataProvider &provider);
124+
125+
[[nodiscard]] ResolverResult<Lockfile> make_resolved_lockfile(const ResolvedGraph &graph);
126+
} // namespace vix::cli::project::native
127+
128+
#endif // VIX_CLI_PROJECT_NATIVE_RESOLVER_HPP

0 commit comments

Comments
 (0)