Skip to content

Commit

Permalink
Add --prune-orphans option in gc
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
christiangnrd committed Jan 17, 2025
1 parent f439a3b commit 843f0ca
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 8 deletions.
5 changes: 4 additions & 1 deletion src/bin/juliaup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ fn main() -> Result<()> {
Juliaup::Remove { channel } => run_command_remove(&channel, &paths),
Juliaup::Status {} => run_command_status(&paths),
Juliaup::Update { channel } => run_command_update(channel, &paths),
Juliaup::Gc { prune_linked } => run_command_gc(prune_linked, &paths),
Juliaup::Gc {
prune_linked,
prune_orphans,
} => run_command_gc(prune_linked, prune_orphans, &paths),
Juliaup::Link {
channel,
file,
Expand Down
2 changes: 2 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub enum Juliaup {
Gc {
#[clap(long)]
prune_linked: bool,
#[clap(long)]
prune_orphans: bool,
},
#[clap(subcommand, name = "config")]
/// Juliaup configuration
Expand Down
4 changes: 2 additions & 2 deletions src/command_gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ use crate::global_paths::GlobalPaths;
use crate::operations::garbage_collect_versions;
use anyhow::{Context, Result};

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

garbage_collect_versions(prune_linked, &mut config_file.data, paths)?;
garbage_collect_versions(prune_linked, prune_orphans, &mut config_file.data, paths)?;

save_config_db(&mut config_file)
.with_context(|| "`gc` command failed to save configuration db.")?;
Expand Down
2 changes: 1 addition & 1 deletion src/command_remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn run_command_remove(channel: &str, paths: &GlobalPaths) -> Result<()> {
#[cfg(not(windows))]
remove_symlink(&format!("julia-{}", channel))?;

garbage_collect_versions(false, &mut config_file.data, paths)?;
garbage_collect_versions(false, false, &mut config_file.data, paths)?;

save_config_db(&mut config_file).with_context(|| {
format!(
Expand Down
2 changes: 1 addition & 1 deletion src/command_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub fn run_command_update(channel: Option<String>, paths: &GlobalPaths) -> Resul
}
};

garbage_collect_versions(false, &mut config_file.data, paths)?;
garbage_collect_versions(false, false, &mut config_file.data, paths)?;

save_config_db(&mut config_file)
.with_context(|| "`update` command failed to save configuration db.")?;
Expand Down
65 changes: 62 additions & 3 deletions src/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use console::style;
use flate2::read::GzDecoder;
use indicatif::{ProgressBar, ProgressStyle};
use indoc::formatdoc;
use itertools::Itertools;
use regex::Regex;
use semver::Version;
#[cfg(not(windows))]
Expand Down Expand Up @@ -687,6 +688,7 @@ pub fn install_non_db_version(

pub fn garbage_collect_versions(
prune_linked: bool,
prune_orphans: bool,
config_data: &mut JuliaupConfig,
paths: &GlobalPaths,
) -> Result<()> {
Expand All @@ -712,22 +714,79 @@ pub fn garbage_collect_versions(
config_data.installed_versions.remove(&version_to_delete);
}

// GC for DirectDownloadChannel channels
let jl_dirs: Vec<_> = std::fs::read_dir(&paths.juliauphome)?
.into_iter()
.filter_map_ok(|r| {
if r.path().is_dir() {
Some(r.path())
} else {
None
}
})
.filter_map_ok(|r| {
let dirname = r.file_name()?.to_str()?;
if dirname.starts_with("julia-") {
Some(dirname.to_owned())
} else {
None
}
})
.filter(|r| r.is_ok())
.map(|r| r.unwrap()) // This is safe, since we only have the Ok variants
.collect();

if prune_orphans {
for jl_dir in jl_dirs {
if config_data
.installed_channels
.iter()
.all(|(_, detail)| match &detail {
JuliaupConfigChannel::SystemChannel { version } => {
let channel_path = &config_data.installed_versions[version]
.path
.replace("./", "");
*channel_path != jl_dir
}
JuliaupConfigChannel::DirectDownloadChannel {
path,
url: _,
local_etag: _,
server_etag: _,
version: _,
} => {
let channel_path = path.replace("./", "");
channel_path != jl_dir
}
JuliaupConfigChannel::LinkedChannel {
command: _,
args: _,
} => true,
})
{
if std::fs::remove_dir_all(paths.juliauphome.join(&jl_dir)).is_err() {
eprintln!("WARNING: Failed to delete {}. You can try to delete at a later point by running `juliaup gc`.", &jl_dir)
}
}
}
}

if prune_linked {
let mut channels_to_uninstall: Vec<String> = Vec::new();
let mut linked_channels_to_uninstall: Vec<String> = Vec::new();
for (installed_channel, detail) in &config_data.installed_channels {
match &detail {
JuliaupConfigChannel::LinkedChannel {
command: cmd,
args: _,
} => {
if !is_valid_julia_path(&PathBuf::from(cmd)) {
channels_to_uninstall.push(installed_channel.clone());
linked_channels_to_uninstall.push(installed_channel.clone());
}
}
_ => (),
}
}
for channel in channels_to_uninstall {
for channel in linked_channels_to_uninstall {
remove_symlink(&format!("julia-{}", &channel))?;
config_data.installed_channels.remove(&channel);
}
Expand Down

0 comments on commit 843f0ca

Please sign in to comment.