Skip to main content

flake_edit/app/commands/
update.rs

1//! `flake-edit update`: bump inputs to the latest semver match.
2//!
3//! Three modes: scripted single-input by ID, interactive
4//! multi-select with current versions rendered for context, and a
5//! non-interactive bump-everything path. `init` toggles whether
6//! [`crate::forge::update::Updater`] seeds updates for inputs the lockfile
7//! has not yet seen.
8
9use nix_uri::FlakeRef;
10
11use crate::edit::{FlakeEdit, sorted_input_ids};
12
13use super::super::editor::Editor;
14use super::super::state::AppState;
15use super::{Error, Result, interactive_multi_select, updater};
16
17pub fn update(
18    editor: &Editor,
19    flake_edit: &mut FlakeEdit,
20    state: &AppState,
21    id: Option<String>,
22    init: bool,
23) -> Result<()> {
24    let inputs = flake_edit.list().clone();
25
26    if let Some(id) = id {
27        let mut updater = updater(editor, inputs);
28        updater.update_inputs_to_latest_semver(&[id.as_str()], init);
29        let change = updater.get_changes();
30        editor.apply_or_diff(&change, state)?;
31    } else if state.interactive {
32        let input_ids = sorted_input_ids(&inputs)
33            .into_iter()
34            .cloned()
35            .collect::<Vec<_>>();
36        if input_ids.is_empty() {
37            return Err(Error::NoInputs);
38        }
39
40        let display_items: Vec<String> = input_ids
41            .iter()
42            .map(|id| {
43                let input = &inputs[id];
44                let parsed = input.url().parse::<FlakeRef>().ok();
45                let version = parsed.as_ref().and_then(|f| f.ref_or_rev());
46                match version {
47                    Some(v) if !v.is_empty() => format!("{} - {}", id, v),
48                    _ => id.clone(),
49                }
50            })
51            .collect();
52
53        interactive_multi_select(
54            editor,
55            state,
56            "Update",
57            "Space select, U all, ^D diff",
58            display_items,
59            |selected| {
60                let ids: Vec<&str> = selected
61                    .iter()
62                    .map(|s| s.split(" - ").next().unwrap_or(s))
63                    .collect();
64                let mut updater = updater(editor, inputs.clone());
65                updater.update_inputs_to_latest_semver(&ids, init);
66                updater.get_changes()
67            },
68        )?;
69    } else {
70        let mut updater = updater(editor, inputs);
71        updater.update_all_to_latest_semver(init);
72        let change = updater.get_changes();
73        editor.apply_or_diff(&change, state)?;
74    }
75
76    Ok(())
77}