#![warn(unused_extern_crates)]
#![allow(clippy::missing_errors_doc)]
pub mod error;
pub mod info;
pub mod json;
pub mod nuget;
pub mod ux;
pub mod validate;
use solp::msbuild::{self};
use solp::{Consume, api::Solution, msbuild::Project};
use std::path::{Path, PathBuf};
use url::Url;
#[must_use]
pub fn parent_of(path: &str) -> &Path {
Path::new(path).parent().unwrap_or_else(|| Path::new(""))
}
#[must_use]
pub fn try_make_local_path(dir: &Path, relative: &str) -> Option<PathBuf> {
Url::parse(relative).err()?;
Some(make_path(dir, relative))
}
#[must_use]
#[cfg(not(target_os = "windows"))]
pub fn make_path(dir: &Path, relative: &str) -> PathBuf {
relative
.split('\\')
.fold(PathBuf::from(&dir), |pb, s| pb.join(s))
}
#[must_use]
#[cfg(target_os = "windows")]
fn make_path(dir: &Path, relative: &str) -> PathBuf {
PathBuf::from(&dir).join(relative)
}
#[must_use]
pub fn calculate_percent(value: i32, total: i32) -> f64 {
if total == 0 {
0_f64
} else {
(f64::from(value) / f64::from(total)) * 100_f64
}
}
pub struct MsbuildProject {
pub project: Option<msbuild::Project>,
pub path: PathBuf,
}
#[must_use]
pub fn collect_msbuild_projects(solution: &Solution) -> Vec<MsbuildProject> {
let dir = parent_of(solution.path);
solution
.iterate_projects_without_web_sites()
.filter_map(|p| try_make_local_path(dir, p.path_or_uri))
.filter_map(|path| match Project::from_path(&path) {
Ok(project) => Some(MsbuildProject {
path,
project: Some(project),
}),
Err(e) => {
if cfg!(debug_assertions) {
let p = path.to_str().unwrap_or_default();
println!("{p}: {e:?}");
}
None
}
})
.collect()
}
#[cfg(test)]
#[cfg(not(target_os = "windows"))]
pub mod tests {
use super::*;
use test_case::test_case;
#[test_case("/base", "x", "/base/x")]
#[test_case("/base", r"x\y", "/base/x/y")]
#[test_case("/base", "x/y", "/base/x/y")]
fn make_path_tests(base: &str, path: &str, expected: &str) {
let d = Path::new(base);
let actual = make_path(d, path);
assert_eq!(actual.to_str().unwrap(), expected);
}
#[test_case("/base", "x", Some(PathBuf::from("/base/x")))]
#[test_case("/base", "http://localhost/a.csproj", None)]
fn try_make_local_path_tests(base: &str, path: &str, expected: Option<PathBuf>) {
let d = Path::new(base);
let actual = try_make_local_path(d, path);
assert_eq!(actual, expected);
}
#[test_case(1, 100, 1.0)]
#[test_case(0, 100, 0.0)]
#[test_case(100, 100, 100.0)]
#[test_case(50, 100, 50.0)]
#[test_case(20, 100, 20.0)]
fn calculate_percent_tests(value: i32, total: i32, expected: f64) {
let actual = calculate_percent(value, total);
assert_eq!(actual, expected);
}
#[test]
fn test_parent_of_absolute_path() {
let path = "/home/user/path";
let expected = Path::new("/home/user");
let actual = parent_of(path);
assert_eq!(actual, expected);
}
#[test]
fn test_parent_of_relative_path() {
let path = "file.txt";
let expected = Path::new("");
let actual = parent_of(path);
assert_eq!(actual, expected);
}
#[test]
fn test_parent_of_empty_string() {
let path = "";
let expected = Path::new("");
let actual = parent_of(path);
assert_eq!(actual, expected);
}
}