Skip to content

Commit 2086d2d

Browse files
sloedegiordano
andauthored
Add manage_shards to interactively remove compiler shards (#303)
* Add `manage_shards` to interactively remove compiler shards * Add total size output * Apply suggestions from code review Co-authored-by: Mosè Giordano <giordano@users.noreply.github.com> * isfile -> !isdir * Make `isless` for shards a local function --------- Co-authored-by: Mosè Giordano <giordano@users.noreply.github.com>
1 parent 5213065 commit 2086d2d

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
1919
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
2020
OutputCollectors = "6c11c7d4-943b-4e2b-80de-f2cfc2930a8c"
2121
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
22+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
2223
ProgressMeter = "92933f4c-e287-5a05-a399-4b506db050ca"
24+
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
2325
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
2426
SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce"
2527
Scratch = "6c6a2e73-6563-6170-7368-637461726353"

src/BinaryBuilderBase.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export AbstractSource, AbstractDependency, SetupSource, PatchSource,
2222
nbits, proc_family, storage_dir, extract_kwargs, extract_fields,
2323
download_source, setup_workspace, setup_dependencies, update_registry,
2424
getname, cleanup_dependencies, compress_dir, prepare_for_deletion,
25-
run_interactive, sourcify, dependencify, with_logfile, get_concrete_platform
25+
run_interactive, sourcify, dependencify, with_logfile, get_concrete_platform,
26+
manage_shards
2627

2728
include("compat.jl")
2829

src/Rootfs.jl

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
export supported_platforms, expand_gfortran_versions, expand_cxxstring_abis, expand_microarchitectures
22

3-
using Pkg.Artifacts: load_artifacts_toml, ensure_all_artifacts_installed
3+
using Pkg.Artifacts: load_artifacts_toml, ensure_all_artifacts_installed, artifact_path
44
using Base.BinaryPlatforms: set_compare_strategy!, compare_version_cap
5+
using REPL.TerminalMenus
6+
using Printf: @sprintf
57

68
# This is a type that encompasses a shard; it makes it easy to pass it around,
79
# get its download url, extraction url, mounting url, etc...
@@ -1100,3 +1102,88 @@ function installed_shards()
11001102

11011103
return all_compiler_shards()[idx]
11021104
end
1105+
1106+
"""
1107+
manage_shards(; sort_by=:name, rev=false)
1108+
1109+
Open a prompt allowing a user to selectively remove downloaded compiler shards.
1110+
By default, the shards are sorted by name, alternatively you can sort them by
1111+
file size on disk by specifying `sort_by=:size`. With `rev=true` you can
1112+
reverse the sort order.
1113+
"""
1114+
function manage_shards(; sort_by=:name, rev=false)
1115+
# Get all installed shards
1116+
shards = installed_shards()
1117+
1118+
# Obtain directory sizes for the artifacts
1119+
totalsizes = totalsize.(Artifacts.artifact_path.(shard_source_artifact_hash.(shards)))
1120+
1121+
# Sort shards and totalsizes
1122+
if sort_by === :name
1123+
function isless_shards(a::CompilerShard, b::CompilerShard)
1124+
return isless((a.name, a.version, string(a.target), a.host, a.archive_type),
1125+
(b.name, b.version, string(b.target), b.host, b.archive_type))
1126+
end
1127+
1128+
perm = sortperm(shards; rev, lt=isless_shards)
1129+
elseif sort_by == :size
1130+
perm = sortperm(totalsizes; rev)
1131+
else
1132+
error("unsupported sort value: :$sort_by (allowed: :name, :size)")
1133+
end
1134+
shards .= shards[perm]
1135+
totalsizes .= totalsizes[perm]
1136+
1137+
# Build menu items
1138+
menuitems = similar(shards, String)
1139+
for i in eachindex(shards, totalsizes)
1140+
menuitems[i] = @sprintf("(%5.3f GiB) %s", totalsizes[i] / 2^30, shards[i])
1141+
end
1142+
1143+
# Prompt user
1144+
ts = @sprintf("%5.3f", sum(totalsizes) / 2^30)
1145+
manage_shards_menu = TerminalMenus.request(
1146+
"Which compiler shards should be removed (total size on disk: $ts GiB)?",
1147+
TerminalMenus.MultiSelectMenu(menuitems; pagesize = 10, charset=:ascii)
1148+
)
1149+
1150+
# Handle no selection
1151+
if isempty(manage_shards_menu)
1152+
println("Removed 0 compiler shards.")
1153+
return nothing
1154+
end
1155+
1156+
# Otherwise prompt for confirmation
1157+
println("\nThe following shards have been marked for removal:\n")
1158+
for item in menuitems[sort(Int.(manage_shards_menu))]
1159+
println(" ", item)
1160+
end
1161+
print("\nAre you sure that these should be removed? [Y/n]: ")
1162+
answer = lowercase(strip(readline()))
1163+
1164+
# If removal is confirmed, deleting the relevant artifacts
1165+
if isempty(answer) || answer == "yes" || answer == "y"
1166+
Pkg.remove_artifact.(shard_source_artifact_hash.(shards[Int.(manage_shards_menu)]))
1167+
println("Removed ", length(manage_shards_menu), " compiler shards.")
1168+
else
1169+
println("Removed 0 compiler shards.")
1170+
end
1171+
end
1172+
1173+
# Return total size on a disk of a file or directory
1174+
function totalsize(path)
1175+
if !isdir(path)
1176+
return filesize(path)
1177+
end
1178+
1179+
total = 0
1180+
for (root, dirs, files) in walkdir(path)
1181+
total += filesize(root)
1182+
1183+
for file in files
1184+
total += filesize(joinpath(root, file))
1185+
end
1186+
end
1187+
1188+
return total
1189+
end

0 commit comments

Comments
 (0)