Skip to content

Commit 843f0ca

Browse files
committed
Add --prune-orphans option in gc
This is to remove julia folders in the juliaup folder whose path is not referenced in juliaup.json This will typically clean up direct download version that were somehow not removed.
1 parent f439a3b commit 843f0ca

6 files changed

+72
-8
lines changed

src/bin/juliaup.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ fn main() -> Result<()> {
9696
Juliaup::Remove { channel } => run_command_remove(&channel, &paths),
9797
Juliaup::Status {} => run_command_status(&paths),
9898
Juliaup::Update { channel } => run_command_update(channel, &paths),
99-
Juliaup::Gc { prune_linked } => run_command_gc(prune_linked, &paths),
99+
Juliaup::Gc {
100+
prune_linked,
101+
prune_orphans,
102+
} => run_command_gc(prune_linked, prune_orphans, &paths),
100103
Juliaup::Link {
101104
channel,
102105
file,

src/cli.rs

+2
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ pub enum Juliaup {
3636
Gc {
3737
#[clap(long)]
3838
prune_linked: bool,
39+
#[clap(long)]
40+
prune_orphans: bool,
3941
},
4042
#[clap(subcommand, name = "config")]
4143
/// Juliaup configuration

src/command_gc.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ use crate::global_paths::GlobalPaths;
33
use crate::operations::garbage_collect_versions;
44
use anyhow::{Context, Result};
55

6-
pub fn run_command_gc(prune_linked: bool, paths: &GlobalPaths) -> Result<()> {
6+
pub fn run_command_gc(prune_linked: bool, prune_orphans: bool, paths: &GlobalPaths) -> Result<()> {
77
let mut config_file = load_mut_config_db(paths)
88
.with_context(|| "`gc` command failed to load configuration data.")?;
99

10-
garbage_collect_versions(prune_linked, &mut config_file.data, paths)?;
10+
garbage_collect_versions(prune_linked, prune_orphans, &mut config_file.data, paths)?;
1111

1212
save_config_db(&mut config_file)
1313
.with_context(|| "`gc` command failed to save configuration db.")?;

src/command_remove.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub fn run_command_remove(channel: &str, paths: &GlobalPaths) -> Result<()> {
6363
#[cfg(not(windows))]
6464
remove_symlink(&format!("julia-{}", channel))?;
6565

66-
garbage_collect_versions(false, &mut config_file.data, paths)?;
66+
garbage_collect_versions(false, false, &mut config_file.data, paths)?;
6767

6868
save_config_db(&mut config_file).with_context(|| {
6969
format!(

src/command_update.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ pub fn run_command_update(channel: Option<String>, paths: &GlobalPaths) -> Resul
147147
}
148148
};
149149

150-
garbage_collect_versions(false, &mut config_file.data, paths)?;
150+
garbage_collect_versions(false, false, &mut config_file.data, paths)?;
151151

152152
save_config_db(&mut config_file)
153153
.with_context(|| "`update` command failed to save configuration db.")?;

src/operations.rs

+62-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use console::style;
2222
use flate2::read::GzDecoder;
2323
use indicatif::{ProgressBar, ProgressStyle};
2424
use indoc::formatdoc;
25+
use itertools::Itertools;
2526
use regex::Regex;
2627
use semver::Version;
2728
#[cfg(not(windows))]
@@ -687,6 +688,7 @@ pub fn install_non_db_version(
687688

688689
pub fn garbage_collect_versions(
689690
prune_linked: bool,
691+
prune_orphans: bool,
690692
config_data: &mut JuliaupConfig,
691693
paths: &GlobalPaths,
692694
) -> Result<()> {
@@ -712,22 +714,79 @@ pub fn garbage_collect_versions(
712714
config_data.installed_versions.remove(&version_to_delete);
713715
}
714716

717+
// GC for DirectDownloadChannel channels
718+
let jl_dirs: Vec<_> = std::fs::read_dir(&paths.juliauphome)?
719+
.into_iter()
720+
.filter_map_ok(|r| {
721+
if r.path().is_dir() {
722+
Some(r.path())
723+
} else {
724+
None
725+
}
726+
})
727+
.filter_map_ok(|r| {
728+
let dirname = r.file_name()?.to_str()?;
729+
if dirname.starts_with("julia-") {
730+
Some(dirname.to_owned())
731+
} else {
732+
None
733+
}
734+
})
735+
.filter(|r| r.is_ok())
736+
.map(|r| r.unwrap()) // This is safe, since we only have the Ok variants
737+
.collect();
738+
739+
if prune_orphans {
740+
for jl_dir in jl_dirs {
741+
if config_data
742+
.installed_channels
743+
.iter()
744+
.all(|(_, detail)| match &detail {
745+
JuliaupConfigChannel::SystemChannel { version } => {
746+
let channel_path = &config_data.installed_versions[version]
747+
.path
748+
.replace("./", "");
749+
*channel_path != jl_dir
750+
}
751+
JuliaupConfigChannel::DirectDownloadChannel {
752+
path,
753+
url: _,
754+
local_etag: _,
755+
server_etag: _,
756+
version: _,
757+
} => {
758+
let channel_path = path.replace("./", "");
759+
channel_path != jl_dir
760+
}
761+
JuliaupConfigChannel::LinkedChannel {
762+
command: _,
763+
args: _,
764+
} => true,
765+
})
766+
{
767+
if std::fs::remove_dir_all(paths.juliauphome.join(&jl_dir)).is_err() {
768+
eprintln!("WARNING: Failed to delete {}. You can try to delete at a later point by running `juliaup gc`.", &jl_dir)
769+
}
770+
}
771+
}
772+
}
773+
715774
if prune_linked {
716-
let mut channels_to_uninstall: Vec<String> = Vec::new();
775+
let mut linked_channels_to_uninstall: Vec<String> = Vec::new();
717776
for (installed_channel, detail) in &config_data.installed_channels {
718777
match &detail {
719778
JuliaupConfigChannel::LinkedChannel {
720779
command: cmd,
721780
args: _,
722781
} => {
723782
if !is_valid_julia_path(&PathBuf::from(cmd)) {
724-
channels_to_uninstall.push(installed_channel.clone());
783+
linked_channels_to_uninstall.push(installed_channel.clone());
725784
}
726785
}
727786
_ => (),
728787
}
729788
}
730-
for channel in channels_to_uninstall {
789+
for channel in linked_channels_to_uninstall {
731790
remove_symlink(&format!("julia-{}", &channel))?;
732791
config_data.installed_channels.remove(&channel);
733792
}

0 commit comments

Comments
 (0)