sancus_lib/
third_party_licenses.rs1use anyhow::{Context, Result};
12use log::*;
13use serde::{Deserialize, Serialize};
14use std::path::Path;
15
16use crate::license_info::LicenseInfo;
17use crate::settings;
18
19#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
20#[serde(rename_all = "snake_case")]
21pub struct License {
22 pub license: String,
23 pub text: String,
24}
25
26#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
27#[serde(rename_all = "snake_case")]
28pub struct ThirdPartyLibrary {
29 pub package_name: String,
30 pub package_version: String,
31 pub license: String,
32 pub licenses: Vec<License>,
33}
34
35#[derive(Debug, Default, Serialize, Deserialize, Clone, PartialEq)]
36#[serde(rename_all = "snake_case")]
37pub struct ThirdPartyLicenses {
38 pub root_name: String,
39 pub third_party_libraries: Vec<ThirdPartyLibrary>,
40}
41
42impl ThirdPartyLicenses {
43 pub fn load(file: &std::path::Path) -> Result<Self> {
44 let str = std::fs::read_to_string(file).with_context(|| {
45 format!(
46 "Cannot read third party licenses from file {}",
47 file.to_str().unwrap_or("empty")
48 )
49 })?;
50 serde_json::from_str::<Self>(str.as_str()).with_context(|| {
51 format!(
52 "Cannot parse third party licenses from file {}",
53 file.to_str().unwrap_or("empty")
54 )
55 })
56 }
57
58 pub fn save(&self, file_path: &Path) -> Result<()> {
59 let parent_dir = file_path.parent().unwrap_or_else(|| {
61 panic!(
62 "Cannot get parent directory of third party file {}",
63 file_path.to_string_lossy().into_owned()
64 )
65 });
66 std::fs::create_dir_all(parent_dir)?;
67 let str = serde_json::to_string_pretty(self).with_context(|| "Cannot serialize third party licenses")?;
69 std::fs::write(file_path, str).with_context(|| {
70 format!(
71 "Cannot serialize third party licenses to file {}",
72 file_path.to_str().unwrap_or("empty")
73 )
74 })
75 }
76
77 pub fn apply_overrides(&mut self, overrides: &[settings::Override]) -> Result<()> {
78 for package in &mut self.third_party_libraries {
79 if let Some(license_override) = settings::Override::find_override(&package.package_name, overrides) {
80 if let Some(license_id) = &license_override.license_id {
81 package.license = license_id.clone();
82
83 if license_override.overwrite_all_license_ids {
84 for package_license in &mut package.licenses {
85 package_license.license = license_id.clone();
86 }
87 }
88 }
89 }
90 }
91 Ok(())
92 }
93
94 pub fn export(&self, result_dir: &Path) -> Result<()> {
95 let base_path = result_dir.join(self.root_name.clone());
96 for package in &self.third_party_libraries {
97 let pkg_dir = base_path.join(package.package_name.clone());
98
99 std::fs::create_dir_all(pkg_dir.as_path())?;
100
101 let pkg_desc_file = pkg_dir.join("README.txt");
102 let pkg_desc = format!(
103 "Package: {}\nVersion: {}\nLicense: {}\n",
104 package.package_name, package.package_version, package.license
105 );
106 std::fs::write(pkg_desc_file.as_path(), pkg_desc).with_context(|| {
107 format!(
108 "Cannot write package description to file {}",
109 pkg_desc_file.to_string_lossy()
110 )
111 })?;
112
113 for license_text in &package.licenses {
114 let file_name = license_text.license.replace(std::path::is_separator, "-");
116 let file_name = file_name.replace('$', "-");
117 let license_text_file = pkg_dir.join(format!("{file_name}.txt"));
118
119 std::fs::write(license_text_file.as_path(), license_text.text.clone()).with_context(|| {
120 format!(
121 "Cannot write license text to file {}",
122 license_text_file.to_string_lossy()
123 )
124 })?;
125 }
126 }
127 Ok(())
128 }
129
130 pub fn new(root_name: &str, license_infos: &[LicenseInfo]) -> Self {
131 let mut third_party_libraries = vec![];
132
133 for info in license_infos {
134 let mut licenses = vec![];
135
136 for license_text in &info.license_texts {
137 licenses.push(License {
138 license: license_text.id.clone(),
139 text: license_text.text.clone(),
140 });
141 }
142
143 third_party_libraries.push(ThirdPartyLibrary {
144 package_name: info.package_name.clone(),
145 package_version: info.version.clone().unwrap_or_default(),
146 license: info.license.clone(),
147 licenses,
148 });
149 }
150
151 ThirdPartyLicenses {
152 root_name: root_name.to_owned(),
153 third_party_libraries,
154 }
155 }
156
157 pub fn print(&self) {
158 let mut root_tree = termtree::Tree::new(self.root_name.clone());
159
160 for lib in &self.third_party_libraries {
161 let mut pkg_tree = termtree::Tree::new(format!("Package: {}", lib.package_name.clone()));
162
163 pkg_tree.push(termtree::Tree::new(format!("Version: {}", lib.package_version)));
164 pkg_tree.push(termtree::Tree::new(format!("License ID: {}", lib.license)));
165
166 let mut license_tree = termtree::Tree::new("Licenses:".to_owned());
167 for license in &lib.licenses {
168 license_tree.push(termtree::Tree::new(format!("ID: {}", license.license)));
169 }
170 pkg_tree.push(license_tree);
171
172 root_tree.push(pkg_tree);
173 }
174
175 for line in root_tree.to_string().lines() {
176 debug!("{line}")
177 }
178 }
179}