Skip to content

Commit

Permalink
fix: clone when user use ssh (#113)
Browse files Browse the repository at this point in the history
* fix: github clone with ssh

* fix: ssh keys can not be in HOME

* chore: use git2_credentials for ssh auth

* chore: clean println

* refactor: remove duplicate git init

* refactor: messages

* fix: handle error. replace unwrap()

* refactor: use prefix for urls

* fix: ssh clone for up command

* fix: test

* nitpicks and lockfile update

* Revert "nitpicks and lockfile update"

This reverts commit bec9c0b.

* refactor: bubble git2::config open error to caller

---------

Co-authored-by: Abhishek Shah <[email protected]>
  • Loading branch information
AlexD10S and weezy20 authored Apr 22, 2024
1 parent ba1d453 commit 5891beb
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 11 deletions.
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ serde_json = { version = "1.0"}
serde = { version = "1.0", features = ["derive"] }
zombienet-sdk = { git = "https://github.com/r0gue-io/zombienet-sdk", branch = "pop", version = "0.1.0-alpha.1"}
zombienet-support = { git = "https://github.com/r0gue-io/zombienet-sdk", branch = "pop", version = "0.1.0-alpha.1" }
git2_credentials = "0.13.0"

# pop-cli
clap = { version = "4.4", features = ["derive"] }
Expand Down
1 change: 1 addition & 0 deletions crates/pop-parachains/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ anyhow.workspace = true
thiserror.workspace = true
duct.workspace = true
git2.workspace = true
git2_credentials.workspace = true
tempfile.workspace = true
url.workspace = true
tokio.workspace = true
Expand Down
9 changes: 3 additions & 6 deletions crates/pop-parachains/src/new_parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::{
},
};
use anyhow::Result;
use git2::Repository;
use std::{fs, path::Path};
use walkdir::WalkDir;

Expand All @@ -31,21 +30,20 @@ pub fn instantiate_template_dir(
sanitize(target)?;
use Template::*;
let url = match template {
FPT => "https://github.com/paritytech/frontier-parachain-template.git",
Contracts => "https://github.com/paritytech/substrate-contracts-node.git",
FPT => "paritytech/frontier-parachain-template.git",
Contracts => "paritytech/substrate-contracts-node.git",
Base => {
return instantiate_base_template(target, config);
},
};
let tag = Git::clone_and_degit(url, target)?;
Repository::init(target)?;
Ok(tag)
}

pub fn instantiate_base_template(target: &Path, config: Config) -> Result<Option<String>> {
let temp_dir = ::tempfile::TempDir::new_in(std::env::temp_dir())?;
let source = temp_dir.path();
let tag = Git::clone_and_degit("https://github.com/r0gue-io/base-parachain", source)?;
let tag = Git::clone_and_degit("r0gue-io/base-parachain.git", source)?;

for entry in WalkDir::new(&source) {
let entry = entry?;
Expand All @@ -72,7 +70,6 @@ pub fn instantiate_base_template(target: &Path, config: Config) -> Result<Option
// Add network configuration
let network = Network { node: "parachain-template-node".into() };
write_to_file(&target.join("network.toml"), network.render().expect("infallible").as_ref())?;
Repository::init(target)?;
Ok(tag)
}

Expand Down
60 changes: 55 additions & 5 deletions crates/pop-parachains/src/utils/git.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use crate::errors::Error;
use anyhow::Result;
use git2::{build::RepoBuilder, FetchOptions, IndexAddOption, Repository, ResetType};
use git2::{
build::RepoBuilder, FetchOptions, IndexAddOption, RemoteCallbacks, Repository, ResetType,
};
use git2_credentials::CredentialHandler;
use regex::Regex;
use std::fs;
use std::path::Path;
use std::{env, fs};
use url::Url;

pub struct Git;
Expand All @@ -17,14 +20,36 @@ impl Git {
if let Some(branch) = branch {
repo.branch(branch);
}
repo.clone(url.as_str(), working_dir)?;
if let Err(_e) = repo.clone(url.as_str(), working_dir) {
Self::ssh_clone(url, working_dir, branch)?;
}
}
Ok(())
}

pub(crate) fn ssh_clone(url: &Url, working_dir: &Path, branch: Option<&str>) -> Result<()> {
// Change the url to the ssh url with [email protected]: prefix, remove / from path and adding .git as suffix
let ssh_url = ["[email protected]:", &url.path()[1..], ".git"].concat();
if !working_dir.exists() {
// Prepare callback and fetch options.
let mut fo = FetchOptions::new();
Self::set_up_ssh_fetch_options(&mut fo)?;
// Prepare builder and clone.
let mut repo = RepoBuilder::new();
repo.fetch_options(fo);
if let Some(branch) = branch {
repo.branch(branch);
}
repo.clone(&ssh_url, working_dir)?;
}
Ok(())
}
/// Clone `url` into `target` and degit it
pub fn clone_and_degit(url: &str, target: &Path) -> Result<Option<String>> {
let repo = Repository::clone(url, target)?;

let repo = match Repository::clone(&["https://github.com/", url].concat(), target) {
Ok(repo) => repo,
Err(_e) => Self::ssh_clone_and_degit(url, target)?,
};
// fetch tags from remote
let release = Self::fetch_latest_tag(&repo);

Expand All @@ -33,6 +58,31 @@ impl Git {
Ok(release)
}

/// For users that have ssh configuration for cloning repositories
fn ssh_clone_and_degit(url: &str, target: &Path) -> Result<Repository> {
// Prepare callback and fetch options.
let mut fo = FetchOptions::new();
Self::set_up_ssh_fetch_options(&mut fo)?;
// Prepare builder and clone.
let mut builder = RepoBuilder::new();
builder.fetch_options(fo);
let repo = builder.clone(&["[email protected]:", url].concat(), target)?;
Ok(repo)
}

fn set_up_ssh_fetch_options(fo: &mut FetchOptions) -> Result<()> {
let mut callbacks = RemoteCallbacks::new();
let git_config = git2::Config::open_default()
.map_err(|e| Error::Config(format!("Cannot open git configuration: {}", e)))?;
let mut ch = CredentialHandler::new(git_config);
callbacks.credentials(move |url, username, allowed| {
ch.try_next_credential(url, username, allowed)
});

fo.remote_callbacks(callbacks);
Ok(())
}

/// Fetch the latest release from a repository
fn fetch_latest_tag(repo: &Repository) -> Option<String> {
let version_reg = Regex::new(r"v\d+\.\d+\.\d+").expect("Valid regex");
Expand Down

0 comments on commit 5891beb

Please sign in to comment.