1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! `self-update` subcommand

use crate::{Application, RUSTIC_APP};

use abscissa_core::{status_err, Command, Runnable, Shutdown};

use anyhow::Result;

/// `self-update` subcommand
#[derive(clap::Parser, Command, Debug)]
pub(crate) struct SelfUpdateCmd {
    /// Do not ask before processing the self-update
    #[clap(long, conflicts_with = "dry_run")]
    force: bool,
}

impl Runnable for SelfUpdateCmd {
    fn run(&self) {
        if let Err(err) = self.inner_run() {
            status_err!("{}", err);
            RUSTIC_APP.shutdown(Shutdown::Crash);
        };
    }
}

impl SelfUpdateCmd {
    #[cfg(feature = "self-update")]
    fn inner_run(&self) -> Result<()> {
        let current_version = semver::Version::parse(self_update::cargo_crate_version!())?;

        let release = self_update::backends::github::Update::configure()
            .repo_owner("rustic-rs")
            .repo_name("rustic")
            .bin_name("rustic")
            .show_download_progress(true)
            .current_version(current_version.to_string().as_str())
            .no_confirm(self.force)
            .build()?;

        let latest_release = release.get_latest_release()?;

        let upstream_version = semver::Version::parse(&latest_release.version)?;

        match current_version.cmp(&upstream_version) {
            std::cmp::Ordering::Greater => {
                println!(
                    "Your rustic version {current_version} is newer than the stable version {upstream_version} on upstream!"
                );
            }
            std::cmp::Ordering::Equal => {
                println!("rustic version {current_version} is up-to-date!");
            }
            std::cmp::Ordering::Less => {
                let status = release.update()?;

                if let self_update::Status::Updated(str) = status {
                    println!("rustic version has been updated to: {str}");
                }
            }
        }

        Ok(())
    }
    #[cfg(not(feature = "self-update"))]
    fn inner_run(&self) -> Result<()> {
        anyhow::bail!(
            "This version of rustic was built without the \"self-update\" feature. Please use your system package manager to update it."
        );
    }
}