|
1 |
| -use std::{borrow::Cow, collections::HashMap, path::Path}; |
| 1 | +use std::{borrow::Cow, cmp::Ordering, collections::HashMap, path::Path}; |
2 | 2 |
|
3 | 3 | use ahash::AHashMap;
|
4 | 4 | use aho_corasick::AhoCorasick;
|
5 | 5 | #[cfg(feature = "apt")]
|
6 | 6 | use oma_apt::config::{Config, ConfigTree};
|
7 | 7 | use oma_fetch::CompressFile;
|
| 8 | +use once_cell::sync::OnceCell; |
8 | 9 | use tracing::debug;
|
9 | 10 |
|
10 | 11 | use crate::{db::RefreshError, inrelease::ChecksumItem};
|
11 | 12 |
|
| 13 | +static COMPRESSION_ORDER: OnceCell<Vec<CompressFileWrapper>> = OnceCell::new(); |
| 14 | + |
| 15 | +#[derive(Debug, Eq, PartialEq)] |
| 16 | +struct CompressFileWrapper { |
| 17 | + compress_file: CompressFile, |
| 18 | +} |
| 19 | + |
| 20 | +impl From<&str> for CompressFileWrapper { |
| 21 | + fn from(value: &str) -> Self { |
| 22 | + match value { |
| 23 | + "xz" => CompressFileWrapper { |
| 24 | + compress_file: CompressFile::Xz, |
| 25 | + }, |
| 26 | + "bz2" => CompressFileWrapper { |
| 27 | + compress_file: CompressFile::Bz2, |
| 28 | + }, |
| 29 | + "lzma" => CompressFileWrapper { |
| 30 | + compress_file: CompressFile::Lzma, |
| 31 | + }, |
| 32 | + "gz" => CompressFileWrapper { |
| 33 | + compress_file: CompressFile::Gzip, |
| 34 | + }, |
| 35 | + "lz4" => CompressFileWrapper { |
| 36 | + compress_file: CompressFile::Lz4, |
| 37 | + }, |
| 38 | + "zst" => CompressFileWrapper { |
| 39 | + compress_file: CompressFile::Zstd, |
| 40 | + }, |
| 41 | + x => { |
| 42 | + if !x.is_ascii() { |
| 43 | + debug!("{x} format is not compress format"); |
| 44 | + } |
| 45 | + |
| 46 | + CompressFileWrapper { |
| 47 | + compress_file: CompressFile::Nothing, |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +impl PartialOrd for CompressFileWrapper { |
| 55 | + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
| 56 | + Some(self.cmp(other)) |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +#[cfg(feature = "apt")] |
| 61 | +impl Ord for CompressFileWrapper { |
| 62 | + fn cmp(&self, other: &Self) -> Ordering { |
| 63 | + let config = Config::new(); |
| 64 | + let t = COMPRESSION_ORDER.get_or_init(|| { |
| 65 | + config |
| 66 | + .get_compression_types() |
| 67 | + .iter() |
| 68 | + .map(|t| CompressFileWrapper::from(t.as_str())) |
| 69 | + .collect::<Vec<_>>() |
| 70 | + }); |
| 71 | + |
| 72 | + let self_pos = t.iter().position(|x| x == self).unwrap(); |
| 73 | + let other_pos = t.iter().position(|x| x == other).unwrap(); |
| 74 | + |
| 75 | + other_pos.cmp(&self_pos) |
| 76 | + } |
| 77 | +} |
| 78 | + |
| 79 | +#[cfg(not(feature = "apt"))] |
| 80 | +impl Ord for CompressFileWrapper { |
| 81 | + fn cmp(&self, other: &Self) -> Ordering { |
| 82 | + let t = COMPRESSION_ORDER.get_or_init(|| { |
| 83 | + vec!["zst", "xz", "bz2", "lzma", "gz", "lz4", "uncompressed"] |
| 84 | + .into_iter() |
| 85 | + .map(CompressFileWrapper::from) |
| 86 | + .collect::<Vec<_>>() |
| 87 | + }); |
| 88 | + |
| 89 | + let self_pos = t.iter().position(|x| x == self).unwrap(); |
| 90 | + let other_pos = t.iter().position(|x| x == other).unwrap(); |
| 91 | + |
| 92 | + other_pos.cmp(&self_pos) |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +impl From<CompressFile> for CompressFileWrapper { |
| 97 | + fn from(value: CompressFile) -> Self { |
| 98 | + Self { |
| 99 | + compress_file: value, |
| 100 | + } |
| 101 | + } |
| 102 | +} |
| 103 | + |
12 | 104 | #[cfg(feature = "apt")]
|
13 | 105 | fn modify_result(
|
14 | 106 | tree: ConfigTree,
|
@@ -232,7 +324,7 @@ fn flat_repo_template_match(
|
232 | 324 | }
|
233 | 325 |
|
234 | 326 | fn uncompress_file_name(target: &str) -> Cow<'_, str> {
|
235 |
| - if compress_file(target) == CompressFile::Nothing { |
| 327 | + if compress_file(target) == CompressFile::Nothing.into() { |
236 | 328 | Cow::Borrowed(target)
|
237 | 329 | } else {
|
238 | 330 | let compress_target_without_ext = Path::new(target).with_extension("");
|
@@ -287,15 +379,53 @@ fn get_matches_language(locales: impl IntoIterator<Item = String>) -> Vec<String
|
287 | 379 | langs
|
288 | 380 | }
|
289 | 381 |
|
290 |
| -fn compress_file(name: &str) -> CompressFile { |
291 |
| - CompressFile::from( |
292 |
| - Path::new(name) |
293 |
| - .extension() |
294 |
| - .map(|x| x.to_string_lossy()) |
295 |
| - .unwrap_or_default() |
296 |
| - .to_string() |
297 |
| - .as_str(), |
298 |
| - ) |
| 382 | +fn compress_file(name: &str) -> CompressFileWrapper { |
| 383 | + CompressFileWrapper { |
| 384 | + compress_file: CompressFile::from( |
| 385 | + Path::new(name) |
| 386 | + .extension() |
| 387 | + .map(|x| x.to_string_lossy()) |
| 388 | + .unwrap_or_default() |
| 389 | + .to_string() |
| 390 | + .as_str(), |
| 391 | + ), |
| 392 | + } |
| 393 | +} |
| 394 | + |
| 395 | +#[cfg(feature = "apt")] |
| 396 | +#[test] |
| 397 | +fn test_compression_order() { |
| 398 | + let config = Config::new(); |
| 399 | + |
| 400 | + config.set_vector( |
| 401 | + "Acquire::CompressionTypes::Order", |
| 402 | + &vec!["zst", "xz", "bz2", "lzma", "gz", "lz4"], |
| 403 | + ); |
| 404 | + |
| 405 | + let mut types = config |
| 406 | + .get_compression_types() |
| 407 | + .iter() |
| 408 | + .map(|t| CompressFileWrapper::from(t.as_str())) |
| 409 | + .collect::<Vec<_>>(); |
| 410 | + |
| 411 | + types.sort_unstable(); |
| 412 | + types.reverse(); |
| 413 | + |
| 414 | + assert_eq!( |
| 415 | + types, |
| 416 | + vec![ |
| 417 | + CompressFile::Zstd, |
| 418 | + CompressFile::Xz, |
| 419 | + CompressFile::Bz2, |
| 420 | + CompressFile::Lzma, |
| 421 | + CompressFile::Gzip, |
| 422 | + CompressFile::Lz4, |
| 423 | + CompressFile::Nothing |
| 424 | + ] |
| 425 | + .into_iter() |
| 426 | + .map(|x| x.into()) |
| 427 | + .collect::<Vec<CompressFileWrapper>>() |
| 428 | + ); |
299 | 429 | }
|
300 | 430 |
|
301 | 431 | #[test]
|
|
0 commit comments