1use crate::pkg::config;
2use anyhow::Result;
3use clap::{Parser, Subcommand};
4use colored::*;
5use comfy_table::{Table, presets::UTF8_FULL};
6use std::collections::HashSet;
7
8#[derive(Parser)]
9pub struct RepoCommand {
10 #[arg(
11 short = 'y',
12 long,
13 help = "Automatically answer yes to all prompts",
14 global = true
15 )]
16 yes: bool,
17 #[command(subcommand)]
18 command: Commands,
19}
20
21#[derive(Subcommand)]
22enum Commands {
23 #[command(alias = "a")]
25 Add {
26 repo_or_url: Option<String>,
28 },
29 #[command(alias = "rm")]
31 Remove { repo_name: String },
32 #[command(alias = "ls")]
34 List {
35 #[command(subcommand)]
36 which: Option<ListSub>,
37 },
38 #[command(subcommand)]
40 Git(GitCommand),
41}
42
43pub fn run(args: RepoCommand) {
44 let yes = args.yes;
45 match args.command {
46 Commands::Add { repo_or_url } => {
47 if let Some(val) = repo_or_url {
48 if val.starts_with("http://")
49 || val.starts_with("https://")
50 || val.ends_with(".git")
51 {
52 if let Err(e) = config::clone_git_repo(&val) {
53 eprintln!("{}: {}", "Error".red().bold(), e);
54 }
55 } else if let Err(e) = config::add_repo(&val) {
56 eprintln!("{}: {}", "Error".red().bold(), e);
57 } else {
58 println!("Repository '{}' added successfully.", val.green());
59 }
60 } else if !yes {
61 if let Err(e) = config::interactive_add_repo() {
62 eprintln!("{}: {}", "Error".red().bold(), e);
63 }
64 } else if let Err(e) = config::interactive_add_repo() {
65 eprintln!("{}: {}", "Error".red().bold(), e);
66 }
67 }
68 Commands::Remove { repo_name } => {
69 if let Err(e) = config::remove_repo(&repo_name) {
70 eprintln!("{}: {}", "Error".red().bold(), e);
71 } else {
72 println!("Repository '{}' removed successfully.", repo_name.green());
73 }
74 }
75 Commands::List { which } => match which {
76 None => {
77 if let Err(e) = run_list_active() {
78 eprintln!("{}: {}", "Error".red().bold(), e);
79 }
80 }
81 Some(ListSub::All) => {
82 if let Err(e) = run_list_all() {
83 eprintln!("{}: {}", "Error".red().bold(), e);
84 }
85 }
86 },
87 Commands::Git(cmd) => match cmd {
88 GitCommand::List => {
89 if let Err(e) = run_list_git_only() {
90 eprintln!("{}: {}", "Error".red().bold(), e);
91 }
92 }
93 GitCommand::Rm { repo_name } => {
94 if let Err(e) = config::remove_git_repo(&repo_name) {
95 eprintln!("{}: {}", "Error".red().bold(), e);
96 }
97 }
98 },
99 }
100}
101
102fn run_list_active() -> Result<()> {
103 let config = config::read_config()?;
104 if config.repos.is_empty() {
105 println!("No active repositories.");
106 return Ok(());
107 }
108
109 let mut table = Table::new();
110 table
111 .load_preset(UTF8_FULL)
112 .set_header(vec!["Active Repositories"]);
113 for repo in config.repos {
114 table.add_row(vec![repo]);
115 }
116 println!("{table}");
117 Ok(())
118}
119
120fn run_list_all() -> Result<()> {
121 let active_repos = config::read_config()?
122 .repos
123 .into_iter()
124 .collect::<HashSet<_>>();
125 let all_repos = config::get_all_repos()?;
126
127 let mut table = Table::new();
128 table
129 .load_preset(UTF8_FULL)
130 .set_header(vec!["Status", "Repository"]);
131
132 for repo in all_repos {
133 let status = if active_repos.contains(&repo.to_lowercase()) {
134 "Added"
135 } else {
136 ""
137 };
138 table.add_row(vec![status.to_string(), repo]);
139 }
140 println!("{table}");
141 Ok(())
142}
143
144#[derive(Subcommand)]
145enum ListSub {
146 All,
148}
149
150#[derive(Subcommand)]
151enum GitCommand {
152 #[command(alias = "ls")]
154 List,
155 Rm { repo_name: String },
157}
158
159fn run_list_git_only() -> Result<()> {
160 let repos = config::list_git_repos()?;
161 if repos.is_empty() {
162 println!("No cloned git repositories.");
163 return Ok(());
164 }
165
166 let mut table = Table::new();
167 table
168 .load_preset(UTF8_FULL)
169 .set_header(vec!["Cloned Git Repositories (~/.zoi/pkgs/git)"]);
170 for repo in repos {
171 table.add_row(vec![repo]);
172 }
173 println!("{table}");
174 Ok(())
175}