diff --git a/crates/soar-core/src/database/models.rs b/crates/soar-core/src/database/models.rs index d25e3d3d..d2ec2996 100644 --- a/crates/soar-core/src/database/models.rs +++ b/crates/soar-core/src/database/models.rs @@ -55,10 +55,6 @@ pub struct Package { pub build_id: Option, pub build_date: Option, pub build_action: Option, - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_script: Option, - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_log: Option, pub provides: Option>, pub snapshots: Option>, pub repology: Option>, @@ -261,7 +257,6 @@ impl From for InstalledPackage { /// Conversion from soar-db metadata Package to soar-core Package. impl From for Package { - #[allow(deprecated)] fn from(pkg: soar_db::models::metadata::Package) -> Self { Self { id: pkg.id as u64, @@ -294,8 +289,6 @@ impl From for Package { build_id: pkg.build_id, build_date: pkg.build_date, build_action: pkg.build_action, - build_script: pkg.build_script, - build_log: pkg.build_log, provides: pkg.provides, snapshots: pkg.snapshots, repology: None, diff --git a/crates/soar-db/migrations/metadata/2026-10-19-000200-0000_drop_build_fields/down.sql b/crates/soar-db/migrations/metadata/2026-10-19-000200-0000_drop_build_fields/down.sql new file mode 100644 index 00000000..6e0a6578 --- /dev/null +++ b/crates/soar-db/migrations/metadata/2026-10-19-000200-0000_drop_build_fields/down.sql @@ -0,0 +1,2 @@ +ALTER TABLE packages ADD COLUMN build_script TEXT; +ALTER TABLE packages ADD COLUMN build_log TEXT; diff --git a/crates/soar-db/migrations/metadata/2026-10-19-000200-0000_drop_build_fields/up.sql b/crates/soar-db/migrations/metadata/2026-10-19-000200-0000_drop_build_fields/up.sql new file mode 100644 index 00000000..950a615c --- /dev/null +++ b/crates/soar-db/migrations/metadata/2026-10-19-000200-0000_drop_build_fields/up.sql @@ -0,0 +1,2 @@ +ALTER TABLE packages DROP COLUMN build_script; +ALTER TABLE packages DROP COLUMN build_log; diff --git a/crates/soar-db/src/connection.rs b/crates/soar-db/src/connection.rs index 9f32a029..202f3558 100644 --- a/crates/soar-db/src/connection.rs +++ b/crates/soar-db/src/connection.rs @@ -391,6 +391,39 @@ mod tests { assert_eq!(to_maintainers.n, 1); } + #[test] + fn upgrading_metadata_drops_build_fields_and_keeps_packages() { + let dir = tempfile::tempdir().unwrap(); + let path = dir.path().join("repo.db"); + { + // The schema as it stood before the build fields were dropped. + let mut conn = SqliteConnection::establish(path.to_str().unwrap()).unwrap(); + for _ in 0..5 { + conn.run_next_migration(METADATA_MIGRATIONS).unwrap(); + } + sql_query( + "INSERT INTO packages (pkg_name, version, download_url, build_log) \ + VALUES ('p', '1', 'https://x', 'https://log')", + ) + .execute(&mut conn) + .unwrap(); + } + + let mut db = DbConnection::open(&path, DbType::Metadata).unwrap(); + let conn = db.conn(); + let packages = sql_query("SELECT count(*) AS n FROM packages") + .get_result::(conn) + .unwrap(); + assert_eq!(packages.n, 1, "upgrading lost a package"); + let build_columns = sql_query( + "SELECT count(*) AS n FROM pragma_table_info('packages') \ + WHERE name IN ('build_script', 'build_log')", + ) + .get_result::(conn) + .unwrap(); + assert_eq!(build_columns.n, 0); + } + #[test] fn readonly_opens_a_path_with_uri_characters() { let dir = tempfile::tempdir().unwrap(); diff --git a/crates/soar-db/src/models/metadata.rs b/crates/soar-db/src/models/metadata.rs index 5a9e8ae8..5c42c397 100644 --- a/crates/soar-db/src/models/metadata.rs +++ b/crates/soar-db/src/models/metadata.rs @@ -35,10 +35,6 @@ pub struct Package { pub build_id: Option, pub build_date: Option, pub build_action: Option, - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_script: Option, - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_log: Option, pub provides: Option>, pub snapshots: Option>, pub replaces: Option>, @@ -80,8 +76,6 @@ impl Queryable for Package { Option, Option, Option, - Option, - Option, Option, Option, Option, @@ -92,7 +86,6 @@ impl Queryable for Package { Option, ); - #[allow(deprecated)] fn build(row: Self::Row) -> diesel::deserialize::Result { Ok(Self { id: row.0, @@ -121,16 +114,14 @@ impl Queryable for Package { build_id: row.23, build_date: row.24, build_action: row.25, - build_script: row.26, - build_log: row.27, - provides: json_vec!(row.28), - snapshots: json_vec!(row.29), - replaces: json_vec!(row.30), - soar_syms: row.31, - desktop_integration: row.32, - portable: row.33, - extra: json_vec!(row.34), - files: json_vec!(row.35), + provides: json_vec!(row.26), + snapshots: json_vec!(row.27), + replaces: json_vec!(row.28), + soar_syms: row.29, + desktop_integration: row.30, + portable: row.31, + extra: json_vec!(row.32), + files: json_vec!(row.33), }) } } @@ -222,10 +213,6 @@ pub struct NewPackage<'a> { pub build_id: Option<&'a str>, pub build_date: Option<&'a str>, pub build_action: Option<&'a str>, - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_script: Option<&'a str>, - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_log: Option<&'a str>, pub provides: Option, pub snapshots: Option, pub replaces: Option, diff --git a/crates/soar-db/src/repository/metadata.rs b/crates/soar-db/src/repository/metadata.rs index fb164026..5324c7ac 100644 --- a/crates/soar-db/src/repository/metadata.rs +++ b/crates/soar-db/src/repository/metadata.rs @@ -631,7 +631,6 @@ impl MetadataRepository { /// Inserts a single remote package. /// Returns whether the package was accepted; rejected entries are skipped /// rather than failing the whole import. - #[allow(deprecated)] fn insert_remote_package( conn: &mut SqliteConnection, package: &RemotePackage, @@ -706,8 +705,6 @@ impl MetadataRepository { build_id: package.build_id.as_deref(), build_date: package.build_date.as_deref(), build_action: package.build_action.as_deref(), - build_script: package.build_script.as_deref(), - build_log: package.build_log.as_deref(), provides: Some(json!(provides)), snapshots: Some(json!(package.snapshots)), replaces: Some(json!(package.replaces)), diff --git a/crates/soar-db/src/schema/metadata.rs b/crates/soar-db/src/schema/metadata.rs index 462cd3c1..e98b2a05 100644 --- a/crates/soar-db/src/schema/metadata.rs +++ b/crates/soar-db/src/schema/metadata.rs @@ -42,8 +42,6 @@ diesel::table! { build_id -> Nullable, build_date -> Nullable, build_action -> Nullable, - build_script -> Nullable, - build_log -> Nullable, provides -> Nullable, snapshots -> Nullable, replaces -> Nullable, diff --git a/crates/soar-package/src/error.rs b/crates/soar-package/src/error.rs index a701b172..ca4d191e 100644 --- a/crates/soar-package/src/error.rs +++ b/crates/soar-package/src/error.rs @@ -29,9 +29,13 @@ pub enum PackageError { #[diagnostic(code(soar_package::appimage))] AppImageError(#[from] squishy::error::SquishyError), - #[error("Configuration error: {0}")] - #[diagnostic(code(soar_package::config))] - ConfigError(String), + #[error(transparent)] + #[diagnostic(transparent)] + Config(#[from] soar_config::error::ConfigError), + + #[error(transparent)] + #[diagnostic(transparent)] + FileSystem(#[from] soar_utils::error::FileSystemError), #[error("{0}")] #[diagnostic(code(soar_package::custom))] @@ -63,14 +67,39 @@ impl ErrorContext for std::io::Result { } } -impl From for PackageError { - fn from(err: soar_config::error::ConfigError) -> Self { - PackageError::ConfigError(err.to_string()) +#[cfg(test)] +mod tests { + use std::error::Error as _; + + use super::*; + + #[test] + fn a_filesystem_error_keeps_its_cause_and_help() { + let err = PackageError::from(soar_utils::error::FileSystemError::ReadFile { + path: "/x/y".into(), + source: std::io::Error::from(std::io::ErrorKind::PermissionDenied), + }); + + assert_eq!(err.to_string(), "Failed to read file '/x/y'"); + assert_eq!( + err.source().map(ToString::to_string).as_deref(), + Some("permission denied") + ); + assert!(err.help().is_some()); + assert_eq!( + err.code().map(|code| code.to_string()).as_deref(), + Some("soar_utils::fs::read_file") + ); } -} -impl From for PackageError { - fn from(err: soar_utils::error::FileSystemError) -> Self { - PackageError::Custom(err.to_string()) + #[test] + fn a_config_error_keeps_its_own_diagnostic() { + let err = PackageError::from(soar_config::error::ConfigError::Custom("bad".into())); + + assert_eq!(err.to_string(), "bad"); + assert_eq!( + err.code().map(|code| code.to_string()).as_deref(), + Some("soar_config::custom") + ); } } diff --git a/crates/soar-package/src/formats/common.rs b/crates/soar-package/src/formats/common.rs index 0e4e3d79..4899093b 100644 --- a/crates/soar-package/src/formats/common.rs +++ b/crates/soar-package/src/formats/common.rs @@ -421,8 +421,7 @@ pub fn create_portable_link>( "refusing to create portable link with unsafe package name: {pkg_name}" ))); } - let base_dir = env::current_dir() - .map_err(|_| PackageError::Custom("Error retrieving current directory".into()))?; + let base_dir = env::current_dir().with_context(|| "retrieving current directory".into())?; let portable_path = portable_path.as_ref(); let portable_path = if portable_path.is_absolute() { portable_path diff --git a/crates/soar-registry/src/error.rs b/crates/soar-registry/src/error.rs index fe06f8cd..a2912785 100644 --- a/crates/soar-registry/src/error.rs +++ b/crates/soar-registry/src/error.rs @@ -69,14 +69,6 @@ pub enum RegistryError { )] MetadataTooShort, - #[error("ETag not found in metadata response")] - #[diagnostic( - code(soar_registry::missing_etag), - help("The server did not return an ETag header") - )] - #[deprecated(note = "a response without an ETag is accepted and refetched next sync")] - MissingEtag, - #[error("Insecure repository URL: {0}")] #[diagnostic( code(soar_registry::insecure_url), diff --git a/crates/soar-registry/src/package.rs b/crates/soar-registry/src/package.rs index 4f1d24d4..688d9264 100644 --- a/crates/soar-registry/src/package.rs +++ b/crates/soar-registry/src/package.rs @@ -198,14 +198,6 @@ pub struct RemotePackage { #[serde(default, deserialize_with = "empty_is_none", alias = "build_gha")] pub build_action: Option, - #[serde(default, deserialize_with = "empty_is_none")] - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_script: Option, - - #[serde(default, deserialize_with = "empty_is_none")] - #[deprecated(note = "no repository publishes build logs or scripts anymore")] - pub build_log: Option, - #[serde(alias = "category")] pub categories: Option>,