From 22d6df15a82369dc4f1ac38f63deb9ba4401ebd0 Mon Sep 17 00:00:00 2001 From: Naoki Ikeguchi Date: Tue, 22 Nov 2022 21:09:45 +0900 Subject: [PATCH] feat: Use Git CLI for cloning repositories by default --- src/cmd/clone.rs | 7 +++++-- src/config.rs | 3 +++ src/git/config.rs | 15 +++++++++++++++ src/git/mod.rs | 15 +++++++++++++++ src/git/strategy/cli.rs | 24 ++++++++++++++++++++++++ src/git/strategy/git2.rs | 22 ++++++++++++++++++++++ src/git/strategy/mod.rs | 30 ++++++++++++++++++++++++++++++ src/main.rs | 1 + 8 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 src/git/config.rs create mode 100644 src/git/mod.rs create mode 100644 src/git/strategy/cli.rs create mode 100644 src/git/strategy/git2.rs create mode 100644 src/git/strategy/mod.rs diff --git a/src/cmd/clone.rs b/src/cmd/clone.rs index 3da443d..6dab298 100644 --- a/src/cmd/clone.rs +++ b/src/cmd/clone.rs @@ -11,6 +11,7 @@ use tracing::info; use crate::config::Config; use crate::console::create_spinner; +use crate::git::CloneRepository; use crate::path::Path; use crate::root::Root; use crate::url::Url; @@ -41,13 +42,15 @@ impl Cmd { }); let url = Url::from_str(&self.repo)?; - let path = Path::resolve(&root, &url); + let path = PathBuf::from(Path::resolve(&root, &url)); let profile = config .rules .resolve(&url) .and_then(|r| config.profiles.resolve(&r.profile)); - let repo = Repository::clone(&url.to_string(), PathBuf::from(&path))?; + config.git.strategy.clone.clone_repository(url, &path)?; + + let repo = Repository::open(&path)?; if let Some((name, p)) = profile { p.apply(&mut repo.config()?)?; diff --git a/src/config.rs b/src/config.rs index 8594321..12c8a31 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,12 +3,15 @@ use std::fs::read_to_string; use anyhow::Result; use serde::Deserialize; +use crate::git::Config as GitConfig; use crate::profile::Profiles; use crate::root::Root; use crate::rule::Rules; #[derive(Debug, Default, Deserialize)] pub struct Config { + #[serde(default)] + pub git: GitConfig, #[serde(default)] pub profiles: Profiles, #[serde(default)] diff --git a/src/git/config.rs b/src/git/config.rs new file mode 100644 index 0000000..64570d4 --- /dev/null +++ b/src/git/config.rs @@ -0,0 +1,15 @@ +use serde::Deserialize; + +use crate::git::strategy::Strategy; + +#[derive(Debug, Default, Deserialize)] +pub struct StrategyConfig { + #[serde(default)] + pub clone: Strategy, +} + +#[derive(Debug, Default, Deserialize)] +pub struct Config { + #[serde(default)] + pub strategy: StrategyConfig, +} diff --git a/src/git/mod.rs b/src/git/mod.rs new file mode 100644 index 0000000..8e5e6ad --- /dev/null +++ b/src/git/mod.rs @@ -0,0 +1,15 @@ +mod config; +mod strategy; + +pub use config::Config; + +use std::path::Path; + +use anyhow::Result; + +pub trait CloneRepository { + fn clone_repository(&self, url: U, path: P) -> Result<()> + where + U: ToString, + P: AsRef; +} diff --git a/src/git/strategy/cli.rs b/src/git/strategy/cli.rs new file mode 100644 index 0000000..ad68d0a --- /dev/null +++ b/src/git/strategy/cli.rs @@ -0,0 +1,24 @@ +use std::path::Path; +use std::process::Command; + +use tracing::debug; + +use crate::git::CloneRepository; + +pub struct Cli; + +impl CloneRepository for Cli { + fn clone_repository(&self, url: U, path: P) -> anyhow::Result<()> + where + U: ToString, + P: AsRef, + { + debug!("Cloning the repository using CLI strategy"); + + let _ = Command::new("git") + .args(["clone", &url.to_string(), path.as_ref().to_str().unwrap()]) + .output()?; + + Ok(()) + } +} diff --git a/src/git/strategy/git2.rs b/src/git/strategy/git2.rs new file mode 100644 index 0000000..f9f1eed --- /dev/null +++ b/src/git/strategy/git2.rs @@ -0,0 +1,22 @@ +use std::path::Path; + +use git2::Repository; +use tracing::debug; + +use crate::git::CloneRepository; + +pub struct Git2; + +impl CloneRepository for Git2 { + fn clone_repository(&self, url: U, path: P) -> anyhow::Result<()> + where + U: ToString, + P: AsRef, + { + debug!("Cloning the repository using Git2 strategy"); + + let _ = Repository::clone(&url.to_string(), path)?; + + Ok(()) + } +} diff --git a/src/git/strategy/mod.rs b/src/git/strategy/mod.rs new file mode 100644 index 0000000..a38eae8 --- /dev/null +++ b/src/git/strategy/mod.rs @@ -0,0 +1,30 @@ +mod cli; +mod git2; + +pub use {self::git2::Git2, cli::Cli}; + +use std::path::Path; + +use serde::Deserialize; + +use crate::git::CloneRepository; + +#[derive(Debug, Default, Deserialize)] +pub enum Strategy { + #[default] + Cli, + Git2, +} + +impl CloneRepository for Strategy { + fn clone_repository(&self, url: U, path: P) -> anyhow::Result<()> + where + U: ToString, + P: AsRef, + { + match self { + Self::Cli => Cli.clone_repository(url, path), + Self::Git2 => Git2.clone_repository(url, path), + } + } +} diff --git a/src/main.rs b/src/main.rs index 9aab097..59bd3ef 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod cmd; mod config; mod console; +mod git; mod path; mod profile; mod root;