aboutsummaryrefslogtreecommitdiff
path: root/mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-08-07 16:05:00 +0800
committer魏曹先生 <1992414357@qq.com>2026-08-09 02:56:28 +0800
commit25ece73e61cd5a9076c63fe884c84a86b35b5b42 (patch)
tree2536540b176ecc3d4c1ba0a50bf3031d4fe07591 /mingling_cli/src/pkg_mgr/cmd_pkg_disable.rs
parentc2de5313748e7d5f8ad7efee9ffecb513994443a (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.rs108
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
+}