feat: add support for renamed package updates and ABI-breaking flags
- Introduced `real_name` field in `InstalledPackageRecord` and `PackageInfo` to handle renamed packages. - Added `abi_breaking` field to manage versioned shared libraries during renamed updates. - Updated database schema to include `real_name` and `abi_breaking` columns. - Enhanced package registration logic to support replacement of renamed packages while retaining specified files and directories. - Modified various functions and tests to accommodate the new fields and ensure backward compatibility. - Updated TOML serialization to include `real_name` and `abi_breaking` in package metadata.
This commit is contained in:
+175
-17
@@ -21,14 +21,57 @@ fn verbose_remove_output() -> bool {
|
||||
/// Installed package row from the local package database.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct InstalledPackageRecord {
|
||||
/// Installed package name.
|
||||
pub name: String,
|
||||
/// Stable package stream name used for renamed updates.
|
||||
pub real_name: Option<String>,
|
||||
/// Installed package version.
|
||||
pub version: String,
|
||||
/// Installed package revision.
|
||||
pub revision: u32,
|
||||
/// Whether renamed updates should retain versioned shared libraries.
|
||||
pub abi_breaking: bool,
|
||||
/// Package completion timestamp if known.
|
||||
pub completed_at: Option<i64>,
|
||||
}
|
||||
|
||||
impl InstalledPackageRecord {
|
||||
/// Return the stable package stream name, defaulting to the package name.
|
||||
pub fn effective_real_name(&self) -> &str {
|
||||
self.real_name.as_deref().unwrap_or(&self.name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Rename-aware replacement metadata applied while registering a new package.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct PackageReplacement {
|
||||
/// Installed package name being replaced.
|
||||
pub old_name: String,
|
||||
/// Subset of old-package files to keep installed and owned by the old package.
|
||||
pub retained_files: Vec<String>,
|
||||
/// Subset of old-package directories to keep owned by the old package.
|
||||
pub retained_directories: Vec<String>,
|
||||
}
|
||||
|
||||
impl PackageReplacement {
|
||||
/// Return true when the replaced package remains installed after registration.
|
||||
pub fn retains_old_package(&self) -> bool {
|
||||
!self.retained_files.is_empty() || !self.retained_directories.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize database and register a package
|
||||
pub fn register_package(db_path: &Path, spec: &PackageSpec, destdir: &Path) -> Result<()> {
|
||||
register_package_with_replacement(db_path, spec, destdir, None)
|
||||
}
|
||||
|
||||
/// Initialize database and register a package, optionally replacing a renamed predecessor.
|
||||
pub fn register_package_with_replacement(
|
||||
db_path: &Path,
|
||||
spec: &PackageSpec,
|
||||
destdir: &Path,
|
||||
replacement: Option<&PackageReplacement>,
|
||||
) -> Result<()> {
|
||||
// Create parent directory (auto-create db dir if missing)
|
||||
if let Some(parent) = db_path.parent() {
|
||||
fs::create_dir_all(parent)?;
|
||||
@@ -43,24 +86,70 @@ pub fn register_package(db_path: &Path, spec: &PackageSpec, destdir: &Path) -> R
|
||||
// Generate manifest with files and directories
|
||||
let manifest = staging::generate_manifest_with_dirs(destdir)?;
|
||||
|
||||
if let Some(replacement) = replacement {
|
||||
if replacement.old_name == spec.package.name {
|
||||
anyhow::bail!(
|
||||
"Replacement package '{}' cannot match new package name",
|
||||
spec.package.name
|
||||
);
|
||||
}
|
||||
|
||||
let old_pkg_id: i64 = tx
|
||||
.query_row(
|
||||
"SELECT id FROM packages WHERE name = ?1",
|
||||
params![replacement.old_name],
|
||||
|row| row.get(0),
|
||||
)
|
||||
.with_context(|| format!("Package '{}' not found", replacement.old_name))?;
|
||||
|
||||
if replacement.retains_old_package() {
|
||||
tx.execute(
|
||||
"DELETE FROM files WHERE package_id = ?1",
|
||||
params![old_pkg_id],
|
||||
)?;
|
||||
tx.execute(
|
||||
"DELETE FROM directories WHERE package_id = ?1",
|
||||
params![old_pkg_id],
|
||||
)?;
|
||||
for file in &replacement.retained_files {
|
||||
tx.execute(
|
||||
"INSERT INTO files (package_id, path) VALUES (?1, ?2)",
|
||||
params![old_pkg_id, file],
|
||||
)?;
|
||||
}
|
||||
for directory in &replacement.retained_directories {
|
||||
tx.execute(
|
||||
"INSERT INTO directories (package_id, path) VALUES (?1, ?2)",
|
||||
params![old_pkg_id, directory],
|
||||
)?;
|
||||
}
|
||||
} else {
|
||||
delete_package_rows_tx(&tx, old_pkg_id)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert/update package without changing its primary key (UPSERT keeps the existing row).
|
||||
tx.execute(
|
||||
"INSERT INTO packages (name, version, revision, description, homepage, license, completed_at)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
|
||||
"INSERT INTO packages (name, real_name, version, revision, description, homepage, license, abi_breaking, completed_at)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)
|
||||
ON CONFLICT(name) DO UPDATE SET
|
||||
real_name=excluded.real_name,
|
||||
version=excluded.version,
|
||||
revision=excluded.revision,
|
||||
description=excluded.description,
|
||||
homepage=excluded.homepage,
|
||||
license=excluded.license,
|
||||
abi_breaking=excluded.abi_breaking,
|
||||
completed_at=excluded.completed_at",
|
||||
params![
|
||||
spec.package.name,
|
||||
spec.package.real_name,
|
||||
spec.package.version,
|
||||
spec.package.revision,
|
||||
spec.package.description,
|
||||
spec.package.homepage,
|
||||
format_licenses(&spec.package.license),
|
||||
spec.package.abi_breaking,
|
||||
completed_at,
|
||||
],
|
||||
)?;
|
||||
@@ -330,16 +419,7 @@ pub fn remove_package(db_path: &Path, name: &str, rootfs: &Path) -> Result<()> {
|
||||
}
|
||||
|
||||
// Remove from database
|
||||
conn.execute("DELETE FROM files WHERE package_id = ?1", params![pkg_id])?;
|
||||
conn.execute(
|
||||
"DELETE FROM directories WHERE package_id = ?1",
|
||||
params![pkg_id],
|
||||
)?;
|
||||
conn.execute(
|
||||
"DELETE FROM provides WHERE package_id = ?1",
|
||||
params![pkg_id],
|
||||
)?;
|
||||
conn.execute("DELETE FROM packages WHERE id = ?1", params![pkg_id])?;
|
||||
delete_package_rows(&conn, pkg_id)?;
|
||||
|
||||
crate::log_info!(
|
||||
"Removed {} files and {} directories",
|
||||
@@ -422,11 +502,13 @@ fn init_db(conn: &Connection) -> Result<()> {
|
||||
CREATE TABLE IF NOT EXISTS packages (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
real_name TEXT,
|
||||
version TEXT NOT NULL,
|
||||
revision INTEGER NOT NULL DEFAULT 1,
|
||||
description TEXT,
|
||||
homepage TEXT,
|
||||
license TEXT,
|
||||
abi_breaking INTEGER NOT NULL DEFAULT 0,
|
||||
completed_at INTEGER
|
||||
);
|
||||
|
||||
@@ -460,6 +542,8 @@ fn init_db(conn: &Connection) -> Result<()> {
|
||||
",
|
||||
)?;
|
||||
ensure_packages_completed_at_column(conn)?;
|
||||
ensure_packages_real_name_column(conn)?;
|
||||
ensure_packages_abi_breaking_column(conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -481,6 +565,73 @@ fn ensure_packages_completed_at_column(conn: &Connection) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_packages_real_name_column(conn: &Connection) -> Result<()> {
|
||||
let has_real_name: bool = conn
|
||||
.query_row(
|
||||
"SELECT COUNT(*) FROM pragma_table_info('packages') WHERE name = 'real_name'",
|
||||
[],
|
||||
|row| {
|
||||
let count: i64 = row.get(0)?;
|
||||
Ok(count > 0)
|
||||
},
|
||||
)
|
||||
.context("Failed to inspect installed package DB schema")?;
|
||||
if !has_real_name {
|
||||
conn.execute("ALTER TABLE packages ADD COLUMN real_name TEXT", [])
|
||||
.context("Failed to add real_name column to installed package DB")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_packages_abi_breaking_column(conn: &Connection) -> Result<()> {
|
||||
let has_abi_breaking: bool = conn
|
||||
.query_row(
|
||||
"SELECT COUNT(*) FROM pragma_table_info('packages') WHERE name = 'abi_breaking'",
|
||||
[],
|
||||
|row| {
|
||||
let count: i64 = row.get(0)?;
|
||||
Ok(count > 0)
|
||||
},
|
||||
)
|
||||
.context("Failed to inspect installed package DB schema")?;
|
||||
if !has_abi_breaking {
|
||||
conn.execute(
|
||||
"ALTER TABLE packages ADD COLUMN abi_breaking INTEGER NOT NULL DEFAULT 0",
|
||||
[],
|
||||
)
|
||||
.context("Failed to add abi_breaking column to installed package DB")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete_package_rows(conn: &Connection, pkg_id: i64) -> Result<()> {
|
||||
conn.execute("DELETE FROM files WHERE package_id = ?1", params![pkg_id])?;
|
||||
conn.execute(
|
||||
"DELETE FROM directories WHERE package_id = ?1",
|
||||
params![pkg_id],
|
||||
)?;
|
||||
conn.execute(
|
||||
"DELETE FROM provides WHERE package_id = ?1",
|
||||
params![pkg_id],
|
||||
)?;
|
||||
conn.execute("DELETE FROM packages WHERE id = ?1", params![pkg_id])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete_package_rows_tx(tx: &rusqlite::Transaction<'_>, pkg_id: i64) -> Result<()> {
|
||||
tx.execute("DELETE FROM files WHERE package_id = ?1", params![pkg_id])?;
|
||||
tx.execute(
|
||||
"DELETE FROM directories WHERE package_id = ?1",
|
||||
params![pkg_id],
|
||||
)?;
|
||||
tx.execute(
|
||||
"DELETE FROM provides WHERE package_id = ?1",
|
||||
params![pkg_id],
|
||||
)?;
|
||||
tx.execute("DELETE FROM packages WHERE id = ?1", params![pkg_id])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn package_completed_at(destdir: &Path) -> Result<Option<i64>> {
|
||||
let metadata_path = destdir.join(".metadata.toml");
|
||||
if let Some(completed_at) =
|
||||
@@ -597,14 +748,19 @@ pub fn list_installed_package_records(db_path: &Path) -> Result<Vec<InstalledPac
|
||||
|
||||
let conn = Connection::open(db_path)?;
|
||||
init_db(&conn)?;
|
||||
let mut stmt =
|
||||
conn.prepare("SELECT name, version, revision, completed_at FROM packages ORDER BY name")?;
|
||||
let mut stmt = conn.prepare(
|
||||
"SELECT name, real_name, version, revision, abi_breaking, completed_at
|
||||
FROM packages
|
||||
ORDER BY name",
|
||||
)?;
|
||||
let rows = stmt.query_map([], |row| {
|
||||
Ok(InstalledPackageRecord {
|
||||
name: row.get(0)?,
|
||||
version: row.get(1)?,
|
||||
revision: row.get::<_, i64>(2)? as u32,
|
||||
completed_at: row.get(3)?,
|
||||
real_name: row.get(1)?,
|
||||
version: row.get(2)?,
|
||||
revision: row.get::<_, i64>(3)? as u32,
|
||||
abi_breaking: row.get(4)?,
|
||||
completed_at: row.get(5)?,
|
||||
})
|
||||
})?;
|
||||
Ok(rows.filter_map(|row| row.ok()).collect())
|
||||
@@ -708,10 +864,12 @@ mod tests {
|
||||
PackageSpec {
|
||||
package: PackageInfo {
|
||||
name: name.into(),
|
||||
real_name: None,
|
||||
version: version.into(),
|
||||
revision: 1,
|
||||
description: "d".into(),
|
||||
homepage: "h".into(),
|
||||
abi_breaking: false,
|
||||
license: vec!["MIT".into()],
|
||||
},
|
||||
packages: Vec::new(),
|
||||
|
||||
+117
-24
@@ -73,8 +73,10 @@ impl<R: Read> Read for HashingReader<R> {
|
||||
|
||||
struct IndexedPackage {
|
||||
name: String,
|
||||
real_name: Option<String>,
|
||||
version: String,
|
||||
revision: u32,
|
||||
abi_breaking: bool,
|
||||
completed_at: Option<i64>,
|
||||
description: Option<String>,
|
||||
homepage: Option<String>,
|
||||
@@ -109,8 +111,10 @@ pub struct BinaryRepoSearchHit {
|
||||
pub struct BinaryRepoPackageRecord {
|
||||
pub repo_name: String,
|
||||
pub name: String,
|
||||
pub real_name: Option<String>,
|
||||
pub version: String,
|
||||
pub revision: u32,
|
||||
pub abi_breaking: bool,
|
||||
pub completed_at: Option<i64>,
|
||||
pub filename: String,
|
||||
pub size: u64,
|
||||
@@ -125,6 +129,13 @@ pub struct BinaryRepoPackageRecord {
|
||||
pub optional_dependencies: Vec<String>,
|
||||
}
|
||||
|
||||
impl BinaryRepoPackageRecord {
|
||||
/// Return the stable package stream name, defaulting to the package name.
|
||||
pub fn effective_real_name(&self) -> &str {
|
||||
self.real_name.as_deref().unwrap_or(&self.name)
|
||||
}
|
||||
}
|
||||
|
||||
/// Local cache paths for a binary package archive and its detached signature.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct BinaryRepoCachedArchive {
|
||||
@@ -283,8 +294,10 @@ impl RepoManager {
|
||||
"CREATE TABLE packages (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
real_name TEXT,
|
||||
version TEXT NOT NULL,
|
||||
revision INTEGER NOT NULL,
|
||||
abi_breaking INTEGER NOT NULL DEFAULT 0,
|
||||
completed_at INTEGER,
|
||||
description TEXT,
|
||||
homepage TEXT,
|
||||
@@ -346,8 +359,10 @@ impl RepoManager {
|
||||
let mut hashing_reader = HashingReader::new(file);
|
||||
|
||||
let mut name = String::new();
|
||||
let mut real_name = None;
|
||||
let mut version = String::new();
|
||||
let mut revision = 1;
|
||||
let mut abi_breaking = false;
|
||||
let mut completed_at = path_modified_unix_timestamp(pkg_path)?;
|
||||
let mut description = None;
|
||||
let mut homepage = None;
|
||||
@@ -378,6 +393,10 @@ impl RepoManager {
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
real_name = metadata
|
||||
.get("real_name")
|
||||
.and_then(|v| v.as_str())
|
||||
.map(String::from);
|
||||
version = metadata
|
||||
.get("version")
|
||||
.and_then(|v| v.as_str())
|
||||
@@ -387,6 +406,10 @@ impl RepoManager {
|
||||
.get("revision")
|
||||
.and_then(|v| v.as_integer())
|
||||
.unwrap_or(1) as u32;
|
||||
abi_breaking = metadata
|
||||
.get("abi_breaking")
|
||||
.and_then(|v| v.as_bool())
|
||||
.unwrap_or(false);
|
||||
completed_at =
|
||||
metadata_time::parse_completed_at_value(&metadata).or(completed_at);
|
||||
description = metadata
|
||||
@@ -469,8 +492,10 @@ impl RepoManager {
|
||||
|
||||
Ok(IndexedPackage {
|
||||
name,
|
||||
real_name,
|
||||
version,
|
||||
revision,
|
||||
abi_breaking,
|
||||
completed_at,
|
||||
description,
|
||||
homepage,
|
||||
@@ -490,8 +515,10 @@ impl RepoManager {
|
||||
fn insert_indexed_package(&self, conn: &mut Connection, indexed: IndexedPackage) -> Result<()> {
|
||||
let IndexedPackage {
|
||||
name,
|
||||
real_name,
|
||||
version,
|
||||
revision,
|
||||
abi_breaking,
|
||||
completed_at,
|
||||
description,
|
||||
homepage,
|
||||
@@ -509,12 +536,14 @@ impl RepoManager {
|
||||
|
||||
// Insert into database
|
||||
conn.execute(
|
||||
"INSERT INTO packages (name, version, revision, completed_at, description, homepage, license, filename, size, sha256, sha512)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11)",
|
||||
"INSERT INTO packages (name, real_name, version, revision, abi_breaking, completed_at, description, homepage, license, filename, size, sha256, sha512)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13)",
|
||||
params![
|
||||
name,
|
||||
real_name,
|
||||
version,
|
||||
revision as i64,
|
||||
abi_breaking,
|
||||
completed_at,
|
||||
description,
|
||||
homepage,
|
||||
@@ -1620,12 +1649,24 @@ fn find_cached_binary_repo_packages(
|
||||
} else {
|
||||
"NULL"
|
||||
};
|
||||
let real_name_expr = if repo_packages_have_real_name(&conn)? {
|
||||
"p.real_name"
|
||||
} else {
|
||||
"NULL"
|
||||
};
|
||||
let abi_breaking_expr = if repo_packages_have_abi_breaking(&conn)? {
|
||||
"p.abi_breaking"
|
||||
} else {
|
||||
"0"
|
||||
};
|
||||
let sql = format!(
|
||||
"SELECT
|
||||
p.id,
|
||||
p.name,
|
||||
{real_name_expr},
|
||||
p.version,
|
||||
p.revision,
|
||||
{abi_breaking_expr},
|
||||
{completed_at_expr},
|
||||
p.filename,
|
||||
p.size,
|
||||
@@ -1654,16 +1695,18 @@ fn find_cached_binary_repo_packages(
|
||||
BinaryRepoPackageRecord {
|
||||
repo_name: repo_name.to_string(),
|
||||
name: row.get(1)?,
|
||||
version: row.get(2)?,
|
||||
revision: row.get::<_, i64>(3)? as u32,
|
||||
completed_at: row.get(4)?,
|
||||
filename: row.get(5)?,
|
||||
size: row.get::<_, i64>(6)? as u64,
|
||||
sha256: row.get(7)?,
|
||||
sha512: row.get(8)?,
|
||||
description: row.get(9)?,
|
||||
homepage: row.get(10)?,
|
||||
license: row.get(11)?,
|
||||
real_name: row.get(2)?,
|
||||
version: row.get(3)?,
|
||||
revision: row.get::<_, i64>(4)? as u32,
|
||||
abi_breaking: row.get(5)?,
|
||||
completed_at: row.get(6)?,
|
||||
filename: row.get(7)?,
|
||||
size: row.get::<_, i64>(8)? as u64,
|
||||
sha256: row.get(9)?,
|
||||
sha512: row.get(10)?,
|
||||
description: row.get(11)?,
|
||||
homepage: row.get(12)?,
|
||||
license: row.get(13)?,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
@@ -1696,12 +1739,24 @@ fn list_cached_binary_repo_packages(
|
||||
} else {
|
||||
"NULL"
|
||||
};
|
||||
let real_name_expr = if repo_packages_have_real_name(&conn)? {
|
||||
"p.real_name"
|
||||
} else {
|
||||
"NULL"
|
||||
};
|
||||
let abi_breaking_expr = if repo_packages_have_abi_breaking(&conn)? {
|
||||
"p.abi_breaking"
|
||||
} else {
|
||||
"0"
|
||||
};
|
||||
let sql = format!(
|
||||
"SELECT
|
||||
p.id,
|
||||
p.name,
|
||||
{real_name_expr},
|
||||
p.version,
|
||||
p.revision,
|
||||
{abi_breaking_expr},
|
||||
{completed_at_expr},
|
||||
p.filename,
|
||||
p.size,
|
||||
@@ -1722,16 +1777,18 @@ fn list_cached_binary_repo_packages(
|
||||
BinaryRepoPackageRecord {
|
||||
repo_name: repo_name.to_string(),
|
||||
name: row.get(1)?,
|
||||
version: row.get(2)?,
|
||||
revision: row.get::<_, i64>(3)? as u32,
|
||||
completed_at: row.get(4)?,
|
||||
filename: row.get(5)?,
|
||||
size: row.get::<_, i64>(6)? as u64,
|
||||
sha256: row.get(7)?,
|
||||
sha512: row.get(8)?,
|
||||
description: row.get(9)?,
|
||||
homepage: row.get(10)?,
|
||||
license: row.get(11)?,
|
||||
real_name: row.get(2)?,
|
||||
version: row.get(3)?,
|
||||
revision: row.get::<_, i64>(4)? as u32,
|
||||
abi_breaking: row.get(5)?,
|
||||
completed_at: row.get(6)?,
|
||||
filename: row.get(7)?,
|
||||
size: row.get::<_, i64>(8)? as u64,
|
||||
sha256: row.get(9)?,
|
||||
sha512: row.get(10)?,
|
||||
description: row.get(11)?,
|
||||
homepage: row.get(12)?,
|
||||
license: row.get(13)?,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
@@ -1764,6 +1821,30 @@ fn repo_packages_have_completed_at(conn: &Connection) -> Result<bool> {
|
||||
.context("Failed to inspect binary repo DB schema")
|
||||
}
|
||||
|
||||
fn repo_packages_have_real_name(conn: &Connection) -> Result<bool> {
|
||||
conn.query_row(
|
||||
"SELECT COUNT(*) FROM pragma_table_info('packages') WHERE name = 'real_name'",
|
||||
[],
|
||||
|row| {
|
||||
let count: i64 = row.get(0)?;
|
||||
Ok(count > 0)
|
||||
},
|
||||
)
|
||||
.context("Failed to inspect binary repo DB schema")
|
||||
}
|
||||
|
||||
fn repo_packages_have_abi_breaking(conn: &Connection) -> Result<bool> {
|
||||
conn.query_row(
|
||||
"SELECT COUNT(*) FROM pragma_table_info('packages') WHERE name = 'abi_breaking'",
|
||||
[],
|
||||
|row| {
|
||||
let count: i64 = row.get(0)?;
|
||||
Ok(count > 0)
|
||||
},
|
||||
)
|
||||
.context("Failed to inspect binary repo DB schema")
|
||||
}
|
||||
|
||||
fn path_modified_unix_timestamp(path: &Path) -> Result<Option<i64>> {
|
||||
let metadata = fs::metadata(path)
|
||||
.with_context(|| format!("Failed to read metadata for {}", path.display()))?;
|
||||
@@ -2350,8 +2431,10 @@ mod tests {
|
||||
|
||||
let metadata = r#"
|
||||
name = "test"
|
||||
real_name = "icu"
|
||||
version = "1.0"
|
||||
revision = 1
|
||||
abi_breaking = true
|
||||
description = "test description"
|
||||
homepage = "https://example.com"
|
||||
license = "MIT"
|
||||
@@ -2385,8 +2468,10 @@ optional = []
|
||||
|
||||
type PackageRow = (
|
||||
String,
|
||||
Option<String>,
|
||||
String,
|
||||
i64,
|
||||
i64,
|
||||
Option<String>,
|
||||
Option<String>,
|
||||
Option<String>,
|
||||
@@ -2394,9 +2479,9 @@ optional = []
|
||||
String,
|
||||
);
|
||||
|
||||
let (name, version, revision, desc, home, lic, sha256, sha512): PackageRow = conn
|
||||
let (name, real_name, version, revision, abi_breaking, desc, home, lic, sha256, sha512): PackageRow = conn
|
||||
.query_row(
|
||||
"SELECT name, version, revision, description, homepage, license, sha256, sha512 FROM packages",
|
||||
"SELECT name, real_name, version, revision, abi_breaking, description, homepage, license, sha256, sha512 FROM packages",
|
||||
[],
|
||||
|r| {
|
||||
Ok((
|
||||
@@ -2408,14 +2493,18 @@ optional = []
|
||||
r.get(5)?,
|
||||
r.get(6)?,
|
||||
r.get(7)?,
|
||||
r.get(8)?,
|
||||
r.get(9)?,
|
||||
))
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(name, "test");
|
||||
assert_eq!(real_name, Some("icu".to_string()));
|
||||
assert_eq!(version, "1.0");
|
||||
assert_eq!(revision, 1);
|
||||
assert_eq!(abi_breaking, 1);
|
||||
assert_eq!(desc, Some("test description".to_string()));
|
||||
assert_eq!(home, Some("https://example.com".to_string()));
|
||||
assert_eq!(lic, Some("MIT".to_string()));
|
||||
@@ -2651,8 +2740,10 @@ revision = 1
|
||||
let rec = BinaryRepoPackageRecord {
|
||||
repo_name: "repo".into(),
|
||||
name: "pkg".into(),
|
||||
real_name: None,
|
||||
version: "1.0".into(),
|
||||
revision: 1,
|
||||
abi_breaking: false,
|
||||
completed_at: None,
|
||||
filename: "pkg.depot.pkg.tar.zst".into(),
|
||||
size: 7,
|
||||
@@ -2687,8 +2778,10 @@ revision = 1
|
||||
BinaryRepoPackageRecord {
|
||||
repo_name: "repo".into(),
|
||||
name: "pkg".into(),
|
||||
real_name: None,
|
||||
version: "1.0".into(),
|
||||
revision: 1,
|
||||
abi_breaking: false,
|
||||
completed_at: None,
|
||||
filename: filename.to_string(),
|
||||
size: payload.len() as u64,
|
||||
|
||||
Reference in New Issue
Block a user