diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ef5337ab7..5b9f450f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,9 @@ Special thanks to external contributors for this release: @CharlyCst ([#347]). - [relayer-cli] - Merge light clients config in relayer config and add commands to add/remove light clients ([#348]) - CLI for client update message ([#277]) -- [proto-compiler] Refactor and allow specifying a commit at which the Cosmos SDK should be checked out ([#366]) +- [proto-compiler] + - Refactor and allow specifying a commit at which the Cosmos SDK should be checked out ([#366]) + - Add a `--tag` option to the `clone-sdk` command to check out a tag instead of a commit ([#369]) - [ibc-proto] Refactor and allow specifying a commit at which the Cosmos SDK should be checked out ([#366]) [#274]: https://github.com/informalsystems/ibc-rs/issues/274 @@ -22,6 +24,7 @@ Special thanks to external contributors for this release: @CharlyCst ([#347]). [#336]: https://github.com/informalsystems/ibc-rs/issues/336 [#348]: https://github.com/informalsystems/ibc-rs/pulls/348 [#366]: https://github.com/informalsystems/ibc-rs/issues/366 +[#369]: https://github.com/informalsystems/ibc-rs/pulls/369 ### IMPROVEMENTS diff --git a/proto-compiler/README.md b/proto-compiler/README.md index 25dfa2ae88..068f2cfbbc 100644 --- a/proto-compiler/README.md +++ b/proto-compiler/README.md @@ -4,15 +4,32 @@ The `ibc-proto-compiler` is a simple command-line tool to automate the compilati ## Usage -From within the `proto-compiler` directory, run the following command to clone the Cosmos SDK repository: +### Clone the Cosmos SDK + +From within the `proto-compiler` directory, run the following command to clone the Cosmos SDK repository, and check out a specific commit: ```bash -$ cargo run -- clone-sdk --commit ce3994020a0d5c246016c8832ba4a668e8b7c77b --out /tmp/sdk +$ cargo run -- clone-sdk --out /tmp/sdk --commit ce3994020a0d5c246016c8832ba4a668e8b7c77b ``` +Note: the full commit hash must be specified. + +Alternatively, one can check out a tag with the `--tag` option: + +```bash +$ cargo run -- clone-sdk --out /tmp/sdk --tag v0.39.1-rc3 +``` + +If neither `--commit` nor `--tag` is specified, then the default main branch will be checked out. + +### Generate Rust sources from Protubuf definitions + To generate the Rust sources from the Protobuf definitions, and copy them to the `src/prost` folder `ibc-proto` crate within the `ibc-rs` project: ```bash $ cargo run -- compile --sdk /tmp/sdk --out ../proto/src/prost ``` +Additionally, this command will output the commit hash at which the Cosmos SDK is checked out into `$out/COSMOS_SDK_COMMIT`. + +This value is exposed via the `ibc_proto::COSMOS_SDK_VERSION` constant in the `ibc-proto` library. diff --git a/proto-compiler/src/cmd/clone.rs b/proto-compiler/src/cmd/clone.rs index db10bd6c88..6c1a376daa 100644 --- a/proto-compiler/src/cmd/clone.rs +++ b/proto-compiler/src/cmd/clone.rs @@ -11,13 +11,27 @@ pub struct CloneCmd { /// commit to checkout #[argh(option, short = 'c')] commit: Option, + + /// tag to checkout + #[argh(option, short = 't')] + tag: Option, + /// where to checkout the repository #[argh(option, short = 'o')] path: PathBuf, } impl CloneCmd { + pub fn validate(&self) { + if self.commit.is_some() && self.tag.is_some() { + println!("[error] The --commit and --tag options are mutually exclusive."); + process::exit(1); + } + } + pub fn run(&self) { + self.validate(); + let repo = if self.path.exists() { println!( "[info ] Found Cosmos SDK source at '{}'", @@ -33,35 +47,77 @@ impl CloneCmd { let url = "https://github.com/cosmos/cosmos-sdk"; - Repository::clone(url, &self.path).unwrap_or_else(|e| { + let repo = Repository::clone(url, &self.path).unwrap_or_else(|e| { println!("[error] Failed to clone the repository: {}", e); process::exit(1) - }) + }); + + println!("[info ] Cloned at '{}'", self.path.display()); + + repo }; if let Some(ref rev) = self.commit { checkout_commit(&repo, rev).unwrap_or_else(|e| { - println!("[error] Failed to checkout {}: {}", rev, e); + println!("[error] Failed to checkout commit {}: {}", rev, e); + process::exit(1) + }); + } else if let Some(ref tag) = self.tag { + checkout_tag(&repo, tag).unwrap_or_else(|e| { + println!("[error] Failed to checkout tag {}: {}", tag, e); process::exit(1) }); - - println!("[info ] HEAD is at {}", rev); } - - println!("[info ] Cloned at '{}'", self.path.display()); } } fn checkout_commit(repo: &Repository, rev: &str) -> Result<(), git2::Error> { let oid = Oid::from_str(rev)?; let commit = repo.find_commit(oid)?; - repo.branch(rev, &commit, false)?; + // Create a new branch `rev` that points to `commit` + repo.branch(rev, &commit, true)?; + + // Checkout the newly created branch let treeish = format!("refs/heads/{}", rev); let object = repo.revparse_single(&treeish)?; - repo.checkout_tree(&object, None)?; repo.set_head(&treeish)?; + println!("[info ] Checked out commit {}", rev); + + Ok(()) +} + +fn checkout_tag(repo: &Repository, tag_name: &str) -> Result<(), git2::Error> { + // Find a tag with name `tag_name` + let tag = repo + .references()? + .into_iter() + .flatten() + .filter(|r| r.is_tag()) + .flat_map(|r| r.peel_to_tag()) + .find(|t| t.name() == Some(tag_name)); + + if let Some(tag) = tag { + // Get the commit this tag points to + let target_oid = tag.target()?.id(); + let commit = repo.find_commit(target_oid)?; + + // Create a new branch `tag_name` that points to `commit` + repo.branch(tag_name, &commit, true)?; + + // Checkout the newly created branch + let rev = format!("refs/heads/{}", tag_name); + let obj = repo.revparse_single(&rev)?; + repo.checkout_tree(&obj, None)?; + repo.set_head(&rev)?; + + println!("[info ] Checked out tag {}", tag_name); + } else { + println!("[error] Could not find tag {}", tag_name); + process::exit(1); + } + Ok(()) }