mirror of
https://codeberg.org/Toasterson/ips.git
synced 2026-04-10 13:20:42 +00:00
Refactor repository traits into ReadableRepository and WritableRepository, introduce Repository to combine traits for backward compatibility, and update relevant modules and tests to use the new structure.
This commit is contained in:
parent
a0fcc13033
commit
ead9ad12af
6 changed files with 1007 additions and 784 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -105,47 +105,20 @@ impl Default for RepositoryConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Repository trait defining the interface for all repository backends
|
/// Repository trait for read-only operations
|
||||||
pub trait Repository {
|
pub trait ReadableRepository {
|
||||||
/// Create a new repository at the specified path
|
|
||||||
fn create<P: AsRef<Path>>(path: P, version: RepositoryVersion) -> Result<Self> where Self: Sized;
|
|
||||||
|
|
||||||
/// Open an existing repository
|
/// Open an existing repository
|
||||||
fn open<P: AsRef<Path>>(path: P) -> Result<Self> where Self: Sized;
|
fn open<P: AsRef<Path>>(path: P) -> Result<Self> where Self: Sized;
|
||||||
|
|
||||||
/// Save the repository configuration
|
|
||||||
fn save_config(&self) -> Result<()>;
|
|
||||||
|
|
||||||
/// Add a publisher to the repository
|
|
||||||
fn add_publisher(&mut self, publisher: &str) -> Result<()>;
|
|
||||||
|
|
||||||
/// Remove a publisher from the repository
|
|
||||||
fn remove_publisher(&mut self, publisher: &str, dry_run: bool) -> Result<()>;
|
|
||||||
|
|
||||||
/// Get repository information
|
/// Get repository information
|
||||||
fn get_info(&self) -> Result<RepositoryInfo>;
|
fn get_info(&self) -> Result<RepositoryInfo>;
|
||||||
|
|
||||||
/// Set a repository property
|
|
||||||
fn set_property(&mut self, property: &str, value: &str) -> Result<()>;
|
|
||||||
|
|
||||||
/// Set a publisher property
|
|
||||||
fn set_publisher_property(&mut self, publisher: &str, property: &str, value: &str) -> Result<()>;
|
|
||||||
|
|
||||||
/// List packages in the repository
|
/// List packages in the repository
|
||||||
fn list_packages(&self, publisher: Option<&str>, pattern: Option<&str>) -> Result<Vec<PackageInfo>>;
|
fn list_packages(&self, publisher: Option<&str>, pattern: Option<&str>) -> Result<Vec<PackageInfo>>;
|
||||||
|
|
||||||
/// Show contents of packages
|
/// Show contents of packages
|
||||||
fn show_contents(&self, publisher: Option<&str>, pattern: Option<&str>, action_types: Option<&[String]>) -> Result<Vec<PackageContents>>;
|
fn show_contents(&self, publisher: Option<&str>, pattern: Option<&str>, action_types: Option<&[String]>) -> Result<Vec<PackageContents>>;
|
||||||
|
|
||||||
/// Rebuild repository metadata
|
|
||||||
fn rebuild(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()>;
|
|
||||||
|
|
||||||
/// Refresh repository metadata
|
|
||||||
fn refresh(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()>;
|
|
||||||
|
|
||||||
/// Set the default publisher for the repository
|
|
||||||
fn set_default_publisher(&mut self, publisher: &str) -> Result<()>;
|
|
||||||
|
|
||||||
/// Search for packages in the repository
|
/// Search for packages in the repository
|
||||||
///
|
///
|
||||||
/// This method searches for packages in the repository using the search index.
|
/// This method searches for packages in the repository using the search index.
|
||||||
|
|
@ -157,4 +130,40 @@ pub trait Repository {
|
||||||
/// * `publisher` - Optional publisher to limit the search to
|
/// * `publisher` - Optional publisher to limit the search to
|
||||||
/// * `limit` - Optional maximum number of results to return
|
/// * `limit` - Optional maximum number of results to return
|
||||||
fn search(&self, query: &str, publisher: Option<&str>, limit: Option<usize>) -> Result<Vec<PackageInfo>>;
|
fn search(&self, query: &str, publisher: Option<&str>, limit: Option<usize>) -> Result<Vec<PackageInfo>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Repository trait for write operations
|
||||||
|
pub trait WritableRepository {
|
||||||
|
/// Create a new repository at the specified path
|
||||||
|
fn create<P: AsRef<Path>>(path: P, version: RepositoryVersion) -> Result<Self> where Self: Sized;
|
||||||
|
|
||||||
|
/// Save the repository configuration
|
||||||
|
fn save_config(&self) -> Result<()>;
|
||||||
|
|
||||||
|
/// Add a publisher to the repository
|
||||||
|
fn add_publisher(&mut self, publisher: &str) -> Result<()>;
|
||||||
|
|
||||||
|
/// Remove a publisher from the repository
|
||||||
|
fn remove_publisher(&mut self, publisher: &str, dry_run: bool) -> Result<()>;
|
||||||
|
|
||||||
|
/// Set a repository property
|
||||||
|
fn set_property(&mut self, property: &str, value: &str) -> Result<()>;
|
||||||
|
|
||||||
|
/// Set a publisher property
|
||||||
|
fn set_publisher_property(&mut self, publisher: &str, property: &str, value: &str) -> Result<()>;
|
||||||
|
|
||||||
|
/// Rebuild repository metadata
|
||||||
|
fn rebuild(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()>;
|
||||||
|
|
||||||
|
/// Refresh repository metadata
|
||||||
|
fn refresh(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()>;
|
||||||
|
|
||||||
|
/// Set the default publisher for the repository
|
||||||
|
fn set_default_publisher(&mut self, publisher: &str) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Repository trait defining the interface for all repository backends
|
||||||
|
///
|
||||||
|
/// This trait combines both ReadableRepository and WritableRepository traits
|
||||||
|
/// for backward compatibility.
|
||||||
|
pub trait Repository: ReadableRepository + WritableRepository {}
|
||||||
|
|
@ -6,7 +6,10 @@
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use super::{Repository, RepositoryConfig, RepositoryVersion, PublisherInfo, RepositoryInfo, PackageInfo, PackageContents};
|
use super::{
|
||||||
|
PackageContents, PackageInfo, PublisherInfo, ReadableRepository, RepositoryConfig,
|
||||||
|
RepositoryInfo, RepositoryVersion, WritableRepository,
|
||||||
|
};
|
||||||
|
|
||||||
/// Repository implementation that uses a REST API
|
/// Repository implementation that uses a REST API
|
||||||
pub struct RestBackend {
|
pub struct RestBackend {
|
||||||
|
|
@ -15,161 +18,82 @@ pub struct RestBackend {
|
||||||
pub local_cache_path: Option<PathBuf>,
|
pub local_cache_path: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repository for RestBackend {
|
impl WritableRepository for RestBackend {
|
||||||
/// Create a new repository at the specified URI
|
/// Create a new repository at the specified URI
|
||||||
fn create<P: AsRef<Path>>(uri: P, version: RepositoryVersion) -> Result<Self> {
|
fn create<P: AsRef<Path>>(uri: P, version: RepositoryVersion) -> Result<Self> {
|
||||||
// This is a stub implementation
|
// This is a stub implementation
|
||||||
// In a real implementation, we would make a REST API call to create the repository
|
// In a real implementation, we would make a REST API call to create the repository
|
||||||
|
|
||||||
let uri_str = uri.as_ref().to_string_lossy().to_string();
|
let uri_str = uri.as_ref().to_string_lossy().to_string();
|
||||||
|
|
||||||
// Create the repository configuration
|
// Create the repository configuration
|
||||||
let config = RepositoryConfig {
|
let config = RepositoryConfig {
|
||||||
version,
|
version,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the repository structure
|
// Create the repository structure
|
||||||
let repo = RestBackend {
|
let repo = RestBackend {
|
||||||
uri: uri_str,
|
uri: uri_str,
|
||||||
config,
|
config,
|
||||||
local_cache_path: None,
|
local_cache_path: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// In a real implementation, we would make a REST API call to create the repository structure
|
// In a real implementation, we would make a REST API call to create the repository structure
|
||||||
|
|
||||||
Ok(repo)
|
Ok(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Open an existing repository
|
|
||||||
fn open<P: AsRef<Path>>(uri: P) -> Result<Self> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to get the repository configuration
|
|
||||||
|
|
||||||
let uri_str = uri.as_ref().to_string_lossy().to_string();
|
|
||||||
|
|
||||||
// In a real implementation, we would fetch the repository configuration from the REST API
|
|
||||||
// For now, we'll just create a default configuration
|
|
||||||
let config = RepositoryConfig::default();
|
|
||||||
|
|
||||||
Ok(RestBackend {
|
|
||||||
uri: uri_str,
|
|
||||||
config,
|
|
||||||
local_cache_path: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Save the repository configuration
|
/// Save the repository configuration
|
||||||
fn save_config(&self) -> Result<()> {
|
fn save_config(&self) -> Result<()> {
|
||||||
// This is a stub implementation
|
// This is a stub implementation
|
||||||
// In a real implementation, we would make a REST API call to save the repository configuration
|
// In a real implementation, we would make a REST API call to save the repository configuration
|
||||||
|
|
||||||
// For now, just return Ok
|
// For now, just return Ok
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a publisher to the repository
|
/// Add a publisher to the repository
|
||||||
fn add_publisher(&mut self, publisher: &str) -> Result<()> {
|
fn add_publisher(&mut self, publisher: &str) -> Result<()> {
|
||||||
// This is a stub implementation
|
// This is a stub implementation
|
||||||
// In a real implementation, we would make a REST API call to add the publisher
|
// In a real implementation, we would make a REST API call to add the publisher
|
||||||
|
|
||||||
if !self.config.publishers.contains(&publisher.to_string()) {
|
if !self.config.publishers.contains(&publisher.to_string()) {
|
||||||
self.config.publishers.push(publisher.to_string());
|
self.config.publishers.push(publisher.to_string());
|
||||||
|
|
||||||
// In a real implementation, we would make a REST API call to create publisher-specific resources
|
// In a real implementation, we would make a REST API call to create publisher-specific resources
|
||||||
|
|
||||||
// Save the updated configuration
|
// Save the updated configuration
|
||||||
self.save_config()?;
|
self.save_config()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove a publisher from the repository
|
/// Remove a publisher from the repository
|
||||||
fn remove_publisher(&mut self, publisher: &str, dry_run: bool) -> Result<()> {
|
fn remove_publisher(&mut self, publisher: &str, dry_run: bool) -> Result<()> {
|
||||||
// This is a stub implementation
|
// This is a stub implementation
|
||||||
// In a real implementation, we would make a REST API call to remove the publisher
|
// In a real implementation, we would make a REST API call to remove the publisher
|
||||||
|
|
||||||
if let Some(pos) = self.config.publishers.iter().position(|p| p == publisher) {
|
if let Some(pos) = self.config.publishers.iter().position(|p| p == publisher) {
|
||||||
if !dry_run {
|
if !dry_run {
|
||||||
self.config.publishers.remove(pos);
|
self.config.publishers.remove(pos);
|
||||||
|
|
||||||
// In a real implementation, we would make a REST API call to remove publisher-specific resources
|
// In a real implementation, we would make a REST API call to remove publisher-specific resources
|
||||||
|
|
||||||
// Save the updated configuration
|
// Save the updated configuration
|
||||||
self.save_config()?;
|
self.save_config()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get repository information
|
/// Rebuild repository metadata
|
||||||
fn get_info(&self) -> Result<RepositoryInfo> {
|
fn rebuild(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()> {
|
||||||
// This is a stub implementation
|
// This is a stub implementation
|
||||||
// In a real implementation, we would make a REST API call to get repository information
|
// In a real implementation, we would make a REST API call to rebuild metadata
|
||||||
|
|
||||||
let mut publishers = Vec::new();
|
|
||||||
|
|
||||||
for publisher_name in &self.config.publishers {
|
|
||||||
// In a real implementation, we would get this information from the REST API
|
|
||||||
let package_count = 0;
|
|
||||||
let status = "online".to_string();
|
|
||||||
let updated = "2025-07-21T18:46:00.000000Z".to_string();
|
|
||||||
|
|
||||||
// Create a PublisherInfo struct and add it to the list
|
|
||||||
publishers.push(PublisherInfo {
|
|
||||||
name: publisher_name.clone(),
|
|
||||||
package_count,
|
|
||||||
status,
|
|
||||||
updated,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create and return a RepositoryInfo struct
|
|
||||||
Ok(RepositoryInfo { publishers })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set a repository property
|
|
||||||
fn set_property(&mut self, property: &str, value: &str) -> Result<()> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to set the property
|
|
||||||
|
|
||||||
self.config.properties.insert(property.to_string(), value.to_string());
|
|
||||||
self.save_config()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set a publisher property
|
|
||||||
fn set_publisher_property(&mut self, publisher: &str, property: &str, value: &str) -> Result<()> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to set the publisher property
|
|
||||||
|
|
||||||
// Check if the publisher exists
|
|
||||||
if !self.config.publishers.contains(&publisher.to_string()) {
|
|
||||||
return Err(anyhow!("Publisher does not exist: {}", publisher));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the property key in the format "publisher/property"
|
|
||||||
let key = format!("{}/{}", publisher, property);
|
|
||||||
|
|
||||||
// Set the property
|
|
||||||
self.config.properties.insert(key, value.to_string());
|
|
||||||
|
|
||||||
// Save the updated configuration
|
|
||||||
self.save_config()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// List packages in the repository
|
|
||||||
fn list_packages(&self, publisher: Option<&str>, pattern: Option<&str>) -> Result<Vec<PackageInfo>> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to list packages
|
|
||||||
|
|
||||||
let mut packages = Vec::new();
|
|
||||||
|
|
||||||
// Filter publishers if specified
|
// Filter publishers if specified
|
||||||
let publishers = if let Some(pub_name) = publisher {
|
let publishers = if let Some(pub_name) = publisher {
|
||||||
if !self.config.publishers.contains(&pub_name.to_string()) {
|
if !self.config.publishers.contains(&pub_name.to_string()) {
|
||||||
|
|
@ -179,38 +103,220 @@ impl Repository for RestBackend {
|
||||||
} else {
|
} else {
|
||||||
self.config.publishers.clone()
|
self.config.publishers.clone()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For each publisher, rebuild metadata
|
||||||
|
for pub_name in publishers {
|
||||||
|
println!("Rebuilding metadata for publisher: {}", pub_name);
|
||||||
|
|
||||||
|
if !no_catalog {
|
||||||
|
println!("Rebuilding catalog...");
|
||||||
|
// In a real implementation, we would make a REST API call to rebuild the catalog
|
||||||
|
}
|
||||||
|
|
||||||
|
if !no_index {
|
||||||
|
println!("Rebuilding search index...");
|
||||||
|
// In a real implementation, we would make a REST API call to rebuild the search index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Refresh repository metadata
|
||||||
|
fn refresh(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to refresh metadata
|
||||||
|
|
||||||
|
// Filter publishers if specified
|
||||||
|
let publishers = if let Some(pub_name) = publisher {
|
||||||
|
if !self.config.publishers.contains(&pub_name.to_string()) {
|
||||||
|
return Err(anyhow!("Publisher does not exist: {}", pub_name));
|
||||||
|
}
|
||||||
|
vec![pub_name.to_string()]
|
||||||
|
} else {
|
||||||
|
self.config.publishers.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
// For each publisher, refresh metadata
|
||||||
|
for pub_name in publishers {
|
||||||
|
println!("Refreshing metadata for publisher: {}", pub_name);
|
||||||
|
|
||||||
|
if !no_catalog {
|
||||||
|
println!("Refreshing catalog...");
|
||||||
|
// In a real implementation, we would make a REST API call to refresh the catalog
|
||||||
|
}
|
||||||
|
|
||||||
|
if !no_index {
|
||||||
|
println!("Refreshing search index...");
|
||||||
|
// In a real implementation, we would make a REST API call to refresh the search index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the default publisher for the repository
|
||||||
|
fn set_default_publisher(&mut self, publisher: &str) -> Result<()> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to set the default publisher
|
||||||
|
|
||||||
|
// Check if the publisher exists
|
||||||
|
if !self.config.publishers.contains(&publisher.to_string()) {
|
||||||
|
return Err(anyhow!("Publisher does not exist: {}", publisher));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default publisher
|
||||||
|
self.config.default_publisher = Some(publisher.to_string());
|
||||||
|
|
||||||
|
// Save the updated configuration
|
||||||
|
self.save_config()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a repository property
|
||||||
|
fn set_property(&mut self, property: &str, value: &str) -> Result<()> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to set the property
|
||||||
|
|
||||||
|
self.config
|
||||||
|
.properties
|
||||||
|
.insert(property.to_string(), value.to_string());
|
||||||
|
self.save_config()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set a publisher property
|
||||||
|
fn set_publisher_property(
|
||||||
|
&mut self,
|
||||||
|
publisher: &str,
|
||||||
|
property: &str,
|
||||||
|
value: &str,
|
||||||
|
) -> Result<()> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to set the publisher property
|
||||||
|
|
||||||
|
// Check if the publisher exists
|
||||||
|
if !self.config.publishers.contains(&publisher.to_string()) {
|
||||||
|
return Err(anyhow!("Publisher does not exist: {}", publisher));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the property key in the format "publisher/property"
|
||||||
|
let key = format!("{}/{}", publisher, property);
|
||||||
|
|
||||||
|
// Set the property
|
||||||
|
self.config.properties.insert(key, value.to_string());
|
||||||
|
|
||||||
|
// Save the updated configuration
|
||||||
|
self.save_config()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReadableRepository for RestBackend {
|
||||||
|
/// Open an existing repository
|
||||||
|
fn open<P: AsRef<Path>>(uri: P) -> Result<Self> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to get the repository configuration
|
||||||
|
|
||||||
|
let uri_str = uri.as_ref().to_string_lossy().to_string();
|
||||||
|
|
||||||
|
// In a real implementation, we would fetch the repository configuration from the REST API
|
||||||
|
// For now, we'll just create a default configuration
|
||||||
|
let config = RepositoryConfig::default();
|
||||||
|
|
||||||
|
Ok(RestBackend {
|
||||||
|
uri: uri_str,
|
||||||
|
config,
|
||||||
|
local_cache_path: None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get repository information
|
||||||
|
fn get_info(&self) -> Result<RepositoryInfo> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to get repository information
|
||||||
|
|
||||||
|
let mut publishers = Vec::new();
|
||||||
|
|
||||||
|
for publisher_name in &self.config.publishers {
|
||||||
|
// In a real implementation, we would get this information from the REST API
|
||||||
|
let package_count = 0;
|
||||||
|
let status = "online".to_string();
|
||||||
|
let updated = "2025-07-21T18:46:00.000000Z".to_string();
|
||||||
|
|
||||||
|
// Create a PublisherInfo struct and add it to the list
|
||||||
|
publishers.push(PublisherInfo {
|
||||||
|
name: publisher_name.clone(),
|
||||||
|
package_count,
|
||||||
|
status,
|
||||||
|
updated,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and return a RepositoryInfo struct
|
||||||
|
Ok(RepositoryInfo { publishers })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List packages in the repository
|
||||||
|
fn list_packages(
|
||||||
|
&self,
|
||||||
|
publisher: Option<&str>,
|
||||||
|
pattern: Option<&str>,
|
||||||
|
) -> Result<Vec<PackageInfo>> {
|
||||||
|
// This is a stub implementation
|
||||||
|
// In a real implementation, we would make a REST API call to list packages
|
||||||
|
|
||||||
|
let mut packages = Vec::new();
|
||||||
|
|
||||||
|
// Filter publishers if specified
|
||||||
|
let publishers = if let Some(pub_name) = publisher {
|
||||||
|
if !self.config.publishers.contains(&pub_name.to_string()) {
|
||||||
|
return Err(anyhow!("Publisher does not exist: {}", pub_name));
|
||||||
|
}
|
||||||
|
vec![pub_name.to_string()]
|
||||||
|
} else {
|
||||||
|
self.config.publishers.clone()
|
||||||
|
};
|
||||||
|
|
||||||
// For each publisher, list packages
|
// For each publisher, list packages
|
||||||
for pub_name in publishers {
|
for pub_name in publishers {
|
||||||
// In a real implementation, we would make a REST API call to get package information
|
// In a real implementation, we would make a REST API call to get package information
|
||||||
// The API call would return a list of packages with their names, versions, and other metadata
|
// The API call would return a list of packages with their names, versions, and other metadata
|
||||||
// We would then parse this information and create PackageInfo structs
|
// We would then parse this information and create PackageInfo structs
|
||||||
|
|
||||||
// For now, we return an empty list since we don't want to return placeholder data
|
// For now, we return an empty list since we don't want to return placeholder data
|
||||||
// and we don't have a real API to call
|
// and we don't have a real API to call
|
||||||
|
|
||||||
// If pattern filtering is needed, it would be applied here to the results from the API
|
// If pattern filtering is needed, it would be applied here to the results from the API
|
||||||
// When implementing, use the regex crate to handle user-provided regexp patterns properly,
|
// When implementing, use the regex crate to handle user-provided regexp patterns properly,
|
||||||
// similar to the implementation in file_backend.rs
|
// similar to the implementation in file_backend.rs
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(packages)
|
Ok(packages)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show contents of packages
|
/// Show contents of packages
|
||||||
fn show_contents(&self, publisher: Option<&str>, pattern: Option<&str>, action_types: Option<&[String]>) -> Result<Vec<PackageContents>> {
|
fn show_contents(
|
||||||
|
&self,
|
||||||
|
publisher: Option<&str>,
|
||||||
|
pattern: Option<&str>,
|
||||||
|
action_types: Option<&[String]>,
|
||||||
|
) -> Result<Vec<PackageContents>> {
|
||||||
// This is a stub implementation
|
// This is a stub implementation
|
||||||
// In a real implementation, we would make a REST API call to get package contents
|
// In a real implementation, we would make a REST API call to get package contents
|
||||||
|
|
||||||
// Get the list of packages
|
// Get the list of packages
|
||||||
let packages = self.list_packages(publisher, pattern)?;
|
let packages = self.list_packages(publisher, pattern)?;
|
||||||
|
|
||||||
// For each package, create a PackageContents struct
|
// For each package, create a PackageContents struct
|
||||||
let mut package_contents = Vec::new();
|
let mut package_contents = Vec::new();
|
||||||
|
|
||||||
for pkg_info in packages {
|
for pkg_info in packages {
|
||||||
// In a real implementation, we would get this information from the REST API
|
// In a real implementation, we would get this information from the REST API
|
||||||
|
|
||||||
// Format the package identifier using the FMRI
|
// Format the package identifier using the FMRI
|
||||||
let version = pkg_info.fmri.version();
|
let version = pkg_info.fmri.version();
|
||||||
let pkg_id = if !version.is_empty() {
|
let pkg_id = if !version.is_empty() {
|
||||||
|
|
@ -218,12 +324,14 @@ impl Repository for RestBackend {
|
||||||
} else {
|
} else {
|
||||||
pkg_info.fmri.stem().to_string()
|
pkg_info.fmri.stem().to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Example content for each type
|
// Example content for each type
|
||||||
// In a real implementation, we would get this information from the REST API
|
// In a real implementation, we would get this information from the REST API
|
||||||
|
|
||||||
// Files
|
// Files
|
||||||
let files = if action_types.is_none() || action_types.as_ref().unwrap().contains(&"file".to_string()) {
|
let files = if action_types.is_none()
|
||||||
|
|| action_types.as_ref().unwrap().contains(&"file".to_string())
|
||||||
|
{
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"/usr/bin/example".to_string(),
|
"/usr/bin/example".to_string(),
|
||||||
"/usr/lib/example.so".to_string(),
|
"/usr/lib/example.so".to_string(),
|
||||||
|
|
@ -231,9 +339,11 @@ impl Repository for RestBackend {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Directories
|
// Directories
|
||||||
let directories = if action_types.is_none() || action_types.as_ref().unwrap().contains(&"dir".to_string()) {
|
let directories = if action_types.is_none()
|
||||||
|
|| action_types.as_ref().unwrap().contains(&"dir".to_string())
|
||||||
|
{
|
||||||
Some(vec![
|
Some(vec![
|
||||||
"/usr/share/doc/example".to_string(),
|
"/usr/share/doc/example".to_string(),
|
||||||
"/usr/share/man/man1".to_string(),
|
"/usr/share/man/man1".to_string(),
|
||||||
|
|
@ -241,34 +351,40 @@ impl Repository for RestBackend {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Links
|
// Links
|
||||||
let links = if action_types.is_none() || action_types.as_ref().unwrap().contains(&"link".to_string()) {
|
let links = if action_types.is_none()
|
||||||
Some(vec![
|
|| action_types.as_ref().unwrap().contains(&"link".to_string())
|
||||||
"/usr/bin/example-link".to_string(),
|
{
|
||||||
])
|
Some(vec!["/usr/bin/example-link".to_string()])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
let dependencies = if action_types.is_none() || action_types.as_ref().unwrap().contains(&"depend".to_string()) {
|
let dependencies = if action_types.is_none()
|
||||||
Some(vec![
|
|| action_types
|
||||||
"pkg:/system/library@0.5.11".to_string(),
|
.as_ref()
|
||||||
])
|
.unwrap()
|
||||||
|
.contains(&"depend".to_string())
|
||||||
|
{
|
||||||
|
Some(vec!["pkg:/system/library@0.5.11".to_string()])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Licenses
|
// Licenses
|
||||||
let licenses = if action_types.is_none() || action_types.as_ref().unwrap().contains(&"license".to_string()) {
|
let licenses = if action_types.is_none()
|
||||||
Some(vec![
|
|| action_types
|
||||||
"/usr/share/licenses/example/LICENSE".to_string(),
|
.as_ref()
|
||||||
])
|
.unwrap()
|
||||||
|
.contains(&"license".to_string())
|
||||||
|
{
|
||||||
|
Some(vec!["/usr/share/licenses/example/LICENSE".to_string()])
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add the package contents to the result
|
// Add the package contents to the result
|
||||||
package_contents.push(PackageContents {
|
package_contents.push(PackageContents {
|
||||||
package_id: pkg_id,
|
package_id: pkg_id,
|
||||||
|
|
@ -279,96 +395,16 @@ impl Repository for RestBackend {
|
||||||
licenses,
|
licenses,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(package_contents)
|
Ok(package_contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rebuild repository metadata
|
|
||||||
fn rebuild(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to rebuild metadata
|
|
||||||
|
|
||||||
// Filter publishers if specified
|
|
||||||
let publishers = if let Some(pub_name) = publisher {
|
|
||||||
if !self.config.publishers.contains(&pub_name.to_string()) {
|
|
||||||
return Err(anyhow!("Publisher does not exist: {}", pub_name));
|
|
||||||
}
|
|
||||||
vec![pub_name.to_string()]
|
|
||||||
} else {
|
|
||||||
self.config.publishers.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
// For each publisher, rebuild metadata
|
|
||||||
for pub_name in publishers {
|
|
||||||
println!("Rebuilding metadata for publisher: {}", pub_name);
|
|
||||||
|
|
||||||
if !no_catalog {
|
|
||||||
println!("Rebuilding catalog...");
|
|
||||||
// In a real implementation, we would make a REST API call to rebuild the catalog
|
|
||||||
}
|
|
||||||
|
|
||||||
if !no_index {
|
|
||||||
println!("Rebuilding search index...");
|
|
||||||
// In a real implementation, we would make a REST API call to rebuild the search index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Refresh repository metadata
|
|
||||||
fn refresh(&self, publisher: Option<&str>, no_catalog: bool, no_index: bool) -> Result<()> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to refresh metadata
|
|
||||||
|
|
||||||
// Filter publishers if specified
|
|
||||||
let publishers = if let Some(pub_name) = publisher {
|
|
||||||
if !self.config.publishers.contains(&pub_name.to_string()) {
|
|
||||||
return Err(anyhow!("Publisher does not exist: {}", pub_name));
|
|
||||||
}
|
|
||||||
vec![pub_name.to_string()]
|
|
||||||
} else {
|
|
||||||
self.config.publishers.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
// For each publisher, refresh metadata
|
|
||||||
for pub_name in publishers {
|
|
||||||
println!("Refreshing metadata for publisher: {}", pub_name);
|
|
||||||
|
|
||||||
if !no_catalog {
|
|
||||||
println!("Refreshing catalog...");
|
|
||||||
// In a real implementation, we would make a REST API call to refresh the catalog
|
|
||||||
}
|
|
||||||
|
|
||||||
if !no_index {
|
|
||||||
println!("Refreshing search index...");
|
|
||||||
// In a real implementation, we would make a REST API call to refresh the search index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the default publisher for the repository
|
|
||||||
fn set_default_publisher(&mut self, publisher: &str) -> Result<()> {
|
|
||||||
// This is a stub implementation
|
|
||||||
// In a real implementation, we would make a REST API call to set the default publisher
|
|
||||||
|
|
||||||
// Check if the publisher exists
|
|
||||||
if !self.config.publishers.contains(&publisher.to_string()) {
|
|
||||||
return Err(anyhow!("Publisher does not exist: {}", publisher));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the default publisher
|
|
||||||
self.config.default_publisher = Some(publisher.to_string());
|
|
||||||
|
|
||||||
// Save the updated configuration
|
|
||||||
self.save_config()?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn search(&self, query: &str, publisher: Option<&str>, limit: Option<usize>) -> Result<Vec<PackageInfo>> {
|
fn search(
|
||||||
|
&self,
|
||||||
|
query: &str,
|
||||||
|
publisher: Option<&str>,
|
||||||
|
limit: Option<usize>,
|
||||||
|
) -> Result<Vec<PackageInfo>> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -379,4 +415,4 @@ impl RestBackend {
|
||||||
self.local_cache_path = Some(path.as_ref().to_path_buf());
|
self.local_cache_path = Some(path.as_ref().to_path_buf());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use libips::actions::{ActionError, File, Manifest};
|
use libips::actions::{ActionError, File, Manifest};
|
||||||
use libips::repository::{Repository, FileBackend};
|
use libips::repository::{ReadableRepository, WritableRepository, FileBackend};
|
||||||
|
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
use anyhow::{anyhow, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use anyhow::{Result, anyhow};
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use libips::repository::{Repository, RepositoryVersion, FileBackend, PublisherInfo, RepositoryInfo, PackageInfo, PackageContents};
|
use libips::repository::{FileBackend, ReadableRepository, RepositoryVersion, WritableRepository};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use libips::repository::{Repository, RepositoryVersion, FileBackend, REPOSITORY_CONFIG_FILENAME, PublisherInfo, RepositoryInfo};
|
use libips::repository::{ReadableRepository, WritableRepository, RepositoryVersion, FileBackend, REPOSITORY_CONFIG_FILENAME, PublisherInfo, RepositoryInfo};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue