Skip to content

Commit 039ca60

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 e02efc8 commit 039ca60

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))]
@@ -748,6 +749,7 @@ pub fn install_non_db_version(
748749

749750
pub fn garbage_collect_versions(
750751
prune_linked: bool,
752+
prune_orphans: bool,
751753
config_data: &mut JuliaupConfig,
752754
paths: &GlobalPaths,
753755
) -> Result<()> {
@@ -773,22 +775,79 @@ pub fn garbage_collect_versions(
773775
config_data.installed_versions.remove(&version_to_delete);
774776
}
775777

778+
// GC for DirectDownloadChannel channels
779+
let jl_dirs: Vec<_> = std::fs::read_dir(&paths.juliauphome)?
780+
.into_iter()
781+
.filter_map_ok(|r| {
782+
if r.path().is_dir() {
783+
Some(r.path())
784+
} else {
785+
None
786+
}
787+
})
788+
.filter_map_ok(|r| {
789+
let dirname = r.file_name()?.to_str()?;
790+
if dirname.starts_with("julia-") {
791+
Some(dirname.to_owned())
792+
} else {
793+
None
794+
}
795+
})
796+
.filter(|r| r.is_ok())
797+
.map(|r| r.unwrap()) // This is safe, since we only have the Ok variants
798+
.collect();
799+
800+
if prune_orphans {
801+
for jl_dir in jl_dirs {
802+
if config_data
803+
.installed_channels
804+
.iter()
805+
.all(|(_, detail)| match &detail {
806+
JuliaupConfigChannel::SystemChannel { version } => {
807+
let channel_path = &config_data.installed_versions[version]
808+
.path
809+
.replace("./", "");
810+
*channel_path != jl_dir
811+
}
812+
JuliaupConfigChannel::DirectDownloadChannel {
813+
path,
814+
url: _,
815+
local_etag: _,
816+
server_etag: _,
817+
version: _,
818+
} => {
819+
let channel_path = path.replace("./", "");
820+
channel_path != jl_dir
821+
}
822+
JuliaupConfigChannel::LinkedChannel {
823+
command: _,
824+
args: _,
825+
} => true,
826+
})
827+
{
828+
if std::fs::remove_dir_all(paths.juliauphome.join(&jl_dir)).is_err() {
829+
eprintln!("WARNING: Failed to delete {}. You can try to delete at a later point by running `juliaup gc`.", &jl_dir)
830+
}
831+
}
832+
}
833+
}
834+
776835
if prune_linked {
777-
let mut channels_to_uninstall: Vec<String> = Vec::new();
836+
let mut linked_channels_to_uninstall: Vec<String> = Vec::new();
778837
for (installed_channel, detail) in &config_data.installed_channels {
779838
match &detail {
780839
JuliaupConfigChannel::LinkedChannel {
781840
command: cmd,
782841
args: _,
783842
} => {
784843
if !is_valid_julia_path(&PathBuf::from(cmd)) {
785-
channels_to_uninstall.push(installed_channel.clone());
844+
linked_channels_to_uninstall.push(installed_channel.clone());
786845
}
787846
}
788847
_ => (),
789848
}
790849
}
791-
for channel in channels_to_uninstall {
850+
for channel in linked_channels_to_uninstall {
792851
remove_symlink(&format!("julia-{}", &channel))?;
793852
config_data.installed_channels.remove(&channel);
794853
}

0 commit comments

Comments
 (0)