use std::path::{Component, Path};
pub fn extract_longest_common_path(path1: &str, path2: &str) -> String {
let path1 = Path::new(path1);
let path2 = Path::new(path2);
let mut components1 = path1.components().peekable();
let mut components2 = path2.components().peekable();
let mut common_path = String::new();
while let (Some(&comp1), Some(&comp2)) = (components1.peek(), components2.peek()) {
if comp1 == comp2 {
match comp1 {
Component::Prefix(_) | Component::RootDir | Component::CurDir | Component::ParentDir => {
common_path.push_str(comp1.as_os_str().to_string_lossy().as_ref());
}
Component::Normal(s) => {
common_path.push_str(s.to_str().unwrap_or("")); common_path.push_str(std::path::MAIN_SEPARATOR_STR);
}
}
components1.next();
components2.next();
} else {
break;
}
}
if common_path.len() > 1 && common_path.ends_with(std::path::MAIN_SEPARATOR_STR) {
common_path.pop();
}
common_path
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_extract_longest_common_path() {
#[cfg(not(windows))]
{
let path1 = "/home/user/documents/report.txt";
let path2 = "/home/user/pictures/image.jpg";
let path3 = "/home/user/documents/presentation.pdf";
let path4 = "/home/user";
let path5 = "/home/user/documents";
let path6 = "/usr/local/bin";
let path7 = "/usr/local";
let path8 = "/";
let path9 = "/";
assert_eq!(extract_longest_common_path(path1, path2), "/home/user");
assert_eq!(extract_longest_common_path(path1, path3), "/home/user/documents");
assert_eq!(extract_longest_common_path(path4, path5), "/home/user");
assert_eq!(extract_longest_common_path(path6, path7), "/usr/local");
assert_eq!(extract_longest_common_path(path1, path6), "/");
assert_eq!(extract_longest_common_path(path8, path9), "/");
}
#[cfg(windows)]
{
let path_mixed1 = "C:\\Users\\user\\Documents\\report.txt";
let path_mixed2 = "/Users/user/Documents/report.txt";
assert_eq!(extract_longest_common_path(path_mixed1, path_mixed2), "");
}
}
}