summaryrefslogtreecommitdiff
path: root/src/net/i2p_package.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/i2p_package.rs')
-rw-r--r--src/net/i2p_package.rs110
1 files changed, 66 insertions, 44 deletions
diff --git a/src/net/i2p_package.rs b/src/net/i2p_package.rs
index 335dbea..751d561 100644
--- a/src/net/i2p_package.rs
+++ b/src/net/i2p_package.rs
@@ -10,9 +10,9 @@ use emissary_core::runtime::{
};
*/
+use indicatif::{ProgressBar, ProgressStyle};
use std::{collections::HashMap, path::Path};
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader};
-use indicatif::{ProgressBar, ProgressStyle};
use url;
use yosemite::Session;
@@ -20,12 +20,12 @@ use yosemite::SessionOptions;
pub struct I2PPackage {
config: Config,
- index_packages: Option<HashMap<String, Package>>,
+ index_packages: Option<HashMap<String, Package>>,
}
#[derive(Deserialize, Debug)]
struct IndexData {
- packages: Vec<Package>,
+ packages: Vec<Package>,
}
impl I2PPackage {
@@ -34,10 +34,10 @@ impl I2PPackage {
/// # Returns
///
/// A new I2P object with the given configuration. The session is initially set to None and the connected status is set to false.
- pub fn new(config: Config) -> Self {
- I2PPackage {
- config: config,
- index_packages: None
+ pub fn new(cfg: Config) -> Self {
+ I2PPackage {
+ config: cfg,
+ index_packages: None,
}
}
@@ -47,7 +47,7 @@ impl I2PPackage {
/// # Errors
///
/// Returns an error if the request fails, if the response status is not successful, or if there's an issue while reading or writing the file.
- pub async fn fetch_index(&mut self) -> Result<bool, Box<dyn std::error::Error>> {
+ pub async fn fetch_index(&mut self) -> Result<bool, Box<dyn std::error::Error>> {
let repo_url_str = &self.config.repo.repo_url;
let cache_dir = &self.config.paths.cache_dir;
@@ -85,7 +85,8 @@ impl I2PPackage {
return Err(format!(
"HTTP Error: {}",
headers_str.lines().next().unwrap_or("Unknown")
- ).into());
+ )
+ .into());
}
let content_length = headers_str
@@ -93,12 +94,11 @@ impl I2PPackage {
.find(|line| line.to_lowercase().starts_with("content-length:"))
.and_then(|line| line.split_at(15).1.trim().parse::<u64>().ok())
.unwrap_or(0);
-
+
let body_start = headers_end + 4;
let mut body_reader = std::io::Cursor::new(&response_buffer[body_start..]);
let file_path = Path::new(cache_dir).join("INDEX.tar.gz");
-
let pb = if content_length > 0 {
let pb = ProgressBar::new(content_length);
pb.set_style(ProgressStyle::default_bar()
@@ -107,8 +107,9 @@ impl I2PPackage {
pb
} else {
let pb = ProgressBar::new_spinner();
- pb.set_style(ProgressStyle::default_spinner()
- .template("{spinner:.green} [{elapsed_precise}] Fetching INDEX.tar.gz...")?
+ pb.set_style(
+ ProgressStyle::default_spinner()
+ .template("{spinner:.green} [{elapsed_precise}] Fetching INDEX.tar.gz...")?,
);
pb
};
@@ -119,11 +120,10 @@ impl I2PPackage {
let mut buffer = vec![0; chunk_size as usize];
loop {
-
let bytes_read_result = std::io::Read::read(&mut body_reader, &mut buffer);
let bytes_read = match bytes_read_result {
- Ok(n) => n,
- Err(e) => return Err(e.into()),
+ Ok(n) => n,
+ Err(e) => return Err(e.into()),
};
if bytes_read == 0 {
@@ -141,13 +141,13 @@ impl I2PPackage {
pb.finish_with_message("INDEX.tar.gz download finished");
log::info!("Extracting INDEX.tar.gz to cache directory...");
- Package::extract_archive(&file_path.to_string_lossy())?;
+ Package::extract_archive(&file_path.to_string_lossy())?;
- let index_toml_path = Path::new(cache_dir).join("INDEX.toml");
+ let index_toml_path = Path::new(cache_dir).join("INDEX.toml");
if !index_toml_path.exists() {
- log::warn!("INDEX.toml not found in INDEX.tar.gz. Proceeding without index data.");
- self.index_packages = Some(HashMap::new());
- return Ok(true);
+ log::warn!("INDEX.toml not found in INDEX.tar.gz. Proceeding without index data.");
+ self.index_packages = Some(HashMap::new());
+ return Ok(true);
}
let index_content = std::fs::read_to_string(&index_toml_path)?;
@@ -155,23 +155,25 @@ impl I2PPackage {
let mut package_map = HashMap::new();
for pkg in index_data.packages {
- // PKG_URL = /repo/package.mesk
- // FULL URL = "http://mesk.anthrill.i2p/i2p/repo/pkg.mesk"
- let base_url = url::Url::parse(&self.config.repo.repo_url)?;
- let full_url = base_url.join(&pkg.url)?;
- let mut pkg_clone = pkg.clone();
- pkg_clone.url = full_url.to_string();
-
- package_map.insert(pkg_clone.name.clone(), pkg_clone);
+ // PKG_URL = /repo/package.mesk
+ // FULL URL = "http://mesk.anthrill.i2p/i2p/repo/pkg.mesk"
+ let base_url = url::Url::parse(&self.config.repo.repo_url)?;
+ let full_url = base_url.join(&pkg.url)?;
+ let mut pkg_clone = pkg.clone();
+ pkg_clone.url = full_url.to_string();
+
+ package_map.insert(pkg_clone.name.clone(), pkg_clone);
}
self.index_packages = Some(package_map.clone());
- log::info!("Index loaded successfully, {} packages found.", package_map.len());
+ log::info!(
+ "Index loaded successfully, {} packages found.",
+ package_map.len()
+ );
Ok(true)
}
-
/// An internal auxiliary function for downloading data and writing it to a file with a progress display.
///
/// # Arguments
@@ -198,9 +200,10 @@ impl I2PPackage {
pb
} else {
let pb = ProgressBar::new_spinner();
- pb.set_style(ProgressStyle::default_spinner()
- .template(&format!("{{spinner:.green}} [{{elapsed_precise}}] {}...", description))?
- );
+ pb.set_style(ProgressStyle::default_spinner().template(&format!(
+ "{{spinner:.green}} [{{elapsed_precise}}] {}...",
+ description
+ ))?);
pb
};
@@ -223,10 +226,16 @@ impl I2PPackage {
/// Fetches a specific package identified by `index` (likely the package name).
/// Assumes `fetch_index` has been called and `self.index_packages` is populated.
- pub fn fetch_package_info(&self, package_name: &str) -> Result<&Package, Box<dyn std::error::Error>> {
- let packages = self.index_packages.as_ref()
+ pub fn fetch_package_info(
+ &self,
+ package_name: &str,
+ ) -> Result<&Package, Box<dyn std::error::Error>> {
+ let packages = self
+ .index_packages
+ .as_ref()
.ok_or("Index not loaded. Call fetch_index first.")?;
- let pkg_info = packages.get(package_name)
+ let pkg_info = packages
+ .get(package_name)
.ok_or(format!("Package '{}' not found in index.", package_name))?;
Ok(pkg_info)
}
@@ -239,9 +248,12 @@ impl I2PPackage {
///
/// Returns an error if the index is not loaded, the package is not found in the index,
/// the package URL is invalid, the request fails, or if there's an issue writing the file.
- /// Why didn't I just abstract the download functionality into a separate function initially?
+ /// Why didn't I just abstract the download functionality into a separate function initially?
/// Yes, I'm scared to work with fetch_index, even I don't often write such shit code.
- pub async fn fetch_package(&self, package_name: &str) -> Result<bool, Box<dyn std::error::Error>> {
+ pub async fn fetch_package(
+ &self,
+ package_name: &str,
+ ) -> Result<bool, Box<dyn std::error::Error>> {
let package_info = self.fetch_package_info(package_name)?;
let url = url::Url::parse(&package_info.url)?;
let host = url.host_str().ok_or("No host in package URL")?;
@@ -271,7 +283,8 @@ impl I2PPackage {
return Err(format!(
"HTTP Error: {}",
headers_str.lines().next().unwrap_or("Unknown")
- ).into());
+ )
+ .into());
}
let content_length = headers_str
@@ -291,10 +304,19 @@ impl I2PPackage {
let cache_dir = &self.config.paths.cache_dir;
let file_path = Path::new(cache_dir).join(file_name);
- Self::download_and_write_file_with_progress(body_bytes, &file_path, content_length, file_name).await?;
-
- log::info!("Package '{}' downloaded successfully to {:?}", package_name, file_path);
+ Self::download_and_write_file_with_progress(
+ body_bytes,
+ &file_path,
+ content_length,
+ file_name,
+ )
+ .await?;
+
+ log::info!(
+ "Package '{}' downloaded successfully to {:?}",
+ package_name,
+ file_path
+ );
Ok(true)
}
}
-