Skip to content

Commit

Permalink
feat(cache): Add "tidy" as older cache removal command
Browse files Browse the repository at this point in the history
- Keep two items in cache for every app
- Files that are less than one month old are not deleted
- Automatically remove older cache of the app after an update
- Short option to do not use cache changed form `-k` to `-d`
(for "download")
- Add option to keep older cache, with `-k` (for "keep")
as short option to `update` command
- Add long option `--keep-cache` to `update` command
  • Loading branch information
flodavid committed Nov 24, 2024
1 parent 84e00fd commit 9565c65
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 8 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## [Unreleased](https://github.com/ScoopInstaller/Scoop/compare/master...develop)

### BREAKING CHANGE

- **scoop-install|update**: `-k`option that skipped cache and forced redownload is replaced by `-d`. `-k` now keeps older cache after app update

### Features

- **scoop-cache|update**: New tidy command that removes older packages from cache. Automatically run it after app update ([#6068](https://github.com/ScoopInstaller/Scoop/issues/6068))

### Bug Fixes

- **scoop-download|install|update:** Fallback to default downloader when aria2 fails ([#4292](https://github.com/ScoopInstaller/Scoop/issues/4292))
Expand Down
35 changes: 35 additions & 0 deletions lib/cache.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Remove older cache of the given app
function tidy_cache([String] $app, [bool] $total_log = $false) {
if ($app -like "*.json") { return }

# Dependencies of the format "bucket/dependency" install in a directory of form
# "dependency". So we need to extract the bucket from the name and only use the app
# name
$app = ($app -split '/|\\')[-1]

$files = @(Get-ChildItem $cachedir | Where-Object -Property Name -Value "^$app#" -Match | Sort-Object LastWriteTime )
if ($files.Count -le 2) {
return
}

# do not remove last two files
$files = $files[0..($files.Count - 3)]
# remove only items more than one month old
$files = $files| Where-Object {$_.LastWriteTime -lt (Get-Date).AddMonths(-1)}
if ($files.Count -le 0) {
if ($total_log) { Write-Host "Nothing to do" -ForegroundColor Yellow }
return
}
Write-Host -f yellow "Removing older cache for $app`:" -NoNewline

$totalLength = ($files | Measure-Object -Property Length -Sum).Sum
$files | ForEach-Object {
Write-Host " $(($_ -split '#')[1])" -NoNewline
Remove-Item $_.FullName
}

Write-Host ''
if ($total_log) {
Write-Host "Deleted: $($files.Count) $(pluralize $files.Count 'file' 'files'), $(filesize $totalLength)" -ForegroundColor Yellow
}
}
40 changes: 39 additions & 1 deletion libexec/scoop-cache.ps1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Usage: scoop cache show|rm [app(s)]
# Usage: scoop cache show|rm|tidy [app(s)]
# Summary: Show or clear the download cache
# Help: Scoop caches downloads so you don't need to download the same files
# when you uninstall and re-install the same version of an app.
Expand All @@ -7,13 +7,19 @@
# scoop cache show
# to see what's in the cache, and
# scoop cache rm <app> to remove downloads for a specific app.
# Or to only remove downloads that older,
# scoop cache tidy <app> removes ones older than a month, keeping the two most recent
#
# To clear everything in your cache, use:
# scoop cache rm *
# To remove older items for all apps, use:
# scoop cache tidy *
# You can also use the `-a/--all` switch in place of `*` here

param($cmd)

. "$PSScriptRoot\..\lib\cache.ps1"

function cacheinfo($file) {
$app, $version, $url = $file.Name -split '#'
New-Object PSObject -Property @{ Name = $app; Version = $version; Length = $file.Length }
Expand Down Expand Up @@ -58,10 +64,42 @@ function cacheremove($app) {
Write-Host "Deleted: $($files.Length) $(pluralize $files.Length 'file' 'files'), $(filesize $totalLength)" -ForegroundColor Yellow
}

function cache_remove_older($app) {
if (!$app) {
'ERROR: <app(s)> missing'
my_usage
exit 1
} elseif ($app -eq '*' -or $app -eq '-a' -or $app -eq '--all') {
$files = @(Get-ChildItem $cachedir)
$totalLength = ($files | Measure-Object -Property Length -Sum).Sum
# Get all apps with cache, and remove their older packages
$apps = @()
$files | ForEach-Object {
$apps += ($_ -split '#', 2)[0]
}
$apps = $apps | Select-Object -Unique

$apps | ForEach-Object {
tidy_cache $_
}

$filesAfter = @(Get-ChildItem $cachedir)
$totalLengthAfter = ($filesAfter | Measure-Object -Property Length -Sum).Sum
$filesRemoved = $files.Length - $filesAfter.length
$sizeRemoved = $totalLength - $totalLengthAfter
Write-Host "Deleted: $($filesRemoved) $(pluralize $filesRemoved 'file' 'files'), $(filesize $sizeRemoved)" -ForegroundColor Yellow
} else {
tidy_cache $app $true
}
}

switch($cmd) {
'rm' {
cacheremove $Args
}
'tidy' {
cache_remove_older $Args
}
'show' {
cacheshow $Args
}
Expand Down
4 changes: 2 additions & 2 deletions libexec/scoop-install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
# Options:
# -g, --global Install the app globally
# -i, --independent Don't install dependencies automatically
# -k, --no-cache Don't use the download cache
# -d, --no-cache Force redownload by not using the download cache
# -s, --skip-hash-check Skip hash validation (use with caution!)
# -u, --no-update-scoop Don't update Scoop before installing if it's outdated
# -a, --arch <32bit|64bit|arm64> Use the specified architecture, if the app supports it
Expand All @@ -49,7 +49,7 @@ if ($err) { "scoop install: $err"; exit 1 }
$global = $opt.g -or $opt.global
$check_hash = !($opt.s -or $opt.'skip-hash-check')
$independent = $opt.i -or $opt.independent
$use_cache = !($opt.k -or $opt.'no-cache')
$use_cache = !($opt.d -or $opt.'no-cache')
$architecture = Get-DefaultArchitecture
try {
$architecture = Format-ArchitectureString ($opt.a + $opt.arch)
Expand Down
18 changes: 13 additions & 5 deletions libexec/scoop-update.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
# -f, --force Force update even when there isn't a newer version
# -g, --global Update a globally installed app
# -i, --independent Don't install dependencies automatically
# -k, --no-cache Don't use the download cache
# -d, --no-cache Force redownload by not using the download cache
# -k, --keep-cache Don't remove older cached install packages
# -s, --skip-hash-check Skip hash validation (use with caution!)
# -q, --quiet Hide extraneous messages
# -a, --all Update all apps (alternative to '*')
Expand All @@ -25,16 +26,18 @@
. "$PSScriptRoot\..\lib\depends.ps1"
. "$PSScriptRoot\..\lib\install.ps1"
. "$PSScriptRoot\..\lib\download.ps1"
. "$PSScriptRoot\..\lib\cache.ps1"
if (get_config USE_SQLITE_CACHE) {
. "$PSScriptRoot\..\lib\database.ps1"
}

$opt, $apps, $err = getopt $args 'gfiksqa' 'global', 'force', 'independent', 'no-cache', 'skip-hash-check', 'quiet', 'all'
$opt, $apps, $err = getopt $args 'gfsdkqia' 'global', 'force', 'skip-hash-check', 'no-cache', 'keep-cache', 'quiet', 'independent', 'all'
if ($err) { "scoop update: $err"; exit 1 }
$global = $opt.g -or $opt.global
$force = $opt.f -or $opt.force
$check_hash = !($opt.s -or $opt.'skip-hash-check')
$use_cache = !($opt.k -or $opt.'no-cache')
$use_cache = !($opt.d -or $opt.'no-cache')
$keep_cache = $use_cache -and ($opt.k -or $opt.'keep-cache')
$quiet = $opt.q -or $opt.quiet
$independent = $opt.i -or $opt.independent
$all = $opt.a -or $opt.all
Expand Down Expand Up @@ -258,7 +261,7 @@ function Sync-Bucket {
}
}

function update($app, $global, $quiet = $false, $independent, $suggested, $use_cache = $true, $check_hash = $true) {
function update($app, $global, $quiet = $false, $independent, $suggested, $use_cache = $true, $keep_cache = $false, $check_hash = $true) {
$old_version = Select-CurrentVersion -AppName $app -Global:$global
$old_manifest = installed_manifest $app $old_version $global
$install = install_info $app $old_version $global
Expand Down Expand Up @@ -383,6 +386,11 @@ function update($app, $global, $quiet = $false, $independent, $suggested, $use_c
ensure_none_failed $apps
$apps.Where({ !(installed $_) }) + $app | ForEach-Object { install_app $_ $architecture $global $suggested $use_cache $check_hash }
}

# remove older cache after update
if (!$keep_cache) {
tidy_cache $app $true
}
}

if (-not ($apps -or $all)) {
Expand Down Expand Up @@ -462,7 +470,7 @@ if (-not ($apps -or $all)) {

$suggested = @{}
# $outdated is a list of ($app, $global) tuples
$outdated | ForEach-Object { update @_ $quiet $independent $suggested $use_cache $check_hash }
$outdated | ForEach-Object { update @_ $quiet $independent $suggested $use_cache $keep_cache $check_hash }
}

exit 0

0 comments on commit 9565c65

Please sign in to comment.