chore(format): format code

This commit is contained in:
Till Wegmueller 2026-01-25 23:17:49 +01:00
parent e7dc9d5a4c
commit 4ab529f4c7
No known key found for this signature in database
11 changed files with 210 additions and 107 deletions

View file

@ -635,7 +635,10 @@ impl Resolver {
// Helper: extract the package FMRI from a manifest's attributes
fn manifest_fmri(manifest: &Manifest) -> Option<Fmri> {
for attr in &manifest.attributes {
if attr.key == "pkg.fmri" && let Some(val) = attr.values.first() && let Ok(f) = Fmri::parse(val) {
if attr.key == "pkg.fmri"
&& let Some(val) = attr.values.first()
&& let Ok(f) = Fmri::parse(val)
{
return Some(f);
}
}

View file

@ -3,12 +3,15 @@
// MPL was not distributed with this file, You can
// obtain one at https://mozilla.org/MPL/2.0/.
use crate::repository::{ReadableRepository, FileBackend, RepositoryError, Result, WritableRepository, ProgressReporter, ProgressInfo, NoopProgressReporter};
use crate::fmri::Fmri;
use crate::actions::Manifest;
use crate::fmri::Fmri;
use crate::repository::{
FileBackend, NoopProgressReporter, ProgressInfo, ProgressReporter, ReadableRepository,
RepositoryError, Result, WritableRepository,
};
use std::collections::HashSet;
use tempfile::tempdir;
use tracing::{info, debug};
use tracing::{debug, info};
/// PackageReceiver handles downloading packages from a source repository
/// and storing them in a destination repository.
@ -21,7 +24,11 @@ pub struct PackageReceiver<'a, S: ReadableRepository> {
impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
/// Create a new PackageReceiver
pub fn new(source: &'a mut S, dest: FileBackend) -> Self {
Self { source, dest, progress: None }
Self {
source,
dest,
progress: None,
}
}
/// Set the progress reporter
@ -37,7 +44,12 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
/// * `default_publisher` - The default publisher name if not specified in FMRI
/// * `fmris` - List of FMRIs to receive
/// * `recursive` - Whether to receive dependencies recursively
pub fn receive(&mut self, default_publisher: Option<&str>, fmris: &[Fmri], recursive: bool) -> Result<()> {
pub fn receive(
&mut self,
default_publisher: Option<&str>,
fmris: &[Fmri],
recursive: bool,
) -> Result<()> {
let mut processed = HashSet::new();
let mut queue: Vec<Fmri> = fmris.to_vec();
let mut updated_publishers = HashSet::new();
@ -53,36 +65,55 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
while let Some(fmri) = queue.pop() {
// If the FMRI doesn't have a version, we need to find the newest one
let fmris_to_fetch = if fmri.version.is_none() {
let publisher = fmri.publisher.as_deref().or(default_publisher).ok_or_else(|| {
RepositoryError::Other(format!("No publisher specified for package {}", fmri.name))
})?;
let publisher =
fmri.publisher
.as_deref()
.or(default_publisher)
.ok_or_else(|| {
RepositoryError::Other(format!(
"No publisher specified for package {}",
fmri.name
))
})?;
overall_progress = overall_progress.with_context(format!("Looking up newest version for {}", fmri.name));
overall_progress = overall_progress
.with_context(format!("Looking up newest version for {}", fmri.name));
progress.update(&overall_progress);
debug!("No version specified for {}, looking up newest", fmri.name);
let pkgs = self.source.list_packages(Some(publisher), Some(&fmri.name))?;
let pkgs = self
.source
.list_packages(Some(publisher), Some(&fmri.name))?;
// Group by package name to find the newest version for each
let mut by_name: std::collections::HashMap<String, Vec<crate::repository::PackageInfo>> = std::collections::HashMap::new();
let mut by_name: std::collections::HashMap<
String,
Vec<crate::repository::PackageInfo>,
> = std::collections::HashMap::new();
for pi in pkgs {
by_name.entry(pi.fmri.name.clone()).or_default().push(pi);
}
let mut results = Vec::new();
for (name, versions) in by_name {
let newest = versions.into_iter().max_by(|a, b| {
a.fmri.to_string().cmp(&b.fmri.to_string())
});
let newest = versions
.into_iter()
.max_by(|a, b| a.fmri.to_string().cmp(&b.fmri.to_string()));
if let Some(pi) = newest {
results.push(pi.fmri);
} else {
info!("Package {} not found in source for publisher {}", name, publisher);
info!(
"Package {} not found in source for publisher {}",
name, publisher
);
}
}
if results.is_empty() {
info!("Package {} not found in source for publisher {}", fmri.name, publisher);
info!(
"Package {} not found in source for publisher {}",
fmri.name, publisher
);
continue;
}
// Update total_packages: remove the wildcard FMRI we just popped, and add actual results
@ -93,9 +124,17 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
};
for fmri_to_fetch in fmris_to_fetch {
let publisher_name = fmri_to_fetch.publisher.as_deref().or(default_publisher).ok_or_else(|| {
RepositoryError::Other(format!("No publisher specified for package {}", fmri_to_fetch.name))
})?.to_string();
let publisher_name = fmri_to_fetch
.publisher
.as_deref()
.or(default_publisher)
.ok_or_else(|| {
RepositoryError::Other(format!(
"No publisher specified for package {}",
fmri_to_fetch.name
))
})?
.to_string();
if !processed.insert(fmri_to_fetch.clone()) {
// If we already processed it (possibly as a dependency), don't count it again
@ -110,7 +149,10 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
.with_context(format!("Receiving {}", fmri_to_fetch));
progress.update(&overall_progress);
info!("Receiving package {} from publisher {}", fmri_to_fetch, publisher_name);
info!(
"Receiving package {} from publisher {}",
fmri_to_fetch, publisher_name
);
let manifest = self.receive_one(&publisher_name, &fmri_to_fetch)?;
updated_publishers.insert(publisher_name.clone());
@ -123,8 +165,8 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
}
if !processed.contains(&dep_fmri) && queued.insert(dep_fmri.clone()) {
total_packages += 1;
queue.push(dep_fmri);
total_packages += 1;
queue.push(dep_fmri);
}
}
}
@ -134,7 +176,8 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
for pub_name in updated_publishers {
info!("Rebuilding metadata for publisher {}", pub_name);
overall_progress = overall_progress.with_context(format!("Rebuilding metadata for {}", pub_name));
overall_progress =
overall_progress.with_context(format!("Rebuilding metadata for {}", pub_name));
progress.update(&overall_progress);
self.dest.rebuild(Some(&pub_name), false, false)?;
}
@ -149,7 +192,8 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
let progress = self.progress.unwrap_or(&NoopProgressReporter);
let manifest_text = self.source.fetch_manifest_text(publisher, fmri)?;
let manifest = Manifest::parse_string(manifest_text.clone()).map_err(RepositoryError::from)?;
let manifest =
Manifest::parse_string(manifest_text.clone()).map_err(RepositoryError::from)?;
// Ensure publisher exists in destination
let dest_info = self.dest.get_info()?;
@ -164,7 +208,11 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
let temp_dir = tempdir().map_err(RepositoryError::IoError)?;
let payload_files: Vec<_> = manifest.files.iter().filter(|f| f.payload.is_some()).collect();
let payload_files: Vec<_> = manifest
.files
.iter()
.filter(|f| f.payload.is_some())
.collect();
let total_files = payload_files.len() as u64;
for (i, file) in payload_files.into_iter().enumerate() {
@ -172,14 +220,21 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
let files_done = (i + 1) as u64;
let digest = &payload.primary_identifier.hash;
progress.update(&ProgressInfo::new(format!("Receiving payloads for {}", fmri.name))
.with_total(total_files)
.with_current(files_done)
.with_context(format!("Payload: {}", digest)));
progress.update(
&ProgressInfo::new(format!("Receiving payloads for {}", fmri.name))
.with_total(total_files)
.with_current(files_done)
.with_context(format!("Payload: {}", digest)),
);
let temp_file_path = temp_dir.path().join(digest);
debug!("Fetching payload {} to {}", digest, temp_file_path.display());
self.source.fetch_payload(publisher, digest, &temp_file_path)?;
debug!(
"Fetching payload {} to {}",
digest,
temp_file_path.display()
);
self.source
.fetch_payload(publisher, digest, &temp_file_path)?;
txn.add_file(file.clone(), &temp_file_path)?;
}
}
@ -194,8 +249,8 @@ impl<'a, S: ReadableRepository> PackageReceiver<'a, S> {
#[cfg(test)]
mod tests {
use super::*;
use crate::repository::{FileBackend, RepositoryVersion};
use crate::actions::Attr;
use crate::repository::{FileBackend, RepositoryVersion};
use tempfile::tempdir;
#[test]
@ -247,11 +302,14 @@ mod tests {
source_repo.add_publisher("test")?;
let _fmri = Fmri::parse("pkg://test/pkgA@1.0").unwrap();
let manifest_content = "set name=pkg.fmri value=pkg://test/pkgA@1.0\nset name=pkg.summary value=test\n";
let manifest_content =
"set name=pkg.fmri value=pkg://test/pkgA@1.0\nset name=pkg.summary value=test\n";
// Manually write the manifest in IPS format to the source repo
let manifest_path = FileBackend::construct_manifest_path(source_dir.path(), "test", "pkgA", "1.0");
std::fs::create_dir_all(manifest_path.parent().unwrap()).map_err(RepositoryError::IoError)?;
let manifest_path =
FileBackend::construct_manifest_path(source_dir.path(), "test", "pkgA", "1.0");
std::fs::create_dir_all(manifest_path.parent().unwrap())
.map_err(RepositoryError::IoError)?;
std::fs::write(&manifest_path, manifest_content).map_err(RepositoryError::IoError)?;
// Rebuild source repo to recognize the package
@ -264,8 +322,10 @@ mod tests {
receiver.receive(Some("test"), &[Fmri::new("pkgA")], false)?;
// Verify dest repo has the package and the manifest is in IPS format
let dest_manifest_path = FileBackend::construct_manifest_path(dest_dir.path(), "test", "pkgA", "1.0");
let content = std::fs::read_to_string(&dest_manifest_path).map_err(RepositoryError::IoError)?;
let dest_manifest_path =
FileBackend::construct_manifest_path(dest_dir.path(), "test", "pkgA", "1.0");
let content =
std::fs::read_to_string(&dest_manifest_path).map_err(RepositoryError::IoError)?;
assert_eq!(content, manifest_content);
assert!(!content.starts_with('{'), "Manifest should not be JSON");
@ -275,9 +335,16 @@ mod tests {
let mut filename = json_path.file_name().unwrap().to_os_string();
filename.push(".json");
json_path.set_file_name(filename);
assert!(json_path.exists(), "JSON manifest should exist at {}", json_path.display());
assert!(
json_path.exists(),
"JSON manifest should exist at {}",
json_path.display()
);
let json_content = std::fs::read_to_string(&json_path).map_err(RepositoryError::IoError)?;
assert!(json_content.starts_with('{'), "JSON manifest should be JSON");
assert!(
json_content.starts_with('{'),
"JSON manifest should be JSON"
);
Ok(())
}

View file

@ -1593,11 +1593,7 @@ impl ReadableRepository for FileBackend {
)))
}
fn fetch_manifest_text(
&mut self,
publisher: &str,
fmri: &Fmri,
) -> Result<String> {
fn fetch_manifest_text(&mut self, publisher: &str, fmri: &Fmri) -> Result<String> {
// Require a concrete version
let version = fmri.version();
if version.is_empty() {
@ -1609,10 +1605,7 @@ impl ReadableRepository for FileBackend {
let path = Self::construct_manifest_path(&self.path, publisher, fmri.stem(), &version);
if path.exists() {
return std::fs::read_to_string(&path)
.map_err(|e| RepositoryError::FileReadError {
path,
source: e,
});
.map_err(|e| RepositoryError::FileReadError { path, source: e });
}
// Fallbacks: global pkg layout without publisher
let encoded_stem = Self::url_encode(fmri.stem());

View file

@ -385,11 +385,7 @@ pub trait ReadableRepository {
) -> Result<crate::actions::Manifest>;
/// Fetch a package manifest as raw text by FMRI from the repository.
fn fetch_manifest_text(
&mut self,
publisher: &str,
fmri: &crate::fmri::Fmri,
) -> Result<String>;
fn fetch_manifest_text(&mut self, publisher: &str, fmri: &crate::fmri::Fmri) -> Result<String>;
/// Search for packages in the repository
///

View file

@ -64,7 +64,11 @@ impl WritableRepository for RestBackend {
// This is a stub implementation
// In a real implementation, we would make a REST API call to create the repository
let uri_str = uri.as_ref().to_string_lossy().trim_end_matches('/').to_string();
let uri_str = uri
.as_ref()
.to_string_lossy()
.trim_end_matches('/')
.to_string();
// Create the repository configuration
let config = RepositoryConfig {
@ -323,7 +327,11 @@ impl WritableRepository for RestBackend {
impl ReadableRepository for RestBackend {
/// Open an existing repository
fn open<P: AsRef<Path>>(uri: P) -> Result<Self> {
let uri_str = uri.as_ref().to_string_lossy().trim_end_matches('/').to_string();
let uri_str = uri
.as_ref()
.to_string_lossy()
.trim_end_matches('/')
.to_string();
// Create an HTTP client
let client = Client::new();
@ -444,14 +452,20 @@ impl ReadableRepository for RestBackend {
return Ok(Vec::new());
}
Err(e) => {
return Err(RepositoryError::Other(format!("Search API error: {} for {}", e, url)));
return Err(RepositoryError::Other(format!(
"Search API error: {} for {}",
e, url
)));
}
};
let reader = BufReader::new(resp);
for line in reader.lines() {
let line = line.map_err(|e| {
RepositoryError::Other(format!("Failed to read search response line: {}", e))
RepositoryError::Other(format!(
"Failed to read search response line: {}",
e
))
})?;
// Line format: <attr> <fmri> <value_type> <value>
// Example: pkg.fmri pkg:/system/rsyslog@8.2508.0,5.11-151056.0:20251023T180542Z set omnios/system/rsyslog
@ -681,11 +695,7 @@ impl ReadableRepository for RestBackend {
todo!()
}
fn fetch_manifest_text(
&mut self,
publisher: &str,
fmri: &crate::fmri::Fmri,
) -> Result<String> {
fn fetch_manifest_text(&mut self, publisher: &str, fmri: &crate::fmri::Fmri) -> Result<String> {
// Require versioned FMRI
let version = fmri.version();
if version.is_empty() {

View file

@ -69,8 +69,8 @@ async fn get_publisher_response(
}],
version: 1,
};
let json =
serde_json::to_string_pretty(&p5i).map_err(|e| DepotError::Server(e.to_string()))?;
let json = serde_json::to_string_pretty(&p5i)
.map_err(|e| DepotError::Server(e.to_string()))?;
Ok(([(header::CONTENT_TYPE, "application/vnd.pkg5.info")], json).into_response())
} else {
Err(DepotError::Repo(

View file

@ -38,9 +38,15 @@ pub fn app_router(state: Arc<DepotRepo>) -> Router {
)
.route("/{publisher}/info/0/{fmri}", get(info::get_info))
.route("/{publisher}/publisher/0", get(publisher::get_publisher_v0))
.route("/{publisher}/publisher/0/", get(publisher::get_publisher_v0))
.route(
"/{publisher}/publisher/0/",
get(publisher::get_publisher_v0),
)
.route("/{publisher}/publisher/1", get(publisher::get_publisher_v1))
.route("/{publisher}/publisher/1/", get(publisher::get_publisher_v1))
.route(
"/{publisher}/publisher/1/",
get(publisher::get_publisher_v1),
)
.route("/publisher/0", get(publisher::get_default_publisher_v0))
.route("/publisher/0/", get(publisher::get_default_publisher_v0))
.route("/publisher/1", get(publisher::get_default_publisher_v1))

View file

@ -476,7 +476,10 @@ async fn test_multiple_publishers_default_route() {
// DESIRED BEHAVIOR: returns 2
assert_eq!(pubs.len(), 2, "Should return all publishers");
let names: Vec<String> = pubs.iter().map(|p| p["name"].as_str().unwrap().to_string()).collect();
let names: Vec<String> = pubs
.iter()
.map(|p| p["name"].as_str().unwrap().to_string())
.collect();
assert!(names.contains(&"pub1".to_string()));
assert!(names.contains(&"pub2".to_string()));
}

View file

@ -1,8 +1,10 @@
use clap::Parser;
use miette::{IntoDiagnostic, Result};
use libips::repository::{FileBackend, RestBackend, ReadableRepository, ProgressReporter, ProgressInfo};
use libips::recv::PackageReceiver;
use libips::fmri::Fmri;
use libips::recv::PackageReceiver;
use libips::repository::{
FileBackend, ProgressInfo, ProgressReporter, ReadableRepository, RestBackend,
};
use miette::{IntoDiagnostic, Result};
use std::path::PathBuf;
use tracing::info;
use tracing_subscriber::{EnvFilter, fmt};
@ -56,7 +58,9 @@ fn main() -> Result<()> {
// Open destination repository
// We'll open it inside each branch to avoid borrow checker issues with moves
let fmris: Vec<Fmri> = cli.packages.iter()
let fmris: Vec<Fmri> = cli
.packages
.iter()
.map(|s| Fmri::parse(s))
.collect::<std::result::Result<Vec<_>, _>>()
.into_diagnostic()?;
@ -69,13 +73,17 @@ fn main() -> Result<()> {
let dest_repo = FileBackend::open(&cli.dest).into_diagnostic()?;
let mut receiver = PackageReceiver::new(&mut source_repo, dest_repo);
receiver = receiver.with_progress(&progress);
receiver.receive(cli.publisher.as_deref(), &fmris, cli.recursive).into_diagnostic()?;
receiver
.receive(cli.publisher.as_deref(), &fmris, cli.recursive)
.into_diagnostic()?;
} else {
let mut source_repo = FileBackend::open(&cli.source).into_diagnostic()?;
let dest_repo = FileBackend::open(&cli.dest).into_diagnostic()?;
let mut receiver = PackageReceiver::new(&mut source_repo, dest_repo);
receiver = receiver.with_progress(&progress);
receiver.receive(cli.publisher.as_deref(), &fmris, cli.recursive).into_diagnostic()?;
receiver
.receive(cli.publisher.as_deref(), &fmris, cli.recursive)
.into_diagnostic()?;
}
info!("Package receive complete.");

View file

@ -131,7 +131,12 @@ fn main() -> Result<()> {
tracing_subscriber::fmt().with_env_filter(env_filter).init();
// Load image
let image = Image::load(&cli.image_path).map_err(|e| PkgTreeError(format!("Failed to load image at {:?}: {}", cli.image_path, e)))?;
let image = Image::load(&cli.image_path).map_err(|e| {
PkgTreeError(format!(
"Failed to load image at {:?}: {}",
cli.image_path, e
))
})?;
// Targeted analysis of solver error file has top priority if provided
if let Some(err_path) = &cli.solver_error_file {
@ -164,7 +169,9 @@ fn main() -> Result<()> {
.query_catalog(Some(needle.as_str()))
.map_err(|e| PkgTreeError(format!("Failed to query catalog: {}", e)))?
} else {
image.query_catalog(None).map_err(|e| PkgTreeError(format!("Failed to query catalog: {}", e)))?
image
.query_catalog(None)
.map_err(|e| PkgTreeError(format!("Failed to query catalog: {}", e)))?
};
// Filter by publisher if specified
@ -765,7 +772,10 @@ fn query_catalog_cached_mut(
return Ok(v.clone());
}
let mut out = Vec::new();
for p in image.query_catalog(Some(stem)).map_err(|e| PkgTreeError(format!("Failed to query catalog for {}: {}", stem, e)))? {
for p in image
.query_catalog(Some(stem))
.map_err(|e| PkgTreeError(format!("Failed to query catalog for {}: {}", stem, e)))?
{
out.push((p.publisher, p.fmri));
}
ctx.catalog_cache.insert(stem.to_string(), out.clone());
@ -781,9 +791,13 @@ fn get_manifest_cached(
if let Some(m) = ctx.manifest_cache.get(&key) {
return Ok(m.clone());
}
let manifest_opt = image
.get_manifest_from_catalog(fmri)
.map_err(|e| PkgTreeError(format!("Failed to load manifest for {}: {}", fmri.to_string(), e)))?;
let manifest_opt = image.get_manifest_from_catalog(fmri).map_err(|e| {
PkgTreeError(format!(
"Failed to load manifest for {}: {}",
fmri.to_string(),
e
))
})?;
let manifest = manifest_opt.unwrap_or_else(|| libips::actions::Manifest::new());
ctx.manifest_cache.insert(key, manifest.clone());
Ok(manifest)
@ -1018,7 +1032,9 @@ fn run_dangling_scan(
format: OutputFormat,
) -> Result<()> {
// Query full catalog once
let mut pkgs = image.query_catalog(None).map_err(|e| PkgTreeError(format!("Failed to query catalog: {}", e)))?;
let mut pkgs = image
.query_catalog(None)
.map_err(|e| PkgTreeError(format!("Failed to query catalog: {}", e)))?;
// Build set of available non-obsolete stems AND an index of available (release, branch) pairs per stem,
// honoring publisher filter
@ -1188,7 +1204,12 @@ fn run_dangling_scan(
// ---------- Targeted analysis: parse pkg6 solver error text ----------
fn analyze_solver_error(image: &Image, publisher: Option<&str>, err_path: &PathBuf) -> Result<()> {
let text = std::fs::read_to_string(err_path).map_err(|e| PkgTreeError(format!("Failed to read solver error file {:?}: {}", err_path, e)))?;
let text = std::fs::read_to_string(err_path).map_err(|e| {
PkgTreeError(format!(
"Failed to read solver error file {:?}: {}",
err_path, e
))
})?;
// Build a stack based on indentation before the tree bullet "└─".
let mut stack: Vec<String> = Vec::new();

View file

@ -262,11 +262,7 @@ fn fmt() -> Result<()> {
/// Run clippy
fn clippy() -> Result<()> {
Command::new("cargo")
.args([
"clippy",
"--all-targets",
"--all-features",
])
.args(["clippy", "--all-targets", "--all-features"])
.status()
.context("Failed to run clippy")?;