mirror of
https://codeberg.org/Toasterson/ips.git
synced 2026-04-10 13:20:42 +00:00
Add support for backward compatibility with legacy repository files
- Introduced creation of `pub.p5i` files for publishers to maintain compatibility with older repository formats. - Implemented saving repository configuration in legacy INI format (`pkg5.repository`). - Updated tests to validate the generation and structure of legacy files. - Added new dependencies (`rust-ini`) and updated `Cargo.toml` and `Cargo.lock` accordingly.
This commit is contained in:
parent
fc00304038
commit
dfe8ac1305
4 changed files with 286 additions and 0 deletions
71
Cargo.lock
generated
71
Cargo.lock
generated
|
|
@ -316,6 +316,26 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "const-random"
|
||||
version = "0.1.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-random-macro"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||
dependencies = [
|
||||
"getrandom 0.2.16",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation"
|
||||
version = "0.9.4"
|
||||
|
|
@ -350,6 +370,12 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
|
|
@ -432,6 +458,15 @@ dependencies = [
|
|||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlv-list"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
|
||||
dependencies = [
|
||||
"const-random",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
|
|
@ -627,6 +662,12 @@ version = "0.12.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.4"
|
||||
|
|
@ -981,6 +1022,7 @@ dependencies = [
|
|||
"pest_derive",
|
||||
"redb",
|
||||
"regex",
|
||||
"rust-ini",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_cbor",
|
||||
|
|
@ -1321,6 +1363,16 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-multimap"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
||||
dependencies = [
|
||||
"dlv-list",
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.6.1"
|
||||
|
|
@ -1644,6 +1696,16 @@ dependencies = [
|
|||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-ini"
|
||||
version = "0.21.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7295b7ce3bf4806b419dc3420745998b447178b7005e2011947b38fc5aa6791"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"ordered-multimap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.25"
|
||||
|
|
@ -2147,6 +2209,15 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.1"
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ tempfile = "3.20.0"
|
|||
walkdir = "2.4.0"
|
||||
redb = "1.5.0"
|
||||
bincode = "1.3.3"
|
||||
rust-ini = "0.21.2"
|
||||
|
||||
[features]
|
||||
default = ["redb-index"]
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ use super::{
|
|||
PackageContents, PackageInfo, PublisherInfo, ReadableRepository, RepositoryConfig,
|
||||
RepositoryInfo, RepositoryVersion, WritableRepository, REPOSITORY_CONFIG_FILENAME,
|
||||
};
|
||||
use ini::Ini;
|
||||
|
||||
// Define a struct to hold the content vectors for each package
|
||||
struct PackageContentVectors {
|
||||
|
|
@ -586,6 +587,31 @@ impl Transaction {
|
|||
);
|
||||
fs::copy(&manifest_path, &pkg_manifest_path)?;
|
||||
|
||||
// Check if we need to create a pub.p5i file for the publisher
|
||||
let config_path = self.repo.join(REPOSITORY_CONFIG_FILENAME);
|
||||
if config_path.exists() {
|
||||
let config_content = fs::read_to_string(&config_path)?;
|
||||
let config: RepositoryConfig = serde_json::from_str(&config_content)?;
|
||||
|
||||
// Check if this publisher was just added in this transaction
|
||||
let publisher_dir = self.repo.join("publisher").join(&publisher);
|
||||
let pub_p5i_path = publisher_dir.join("pub.p5i");
|
||||
|
||||
if !pub_p5i_path.exists() {
|
||||
debug!("Creating pub.p5i file for publisher: {}", publisher);
|
||||
|
||||
// Create the pub.p5i file
|
||||
let repo = FileBackend {
|
||||
path: self.repo.clone(),
|
||||
config,
|
||||
catalog_manager: None,
|
||||
obsoleted_manager: None,
|
||||
};
|
||||
|
||||
repo.create_pub_p5i_file(&publisher)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up the transaction directory
|
||||
fs::remove_dir_all(self.path)?;
|
||||
|
||||
|
|
@ -1333,9 +1359,14 @@ impl WritableRepository for FileBackend {
|
|||
|
||||
/// Save the repository configuration
|
||||
fn save_config(&self) -> Result<()> {
|
||||
// Save the modern JSON format
|
||||
let config_path = self.path.join(REPOSITORY_CONFIG_FILENAME);
|
||||
let config_data = serde_json::to_string_pretty(&self.config)?;
|
||||
fs::write(config_path, config_data)?;
|
||||
|
||||
// Save the legacy INI format for backward compatibility
|
||||
self.save_legacy_config()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -1348,6 +1379,13 @@ impl WritableRepository for FileBackend {
|
|||
fs::create_dir_all(Self::construct_catalog_path(&self.path, publisher))?;
|
||||
fs::create_dir_all(Self::construct_package_dir(&self.path, publisher, ""))?;
|
||||
|
||||
// Create the publisher directory if it doesn't exist
|
||||
let publisher_dir = self.path.join("publisher").join(publisher);
|
||||
fs::create_dir_all(&publisher_dir)?;
|
||||
|
||||
// Create the pub.p5i file for backward compatibility
|
||||
self.create_pub_p5i_file(publisher)?;
|
||||
|
||||
// Set as the default publisher if no default publisher is set
|
||||
if self.config.default_publisher.is_none() {
|
||||
self.config.default_publisher = Some(publisher.to_string());
|
||||
|
|
@ -1513,6 +1551,81 @@ impl WritableRepository for FileBackend {
|
|||
}
|
||||
|
||||
impl FileBackend {
|
||||
/// Save the legacy pkg5.repository INI file for backward compatibility
|
||||
pub fn save_legacy_config(&self) -> Result<()> {
|
||||
let legacy_config_path = self.path.join("pkg5.repository");
|
||||
let mut conf = Ini::new();
|
||||
|
||||
// Add publisher section with default publisher
|
||||
if let Some(default_publisher) = &self.config.default_publisher {
|
||||
conf.with_section(Some("publisher"))
|
||||
.set("prefix", default_publisher);
|
||||
}
|
||||
|
||||
// Add repository section with version and default values
|
||||
conf.with_section(Some("repository"))
|
||||
.set("version", "4")
|
||||
.set("trust-anchor-directory", "/etc/certs/CA/")
|
||||
.set("signature-required-names", "[]")
|
||||
.set("check-certificate-revocation", "False");
|
||||
|
||||
// Add CONFIGURATION section with version
|
||||
conf.with_section(Some("CONFIGURATION"))
|
||||
.set("version", "4");
|
||||
|
||||
// Write the INI file
|
||||
conf.write_to_file(legacy_config_path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create a pub.p5i file for a publisher for backward compatibility
|
||||
///
|
||||
/// Format: base_path/publisher/publisher_name/pub.p5i
|
||||
fn create_pub_p5i_file(&self, publisher: &str) -> Result<()> {
|
||||
// Define the structure for the pub.p5i file
|
||||
#[derive(serde::Serialize)]
|
||||
struct P5iPublisherInfo {
|
||||
alias: Option<String>,
|
||||
name: String,
|
||||
packages: Vec<String>,
|
||||
repositories: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct P5iFile {
|
||||
packages: Vec<String>,
|
||||
publishers: Vec<P5iPublisherInfo>,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
// Create the publisher info
|
||||
let publisher_info = P5iPublisherInfo {
|
||||
alias: None,
|
||||
name: publisher.to_string(),
|
||||
packages: Vec::new(),
|
||||
repositories: Vec::new(),
|
||||
};
|
||||
|
||||
// Create the p5i file content
|
||||
let p5i_content = P5iFile {
|
||||
packages: Vec::new(),
|
||||
publishers: vec![publisher_info],
|
||||
version: 1,
|
||||
};
|
||||
|
||||
// Serialize to JSON
|
||||
let json_content = serde_json::to_string_pretty(&p5i_content)?;
|
||||
|
||||
// Create the path for the pub.p5i file
|
||||
let pub_p5i_path = self.path.join("publisher").join(publisher).join("pub.p5i");
|
||||
|
||||
// Write the file
|
||||
fs::write(pub_p5i_path, json_content)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper method to construct a catalog path consistently
|
||||
///
|
||||
/// Format: base_path/publisher/publisher_name/catalog
|
||||
|
|
|
|||
|
|
@ -206,6 +206,20 @@ mod tests {
|
|||
assert!(repo.config.publishers.contains(&"example.com".to_string()));
|
||||
assert!(FileBackend::construct_catalog_path(&repo_path, "example.com").exists());
|
||||
assert!(FileBackend::construct_package_dir(&repo_path, "example.com", "").exists());
|
||||
|
||||
// Check that the pub.p5i file was created for backward compatibility
|
||||
let pub_p5i_path = repo_path.join("publisher").join("example.com").join("pub.p5i");
|
||||
assert!(pub_p5i_path.exists(), "pub.p5i file should be created for backward compatibility");
|
||||
|
||||
// Verify the content of the pub.p5i file
|
||||
let pub_p5i_content = fs::read_to_string(&pub_p5i_path).unwrap();
|
||||
let pub_p5i_json: serde_json::Value = serde_json::from_str(&pub_p5i_content).unwrap();
|
||||
|
||||
// Check the structure of the pub.p5i file
|
||||
assert_eq!(pub_p5i_json["version"], 1);
|
||||
assert!(pub_p5i_json["packages"].is_array());
|
||||
assert!(pub_p5i_json["publishers"].is_array());
|
||||
assert_eq!(pub_p5i_json["publishers"][0]["name"], "example.com");
|
||||
|
||||
// Clean up
|
||||
cleanup_test_dir(&test_dir);
|
||||
|
|
@ -432,4 +446,91 @@ mod tests {
|
|||
// Clean up
|
||||
cleanup_test_dir(&test_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_transaction_pub_p5i_creation() {
|
||||
// Run the setup script to prepare the test environment
|
||||
let (prototype_dir, manifest_dir) = run_setup_script();
|
||||
|
||||
// Create a test directory
|
||||
let test_dir = create_test_dir("transaction_pub_p5i");
|
||||
let repo_path = test_dir.join("repo");
|
||||
|
||||
// Create a repository
|
||||
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
|
||||
|
||||
// Create a new publisher through a transaction
|
||||
let publisher = "transaction_test";
|
||||
|
||||
// Start a transaction
|
||||
let mut transaction = repo.begin_transaction().unwrap();
|
||||
|
||||
// Set the publisher for the transaction
|
||||
transaction.set_publisher(publisher);
|
||||
|
||||
// Add a simple manifest to the transaction
|
||||
let manifest_path = manifest_dir.join("example.p5m");
|
||||
let manifest = Manifest::parse_file(&manifest_path).unwrap();
|
||||
transaction.update_manifest(manifest);
|
||||
|
||||
// Commit the transaction
|
||||
transaction.commit().unwrap();
|
||||
|
||||
// Check that the pub.p5i file was created for the new publisher
|
||||
let pub_p5i_path = repo_path.join("publisher").join(publisher).join("pub.p5i");
|
||||
assert!(pub_p5i_path.exists(), "pub.p5i file should be created for new publisher in transaction");
|
||||
|
||||
// Verify the content of the pub.p5i file
|
||||
let pub_p5i_content = fs::read_to_string(&pub_p5i_path).unwrap();
|
||||
let pub_p5i_json: serde_json::Value = serde_json::from_str(&pub_p5i_content).unwrap();
|
||||
|
||||
// Check the structure of the pub.p5i file
|
||||
assert_eq!(pub_p5i_json["version"], 1);
|
||||
assert!(pub_p5i_json["packages"].is_array());
|
||||
assert!(pub_p5i_json["publishers"].is_array());
|
||||
assert_eq!(pub_p5i_json["publishers"][0]["name"], publisher);
|
||||
|
||||
// Clean up
|
||||
cleanup_test_dir(&test_dir);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_legacy_pkg5_repository_creation() {
|
||||
// Create a test directory
|
||||
let test_dir = create_test_dir("legacy_pkg5_repository");
|
||||
let repo_path = test_dir.join("repo");
|
||||
|
||||
// Create a repository
|
||||
let mut repo = FileBackend::create(&repo_path, RepositoryVersion::V4).unwrap();
|
||||
|
||||
// Add a publisher
|
||||
let publisher = "openindiana.org";
|
||||
repo.add_publisher(publisher).unwrap();
|
||||
|
||||
// Set as default publisher
|
||||
repo.set_default_publisher(publisher).unwrap();
|
||||
|
||||
// Check that the pkg5.repository file was created
|
||||
let pkg5_repo_path = repo_path.join("pkg5.repository");
|
||||
assert!(pkg5_repo_path.exists(), "pkg5.repository file should be created for backward compatibility");
|
||||
|
||||
// Verify the content of the pkg5.repository file
|
||||
let pkg5_content = fs::read_to_string(&pkg5_repo_path).unwrap();
|
||||
|
||||
// Print the content for debugging
|
||||
println!("pkg5.repository content:\n{}", pkg5_content);
|
||||
|
||||
// Check that the file contains the expected sections and values
|
||||
assert!(pkg5_content.contains("[publisher]"));
|
||||
assert!(pkg5_content.contains("prefix=openindiana.org"));
|
||||
assert!(pkg5_content.contains("[repository]"));
|
||||
assert!(pkg5_content.contains("version=4"));
|
||||
assert!(pkg5_content.contains("trust-anchor-directory=/etc/certs/CA/"));
|
||||
assert!(pkg5_content.contains("signature-required-names=[]"));
|
||||
assert!(pkg5_content.contains("check-certificate-revocation=False"));
|
||||
assert!(pkg5_content.contains("[CONFIGURATION]"));
|
||||
|
||||
// Clean up
|
||||
cleanup_test_dir(&test_dir);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue