mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
Cleanups (#14632)
* refactor(tauri-utils): current_dest and current_pattern always change in-sync, group them to one Option * refactor(tauri-utils): pass path as explicit argument instead of implicitly through self * refactor(tauri-utils): remove struct field that is never set to Some * refactor(tauri-cli): use OsString, OsStr where possible * refactor(tauri-cli): Deref Arc early * refactor(tauri-cli): lock config before passing to build::setup() * refactor(tauri-build, tauri-utils): bettern pattern matching and borrowing * refactor(tauri-cli): dont need Arc if already have static * fix(tauri-cli): race condition initializing static flag, remove unnecessary OnceLock * refactor(tauri-cli): use expect * refactor(tauri-cli): remove unnecessary OnceLock * refactor(tauri-cli): better use of dunce api * refactor(tauri-cli): rename
This commit is contained in:
7
.changes/change-pr-14632.md
Normal file
7
.changes/change-pr-14632.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri-utils": patch:enhance
|
||||
"tauri-build": patch:enhance
|
||||
"tauri-cli": patch:enhance
|
||||
---
|
||||
|
||||
Small code refactors for improved code readability. No user facing changes.
|
||||
@@ -165,21 +165,21 @@ fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
|
||||
.with_context(|| format!("Failed to create frameworks output directory at {dest_dir:?}"))?;
|
||||
for framework in frameworks.iter() {
|
||||
if framework.ends_with(".framework") {
|
||||
let src_path = PathBuf::from(framework);
|
||||
let src_path = Path::new(framework);
|
||||
let src_name = src_path
|
||||
.file_name()
|
||||
.expect("Couldn't get framework filename");
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
copy_dir(&src_path, &dest_path)?;
|
||||
copy_dir(src_path, &dest_path)?;
|
||||
continue;
|
||||
} else if framework.ends_with(".dylib") {
|
||||
let src_path = PathBuf::from(framework);
|
||||
let src_path = Path::new(framework);
|
||||
if !src_path.exists() {
|
||||
return Err(anyhow::anyhow!("Library not found: {}", framework));
|
||||
}
|
||||
let src_name = src_path.file_name().expect("Couldn't get library filename");
|
||||
let dest_path = dest_dir.join(src_name);
|
||||
copy_file(&src_path, &dest_path)?;
|
||||
copy_file(src_path, &dest_path)?;
|
||||
continue;
|
||||
} else if framework.contains('/') {
|
||||
return Err(anyhow::anyhow!(
|
||||
@@ -192,12 +192,8 @@ fn copy_frameworks(dest_dir: &Path, frameworks: &[String]) -> Result<()> {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if copy_framework_from(&PathBuf::from("/Library/Frameworks/"), framework, dest_dir)?
|
||||
|| copy_framework_from(
|
||||
&PathBuf::from("/Network/Library/Frameworks/"),
|
||||
framework,
|
||||
dest_dir,
|
||||
)?
|
||||
if copy_framework_from("/Library/Frameworks/".as_ref(), framework, dest_dir)?
|
||||
|| copy_framework_from("/Network/Library/Frameworks/".as_ref(), framework, dest_dir)?
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -266,8 +266,7 @@ pub fn try_sign<P: AsRef<Path>>(file_path: P, settings: &Settings) -> crate::Res
|
||||
pub fn should_sign(file_path: &Path) -> crate::Result<bool> {
|
||||
let is_binary = file_path
|
||||
.extension()
|
||||
.and_then(|extension| extension.to_str())
|
||||
.is_some_and(|extension| matches!(extension, "exe" | "dll"));
|
||||
.is_some_and(|ext| ext == "exe" || ext == "dll");
|
||||
if !is_binary {
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
helpers::{
|
||||
self,
|
||||
app_paths::{frontend_dir, tauri_dir},
|
||||
config::{get as get_config, ConfigHandle, FrontendDist},
|
||||
config::{get as get_config, ConfigMetadata, FrontendDist},
|
||||
},
|
||||
info::plugins::check_mismatched_packages,
|
||||
interface::{rust::get_cargo_target_dir, AppInterface, Interface},
|
||||
@@ -106,11 +106,11 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
options.target.clone(),
|
||||
)?;
|
||||
|
||||
setup(&interface, &mut options, config.clone(), false)?;
|
||||
|
||||
let config_guard = config.lock().unwrap();
|
||||
let config_ = config_guard.as_ref().unwrap();
|
||||
|
||||
setup(&interface, &mut options, config_, false)?;
|
||||
|
||||
if let Some(minimum_system_version) = &config_.bundle.macos.minimum_system_version {
|
||||
std::env::set_var("MACOSX_DEPLOYMENT_TARGET", minimum_system_version);
|
||||
}
|
||||
@@ -132,7 +132,7 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
verbosity,
|
||||
ci,
|
||||
&interface,
|
||||
&app_settings,
|
||||
&*app_settings,
|
||||
config_,
|
||||
&out_dir,
|
||||
)?;
|
||||
@@ -144,7 +144,7 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
|
||||
pub fn setup(
|
||||
interface: &AppInterface,
|
||||
options: &mut Options,
|
||||
config: ConfigHandle,
|
||||
config: &ConfigMetadata,
|
||||
mobile: bool,
|
||||
) -> Result<()> {
|
||||
let tauri_path = tauri_dir();
|
||||
@@ -162,44 +162,39 @@ pub fn setup(
|
||||
|
||||
set_current_dir(tauri_path).context("failed to set current directory")?;
|
||||
|
||||
let config_guard = config.lock().unwrap();
|
||||
let config_ = config_guard.as_ref().unwrap();
|
||||
|
||||
let bundle_identifier_source = config_
|
||||
let bundle_identifier_source = config
|
||||
.find_bundle_identifier_overwriter()
|
||||
.unwrap_or_else(|| "tauri.conf.json".into());
|
||||
|
||||
if config_.identifier == "com.tauri.dev" {
|
||||
if config.identifier == "com.tauri.dev" {
|
||||
crate::error::bail!(
|
||||
"You must change the bundle identifier in `{bundle_identifier_source} identifier`. The default value `com.tauri.dev` is not allowed as it must be unique across applications.",
|
||||
);
|
||||
}
|
||||
|
||||
if config_
|
||||
if config
|
||||
.identifier
|
||||
.chars()
|
||||
.any(|ch| !(ch.is_alphanumeric() || ch == '-' || ch == '.'))
|
||||
{
|
||||
crate::error::bail!(
|
||||
"The bundle identifier \"{}\" set in `{} identifier`. The bundle identifier string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-), and periods (.).",
|
||||
config_.identifier,
|
||||
bundle_identifier_source
|
||||
"The bundle identifier \"{}\" set in `{bundle_identifier_source:?} identifier`. The bundle identifier string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-), and periods (.).",
|
||||
config.identifier,
|
||||
);
|
||||
}
|
||||
|
||||
if config_.identifier.ends_with(".app") {
|
||||
if config.identifier.ends_with(".app") {
|
||||
log::warn!(
|
||||
"The bundle identifier \"{}\" set in `{} identifier` ends with `.app`. This is not recommended because it conflicts with the application bundle extension on macOS.",
|
||||
config_.identifier,
|
||||
bundle_identifier_source
|
||||
"The bundle identifier \"{}\" set in `{bundle_identifier_source:?} identifier` ends with `.app`. This is not recommended because it conflicts with the application bundle extension on macOS.",
|
||||
config.identifier,
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(before_build) = config_.build.before_build_command.clone() {
|
||||
if let Some(before_build) = config.build.before_build_command.clone() {
|
||||
helpers::run_hook("beforeBuildCommand", before_build, interface, options.debug)?;
|
||||
}
|
||||
|
||||
if let Some(FrontendDist::Directory(web_asset_path)) = &config_.build.frontend_dist {
|
||||
if let Some(FrontendDist::Directory(web_asset_path)) = &config.build.frontend_dist {
|
||||
if !web_asset_path.exists() {
|
||||
let absolute_path = web_asset_path
|
||||
.parent()
|
||||
@@ -252,13 +247,13 @@ pub fn setup(
|
||||
}
|
||||
|
||||
if options.runner.is_none() {
|
||||
options.runner = config_.build.runner.clone();
|
||||
options.runner = config.build.runner.clone();
|
||||
}
|
||||
|
||||
options
|
||||
.features
|
||||
.get_or_insert(Vec::new())
|
||||
.extend(config_.build.features.clone().unwrap_or_default());
|
||||
.extend(config.build.features.clone().unwrap_or_default());
|
||||
interface.build_options(&mut options.args, &mut options.features, mobile);
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -158,7 +158,7 @@ pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
|
||||
verbosity,
|
||||
ci,
|
||||
&interface,
|
||||
&app_settings,
|
||||
&*app_settings,
|
||||
config_,
|
||||
&out_dir,
|
||||
)
|
||||
@@ -170,7 +170,7 @@ pub fn bundle<A: AppSettings>(
|
||||
verbosity: u8,
|
||||
ci: bool,
|
||||
interface: &AppInterface,
|
||||
app_settings: &std::sync::Arc<A>,
|
||||
app_settings: &A,
|
||||
config: &ConfigMetadata,
|
||||
out_dir: &Path,
|
||||
) -> crate::Result<()> {
|
||||
|
||||
@@ -34,7 +34,7 @@ use std::{
|
||||
mod builtin_dev_server;
|
||||
|
||||
static BEFORE_DEV: OnceLock<Mutex<Arc<SharedChild>>> = OnceLock::new();
|
||||
static KILL_BEFORE_DEV_FLAG: OnceLock<AtomicBool> = OnceLock::new();
|
||||
static KILL_BEFORE_DEV_FLAG: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[cfg(unix)]
|
||||
const KILL_CHILDREN_SCRIPT: &[u8] = include_bytes!("../scripts/kill-children.sh");
|
||||
@@ -218,14 +218,13 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
let status = child_
|
||||
.wait()
|
||||
.expect("failed to wait on \"beforeDevCommand\"");
|
||||
if !(status.success() || KILL_BEFORE_DEV_FLAG.get().unwrap().load(Ordering::Relaxed)) {
|
||||
if !(status.success() || KILL_BEFORE_DEV_FLAG.load(Ordering::Relaxed)) {
|
||||
log::error!("The \"beforeDevCommand\" terminated with a non-zero status code.");
|
||||
exit(status.code().unwrap_or(1));
|
||||
}
|
||||
});
|
||||
|
||||
BEFORE_DEV.set(Mutex::new(child)).unwrap();
|
||||
KILL_BEFORE_DEV_FLAG.set(AtomicBool::default()).unwrap();
|
||||
|
||||
let _ = ctrlc::set_handler(move || {
|
||||
kill_before_dev_process();
|
||||
@@ -304,12 +303,10 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
|
||||
|
||||
if !options.no_dev_server_wait {
|
||||
if let Some(url) = dev_url {
|
||||
let host = url
|
||||
.host()
|
||||
.unwrap_or_else(|| panic!("No host name in the URL"));
|
||||
let host = url.host().expect("No host name in the URL");
|
||||
let port = url
|
||||
.port_or_known_default()
|
||||
.unwrap_or_else(|| panic!("No port number in the URL"));
|
||||
.expect("No port number in the URL");
|
||||
let addrs;
|
||||
let addr;
|
||||
let addrs = match host {
|
||||
@@ -380,11 +377,10 @@ pub fn on_app_exit(code: Option<i32>, reason: ExitReason, exit_on_panic: bool, n
|
||||
pub fn kill_before_dev_process() {
|
||||
if let Some(child) = BEFORE_DEV.get() {
|
||||
let child = child.lock().unwrap();
|
||||
let kill_before_dev_flag = KILL_BEFORE_DEV_FLAG.get().unwrap();
|
||||
if kill_before_dev_flag.load(Ordering::Relaxed) {
|
||||
if KILL_BEFORE_DEV_FLAG.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
kill_before_dev_flag.store(true, Ordering::Relaxed);
|
||||
KILL_BEFORE_DEV_FLAG.store(true, Ordering::Relaxed);
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let powershell_path = std::env::var("SYSTEMROOT").map_or_else(
|
||||
|
||||
@@ -75,21 +75,13 @@ fn lookup<F: Fn(&PathBuf) -> bool>(dir: &Path, checker: F) -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
fn env_tauri_app_path() -> Option<PathBuf> {
|
||||
std::env::var(ENV_TAURI_APP_PATH)
|
||||
.map(PathBuf::from)
|
||||
.ok()?
|
||||
.canonicalize()
|
||||
.ok()
|
||||
.map(|p| dunce::simplified(&p).to_path_buf())
|
||||
let p = PathBuf::from(std::env::var_os(ENV_TAURI_APP_PATH)?);
|
||||
dunce::canonicalize(p).ok()
|
||||
}
|
||||
|
||||
fn env_tauri_frontend_path() -> Option<PathBuf> {
|
||||
std::env::var(ENV_TAURI_FRONTEND_PATH)
|
||||
.map(PathBuf::from)
|
||||
.ok()?
|
||||
.canonicalize()
|
||||
.ok()
|
||||
.map(|p| dunce::simplified(&p).to_path_buf())
|
||||
let p = PathBuf::from(std::env::var_os(ENV_TAURI_FRONTEND_PATH)?);
|
||||
dunce::canonicalize(p).ok()
|
||||
}
|
||||
|
||||
pub fn resolve_tauri_dir() -> Option<PathBuf> {
|
||||
|
||||
@@ -12,9 +12,9 @@ pub use tauri_utils::{config::*, platform::Target};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env::{current_dir, set_current_dir, set_var},
|
||||
ffi::OsStr,
|
||||
ffi::{OsStr, OsString},
|
||||
process::exit,
|
||||
sync::{Arc, Mutex, OnceLock},
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
use crate::error::Context;
|
||||
@@ -30,7 +30,7 @@ pub struct ConfigMetadata {
|
||||
inner: Config,
|
||||
/// The config extensions (platform-specific config files or the config CLI argument).
|
||||
/// Maps the extension name to its value.
|
||||
extensions: HashMap<String, JsonValue>,
|
||||
extensions: HashMap<OsString, JsonValue>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for ConfigMetadata {
|
||||
@@ -50,7 +50,7 @@ impl ConfigMetadata {
|
||||
}
|
||||
|
||||
/// Checks which config is overwriting the bundle identifier.
|
||||
pub fn find_bundle_identifier_overwriter(&self) -> Option<String> {
|
||||
pub fn find_bundle_identifier_overwriter(&self) -> Option<OsString> {
|
||||
for (ext, config) in &self.extensions {
|
||||
if let Some(identifier) = config
|
||||
.as_object()
|
||||
@@ -66,7 +66,7 @@ impl ConfigMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
pub type ConfigHandle = Arc<Mutex<Option<ConfigMetadata>>>;
|
||||
pub type ConfigHandle = &'static Mutex<Option<ConfigMetadata>>;
|
||||
|
||||
pub fn wix_settings(config: WixConfig) -> tauri_bundler::WixSettings {
|
||||
tauri_bundler::WixSettings {
|
||||
@@ -141,9 +141,9 @@ pub fn custom_sign_settings(
|
||||
}
|
||||
}
|
||||
|
||||
fn config_handle() -> &'static ConfigHandle {
|
||||
static CONFIG_HANDLE: OnceLock<ConfigHandle> = OnceLock::new();
|
||||
CONFIG_HANDLE.get_or_init(Default::default)
|
||||
fn config_handle() -> ConfigHandle {
|
||||
static CONFIG_HANDLE: Mutex<Option<ConfigMetadata>> = Mutex::new(None);
|
||||
&CONFIG_HANDLE
|
||||
}
|
||||
|
||||
/// Gets the static parsed config from `tauri.conf.json`.
|
||||
@@ -153,14 +153,14 @@ fn get_internal(
|
||||
target: Target,
|
||||
) -> crate::Result<ConfigHandle> {
|
||||
if !reload && config_handle().lock().unwrap().is_some() {
|
||||
return Ok(config_handle().clone());
|
||||
return Ok(config_handle());
|
||||
}
|
||||
|
||||
let tauri_dir = super::app_paths::tauri_dir();
|
||||
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().to_string_lossy();
|
||||
let config_file_name = config_path.file_name().unwrap();
|
||||
let mut extensions = HashMap::new();
|
||||
|
||||
let original_identifier = config
|
||||
@@ -174,10 +174,7 @@ fn get_internal(
|
||||
.context("failed to parse platform config")?
|
||||
{
|
||||
merge(&mut config, &platform_config);
|
||||
extensions.insert(
|
||||
config_path.file_name().unwrap().to_str().unwrap().into(),
|
||||
platform_config,
|
||||
);
|
||||
extensions.insert(config_path.file_name().unwrap().into(), platform_config);
|
||||
}
|
||||
|
||||
if !merge_configs.is_empty() {
|
||||
@@ -203,9 +200,9 @@ fn get_internal(
|
||||
for error in errors {
|
||||
let path = error.instance_path.into_iter().join(" > ");
|
||||
if path.is_empty() {
|
||||
log::error!("`{}` error: {}", config_file_name, error);
|
||||
log::error!("`{config_file_name:?}` error: {}", error);
|
||||
} else {
|
||||
log::error!("`{}` error on `{}`: {}", config_file_name, path, error);
|
||||
log::error!("`{config_file_name:?}` error on `{}`: {}", path, error);
|
||||
}
|
||||
}
|
||||
if !reload {
|
||||
@@ -243,7 +240,7 @@ fn get_internal(
|
||||
extensions,
|
||||
});
|
||||
|
||||
Ok(config_handle().clone())
|
||||
Ok(config_handle())
|
||||
}
|
||||
|
||||
pub fn get(target: Target, merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
|
||||
@@ -268,7 +265,7 @@ pub fn merge_with(merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigH
|
||||
let handle = config_handle();
|
||||
|
||||
if merge_configs.is_empty() {
|
||||
return Ok(handle.clone());
|
||||
return Ok(handle);
|
||||
}
|
||||
|
||||
if let Some(config_metadata) = &mut *handle.lock().unwrap() {
|
||||
@@ -285,7 +282,7 @@ pub fn merge_with(merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigH
|
||||
merge(&mut value, &merge_config);
|
||||
config_metadata.inner = serde_json::from_value(value).context("failed to parse config")?;
|
||||
|
||||
Ok(handle.clone())
|
||||
Ok(handle)
|
||||
} else {
|
||||
crate::error::bail!("config not loaded");
|
||||
}
|
||||
|
||||
@@ -184,7 +184,12 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<BuiltApplica
|
||||
false,
|
||||
)?;
|
||||
|
||||
crate::build::setup(&interface, &mut build_options, tauri_config.clone(), true)?;
|
||||
{
|
||||
let config_guard = tauri_config.lock().unwrap();
|
||||
let config_ = config_guard.as_ref().unwrap();
|
||||
|
||||
crate::build::setup(&interface, &mut build_options, config_, true)?;
|
||||
}
|
||||
|
||||
let installed_targets =
|
||||
crate::interface::rust::installation::installed_targets().unwrap_or_default();
|
||||
|
||||
@@ -257,7 +257,7 @@ fn run_dev(
|
||||
use_network_address_for_dev_url(&tauri_config, &mut dev_options, options.force_ip_prompt)?;
|
||||
}
|
||||
|
||||
crate::dev::setup(&interface, &mut dev_options, tauri_config.clone())?;
|
||||
crate::dev::setup(&interface, &mut dev_options, tauri_config)?;
|
||||
|
||||
let interface_options = InterfaceOptions {
|
||||
debug: !dev_options.release_mode,
|
||||
|
||||
@@ -367,7 +367,12 @@ fn run_build(
|
||||
Profile::Release
|
||||
};
|
||||
|
||||
crate::build::setup(interface, &mut build_options, tauri_config.clone(), true)?;
|
||||
crate::build::setup(
|
||||
interface,
|
||||
&mut build_options,
|
||||
tauri_config.lock().unwrap().as_ref().unwrap(),
|
||||
true,
|
||||
)?;
|
||||
|
||||
let app_settings = interface.app_settings();
|
||||
let out_dir = app_settings.out_dir(&InterfaceOptions {
|
||||
|
||||
@@ -209,7 +209,7 @@ pub fn read_platform(
|
||||
/// JSON with `.json`.
|
||||
pub fn does_supported_file_name_exist(target: Target, path: impl Into<PathBuf>) -> bool {
|
||||
let path = path.into();
|
||||
let source_file_name = path.file_name().unwrap().to_str().unwrap();
|
||||
let source_file_name = path.file_name().unwrap();
|
||||
let lookup_platform_config = ENABLED_FORMATS
|
||||
.iter()
|
||||
.any(|format| source_file_name == format.into_platform_file_name(target));
|
||||
|
||||
@@ -238,16 +238,12 @@ const CARGO_OUTPUT_DIRECTORIES: &[&str] = &["debug", "release", "custom-profile"
|
||||
|
||||
#[cfg(test)]
|
||||
fn is_cargo_output_directory(path: &std::path::Path) -> bool {
|
||||
let last_component = path
|
||||
.components()
|
||||
.next_back()
|
||||
.unwrap()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
let Some(last_component) = path.components().next_back() else {
|
||||
return false;
|
||||
};
|
||||
CARGO_OUTPUT_DIRECTORIES
|
||||
.iter()
|
||||
.any(|dirname| &last_component == dirname)
|
||||
.any(|dirname| &last_component.as_os_str() == dirname)
|
||||
}
|
||||
|
||||
/// Computes the resource directory of the current environment.
|
||||
|
||||
@@ -97,9 +97,7 @@ impl<'a> ResourcePaths<'a> {
|
||||
iter: ResourcePathsIter {
|
||||
pattern_iter: PatternIter::Slice(patterns.iter()),
|
||||
allow_walk,
|
||||
current_path: None,
|
||||
current_pattern: None,
|
||||
current_dest: None,
|
||||
walk_iter: None,
|
||||
glob_iter: None,
|
||||
},
|
||||
@@ -112,9 +110,7 @@ impl<'a> ResourcePaths<'a> {
|
||||
iter: ResourcePathsIter {
|
||||
pattern_iter: PatternIter::Map(patterns.iter()),
|
||||
allow_walk,
|
||||
current_path: None,
|
||||
current_pattern: None,
|
||||
current_dest: None,
|
||||
walk_iter: None,
|
||||
glob_iter: None,
|
||||
},
|
||||
@@ -136,13 +132,9 @@ pub struct ResourcePathsIter<'a> {
|
||||
/// whether the resource paths allows directories or not.
|
||||
allow_walk: bool,
|
||||
|
||||
current_path: Option<PathBuf>,
|
||||
/// The key of map when `pattern_iter` is a [`PatternIter::Map`],
|
||||
/// The (key, value) of map when `pattern_iter` is a [`PatternIter::Map`],
|
||||
/// used for determining [`Resource::target`]
|
||||
current_pattern: Option<String>,
|
||||
/// The value of the map when `pattern_iter` is a [`PatternIter::Map`],
|
||||
/// used for determining [`Resource::target`]
|
||||
current_dest: Option<PathBuf>,
|
||||
current_pattern: Option<(String, PathBuf)>,
|
||||
|
||||
walk_iter: Option<walkdir::IntoIter>,
|
||||
glob_iter: Option<glob::Paths>,
|
||||
@@ -157,8 +149,7 @@ impl ResourcePathsIter<'_> {
|
||||
Err(err) => return Some(Err(err.into())),
|
||||
};
|
||||
|
||||
self.current_path = Some(normalize(&entry));
|
||||
self.next_current_path()
|
||||
self.next_current_path(normalize(&entry))
|
||||
}
|
||||
|
||||
fn next_walk_iter(&mut self) -> Option<crate::Result<Resource>> {
|
||||
@@ -169,8 +160,7 @@ impl ResourcePathsIter<'_> {
|
||||
Err(err) => return Some(Err(err.into())),
|
||||
};
|
||||
|
||||
self.current_path = Some(normalize(entry.path()));
|
||||
self.next_current_path()
|
||||
self.next_current_path(normalize(entry.path()))
|
||||
}
|
||||
|
||||
fn resource_from_path(&mut self, path: &Path) -> crate::Result<Resource> {
|
||||
@@ -180,12 +170,11 @@ impl ResourcePathsIter<'_> {
|
||||
|
||||
Ok(Resource {
|
||||
path: path.to_path_buf(),
|
||||
target: if let Some(current_dest) = &self.current_dest {
|
||||
target: if let Some((pattern, dest)) = &self.current_pattern {
|
||||
// if processing a directory, preserve directory structure under current_dest
|
||||
if self.walk_iter.is_some() {
|
||||
let current_pattern = self.current_pattern.as_ref().unwrap();
|
||||
current_dest.join(path.strip_prefix(current_pattern).unwrap_or(path))
|
||||
} else if current_dest.components().count() == 0 {
|
||||
dest.join(path.strip_prefix(pattern).unwrap_or(path))
|
||||
} else if dest.components().count() == 0 {
|
||||
// if current_dest is empty while processing a file pattern or glob
|
||||
// we preserve the file name as it is
|
||||
PathBuf::from(path.file_name().unwrap())
|
||||
@@ -193,9 +182,9 @@ impl ResourcePathsIter<'_> {
|
||||
// if processing a glob and current_dest is not empty
|
||||
// we put all globbed paths under current_dest
|
||||
// preserving the file name as it is
|
||||
current_dest.join(path.file_name().unwrap())
|
||||
dest.join(path.file_name().unwrap())
|
||||
} else {
|
||||
current_dest.clone()
|
||||
dest.clone()
|
||||
}
|
||||
} else {
|
||||
// If `pattern_iter` is a [`PatternIter::Slice`]
|
||||
@@ -204,11 +193,7 @@ impl ResourcePathsIter<'_> {
|
||||
})
|
||||
}
|
||||
|
||||
fn next_current_path(&mut self) -> Option<crate::Result<Resource>> {
|
||||
// should be safe to unwrap since every call to `self.next_current_path()`
|
||||
// is preceded with assignment to `self.current_path`
|
||||
let path = self.current_path.take().unwrap();
|
||||
|
||||
fn next_current_path(&mut self, path: PathBuf) -> Option<crate::Result<Resource>> {
|
||||
let is_dir = path.is_dir();
|
||||
|
||||
if is_dir {
|
||||
@@ -238,15 +223,12 @@ impl ResourcePathsIter<'_> {
|
||||
|
||||
fn next_pattern(&mut self) -> Option<crate::Result<Resource>> {
|
||||
self.current_pattern = None;
|
||||
self.current_dest = None;
|
||||
self.current_path = None;
|
||||
|
||||
let pattern = match &mut self.pattern_iter {
|
||||
PatternIter::Slice(iter) => iter.next()?,
|
||||
PatternIter::Map(iter) => {
|
||||
let (pattern, dest) = iter.next()?;
|
||||
self.current_pattern = Some(pattern.clone());
|
||||
self.current_dest = Some(resource_relpath(Path::new(dest)));
|
||||
self.current_pattern = Some((pattern.clone(), resource_relpath(Path::new(dest))));
|
||||
pattern
|
||||
}
|
||||
};
|
||||
@@ -265,8 +247,7 @@ impl ResourcePathsIter<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
self.current_path = Some(normalize(Path::new(pattern)));
|
||||
self.next_current_path()
|
||||
self.next_current_path(normalize(Path::new(pattern)))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,10 +263,6 @@ impl Iterator for ResourcePathsIter<'_> {
|
||||
type Item = crate::Result<Resource>;
|
||||
|
||||
fn next(&mut self) -> Option<crate::Result<Resource>> {
|
||||
if self.current_path.is_some() {
|
||||
return self.next_current_path();
|
||||
}
|
||||
|
||||
if self.walk_iter.is_some() {
|
||||
match self.next_walk_iter() {
|
||||
Some(r) => return Some(r),
|
||||
|
||||
Reference in New Issue
Block a user