579579const UsageDict = Dict{String, DateTime}
580580const UsageByDepotDict = Dict{String, UsageDict}
581581
582- """
583- gc(ctx::Context=Context(); verbose=false, force=false, kwargs...)
584-
585- Garbage-collect package and artifact installations by sweeping over all known
586- `Manifest.toml` and `Artifacts.toml` files, noting those that have been deleted, and then
587- finding artifacts and packages that are thereafter not used by any other projects.
588- Unused packages, artifacts, repos, and scratch spaces are immediately deleted.
589-
590- Garbage collection is only applied to the "user depot", e.g. the first entry in the
591- depot path. If you want to run `gc` on all depots set `force=true` (this might require
592- admin privileges depending on the setup).
593-
594- Use verbose mode (`verbose=true`) for detailed output.
595- """
596- function gc (ctx:: Context = Context (); collect_delay:: Union{Period, Nothing} = nothing , verbose = false , force = false , kwargs... )
582+ function gc (ctx:: Context = Context (); collect_delay:: Union{Period, Nothing} = nothing , verbose = false , force = false , collect_unused_for:: Union{Period, Nothing} = nothing , kwargs... )
597583 Context! (ctx; kwargs... )
598584 if collect_delay != = nothing
599585 @warn " The `collect_delay` parameter is no longer used. Packages are now deleted immediately when they become unreachable."
@@ -690,6 +676,33 @@ function gc(ctx::Context = Context(); collect_delay::Union{Period, Nothing} = no
690676 all_scratch_dirs = Set (filter (Pkg. isdir_nothrow, all_scratch_dirs))
691677 all_scratch_parents = Set (filter (Pkg. isfile_nothrow, all_scratch_parents))
692678
679+ # Apply time-based filtering if collect_unused_for is specified
680+ # This creates a separate filtered set for marking packages as active,
681+ # but preserves the full manifest list for writing back to usage files
682+ manifest_tomls_for_gc = all_manifest_tomls
683+ if collect_unused_for != = nothing
684+ # Create a unified usage dict to check timestamps across all depots
685+ unified_manifest_usage = UsageDict ()
686+ for (depot, usage) in manifest_usage_by_depot
687+ for (manifest, time) in usage
688+ # Keep the most recent time if a manifest appears in multiple depots
689+ unified_manifest_usage[manifest] = max (get (unified_manifest_usage, manifest, DateTime (0 )), time)
690+ end
691+ end
692+
693+ cutoff_time = now () - collect_unused_for
694+ # Filter out manifests that haven't been used since the cutoff time
695+ # This only affects which packages are marked as active for this GC run
696+ manifest_tomls_for_gc = Set (f for f in all_manifest_tomls if get (unified_manifest_usage, f, DateTime (0 )) >= cutoff_time)
697+
698+ if verbose
699+ n_filtered = length (all_manifest_tomls) - length (manifest_tomls_for_gc)
700+ if n_filtered > 0
701+ printpkgstyle (ctx. io, :Filtered , " $(n_filtered) manifest(s) older than $(collect_unused_for) " )
702+ end
703+ end
704+ end
705+
693706 # Immediately write these back as condensed toml files
694707 function write_condensed_toml (f:: Function , usage_by_depot, fname)
695708 for (depot, usage) in usage_by_depot
@@ -868,9 +881,10 @@ function gc(ctx::Context = Context(); collect_delay::Union{Period, Nothing} = no
868881
869882
870883 # Scan manifests, parse them, read in all UUIDs listed and mark those as active
884+ # Use manifest_tomls_for_gc which excludes old manifests if collect_unused_for is set
871885 # printpkgstyle(ctx.io, :Active, "manifests:")
872886 packages_to_keep = mark (
873- process_manifest_pkgs, all_manifest_tomls , ctx,
887+ process_manifest_pkgs, manifest_tomls_for_gc , ctx,
874888 verbose = verbose, file_str = " manifest files"
875889 )
876890
@@ -881,7 +895,7 @@ function gc(ctx::Context = Context(); collect_delay::Union{Period, Nothing} = no
881895 x -> process_artifacts_toml (x, String[]),
882896 all_artifact_tomls, ctx; verbose = verbose, file_str = " artifact files"
883897 )
884- repos_to_keep = mark (process_manifest_repos, all_manifest_tomls , ctx; do_print = false )
898+ repos_to_keep = mark (process_manifest_repos, manifest_tomls_for_gc , ctx; do_print = false )
885899 # printpkgstyle(ctx.io, :Active, "scratchspaces:")
886900 spaces_to_keep = mark (
887901 x -> process_scratchspace (x, String[]),
0 commit comments