✨ feat(commands):为所有命令添加config_path参数支持,实现自定义配置文件路径
♻️ refactor(config):重构ConfigManager,添加with_path_fresh方法用于初始化新配置 🔧 fix(git):改进跨平台路径处理,增强git仓库检测的鲁棒性 ✅ test(tests):添加全面的集成测试,覆盖所有命令和跨平台场景
This commit is contained in:
@@ -2,6 +2,7 @@ use anyhow::{bail, Result};
|
||||
use clap::{Parser, Subcommand};
|
||||
use colored::Colorize;
|
||||
use dialoguer::{Confirm, Input, Select};
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::config::manager::ConfigManager;
|
||||
use crate::config::{GitProfile, TokenConfig, TokenType};
|
||||
@@ -123,27 +124,34 @@ enum TokenSubcommand {
|
||||
}
|
||||
|
||||
impl ProfileCommand {
|
||||
pub async fn execute(&self) -> Result<()> {
|
||||
pub async fn execute(&self, config_path: Option<PathBuf>) -> Result<()> {
|
||||
match &self.command {
|
||||
Some(ProfileSubcommand::Add) => self.add_profile().await,
|
||||
Some(ProfileSubcommand::Remove { name }) => self.remove_profile(name).await,
|
||||
Some(ProfileSubcommand::List) => self.list_profiles().await,
|
||||
Some(ProfileSubcommand::Show { name }) => self.show_profile(name.as_deref()).await,
|
||||
Some(ProfileSubcommand::Edit { name }) => self.edit_profile(name).await,
|
||||
Some(ProfileSubcommand::SetDefault { name }) => self.set_default(name).await,
|
||||
Some(ProfileSubcommand::SetRepo { name }) => self.set_repo(name).await,
|
||||
Some(ProfileSubcommand::Apply { name, global }) => self.apply_profile(name.as_deref(), *global).await,
|
||||
Some(ProfileSubcommand::Switch) => self.switch_profile().await,
|
||||
Some(ProfileSubcommand::Copy { from, to }) => self.copy_profile(from, to).await,
|
||||
Some(ProfileSubcommand::Token { token_command }) => self.handle_token_command(token_command).await,
|
||||
Some(ProfileSubcommand::Check { name }) => self.check_profile(name.as_deref()).await,
|
||||
Some(ProfileSubcommand::Stats { name }) => self.show_stats(name.as_deref()).await,
|
||||
None => self.list_profiles().await,
|
||||
Some(ProfileSubcommand::Add) => self.add_profile(&config_path).await,
|
||||
Some(ProfileSubcommand::Remove { name }) => self.remove_profile(name, &config_path).await,
|
||||
Some(ProfileSubcommand::List) => self.list_profiles(&config_path).await,
|
||||
Some(ProfileSubcommand::Show { name }) => self.show_profile(name.as_deref(), &config_path).await,
|
||||
Some(ProfileSubcommand::Edit { name }) => self.edit_profile(name, &config_path).await,
|
||||
Some(ProfileSubcommand::SetDefault { name }) => self.set_default(name, &config_path).await,
|
||||
Some(ProfileSubcommand::SetRepo { name }) => self.set_repo(name, &config_path).await,
|
||||
Some(ProfileSubcommand::Apply { name, global }) => self.apply_profile(name.as_deref(), *global, &config_path).await,
|
||||
Some(ProfileSubcommand::Switch) => self.switch_profile(&config_path).await,
|
||||
Some(ProfileSubcommand::Copy { from, to }) => self.copy_profile(from, to, &config_path).await,
|
||||
Some(ProfileSubcommand::Token { token_command }) => self.handle_token_command(token_command, &config_path).await,
|
||||
Some(ProfileSubcommand::Check { name }) => self.check_profile(name.as_deref(), &config_path).await,
|
||||
Some(ProfileSubcommand::Stats { name }) => self.show_stats(name.as_deref(), &config_path).await,
|
||||
None => self.list_profiles(&config_path).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_profile(&self) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
fn get_manager(&self, config_path: &Option<PathBuf>) -> Result<ConfigManager> {
|
||||
match config_path {
|
||||
Some(path) => ConfigManager::with_path(path),
|
||||
None => ConfigManager::new(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_profile(&self, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
println!("{}", "\nAdd new profile".bold());
|
||||
println!("{}", "─".repeat(40));
|
||||
@@ -244,8 +252,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn remove_profile(&self, name: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn remove_profile(&self, name: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
if !manager.has_profile(name) {
|
||||
bail!("Profile '{}' not found", name);
|
||||
@@ -269,8 +277,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn list_profiles(&self) -> Result<()> {
|
||||
let manager = ConfigManager::new()?;
|
||||
async fn list_profiles(&self, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let manager = self.get_manager(config_path)?;
|
||||
|
||||
let profiles = manager.list_profiles();
|
||||
|
||||
@@ -319,8 +327,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn show_profile(&self, name: Option<&str>) -> Result<()> {
|
||||
let manager = ConfigManager::new()?;
|
||||
async fn show_profile(&self, name: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let manager = self.get_manager(config_path)?;
|
||||
|
||||
let profile = if let Some(n) = name {
|
||||
manager.get_profile(n)
|
||||
@@ -380,8 +388,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn edit_profile(&self, name: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn edit_profile(&self, name: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
let profile = manager.get_profile(name)
|
||||
.ok_or_else(|| anyhow::anyhow!("Profile '{}' not found", name))?
|
||||
@@ -420,8 +428,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_default(&self, name: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn set_default(&self, name: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
manager.set_default_profile(Some(name.to_string()))?;
|
||||
manager.save()?;
|
||||
@@ -431,8 +439,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_repo(&self, name: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn set_repo(&self, name: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
let repo = find_repo(std::env::current_dir()?.as_path())?;
|
||||
|
||||
let repo_path = repo.path().to_string_lossy().to_string();
|
||||
@@ -453,8 +461,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn apply_profile(&self, name: Option<&str>, global: bool) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn apply_profile(&self, name: Option<&str>, global: bool, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
let profile_name = if let Some(n) = name {
|
||||
n.to_string()
|
||||
@@ -490,8 +498,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn switch_profile(&self) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn switch_profile(&self, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
let profiles: Vec<String> = manager.list_profiles()
|
||||
.into_iter()
|
||||
@@ -527,15 +535,15 @@ impl ProfileCommand {
|
||||
.interact()?;
|
||||
|
||||
if apply {
|
||||
self.apply_profile(Some(selected), false).await?;
|
||||
self.apply_profile(Some(selected), false, config_path).await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn copy_profile(&self, from: &str, to: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn copy_profile(&self, from: &str, to: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
let source = manager.get_profile(from)
|
||||
.ok_or_else(|| anyhow::anyhow!("Profile '{}' not found", from))?
|
||||
@@ -555,16 +563,16 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_token_command(&self, cmd: &TokenSubcommand) -> Result<()> {
|
||||
async fn handle_token_command(&self, cmd: &TokenSubcommand, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
match cmd {
|
||||
TokenSubcommand::Add { profile, service } => self.add_token(profile, service).await,
|
||||
TokenSubcommand::Remove { profile, service } => self.remove_token(profile, service).await,
|
||||
TokenSubcommand::List { profile } => self.list_tokens(profile).await,
|
||||
TokenSubcommand::Add { profile, service } => self.add_token(profile, service, config_path).await,
|
||||
TokenSubcommand::Remove { profile, service } => self.remove_token(profile, service, config_path).await,
|
||||
TokenSubcommand::List { profile } => self.list_tokens(profile, config_path).await,
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_token(&self, profile_name: &str, service: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn add_token(&self, profile_name: &str, service: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
if !manager.has_profile(profile_name) {
|
||||
bail!("Profile '{}' not found", profile_name);
|
||||
@@ -610,8 +618,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn remove_token(&self, profile_name: &str, service: &str) -> Result<()> {
|
||||
let mut manager = ConfigManager::new()?;
|
||||
async fn remove_token(&self, profile_name: &str, service: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let mut manager = self.get_manager(config_path)?;
|
||||
|
||||
if !manager.has_profile(profile_name) {
|
||||
bail!("Profile '{}' not found", profile_name);
|
||||
@@ -635,8 +643,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn list_tokens(&self, profile_name: &str) -> Result<()> {
|
||||
let manager = ConfigManager::new()?;
|
||||
async fn list_tokens(&self, profile_name: &str, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let manager = self.get_manager(config_path)?;
|
||||
|
||||
let profile = manager.get_profile(profile_name)
|
||||
.ok_or_else(|| anyhow::anyhow!("Profile '{}' not found", profile_name))?;
|
||||
@@ -662,8 +670,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn check_profile(&self, name: Option<&str>) -> Result<()> {
|
||||
let manager = ConfigManager::new()?;
|
||||
async fn check_profile(&self, name: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let manager = self.get_manager(config_path)?;
|
||||
|
||||
let profile_name = if let Some(n) = name {
|
||||
n.to_string()
|
||||
@@ -695,8 +703,8 @@ impl ProfileCommand {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn show_stats(&self, name: Option<&str>) -> Result<()> {
|
||||
let manager = ConfigManager::new()?;
|
||||
async fn show_stats(&self, name: Option<&str>, config_path: &Option<PathBuf>) -> Result<()> {
|
||||
let manager = self.get_manager(config_path)?;
|
||||
|
||||
if let Some(n) = name {
|
||||
let profile = manager.get_profile(n)
|
||||
|
||||
Reference in New Issue
Block a user