juliaup/
command_selfupdate.rs1use crate::global_paths::GlobalPaths;
2use crate::operations::update_version_db;
3use anyhow::{Context, Result};
4
5#[cfg(feature = "selfupdate")]
6pub fn run_command_selfupdate(paths: &GlobalPaths) -> Result<()> {
7 use crate::config_file::{load_mut_config_db, save_config_db};
8 use crate::operations::{download_extract_sans_parent, download_juliaup_version};
9 use crate::utils::get_juliaserver_base_url;
10 use crate::{get_juliaup_target, get_own_version};
11 use anyhow::{anyhow, bail};
12
13 update_version_db(&None, paths).with_context(|| "Failed to update versions db.")?;
14
15 let mut config_file = load_mut_config_db(paths)
16 .with_context(|| "`selfupdate` command failed to load configuration db.")?;
17
18 let juliaup_channel = match &config_file.self_data.juliaup_channel {
19 Some(juliaup_channel) => juliaup_channel.to_string(),
20 None => "release".to_string(),
21 };
22
23 let juliaupserver_base =
24 get_juliaserver_base_url().with_context(|| "Failed to get Juliaup server base URL.")?;
25
26 let version_url_path = match juliaup_channel.as_str() {
27 "release" => "juliaup/RELEASECHANNELVERSION",
28 "releasepreview" => "juliaup/RELEASEPREVIEWCHANNELVERSION",
29 "dev" => "juliaup/DEVCHANNELVERSION",
30 _ => bail!(
31 "Juliaup is configured to a channel named '{}' that does not exist.",
32 &juliaup_channel
33 ),
34 };
35
36 eprintln!("Checking for self-updates");
37
38 let version_url = juliaupserver_base.join(version_url_path).with_context(|| {
39 format!(
40 "Failed to construct a valid url from '{}' and '{}'.",
41 juliaupserver_base, version_url_path
42 )
43 })?;
44
45 let version = download_juliaup_version(version_url.as_ref())?;
46
47 config_file.self_data.last_selfupdate = Some(chrono::Utc::now());
48
49 save_config_db(&mut config_file).with_context(|| "Failed to save configuration file.")?;
50
51 if version == get_own_version().unwrap() {
52 eprintln!(
53 "Juliaup unchanged on channel '{}' - {}",
54 juliaup_channel, version
55 );
56 } else {
57 let juliaup_target = get_juliaup_target();
58
59 let juliaupserver_base =
60 get_juliaserver_base_url().with_context(|| "Failed to get Juliaup server base URL.")?;
61
62 let download_url_path =
63 format!("juliaup/bin/juliaup-{}-{}.tar.gz", version, juliaup_target);
64
65 let new_juliaup_url = juliaupserver_base
66 .join(&download_url_path)
67 .with_context(|| {
68 format!(
69 "Failed to construct a valid url from '{}' and '{}'.",
70 juliaupserver_base, download_url_path
71 )
72 })?;
73
74 let my_own_path = std::env::current_exe()
75 .with_context(|| "Could not determine the path of the running exe.")?;
76
77 let my_own_folder = my_own_path
78 .parent()
79 .ok_or_else(|| anyhow!("Could not determine parent."))?;
80
81 eprintln!(
82 "Found new version {} on channel {}.",
83 version, juliaup_channel
84 );
85
86 download_extract_sans_parent(new_juliaup_url.as_ref(), my_own_folder, 0)?;
87 eprintln!("Updated Juliaup to version {}.", version);
88 }
89
90 Ok(())
91}
92
93#[cfg(feature = "windowsstore")]
94pub fn run_command_selfupdate(paths: &GlobalPaths) -> Result<()> {
95 use windows::{
96 core::Interface,
97 Win32::{System::Console::GetConsoleWindow, UI::Shell::IInitializeWithWindow},
98 };
99
100 update_version_db(&None, paths).with_context(|| "Failed to update versions db.")?;
101
102 let update_manager = windows::Services::Store::StoreContext::GetDefault()
103 .with_context(|| "Failed to get the store context.")?;
104
105 let interop: IInitializeWithWindow = update_manager
106 .cast()
107 .with_context(|| "Failed to cast the store context to IInitializeWithWindow.")?;
108
109 unsafe {
110 let x = GetConsoleWindow();
111
112 interop
113 .Initialize(x)
114 .with_context(|| "Call to IInitializeWithWindow.Initialize failed.")?;
115 }
116
117 let updates = update_manager
118 .GetAppAndOptionalStorePackageUpdatesAsync()
119 .with_context(|| "Call to GetAppAndOptionalStorePackageUpdatesAsync failed.")?
120 .join()
121 .with_context(|| {
122 "get on the return of GetAppAndOptionalStorePackageUpdatesAsync failed."
123 })?;
124
125 if updates
126 .Size()
127 .with_context(|| "Call to Size on update results failed.")?
128 > 0
129 {
130 eprintln!("An update is available.");
131
132 let download_operation = update_manager
133 .RequestDownloadAndInstallStorePackageUpdatesAsync(&updates)
134 .with_context(|| "Call to RequestDownloadAndInstallStorePackageUpdatesAsync failed.")?;
135
136 download_operation.join().with_context(|| {
137 "get on result from RequestDownloadAndInstallStorePackageUpdatesAsync failed."
138 })?;
139 } else {
141 eprintln!("No updates available.");
142 }
143
144 Ok(())
145}
146
147#[cfg(not(any(feature = "windowsstore", feature = "selfupdate")))]
148pub fn run_command_selfupdate(paths: &GlobalPaths) -> Result<()> {
149 update_version_db(&None, paths).with_context(|| "Failed to update versions db.")?;
150 Ok(())
151}