Skip to main content

ephemeris_forge_forgejo/plan/
labels.rs

1use 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}