Skip to main content

soldeer_commands/commands/
update.rs

1use crate::{
2    ConfigLocation,
3    utils::{Progress, success, warn_unknown_lockfile_version, warning},
4};
5use clap::Parser;
6use soldeer_core::{
7    Result,
8    config::{Paths, read_config_deps, read_soldeer_config},
9    install::{InstallProgress, ensure_dependencies_dir},
10    lock::{LockFileVersion, generate_lockfile_contents, read_lockfile, write_lockfile},
11    remappings::{RemappingsAction, edit_remappings},
12    update::update_dependencies,
13};
14
15/// Update dependencies by reading the config file
16#[derive(Debug, Clone, Default, Parser, bon::Builder)]
17#[allow(clippy::duplicated_attributes)]
18#[builder(on(String, into), on(ConfigLocation, into))]
19#[clap(after_help = "For more information, read the README.md")]
20#[non_exhaustive]
21pub struct Update {
22    /// If set, this command will delete the existing remappings and re-create them
23    #[arg(short = 'g', long, default_value_t = false)]
24    #[builder(default)]
25    pub regenerate_remappings: bool,
26
27    /// If set, this command will install the dependencies recursively (via submodules or via
28    /// soldeer)
29    #[arg(short = 'd', long, default_value_t = false)]
30    #[builder(default)]
31    pub recursive_deps: bool,
32
33    /// Specify the config location without prompting.
34    ///
35    /// This prevents prompting the user if the automatic detection can't determine the config
36    /// location.
37    #[arg(long, value_enum)]
38    pub config_location: Option<ConfigLocation>,
39}
40
41// TODO: add a parameter for a dependency name, where we would only update that particular
42// dependency
43
44pub(crate) async fn update_command(paths: &Paths, cmd: Update) -> Result<()> {
45    let mut config = read_soldeer_config(&paths.config)?;
46    if cmd.regenerate_remappings {
47        config.remappings_regenerate = true;
48    }
49    if cmd.recursive_deps {
50        config.recursive_deps = true;
51    }
52    success!("Done reading config");
53    ensure_dependencies_dir(&paths.dependencies)?;
54    let (dependencies, warnings) = read_config_deps(&paths.config)?;
55    for w in warnings {
56        warning!(format!("Config warning: {w}"));
57    }
58
59    let lockfile = read_lockfile(&paths.lock)?;
60    success!("Done reading lockfile");
61    warn_unknown_lockfile_version(&lockfile);
62    let (progress, monitor) = InstallProgress::new();
63    let bars = Progress::new("Updating dependencies", dependencies.len(), monitor);
64    bars.start_all();
65    let new_locks = update_dependencies(
66        &dependencies,
67        &lockfile.entries,
68        lockfile.version,
69        &paths.dependencies,
70        config.recursive_deps,
71        progress,
72    )
73    .await
74    .inspect_err(|e| {
75        bars.set_error(e);
76    })?;
77    bars.stop_all();
78
79    let new_lockfile_content = generate_lockfile_contents(new_locks, LockFileVersion::default());
80    write_lockfile(&new_lockfile_content, &paths.lock)?;
81    success!("Updated lockfile");
82
83    edit_remappings(&RemappingsAction::Update, &config, paths)?;
84    success!("Updated remappings");
85    Ok(())
86}