ephemeris_forge_forgejo/plan/
labels.rs1use ephemeris_forge::{Collection, FieldDiff, Report};
2
3use crate::Live;
4use crate::api::model;
5use crate::api::request::{CreateLabelOption, EditLabelOption};
6use crate::config::{Label, Labels};
7use crate::operation::labels::Operation;
8
9pub(super) fn plan(config: Option<&Labels>, live: &Live, report: &mut Report) -> Vec<Operation> {
10 let Some(config) = config else {
11 return Vec::new();
12 };
13 Collection {
14 noun: "label",
15 mode: config.mode,
16 }
17 .plan(
18 &config.labels,
19 &live.labels,
20 report,
21 |label, name| label.name.as_deref() == Some(name),
22 |name, desired, actual, _| {
23 let (edit, diff) = compare(desired, actual);
24 let operations = match actual {
25 Some(actual) if !edit.is_empty() => Some(Operation::Patch {
26 id: actual.id,
27 name: name.to_owned(),
28 edit,
29 }),
30 Some(_) => None,
31 None => Some(Operation::Create {
32 body: CreateLabelOption::new(name, desired),
33 }),
34 };
35 (diff, operations.into_iter().collect())
36 },
37 |label, _| {
38 let name = label.name.clone()?;
39 Some((name.clone(), Operation::Delete { id: label.id, name }))
40 },
41 )
42}
43
44fn compare(desired: &Label, actual: Option<&model::Label>) -> (EditLabelOption, FieldDiff) {
45 let mut diff = FieldDiff::default();
46 let mut edit = EditLabelOption::default();
47 let description = desired.description.clone().unwrap_or_default();
48 if diff.check(
49 "color",
50 actual
51 .and_then(|label| label.color.as_deref())
52 .is_some_and(|color| desired.color.matches(color)),
53 &actual.and_then(|label| label.color.as_deref()),
54 &desired.color,
55 ) {
56 edit.color = Some(desired.color.to_string());
57 }
58 let live_description = actual.map(|label| label.description.clone().unwrap_or_default());
59 edit.description = diff.want("description", &description, live_description.as_ref());
60 let exclusive = actual.map(|label| label.exclusive.unwrap_or(false));
61 edit.exclusive = diff.want("exclusive", &desired.exclusive, exclusive.as_ref());
62 let archived = actual.map(|label| label.is_archived.unwrap_or(false));
63 edit.is_archived = diff.want("is_archived", &desired.is_archived, archived.as_ref());
64 (edit, diff)
65}