diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-07 16:05:00 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-09 02:56:28 +0800 |
| commit | 25ece73e61cd5a9076c63fe884c84a86b35b5b42 (patch) | |
| tree | 2536540b176ecc3d4c1ba0a50bf3031d4fe07591 /mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs | |
| parent | c2de5313748e7d5f8ad7efee9ffecb513994443a (diff) | |
feat: implement pkg-enable and pkg-disable commands
Add package enable/disable functionality with version matching
for pkg-enable, and fix help text to reflect implemented commands.
Diffstat (limited to 'mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs')
| -rw-r--r-- | mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs b/mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs new file mode 100644 index 0000000..679421c --- /dev/null +++ b/mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs @@ -0,0 +1,108 @@ +use std::{fs, io}; + +use mingling::{ + Grouped, Routable, ShellContext, Suggest, SuggestItem, + macros::{ + arg, buffer, chain, command, completion, metadata, pack, pack_err, r_println, renderer, + routeify, + }, + metadata::Description, + picker::{EntryPicker, PickerArg}, +}; + +use crate::{ + Next, + pkg_mgr::{ + ErrorNoDataDirectory, ErrorPackageNameRequired, ErrorPackageSpecInvalid, ResPackagesDir, + }, +}; + +/// Positional argument: package name +pub static ARG_NAME: PickerArg<String> = arg![String]; + +pack_err!(ErrorPackageNotEnabled = String); + +// The name of the package to disable +pack!(StatePkgDisable = String); + +#[derive(Debug, Default, Grouped)] +pub struct ResultPkgDisable { + pub name: String, + pub removed: bool, +} + +#[metadata(EntryPkgDisable)] +pub fn desc_pkg_disable() -> Description { + "Disable the specified package".into() +} + +#[command(node = "pkg-disable", routeify)] +pub fn package_disable(args: EntryPkgDisable, packages_dir: &ResPackagesDir) -> Next { + let name = args + .pick_or_route(&ARG_NAME, || ErrorPackageNameRequired::default().to_chain()) + .to_result()?; + let packages_dir = &packages_dir.path; + if packages_dir.as_os_str().is_empty() { + return ErrorNoDataDirectory::default().to_chain(); + } + if name.contains('/') || name.contains('\\') || name.contains("..") || name.contains('@') { + return ErrorPackageSpecInvalid::new(name).to_chain(); + } + + StatePkgDisable::new(name).to_chain() +} + +#[chain(routeify)] +pub fn handle_state_pkg_disable(p: StatePkgDisable, packages_dir: &ResPackagesDir) -> Next { + let name = p.inner; + let packages_dir = &packages_dir.path; + if packages_dir.as_os_str().is_empty() { + return ErrorNoDataDirectory::default().to_chain(); + } + + let file = packages_dir.join(&name); + if !file.is_file() { + return ErrorPackageNotEnabled::new(name).to_chain(); + } + fs::remove_file(&file).map_err(|e| { + io::Error::new( + e.kind(), + format!("failed to remove {}: {e}", file.display()), + ) + })?; + + ResultPkgDisable { + name, + removed: true, + } + .to_chain() +} + +#[renderer(buffer)] +pub fn render_result_pkg_disable(r: ResultPkgDisable) { + r_println!("Disabled {}", r.name); +} + +#[renderer(buffer)] +pub fn render_error_package_not_enabled(err: ErrorPackageNotEnabled) { + r_println!("error: package is not enabled: {}", err.info); +} + +#[completion(EntryPkgDisable)] +pub fn complete_pkg_disable(ctx: &ShellContext, packages_dir: &ResPackagesDir) -> Suggest { + if ctx.previous_word != "pkg-disable" { + return Suggest::FileCompletion; + } + let mut suggest = Suggest::new(); + if let Ok(entries) = fs::read_dir(&packages_dir.path) { + for entry in entries.flatten() { + if !entry.file_type().is_ok_and(|t| t.is_file()) { + continue; + } + if let Some(name) = entry.file_name().to_str() { + suggest.insert(SuggestItem::Simple(name.to_string())); + } + } + } + suggest +} |
