fix(cli): manifest v1 migration (#10540)

update features that got removed/renamed, and also migrate any core crate on any dependency table
This commit is contained in:
Lucas Fernandes Nogueira 2024-08-12 00:23:39 -03:00 committed by GitHub
parent 3beba92b5b
commit 3998570fd3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 118 additions and 47 deletions

View File

@ -0,0 +1,6 @@
---
"tauri-cli": patch:bug
"@tauri-apps/cli": patch:bug
---
Fixes v1 migration of Cargo.toml dependencies and features.

View File

@ -8,9 +8,8 @@ use crate::{
}; };
use anyhow::Context; use anyhow::Context;
use itertools::Itertools;
use tauri_utils_v1::config::Allowlist; use tauri_utils_v1::config::Allowlist;
use toml_edit::{Document, Entry, Item, Table, TableLike, Value}; use toml_edit::{Document, Entry, Item, TableLike, Value};
use std::path::Path; use std::path::Path;
@ -30,23 +29,47 @@ pub fn migrate(tauri_dir: &Path) -> Result<()> {
fn migrate_manifest(manifest: &mut Document) -> Result<()> { fn migrate_manifest(manifest: &mut Document) -> Result<()> {
let version = dependency_version(); let version = dependency_version();
let dependencies = manifest let remove_features = features_to_remove();
.as_table_mut() let rename_features = features_to_rename();
.entry("dependencies") let rename_message = rename_features
.or_insert(Item::Table(Table::new())) .iter()
.as_table_mut() .map(|(from, to)| format!("{from} to {to}"))
.context("manifest dependencies isn't a table")?; .collect::<Vec<_>>()
.join(", ");
migrate_dependency(dependencies, "tauri", &version, &features_to_remove()); for (dependency, table) in [
// normal deps
("tauri", "dependencies"),
("tauri-utils", "dependencies"),
("tauri-runtime", "dependencies"),
("tauri-codegen", "dependencies"),
("tauri-macros", "dependencies"),
("tauri-runtime-wry", "dependencies"),
// dev
("tauri", "dev-dependencies"),
("tauri-utils", "dev-dependencies"),
("tauri-runtime", "dev-dependencies"),
("tauri-codegen", "dev-dependencies"),
("tauri-macros", "dev-dependencies"),
("tauri-runtime-wry", "dev-dependencies"),
// build
("tauri-build", "build-dependencies"),
] {
let items = find_dependency(manifest, dependency, table);
let build_dependencies = manifest for item in items {
.as_table_mut() // do not rewrite if dependency uses workspace inheritance
.entry("build-dependencies") if item
.or_insert(Item::Table(Table::new())) .get("workspace")
.as_table_mut() .and_then(|v| v.as_bool())
.context("manifest build-dependencies isn't a table")?; .unwrap_or_default()
{
migrate_dependency(build_dependencies, "tauri-build", &version, &[]); log::warn!("`{dependency}` dependency has workspace inheritance enabled. This migration must be manually migrated to v2 by changing its version to {version}, removing any of the {remove_features:?} and renaming [{}] Cargo features.", rename_message);
} else {
migrate_dependency(item, &version, &remove_features, &rename_features);
}
}
}
if let Some(lib) = manifest if let Some(lib) = manifest
.as_table_mut() .as_table_mut()
@ -82,15 +105,66 @@ fn migrate_manifest(manifest: &mut Document) -> Result<()> {
Ok(()) Ok(())
} }
fn find_dependency<'a>(
manifest: &'a mut Document,
name: &'a str,
table: &'a str,
) -> Vec<&'a mut Item> {
let m = manifest.as_table_mut();
for (k, v) in m.iter_mut() {
if let Some(t) = v.as_table_mut() {
if k == table {
if let Some(item) = t.get_mut(name) {
return vec![item];
}
} else if k == "target" {
let mut matching_deps = Vec::new();
for (_, target_value) in t.iter_mut() {
if let Some(target_table) = target_value.as_table_mut() {
if let Some(deps) = target_table.get_mut(table) {
if let Some(item) = deps.as_table_mut().and_then(|t| t.get_mut(name)) {
matching_deps.push(item);
}
}
}
}
return matching_deps;
}
}
}
Vec::new()
}
fn features_to_rename() -> Vec<(&'static str, &'static str)> {
vec![
("window-data-url", "webview-data-url"),
("reqwest-native-tls-vendored", "native-tls-vendored"),
("system-tray", "tray-icon"),
("icon-ico", "image-ico"),
("icon-png", "image-png"),
]
}
fn features_to_remove() -> Vec<&'static str> { fn features_to_remove() -> Vec<&'static str> {
let mut features_to_remove = tauri_utils_v1::config::AllowlistConfig::all_features(); let mut features_to_remove = tauri_utils_v1::config::AllowlistConfig::all_features();
features_to_remove.push("reqwest-client"); features_to_remove.extend(&[
features_to_remove.push("reqwest-native-tls-vendored"); "reqwest-client",
features_to_remove.push("process-command-api"); "http-multipart",
features_to_remove.push("shell-open-api"); "process-command-api",
features_to_remove.push("windows7-compat"); "shell-open-api",
features_to_remove.push("updater"); "os-api",
features_to_remove.push("system-tray"); "global-shortcut",
"clipboard",
"dialog",
"notification",
"fs-extract-api",
"windows7-compat",
"updater",
"cli",
"linux-protocol-headers",
"dox",
]);
// this allowlist feature was not removed // this allowlist feature was not removed
let index = features_to_remove let index = features_to_remove
@ -117,29 +191,22 @@ fn dependency_version() -> String {
} }
} }
fn migrate_dependency(dependencies: &mut Table, name: &str, version: &str, remove: &[&str]) { fn migrate_dependency(item: &mut Item, version: &str, remove: &[&str], rename: &[(&str, &str)]) {
let item = dependencies.entry(name).or_insert(Item::None);
// do not rewrite if dependency uses workspace inheritance
if item
.get("workspace")
.and_then(|v| v.as_bool())
.unwrap_or_default()
{
log::info!("`{name}` dependency has workspace inheritance enabled. The features array won't be automatically rewritten. Remove features: [{}]", remove.iter().join(", "));
return;
}
if let Some(dep) = item.as_table_mut() { if let Some(dep) = item.as_table_mut() {
migrate_dependency_table(dep, version, remove); migrate_dependency_table(dep, version, remove, rename);
} else if let Some(Value::InlineTable(table)) = item.as_value_mut() { } else if let Some(Value::InlineTable(table)) = item.as_value_mut() {
migrate_dependency_table(table, version, remove); migrate_dependency_table(table, version, remove, rename);
} else if item.as_str().is_some() { } else if item.as_str().is_some() {
*item = Item::Value(version.into()); *item = Item::Value(version.into());
} }
} }
fn migrate_dependency_table<D: TableLike>(dep: &mut D, version: &str, remove: &[&str]) { fn migrate_dependency_table<D: TableLike>(
dep: &mut D,
version: &str,
remove: &[&str],
rename: &[(&str, &str)],
) {
*dep.entry("version").or_insert(Item::None) = Item::Value(version.into()); *dep.entry("version").or_insert(Item::None) = Item::Value(version.into());
let manifest_features = dep.entry("features").or_insert(Item::None); let manifest_features = dep.entry("features").or_insert(Item::None);
if let Some(features_array) = manifest_features.as_array_mut() { if let Some(features_array) = manifest_features.as_array_mut() {
@ -150,19 +217,17 @@ fn migrate_dependency_table<D: TableLike>(dep: &mut D, version: &str, remove: &[
let index = i - 1; let index = i - 1;
if let Some(f) = features_array.get(index).and_then(|f| f.as_str()) { if let Some(f) = features_array.get(index).and_then(|f| f.as_str()) {
if remove.contains(&f) { if remove.contains(&f) {
let f = f.to_string();
features_array.remove(index); features_array.remove(index);
if f == "reqwest-native-tls-vendored" { } else if let Some((_from, rename_to)) = rename.iter().find(|(from, _to)| *from == f) {
add_features.push("native-tls-vendored"); features_array.remove(index);
} else if f == "system-tray" { add_features.push(rename_to);
add_features.push("tray-icon");
}
} }
} }
i -= 1; i -= 1;
} }
for f in add_features { for f in add_features {
features_array.push(f); features_array.push(f.to_string());
} }
} }
} }