From 7701b6d6b0bbcc917664d46d96dfd3e4ad0e110c Mon Sep 17 00:00:00 2001 From: cyr Date: Thu, 4 Jan 2024 19:14:59 +0100 Subject: [PATCH] 0.4, support for deb-src, some refactoring and bugfixes --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/config.rs | 8 +- src/error.rs | 10 +- src/metadata.rs | 96 +++++++++++- src/metadata/checksum.rs | 49 ++++++- src/metadata/{package.rs => packages_file.rs} | 80 +++------- src/metadata/release.rs | 73 ++++++---- src/metadata/sources_file.rs | 137 ++++++++++++++++++ src/mirror.rs | 91 ++++++------ src/mirror/repository.rs | 10 +- 11 files changed, 411 insertions(+), 147 deletions(-) rename src/metadata/{package.rs => packages_file.rs} (61%) create mode 100644 src/metadata/sources_file.rs diff --git a/Cargo.lock b/Cargo.lock index 8fb547f..ab76cdf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "aptmirs" -version = "0.3.3" +version = "0.4.0" dependencies = [ "async-channel", "bzip2", diff --git a/Cargo.toml b/Cargo.toml index 8d55e8e..63953e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "aptmirs" description = "A simple tool for mirroring apt/deb repositories" -version = "0.3.3" +version = "0.4.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/src/config.rs b/src/config.rs index 7a52170..798110d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -75,6 +75,7 @@ pub struct MirrorOpts { pub suite: String, pub components: Vec, pub arch: Vec, + pub source: bool, } @@ -124,8 +125,10 @@ impl MirrorOpts { pub fn try_from(mut line: &str) -> Result { let mut arch = Vec::new(); + let mut source = false; + line = if let Some(line) = line.strip_prefix("deb-src") { - arch.push("source".to_string()); + source = true; line } else if let Some(line) = line.strip_prefix("deb") { line @@ -187,7 +190,8 @@ impl MirrorOpts { url: url.to_owned(), suite: suite.to_owned(), components, - arch + arch, + source }) } } \ No newline at end of file diff --git a/src/error.rs b/src/error.rs index fa0ee44..d52db4a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -36,8 +36,11 @@ pub enum MirsError { #[error("url does not point to a valid repository, no release file found")] NoReleaseFile, - #[error("unable to parse package file {path}")] - ParsingPackage { path: PathBuf }, + #[error("unable to parse packages file {path}")] + ParsingPackages { path: PathBuf }, + + #[error("unable to parse sources file {path}")] + ParsingSources { path: PathBuf }, #[error("unable to parse url {url}")] UrlParsing { url: String }, @@ -51,6 +54,9 @@ pub enum MirsError { #[error(transparent)] Hex(#[from]FromHexError), + #[error("{value} is not a recognized checksum")] + IntoChecksum { value: String }, + #[error("checksum failed for: {url}, expected hash: {expected}, calculated hash: {hash}")] Checksum { url: String, expected: String, hash: String }, diff --git a/src/metadata.rs b/src/metadata.rs index 72296d0..caf8cee 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -1,3 +1,95 @@ +use std::{io::{Read, BufRead, BufReader}, sync::{Arc, atomic::{AtomicU64, Ordering}}, path::{Path, PathBuf}}; + +use crate::error::{Result, MirsError}; + +use self::{checksum::Checksum, packages_file::PackagesFile, sources_file::SourcesFile}; + pub mod release; -pub mod package; -pub mod checksum; \ No newline at end of file +pub mod packages_file; +pub mod sources_file; +pub mod checksum; + +pub enum IndexSource { + Packages(PathBuf), + Sources(PathBuf) +} + +impl IndexSource { + pub fn into_reader(self) -> Result> { + match self { + IndexSource::Packages(path) => PackagesFile::build(&path), + IndexSource::Sources(path) => SourcesFile::build(&path), + } + } +} + +impl From for IndexSource { + fn from(value: PathBuf) -> Self { + match value.file_name().expect("indices should have names") + .to_str().expect("the file name of indices should be valid utf8") { + v if v.starts_with("Packages") => IndexSource::Packages(value), + v if v.starts_with("Sources") => IndexSource::Sources(value), + _ => unreachable!("implementation error; non-index file as IndexSource") + } + } +} + +pub trait IndexFileEntryIterator : Iterator> { + fn size(&self) -> u64; + fn counter(&self) -> Arc; +} + +pub struct IndexFileEntry { + pub path: String, + pub size: u64, + pub checksum: Option +} +pub struct TrackingReader { + inner: R, + read: Arc +} + +impl Read for TrackingReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let result = self.inner.read(buf); + + if let Ok(read) = result { + self.read.fetch_add(read as u64, Ordering::SeqCst); + } + + result + } +} + +pub fn create_reader(file: R, path: &Path) -> Result<(Box, Arc)> { + let counter = Arc::new(AtomicU64::from(0)); + + let file_reader = TrackingReader { + inner: file, + read: counter.clone(), + }; + + let reader: Box = match path.extension() + .map(|v| + v.to_str().expect("extension must be valid ascii") + ) { + Some("xz") => { + let xz_decoder = xz2::read::XzDecoder::new_multi_decoder(file_reader); + Box::new(BufReader::with_capacity(1024*1024, xz_decoder)) + } + Some("gz") => { + let gz_decoder = flate2::read::GzDecoder::new(file_reader); + Box::new(BufReader::with_capacity(1024*1024, gz_decoder)) + }, + Some("bz2") => { + let bz2_decoder = bzip2::read::BzDecoder::new(file_reader); + Box::new(BufReader::with_capacity(1024*1024, bz2_decoder)) + }, + None => { + Box::new(BufReader::with_capacity(1024*1024, file_reader)) + }, + _ => return Err(MirsError::ParsingPackages { path: path.to_owned() }) + }; + + Ok((reader, counter)) +} \ No newline at end of file diff --git a/src/metadata/checksum.rs b/src/metadata/checksum.rs index 9d63d32..afa494b 100644 --- a/src/metadata/checksum.rs +++ b/src/metadata/checksum.rs @@ -5,7 +5,7 @@ use sha1::{Sha1, Digest, digest::{FixedOutput, Update}}; use sha2::{Sha256, Sha512}; use tokio::io::AsyncReadExt; -use crate::error::Result; +use crate::error::{Result, MirsError}; #[derive(Debug, PartialEq)] pub enum Checksum { @@ -15,6 +15,36 @@ pub enum Checksum { Sha512([u8; 64]) } +impl TryFrom<&str> for Checksum { + type Error = MirsError; + + fn try_from(value: &str) -> std::prelude::v1::Result { + match value.len() { + 32 => { + let mut bytes = [0_u8; 16]; + hex::decode_to_slice(value, &mut bytes)?; + Ok(bytes.into()) + }, + 40 => { + let mut bytes = [0_u8; 20]; + hex::decode_to_slice(value, &mut bytes)?; + Ok(bytes.into()) + }, + 64 => { + let mut bytes = [0_u8; 32]; + hex::decode_to_slice(value, &mut bytes)?; + Ok(bytes.into()) + }, + 128 => { + let mut bytes = [0_u8; 64]; + hex::decode_to_slice(value, &mut bytes)?; + Ok(bytes.into()) + } + _ => Err(MirsError::IntoChecksum { value: value.to_string() }) + } + } +} + impl From<[u8; 16]> for Checksum { fn from(value: [u8; 16]) -> Self { Self::Md5(value) @@ -77,6 +107,23 @@ impl Checksum { Ok(hasher.compute()) } + + pub fn bits(&self) -> usize { + match self { + Checksum::Md5(v) => v.len(), + Checksum::Sha1(v) => v.len(), + Checksum::Sha256(v) => v.len(), + Checksum::Sha512(v) => v.len(), + } + } + + pub fn replace_if_stronger(&mut self, other: Checksum) { + if self.bits() >= other.bits() { + return + } + + *self = other + } } impl ChecksumType { diff --git a/src/metadata/package.rs b/src/metadata/packages_file.rs similarity index 61% rename from src/metadata/package.rs rename to src/metadata/packages_file.rs index 63ae736..b794d9c 100644 --- a/src/metadata/package.rs +++ b/src/metadata/packages_file.rs @@ -1,27 +1,10 @@ -use std::{path::{Path, PathBuf}, fs::File, io::{BufReader, BufRead, Read}, sync::{atomic::{AtomicU64, Ordering}, Arc}}; +use std::{path::{Path, PathBuf}, fs::File, io::BufRead, sync::{atomic::AtomicU64, Arc}}; use crate::error::{Result, MirsError}; -use super::checksum::{Checksum, ChecksumType}; +use super::{checksum::{Checksum, ChecksumType}, create_reader, IndexFileEntry, IndexFileEntryIterator}; -pub struct TrackingReader { - inner: R, - read: Arc -} - -impl Read for TrackingReader { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { - let result = self.inner.read(buf); - - if let Ok(read) = result { - self.read.fetch_add(read as u64, Ordering::SeqCst); - } - - result - } -} - -pub struct Package { +pub struct PackagesFile { reader: Box, path: PathBuf, buf: String, @@ -29,60 +12,35 @@ pub struct Package { read: Arc } -impl Package { - pub fn build(path: &Path) -> Result { +impl PackagesFile { + pub fn build(path: &Path) -> Result> { let file = File::open(path)?; let size = file.metadata()?.len(); - let counter = Arc::new(AtomicU64::from(0)); + let (reader, counter) = create_reader(file, path)?; - let file_reader = TrackingReader { - inner: file, - read: counter.clone(), - }; - - let reader: Box = match path.extension() - .map(|v| - v.to_str().expect("extension must be valid ascii") - ) { - Some("xz") => { - let xz_decoder = xz2::read::XzDecoder::new_multi_decoder(file_reader); - Box::new(BufReader::with_capacity(1024*1024, xz_decoder)) - } - Some("gz") => { - let gz_decoder = flate2::read::GzDecoder::new(file_reader); - Box::new(BufReader::with_capacity(1024*1024, gz_decoder)) - }, - Some("bz2") => { - let bz2_decoder = bzip2::read::BzDecoder::new(file_reader); - Box::new(BufReader::with_capacity(1024*1024, bz2_decoder)) - }, - None => { - Box::new(BufReader::with_capacity(1024*1024, file_reader)) - }, - _ => return Err(MirsError::ParsingPackage { path: path.to_owned() }) - }; - - Ok(Self { + Ok(Box::new(Self { reader, path: path.to_path_buf(), buf: String::with_capacity(1024*8), size, read: counter, - }) + })) } +} - pub fn size(&self) -> u64 { +impl IndexFileEntryIterator for PackagesFile { + fn size(&self) -> u64 { self.size } - pub fn counter(&self) -> Arc { + fn counter(&self) -> Arc { self.read.clone() } } -impl Iterator for Package { - type Item = Result<(String, u64, Option)>; +impl Iterator for PackagesFile { + type Item = Result; fn next(&mut self) -> Option { loop { @@ -148,10 +106,14 @@ impl Iterator for Package { self.buf.clear(); - if let (Some(p), Some(s), h) = (path, size, hash) { - Some(Ok((p, s, h))) + if let (Some(path), Some(size), checksum) = (path, size, hash) { + Some(Ok(IndexFileEntry { + path, + size, + checksum + })) } else { None } } -} \ No newline at end of file +} diff --git a/src/metadata/release.rs b/src/metadata/release.rs index d7fc1c1..d2c22c4 100644 --- a/src/metadata/release.rs +++ b/src/metadata/release.rs @@ -149,36 +149,49 @@ pub struct ReleaseFileIterator<'a> { impl<'a> ReleaseFileIterator<'a> { pub fn new(release: Release, opts: &'a MirrorOpts) -> Self { - let mut file_prefix_filter = Vec::from([ - String::from("Release"), - String::from("Contents-all"), - String::from("Components-all"), - String::from("Commands-all"), - String::from("Packages"), - String::from("icons"), - String::from("Translation"), - String::from("Sources"), - String::from("Index"), - ]); - - let mut dir_filter = BTreeSet::from([ - String::from("dep11"), - String::from("i18n"), - String::from("binary-all"), - String::from("cnf"), - String::from("Contents-all.diff"), - String::from("Packages.diff"), - ]); - - for arch in &opts.arch { - dir_filter.insert(format!("binary-{arch}")); - dir_filter.insert(format!("Contents-{arch}.diff")); - //dir_filter.insert(format!("Translation-{lang}.diff")); ?? Translation-en.diff - - file_prefix_filter.push(format!("Components-{arch}")); - file_prefix_filter.push(format!("Contents-{arch}")); - file_prefix_filter.push(format!("Commands-{arch}")); - } + let (file_prefix_filter, dir_filter) = if opts.source { + let file_prefix_filter = Vec::from([ + String::from("Release"), + String::from("Sources"), + ]); + + let dir_filter = BTreeSet::from([ + String::from("source"), + ]); + + (file_prefix_filter, dir_filter) + } else { + let mut file_prefix_filter = Vec::from([ + String::from("Release"), + String::from("Contents-all"), + String::from("Components-all"), + String::from("Commands-all"), + String::from("Packages"), + String::from("icons"), + String::from("Translation"), + String::from("Index"), + ]); + + let mut dir_filter = BTreeSet::from([ + String::from("dep11"), + String::from("i18n"), + String::from("binary-all"), + String::from("cnf"), + String::from("Contents-all.diff"), + String::from("Packages.diff"), + ]); + + for arch in &opts.arch { + dir_filter.insert(format!("binary-{arch}")); + dir_filter.insert(format!("Contents-{arch}.diff")); + + file_prefix_filter.push(format!("Components-{arch}")); + file_prefix_filter.push(format!("Contents-{arch}")); + file_prefix_filter.push(format!("Commands-{arch}")); + } + + (file_prefix_filter, dir_filter) + }; Self { release, diff --git a/src/metadata/sources_file.rs b/src/metadata/sources_file.rs new file mode 100644 index 0000000..fbd7457 --- /dev/null +++ b/src/metadata/sources_file.rs @@ -0,0 +1,137 @@ +use std::{path::{Path, PathBuf}, fs::File, io::BufRead, sync::{atomic::AtomicU64, Arc}, collections::BTreeMap}; + +use crate::error::{Result, MirsError}; + +use super::{checksum::Checksum, create_reader, IndexFileEntry, IndexFileEntryIterator}; + +pub struct SourceEntry { + pub size: u64, + pub checksum: Checksum +} + +pub struct SourcesFile { + reader: Box, + path: PathBuf, + buf: String, + files_buf: BTreeMap, + size: u64, + read: Arc +} + +impl SourcesFile { + pub fn build(path: &Path) -> Result> { + let file = File::open(path)?; + let size = file.metadata()?.len(); + + let (reader, counter) = create_reader(file, path)?; + + Ok(Box::new(Self { + reader, + path: path.to_path_buf(), + buf: String::with_capacity(1024*8), + files_buf: BTreeMap::new(), + size, + read: counter, + })) + } +} + +impl IndexFileEntryIterator for SourcesFile { + fn size(&self) -> u64 { + self.size + } + + fn counter(&self) -> Arc { + self.read.clone() + } +} + +impl Iterator for SourcesFile { + type Item = Result; + + fn next(&mut self) -> Option { + if self.files_buf.is_empty() { + loop { + match self.reader.read_line(&mut self.buf) { + Ok(0) => return None, + Ok(1) => break, + Ok(_) => (), + Err(e) => return Some(Err( + MirsError::ReadingPackage { + path: self.path.to_string_lossy().to_string(), + inner: Box::new(e.into()) + } + )) + } + } + + let mut dir = None; + + let mut line_iter = self.buf.lines().peekable(); + + while let Some(line) = line_iter.next() { + if let Some(d) = line.strip_prefix("Directory: ") { + dir = Some(d) + } else if matches!(line, "Files:" | "Checksums-Sha1:" | "Checksums-Sha256:" | "Checksums-Sha512:") { + while let Some(line) = line_iter.next() { + let mut parts = line.split_whitespace(); + + let Some(checksum_part) = parts.next() else { + return Some(Err(MirsError::ParsingSources { path: self.path.clone() })) + }; + + let checksum = match Checksum::try_from(checksum_part) { + Ok(v) => v, + Err(e) => return Some(Err(e)) + }; + + let Some(size_part) = parts.next() else { + return Some(Err(MirsError::ParsingSources { path: self.path.clone() })) + }; + + let size: u64 = match size_part.parse() { + Ok(v) => v, + Err(e) => return Some(Err(e.into())), + }; + + let Some(file_name) = parts.next() else { + return Some(Err(MirsError::ParsingSources { path: self.path.clone() })) + }; + + let rel_path = if let Some(dir) = dir { + format!("{dir}/{file_name}") + } else { + return Some(Err(MirsError::ParsingSources { path: self.path.clone() })) + }; + + if let Some(entry) = self.files_buf.get_mut(&rel_path) { + entry.checksum.replace_if_stronger(checksum) + } else { + self.files_buf.insert(rel_path, SourceEntry { + size, + checksum + }); + } + + if line_iter.peek().is_some_and(|v| !v.starts_with(' ')) { + _ = line_iter.next(); + break + } + } + } + } + + self.buf.clear(); + } + + if let Some((path, entry)) = self.files_buf.pop_first() { + return Some(Ok(IndexFileEntry { + path, + size: entry.size, + checksum: Some(entry.checksum) + })) + } + + None + } +} \ No newline at end of file diff --git a/src/mirror.rs b/src/mirror.rs index 4c453a6..c7097f3 100644 --- a/src/mirror.rs +++ b/src/mirror.rs @@ -9,8 +9,9 @@ use indicatif::{MultiProgress, HumanBytes}; use crate::config::MirrorOpts; use crate::error::{Result, MirsError}; +use crate::metadata::IndexSource; use crate::metadata::checksum::Checksum; -use crate::metadata::{package::Package, release::Release}; +use crate::metadata::release::Release; use self::{progress::Progress, repository::Repository, downloader::{Downloader, Download}}; pub mod downloader; @@ -18,7 +19,7 @@ pub mod progress; pub mod repository; pub enum MirrorResult { - NewRelease { total_download_size: u64, num_packages_downloaded: u64, packages_size: u64 }, + NewRelease { total_download_size: u64, num_packages_downloaded: u64 }, ReleaseUnchanged, IrrelevantChanges } @@ -26,12 +27,11 @@ pub enum MirrorResult { impl Display for MirrorResult { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - MirrorResult::NewRelease { total_download_size, num_packages_downloaded, packages_size } => + MirrorResult::NewRelease { total_download_size, num_packages_downloaded } => f.write_fmt(format_args!( - "{} downloaded, {} packages ({})", + "{} downloaded, {} packages/source files", HumanBytes(*total_download_size), - num_packages_downloaded, - HumanBytes(*packages_size), + num_packages_downloaded )), MirrorResult::ReleaseUnchanged => f.write_str("release unchanged"), @@ -78,11 +78,11 @@ pub async fn mirror(opts: &MirrorOpts, output_dir: &Path) -> Result indices, - Ok(None) => { + Ok(indices) if indices.is_empty() => { repo.finalize().await?; return Ok(MirrorResult::IrrelevantChanges) } + Ok(indices) => indices, Err(e) => { _ = repo.delete_tmp(); return Err(MirsError::DownloadIndices { inner: Box::new(e) }) @@ -110,53 +110,49 @@ pub async fn mirror(opts: &MirrorOpts, output_dir: &Path) -> Result Result>> { +async fn download_indices(release: Release, opts: &MirrorOpts, progress: &mut Progress, repo: &Repository, downloader: &mut Downloader) -> Result> { let mut indices = Vec::new(); let by_hash = release.acquire_by_hash(); for (path, file_entry) in release.into_filtered_files(opts) { let url = repo.to_url_in_dist(&path); - let file_path = repo.to_path_in_tmp(&url); + let file_path_in_tmp = repo.to_path_in_tmp(&url); + + let file_path_in_root = repo.to_path_in_root(&url); // since all files have their checksums verified on download, any file that is local can - // presumably be trusted to be correct. and since we only move in the package files on - // a successful mirror operation, if we see the package file and its hash file, there is - // no need to queue its packages. + // presumably be trusted to be correct. and since we only move in the metadata files on + // a successful mirror operation, if we see the metadata file and its hash file, there is + // no need to queue its content. if let Some(checksum) = file_entry.strongest_hash() { - let by_hash_base = file_path + let by_hash_base = file_path_in_root .parent() - .expect("all files needs a parent(?)") - .to_owned(); + .expect("all files need a parent(?)"); let checksum_path = by_hash_base.join(checksum.relative_path()); - if checksum_path.exists() && file_path.exists() { + if checksum_path.exists() && file_path_in_root.exists() { continue } } - if is_package(&path) { - indices.push(repo.to_path_in_tmp(&repo.to_url_in_dist(&path))); + if is_packages_file(&path) || is_sources_file(&path) { + indices.push(file_path_in_tmp.clone()); } - let download = repo.create_metadata_download(url, file_path, file_entry, by_hash)?; + let download = repo.create_metadata_download(url, file_path_in_tmp, file_entry, by_hash)?; downloader.queue(download).await?; } let mut progress_bar = progress.create_download_progress_bar().await; progress.wait_for_completion(&mut progress_bar).await; - if !indices.is_empty() { - Ok(Some(indices)) - } else { - Ok(None) - } + Ok(indices) } pub async fn download_from_indices(repo: &Repository, downloader: &mut Downloader, indices: Vec) -> Result<()> { @@ -170,40 +166,40 @@ pub async fn download_from_indices(repo: &Repository, downloader: &mut Downloade let mut existing_indices = BTreeMap::::new(); - for package_file in indices.into_iter().filter(|f| f.exists()) { - let file_stem = package_file.file_stem().unwrap(); - let path_with_stem = package_file.parent().unwrap().join(file_stem); + for index_file_path in indices.into_iter().filter(|f| f.exists()) { + let file_stem = index_file_path.file_stem().unwrap(); + let path_with_stem = index_file_path.parent().unwrap().join(file_stem); if let Some(val) = existing_indices.get_mut(&path_with_stem) { - if is_extension_preferred(val.extension(), package_file.extension()) { - *val = package_file + if is_extension_preferred(val.extension(), index_file_path.extension()) { + *val = index_file_path } } else { - existing_indices.insert(path_with_stem, package_file); + existing_indices.insert(path_with_stem, index_file_path); } } file_progress.files.inc_total(existing_indices.len() as u64); - let packages = existing_indices - .values() - .map(|v| Package::build(v)) + let packages_files = existing_indices.into_values() + .map(IndexSource::from) + .map(|v| v.into_reader()) .collect::>>()?; - let total_size = packages.iter().map(|v| v.size()).sum(); + let total_size = packages_files.iter().map(|v| v.size()).sum(); let mut incremental_size_base = 0; file_progress.bytes.inc_total(total_size); - for package in packages { - let counter = package.counter(); + for packages_file in packages_files { + let counter = packages_file.counter(); file_progress.update_for_bytes(&mut file_progress_bar); - let package_size = package.size(); + let package_size = packages_file.size(); - for maybe_entry in package { - let (file_path, file_size, file_checksum) = maybe_entry?; + for package in packages_file { + let package = package?; - let dl = repo.create_file_download(&file_path, file_size, file_checksum); + let dl = repo.create_file_download(package); downloader.queue(dl).await?; file_progress.bytes.set_success(counter.load(Ordering::SeqCst) + incremental_size_base); @@ -303,13 +299,20 @@ fn is_extension_preferred(old: Option<&OsStr>, new: Option<&OsStr>) -> bool { ) } -fn is_package(path: &str) -> bool { +fn is_packages_file(path: &str) -> bool { path.ends_with("Packages") || path.ends_with("Packages.gz") || path.ends_with("Packages.xz") || path.ends_with("Packages.bz2") } +fn is_sources_file(path: &str) -> bool { + path.ends_with("Sources") || + path.ends_with("Sources.gz") || + path.ends_with("Sources.xz") || + path.ends_with("Sources.bz2") +} + fn get_release_file(files: &Vec) -> Option<&PathBuf> { for file in files { let file_name = file.file_name() diff --git a/src/mirror/repository.rs b/src/mirror/repository.rs index 34539a0..2d45388 100644 --- a/src/mirror/repository.rs +++ b/src/mirror/repository.rs @@ -4,7 +4,7 @@ use reqwest::Url; use super::downloader::Download; -use crate::{error::{Result, MirsError}, metadata::{release::FileEntry, checksum::Checksum}}; +use crate::{error::{Result, MirsError}, metadata::{release::FileEntry, IndexFileEntry}}; pub struct Repository { root_url: String, @@ -101,14 +101,14 @@ impl Repository { .ok() } - pub fn create_file_download(&self, path: &str, size: u64, checksum: Option) -> Box { - let url = self.to_url_in_root(path); + pub fn create_file_download(&self, package: IndexFileEntry) -> Box { + let url = self.to_url_in_root(&package.path); let primary_target_path = self.to_path_in_root(&url); Box::new(Download { url, - size: Some(size), - checksum, + size: Some(package.size), + checksum: package.checksum, primary_target_path, symlink_paths: Vec::new(), always_download: false,