diff options
Diffstat (limited to 'src/utils/process.rs')
-rw-r--r-- | src/utils/process.rs | 165 |
1 files changed, 63 insertions, 102 deletions
diff --git a/src/utils/process.rs b/src/utils/process.rs index 7c3003d8..d392eb9b 100644 --- a/src/utils/process.rs +++ b/src/utils/process.rs @@ -10,7 +10,7 @@ pub type DeltaPid = u32; #[derive(Clone, Debug, PartialEq, Eq)] pub enum CallingProcess { GitDiff(CommandLine), - GitShow(CommandLine, Option<String>), // element 2 is file extension + GitShow(CommandLine, Option<String>), // element 2 is filename GitLog(CommandLine), GitReflog(CommandLine), GitGrep(CommandLine), @@ -110,11 +110,11 @@ pub enum ProcessArgs<T> { OtherProcess, } -pub fn git_blame_filename_extension() -> Option<String> { - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension) +pub fn git_blame_filename() -> Option<String> { + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename) } -pub fn guess_git_blame_filename_extension(args: &[String]) -> ProcessArgs<String> { +pub fn guess_git_blame_filename(args: &[String]) -> ProcessArgs<String> { let all_args = args.iter().map(|s| s.as_str()); // See git(1) and git-blame(1). Some arguments separate their parameter with space or '=', e.g. @@ -126,10 +126,15 @@ pub fn guess_git_blame_filename_extension(args: &[String]) -> ProcessArgs<String skip_uninteresting_args(all_args, git_blame_options_with_parameter.split(' ')); match selected_args.as_slice() { - [git, "blame", .., last_arg] if is_git_binary(git) => match last_arg.split('.').last() { - Some(arg) => ProcessArgs::Args(arg.to_string()), - None => ProcessArgs::ArgError, - }, + [git, "blame", .., last_arg] if is_git_binary(git) => { + match Path::new(last_arg) + .file_name() + .map(|filename| filename.to_string_lossy().to_string()) + { + Some(filename) => ProcessArgs::Args(filename), + None => ProcessArgs::ArgError, + } + } [git, "blame"] if is_git_binary(git) => ProcessArgs::ArgError, _ => ProcessArgs::OtherProcess, } @@ -158,17 +163,17 @@ pub fn describe_calling_process(args: &[String]) -> ProcessArgs<CallingProcess> } Some("show") => { let command_line = parse_command_line(args); - let extension = if let Some(last_arg) = &command_line.last_arg { + let filename = if let Some(last_arg) = &command_line.last_arg { match last_arg.split_once(':') { - Some((_, suffix)) => { - suffix.split('.').last().map(|s| s.to_string()) - } + Some((_, filename)) => Path::new(filename) + .file_name() + .map(|f| f.to_string_lossy().to_string()), None => None, } } else { None }; - ProcessArgs::Args(CallingProcess::GitShow(command_line, extension)) + ProcessArgs::Args(CallingProcess::GitShow(command_line, filename)) } Some("log") => { ProcessArgs::Args(CallingProcess::GitLog(parse_command_line(args))) @@ -583,7 +588,7 @@ pub mod tests { use std::rc::Rc; thread_local! { - static FAKE_ARGS: RefCell<TlsState<Vec<String>>> = RefCell::new(TlsState::None); + static FAKE_ARGS: RefCell<TlsState<Vec<String>>> = const { RefCell::new(TlsState::None) }; } #[derive(Debug, PartialEq)] @@ -682,17 +687,14 @@ pub mod tests { } #[test] - fn test_guess_git_blame_filename_extension() { + fn test_guess_git_blame_filename() { use ProcessArgs::Args; fn make_string_vec(args: &[&str]) -> Vec<String> { args.iter().map(|&x| x.to_owned()).collect::<Vec<String>>() } let args = make_string_vec(&["git", "blame", "hello", "world.txt"]); - assert_eq!( - guess_git_blame_filename_extension(&args), - Args("txt".into()) - ); + assert_eq!(guess_git_blame_filename(&args), Args("world.txt".into())); let args = make_string_vec(&[ "git", @@ -704,49 +706,34 @@ pub mod tests { "--date", "now", ]); - assert_eq!( - guess_git_blame_filename_extension(&args), - Args("txt".into()) - ); + assert_eq!(guess_git_blame_filename(&args), Args("hello.txt".into())); let args = make_string_vec(&["git", "blame", "-s", "-f", "--", "hello.txt"]); - assert_eq!( - guess_git_blame_filename_extension(&args), - Args("txt".into()) - ); + assert_eq!(guess_git_blame_filename(&args), Args("hello.txt".into())); let args = make_string_vec(&["git", "blame", "--", "--not.an.argument"]); assert_eq!( - guess_git_blame_filename_extension(&args), - Args("argument".into()) + guess_git_blame_filename(&args), + Args("--not.an.argument".into()) ); let args = make_string_vec(&["foo", "bar", "-a", "--123", "not.git"]); - assert_eq!( - guess_git_blame_filename_extension(&args), - ProcessArgs::OtherProcess - ); + assert_eq!(guess_git_blame_filename(&args), ProcessArgs::OtherProcess); let args = make_string_vec(&["git", "blame", "--help.txt"]); - assert_eq!( - guess_git_blame_filename_extension(&args), - ProcessArgs::ArgError - ); + assert_eq!(guess_git_blame_filename(&args), ProcessArgs::ArgError); let args = make_string_vec(&["git", "-c", "a=b", "blame", "main.rs"]); - assert_eq!(guess_git_blame_filename_extension(&args), Args("rs".into())); + assert_eq!(guess_git_blame_filename(&args), Args("main.rs".into())); let args = make_string_vec(&["git", "blame", "README"]); - assert_eq!( - guess_git_blame_filename_extension(&args), - Args("README".into()) - ); + assert_eq!(guess_git_blame_filename(&args), Args("README".into())); let args = make_string_vec(&["git", "blame", ""]); - assert_eq!(guess_git_blame_filename_extension(&args), Args("".into())); + assert_eq!(guess_git_blame_filename(&args), ProcessArgs::ArgError); } - #[derive(Debug)] + #[derive(Debug, Default)] struct FakeProc { #[allow(dead_code)] pid: DeltaPid, @@ -754,16 +741,6 @@ pub mod tests { cmd: Vec<String>, ppid: Option<DeltaPid>, } - impl Default for FakeProc { - fn default() -> Self { - Self { - pid: 0, - start_time: 0, - cmd: Vec::new(), - ppid: None, - } - } - } impl FakeProc { fn new(pid: DeltaPid, start_time: u64, cmd: Vec<String>, ppid: Option<DeltaPid>) -> Self { FakeProc { @@ -790,19 +767,11 @@ pub mod tests { } } - #[derive(Debug)] + #[derive(Debug, Default)] struct MockProcInfo { delta_pid: DeltaPid, info: HashMap<Pid, FakeProc>, } - impl Default for MockProcInfo { - fn default() -> Self { - Self { - delta_pid: 0, - info: HashMap::new(), - } - } - } impl MockProcInfo { fn with(processes: &[(DeltaPid, u64, &str, Option<DeltaPid>)]) -> Self { MockProcInfo { @@ -848,27 +817,22 @@ pub mod tests { { let _args = FakeParentArgs::once("git blame hello"); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), Some("hello".into()) ); } { let _args = FakeParentArgs::once("git blame world.txt"); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), - Some("txt".into()) + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), + Some("world.txt".into()) ); } { let _args = FakeParentArgs::for_scope("git blame hello world.txt"); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), - Some("txt".into()) - ); - - assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), - Some("txt".into()) + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), + Some("world.txt".into()) ); } } @@ -878,11 +842,11 @@ pub mod tests { fn test_process_testing_assert() { let _args = FakeParentArgs::once("git blame do.not.panic"); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), - Some("panic".into()) + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), + Some("do.not.panic".into()) ); - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension); + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename); } #[test] @@ -904,12 +868,12 @@ pub mod tests { fn test_process_testing_n_times_panic() { let _args = FakeParentArgs::with(&["git blame once", "git blame twice"]); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), Some("once".into()) ); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), Some("twice".into()) ); } @@ -925,7 +889,7 @@ pub mod tests { fn test_process_testing_n_times_underused() { let _args = FakeParentArgs::with(&["git blame once", "git blame twice"]); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), Some("once".into()) ); } @@ -936,11 +900,11 @@ pub mod tests { fn test_process_testing_n_times_overused() { let _args = FakeParentArgs::with(&["git blame once"]); assert_eq!( - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension), + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename), Some("once".into()) ); // ignored: dropping causes a panic while panicking, so can't test - calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename_extension); + calling_process_cmdline(ProcInfo::new(), guess_git_blame_filename); } #[test] @@ -952,7 +916,7 @@ pub mod tests { (5, 100, "delta", Some(4)), ]); assert_eq!( - calling_process_cmdline(two_trees, guess_git_blame_filename_extension), + calling_process_cmdline(two_trees, guess_git_blame_filename), None ); } @@ -961,7 +925,7 @@ pub mod tests { fn test_process_blame_info_with_parent() { let no_processes = MockProcInfo::with(&[]); assert_eq!( - calling_process_cmdline(no_processes, guess_git_blame_filename_extension), + calling_process_cmdline(no_processes, guess_git_blame_filename), None ); @@ -971,8 +935,8 @@ pub mod tests { (4, 100, "delta", Some(3)), ]); assert_eq!( - calling_process_cmdline(parent, guess_git_blame_filename_extension), - Some("txt".into()) + calling_process_cmdline(parent, guess_git_blame_filename), + Some("hello.txt".into()) ); let grandparent = MockProcInfo::with(&[ @@ -982,8 +946,8 @@ pub mod tests { (5, 100, "delta", Some(4)), ]); assert_eq!( - calling_process_cmdline(grandparent, guess_git_blame_filename_extension), - Some("rs".into()) + calling_process_cmdline(grandparent, guess_git_blame_filename), + Some("main.rs".into()) ); } @@ -996,8 +960,8 @@ pub mod tests { (5, 100, "delta", Some(3)), ]); assert_eq!( - calling_process_cmdline(sibling, guess_git_blame_filename_extension), - Some("rs".into()) + calling_process_cmdline(sibling, guess_git_blame_filename), + Some("main.rs".into()) ); let indirect_sibling = MockProcInfo::with(&[ @@ -1014,8 +978,8 @@ pub mod tests { (20, 100, "delta", Some(5)), ]); assert_eq!( - calling_process_cmdline(indirect_sibling, guess_git_blame_filename_extension), - Some("abc".into()) + calling_process_cmdline(indirect_sibling, guess_git_blame_filename), + Some("main.abc".into()) ); let indirect_sibling2 = MockProcInfo::with(&[ @@ -1027,8 +991,8 @@ pub mod tests { (20, 100, "delta", Some(5)), ]); assert_eq!( - calling_process_cmdline(indirect_sibling2, guess_git_blame_filename_extension), - Some("def".into()) + calling_process_cmdline(indirect_sibling2, guess_git_blame_filename), + Some("main.def".into()) ); // 3 blame processes, 2 with matching start times, pick the one with lower @@ -1046,11 +1010,8 @@ pub mod tests { (20, 100, "delta", Some(5)), ]); assert_eq!( - calling_process_cmdline( - indirect_sibling_start_times, - guess_git_blame_filename_extension - ), - Some("this".into()) + calling_process_cmdline(indirect_sibling_start_times, guess_git_blame_filename), + Some("main.this".into()) ); } @@ -1140,7 +1101,7 @@ pub mod tests { for (command, expected_extension) in [ ( "/usr/local/bin/git show --abbrev-commit -w 775c3b84:./src/hello.rs", - "rs", + "hello.rs", ), ( "/usr/local/bin/git show --abbrev-commit -w HEAD~1:Makefile", @@ -1148,7 +1109,7 @@ pub mod tests { ), ( "git -c x.y=z show --abbrev-commit -w 775c3b84:./src/hello.bye.R", - "R", + "hello.bye.R", ), ] { let parent = MockProcInfo::with(&[ @@ -1156,12 +1117,12 @@ pub mod tests { (3, 100, command, Some(2)), (4, 100, "delta", Some(3)), ]); - if let Some(CallingProcess::GitShow(cmd_line, ext)) = + if let Some(CallingProcess::GitShow(cmd_line, filename)) = calling_process_cmdline(parent, describe_calling_process) { assert_eq!(cmd_line.long_options, set(&["--abbrev-commit"])); assert_eq!(cmd_line.short_options, set(&["-w"])); - assert_eq!(ext, Some(expected_extension.to_string())); + assert_eq!(filename, Some(expected_extension.to_string())); } else { unreachable!(); } |