use crate::common::pack_path::PackPath;
use anyhow::{Error, anyhow, ensure};
use std::{
iter,
path::{Component, Path},
};
pub fn from_file_base_relative_path(file_base_relative_path: &Path) -> Result<PackPath, Error> {
assert!(file_base_relative_path.is_relative());
let file_base_relative_path_components = file_base_relative_path
.components()
.map(|component| {
ensure!(
matches!(component, Component::Normal(_)),
"relative path must not contain only standard path items, got {:?}",
component
);
component
.as_os_str()
.to_str()
.ok_or_else(|| anyhow!("cannot convert path component to string"))
})
.collect::<Result<Vec<_>, Error>>()?;
let pack_path_string = itertools::join(
iter::once("").chain(file_base_relative_path_components),
"/",
);
let pack_path = PackPath::from_string(pack_path_string);
Ok(pack_path)
}
#[cfg(test)]
mod test {
use super::from_file_base_relative_path;
use crate::common::pack_path::PackPath;
use std::path::{Path, PathBuf};
use test_case::test_case;
#[test_case(
&PathBuf::from("somefile"),
&PackPath::from_string("/somefile".to_owned());
"base file path without prefix"
)]
#[test_case(
&PathBuf::from("linux/like/relative/path.html"),
&PackPath::from_string("/linux/like/relative/path.html".to_owned());
"linux like relative path"
)]
#[test_case(
&PathBuf::from("Project\\MyApp\\Application.js"),
&PackPath::from_string("/Project/MyApp/Application.js".to_owned());
"windows relative path"
)]
fn from_file_base_relative_path_returns_expected(
path: &Path,
expected: &PackPath,
) {
assert_eq!(&from_file_base_relative_path(path).unwrap(), expected);
}
}