1use alpm_types::{Architecture, Architectures};
4
5use super::{
6    package::{Override, Package, PackageArchitecture},
7    package_base::{PackageBase, PackageBaseArchitecture},
8};
9#[cfg(doc)]
10use crate::SourceInfo;
11
12fn push_section(section: &str, value: &str, output: &mut String) {
16    output.push_str(section);
17    output.push_str(" = ");
18    output.push_str(value);
19    output.push('\n');
20}
21
22fn push_key_value(key: &str, value: &str, output: &mut String) {
27    output.push('\t');
28    output.push_str(key);
29    output.push_str(" = ");
30    output.push_str(value);
31    output.push('\n');
32}
33
34fn push_optional_value<T: ToString>(key: &str, value: &Option<T>, output: &mut String) {
39    let Some(value) = value else {
40        return;
41    };
42
43    push_key_value(key, &value.to_string(), output);
44}
45
46fn push_value_list<T: ToString>(key: &str, values: &Vec<T>, output: &mut String) {
56    for value in values {
57        push_key_value(key, &value.to_string(), output);
58    }
59}
60
61pub(crate) fn pkgbase_section(base: &PackageBase, output: &mut String) {
69    push_section("pkgbase", base.name.inner(), output);
70
71    if let Some(description) = &base.description {
72        push_key_value("pkgdesc", description.as_ref(), output);
73    }
74    push_key_value("pkgver", &base.version.pkgver.to_string(), output);
75    push_key_value("pkgrel", &base.version.pkgrel.to_string(), output);
76    push_optional_value("epoch", &base.version.epoch, output);
77    push_optional_value("url", &base.url, output);
78    push_optional_value("install", &base.install, output);
79    push_optional_value("changelog", &base.changelog, output);
80    let architectures: Vec<Architecture> = (&base.architectures).into();
81    push_value_list("arch", &architectures, output);
82
83    push_value_list("groups", &base.groups, output);
84    push_value_list("license", &base.licenses, output);
85    push_value_list("checkdepends", &base.check_dependencies, output);
86    push_value_list("makedepends", &base.make_dependencies, output);
87    push_value_list("depends", &base.dependencies, output);
88    push_value_list("optdepends", &base.optional_dependencies, output);
89    push_value_list("provides", &base.provides, output);
90    push_value_list("conflicts", &base.conflicts, output);
91    push_value_list("replaces", &base.replaces, output);
92    push_value_list("noextract", &base.no_extracts, output);
93    push_value_list("options", &base.options, output);
94    push_value_list("backup", &base.backups, output);
95    push_value_list("source", &base.sources, output);
96    push_value_list("validpgpkeys", &base.pgp_fingerprints, output);
97    push_value_list("md5sums", &base.md5_checksums, output);
98    push_value_list("sha1sums", &base.sha1_checksums, output);
99    push_value_list("sha224sums", &base.sha224_checksums, output);
100    push_value_list("sha256sums", &base.sha256_checksums, output);
101    push_value_list("sha384sums", &base.sha384_checksums, output);
102    push_value_list("sha512sums", &base.sha512_checksums, output);
103    push_value_list("b2sums", &base.b2_checksums, output);
104
105    for architecture in &base.architectures {
108        if let Architecture::Some(system_arch) = &architecture
109            && let Some(properties) = base.architecture_properties.get(system_arch)
110        {
111            pkgbase_architecture_properties(architecture, properties, output);
112        }
113    }
114}
115
116fn pkgbase_architecture_properties(
125    architecture: Architecture,
126    properties: &PackageBaseArchitecture,
127    output: &mut String,
128) {
129    push_value_list(
130        &format!("source_{architecture}"),
131        &properties.sources,
132        output,
133    );
134    push_value_list(
135        &format!("provides_{architecture}"),
136        &properties.provides,
137        output,
138    );
139    push_value_list(
140        &format!("conflicts_{architecture}"),
141        &properties.conflicts,
142        output,
143    );
144    push_value_list(
145        &format!("depends_{architecture}"),
146        &properties.dependencies,
147        output,
148    );
149    push_value_list(
150        &format!("replaces_{architecture}"),
151        &properties.replaces,
152        output,
153    );
154    push_value_list(
155        &format!("optdepends_{architecture}"),
156        &properties.optional_dependencies,
157        output,
158    );
159    push_value_list(
160        &format!("makedepends_{architecture}"),
161        &properties.make_dependencies,
162        output,
163    );
164    push_value_list(
165        &format!("checkdepends_{architecture}"),
166        &properties.check_dependencies,
167        output,
168    );
169    push_value_list(
170        &format!("md5sums_{architecture}"),
171        &properties.md5_checksums,
172        output,
173    );
174    push_value_list(
175        &format!("sha1sums_{architecture}"),
176        &properties.sha1_checksums,
177        output,
178    );
179    push_value_list(
180        &format!("sha224sums_{architecture}"),
181        &properties.sha224_checksums,
182        output,
183    );
184    push_value_list(
185        &format!("sha256sums_{architecture}"),
186        &properties.sha256_checksums,
187        output,
188    );
189    push_value_list(
190        &format!("sha384sums_{architecture}"),
191        &properties.sha384_checksums,
192        output,
193    );
194    push_value_list(
195        &format!("sha512sums_{architecture}"),
196        &properties.sha512_checksums,
197        output,
198    );
199    push_value_list(
200        &format!("b2sums_{architecture}"),
201        &properties.b2_checksums,
202        output,
203    );
204}
205
206fn push_override_value<T: ToString>(key: &str, value: &Override<T>, output: &mut String) {
213    match value {
214        Override::No => (),
215        Override::Clear => {
216            output.push('\t');
218            output.push_str(key);
219            output.push_str(" = \n");
220        }
221        Override::Yes { value } => {
222            push_key_value(key, &value.to_string(), output);
223        }
224    }
225}
226
227fn push_override_value_list<T: ToString>(
237    key: &str,
238    values: &Override<Vec<T>>,
239    output: &mut String,
240) {
241    match values {
242        Override::No => (),
243        Override::Clear => {
244            output.push('\t');
246            output.push_str(key);
247            output.push_str(" = \n");
248        }
249        Override::Yes { value } => {
250            for inner_value in value {
251                push_key_value(key, &inner_value.to_string(), output);
252            }
253        }
254    }
255}
256
257pub(crate) fn pkgname_section(
265    package: &Package,
266    base_architectures: &Architectures,
267    output: &mut String,
268) {
269    push_section("pkgname", package.name.inner(), output);
270
271    push_override_value("pkgdesc", &package.description, output);
272    push_override_value("url", &package.url, output);
273    push_override_value("install", &package.install, output);
274    push_override_value("changelog", &package.changelog, output);
275
276    if let Some(architectures) = &package.architectures {
277        let arch_vec: Vec<Architecture> = architectures.into();
278        push_value_list("arch", &arch_vec, output);
279    }
280
281    push_override_value_list("groups", &package.groups, output);
282    push_override_value_list("license", &package.licenses, output);
283    push_override_value_list("depends", &package.dependencies, output);
284    push_override_value_list("optdepends", &package.optional_dependencies, output);
285    push_override_value_list("provides", &package.provides, output);
286    push_override_value_list("conflicts", &package.conflicts, output);
287    push_override_value_list("replaces", &package.replaces, output);
288    push_override_value_list("options", &package.options, output);
289    push_override_value_list("backup", &package.backups, output);
290
291    for architecture in base_architectures {
293        if let Architecture::Some(system_arch) = &architecture
294            && let Some(properties) = package.architecture_properties.get(system_arch)
295        {
296            pkgname_architecture_properties(architecture, properties, output);
297        }
298    }
299}
300
301fn pkgname_architecture_properties(
310    architecture: Architecture,
311    properties: &PackageArchitecture,
312    output: &mut String,
313) {
314    push_override_value_list(
315        &format!("provides_{architecture}"),
316        &properties.provides,
317        output,
318    );
319    push_override_value_list(
320        &format!("conflicts_{architecture}"),
321        &properties.conflicts,
322        output,
323    );
324    push_override_value_list(
325        &format!("depends_{architecture}"),
326        &properties.dependencies,
327        output,
328    );
329    push_override_value_list(
330        &format!("replaces_{architecture}"),
331        &properties.replaces,
332        output,
333    );
334    push_override_value_list(
335        &format!("optdepends_{architecture}"),
336        &properties.optional_dependencies,
337        output,
338    );
339}