1use std::path::{MAIN_SEPARATOR, Path};
5
6pub(crate) fn to_posix_string(path: &Path) -> String {
12 path.to_string_lossy().replace(MAIN_SEPARATOR, "/")
13}
14
15pub(crate) fn parent_dir(path: &str) -> &str {
16 path.rsplit_once('/').map_or("", |(parent, _)| parent)
17}
18
19pub(crate) fn parent_dir_for_lookup(path: &str) -> Option<&str> {
20 if path.is_empty() {
21 return None;
22 }
23
24 path.rsplit_once('/').map(|(parent, _)| parent).or(Some(""))
25}
26
27#[cfg(test)]
28mod tests {
29 use super::{parent_dir, parent_dir_for_lookup, to_posix_string};
30
31 #[test]
32 fn to_posix_string_uses_forward_slashes() {
33 let path: std::path::PathBuf = ["packages", "app", "index.js"].iter().collect();
36 assert_eq!(to_posix_string(&path), "packages/app/index.js");
37 }
38
39 #[test]
40 fn parent_dir_handles_top_level_paths() {
41 assert_eq!(parent_dir("package.json"), "");
42 assert_eq!(parent_dir("packages/app/package.json"), "packages/app");
43 }
44
45 #[test]
46 fn parent_dir_for_lookup_walks_up_to_empty_root() {
47 assert_eq!(parent_dir_for_lookup("packages/app"), Some("packages"));
48 assert_eq!(parent_dir_for_lookup("packages"), Some(""));
49 assert_eq!(parent_dir_for_lookup(""), None);
50 }
51}