diff --git a/src/app.rs b/src/app.rs index 8626aa3b..a8fd15d0 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,6 +1,6 @@ use crate::{ accessors, - args::CliArgs, + args::{resolve_select_file_path, CliArgs}, cmdbar::CommandBar, components::{ command_pump, event_pump, CommandInfo, Component, @@ -178,14 +178,13 @@ impl App { let mut select_file: Option = None; let tab = if let Some(file) = cliargs.select_file { - // convert to relative git path - if let Ok(abs) = file.canonicalize() { - if let Ok(path) = abs.strip_prefix( - env.repo.borrow().gitpath().canonicalize()?, - ) { - select_file = Some(Path::new(".").join(path)); - } - } + let workdir = + PathBuf::from(repo_work_dir(&env.repo.borrow())?); + select_file = resolve_select_file_path( + &file, + &workdir, + &std::env::current_dir()?, + ); 2 } else { env.options.borrow().current_tab() diff --git a/src/args.rs b/src/args.rs index 22c6cc8d..54f3ba12 100644 --- a/src/args.rs +++ b/src/args.rs @@ -9,7 +9,7 @@ use simplelog::{Config, LevelFilter, WriteLogger}; use std::{ env, fs::{self, File}, - path::PathBuf, + path::{Path, PathBuf}, }; const BUG_REPORT_FLAG_ID: &str = "bugreport"; @@ -238,6 +238,73 @@ pub fn get_app_config_path() -> Result { Ok(path) } +/// Resolves `--file` to a path relative to the repository workdir. +pub(crate) fn resolve_select_file_path( + file: &Path, + repo_workdir: &Path, + cwd: &Path, +) -> Option { + let repo_workdir = repo_workdir.canonicalize().ok()?; + let absolute = if file.is_absolute() { + file.to_path_buf() + } else { + cwd.join(file) + }; + let absolute = absolute.canonicalize().ok()?; + + absolute + .strip_prefix(&repo_workdir) + .ok() + .map(Path::to_path_buf) +} + +#[cfg(test)] +mod select_file_tests { + use super::*; + use std::fs; + use tempfile::tempdir; + + #[test] + fn resolve_select_file_from_subdirectory() { + let repo = tempdir().unwrap(); + let frontend = repo.path().join("frontend"); + fs::create_dir_all(frontend.join("src")).unwrap(); + fs::write(frontend.join("src/index.html"), "hi").unwrap(); + + let cwd = frontend.clone(); + let file = Path::new("src/index.html"); + let resolved = resolve_select_file_path( + file, + repo.path(), + &cwd, + ) + .unwrap(); + + assert_eq!(resolved, Path::new("frontend/src/index.html")); + } + + #[test] + fn resolve_select_file_from_repo_root() { + let repo = tempdir().unwrap(); + fs::create_dir_all(repo.path().join("frontend/src")).unwrap(); + fs::write( + repo.path().join("frontend/src/index.html"), + "hi", + ) + .unwrap(); + + let file = Path::new("frontend/src/index.html"); + let resolved = resolve_select_file_path( + file, + repo.path(), + repo.path(), + ) + .unwrap(); + + assert_eq!(resolved, file); + } +} + #[test] fn verify_app() { app().debug_assert();