diff --git a/src/cmd/add.rs b/src/cmd/add.rs index 302ae0a..546051a 100644 --- a/src/cmd/add.rs +++ b/src/cmd/add.rs @@ -4,7 +4,7 @@ use anyhow::{Result, bail}; use crate::cmd::{Add, Run}; use crate::db::Database; -use crate::{config, util}; +use crate::{config, path_resolver, util}; impl Run for Add { fn run(&self) -> Result<()> { @@ -19,10 +19,7 @@ impl Run for Add { let mut db = Database::open()?; for path in &self.paths { - let path = - if config::resolve_symlinks() { util::canonicalize } else { util::resolve_path }( - path, - )?; + let path = path_resolver::resolve(path, config::resolve_symlinks())?; let path = util::path_to_str(&path)?; // Ignore path if it contains unsupported characters, or if it's in the exclude diff --git a/src/main.rs b/src/main.rs index e432b12..11b5ecc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod config; mod db; mod error; mod import; +mod path_resolver; mod shell; mod util; diff --git a/src/path_resolver.rs b/src/path_resolver.rs new file mode 100644 index 0000000..a853387 --- /dev/null +++ b/src/path_resolver.rs @@ -0,0 +1,65 @@ +use std::path::{Path, PathBuf}; +use std::process::Command; + +use anyhow::{Context, Result}; + +use crate::util; + +pub fn resolve(path: impl AsRef, resolve_symlinks: bool) -> Result { + if resolve_symlinks { + return util::canonicalize(path); + } + + #[cfg(target_os = "macos")] + { + return resolve_macos(path); + } + + #[cfg(not(target_os = "macos"))] + { + util::resolve_path(path) + } +} + +#[cfg(target_os = "macos")] +fn resolve_macos(path: impl AsRef) -> Result { + let path = util::resolve_path(path)?; + + if path.is_file() { + if let Some(resolved) = resolve_finder_alias(&path)? { + return Ok(resolved); + } + } + + Ok(path) +} + +#[cfg(target_os = "macos")] +fn resolve_finder_alias(path: &Path) -> Result> { + let script = r#" +on run argv + tell application "Finder" + set alias_path to POSIX file (item 1 of argv) as alias + return POSIX path of (original item of alias_path as alias) + end tell +end run +"#; + + let output = Command::new("osascript") + .arg("-e") + .arg(script) + .arg(path) + .output() + .context("could not run osascript to resolve Finder alias")?; + + if !output.status.success() { + return Ok(None); + } + + let resolved = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if resolved.is_empty() { + return Ok(None); + } + + Ok(Some(util::resolve_path(resolved)?)) +} \ No newline at end of file