use crate::pkg::config;
use anyhow::Result;
use anyhow::anyhow;
use clap::{Parser, Subcommand};
use colored::*;
use comfy_table::{Table, presets::UTF8_FULL};
use std::collections::HashSet;
#[derive(Parser)]
pub struct RepoCommand {
#[arg(
short = 'y',
long,
help = "Automatically answer yes to all prompts",
global = true
)]
yes: bool,
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
#[command(alias = "a")]
Add {
repo_or_url: Option<String>,
},
#[command(alias = "rm")]
Remove { repo_name: String },
#[command(alias = "ls")]
List {
#[command(subcommand)]
which: Option<ListSub>,
},
#[command(subcommand)]
Git(GitCommand),
}
pub fn run(args: RepoCommand) -> Result<()> {
let yes = args.yes;
match args.command {
Commands::Add { repo_or_url } => {
if let Some(val) = repo_or_url {
if val.starts_with("http://")
|| val.starts_with("https://")
|| val.ends_with(".git")
{
config::clone_git_repo(&val)?;
} else {
config::add_repo(&val)?;
println!("Repository '{}' added successfully.", val.green());
}
} else if yes {
return Err(anyhow!(
"A repository name or URL is required when using --yes."
));
} else {
config::interactive_add_repo()?;
}
}
Commands::Remove { repo_name } => {
config::remove_repo(&repo_name)?;
println!("Repository '{}' removed successfully.", repo_name.green());
}
Commands::List { which } => match which {
None => run_list_active()?,
Some(ListSub::All) => run_list_all()?,
},
Commands::Git(cmd) => match cmd {
GitCommand::List => run_list_git_only()?,
GitCommand::Rm { repo_name } => config::remove_git_repo(&repo_name)?,
},
}
Ok(())
}
fn run_list_active() -> Result<()> {
let config = config::read_config()?;
if config.repos.is_empty() {
println!("No active repositories.");
return Ok(());
}
println!("{} Active repositories:", "::".bold().blue());
let mut table = Table::new();
table.load_preset(UTF8_FULL).set_header(vec!["Repository"]);
for repo in config.repos {
table.add_row(vec![repo]);
}
println!("{table}");
Ok(())
}
fn run_list_all() -> Result<()> {
let active_repos = config::read_config()?
.repos
.into_iter()
.collect::<HashSet<_>>();
let all_repos = config::get_all_repos()?;
println!("{} All available repositories:", "::".bold().blue());
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.set_header(vec!["Status", "Repository"]);
for repo in all_repos {
let status = if active_repos.contains(&repo.to_lowercase()) {
"Added"
} else {
""
};
table.add_row(vec![status.to_string(), repo]);
}
println!("{table}");
Ok(())
}
#[derive(Subcommand)]
enum ListSub {
All,
}
#[derive(Subcommand)]
enum GitCommand {
#[command(alias = "ls")]
List,
Rm { repo_name: String },
}
fn run_list_git_only() -> Result<()> {
let repos = config::list_git_repos()?;
if repos.is_empty() {
println!("No cloned git repositories.");
return Ok(());
}
println!(
"{} Cloned git repositories (~/.zoi/pkgs/git):",
"::".bold().blue()
);
let mut table = Table::new();
table.load_preset(UTF8_FULL).set_header(vec!["Repository"]);
for repo in repos {
table.add_row(vec![repo]);
}
println!("{table}");
Ok(())
}