use std::collections::HashMap;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use super::{Amd64Variant, FileInfo, StringOrU32};
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmConfig {
pub id: Option<String>,
pub package_name: Option<String>,
pub formats: Vec<String>,
pub vendor: Option<String>,
pub homepage: Option<String>,
pub maintainer: Option<String>,
pub description: Option<String>,
pub license: Option<String>,
pub bindir: Option<String>,
pub bin_alias: Option<String>,
pub contents: Option<Vec<NfpmContent>>,
pub dependencies: Option<HashMap<String, Vec<String>>>,
pub overrides: Option<HashMap<String, serde_json::Value>>,
pub file_name_template: Option<String>,
pub scripts: Option<NfpmScripts>,
pub recommends: Option<Vec<String>>,
pub suggests: Option<Vec<String>>,
pub conflicts: Option<Vec<String>>,
pub replaces: Option<Vec<String>>,
pub provides: Option<Vec<String>>,
#[serde(alias = "builds")]
pub ids: Option<Vec<String>>,
#[serde(alias = "goamd64")]
pub amd64_variant: Option<Vec<Amd64Variant>>,
pub epoch: Option<String>,
pub release: Option<String>,
pub prerelease: Option<String>,
pub version_metadata: Option<String>,
pub section: Option<String>,
pub priority: Option<String>,
pub meta: Option<bool>,
pub umask: Option<StringOrU32>,
pub mtime: Option<String>,
pub rpm: Option<NfpmRpmConfig>,
pub deb: Option<NfpmDebConfig>,
pub apk: Option<NfpmApkConfig>,
pub archlinux: Option<NfpmArchlinuxConfig>,
pub ipk: Option<NfpmIpkConfig>,
pub msix: Option<NfpmMsixConfig>,
pub libdirs: Option<NfpmLibdirs>,
pub changelog: Option<String>,
#[serde(rename = "if")]
pub if_condition: Option<String>,
pub templated_contents: Option<Vec<NfpmContent>>,
pub templated_scripts: Option<NfpmScripts>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmLibdirs {
pub header: Option<String>,
pub carchive: Option<String>,
pub cshared: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmScripts {
pub preinstall: Option<String>,
pub postinstall: Option<String>,
pub preremove: Option<String>,
pub postremove: Option<String>,
}
pub type NfpmFileInfo = FileInfo;
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
pub struct NfpmContent {
pub src: String,
pub dst: String,
#[serde(rename = "type")]
pub content_type: Option<String>,
pub file_info: Option<NfpmFileInfo>,
pub packager: Option<String>,
pub expand: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmRpmConfig {
pub summary: Option<String>,
pub compression: Option<String>,
pub group: Option<String>,
pub packager: Option<String>,
pub prefixes: Option<Vec<String>>,
pub signature: Option<NfpmSignatureConfig>,
pub scripts: Option<NfpmRpmScripts>,
pub build_host: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmRpmScripts {
pub pretrans: Option<String>,
pub posttrans: Option<String>,
}
impl NfpmRpmConfig {
pub fn is_empty(&self) -> bool {
self.summary.is_none()
&& self.compression.is_none()
&& self.group.is_none()
&& self.packager.is_none()
&& self.prefixes.is_none()
&& self.signature.is_none()
&& self.scripts.is_none()
&& self.build_host.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmDebConfig {
pub compression: Option<String>,
pub predepends: Option<Vec<String>>,
pub triggers: Option<NfpmDebTriggers>,
pub breaks: Option<Vec<String>>,
pub lintian_overrides: Option<Vec<String>>,
pub signature: Option<NfpmSignatureConfig>,
pub fields: Option<HashMap<String, String>>,
pub scripts: Option<NfpmDebScripts>,
pub arch_variant: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmDebScripts {
pub rules: Option<String>,
pub templates: Option<String>,
pub config: Option<String>,
}
impl NfpmDebConfig {
pub fn is_empty(&self) -> bool {
self.compression.is_none()
&& self.predepends.is_none()
&& self.triggers.is_none()
&& self.breaks.is_none()
&& self.lintian_overrides.is_none()
&& self.signature.is_none()
&& self.fields.is_none()
&& self.scripts.is_none()
&& self.arch_variant.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmDebTriggers {
pub interest: Option<Vec<String>>,
pub interest_await: Option<Vec<String>>,
pub interest_noawait: Option<Vec<String>>,
pub activate: Option<Vec<String>>,
pub activate_await: Option<Vec<String>>,
pub activate_noawait: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmApkConfig {
pub signature: Option<NfpmSignatureConfig>,
pub scripts: Option<NfpmApkScripts>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmApkScripts {
pub preupgrade: Option<String>,
pub postupgrade: Option<String>,
}
impl NfpmApkConfig {
pub fn is_empty(&self) -> bool {
self.signature.is_none() && self.scripts.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmArchlinuxConfig {
pub pkgbase: Option<String>,
pub packager: Option<String>,
pub scripts: Option<NfpmArchlinuxScripts>,
}
impl NfpmArchlinuxConfig {
pub fn is_empty(&self) -> bool {
self.pkgbase.is_none() && self.packager.is_none() && self.scripts.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmArchlinuxScripts {
pub preupgrade: Option<String>,
pub postupgrade: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmIpkConfig {
pub abi_version: Option<String>,
pub alternatives: Option<Vec<NfpmIpkAlternative>>,
pub auto_installed: Option<bool>,
pub essential: Option<bool>,
pub predepends: Option<Vec<String>>,
pub tags: Option<Vec<String>>,
pub fields: Option<HashMap<String, String>>,
}
impl NfpmIpkConfig {
pub fn is_empty(&self) -> bool {
self.abi_version.is_none()
&& self.alternatives.is_none()
&& self.auto_installed.is_none()
&& self.essential.is_none()
&& self.predepends.is_none()
&& self.tags.is_none()
&& self.fields.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixConfig {
pub arch: Option<String>,
pub publisher: Option<String>,
pub identity: Option<NfpmMsixIdentity>,
pub properties: Option<NfpmMsixProperties>,
pub applications: Option<Vec<NfpmMsixApplication>>,
pub dependencies: Option<NfpmMsixDependencies>,
pub capabilities: Option<NfpmMsixCapabilities>,
pub signature: Option<NfpmMsixSignature>,
}
impl NfpmMsixConfig {
pub fn is_empty(&self) -> bool {
self.arch.is_none()
&& self.publisher.is_none()
&& self.identity.is_none()
&& self.properties.is_none()
&& self.applications.is_none()
&& self.dependencies.is_none()
&& self.capabilities.is_none()
&& self.signature.is_none()
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixIdentity {
pub resource_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixProperties {
pub display_name: Option<String>,
pub publisher_display_name: Option<String>,
pub logo: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixApplication {
pub id: Option<String>,
pub executable: Option<String>,
pub entry_point: Option<String>,
pub visual_elements: Option<NfpmMsixVisualElements>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixVisualElements {
pub display_name: Option<String>,
pub description: Option<String>,
pub background_color: Option<String>,
pub square150x150_logo: Option<String>,
pub square44x44_logo: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixDependencies {
pub target_device_families: Option<Vec<NfpmMsixTargetDeviceFamily>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixTargetDeviceFamily {
pub name: Option<String>,
pub min_version: Option<String>,
pub max_version_tested: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixCapabilities {
pub capabilities: Option<Vec<String>>,
pub device_capabilities: Option<Vec<String>>,
pub restricted: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmMsixSignature {
pub pfx_file: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmIpkAlternative {
pub priority: Option<i32>,
pub target: Option<String>,
pub link_name: Option<String>,
}
#[cfg(test)]
mod is_empty_tests {
use super::*;
#[test]
fn deb_arch_variant_alone_is_not_empty() {
let cfg = NfpmDebConfig {
arch_variant: Some("v3".to_string()),
..Default::default()
};
assert!(
!cfg.is_empty(),
"deb block with only arch_variant must NOT be dropped"
);
}
#[test]
fn deb_default_is_empty() {
assert!(NfpmDebConfig::default().is_empty());
}
#[test]
fn nfpm_goamd64_alias_parses_into_amd64_variant() {
let nfpm: NfpmConfig =
serde_yaml_ng::from_str("formats: [deb]\ngoamd64: [v2, v3]").unwrap();
assert_eq!(
nfpm.amd64_variant.as_deref(),
Some([Amd64Variant::V2, Amd64Variant::V3].as_slice())
);
}
#[test]
fn nfpm_canonical_amd64_variant_still_parses() {
let nfpm: NfpmConfig =
serde_yaml_ng::from_str("formats: [deb]\namd64_variant: [v1]").unwrap();
assert_eq!(
nfpm.amd64_variant.as_deref(),
Some([Amd64Variant::V1].as_slice())
);
}
#[test]
fn nfpm_amd64_variant_list_rejects_garbage_at_parse() {
let err =
serde_yaml_ng::from_str::<NfpmConfig>("formats: [deb]\namd64_variant: [v2, x86-64-v3]")
.unwrap_err()
.to_string();
assert!(
err.contains("unknown variant `x86-64-v3`")
&& err.contains("expected one of `v1`, `v2`, `v3`, `v4`"),
"parse error must name the bad value and the valid set: {err}"
);
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
#[serde(default, deny_unknown_fields)]
pub struct NfpmSignatureConfig {
pub key_file: Option<String>,
pub key_id: Option<String>,
pub key_passphrase: Option<String>,
pub key_name: Option<String>,
#[serde(rename = "type")]
pub type_: Option<String>,
}