mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-02-06 15:56:51 +00:00
fix(cli): ensure Xcode project is up to date with Cargo project name (#14101)
* fix(cli): ensure Xcode project is up to date with Cargo project name closes #13542 * clippy
This commit is contained in:
parent
ed7c9a4100
commit
28a2f9bc55
6
.changes/fix-ios-cmd-pkg-name-change.md
Normal file
6
.changes/fix-ios-cmd-pkg-name-change.md
Normal file
@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-cli": patch:bug
|
||||
"@tauri-apps/cli": patch:bug
|
||||
---
|
||||
|
||||
Fix iOS CLI usage after modifying the package name.
|
||||
@ -2,8 +2,11 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use crate::{error::ErrorExt, Error};
|
||||
use std::path::Path;
|
||||
use crate::{
|
||||
error::{Context, ErrorExt},
|
||||
Error,
|
||||
};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> crate::Result<()> {
|
||||
let from = from.as_ref();
|
||||
@ -28,3 +31,25 @@ pub fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> crate::Result<
|
||||
std::fs::copy(from, to).fs_context("failed to copy file", from.to_path_buf())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Find an entry in a directory matching a glob pattern.
|
||||
/// Currently does not traverse subdirectories.
|
||||
// currently only used on macOS
|
||||
#[allow(dead_code)]
|
||||
pub fn find_in_directory(path: &Path, glob_pattern: &str) -> crate::Result<PathBuf> {
|
||||
let pattern = glob::Pattern::new(glob_pattern)
|
||||
.with_context(|| format!("failed to parse glob pattern {glob_pattern}"))?;
|
||||
for entry in std::fs::read_dir(path)
|
||||
.with_context(|| format!("failed to read directory {}", path.display()))?
|
||||
{
|
||||
let entry = entry.context("failed to read directory entry")?;
|
||||
if pattern.matches_path(&entry.path()) {
|
||||
return Ok(entry.path());
|
||||
}
|
||||
}
|
||||
crate::error::bail!(
|
||||
"No file found in {} matching {}",
|
||||
path.display(),
|
||||
glob_pattern
|
||||
)
|
||||
}
|
||||
|
||||
@ -91,6 +91,7 @@ pub fn command(options: Options) -> Result<()> {
|
||||
config.app(),
|
||||
config.project_dir(),
|
||||
MobileTarget::Android,
|
||||
std::env::var("CI").is_ok(),
|
||||
)?;
|
||||
|
||||
if !cli_options.config.is_empty() {
|
||||
|
||||
@ -161,6 +161,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
|
||||
config.app(),
|
||||
config.project_dir(),
|
||||
MobileTarget::Android,
|
||||
options.ci,
|
||||
)?;
|
||||
|
||||
let mut env = env(options.ci)?;
|
||||
|
||||
@ -206,6 +206,7 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> {
|
||||
config.app(),
|
||||
config.project_dir(),
|
||||
MobileTarget::Android,
|
||||
false,
|
||||
)?;
|
||||
run_dev(
|
||||
interface,
|
||||
|
||||
@ -203,6 +203,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
|
||||
config.app(),
|
||||
config.project_dir(),
|
||||
MobileTarget::Ios,
|
||||
options.ci,
|
||||
)?;
|
||||
inject_resources(&config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
|
||||
|
||||
@ -212,6 +212,7 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> {
|
||||
config.app(),
|
||||
config.project_dir(),
|
||||
MobileTarget::Ios,
|
||||
false,
|
||||
)?;
|
||||
inject_resources(&config, tauri_config.lock().unwrap().as_ref().unwrap())?;
|
||||
|
||||
|
||||
@ -138,6 +138,7 @@ pub fn command(options: Options) -> Result<()> {
|
||||
config.app(),
|
||||
config.project_dir(),
|
||||
MobileTarget::Ios,
|
||||
std::env::var("CI").is_ok(),
|
||||
)?;
|
||||
|
||||
if !cli_options.config.is_empty() {
|
||||
|
||||
@ -497,6 +497,7 @@ fn ensure_init(
|
||||
app: &App,
|
||||
project_dir: PathBuf,
|
||||
target: Target,
|
||||
noninteractive: bool,
|
||||
) -> Result<()> {
|
||||
if !project_dir.exists() {
|
||||
crate::error::bail!(
|
||||
@ -527,32 +528,83 @@ fn ensure_init(
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
Target::Ios => {
|
||||
let pbxproj_contents = read_to_string(
|
||||
project_dir
|
||||
.join(format!("{}.xcodeproj", app.name()))
|
||||
.join("project.pbxproj"),
|
||||
)
|
||||
.fs_context(
|
||||
"missing project.pbxproj file in the Xcode project directory",
|
||||
project_dir
|
||||
.join(format!("{}.xcodeproj", app.name()))
|
||||
.join("project.pbxproj"),
|
||||
)?;
|
||||
let xcodeproj_path = crate::helpers::fs::find_in_directory(&project_dir, "*.xcodeproj")
|
||||
.with_context(|| format!("failed to locate xcodeproj in {}", project_dir.display()))?;
|
||||
|
||||
if !(pbxproj_contents.contains(ios::LIB_OUTPUT_FILE_NAME)
|
||||
|| pbxproj_contents.contains(&format!("lib{}.a", app.lib_name())))
|
||||
{
|
||||
project_outdated_reasons
|
||||
.push("you have modified your [lib.name] or [package.name] in the Cargo.toml file");
|
||||
let xcodeproj_name = xcodeproj_path.file_stem().unwrap().to_str().unwrap();
|
||||
if xcodeproj_name != app.name() {
|
||||
let rename_targets = vec![
|
||||
// first rename the entitlements
|
||||
(
|
||||
format!("{xcodeproj_name}_iOS/{xcodeproj_name}_iOS.entitlements"),
|
||||
format!("{xcodeproj_name}_iOS/{}_iOS.entitlements", app.name()),
|
||||
),
|
||||
// then the scheme folder
|
||||
(
|
||||
format!("{xcodeproj_name}_iOS"),
|
||||
format!("{}_iOS", app.name()),
|
||||
),
|
||||
(
|
||||
format!("{xcodeproj_name}.xcodeproj"),
|
||||
format!("{}.xcodeproj", app.name()),
|
||||
),
|
||||
];
|
||||
let rename_info = rename_targets
|
||||
.iter()
|
||||
.map(|(from, to)| format!("- {from} to {to}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
log::error!(
|
||||
"you have modified your package name from {current_project_name} to {new_project_name}\nWe need to apply the name change to the Xcode project, renaming:\n{rename_info}",
|
||||
new_project_name = app.name(),
|
||||
current_project_name = xcodeproj_name,
|
||||
);
|
||||
if noninteractive {
|
||||
project_outdated_reasons
|
||||
.push("you have modified your [lib.name] or [package.name] in the Cargo.toml file");
|
||||
} else {
|
||||
let confirm = crate::helpers::prompts::confirm(
|
||||
"Do you want to apply the name change to the Xcode project?",
|
||||
Some(true),
|
||||
)
|
||||
.unwrap_or_default();
|
||||
if confirm {
|
||||
for (from, to) in rename_targets {
|
||||
std::fs::rename(project_dir.join(&from), project_dir.join(&to))
|
||||
.with_context(|| format!("failed to rename {from} to {to}"))?;
|
||||
}
|
||||
|
||||
// update scheme name in pbxproj
|
||||
// identifier / product name are synchronized by the dev/build commands
|
||||
let pbxproj_path =
|
||||
project_dir.join(format!("{}.xcodeproj/project.pbxproj", app.name()));
|
||||
let pbxproj_contents = std::fs::read_to_string(&pbxproj_path)
|
||||
.with_context(|| format!("failed to read {}", pbxproj_path.display()))?;
|
||||
std::fs::write(
|
||||
&pbxproj_path,
|
||||
pbxproj_contents.replace(
|
||||
&format!("{xcodeproj_name}_iOS"),
|
||||
&format!("{}_iOS", app.name()),
|
||||
),
|
||||
)
|
||||
.with_context(|| format!("failed to write {}", pbxproj_path.display()))?;
|
||||
} else {
|
||||
project_outdated_reasons
|
||||
.push("you have modified your [lib.name] or [package.name] in the Cargo.toml file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// note: pbxproj is synchronied by the dev/build commands
|
||||
}
|
||||
}
|
||||
|
||||
if !project_outdated_reasons.is_empty() {
|
||||
let reason = project_outdated_reasons.join(" and ");
|
||||
crate::error::bail!(
|
||||
"{} project directory is outdated because {reason}. Please run `tauri {} init` and try again.",
|
||||
"{} project directory is outdated because {reason}. Please delete {}, run `tauri {} init` and try again.",
|
||||
target.ide_name(),
|
||||
project_dir.display(),
|
||||
target.command_name(),
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user