Implement package replacement feature across the codebase
- Introduced a new `replaces` field in various structs to support package replacements. - Updated database schema to include a `replaces` table and corresponding queries. - Modified the package index to handle replacements and ensure they take precedence over exact package names. - Enhanced the `create_source_repo_index` function to include replacement entries in the index. - Updated tests to validate the new replacement functionality, including parsing and metadata generation. - Refactored relevant functions and structures to accommodate the new `replaces` feature in package specifications and alternatives.
This commit is contained in:
+65
-1
@@ -87,6 +87,7 @@ struct IndexedPackage {
|
||||
sha512: String,
|
||||
provides: Vec<String>,
|
||||
conflicts: Vec<String>,
|
||||
replaces: Vec<String>,
|
||||
runtime_dependencies: Vec<String>,
|
||||
optional_dependencies: Vec<String>,
|
||||
archive_files: Vec<String>,
|
||||
@@ -125,6 +126,7 @@ pub struct BinaryRepoPackageRecord {
|
||||
pub license: Option<String>,
|
||||
pub provides: Vec<String>,
|
||||
pub conflicts: Vec<String>,
|
||||
pub replaces: Vec<String>,
|
||||
pub runtime_dependencies: Vec<String>,
|
||||
pub optional_dependencies: Vec<String>,
|
||||
}
|
||||
@@ -317,6 +319,11 @@ impl RepoManager {
|
||||
name TEXT NOT NULL,
|
||||
FOREIGN KEY(package_id) REFERENCES packages(id)
|
||||
);
|
||||
CREATE TABLE replaces (
|
||||
package_id INTEGER,
|
||||
name TEXT NOT NULL,
|
||||
FOREIGN KEY(package_id) REFERENCES packages(id)
|
||||
);
|
||||
CREATE TABLE dependencies (
|
||||
package_id INTEGER,
|
||||
kind TEXT NOT NULL,
|
||||
@@ -338,6 +345,7 @@ impl RepoManager {
|
||||
"CREATE INDEX idx_packages_name ON packages(name);
|
||||
CREATE INDEX idx_provides_name ON provides(name);
|
||||
CREATE INDEX idx_conflicts_name ON conflicts(name);
|
||||
CREATE INDEX idx_replaces_name ON replaces(name);
|
||||
CREATE INDEX idx_dependencies_name ON dependencies(name);
|
||||
CREATE INDEX idx_dependencies_kind ON dependencies(kind);
|
||||
CREATE INDEX idx_repo_files_path ON files(path);",
|
||||
@@ -369,6 +377,7 @@ impl RepoManager {
|
||||
let mut license = None;
|
||||
let mut provides = Vec::new();
|
||||
let mut conflicts = Vec::new();
|
||||
let mut replaces = Vec::new();
|
||||
let mut runtime_dependencies = Vec::new();
|
||||
let mut optional_dependencies = Vec::new();
|
||||
let mut archive_files = Vec::new();
|
||||
@@ -439,6 +448,14 @@ impl RepoManager {
|
||||
.map(String::from)
|
||||
.collect();
|
||||
}
|
||||
if let Some(replaces_arr) = metadata.get("replaces").and_then(|v| v.as_array())
|
||||
{
|
||||
replaces = replaces_arr
|
||||
.iter()
|
||||
.filter_map(|v| v.as_str())
|
||||
.map(String::from)
|
||||
.collect();
|
||||
}
|
||||
if let Some(runtime_arr) = metadata
|
||||
.get("dependencies")
|
||||
.and_then(|v| v.get("runtime"))
|
||||
@@ -506,6 +523,7 @@ impl RepoManager {
|
||||
sha512,
|
||||
provides,
|
||||
conflicts,
|
||||
replaces,
|
||||
runtime_dependencies,
|
||||
optional_dependencies,
|
||||
archive_files,
|
||||
@@ -529,6 +547,7 @@ impl RepoManager {
|
||||
sha512,
|
||||
provides,
|
||||
conflicts,
|
||||
replaces,
|
||||
runtime_dependencies,
|
||||
optional_dependencies,
|
||||
archive_files,
|
||||
@@ -570,6 +589,12 @@ impl RepoManager {
|
||||
params![package_id, conflict],
|
||||
)?;
|
||||
}
|
||||
for replacement in replaces {
|
||||
conn.execute(
|
||||
"INSERT INTO replaces (package_id, name) VALUES (?1, ?2)",
|
||||
params![package_id, replacement],
|
||||
)?;
|
||||
}
|
||||
|
||||
for dep in runtime_dependencies {
|
||||
conn.execute(
|
||||
@@ -1592,6 +1617,26 @@ fn query_package_conflicts(conn: &Connection, package_id: i64) -> Result<Vec<Str
|
||||
Ok(rows.filter_map(|r| r.ok()).collect())
|
||||
}
|
||||
|
||||
fn query_package_replaces(conn: &Connection, package_id: i64) -> Result<Vec<String>> {
|
||||
let has_replaces_table: bool = conn
|
||||
.query_row(
|
||||
"SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='replaces'",
|
||||
[],
|
||||
|r| {
|
||||
let n: i64 = r.get(0)?;
|
||||
Ok(n > 0)
|
||||
},
|
||||
)
|
||||
.unwrap_or(false);
|
||||
if !has_replaces_table {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
|
||||
let mut stmt = conn.prepare("SELECT name FROM replaces WHERE package_id = ?1 ORDER BY name")?;
|
||||
let rows = stmt.query_map(params![package_id], |row| row.get(0))?;
|
||||
Ok(rows.filter_map(|r| r.ok()).collect())
|
||||
}
|
||||
|
||||
fn query_package_runtime_deps(conn: &Connection, package_id: i64) -> Result<Vec<String>> {
|
||||
let has_dependencies_table: bool = conn
|
||||
.query_row(
|
||||
@@ -1677,13 +1722,26 @@ fn find_cached_binary_repo_packages(
|
||||
p.license
|
||||
FROM packages p
|
||||
WHERE lower(p.name) = lower(?1)
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM replaces rp
|
||||
WHERE rp.package_id = p.id
|
||||
AND lower(rp.name) = lower(?1)
|
||||
)
|
||||
OR EXISTS (
|
||||
SELECT 1 FROM provides pr
|
||||
WHERE pr.package_id = p.id
|
||||
AND lower(pr.name) = lower(?1)
|
||||
)
|
||||
ORDER BY
|
||||
CASE WHEN lower(p.name) = lower(?1) THEN 0 ELSE 1 END,
|
||||
CASE
|
||||
WHEN EXISTS (
|
||||
SELECT 1 FROM replaces rp
|
||||
WHERE rp.package_id = p.id
|
||||
AND lower(rp.name) = lower(?1)
|
||||
) THEN 0
|
||||
WHEN lower(p.name) = lower(?1) THEN 1
|
||||
ELSE 2
|
||||
END,
|
||||
p.name ASC"
|
||||
);
|
||||
let mut stmt = conn.prepare(&sql)?;
|
||||
@@ -1709,6 +1767,7 @@ fn find_cached_binary_repo_packages(
|
||||
license: row.get(13)?,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
replaces: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
optional_dependencies: Vec::new(),
|
||||
},
|
||||
@@ -1720,6 +1779,7 @@ fn find_cached_binary_repo_packages(
|
||||
let (package_id, mut rec) = row?;
|
||||
rec.provides = query_package_provides(&conn, package_id)?;
|
||||
rec.conflicts = query_package_conflicts(&conn, package_id)?;
|
||||
rec.replaces = query_package_replaces(&conn, package_id)?;
|
||||
rec.runtime_dependencies = query_package_runtime_deps(&conn, package_id)?;
|
||||
rec.optional_dependencies = query_package_optional_deps(&conn, package_id)?;
|
||||
out.push(rec);
|
||||
@@ -1791,6 +1851,7 @@ fn list_cached_binary_repo_packages(
|
||||
license: row.get(13)?,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
replaces: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
optional_dependencies: Vec::new(),
|
||||
},
|
||||
@@ -1802,6 +1863,7 @@ fn list_cached_binary_repo_packages(
|
||||
let (package_id, mut rec) = row?;
|
||||
rec.provides = query_package_provides(&conn, package_id)?;
|
||||
rec.conflicts = query_package_conflicts(&conn, package_id)?;
|
||||
rec.replaces = query_package_replaces(&conn, package_id)?;
|
||||
rec.runtime_dependencies = query_package_runtime_deps(&conn, package_id)?;
|
||||
rec.optional_dependencies = query_package_optional_deps(&conn, package_id)?;
|
||||
out.push(rec);
|
||||
@@ -2754,6 +2816,7 @@ revision = 1
|
||||
license: None,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
replaces: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
optional_dependencies: Vec::new(),
|
||||
};
|
||||
@@ -2792,6 +2855,7 @@ revision = 1
|
||||
license: None,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
replaces: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
optional_dependencies: Vec::new(),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user