use std::path::{Path, PathBuf};
use super::error::PackageError;
pub(crate) struct LicenseInventory {
pub entries: Vec<(String, PathBuf)>,
}
impl LicenseInventory {
pub(crate) fn discover(app_root: &Path, framework_root: &Path) -> Result<Self, PackageError> {
let mut entries = Vec::new();
for candidate in ["LICENSE", "LICENSE.md", "LICENSE.txt", "COPYING"] {
let path = app_root.join(candidate);
if path.is_file() {
entries.push(("LICENSE".to_owned(), path));
break;
}
}
let fw_license = framework_root.join("LICENSE");
if fw_license.is_file() {
entries.push(("LICENSE-arcature".to_owned(), fw_license));
}
Ok(LicenseInventory { entries })
}
pub(crate) fn write(
&self,
licenses_dir: &Path,
) -> Result<Vec<(String, PathBuf)>, PackageError> {
std::fs::create_dir_all(licenses_dir).map_err(|source| PackageError::Write {
path: licenses_dir.to_path_buf(),
source,
})?;
let mut copied = Vec::new();
for (name, source) in &self.entries {
let dest = licenses_dir.join(name);
std::fs::copy(source, &dest).map_err(|err| PackageError::Copy {
what: "license",
from: source.clone(),
source: err,
})?;
copied.push((name.clone(), dest));
}
copied.sort_by(|a, b| a.0.cmp(&b.0));
Ok(copied)
}
}
#[cfg(test)]
mod tests {
use super::LicenseInventory;
use std::fs;
use std::path::Path;
#[test]
fn discovers_app_and_framework_licenses() {
let dir = tempfile::tempdir().expect("tempdir");
let app_root = dir.path().join("app");
let fw_root = dir.path().join("fw");
fs::create_dir_all(&app_root).expect("dir");
fs::create_dir_all(&fw_root).expect("dir");
fs::write(app_root.join("LICENSE"), b"app license").expect("write");
fs::write(fw_root.join("LICENSE"), b"arcature license").expect("write");
let inv = LicenseInventory::discover(&app_root, &fw_root).expect("discover");
assert_eq!(inv.entries.len(), 2);
assert!(inv.entries.iter().any(|(n, _)| n == "LICENSE"));
assert!(inv.entries.iter().any(|(n, _)| n == "LICENSE-arcature"));
}
#[test]
fn writes_licenses_into_bundle() {
let dir = tempfile::tempdir().expect("tempdir");
let app_root = dir.path().join("app");
let fw_root = dir.path().join("fw");
fs::create_dir_all(&app_root).expect("dir");
fs::create_dir_all(&fw_root).expect("dir");
fs::write(app_root.join("LICENSE"), b"app license").expect("write");
fs::write(fw_root.join("LICENSE"), b"arcature license").expect("write");
let inv = LicenseInventory::discover(&app_root, &fw_root).expect("discover");
let licenses_dir = dir.path().join("bundle").join("licenses");
let copied = inv.write(&licenses_dir).expect("write");
assert_eq!(copied.len(), 2);
let app_text = fs::read_to_string(licenses_dir.join("LICENSE")).expect("read");
assert_eq!(app_text, "app license");
let fw_text = fs::read_to_string(licenses_dir.join("LICENSE-arcature")).expect("read");
assert_eq!(fw_text, "arcature license");
let _ = Path::new(&licenses_dir);
}
#[test]
fn missing_app_license_is_skipped() {
let dir = tempfile::tempdir().expect("tempdir");
let app_root = dir.path().join("app");
let fw_root = dir.path().join("fw");
fs::create_dir_all(&app_root).expect("dir");
fs::create_dir_all(&fw_root).expect("dir");
fs::write(fw_root.join("LICENSE"), b"arcature license").expect("write");
let inv = LicenseInventory::discover(&app_root, &fw_root).expect("discover");
assert_eq!(inv.entries.len(), 1);
assert_eq!(inv.entries[0].0, "LICENSE-arcature");
}
}