Skip to main content

anodizer_core/
packagers.rs

1//! Packaging-axis config types lifted out of the monolithic
2//! `crate::config` module.
3//!
4//! Currently houses [`MakeselfConfig`] + helpers and [`SrpmConfig`].
5//! The remaining packaging types (`NfpmConfig`, `SnapcraftConfig`,
6//! `FlatpakConfig`, `AppBundleConfig`, `DmgConfig`, `PkgConfig`,
7//! `MsiConfig`, `NsisConfig`) still live in `config.rs` and will move
8//! here in subsequent extraction passes — each with their dedicated
9//! deserializer / `*_schema()` helper alongside.
10//!
11//! Public API path is preserved by re-exports in `config.rs` so consumers
12//! can keep importing from `anodizer_core::config::*`.
13
14use crate::config::{
15    NfpmContent, NfpmSignatureConfig, StringOrBool, deserialize_string_or_bool_opt,
16};
17use schemars::JsonSchema;
18use serde::{Deserialize, Deserializer, Serialize};
19
20// ---------------------------------------------------------------------------
21// MakeselfConfig
22// ---------------------------------------------------------------------------
23
24#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
25#[serde(default)]
26pub struct MakeselfConfig {
27    /// Unique identifier for this makeself config (default: "default").
28    pub id: Option<String>,
29    /// Build IDs filter: only include artifacts whose `id` is in this list.
30    pub ids: Option<Vec<String>>,
31    /// Output filename template (default includes project, version, os, arch).
32    pub filename: Option<String>,
33    /// Display name embedded in the self-extracting archive.
34    pub name: Option<String>,
35    /// Startup script to run when the archive is extracted and executed.
36    /// Required — the archive will not be created without this.
37    pub script: Option<String>,
38    /// Description for LSM metadata.
39    pub description: Option<String>,
40    /// Maintainer for LSM metadata.
41    pub maintainer: Option<String>,
42    /// Keywords for LSM metadata.
43    pub keywords: Option<Vec<String>>,
44    /// Homepage URL for LSM metadata.
45    pub homepage: Option<String>,
46    /// License for LSM metadata.
47    pub license: Option<String>,
48    /// Compression algorithm: gzip, bzip2, xz, lzo, compress, or none.
49    pub compression: Option<String>,
50    /// Extra arguments passed to the makeself command.
51    pub extra_args: Option<Vec<String>>,
52    /// Additional files to include in the archive.
53    pub files: Option<Vec<MakeselfFile>>,
54    /// Target OS filter (default: ["linux", "darwin"]).
55    pub goos: Option<Vec<String>>,
56    /// Target architecture filter.
57    pub goarch: Option<Vec<String>>,
58    /// Skip this config. Accepts bool or template string.
59    #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
60    pub skip: Option<StringOrBool>,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
64#[serde(default)]
65pub struct MakeselfFile {
66    /// Source file path (relative to project root).
67    pub source: String,
68    /// Destination path inside the archive.
69    pub destination: Option<String>,
70    /// Strip the parent directory from the source path.
71    pub strip_parent: Option<bool>,
72}
73
74/// Deserialize makeselfs: single object → vec of one, array → vec of many.
75pub(crate) fn deserialize_makeselfs<'de, D>(
76    deserializer: D,
77) -> Result<Vec<MakeselfConfig>, D::Error>
78where
79    D: Deserializer<'de>,
80{
81    use serde::de::{self, Visitor};
82
83    struct MakeselfVisitor;
84
85    impl<'de> Visitor<'de> for MakeselfVisitor {
86        type Value = Vec<MakeselfConfig>;
87
88        fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89            f.write_str("a makeself config object or an array of makeself config objects")
90        }
91
92        fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
93            let mut configs = Vec::new();
94            while let Some(item) = seq.next_element::<MakeselfConfig>()? {
95                configs.push(item);
96            }
97            Ok(configs)
98        }
99
100        fn visit_map<M: de::MapAccess<'de>>(self, map: M) -> Result<Self::Value, M::Error> {
101            let config = MakeselfConfig::deserialize(de::value::MapAccessDeserializer::new(map))?;
102            Ok(vec![config])
103        }
104
105        fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
106            Ok(Vec::new())
107        }
108
109        fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
110            Ok(Vec::new())
111        }
112    }
113
114    deserializer.deserialize_any(MakeselfVisitor)
115}
116
117pub(crate) fn makeselfs_schema(
118    generator: &mut schemars::r#gen::SchemaGenerator,
119) -> schemars::schema::Schema {
120    let mut schema = generator.subschema_for::<Vec<MakeselfConfig>>();
121    if let schemars::schema::Schema::Object(ref mut obj) = schema {
122        obj.metadata().description = Some(
123            "Makeself self-extracting archive configurations. Accepts a single object or array."
124                .to_owned(),
125        );
126    }
127    schema
128}
129
130// ---------------------------------------------------------------------------
131// SrpmConfig
132// ---------------------------------------------------------------------------
133
134#[derive(Debug, Clone, Serialize, Deserialize, Default, JsonSchema)]
135#[serde(default)]
136pub struct SrpmConfig {
137    /// Enable source RPM generation. Default: false.
138    pub enabled: Option<bool>,
139    /// Package name (default: project_name).
140    pub package_name: Option<String>,
141    /// Output filename template.
142    pub file_name_template: Option<String>,
143    /// Path to the RPM spec file template.
144    pub spec_file: Option<String>,
145    /// RPM epoch.
146    pub epoch: Option<String>,
147    /// RPM section.
148    pub section: Option<String>,
149    /// Package maintainer.
150    pub maintainer: Option<String>,
151    /// Package vendor.
152    pub vendor: Option<String>,
153    /// Summary line.
154    pub summary: Option<String>,
155    /// RPM group.
156    pub group: Option<String>,
157    /// Package description.
158    pub description: Option<String>,
159    /// License identifier.
160    pub license: Option<String>,
161    /// License file name to include.
162    pub license_file_name: Option<String>,
163    /// Homepage URL.
164    pub url: Option<String>,
165    /// RPM packager field.
166    pub packager: Option<String>,
167    /// Compression algorithm (gzip, xz, zstd, none).
168    pub compression: Option<String>,
169    /// Documentation files to include.
170    pub docs: Option<Vec<String>>,
171    /// Additional contents to include in the source RPM. Shares the unified
172    /// [`NfpmContent`] type with nFPM contents; SRPM-style `source:` /
173    /// `destination:` / `type:` keys are accepted via serde aliases.
174    pub contents: Option<Vec<NfpmContent>>,
175    /// RPM signature configuration. Shares the unified
176    /// [`NfpmSignatureConfig`] type with nFPM.
177    pub signature: Option<NfpmSignatureConfig>,
178    /// Build IDs whose binaries are bundled into the source RPM. When set,
179    /// only artifacts produced by builds with these IDs are packaged.
180    /// Mirrors GR `NFPM.Builds`.
181    pub bins: Option<Vec<String>>,
182    /// Project import path (Go-style; for Rust this is the canonical
183    /// repository URL, e.g. `github.com/owner/repo`). Used in spec file
184    /// generation for downstream tooling that expects a vcs-rooted path.
185    pub import_path: Option<String>,
186    /// Filesystem prefixes the package may install to (RPM `Prefix:` tag).
187    /// Each entry becomes one `Prefix:` directive — relocatable RPMs need
188    /// at least one prefix declared.
189    pub prefixes: Option<Vec<String>>,
190    /// Override the build host recorded in the RPM header. Useful for
191    /// reproducible builds where the actual hostname leaks build-env detail.
192    pub build_host: Option<String>,
193    /// `%pretrans` scriptlet — executed on the package transaction *before*
194    /// any package in the transaction is installed. Path to a script file.
195    pub pretrans: Option<String>,
196    /// `%posttrans` scriptlet — executed *after* all packages in the
197    /// transaction have been installed. Path to a script file.
198    pub posttrans: Option<String>,
199    /// Prerelease suffix appended to the version (e.g. `rc1`, `beta2`).
200    /// Mirrors GR `NFPM.Prerelease`.
201    pub prerelease: Option<String>,
202    /// Build metadata appended to the version (e.g. git commit hash).
203    /// Mirrors GR `NFPM.VersionMetadata`.
204    pub version_metadata: Option<String>,
205    /// Skip this config. Accepts bool or template string.
206    #[serde(deserialize_with = "deserialize_string_or_bool_opt", default)]
207    pub skip: Option<StringOrBool>,
208}
209
210// SRPM signatures share [`NfpmSignatureConfig`]; the SRPM-style
211// `passphrase:` key is accepted as a serde alias for `key_passphrase:`.
212//
213// SRPM contents share [`NfpmContent`]; both the canonical `src` / `dst`
214// keys and the SRPM-style `source` / `destination` aliases parse.