Skip to content

Commit

Permalink
Merge pull request #1827 from multiversx/build-git
Browse files Browse the repository at this point in the history
sc-meta - dependency refactor, full support for referencing the framework by git commit
  • Loading branch information
andrei-marinica authored Oct 23, 2024
2 parents 860c80e + fd6a6c8 commit 3ce390e
Show file tree
Hide file tree
Showing 22 changed files with 550 additions and 265 deletions.
204 changes: 111 additions & 93 deletions Cargo.lock

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,7 @@ impl Config {
}

pub fn token_amount(&self) -> BigUint {
match BigUint::from_str(&self.amount) {
Ok(amount) => amount,
Err(_) => BigUint::default(),
}
BigUint::from_str(&self.amount).unwrap_or_default()
}

pub fn token_nonce(&self) -> u64 {
Expand Down
12 changes: 12 additions & 0 deletions framework/meta-lib/src/cargo_toml.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
mod cargo_toml_contents;
mod cargo_toml_deps;
mod cargo_toml_deps_raw;
mod version_req;

pub use cargo_toml_contents::{
change_from_base_to_adapter_path, CargoTomlContents, CARGO_TOML_DEPENDENCIES,
CARGO_TOML_DEV_DEPENDENCIES,
};
pub use cargo_toml_deps::{DependencyReference, GitCommitReference};
pub use cargo_toml_deps_raw::DependencyRawValue;
pub use version_req::VersionReq;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use toml::{value::Table, Value};

use crate::contract::sc_config::ContractVariantProfile;

use super::DependencyRawValue;

pub const CARGO_TOML_DEPENDENCIES: &str = "dependencies";
pub const CARGO_TOML_DEV_DEPENDENCIES: &str = "dev-dependencies";
pub const PACKAGE: &str = "package";
Expand All @@ -34,24 +36,26 @@ pub struct CargoTomlContents {
}

impl CargoTomlContents {
pub fn parse_string(raw_str: &str, path: &Path) -> Self {
let toml_value = raw_str.parse::<toml::Value>().unwrap_or_else(|e| {
panic!(
"failed to parse Cargo.toml toml format, path:{}, error: {e}",
path.display()
)
});
CargoTomlContents {
path: path.to_owned(),
toml_value,
prepend_auto_generated_comment: false,
}
}

pub fn load_from_file<P: AsRef<Path>>(path: P) -> Self {
let path_ref = path.as_ref();
let cargo_toml_content = fs::read(path_ref).expect("failed to open Cargo.toml file");
let cargo_toml_content_str =
String::from_utf8(cargo_toml_content).expect("error decoding Cargo.toml utf-8");
let toml_value = cargo_toml_content_str
.parse::<toml::Value>()
.unwrap_or_else(|e| {
panic!(
"failed to parse Cargo.toml toml format, path:{}, error: {e}",
path_ref.display()
)
});
CargoTomlContents {
path: path_ref.to_owned(),
toml_value,
prepend_auto_generated_comment: false,
}
Self::parse_string(&cargo_toml_content_str, path_ref)
}

pub fn new() -> Self {
Expand Down Expand Up @@ -91,27 +95,15 @@ impl CargoTomlContents {
.to_string()
}

pub fn dependency_version(&self, crate_name: &str) -> String {
let toml_value = self.dependency(crate_name).unwrap().to_owned();

if let Value::Table(table) = toml_value {
if let Some(version) = table.get("version") {
return remove_quotes(version);
}
}
panic!("could not find multiversx-sc dependency version in cargo toml")
/// Interprets the dependency value and organizes values in a struct.
pub fn dependency_raw_value(&self, crate_name: &str) -> Option<DependencyRawValue> {
self.dependency(crate_name)
.map(DependencyRawValue::parse_toml_value)
}

pub fn dependency_path(&self, crate_name: &str) -> Option<String> {
let toml_value = self.dependency(crate_name).unwrap().to_owned();

if let Value::Table(table) = toml_value {
if let Some(path) = table.get("path") {
return Option::Some(remove_quotes(path));
}
}

Option::None
pub fn insert_dependency_raw_value(&mut self, crate_name: &str, raw_value: DependencyRawValue) {
self.dependencies_mut()
.insert(crate_name.to_owned(), raw_value.into_toml_value());
}

/// Assumes that a package section already exists.
Expand Down Expand Up @@ -150,8 +142,10 @@ impl CargoTomlContents {

pub fn dependencies_mut(&mut self) -> &mut Table {
self.toml_value
.get_mut(CARGO_TOML_DEPENDENCIES)
.unwrap_or_else(|| panic!("no dependencies found in crate {}", self.path.display()))
.as_table_mut()
.expect("add deps cargo toml error wasm adapter")
.entry(CARGO_TOML_DEPENDENCIES)
.or_insert(toml::Value::Table(toml::map::Map::new()))
.as_table_mut()
.expect("malformed crate Cargo.toml")
}
Expand Down Expand Up @@ -341,11 +335,16 @@ pub fn change_from_base_to_adapter_path(base_path: &str) -> String {
)
}

/// TODO: still useful?
#[allow(unused)]
fn remove_quotes(var: &Value) -> String {
var.to_string().replace('\"', "")
}

#[cfg(test)]
mod tests {
use super::*;
use crate::cargo_toml::{DependencyReference, GitCommitReference, VersionReq};

#[test]
fn test_change_from_base_to_adapter_path() {
Expand All @@ -356,4 +355,154 @@ mod tests {
adapter_path
);
}

const CARGO_TOML_RAW: &str = r#"
[dependencies.by-version-1]
version = "1.2.30"
[dependencies.by-version-1-strict]
version = "=1.2.31"
[dependencies.by-git-commit-1]
git = "https://github.com/multiversx/repo1"
rev = "85c31b9ce730bd5ffe41589c353d935a14baaa96"
[dependencies.by-path-1]
path = "a/b/c"
[dependencies]
by-version-2 = "4.5.60"
by-version-2-strict = "=4.5.61"
by-path-2 = { path = "d/e/f" }
by-git-commit-2 = { git = "https://github.com/multiversx/repo2", rev = "e990be823f26d1e7f59c71536d337b7240dc3fa2" }
"#;

#[test]
fn test_dependency_value() {
let cargo_toml = CargoTomlContents::parse_string(CARGO_TOML_RAW, "/test".as_ref());

// version
let raw_value = cargo_toml.dependency_raw_value("by-version-1").unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
version: Some("1.2.30".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::Version(VersionReq::from_version_str("1.2.30")),
);

// version, strict
let raw_value = cargo_toml
.dependency_raw_value("by-version-1-strict")
.unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
version: Some("=1.2.31".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::Version(VersionReq::from_version_str("1.2.31").strict()),
);

// version, compact
let raw_value = cargo_toml.dependency_raw_value("by-version-2").unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
version: Some("4.5.60".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::Version(VersionReq::from_version_str("4.5.60")),
);

// version, compact, strict
let raw_value = cargo_toml
.dependency_raw_value("by-version-2-strict")
.unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
version: Some("=4.5.61".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::Version(VersionReq::from_version_str("4.5.61").strict()),
);

// git
let raw_value = cargo_toml.dependency_raw_value("by-git-commit-1").unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
git: Some("https://github.com/multiversx/repo1".to_owned()),
rev: Some("85c31b9ce730bd5ffe41589c353d935a14baaa96".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::GitCommit(GitCommitReference {
git: "https://github.com/multiversx/repo1".to_owned(),
rev: "85c31b9ce730bd5ffe41589c353d935a14baaa96".to_owned(),
})
);

// git, compact
let raw_value = cargo_toml.dependency_raw_value("by-git-commit-2").unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
git: Some("https://github.com/multiversx/repo2".to_owned()),
rev: Some("e990be823f26d1e7f59c71536d337b7240dc3fa2".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::GitCommit(GitCommitReference {
git: "https://github.com/multiversx/repo2".to_owned(),
rev: "e990be823f26d1e7f59c71536d337b7240dc3fa2".to_owned(),
})
);

// path
let raw_value = cargo_toml.dependency_raw_value("by-path-1").unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
path: Some("a/b/c".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::Path("a/b/c".to_owned()),
);

// path, compact
let raw_value = cargo_toml.dependency_raw_value("by-path-2").unwrap();
assert_eq!(
raw_value,
DependencyRawValue {
path: Some("d/e/f".to_owned()),
..Default::default()
},
);
assert_eq!(
raw_value.interpret(),
DependencyReference::Path("d/e/f".to_owned()),
);
}
}
85 changes: 85 additions & 0 deletions framework/meta-lib/src/cargo_toml/cargo_toml_deps.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use crate::version::FrameworkVersion;

use super::{DependencyRawValue, VersionReq};

/// A dependency reference to a git commit. We mostly use git commits when referencing git.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GitCommitReference {
pub git: String,
pub rev: String,
}

/// A dependency reference to a git branch.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GitBranchReference {
pub git: String,
pub branch: String,
}

/// A dependency reference to a git tag.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GitTagReference {
pub git: String,
pub tag: String,
}

/// Models how a dependency is expressed in Cargo.toml.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum DependencyReference {
Version(VersionReq),
GitCommit(GitCommitReference),
GitBranch(GitBranchReference),
GitTag(GitTagReference),
Path(String),
Unsupported(&'static str),
}

impl DependencyReference {
pub fn is_framework_version(&self, version: &FrameworkVersion) -> bool {
if let DependencyReference::Version(version_req) = self {
&version_req.semver == version
} else {
false
}
}
}

impl DependencyRawValue {
/// Interprets the raw dependency value as one of several possible formats.
pub fn interpret(self) -> DependencyReference {
// path is top priority
if let Some(path) = self.path {
return DependencyReference::Path(path);
}

if let Some(git) = self.git {
return match (self.rev, self.branch, self.tag) {
(Some(rev), None, None) => {
DependencyReference::GitCommit(GitCommitReference { git, rev })
},
(None, Some(branch), None) => {
DependencyReference::GitBranch(GitBranchReference { git, branch })
},

(None, None, Some(tag)) => {
DependencyReference::GitTag(GitTagReference { git, tag })
},

(None, None, None) => DependencyReference::Unsupported(
"need at least one of: git commit, git brach, or git tag",
),
_ => DependencyReference::Unsupported(
"can only have one of: git commit, git brach, or git tag",
),
};
}

// explicit version = "..."
// handled last, because it has the lowest priority, both path and git fields override it
if let Some(version) = self.version {
return DependencyReference::Version(VersionReq::from_version_str(&version));
}

DependencyReference::Unsupported("expected at least one of: version, git, path")
}
}
Loading

0 comments on commit 3ce390e

Please sign in to comment.