-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Using git branch/tag to pull dependencies (#147)
* Using git branch, tag to pull dependencies * fixed bug on showing wrong error if config was incorrect * fixed janitor tests * refactor: git branches and tags (#162) * fix: rev in git dependency * fix: behavior with no rev * fixed clippy --------- Co-authored-by: Valentin B. <[email protected]>
- Loading branch information
Showing
10 changed files
with
519 additions
and
142 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,11 @@ You can install a dependency from the Soldeer repository, a custom URL pointing | |
- **Example from Git:** | ||
soldeer install @openzeppelin-contracts~2.3.0 [email protected]:OpenZeppelin/openzeppelin-contracts.git | ||
- **Example from Git with a specified commit:** | ||
soldeer install @openzeppelin-contracts~2.3.0 [email protected]:OpenZeppelin/openzeppelin-contracts.git --rev 05f218fb6617932e56bf5388c3b389c3028a7b73", | ||
soldeer install @openzeppelin-contracts~2.3.0 [email protected]:OpenZeppelin/openzeppelin-contracts.git --rev 05f218fb6617932e56bf5388c3b389c3028a7b73 | ||
- **Example from Git with a specified tag:** | ||
soldeer install @openzeppelin-contracts~2.3.0 [email protected]:OpenZeppelin/openzeppelin-contracts.git --tag my-tag | ||
- **Example from Git with a specified branch:** | ||
soldeer install @openzeppelin-contracts~2.3.0 [email protected]:OpenZeppelin/openzeppelin-contracts.git --branch my-branch", | ||
after_help = "For more information, read the README.md" | ||
)] | ||
pub struct Install { | ||
|
@@ -63,13 +67,21 @@ pub struct Install { | |
/// The URL to the dependency zip file, if not from the Soldeer repository | ||
/// | ||
/// Example: https://my-domain/dep.zip | ||
#[arg(value_name = "URL")] | ||
#[arg(value_name = "URL", requires = "dependency")] | ||
pub remote_url: Option<String>, | ||
|
||
/// The revision of the dependency, if from Git | ||
#[arg(long)] | ||
/// A Git revision | ||
#[arg(long, group = "identifier", requires = "remote_url")] | ||
pub rev: Option<String>, | ||
|
||
/// A Git tag | ||
#[arg(long, group = "identifier", requires = "remote_url")] | ||
pub tag: Option<String>, | ||
|
||
/// A Git branch | ||
#[arg(long, group = "identifier", requires = "remote_url")] | ||
pub branch: Option<String>, | ||
|
||
/// If set, this command will delete the existing remappings and re-create them | ||
#[arg(short = 'g', long, default_value_t = false)] | ||
pub regenerate_remappings: bool, | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,12 +64,47 @@ impl Default for SoldeerConfig { | |
} | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] | ||
pub enum GitIdentifier { | ||
Rev(String), | ||
Branch(String), | ||
Tag(String), | ||
} | ||
|
||
impl GitIdentifier { | ||
pub fn from_rev(rev: impl Into<String>) -> Self { | ||
let rev: String = rev.into(); | ||
GitIdentifier::Rev(rev) | ||
} | ||
|
||
pub fn from_branch(branch: impl Into<String>) -> Self { | ||
let branch: String = branch.into(); | ||
GitIdentifier::Branch(branch) | ||
} | ||
|
||
pub fn from_tag(tag: impl Into<String>) -> Self { | ||
let tag: String = tag.into(); | ||
GitIdentifier::Tag(tag) | ||
} | ||
} | ||
|
||
impl fmt::Display for GitIdentifier { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
let val = match self { | ||
GitIdentifier::Rev(rev) => rev, | ||
GitIdentifier::Branch(branch) => branch, | ||
GitIdentifier::Tag(tag) => tag, | ||
}; | ||
write!(f, "{val}") | ||
} | ||
} | ||
|
||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] | ||
pub struct GitDependency { | ||
pub name: String, | ||
pub version: String, | ||
pub git: String, | ||
pub rev: Option<String>, | ||
pub identifier: Option<GitIdentifier>, | ||
} | ||
|
||
impl fmt::Display for GitDependency { | ||
|
@@ -144,48 +179,43 @@ impl Dependency { | |
None => value(&dep.version), | ||
}, | ||
), | ||
Dependency::Git(dep) => ( | ||
dep.name.clone(), | ||
match &dep.rev { | ||
Some(rev) => { | ||
let mut table = InlineTable::new(); | ||
table.insert( | ||
"version", | ||
value(&dep.version) | ||
.into_value() | ||
.expect("version should be a valid toml value"), | ||
); | ||
table.insert( | ||
"git", | ||
value(&dep.git) | ||
.into_value() | ||
.expect("git URL should be a valid toml value"), | ||
); | ||
Dependency::Git(dep) => { | ||
let mut table = InlineTable::new(); | ||
table.insert( | ||
"version", | ||
value(&dep.version).into_value().expect("version should be a valid toml value"), | ||
); | ||
table.insert( | ||
"git", | ||
value(&dep.git).into_value().expect("git URL should be a valid toml value"), | ||
); | ||
|
||
match &dep.identifier { | ||
Some(GitIdentifier::Rev(rev)) => { | ||
table.insert( | ||
"rev", | ||
value(rev).into_value().expect("rev should be a valid toml value"), | ||
); | ||
value(table) | ||
} | ||
None => { | ||
let mut table = InlineTable::new(); | ||
Some(GitIdentifier::Branch(branch)) => { | ||
table.insert( | ||
"version", | ||
value(&dep.version) | ||
"branch", | ||
value(branch) | ||
.into_value() | ||
.expect("version should be a valid toml value"), | ||
.expect("branch should be a valid toml value"), | ||
); | ||
} | ||
Some(GitIdentifier::Tag(tag)) => { | ||
table.insert( | ||
"git", | ||
value(&dep.git) | ||
.into_value() | ||
.expect("git URL should be a valid toml value"), | ||
"tag", | ||
value(tag).into_value().expect("tag should be a valid toml value"), | ||
); | ||
|
||
value(table) | ||
} | ||
}, | ||
), | ||
None => {} | ||
} | ||
|
||
(dep.name.clone(), value(table)) | ||
} | ||
} | ||
} | ||
|
||
|
@@ -454,29 +484,6 @@ fn parse_dependency(name: impl Into<String>, value: &Item) -> Result<Dependency> | |
); | ||
} | ||
|
||
// else if value.is_inline_table() && // TODO: Hacky way of doing this, might need rewritten | ||
// !value.as_inline_table().unwrap().contains_key("url") && | ||
// !value.as_inline_table().unwrap().contains_key("git") | ||
// { | ||
// // this function does not retrieve the url, only version | ||
// return Ok(HttpDependency { | ||
// name: name.clone(), | ||
// version: match value.as_inline_table() { | ||
// // we normalize to inline table | ||
// Some(table) => { | ||
// let version = table.get("version").unwrap().to_string(); | ||
// version.replace("\"", "").trim().to_string() | ||
// } | ||
// None => { | ||
// return Err(ConfigError::InvalidDependency(name)); | ||
// } | ||
// }, | ||
// url: None, | ||
// checksum: None, | ||
// } | ||
// .into()); | ||
// } | ||
|
||
// we should have a table or inline table | ||
let table = { | ||
match value.as_inline_table() { | ||
|
@@ -508,15 +515,46 @@ fn parse_dependency(name: impl Into<String>, value: &Item) -> Result<Dependency> | |
return Err(ConfigError::InvalidField { field: "git".to_string(), dep: name }); | ||
} | ||
Some(Some(git)) => { | ||
// rev field is optional but needs to be a string if present | ||
// rev/branch/tag fields are optional but need to be a string if present | ||
let rev = match table.get("rev").map(|v| v.as_str()) { | ||
Some(Some(rev)) => Some(rev.to_string()), | ||
Some(None) => { | ||
return Err(ConfigError::InvalidField { field: "rev".to_string(), dep: name }); | ||
} | ||
None => None, | ||
}; | ||
return Ok(Dependency::Git(GitDependency { name, git: git.to_string(), version, rev })); | ||
let branch = match table.get("branch").map(|v| v.as_str()) { | ||
Some(Some(tag)) => Some(tag.to_string()), | ||
Some(None) => { | ||
return Err(ConfigError::InvalidField { | ||
field: "branch".to_string(), | ||
dep: name, | ||
}); | ||
} | ||
None => None, | ||
}; | ||
let tag = match table.get("tag").map(|v| v.as_str()) { | ||
Some(Some(tag)) => Some(tag.to_string()), | ||
Some(None) => { | ||
return Err(ConfigError::InvalidField { field: "tag".to_string(), dep: name }); | ||
} | ||
None => None, | ||
}; | ||
let identifier = match (rev, branch, tag) { | ||
(Some(rev), None, None) => Some(GitIdentifier::from_rev(rev)), | ||
(None, Some(branch), None) => Some(GitIdentifier::from_branch(branch)), | ||
(None, None, Some(tag)) => Some(GitIdentifier::from_tag(tag)), | ||
(None, None, None) => None, | ||
_ => { | ||
return Err(ConfigError::GitIdentifierConflict(name)); | ||
} | ||
}; | ||
return Ok(Dependency::Git(GitDependency { | ||
name, | ||
git: git.to_string(), | ||
version, | ||
identifier, | ||
})); | ||
} | ||
None => {} | ||
} | ||
|
@@ -1431,7 +1469,7 @@ gas_reports = ['*'] | |
name: "dep1".to_string(), | ||
version: "1.0.0".to_string(), | ||
git: "[email protected]:foundry-rs/forge-std.git".to_string(), | ||
rev: Some("07263d193d621c4b2b0ce8b4d54af58f6957d97d".to_string()), | ||
identifier: Some(GitIdentifier::from_rev("07263d193d621c4b2b0ce8b4d54af58f6957d97d")), | ||
}); | ||
|
||
add_to_config(&dependency, &target_config).unwrap(); | ||
|
@@ -1449,6 +1487,108 @@ gas_reports = ['*'] | |
[dependencies] | ||
dep1 = { version = "1.0.0", git = "[email protected]:foundry-rs/forge-std.git", rev = "07263d193d621c4b2b0ce8b4d54af58f6957d97d" } | ||
# we don't have [dependencies] declared | ||
"#; | ||
|
||
assert_eq!(read_file_to_string(&target_config), content); | ||
|
||
let _ = remove_file(target_config); | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn add_to_config_foundry_github_with_tag() -> Result<()> { | ||
let mut content = r#" | ||
# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config | ||
[profile.default] | ||
script = "script" | ||
solc = "0.8.26" | ||
src = "src" | ||
test = "test" | ||
libs = ["dependencies"] | ||
gas_reports = ['*'] | ||
# we don't have [dependencies] declared | ||
"#; | ||
|
||
let target_config = define_config(true); | ||
|
||
write_to_config(&target_config, content); | ||
|
||
let dependency = Dependency::Git(GitDependency { | ||
name: "dep1".to_string(), | ||
version: "1.0.0".to_string(), | ||
git: "https://gitlab.com/mario4582928/Mario.git".to_string(), | ||
identifier: Some(GitIdentifier::from_tag("custom-tag")), | ||
}); | ||
|
||
add_to_config(&dependency, &target_config).unwrap(); | ||
content = r#" | ||
# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config | ||
[profile.default] | ||
script = "script" | ||
solc = "0.8.26" | ||
src = "src" | ||
test = "test" | ||
libs = ["dependencies"] | ||
gas_reports = ['*'] | ||
[dependencies] | ||
dep1 = { version = "1.0.0", git = "https://gitlab.com/mario4582928/Mario.git", tag = "custom-tag" } | ||
# we don't have [dependencies] declared | ||
"#; | ||
|
||
assert_eq!(read_file_to_string(&target_config), content); | ||
|
||
let _ = remove_file(target_config); | ||
Ok(()) | ||
} | ||
|
||
#[test] | ||
fn add_to_config_foundry_github_with_branch() -> Result<()> { | ||
let mut content = r#" | ||
# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config | ||
[profile.default] | ||
script = "script" | ||
solc = "0.8.26" | ||
src = "src" | ||
test = "test" | ||
libs = ["dependencies"] | ||
gas_reports = ['*'] | ||
# we don't have [dependencies] declared | ||
"#; | ||
|
||
let target_config = define_config(true); | ||
|
||
write_to_config(&target_config, content); | ||
|
||
let dependency = Dependency::Git(GitDependency { | ||
name: "dep1".to_string(), | ||
version: "1.0.0".to_string(), | ||
git: "https://gitlab.com/mario4582928/Mario.git".to_string(), | ||
identifier: Some(GitIdentifier::from_branch("custom-branch")), | ||
}); | ||
|
||
add_to_config(&dependency, &target_config).unwrap(); | ||
content = r#" | ||
# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config | ||
[profile.default] | ||
script = "script" | ||
solc = "0.8.26" | ||
src = "src" | ||
test = "test" | ||
libs = ["dependencies"] | ||
gas_reports = ['*'] | ||
[dependencies] | ||
dep1 = { version = "1.0.0", git = "https://gitlab.com/mario4582928/Mario.git", branch = "custom-branch" } | ||
# we don't have [dependencies] declared | ||
"#; | ||
|
||
|
@@ -1485,7 +1625,7 @@ dep1 = { version = "1.0.0", git = "[email protected]:foundry-rs/forge-std.git" } | |
name: "dep1".to_string(), | ||
version: "1.0.0".to_string(), | ||
git: "[email protected]:foundry-rs/forge-std.git".to_string(), | ||
rev: Some("07263d193d621c4b2b0ce8b4d54af58f6957d97d".to_string()), | ||
identifier: Some(GitIdentifier::from_rev("07263d193d621c4b2b0ce8b4d54af58f6957d97d")), | ||
}); | ||
|
||
add_to_config(&dependency, &target_config).unwrap(); | ||
|
Oops, something went wrong.