Skip to content

Commit

Permalink
feat: big renovation
Browse files Browse the repository at this point in the history
  • Loading branch information
Yingrjimsch committed Sep 6, 2024
1 parent b1aff8f commit 4201d88
Show file tree
Hide file tree
Showing 19 changed files with 767 additions and 821 deletions.
120 changes: 120 additions & 0 deletions src/cli/clone.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
use std::{ops::ControlFlow, path::Path, process::{Command, Stdio}};
use regex::Regex;
use crate::{utils::cmd::{create_git_cmd, run_cmd_o, run_cmd_o_soft, run_cmd_s}, git_api::git_providers::{get_provider, GitProvider, Repo}, config::config::{Config, Profile}, utils::helper::{self, prntln, run_in_threads_default, MessageType}};

pub async fn clone(directory: &str, user: bool, branch: String, regex: &str, reverse: bool, dry_run: bool, config: Config,
) {
let active_profile: Profile = config.active_profile().clone();
let pat: Option<String> = Some(active_profile.clone().token);
let provider_type: &str = &active_profile.provider;
// Find amount of repositories
let provider: Box<dyn GitProvider> = get_provider(provider_type);
let all_repos: Vec<Box<dyn Repo>> =
provider.get_repos(&pat, directory, user, active_profile.clone());

let re: Regex = Regex::new(regex).expect("Invalid regex pattern");
let repos_to_clone: Vec<Box<dyn Repo>> = all_repos
.into_iter()
.filter(|repo: &Box<dyn Repo>| (re.is_match(&repo.http_url()) || re.is_match(&repo.ssh_url())) ^ reverse)
.collect();
run_in_threads_default(
repos_to_clone,
move |_thread_id: usize, repo: &Box<dyn Repo>| {
let destination_path: String =
format!("{}/{}", active_profile.targetbasepath, repo.full_path());
let clone_url = get_clone_url(&active_profile.pulloption, repo);
if Path::new(&destination_path).exists() {
pull(&branch, destination_path, clone_url, dry_run)
} else {
let status: bool = run_cmd_s(
Command::new("git")
.args(&create_pull_request_args(
&branch,
&clone_url,
&active_profile.targetbasepath,
&repo.full_path(),
))
.stdout(Stdio::null())
.stderr(Stdio::null()),
dry_run,
true,
);
if status {
helper::prntln(&format!("{} {} {}", "Repository", clone_url, "successfully cloned!"), MessageType::Success);
}
ControlFlow::Continue(())
}
},
);
prntln("Finished cloning repositories", MessageType::Success);
}

fn pull(branch: &String, destination_path: String, clone_url: &str, dry_run: bool) -> ControlFlow<()> {
let current_branch = match get_current_pull_branch(branch, &destination_path, dry_run) {
Ok(value) => value,
Err(value) => return value,
};
let branch_exists: String = run_cmd_o(
create_git_cmd(&destination_path).arg("ls-remote").arg("--heads").arg("origin").arg(&current_branch),
dry_run,
);
if branch_exists != "" {
run_cmd_s(
create_git_cmd(&destination_path).arg("checkout").arg(&current_branch),
dry_run,
true,
);
run_cmd_s(
create_git_cmd(&destination_path).arg("pull"),
dry_run,
true,
);
helper::prntln(&format!("{} {} {}", "Repository", clone_url, "successfully pulled!"), MessageType::Success);
}
ControlFlow::Continue(())
}

fn get_current_pull_branch(branch: &str, destination_path: &String, dry_run: bool) -> Result<String, ControlFlow<()>> {
let current_branch: String = if branch == "" {
let (symbolic_ref, success) = run_cmd_o_soft(
create_git_cmd(destination_path).arg("symbolic-ref").arg("refs/remotes/origin/HEAD").arg("--short"),
dry_run,
);
if !success {
prntln("There is no HEAD branch defined in origin", MessageType::Error);
return Err(ControlFlow::Break(()));
}
symbolic_ref.strip_prefix("origin/").unwrap().to_string()
} else {
branch.to_string()
};
Ok(current_branch)
}

fn get_clone_url<'a>(pulloption: &'a str, repo: &'a Box<dyn Repo>) -> &'a str {
let clone_url = if pulloption == "ssh" {
repo.ssh_url()
} else {
repo.http_url()
};
return clone_url
}

fn create_pull_request_args(
branch: &str,
clone_url: &str,
target_basepath: &str,
directory: &str,
) -> Vec<String> {
let mut args: Vec<String> = vec![
"clone".to_string(),
clone_url.to_string(),
format!("{}/{}", target_basepath, directory),
];

if branch != "" {
args.insert(1, "-b".to_string());
args.insert(2, branch.to_string());
}
return args;
}
30 changes: 26 additions & 4 deletions src/cli/commands.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use clap::Subcommand;

#[derive(Subcommand)]
pub enum Commands {
#[command(about = "Clone a repository into the specified directory.")]
Expand Down Expand Up @@ -28,6 +29,13 @@ pub enum Commands {

#[clap(flatten)]
regex_args: Regex,

#[arg(
long,
default_value_t = false,
help = "Only make a dry run and list the commands which would be executed."
)]
dry_run: bool,
},
#[command(about = "Make git add, git commit, git push in one go.")]
Quick {
Expand All @@ -51,6 +59,13 @@ pub enum Commands {
help = "Don't ask for permission to execute command per repository."
)]
skip_interactive: bool,

#[arg(
long,
default_value_t = false,
help = "Only make a dry run and list the commands which would be executed."
)]
dry_run: bool,
},
#[command(about = "Execute a git command on a mass of repos.")]
Mass {
Expand All @@ -71,13 +86,20 @@ pub enum Commands {
help = "Don't ask for permission to execute command per repository."
)]
skip_interactive: bool,

#[arg(
long,
default_value_t = false,
help = "Only make a dry run and list the commands which would be executed."
)]
dry_run: bool,
},
#[command(about = "Manage your grgry profiles for different providers like github and gitlab.")]
Profile {
#[clap(subcommand)]
sub: ProfileCommands,
},
Test
// Test
}

#[derive(Subcommand)]
Expand Down Expand Up @@ -112,11 +134,11 @@ impl Regex {
pub fn get_regex_args(&self, default: &str) -> (String, bool) {
// Determine the value and whether reverse is true
if let Some(rev_regex) = &self.rev_regex {
(rev_regex.clone(), true)
return (rev_regex.clone(), true)
} else if let Some(regex) = &self.regex {
(regex.clone(), false);
return (regex.clone(), false);
} else {
(default.to_string(), false)
return (default.to_string(), false)
}
}
}
Loading

0 comments on commit 4201d88

Please sign in to comment.