mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-01 10:01:07 +02:00
feat(cli): add tauri remove command (#11322)
This commit is contained in:
6
.changes/cli-remove-command.md
Normal file
6
.changes/cli-remove-command.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": minor:feat
|
||||
"@tauri-apps/cli": minor:feat
|
||||
---
|
||||
|
||||
Add `tauri remove` to remove plugins from projects.
|
||||
@@ -9,7 +9,7 @@ use crate::Result;
|
||||
pub mod add;
|
||||
mod ls;
|
||||
mod new;
|
||||
mod rm;
|
||||
pub mod rm;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(about = "Manage or create permissions for your app or plugin")]
|
||||
|
||||
@@ -46,13 +46,15 @@ fn rm_permission_files(identifier: &str, dir: &Path) -> Result<()> {
|
||||
permission_file.default = None;
|
||||
} else {
|
||||
let set_len = permission_file.set.len();
|
||||
permission_file.set.retain(|s| s.identifier != identifier);
|
||||
permission_file
|
||||
.set
|
||||
.retain(|s| !identifier_match(identifier, &s.identifier));
|
||||
updated = permission_file.set.len() != set_len;
|
||||
|
||||
let permission_len = permission_file.permission.len();
|
||||
permission_file
|
||||
.permission
|
||||
.retain(|s| s.identifier != identifier);
|
||||
.retain(|s| !identifier_match(identifier, &s.identifier));
|
||||
updated = updated || permission_file.permission.len() != permission_len;
|
||||
}
|
||||
|
||||
@@ -84,7 +86,11 @@ fn rm_permission_from_capabilities(identifier: &str, dir: &Path) -> Result<()> {
|
||||
if let Ok(mut value) = content.parse::<toml_edit::DocumentMut>() {
|
||||
if let Some(permissions) = value.get_mut("permissions").and_then(|p| p.as_array_mut()) {
|
||||
let prev_len = permissions.len();
|
||||
permissions.retain(|p| p.as_str().map(|p| p != identifier).unwrap_or(false));
|
||||
permissions.retain(|p| {
|
||||
p.as_str()
|
||||
.map(|p| !identifier_match(identifier, p))
|
||||
.unwrap_or(false)
|
||||
});
|
||||
if prev_len != permissions.len() {
|
||||
std::fs::write(&path, value.to_string())?;
|
||||
log::info!(action = "Removed"; "permission from capability at {}", dunce::simplified(&path).display());
|
||||
@@ -97,7 +103,11 @@ fn rm_permission_from_capabilities(identifier: &str, dir: &Path) -> Result<()> {
|
||||
if let Ok(mut value) = serde_json::from_slice::<serde_json::Value>(&content) {
|
||||
if let Some(permissions) = value.get_mut("permissions").and_then(|p| p.as_array_mut()) {
|
||||
let prev_len = permissions.len();
|
||||
permissions.retain(|p| p.as_str().map(|p| p != identifier).unwrap_or(false));
|
||||
permissions.retain(|p| {
|
||||
p.as_str()
|
||||
.map(|p| !identifier_match(identifier, p))
|
||||
.unwrap_or(false)
|
||||
});
|
||||
if prev_len != permissions.len() {
|
||||
std::fs::write(&path, serde_json::to_vec_pretty(&value)?)?;
|
||||
log::info!(action = "Removed"; "permission from capability at {}", dunce::simplified(&path).display());
|
||||
@@ -113,11 +123,20 @@ fn rm_permission_from_capabilities(identifier: &str, dir: &Path) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn identifier_match(identifier: &str, permission: &str) -> bool {
|
||||
match identifier.split_once(':') {
|
||||
Some((plugin_name, "*")) => permission.contains(plugin_name),
|
||||
_ => permission == identifier,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(about = "Remove a permission file, and its reference from any capability")]
|
||||
pub struct Options {
|
||||
/// Permission to remove.
|
||||
identifier: String,
|
||||
///
|
||||
/// To remove all permissions for a given plugin, provide `<plugin-name>:*`
|
||||
pub identifier: String,
|
||||
}
|
||||
|
||||
pub fn command(options: Options) -> Result<()> {
|
||||
|
||||
@@ -61,3 +61,33 @@ pub fn install_one(options: CargoInstallOptions) -> crate::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub struct CargoUninstallOptions<'a> {
|
||||
pub name: &'a str,
|
||||
pub cwd: Option<&'a std::path::Path>,
|
||||
pub target: Option<&'a str>,
|
||||
}
|
||||
|
||||
pub fn uninstall_one(options: CargoUninstallOptions) -> crate::Result<()> {
|
||||
let mut cargo = Command::new("cargo");
|
||||
cargo.arg("remove");
|
||||
|
||||
cargo.arg(options.name);
|
||||
|
||||
if let Some(target) = options.target {
|
||||
cargo.args(["--target", target]);
|
||||
}
|
||||
|
||||
if let Some(cwd) = options.cwd {
|
||||
cargo.current_dir(cwd);
|
||||
}
|
||||
|
||||
log::info!("Uninstalling Cargo dependency \"{}\"...", options.name);
|
||||
let status = cargo.status().context("failed to run `cargo remove`")?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("Failed to remove Cargo dependency");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ mod interface;
|
||||
mod migrate;
|
||||
mod mobile;
|
||||
mod plugin;
|
||||
mod remove;
|
||||
mod signer;
|
||||
|
||||
use clap::{ArgAction, CommandFactory, FromArgMatches, Parser, Subcommand, ValueEnum};
|
||||
@@ -146,6 +147,7 @@ enum Commands {
|
||||
Migrate,
|
||||
Info(info::Options),
|
||||
Add(add::Options),
|
||||
Remove(remove::Options),
|
||||
Plugin(plugin::Cli),
|
||||
Icon(icon::Options),
|
||||
Signer(signer::Cli),
|
||||
@@ -265,6 +267,7 @@ where
|
||||
Commands::Bundle(options) => bundle::command(options, cli.verbose)?,
|
||||
Commands::Dev(options) => dev::command(options)?,
|
||||
Commands::Add(options) => add::command(options)?,
|
||||
Commands::Remove(options) => remove::command(options)?,
|
||||
Commands::Icon(options) => icon::command(options)?,
|
||||
Commands::Info(options) => info::command(options)?,
|
||||
Commands::Init(options) => init::command(options)?,
|
||||
|
||||
69
crates/tauri-cli/src/remove.rs
Normal file
69
crates/tauri-cli/src/remove.rs
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use crate::{
|
||||
acl,
|
||||
helpers::{
|
||||
app_paths::{resolve_frontend_dir, tauri_dir},
|
||||
cargo,
|
||||
npm::PackageManager,
|
||||
},
|
||||
Result,
|
||||
};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[clap(about = "Remove a tauri plugin from the project")]
|
||||
pub struct Options {
|
||||
/// The plugin to remove.
|
||||
pub plugin: String,
|
||||
}
|
||||
|
||||
pub fn command(options: Options) -> Result<()> {
|
||||
crate::helpers::app_paths::resolve();
|
||||
run(options)
|
||||
}
|
||||
|
||||
pub fn run(options: Options) -> Result<()> {
|
||||
let plugin = options.plugin;
|
||||
|
||||
let crate_name = format!("tauri-plugin-{plugin}");
|
||||
|
||||
let mut plugins = crate::helpers::plugins::known_plugins();
|
||||
let metadata = plugins.remove(plugin.as_str()).unwrap_or_default();
|
||||
|
||||
let frontend_dir = resolve_frontend_dir();
|
||||
let tauri_dir = tauri_dir();
|
||||
|
||||
let target_str = metadata
|
||||
.desktop_only
|
||||
.then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#)
|
||||
.or_else(|| {
|
||||
metadata
|
||||
.mobile_only
|
||||
.then_some(r#"cfg(any(target_os = "android", target_os = "ios"))"#)
|
||||
});
|
||||
|
||||
cargo::uninstall_one(cargo::CargoUninstallOptions {
|
||||
name: &crate_name,
|
||||
cwd: Some(tauri_dir),
|
||||
target: target_str,
|
||||
})?;
|
||||
|
||||
if !metadata.rust_only {
|
||||
if let Some(manager) = frontend_dir.map(PackageManager::from_project) {
|
||||
let npm_name = format!("@tauri-apps/plugin-{plugin}");
|
||||
manager.remove(&[npm_name], tauri_dir)?;
|
||||
}
|
||||
|
||||
acl::permission::rm::command(acl::permission::rm::Options {
|
||||
identifier: format!("{plugin}:*"),
|
||||
})?;
|
||||
}
|
||||
|
||||
log::info!("Now, you must manually remove the plugin from your Rust code.",);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user