mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-09-11 07:55:34 +03:00
fix(cli/migrate): tolerate non-UTF-8 in migration (#9457)
This commit is contained in:
parent
9331435a50
commit
73c1c2d338
6
.changes/cli-migrate-non-utf8.md
Normal file
6
.changes/cli-migrate-non-utf8.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
'tauri-cli': 'patch:bug'
|
||||||
|
'@tauri-apps/cli': 'patch:bug'
|
||||||
|
---
|
||||||
|
|
||||||
|
Gracefully handle Non-UTF8 files when using `tauri migrate`
|
@ -55,7 +55,7 @@ fn symlink_runner(create_symlinks: impl Fn(&Path) -> io::Result<Symlink>) -> Res
|
|||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
// gather the output into a string
|
// gather the output into a string
|
||||||
let stdout = String::from_utf8(output.stdout)?;
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
// we expect the output to be the bin path, twice
|
// we expect the output to be the bin path, twice
|
||||||
assert_eq!(stdout, format!("{bin}\n{bin}\n", bin = bin.display()));
|
assert_eq!(stdout, format!("{bin}\n{bin}\n", bin = bin.display()));
|
||||||
@ -64,7 +64,7 @@ fn symlink_runner(create_symlinks: impl Fn(&Path) -> io::Result<Symlink>) -> Res
|
|||||||
not(feature = "process-relaunch-dangerous-allow-symlink-macos")
|
not(feature = "process-relaunch-dangerous-allow-symlink-macos")
|
||||||
)) {
|
)) {
|
||||||
// we expect this to fail on macOS without the dangerous symlink flag set
|
// we expect this to fail on macOS without the dangerous symlink flag set
|
||||||
let stderr = String::from_utf8(output.stderr)?;
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||||
|
|
||||||
// make sure it's the error that we expect
|
// make sure it's the error that we expect
|
||||||
assert!(stderr.contains(
|
assert!(stderr.contains(
|
||||||
|
@ -92,8 +92,8 @@ pub fn run_collect(cmd: &[&str]) -> (String, String) {
|
|||||||
stderr,
|
stderr,
|
||||||
status,
|
status,
|
||||||
} = prog.wait_with_output().expect("failed to wait on child");
|
} = prog.wait_with_output().expect("failed to wait on child");
|
||||||
let stdout = String::from_utf8(stdout).unwrap();
|
let stdout = String::from_utf8_lossy(&stdout);
|
||||||
let stderr = String::from_utf8(stderr).unwrap();
|
let stderr = String::from_utf8_lossy(&stderr);
|
||||||
if !status.success() {
|
if !status.success() {
|
||||||
eprintln!("stdout: <<<{}>>>", stdout);
|
eprintln!("stdout: <<<{}>>>", stdout);
|
||||||
eprintln!("stderr: <<<{}>>>", stderr);
|
eprintln!("stderr: <<<{}>>>", stderr);
|
||||||
|
@ -1127,7 +1127,7 @@ fn get_cargo_metadata() -> crate::Result<CargoMetadata> {
|
|||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"cargo metadata command exited with a non zero exit code: {}",
|
"cargo metadata command exited with a non zero exit code: {}",
|
||||||
String::from_utf8(output.stderr)?
|
String::from_utf8_lossy(&output.stderr)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ use tauri_utils::acl::{
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashSet},
|
collections::{BTreeMap, HashSet},
|
||||||
fs::{create_dir_all, write},
|
fs,
|
||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ pub fn migrate(tauri_dir: &Path) -> Result<MigratedConfig> {
|
|||||||
tauri_utils_v1::config::parse::parse_value(tauri_dir.join("tauri.conf.json"))
|
tauri_utils_v1::config::parse::parse_value(tauri_dir.join("tauri.conf.json"))
|
||||||
{
|
{
|
||||||
let migrated = migrate_config(&mut config)?;
|
let migrated = migrate_config(&mut config)?;
|
||||||
write(&config_path, serde_json::to_string_pretty(&config)?)?;
|
fs::write(&config_path, serde_json::to_string_pretty(&config)?)?;
|
||||||
|
|
||||||
let mut permissions: Vec<PermissionEntry> = vec![
|
let mut permissions: Vec<PermissionEntry> = vec![
|
||||||
"path:default",
|
"path:default",
|
||||||
@ -38,8 +38,8 @@ pub fn migrate(tauri_dir: &Path) -> Result<MigratedConfig> {
|
|||||||
permissions.extend(migrated.permissions.clone());
|
permissions.extend(migrated.permissions.clone());
|
||||||
|
|
||||||
let capabilities_path = config_path.parent().unwrap().join("capabilities");
|
let capabilities_path = config_path.parent().unwrap().join("capabilities");
|
||||||
create_dir_all(&capabilities_path)?;
|
fs::create_dir_all(&capabilities_path)?;
|
||||||
write(
|
fs::write(
|
||||||
capabilities_path.join("migrated.json"),
|
capabilities_path.join("migrated.json"),
|
||||||
serde_json::to_string_pretty(&Capability {
|
serde_json::to_string_pretty(&Capability {
|
||||||
identifier: "migrated".to_string(),
|
identifier: "migrated".to_string(),
|
||||||
|
@ -6,15 +6,14 @@ use crate::{
|
|||||||
helpers::{app_paths::walk_builder, cargo, npm::PackageManager},
|
helpers::{app_paths::walk_builder, cargo, npm::PackageManager},
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
use std::{
|
use std::{fs, path::Path};
|
||||||
fs::{read_to_string, write},
|
|
||||||
path::Path,
|
|
||||||
};
|
|
||||||
|
|
||||||
const CORE_API_MODULES: &[&str] = &["dpi", "event", "path", "core", "window", "mocks"];
|
const CORE_API_MODULES: &[&str] = &["dpi", "event", "path", "core", "window", "mocks"];
|
||||||
const JS_EXTENSIONS: &[&str] = &["js", "jsx", "ts", "tsx", "mjs"];
|
const JS_EXTENSIONS: &[&str] = &["js", "jsx", "ts", "tsx", "mjs"];
|
||||||
|
|
||||||
|
/// Returns a list of paths that could not be migrated
|
||||||
pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
||||||
let mut new_npm_packages = Vec::new();
|
let mut new_npm_packages = Vec::new();
|
||||||
let mut new_cargo_packages = Vec::new();
|
let mut new_cargo_packages = Vec::new();
|
||||||
@ -24,19 +23,21 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
|||||||
.next()
|
.next()
|
||||||
.unwrap_or(PackageManager::Npm);
|
.unwrap_or(PackageManager::Npm);
|
||||||
|
|
||||||
let tauri_api_import_regex = regex::Regex::new(r"@tauri-apps/api/(\w+)").unwrap();
|
let tauri_api_import_regex = regex::bytes::Regex::new(r"@tauri-apps/api/(\w+)").unwrap();
|
||||||
|
|
||||||
for entry in walk_builder(app_dir).build().flatten() {
|
for entry in walk_builder(app_dir).build().flatten() {
|
||||||
if entry.file_type().map(|t| t.is_file()).unwrap_or_default() {
|
if entry.file_type().map(|t| t.is_file()).unwrap_or_default() {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
let ext = path.extension().unwrap_or_default();
|
let ext = path.extension().unwrap_or_default();
|
||||||
if JS_EXTENSIONS.iter().any(|e| e == &ext) {
|
if JS_EXTENSIONS.iter().any(|e| e == &ext) {
|
||||||
let js_contents = read_to_string(path)?;
|
let js_contents = fs::read(path)?;
|
||||||
|
|
||||||
let new_contents =
|
let new_contents =
|
||||||
tauri_api_import_regex.replace_all(&js_contents, |cap: ®ex::Captures<'_>| {
|
tauri_api_import_regex.replace_all(&js_contents, |cap: ®ex::bytes::Captures<'_>| {
|
||||||
let module = cap.get(1).unwrap().as_str();
|
let module = cap.get(1).unwrap().as_bytes();
|
||||||
let original = cap.get(0).unwrap().as_str();
|
let module = String::from_utf8_lossy(module).to_string();
|
||||||
|
let original = cap.get(0).unwrap().as_bytes();
|
||||||
|
let original = String::from_utf8_lossy(original).to_string();
|
||||||
|
|
||||||
if module == "tauri" {
|
if module == "tauri" {
|
||||||
let new = "@tauri-apps/api/core".to_string();
|
let new = "@tauri-apps/api/core".to_string();
|
||||||
@ -46,8 +47,8 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
|||||||
let new = "@tauri-apps/api/webviewWindow".to_string();
|
let new = "@tauri-apps/api/webviewWindow".to_string();
|
||||||
log::info!("Replacing `{original}` with `{new}` on {}", path.display());
|
log::info!("Replacing `{original}` with `{new}` on {}", path.display());
|
||||||
new
|
new
|
||||||
} else if CORE_API_MODULES.contains(&module) {
|
} else if CORE_API_MODULES.contains(&module.as_str()) {
|
||||||
original.to_string()
|
original
|
||||||
} else {
|
} else {
|
||||||
let plugin = format!("@tauri-apps/plugin-{module}");
|
let plugin = format!("@tauri-apps/plugin-{module}");
|
||||||
log::info!(
|
log::info!(
|
||||||
@ -61,7 +62,7 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
|||||||
if module == "clipboard" {
|
if module == "clipboard" {
|
||||||
"clipboard-manager"
|
"clipboard-manager"
|
||||||
} else {
|
} else {
|
||||||
module
|
&module
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -70,18 +71,21 @@ pub fn migrate(app_dir: &Path, tauri_dir: &Path) -> Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if new_contents != js_contents {
|
if new_contents != js_contents {
|
||||||
write(path, new_contents.as_bytes())?;
|
fs::write(path, new_contents)
|
||||||
|
.with_context(|| format!("Error writing {}", path.display()))?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !new_npm_packages.is_empty() {
|
if !new_npm_packages.is_empty() {
|
||||||
pm.install(&new_npm_packages)?;
|
pm.install(&new_npm_packages)
|
||||||
|
.context("Error installing new npm packages")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !new_cargo_packages.is_empty() {
|
if !new_cargo_packages.is_empty() {
|
||||||
cargo::install(&new_cargo_packages, Some(tauri_dir))?;
|
cargo::install(&new_cargo_packages, Some(tauri_dir))
|
||||||
|
.context("Error installing new Cargo packages")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
helpers::app_paths::{app_dir, tauri_dir},
|
helpers::app_paths::{app_dir, tauri_dir},
|
||||||
Result,
|
Result,
|
||||||
};
|
};
|
||||||
|
use anyhow::Context;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod frontend;
|
mod frontend;
|
||||||
@ -15,18 +16,19 @@ pub fn command() -> Result<()> {
|
|||||||
let tauri_dir = tauri_dir();
|
let tauri_dir = tauri_dir();
|
||||||
let app_dir = app_dir();
|
let app_dir = app_dir();
|
||||||
|
|
||||||
let migrated = config::migrate(&tauri_dir)?;
|
let migrated = config::migrate(&tauri_dir).context("Could not migrate config")?;
|
||||||
manifest::migrate(&tauri_dir)?;
|
manifest::migrate(&tauri_dir).context("Could not migrate manifest")?;
|
||||||
frontend::migrate(app_dir, &tauri_dir)?;
|
frontend::migrate(app_dir, &tauri_dir)?;
|
||||||
|
|
||||||
// Add plugins
|
// Add plugins
|
||||||
for plugin in migrated.plugins {
|
for plugin in migrated.plugins {
|
||||||
crate::add::command(crate::add::Options {
|
crate::add::command(crate::add::Options {
|
||||||
plugin,
|
plugin: plugin.clone(),
|
||||||
branch: None,
|
branch: None,
|
||||||
tag: None,
|
tag: None,
|
||||||
rev: None,
|
rev: None,
|
||||||
})?
|
})
|
||||||
|
.with_context(|| format!("Could not migrate plugin '{plugin}'"))?
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user