snapshot of https://github.com/tauri-apps/tauri.git (dev, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
This commit is contained in:
362
crates/tauri-cli/src/helpers/config.rs
Normal file
362
crates/tauri-cli/src/helpers/config.rs
Normal file
@@ -0,0 +1,362 @@
|
||||
// Copyright 2019-2025 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use itertools::Itertools;
|
||||
use json_patch::merge;
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use tauri_utils::acl::REMOVE_UNUSED_COMMANDS_ENV_VAR;
|
||||
pub use tauri_utils::{config::*, platform::Target};
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env::{current_dir, set_current_dir, set_var},
|
||||
ffi::{OsStr, OsString},
|
||||
path::Path,
|
||||
process::exit,
|
||||
sync::LazyLock,
|
||||
};
|
||||
|
||||
use crate::error::Context;
|
||||
|
||||
pub const MERGE_CONFIG_EXTENSION_NAME: &str = "--config";
|
||||
|
||||
pub struct ConfigMetadata {
|
||||
/// The current target.
|
||||
target: Target,
|
||||
|
||||
original_identifier: Option<String>,
|
||||
/// The actual configuration, merged with any extension.
|
||||
inner: Config,
|
||||
/// The config extensions (platform-specific config files or the config CLI argument).
|
||||
/// Maps the extension name to its value.
|
||||
extensions: HashMap<OsString, JsonValue>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ConfigMetadata {
|
||||
type Target = Config;
|
||||
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &Config {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl ConfigMetadata {
|
||||
/// The original bundle identifier from the config file.
|
||||
/// This does not take any extensions into account.
|
||||
pub fn original_identifier(&self) -> Option<&str> {
|
||||
self.original_identifier.as_deref()
|
||||
}
|
||||
|
||||
/// Checks which config is overwriting the bundle identifier.
|
||||
pub fn find_bundle_identifier_overwriter(&self) -> Option<OsString> {
|
||||
for (ext, config) in &self.extensions {
|
||||
if let Some(identifier) = config
|
||||
.as_object()
|
||||
.and_then(|bundle_config| bundle_config.get("identifier")?.as_str())
|
||||
{
|
||||
if identifier == self.inner.identifier {
|
||||
return Some(ext.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn wix_settings(config: WixConfig) -> tauri_bundler::WixSettings {
|
||||
tauri_bundler::WixSettings {
|
||||
version: config.version,
|
||||
upgrade_code: config.upgrade_code,
|
||||
fips_compliant: std::env::var_os("TAURI_BUNDLER_WIX_FIPS_COMPLIANT")
|
||||
.map(|v| v == "true")
|
||||
.unwrap_or(config.fips_compliant),
|
||||
language: tauri_bundler::WixLanguage(match config.language {
|
||||
WixLanguage::One(lang) => vec![(lang, Default::default())],
|
||||
WixLanguage::List(languages) => languages
|
||||
.into_iter()
|
||||
.map(|lang| (lang, Default::default()))
|
||||
.collect(),
|
||||
WixLanguage::Localized(languages) => languages
|
||||
.into_iter()
|
||||
.map(|(lang, config)| {
|
||||
(
|
||||
lang,
|
||||
tauri_bundler::WixLanguageConfig {
|
||||
locale_path: config.locale_path.map(Into::into),
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
}),
|
||||
template: config.template,
|
||||
fragment_paths: config.fragment_paths,
|
||||
component_group_refs: config.component_group_refs,
|
||||
component_refs: config.component_refs,
|
||||
feature_group_refs: config.feature_group_refs,
|
||||
feature_refs: config.feature_refs,
|
||||
merge_refs: config.merge_refs,
|
||||
enable_elevated_update_task: config.enable_elevated_update_task,
|
||||
banner_path: config.banner_path,
|
||||
dialog_image_path: config.dialog_image_path,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nsis_settings(config: NsisConfig) -> tauri_bundler::NsisSettings {
|
||||
tauri_bundler::NsisSettings {
|
||||
template: config.template,
|
||||
header_image: config.header_image,
|
||||
sidebar_image: config.sidebar_image,
|
||||
installer_icon: config.installer_icon,
|
||||
uninstaller_icon: config.uninstaller_icon,
|
||||
uninstaller_header_image: config.uninstaller_header_image,
|
||||
install_mode: config.install_mode,
|
||||
languages: config.languages,
|
||||
custom_language_files: config.custom_language_files,
|
||||
display_language_selector: config.display_language_selector,
|
||||
compression: config.compression,
|
||||
start_menu_folder: config.start_menu_folder,
|
||||
installer_hooks: config.installer_hooks,
|
||||
#[allow(deprecated)]
|
||||
minimum_webview2_version: config.minimum_webview2_version,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn custom_sign_settings(
|
||||
config: CustomSignCommandConfig,
|
||||
) -> tauri_bundler::CustomSignCommandSettings {
|
||||
match config {
|
||||
CustomSignCommandConfig::Command(command) => {
|
||||
let mut tokens = command.split(' ');
|
||||
tauri_bundler::CustomSignCommandSettings {
|
||||
cmd: tokens.next().unwrap().to_string(), // split always has at least one element
|
||||
args: tokens.map(String::from).collect(),
|
||||
}
|
||||
}
|
||||
CustomSignCommandConfig::CommandWithOptions { cmd, args } => {
|
||||
tauri_bundler::CustomSignCommandSettings { cmd, args }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static CONFIG_SCHEMA_VALIDATOR: LazyLock<jsonschema::Validator> = LazyLock::new(|| {
|
||||
let schema: JsonValue = serde_json::from_str(include_str!("../../config.schema.json"))
|
||||
.expect("Failed to parse config schema bundled in the tauri-cli");
|
||||
jsonschema::validator_for(&schema).expect("Config schema bundled in the tauri-cli is invalid")
|
||||
});
|
||||
|
||||
fn load_config(
|
||||
merge_configs: &[&serde_json::Value],
|
||||
reload: bool,
|
||||
target: Target,
|
||||
tauri_dir: &Path,
|
||||
) -> crate::Result<ConfigMetadata> {
|
||||
let (mut config, config_path) =
|
||||
tauri_utils::config::parse::parse_value(target, tauri_dir.join("tauri.conf.json"))
|
||||
.context("failed to parse config")?;
|
||||
let config_file_name = config_path.file_name().unwrap();
|
||||
let mut extensions = HashMap::new();
|
||||
|
||||
let original_identifier = config
|
||||
.as_object()
|
||||
.and_then(|config| config.get("identifier")?.as_str())
|
||||
.map(ToString::to_string);
|
||||
|
||||
if let Some((platform_config, config_path)) =
|
||||
tauri_utils::config::parse::read_platform(target, tauri_dir)
|
||||
.context("failed to parse platform config")?
|
||||
{
|
||||
merge(&mut config, &platform_config);
|
||||
extensions.insert(config_path.file_name().unwrap().into(), platform_config);
|
||||
}
|
||||
|
||||
if !merge_configs.is_empty() {
|
||||
let mut merge_config = serde_json::Value::Object(Default::default());
|
||||
for conf in merge_configs {
|
||||
merge_patches(&mut merge_config, conf);
|
||||
}
|
||||
|
||||
let merge_config_str = serde_json::to_string(&merge_config).unwrap();
|
||||
unsafe { set_var("TAURI_CONFIG", merge_config_str) };
|
||||
merge(&mut config, &merge_config);
|
||||
extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config);
|
||||
}
|
||||
|
||||
if config_path.extension() == Some(OsStr::new("json"))
|
||||
|| config_path.extension() == Some(OsStr::new("json5"))
|
||||
{
|
||||
let mut errors = CONFIG_SCHEMA_VALIDATOR.iter_errors(&config).peekable();
|
||||
if errors.peek().is_some() {
|
||||
for error in errors {
|
||||
let path = error.instance_path().into_iter().join(" > ");
|
||||
if path.is_empty() {
|
||||
log::error!("`{config_file_name:?}` error: {error}");
|
||||
} else {
|
||||
log::error!("`{config_file_name:?}` error on `{path}`: {error}");
|
||||
}
|
||||
}
|
||||
if !reload {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the `Config` deserializer for `package > version` can resolve the version from a path relative to the config path
|
||||
// so we actually need to change the current working directory here
|
||||
let current_dir = current_dir().context("failed to resolve current directory")?;
|
||||
set_current_dir(config_path.parent().unwrap()).context("failed to set current directory")?;
|
||||
let config: Config = serde_json::from_value(config).context("failed to parse config")?;
|
||||
// revert to previous working directory
|
||||
set_current_dir(current_dir).context("failed to set current directory")?;
|
||||
|
||||
for (plugin, conf) in &config.plugins.0 {
|
||||
unsafe {
|
||||
set_var(
|
||||
format!(
|
||||
"TAURI_{}_PLUGIN_CONFIG",
|
||||
plugin.to_uppercase().replace('-', "_")
|
||||
),
|
||||
serde_json::to_string(&conf).context("failed to serialize config")?,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
if config.build.remove_unused_commands {
|
||||
unsafe { std::env::set_var(REMOVE_UNUSED_COMMANDS_ENV_VAR, tauri_dir) };
|
||||
}
|
||||
|
||||
Ok(ConfigMetadata {
|
||||
target,
|
||||
original_identifier,
|
||||
inner: config,
|
||||
extensions,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_config(
|
||||
target: Target,
|
||||
merge_configs: &[&serde_json::Value],
|
||||
tauri_dir: &Path,
|
||||
) -> crate::Result<ConfigMetadata> {
|
||||
load_config(merge_configs, false, target, tauri_dir)
|
||||
}
|
||||
|
||||
pub fn reload_config(
|
||||
config: &mut ConfigMetadata,
|
||||
merge_configs: &[&serde_json::Value],
|
||||
tauri_dir: &Path,
|
||||
) -> crate::Result<()> {
|
||||
let target = config.target;
|
||||
*config = load_config(merge_configs, true, target, tauri_dir)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// merges the loaded config with the given value
|
||||
pub fn merge_config_with(
|
||||
config: &mut ConfigMetadata,
|
||||
merge_configs: &[&serde_json::Value],
|
||||
) -> crate::Result<()> {
|
||||
if merge_configs.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut merge_config = serde_json::Value::Object(Default::default());
|
||||
for conf in merge_configs {
|
||||
merge_patches(&mut merge_config, conf);
|
||||
}
|
||||
|
||||
let merge_config_str = serde_json::to_string(&merge_config).unwrap();
|
||||
unsafe { set_var("TAURI_CONFIG", merge_config_str) };
|
||||
|
||||
let mut value =
|
||||
serde_json::to_value(config.inner.clone()).context("failed to serialize config")?;
|
||||
merge(&mut value, &merge_config);
|
||||
config.inner = serde_json::from_value(value).context("failed to parse config")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Same as [`json_patch::merge`] but doesn't delete the key when the patch's value is `null`
|
||||
fn merge_patches(doc: &mut serde_json::Value, patch: &serde_json::Value) {
|
||||
use serde_json::{Map, Value};
|
||||
|
||||
if !patch.is_object() {
|
||||
*doc = patch.clone();
|
||||
return;
|
||||
}
|
||||
|
||||
if !doc.is_object() {
|
||||
*doc = Value::Object(Map::new());
|
||||
}
|
||||
let map = doc.as_object_mut().unwrap();
|
||||
for (key, value) in patch.as_object().unwrap() {
|
||||
merge_patches(map.entry(key.as_str()).or_insert(Value::Null), value);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn merge_patches() {
|
||||
let mut json = serde_json::Value::Object(Default::default());
|
||||
|
||||
super::merge_patches(
|
||||
&mut json,
|
||||
&serde_json::json!({
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": []
|
||||
},
|
||||
"plugins": {
|
||||
"test": "tauri"
|
||||
},
|
||||
"build": {
|
||||
"devUrl": "http://localhost:8080"
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
super::merge_patches(
|
||||
&mut json,
|
||||
&serde_json::json!({
|
||||
"app": { "withGlobalTauri": null }
|
||||
}),
|
||||
);
|
||||
|
||||
super::merge_patches(
|
||||
&mut json,
|
||||
&serde_json::json!({
|
||||
"app": { "windows": null }
|
||||
}),
|
||||
);
|
||||
|
||||
super::merge_patches(
|
||||
&mut json,
|
||||
&serde_json::json!({
|
||||
"plugins": { "updater": {
|
||||
"endpoints": ["https://tauri.app"]
|
||||
} }
|
||||
}),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
json,
|
||||
serde_json::json!({
|
||||
"app": {
|
||||
"withGlobalTauri": null,
|
||||
"windows": null
|
||||
},
|
||||
"plugins": {
|
||||
"test": "tauri",
|
||||
"updater": {
|
||||
"endpoints": ["https://tauri.app"]
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"devUrl": "http://localhost:8080"
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user