|
1 |
| -use std::{path::PathBuf, process::Command}; |
2 |
| - |
| 1 | +use std::fs::File; |
| 2 | +use std::io::{BufReader, BufWriter, Write}; |
| 3 | +use std::{ |
| 4 | + fs, |
| 5 | + os::unix::fs::symlink, |
| 6 | + path::{Component, PathBuf}, |
| 7 | + process::Command, |
| 8 | +}; |
| 9 | + |
| 10 | +use itertools::Itertools; |
3 | 11 | use moss::{dependency, Dependency, Provider};
|
4 | 12 |
|
5 | 13 | use crate::package::collect::PathInfo;
|
@@ -134,3 +142,69 @@ pub fn cmake(bucket: &mut BucketMut, info: &mut PathInfo) -> Result<Response, Bo
|
134 | 142 |
|
135 | 143 | Ok(Decision::NextHandler.into())
|
136 | 144 | }
|
| 145 | + |
| 146 | +pub fn compressman(bucket: &mut BucketMut, info: &mut PathInfo) -> Result<Response, BoxError> { |
| 147 | + if !bucket.recipe.parsed.options.compressman { |
| 148 | + return Ok(Decision::NextHandler.into()); |
| 149 | + } |
| 150 | + |
| 151 | + let is_man_file = info.path.components().contains(&Component::Normal("man".as_ref())) |
| 152 | + && info.file_name().ends_with(|c| ('1'..'9').contains(&c)); |
| 153 | + let is_info_file = |
| 154 | + info.path.components().contains(&Component::Normal("info".as_ref())) && info.file_name().ends_with(".info"); |
| 155 | + |
| 156 | + if !(is_man_file || is_info_file) { |
| 157 | + return Ok(Decision::NextHandler.into()); |
| 158 | + } |
| 159 | + |
| 160 | + let mut generated_path = PathBuf::new(); |
| 161 | + |
| 162 | + /* If we have a man/info symlink update the link to the compressed file */ |
| 163 | + if info.path.is_symlink() { |
| 164 | + let new_original = format!("{}.zst", fs::canonicalize(&info.path)?.display()); |
| 165 | + let new_link = format!("{}.zst", &info.path.display()); |
| 166 | + |
| 167 | + /* |
| 168 | + * Depending on the order the files get analysed the new compressed file may not yet exist, |
| 169 | + * compress it _now_ so the correct metadata src info is returned to the binary writer. |
| 170 | + */ |
| 171 | + if !std::path::Path::new(&new_original).exists() { |
| 172 | + let compressed_file = compress_file_zstd(PathBuf::from(fs::canonicalize(&info.path)?))?; |
| 173 | + let _ = bucket.paths.install().guest.join(compressed_file); |
| 174 | + } |
| 175 | + |
| 176 | + symlink(format!("{}.zst", fs::read_link(&info.path)?.display()), &new_link)?; |
| 177 | + generated_path.push(bucket.paths.install().guest.join(new_link)); |
| 178 | + return Ok(Decision::ReplaceFile { |
| 179 | + newpath: generated_path, |
| 180 | + } |
| 181 | + .into()); |
| 182 | + } |
| 183 | + |
| 184 | + let mut compressed_file = PathBuf::from(format!("{}.zst", info.path.display())); |
| 185 | + |
| 186 | + /* We may have already compressed the file if we encountered a symlink to this file first */ |
| 187 | + if !&compressed_file.exists() { |
| 188 | + compressed_file = compress_file_zstd(info.path.clone())?; |
| 189 | + } |
| 190 | + |
| 191 | + generated_path.push(bucket.paths.install().guest.join(compressed_file)); |
| 192 | + |
| 193 | + pub fn compress_file_zstd(path: PathBuf) -> Result<PathBuf, BoxError> { |
| 194 | + let output_path = PathBuf::from(format!("{}.zst", path.display())); |
| 195 | + let input = File::create(&output_path)?; |
| 196 | + let mut reader = BufReader::new(File::open(&path)?); |
| 197 | + let mut writer = BufWriter::new(input); |
| 198 | + |
| 199 | + zstd::stream::copy_encode(&mut reader, &mut writer, 16)?; |
| 200 | + |
| 201 | + writer.flush()?; |
| 202 | + |
| 203 | + Ok(output_path) |
| 204 | + } |
| 205 | + |
| 206 | + Ok(Decision::ReplaceFile { |
| 207 | + newpath: generated_path, |
| 208 | + } |
| 209 | + .into()) |
| 210 | +} |
0 commit comments