multiversx_sc_meta_lib/cargo_toml/
cargo_toml_deps.rs

1use std::path::PathBuf;
2
3use crate::version::FrameworkVersion;
4
5use super::{DependencyRawValue, VersionReq};
6
7/// A dependency reference to a git commit. We mostly use git commits when referencing git.
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct GitCommitReference {
10    pub git: String,
11    pub rev: String,
12}
13
14/// A dependency reference to a git branch.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct GitBranchReference {
17    pub git: String,
18    pub branch: String,
19}
20
21/// A dependency reference to a git tag.
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct GitTagReference {
24    pub git: String,
25    pub tag: String,
26}
27
28/// Models how a dependency is expressed in Cargo.toml.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub enum DependencyReference {
31    Version(VersionReq),
32    GitCommit(GitCommitReference),
33    GitBranch(GitBranchReference),
34    GitTag(GitTagReference),
35    Path(PathBuf),
36    Unsupported(String),
37}
38
39impl DependencyReference {
40    pub fn eq_framework_version(&self, version: &FrameworkVersion) -> bool {
41        if let DependencyReference::Version(version_req) = self {
42            &version_req.semver == version
43        } else {
44            false
45        }
46    }
47
48    pub fn to_framework_version(&self) -> Option<VersionReq> {
49        if let DependencyReference::Version(version_req) = self {
50            Some(version_req.clone())
51        } else {
52            None
53        }
54    }
55}
56
57impl DependencyRawValue {
58    /// Interprets the raw dependency value as one of several possible formats.
59    pub fn interpret(self) -> DependencyReference {
60        // path is top priority
61        if let Some(path) = self.path {
62            return DependencyReference::Path(path);
63        }
64
65        if let Some(git) = self.git {
66            return match (self.rev, self.branch, self.tag) {
67                (Some(rev), None, None) => {
68                    DependencyReference::GitCommit(GitCommitReference { git, rev })
69                }
70                (None, Some(branch), None) => {
71                    DependencyReference::GitBranch(GitBranchReference { git, branch })
72                }
73
74                (None, None, Some(tag)) => {
75                    DependencyReference::GitTag(GitTagReference { git, tag })
76                }
77
78                (None, None, None) => DependencyReference::Unsupported(
79                    "need at least one of: git commit, git branch, or git tag".to_owned(),
80                ),
81                _ => DependencyReference::Unsupported(
82                    "can only have one of: git commit, git branch, or git tag".to_owned(),
83                ),
84            };
85        }
86
87        // explicit version = "..."
88        // handled last, because it has the lowest priority, both path and git fields override it
89        if let Some(version) = self.version {
90            if let Some(version_req) = VersionReq::from_version_str(&version) {
91                return DependencyReference::Version(version_req);
92            } else {
93                return DependencyReference::Unsupported(format!(
94                    "unknown framework version: {version}"
95                ));
96            }
97        }
98
99        DependencyReference::Unsupported("expected at least one of: version, git, path".to_owned())
100    }
101}