cli: fix global -y flag conflicts in add-prj` and sync commands
`AddPrjArgs` had a local `-y` flag that conflicted with the global flag, causing runtime panics. Removed the local field and updated callers to use `global_yes` consistently. The sync command now respects the global `-y` flag by accepting, you guessed it, the `global_yes` parameter. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I7b7c42fabbca0e363bd18a1d8b6b3bb76a6a6964
This commit is contained in:
parent
d4938c4ae8
commit
b0a594e892
3 changed files with 81 additions and 50 deletions
28
src/cli.rs
28
src/cli.rs
|
|
@ -15,6 +15,10 @@ pub struct Cli {
|
||||||
#[clap(short, long, action = clap::ArgAction::Count)]
|
#[clap(short, long, action = clap::ArgAction::Count)]
|
||||||
pub verbose: u8,
|
pub verbose: u8,
|
||||||
|
|
||||||
|
/// Skip all confirmation prompts (assume yes)
|
||||||
|
#[clap(short, long, global = true)]
|
||||||
|
pub yes: bool,
|
||||||
|
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
pub command: Commands,
|
pub command: Commands,
|
||||||
}
|
}
|
||||||
|
|
@ -107,10 +111,6 @@ pub struct InitArgs {
|
||||||
/// Mod loaders (format: name=version, can be specified multiple times)
|
/// Mod loaders (format: name=version, can be specified multiple times)
|
||||||
#[clap(short, long = "loaders", value_delimiter = ',')]
|
#[clap(short, long = "loaders", value_delimiter = ',')]
|
||||||
pub loaders: Option<Vec<String>>,
|
pub loaders: Option<Vec<String>>,
|
||||||
|
|
||||||
/// Skip interactive prompts (use defaults)
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub yes: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -121,10 +121,6 @@ pub struct ImportArgs {
|
||||||
/// Resolve dependencies
|
/// Resolve dependencies
|
||||||
#[clap(short = 'D', long = "deps")]
|
#[clap(short = 'D', long = "deps")]
|
||||||
pub deps: bool,
|
pub deps: bool,
|
||||||
|
|
||||||
/// Skip confirmation prompts
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub yes: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -144,10 +140,6 @@ pub struct AddArgs {
|
||||||
/// Update if already exists
|
/// Update if already exists
|
||||||
#[clap(short, long)]
|
#[clap(short, long)]
|
||||||
pub update: bool,
|
pub update: bool,
|
||||||
|
|
||||||
/// Skip confirmation prompts
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub yes: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -195,10 +187,6 @@ pub struct AddPrjArgs {
|
||||||
/// Skip resolving dependencies
|
/// Skip resolving dependencies
|
||||||
#[clap(short = 'D', long = "no-deps")]
|
#[clap(short = 'D', long = "no-deps")]
|
||||||
pub no_deps: bool,
|
pub no_deps: bool,
|
||||||
|
|
||||||
/// Skip confirmation prompts
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub yes: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
@ -211,10 +199,6 @@ pub struct RmArgs {
|
||||||
#[clap(short = 'a', long)]
|
#[clap(short = 'a', long)]
|
||||||
pub all: bool,
|
pub all: bool,
|
||||||
|
|
||||||
/// Skip confirmation prompt
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub yes: bool,
|
|
||||||
|
|
||||||
/// Skip removing dependent projects
|
/// Skip removing dependent projects
|
||||||
#[clap(short = 'D', long = "no-deps")]
|
#[clap(short = 'D', long = "no-deps")]
|
||||||
pub no_deps: bool,
|
pub no_deps: bool,
|
||||||
|
|
@ -229,10 +213,6 @@ pub struct UpdateArgs {
|
||||||
/// Update all projects
|
/// Update all projects
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
pub all: bool,
|
pub all: bool,
|
||||||
|
|
||||||
/// Skip confirmation prompts
|
|
||||||
#[arg(short, long)]
|
|
||||||
pub yes: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fs,
|
fs,
|
||||||
io::{self, Write},
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -22,6 +21,7 @@ enum SyncChange {
|
||||||
|
|
||||||
pub async fn execute(
|
pub async fn execute(
|
||||||
args: SyncArgs,
|
args: SyncArgs,
|
||||||
|
global_yes: bool,
|
||||||
lockfile_path: &Path,
|
lockfile_path: &Path,
|
||||||
config_path: &Path,
|
config_path: &Path,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
|
|
@ -66,7 +66,11 @@ pub async fn execute(
|
||||||
for (file_path, _) in &additions {
|
for (file_path, _) in &additions {
|
||||||
spinner
|
spinner
|
||||||
.set_message(format!("Processing addition: {}", file_path.display()));
|
.set_message(format!("Processing addition: {}", file_path.display()));
|
||||||
if prompt_user(&format!("Add {} to lockfile?", file_path.display()))? {
|
if crate::ui_utils::prompt_yes_no(
|
||||||
|
&format!("Add {} to lockfile?", file_path.display()),
|
||||||
|
false,
|
||||||
|
global_yes,
|
||||||
|
)? {
|
||||||
add_file_to_lockfile(&mut lockfile, file_path, &config).await?;
|
add_file_to_lockfile(&mut lockfile, file_path, &config).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +91,11 @@ pub async fn execute(
|
||||||
.or(project.pakku_id.as_deref())
|
.or(project.pakku_id.as_deref())
|
||||||
.unwrap_or("unknown");
|
.unwrap_or("unknown");
|
||||||
spinner.set_message(format!("Processing removal: {name}"));
|
spinner.set_message(format!("Processing removal: {name}"));
|
||||||
if prompt_user(&format!("Remove {name} from lockfile?"))? {
|
if crate::ui_utils::prompt_yes_no(
|
||||||
|
&format!("Remove {name} from lockfile?"),
|
||||||
|
false,
|
||||||
|
global_yes,
|
||||||
|
)? {
|
||||||
lockfile
|
lockfile
|
||||||
.remove_project(pakku_id)
|
.remove_project(pakku_id)
|
||||||
.ok_or_else(|| PakkerError::ProjectNotFound(pakku_id.clone()))?;
|
.ok_or_else(|| PakkerError::ProjectNotFound(pakku_id.clone()))?;
|
||||||
|
|
@ -174,7 +182,7 @@ async fn add_file_to_lockfile(
|
||||||
_config: &Config,
|
_config: &Config,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// Try to identify the file by hash lookup
|
// Try to identify the file by hash lookup
|
||||||
let _modrinth = ModrinthPlatform::new();
|
let modrinth = ModrinthPlatform::new();
|
||||||
let curseforge = CurseForgePlatform::new(None);
|
let curseforge = CurseForgePlatform::new(None);
|
||||||
|
|
||||||
// Compute file hash
|
// Compute file hash
|
||||||
|
|
@ -186,7 +194,7 @@ async fn add_file_to_lockfile(
|
||||||
let hash = format!("{:x}", hasher.finalize());
|
let hash = format!("{:x}", hasher.finalize());
|
||||||
|
|
||||||
// Try Modrinth first (SHA-1 hash)
|
// Try Modrinth first (SHA-1 hash)
|
||||||
if let Ok(Some(project)) = _modrinth.lookup_by_hash(&hash).await {
|
if let Ok(Some(project)) = modrinth.lookup_by_hash(&hash).await {
|
||||||
lockfile.add_project(project);
|
lockfile.add_project(project);
|
||||||
println!("✓ Added {} (from Modrinth)", file_path.display());
|
println!("✓ Added {} (from Modrinth)", file_path.display());
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
|
@ -202,15 +210,3 @@ async fn add_file_to_lockfile(
|
||||||
println!("⚠ Could not identify {}, skipping", file_path.display());
|
println!("⚠ Could not identify {}, skipping", file_path.display());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prompt_user(message: &str) -> Result<bool> {
|
|
||||||
print!("{message} [y/N] ");
|
|
||||||
io::stdout().flush().map_err(PakkerError::IoError)?;
|
|
||||||
|
|
||||||
let mut input = String::new();
|
|
||||||
io::stdin()
|
|
||||||
.read_line(&mut input)
|
|
||||||
.map_err(PakkerError::IoError)?;
|
|
||||||
|
|
||||||
Ok(input.trim().eq_ignore_ascii_case("y"))
|
|
||||||
}
|
|
||||||
|
|
|
||||||
73
src/main.rs
73
src/main.rs
|
|
@ -18,12 +18,31 @@ mod resolver;
|
||||||
mod ui_utils;
|
mod ui_utils;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::{env, path::PathBuf};
|
||||||
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use cli::{Cli, Commands};
|
use cli::{Cli, Commands};
|
||||||
use error::PakkerError;
|
use error::PakkerError;
|
||||||
|
|
||||||
|
/// Search for pakker-lock.json in current directory and parent directories
|
||||||
|
/// Returns the directory containing pakker-lock.json, or None if not found
|
||||||
|
fn find_working_directory() -> Option<PathBuf> {
|
||||||
|
let mut current_dir = env::current_dir().ok()?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let lockfile = current_dir.join("pakker-lock.json");
|
||||||
|
if lockfile.exists() {
|
||||||
|
return Some(current_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try parent directory
|
||||||
|
if !current_dir.pop() {
|
||||||
|
// Reached filesystem root
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), PakkerError> {
|
async fn main() -> Result<(), PakkerError> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
@ -43,19 +62,41 @@ async fn main() -> Result<(), PakkerError> {
|
||||||
.format_module_path(false)
|
.format_module_path(false)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let working_dir = PathBuf::from(".");
|
// Search for pakker-lock.json in current directory and parent directories
|
||||||
|
let working_dir =
|
||||||
|
find_working_directory().unwrap_or_else(|| PathBuf::from("."));
|
||||||
let lockfile_path = working_dir.join("pakker-lock.json");
|
let lockfile_path = working_dir.join("pakker-lock.json");
|
||||||
let config_path = working_dir.join("pakker.json");
|
let config_path = working_dir.join("pakker.json");
|
||||||
|
|
||||||
|
let global_yes = cli.yes;
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Commands::Init(args) => {
|
Commands::Init(args) => {
|
||||||
cli::commands::init::execute(args, &lockfile_path, &config_path).await
|
cli::commands::init::execute(
|
||||||
|
args,
|
||||||
|
global_yes,
|
||||||
|
&lockfile_path,
|
||||||
|
&config_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
},
|
},
|
||||||
Commands::Import(args) => {
|
Commands::Import(args) => {
|
||||||
cli::commands::import::execute(args, &lockfile_path, &config_path).await
|
cli::commands::import::execute(
|
||||||
|
args,
|
||||||
|
global_yes,
|
||||||
|
&lockfile_path,
|
||||||
|
&config_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
},
|
},
|
||||||
Commands::Add(args) => {
|
Commands::Add(args) => {
|
||||||
cli::commands::add::execute(args, &lockfile_path, &config_path).await
|
cli::commands::add::execute(
|
||||||
|
args,
|
||||||
|
global_yes,
|
||||||
|
&lockfile_path,
|
||||||
|
&config_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
},
|
},
|
||||||
Commands::AddPrj(args) => {
|
Commands::AddPrj(args) => {
|
||||||
cli::commands::add_prj::execute(
|
cli::commands::add_prj::execute(
|
||||||
|
|
@ -70,17 +111,24 @@ async fn main() -> Result<(), PakkerError> {
|
||||||
args.aliases,
|
args.aliases,
|
||||||
args.export,
|
args.export,
|
||||||
args.no_deps,
|
args.no_deps,
|
||||||
args.yes,
|
global_yes,
|
||||||
&lockfile_path,
|
&lockfile_path,
|
||||||
&config_path,
|
&config_path,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
},
|
},
|
||||||
Commands::Rm(args) => {
|
Commands::Rm(args) => {
|
||||||
cli::commands::rm::execute(args, &lockfile_path, &config_path).await
|
cli::commands::rm::execute(args, global_yes, &lockfile_path, &config_path)
|
||||||
|
.await
|
||||||
},
|
},
|
||||||
Commands::Update(args) => {
|
Commands::Update(args) => {
|
||||||
cli::commands::update::execute(args, &lockfile_path, &config_path).await
|
cli::commands::update::execute(
|
||||||
|
args,
|
||||||
|
global_yes,
|
||||||
|
&lockfile_path,
|
||||||
|
&config_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
},
|
},
|
||||||
Commands::Ls(args) => cli::commands::ls::execute(args, &lockfile_path),
|
Commands::Ls(args) => cli::commands::ls::execute(args, &lockfile_path),
|
||||||
Commands::Set(args) => {
|
Commands::Set(args) => {
|
||||||
|
|
@ -95,7 +143,13 @@ async fn main() -> Result<(), PakkerError> {
|
||||||
cli::commands::fetch::execute(args, &lockfile_path, &config_path).await
|
cli::commands::fetch::execute(args, &lockfile_path, &config_path).await
|
||||||
},
|
},
|
||||||
Commands::Sync(args) => {
|
Commands::Sync(args) => {
|
||||||
cli::commands::sync::execute(args, &lockfile_path, &config_path).await
|
cli::commands::sync::execute(
|
||||||
|
args,
|
||||||
|
global_yes,
|
||||||
|
&lockfile_path,
|
||||||
|
&config_path,
|
||||||
|
)
|
||||||
|
.await
|
||||||
},
|
},
|
||||||
Commands::Export(args) => {
|
Commands::Export(args) => {
|
||||||
cli::commands::export::execute(args, &lockfile_path, &config_path).await
|
cli::commands::export::execute(args, &lockfile_path, &config_path).await
|
||||||
|
|
@ -107,6 +161,7 @@ async fn main() -> Result<(), PakkerError> {
|
||||||
Commands::Status(args) => {
|
Commands::Status(args) => {
|
||||||
cli::commands::status::execute(
|
cli::commands::status::execute(
|
||||||
args.parallel,
|
args.parallel,
|
||||||
|
global_yes,
|
||||||
&lockfile_path,
|
&lockfile_path,
|
||||||
&config_path,
|
&config_path,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue