mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-08-16 19:30:27 +03:00
feat(cli/add): add default permission to capabilities (#9124)
* feat(cli/add): add default permission to capabilities also cleanup `tauri add` command * license headers & clippy * print permission name * do not error out if default permission is not set --------- Co-authored-by: Lucas Nogueira <lucas@tauri.app>
This commit is contained in:
parent
acdd76833d
commit
7213b9e472
6
.changes/acl-default-permission-verification.md
Normal file
6
.changes/acl-default-permission-verification.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"tauri-build": patch:enhance
|
||||||
|
"tauri-utils": patch:enhance
|
||||||
|
---
|
||||||
|
|
||||||
|
Fallback to an empty permission set if the plugin did not define its `default` permissions.
|
6
.changes/tauri-cli-add-default-perm.md
Normal file
6
.changes/tauri-cli-add-default-perm.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
'tauri-cli': 'patch:feat'
|
||||||
|
'@tauri-apps/cli': 'patch:feat'
|
||||||
|
---
|
||||||
|
|
||||||
|
Add default permission for a plugin to capabilities when using `tauri add <plugin>`.
|
@ -131,13 +131,14 @@ fn capabilities_schema(acl_manifests: &BTreeMap<String, Manifest>) -> RootSchema
|
|||||||
permission_schemas.push(schema_from(key, set_id, Some(&set.description)));
|
permission_schemas.push(schema_from(key, set_id, Some(&set.description)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(default) = &manifest.default_permission {
|
permission_schemas.push(schema_from(
|
||||||
permission_schemas.push(schema_from(
|
key,
|
||||||
key,
|
"default",
|
||||||
"default",
|
manifest
|
||||||
Some(default.description.as_ref()),
|
.default_permission
|
||||||
));
|
.as_ref()
|
||||||
}
|
.map(|d| d.description.as_ref()),
|
||||||
|
));
|
||||||
|
|
||||||
for (permission_id, permission) in &manifest.permissions {
|
for (permission_id, permission) in &manifest.permissions {
|
||||||
permission_schemas.push(schema_from(
|
permission_schemas.push(schema_from(
|
||||||
@ -198,9 +199,14 @@ fn capabilities_schema(acl_manifests: &BTreeMap<String, Manifest>) -> RootSchema
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut permission_schemas = Vec::new();
|
let mut permission_schemas = Vec::new();
|
||||||
if let Some(default) = &manifest.default_permission {
|
permission_schemas.push(schema_from(
|
||||||
permission_schemas.push(schema_from(key, "default", Some(&default.description)));
|
key,
|
||||||
}
|
"default",
|
||||||
|
manifest
|
||||||
|
.default_permission
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| d.description.as_ref()),
|
||||||
|
));
|
||||||
for set in manifest.permission_sets.values() {
|
for set in manifest.permission_sets.values() {
|
||||||
permission_schemas.push(schema_from(key, &set.identifier, Some(&set.description)));
|
permission_schemas.push(schema_from(key, &set.identifier, Some(&set.description)));
|
||||||
}
|
}
|
||||||
@ -471,12 +477,10 @@ pub fn validate_capabilities(
|
|||||||
let permission_exists = acl_manifests
|
let permission_exists = acl_manifests
|
||||||
.get(key)
|
.get(key)
|
||||||
.map(|manifest| {
|
.map(|manifest| {
|
||||||
if permission_name == "default" {
|
// the default permission is always treated as valid, the CLI automatically adds it on the `tauri add` command
|
||||||
manifest.default_permission.is_some()
|
permission_name == "default"
|
||||||
} else {
|
|| manifest.permissions.contains_key(permission_name)
|
||||||
manifest.permissions.contains_key(permission_name)
|
|| manifest.permission_sets.contains_key(permission_name)
|
||||||
|| manifest.permission_sets.contains_key(permission_name)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
@ -367,15 +367,8 @@ fn get_permissions<'a>(
|
|||||||
manifest
|
manifest
|
||||||
.default_permission
|
.default_permission
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| Error::UnknownPermission {
|
.map(|default| get_permission_set_permissions(manifest, default))
|
||||||
key: if key == APP_ACL_KEY {
|
.unwrap_or_else(|| Ok(Vec::new()))
|
||||||
"app manifest".to_string()
|
|
||||||
} else {
|
|
||||||
key.to_string()
|
|
||||||
},
|
|
||||||
permission: permission_name.to_string(),
|
|
||||||
})
|
|
||||||
.and_then(|default| get_permission_set_permissions(manifest, default))
|
|
||||||
} else if let Some(set) = manifest.permission_sets.get(permission_name) {
|
} else if let Some(set) = manifest.permission_sets.get(permission_name) {
|
||||||
get_permission_set_permissions(manifest, set)
|
get_permission_set_permissions(manifest, set)
|
||||||
} else if let Some(permission) = manifest.permissions.get(permission_name) {
|
} else if let Some(permission) = manifest.permissions.get(permission_name) {
|
||||||
|
@ -80,10 +80,10 @@ fn capability_from_path<P: AsRef<Path>>(path: P) -> Option<TomlOrJson> {
|
|||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[clap(about = "Add a permission to capabilities")]
|
#[clap(about = "Add a permission to capabilities")]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
/// Permission to remove.
|
/// Permission to add.
|
||||||
identifier: String,
|
pub identifier: String,
|
||||||
/// Capability to add the permission to.
|
/// Capability to add the permission to.
|
||||||
capability: Option<String>,
|
pub capability: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn command(options: Options) -> Result<()> {
|
pub fn command(options: Options) -> Result<()> {
|
||||||
@ -114,7 +114,10 @@ pub fn command(options: Options) -> Result<()> {
|
|||||||
|
|
||||||
let mut capabilities = if capabilities.len() > 1 {
|
let mut capabilities = if capabilities.len() > 1 {
|
||||||
let selections = prompts::multiselect(
|
let selections = prompts::multiselect(
|
||||||
"Choose which capabilities to add the permission to:",
|
&format!(
|
||||||
|
"Choose which capabilities to add the permission `{}` to:",
|
||||||
|
options.identifier
|
||||||
|
),
|
||||||
capabilities
|
capabilities
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(c, p)| {
|
.map(|(c, p)| {
|
||||||
|
@ -6,7 +6,7 @@ use clap::{Parser, Subcommand};
|
|||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
|
|
||||||
mod add;
|
pub mod add;
|
||||||
mod ls;
|
mod ls;
|
||||||
mod new;
|
mod new;
|
||||||
mod rm;
|
mod rm;
|
||||||
|
@ -2,15 +2,15 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
acl,
|
||||||
helpers::{
|
helpers::{
|
||||||
app_paths::{app_dir, tauri_dir},
|
app_paths::{app_dir, tauri_dir},
|
||||||
cross_command,
|
cargo,
|
||||||
npm::PackageManager,
|
npm::PackageManager,
|
||||||
},
|
},
|
||||||
Result,
|
Result,
|
||||||
@ -18,165 +18,6 @@ use crate::{
|
|||||||
|
|
||||||
use std::{collections::HashMap, process::Command};
|
use std::{collections::HashMap, process::Command};
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
|
||||||
#[clap(about = "Add a tauri plugin to the project")]
|
|
||||||
pub struct Options {
|
|
||||||
/// The plugin to add.
|
|
||||||
pub plugin: String,
|
|
||||||
/// Git tag to use.
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub tag: Option<String>,
|
|
||||||
/// Git rev to use.
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub rev: Option<String>,
|
|
||||||
/// Git branch to use.
|
|
||||||
#[clap(short, long)]
|
|
||||||
pub branch: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn command(options: Options) -> Result<()> {
|
|
||||||
let plugin = options.plugin;
|
|
||||||
let plugin_snake_case = plugin.replace('-', "_");
|
|
||||||
let crate_name = format!("tauri-plugin-{plugin}");
|
|
||||||
let npm_name = format!("@tauri-apps/plugin-{plugin}");
|
|
||||||
|
|
||||||
let mut plugins = plugins();
|
|
||||||
let metadata = plugins.remove(plugin.as_str()).unwrap_or_default();
|
|
||||||
|
|
||||||
let tauri_dir = tauri_dir();
|
|
||||||
|
|
||||||
let mut cargo = Command::new("cargo");
|
|
||||||
cargo.current_dir(&tauri_dir).arg("add").arg(&crate_name);
|
|
||||||
|
|
||||||
if options.tag.is_some() || options.rev.is_some() || options.branch.is_some() {
|
|
||||||
cargo
|
|
||||||
.arg("--git")
|
|
||||||
.arg("https://github.com/tauri-apps/plugins-workspace");
|
|
||||||
}
|
|
||||||
|
|
||||||
if metadata.desktop_only {
|
|
||||||
cargo
|
|
||||||
.arg("--target")
|
|
||||||
.arg(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#);
|
|
||||||
}
|
|
||||||
|
|
||||||
let npm_spec = match (options.tag, options.rev, options.branch) {
|
|
||||||
(Some(tag), None, None) => {
|
|
||||||
cargo.args(["--tag", &tag]);
|
|
||||||
format!("tauri-apps/tauri-plugin-{plugin}#{tag}")
|
|
||||||
}
|
|
||||||
(None, Some(rev), None) => {
|
|
||||||
cargo.args(["--rev", &rev]);
|
|
||||||
format!("tauri-apps/tauri-plugin-{plugin}#{rev}")
|
|
||||||
}
|
|
||||||
(None, None, Some(branch)) => {
|
|
||||||
cargo.args(["--branch", &branch]);
|
|
||||||
format!("tauri-apps/tauri-plugin-{plugin}#{branch}")
|
|
||||||
}
|
|
||||||
(None, None, None) => npm_name,
|
|
||||||
_ => anyhow::bail!("Only one of --tag, --rev and --branch can be specified"),
|
|
||||||
};
|
|
||||||
|
|
||||||
log::info!("Installing Cargo dependency {crate_name}...");
|
|
||||||
let status = cargo.status().context("failed to run `cargo add`")?;
|
|
||||||
if !status.success() {
|
|
||||||
anyhow::bail!("Failed to install Cargo dependency");
|
|
||||||
}
|
|
||||||
|
|
||||||
if !metadata.rust_only {
|
|
||||||
if let Some(manager) = std::panic::catch_unwind(app_dir)
|
|
||||||
.map(Some)
|
|
||||||
.unwrap_or_default()
|
|
||||||
.map(PackageManager::from_project)
|
|
||||||
.and_then(|managers| managers.into_iter().next())
|
|
||||||
{
|
|
||||||
let mut cmd = match manager {
|
|
||||||
PackageManager::Npm => cross_command("npm"),
|
|
||||||
PackageManager::Pnpm => cross_command("pnpm"),
|
|
||||||
PackageManager::Yarn => cross_command("yarn"),
|
|
||||||
PackageManager::YarnBerry => cross_command("yarn"),
|
|
||||||
PackageManager::Bun => cross_command("bun"),
|
|
||||||
};
|
|
||||||
|
|
||||||
cmd.arg("add").arg(&npm_spec);
|
|
||||||
|
|
||||||
log::info!("Installing NPM dependency {npm_spec}...");
|
|
||||||
let status = cmd
|
|
||||||
.status()
|
|
||||||
.with_context(|| format!("failed to run {manager}"))?;
|
|
||||||
if !status.success() {
|
|
||||||
anyhow::bail!("Failed to install NPM dependency");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add plugin init code to main.rs or lib.rs
|
|
||||||
let plugin_init_fn = if plugin == "stronghold" {
|
|
||||||
"Builder::new(|pass| todo!()).build()"
|
|
||||||
} else if metadata.builder {
|
|
||||||
"Builder::new().build()"
|
|
||||||
} else {
|
|
||||||
"init()"
|
|
||||||
};
|
|
||||||
let plugin_init = format!(".plugin(tauri_plugin_{plugin_snake_case}::{plugin_init_fn})");
|
|
||||||
let re = Regex::new(r"(tauri\s*::\s*Builder\s*::\s*default\(\))(\s*)")?;
|
|
||||||
for file in [tauri_dir.join("src/main.rs"), tauri_dir.join("src/lib.rs")] {
|
|
||||||
let contents = std::fs::read_to_string(&file)?;
|
|
||||||
|
|
||||||
if contents.contains(&plugin_init) {
|
|
||||||
log::info!(
|
|
||||||
"Plugin initialization code already found on {}",
|
|
||||||
file.display()
|
|
||||||
);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if re.is_match(&contents) {
|
|
||||||
let out = re.replace(&contents, format!("$1$2{plugin_init}$2"));
|
|
||||||
|
|
||||||
log::info!("Adding plugin to {}", file.display());
|
|
||||||
std::fs::write(file, out.as_bytes())?;
|
|
||||||
|
|
||||||
// run cargo fmt
|
|
||||||
log::info!("Running `cargo fmt`...");
|
|
||||||
let _ = Command::new("cargo")
|
|
||||||
.arg("fmt")
|
|
||||||
.current_dir(&tauri_dir)
|
|
||||||
.status();
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let builder_code = if metadata.builder {
|
|
||||||
format!(r#"+ .plugin(tauri_plugin_{plugin_snake_case}::Builder::new().build())"#,)
|
|
||||||
} else {
|
|
||||||
format!(r#"+ .plugin(tauri_plugin_{plugin_snake_case}::init())"#)
|
|
||||||
};
|
|
||||||
|
|
||||||
let rust_code = format!(
|
|
||||||
r#" {}
|
|
||||||
{}
|
|
||||||
{}"#,
|
|
||||||
"tauri::Builder::default()".dimmed(),
|
|
||||||
builder_code.normal().green(),
|
|
||||||
r#".invoke_handler(tauri::generate_handler![])
|
|
||||||
.run(tauri::generate_context!())
|
|
||||||
.expect("error while running tauri application");"#
|
|
||||||
.dimmed(),
|
|
||||||
);
|
|
||||||
|
|
||||||
log::warn!(
|
|
||||||
"Couldn't find `{}` in `{}` or `{}`, you must enable the plugin in your Rust code manually:\n\n{}",
|
|
||||||
"tauri::Builder".cyan(),
|
|
||||||
"main.rs".cyan(),
|
|
||||||
"lib.rs".cyan(),
|
|
||||||
rust_code
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct PluginMetadata {
|
struct PluginMetadata {
|
||||||
desktop_only: bool,
|
desktop_only: bool,
|
||||||
@ -221,3 +62,137 @@ fn plugins() -> HashMap<&'static str, PluginMetadata> {
|
|||||||
|
|
||||||
plugins
|
plugins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[clap(about = "Add a tauri plugin to the project")]
|
||||||
|
pub struct Options {
|
||||||
|
/// The plugin to add.
|
||||||
|
pub plugin: String,
|
||||||
|
/// Git tag to use.
|
||||||
|
#[clap(short, long)]
|
||||||
|
pub tag: Option<String>,
|
||||||
|
/// Git rev to use.
|
||||||
|
#[clap(short, long)]
|
||||||
|
pub rev: Option<String>,
|
||||||
|
/// Git branch to use.
|
||||||
|
#[clap(short, long)]
|
||||||
|
pub branch: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn command(options: Options) -> Result<()> {
|
||||||
|
let plugin = options.plugin;
|
||||||
|
let plugin_snake_case = plugin.replace('-', "_");
|
||||||
|
let crate_name = format!("tauri-plugin-{plugin}");
|
||||||
|
let npm_name = format!("@tauri-apps/plugin-{plugin}");
|
||||||
|
|
||||||
|
let mut plugins = plugins();
|
||||||
|
let metadata = plugins.remove(plugin.as_str()).unwrap_or_default();
|
||||||
|
|
||||||
|
let tauri_dir = tauri_dir();
|
||||||
|
|
||||||
|
cargo::install_one(cargo::CargoInstallOptions {
|
||||||
|
name: &crate_name,
|
||||||
|
branch: options.branch.as_deref(),
|
||||||
|
rev: options.rev.as_deref(),
|
||||||
|
tag: options.tag.as_deref(),
|
||||||
|
cwd: Some(&tauri_dir),
|
||||||
|
target: metadata
|
||||||
|
.desktop_only
|
||||||
|
.then_some(r#"cfg(not(any(target_os = "android", target_os = "ios")))"#),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if !metadata.rust_only {
|
||||||
|
if let Some(manager) = std::panic::catch_unwind(app_dir)
|
||||||
|
.map(Some)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.map(PackageManager::from_project)
|
||||||
|
.and_then(|managers| managers.into_iter().next())
|
||||||
|
{
|
||||||
|
let npm_spec = match (options.tag, options.rev, options.branch) {
|
||||||
|
(Some(tag), None, None) => {
|
||||||
|
format!("tauri-apps/tauri-plugin-{plugin}#{tag}")
|
||||||
|
}
|
||||||
|
(None, Some(rev), None) => {
|
||||||
|
format!("tauri-apps/tauri-plugin-{plugin}#{rev}")
|
||||||
|
}
|
||||||
|
(None, None, Some(branch)) => {
|
||||||
|
format!("tauri-apps/tauri-plugin-{plugin}#{branch}")
|
||||||
|
}
|
||||||
|
(None, None, None) => npm_name,
|
||||||
|
_ => anyhow::bail!("Only one of --tag, --rev and --branch can be specified"),
|
||||||
|
};
|
||||||
|
manager.install(&[npm_spec])?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = acl::permission::add::command(acl::permission::add::Options {
|
||||||
|
identifier: format!("{plugin}:default"),
|
||||||
|
capability: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
// add plugin init code to main.rs or lib.rs
|
||||||
|
let plugin_init_fn = if plugin == "stronghold" {
|
||||||
|
"Builder::new(|pass| todo!()).build()"
|
||||||
|
} else if metadata.builder {
|
||||||
|
"Builder::new().build()"
|
||||||
|
} else {
|
||||||
|
"init()"
|
||||||
|
};
|
||||||
|
let plugin_init = format!(".plugin(tauri_plugin_{plugin_snake_case}::{plugin_init_fn})");
|
||||||
|
|
||||||
|
let re = Regex::new(r"(tauri\s*::\s*Builder\s*::\s*default\(\))(\s*)")?;
|
||||||
|
for file in [tauri_dir.join("src/main.rs"), tauri_dir.join("src/lib.rs")] {
|
||||||
|
let contents = std::fs::read_to_string(&file)?;
|
||||||
|
|
||||||
|
if contents.contains(&plugin_init) {
|
||||||
|
log::info!(
|
||||||
|
"Plugin initialization code already found on {}",
|
||||||
|
file.display()
|
||||||
|
);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if re.is_match(&contents) {
|
||||||
|
let out = re.replace(&contents, format!("$1$2{plugin_init}$2"));
|
||||||
|
|
||||||
|
log::info!("Adding plugin to {}", file.display());
|
||||||
|
std::fs::write(file, out.as_bytes())?;
|
||||||
|
|
||||||
|
// run cargo fmt
|
||||||
|
log::info!("Running `cargo fmt`...");
|
||||||
|
let _ = Command::new("cargo")
|
||||||
|
.arg("fmt")
|
||||||
|
.current_dir(&tauri_dir)
|
||||||
|
.status();
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let builder_code = if metadata.builder {
|
||||||
|
format!(r#"+ .plugin(tauri_plugin_{plugin_snake_case}::Builder::new().build())"#,)
|
||||||
|
} else {
|
||||||
|
format!(r#"+ .plugin(tauri_plugin_{plugin_snake_case}::init())"#)
|
||||||
|
};
|
||||||
|
|
||||||
|
let rust_code = format!(
|
||||||
|
r#" {}
|
||||||
|
{}
|
||||||
|
{}"#,
|
||||||
|
"tauri::Builder::default()".dimmed(),
|
||||||
|
builder_code.normal().green(),
|
||||||
|
r#".invoke_handler(tauri::generate_handler![])
|
||||||
|
.run(tauri::generate_context!())
|
||||||
|
.expect("error while running tauri application");"#
|
||||||
|
.dimmed(),
|
||||||
|
);
|
||||||
|
|
||||||
|
log::warn!(
|
||||||
|
"Couldn't find `{}` in `{}` or `{}`, you must enable the plugin in your Rust code manually:\n\n{}",
|
||||||
|
"tauri::Builder".cyan(),
|
||||||
|
"main.rs".cyan(),
|
||||||
|
"lib.rs".cyan(),
|
||||||
|
rust_code
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
87
tooling/cli/src/helpers/cargo.rs
Normal file
87
tooling/cli/src/helpers/cargo.rs
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
use std::{path::Path, process::Command};
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Clone, Copy)]
|
||||||
|
pub struct CargoInstallOptions<'a> {
|
||||||
|
pub name: &'a str,
|
||||||
|
pub rev: Option<&'a str>,
|
||||||
|
pub tag: Option<&'a str>,
|
||||||
|
pub branch: Option<&'a str>,
|
||||||
|
pub cwd: Option<&'a std::path::Path>,
|
||||||
|
pub target: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn install(dependencies: &[String], cwd: Option<&Path>) -> crate::Result<()> {
|
||||||
|
let dependencies_str = if dependencies.len() > 1 {
|
||||||
|
"dependencies"
|
||||||
|
} else {
|
||||||
|
"dependency"
|
||||||
|
};
|
||||||
|
log::info!(
|
||||||
|
"Installing Cargo {dependencies_str} {}...",
|
||||||
|
dependencies
|
||||||
|
.iter()
|
||||||
|
.map(|d| format!("\"{d}\""))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut cmd = Command::new("cargo");
|
||||||
|
cmd.arg("add").args(dependencies);
|
||||||
|
|
||||||
|
if let Some(cwd) = cwd {
|
||||||
|
cmd.current_dir(cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
let status = cmd.status().with_context(|| "failed to run cargo")?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
anyhow::bail!("Failed to install Cargo {dependencies_str}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn install_one(options: CargoInstallOptions) -> crate::Result<()> {
|
||||||
|
let mut cargo = Command::new("cargo");
|
||||||
|
cargo.args(["add", options.name]);
|
||||||
|
|
||||||
|
if options.tag.is_some() || options.rev.is_some() || options.branch.is_some() {
|
||||||
|
cargo.args(["--git", "https://github.com/tauri-apps/plugins-workspace"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
match (options.tag, options.rev, options.branch) {
|
||||||
|
(Some(tag), None, None) => {
|
||||||
|
cargo.args(["--tag", &tag]);
|
||||||
|
}
|
||||||
|
(None, Some(rev), None) => {
|
||||||
|
cargo.args(["--rev", &rev]);
|
||||||
|
}
|
||||||
|
(None, None, Some(branch)) => {
|
||||||
|
cargo.args(["--branch", &branch]);
|
||||||
|
}
|
||||||
|
(None, None, None) => {}
|
||||||
|
_ => anyhow::bail!("Only one of --tag, --rev and --branch can be specified"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(target) = options.target {
|
||||||
|
cargo.args(["--target", target]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(cwd) = options.cwd {
|
||||||
|
cargo.current_dir(cwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info!("Installing Cargo dependency \"{}\"...", options.name);
|
||||||
|
let status = cargo.status().context("failed to run `cargo add`")?;
|
||||||
|
if !status.success() {
|
||||||
|
anyhow::bail!("Failed to install Cargo dependency");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
pub mod app_paths;
|
pub mod app_paths;
|
||||||
|
pub mod cargo;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod flock;
|
pub mod flock;
|
||||||
pub mod framework;
|
pub mod framework;
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use crate::{helpers::cross_command, Result};
|
use anyhow::Context;
|
||||||
use std::{fmt::Display, path::Path, process::ExitStatus};
|
|
||||||
|
use crate::helpers::cross_command;
|
||||||
|
use std::{fmt::Display, path::Path, process::Command};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum PackageManager {
|
pub enum PackageManager {
|
||||||
@ -69,48 +71,42 @@ impl PackageManager {
|
|||||||
found
|
found
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn install(&self, dependencies: &[String]) -> Result<ExitStatus> {
|
fn cross_command(&self) -> Command {
|
||||||
match self {
|
match self {
|
||||||
PackageManager::Yarn => {
|
PackageManager::Yarn => cross_command("yarn"),
|
||||||
let mut cmd = cross_command("yarn");
|
PackageManager::YarnBerry => cross_command("yarn"),
|
||||||
cmd
|
PackageManager::Npm => cross_command("npm"),
|
||||||
.arg("add")
|
PackageManager::Pnpm => cross_command("pnpm"),
|
||||||
.args(dependencies)
|
PackageManager::Bun => cross_command("bun"),
|
||||||
.status()
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
PackageManager::YarnBerry => {
|
|
||||||
let mut cmd = cross_command("yarn");
|
|
||||||
cmd
|
|
||||||
.arg("add")
|
|
||||||
.args(dependencies)
|
|
||||||
.status()
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
PackageManager::Npm => {
|
|
||||||
let mut cmd = cross_command("npm");
|
|
||||||
cmd
|
|
||||||
.arg("install")
|
|
||||||
.args(dependencies)
|
|
||||||
.status()
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
PackageManager::Pnpm => {
|
|
||||||
let mut cmd = cross_command("pnpm");
|
|
||||||
cmd
|
|
||||||
.arg("install")
|
|
||||||
.args(dependencies)
|
|
||||||
.status()
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
PackageManager::Bun => {
|
|
||||||
let mut cmd = cross_command("bun");
|
|
||||||
cmd
|
|
||||||
.arg("install")
|
|
||||||
.args(dependencies)
|
|
||||||
.status()
|
|
||||||
.map_err(Into::into)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn install(&self, dependencies: &[String]) -> crate::Result<()> {
|
||||||
|
let dependencies_str = if dependencies.len() > 1 {
|
||||||
|
"dependencies"
|
||||||
|
} else {
|
||||||
|
"dependency"
|
||||||
|
};
|
||||||
|
log::info!(
|
||||||
|
"Installing NPM {dependencies_str} {}...",
|
||||||
|
dependencies
|
||||||
|
.iter()
|
||||||
|
.map(|d| format!("\"{d}\""))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", ")
|
||||||
|
);
|
||||||
|
|
||||||
|
let status = self
|
||||||
|
.cross_command()
|
||||||
|
.arg("add")
|
||||||
|
.args(dependencies)
|
||||||
|
.status()
|
||||||
|
.with_context(|| format!("failed to run {self}"))?;
|
||||||
|
|
||||||
|
if !status.success() {
|
||||||
|
anyhow::bail!("Failed to install NPM {dependencies_str}");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,14 +3,13 @@
|
|||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
helpers::{app_paths::walk_builder, npm::PackageManager},
|
helpers::{app_paths::walk_builder, cargo, npm::PackageManager},
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
fs::{read_to_string, write},
|
fs::{read_to_string, write},
|
||||||
path::Path,
|
path::Path,
|
||||||
process::Command,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CORE_API_MODULES: &[&str] = &["dpi", "event", "path", "core", "window", "mocks"];
|
const CORE_API_MODULES: &[&str] = &["dpi", "event", "path", "core", "window", "mocks"];
|
||||||
@ -78,23 +77,11 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !new_npm_packages.is_empty() {
|
if !new_npm_packages.is_empty() {
|
||||||
log::info!(
|
|
||||||
"Installing NPM packages for plugins: {}",
|
|
||||||
new_npm_packages.join(", ")
|
|
||||||
);
|
|
||||||
pm.install(&new_npm_packages)?;
|
pm.install(&new_npm_packages)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !new_cargo_packages.is_empty() {
|
if !new_cargo_packages.is_empty() {
|
||||||
log::info!(
|
cargo::install(&new_cargo_packages, Some(tauri_dir))?;
|
||||||
"Installing Cargo dependencies for plugins: {}",
|
|
||||||
new_cargo_packages.join(", ")
|
|
||||||
);
|
|
||||||
Command::new("cargo")
|
|
||||||
.arg("add")
|
|
||||||
.args(new_cargo_packages)
|
|
||||||
.current_dir(tauri_dir)
|
|
||||||
.status()?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user