<commit_before># Usage: scoop cleanup <app> [options]
# Summary: Cleanup apps by removing old versions
# Help: 'scoop cleanup' cleans Scoop apps by removing old versions.
# 'scoop cleanup <app>' cleans up the old versions of that app if said versions exist.
#
# You can use '*' in place of <app> to cleanup all apps.
#
# Options:
#   --global, -g       Cleanup a globally installed app
. "$psscriptroot\..\lib\core.ps1"
. "$psscriptroot\..\lib\manifest.ps1"
. "$psscriptroot\..\lib\buckets.ps1"
. "$psscriptroot\..\lib\versions.ps1"
. "$psscriptroot\..\lib\getopt.ps1"
. "$psscriptroot\..\lib\help.ps1"

reset_aliases

$opt, $apps, $err = getopt $args 'g' 'global'
if ($err) { "scoop cleanup: $err"; exit 1 }
$global = $opt.g -or $opt.global

if(!$apps) { 'ERROR: <app> missing'; my_usage; exit 1 }

if($global -and !(is_admin)) {
    'ERROR: you need admin rights to cleanup global apps'; exit 1
}

function cleanup($app, $global, $verbose) {
    $current_version  = current_version $app $global
    $versions = versions $app $global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
    if(!$versions) {
        if($verbose) { success "$app is already clean" }
        return
    }

    write-host -f yellow "Removing $app`:" -nonewline
    $versions | ForEach-Object {
        $version = $_
        write-host " $version" -nonewline
        $dir = versiondir $app $version $global
        Get-ChildItem $dir | ForEach-Object {
            $file = $_
            if($null -ne $file.LinkType) {
                fsutil.exe reparsepoint delete $file.FullName | out-null
            }
        }
        Remove-Item $dir -Recurse -Force
    }
    write-host ''
}

if($apps) {
    $verbose = $true
    if ($apps -eq '*') {
        $verbose = $false
        $apps = applist (installed_apps $false) $false
        if ($global) {
            $apps += applist (installed_apps $true) $true
        }
    }
    else {
        $apps = ensure_all_installed $apps $global
    }

    # $apps is now a list of ($app, $global) tuples
    $apps | ForEach-Object { cleanup @_ $verbose }

    if(!$verbose) {
        success 'Everything is shiny now!'
    }
}

exit 0
<commit_msg>scoop-cleanup: handle with junction better (#2882)<commit_after># Usage: scoop cleanup <app> [options]
# Summary: Cleanup apps by removing old versions
# Help: 'scoop cleanup' cleans Scoop apps by removing old versions.
# 'scoop cleanup <app>' cleans up the old versions of that app if said versions exist.
#
# You can use '*' in place of <app> to cleanup all apps.
#
# Options:
#   --global, -g       Cleanup a globally installed app
. "$psscriptroot\..\lib\core.ps1"
. "$psscriptroot\..\lib\manifest.ps1"
. "$psscriptroot\..\lib\buckets.ps1"
. "$psscriptroot\..\lib\versions.ps1"
. "$psscriptroot\..\lib\getopt.ps1"
. "$psscriptroot\..\lib\help.ps1"

reset_aliases

$opt, $apps, $err = getopt $args 'g' 'global'
if ($err) { "scoop cleanup: $err"; exit 1 }
$global = $opt.g -or $opt.global

if(!$apps) { 'ERROR: <app> missing'; my_usage; exit 1 }

if($global -and !(is_admin)) {
    'ERROR: you need admin rights to cleanup global apps'; exit 1
}

function cleanup($app, $global, $verbose) {
    $current_version  = current_version $app $global
    $versions = versions $app $global | Where-Object { $_ -ne $current_version -and $_ -ne 'current' }
    if(!$versions) {
        if($verbose) { success "$app is already clean" }
        return
    }

    write-host -f yellow "Removing $app`:" -nonewline
    $versions | ForEach-Object {
        $version = $_
        write-host " $version" -nonewline
        $dir = versiondir $app $version $global
        Get-ChildItem $dir | ForEach-Object {
            $file = $_
            # the file is a junction
            if ($null -ne $file.LinkType -and $file -is [System.IO.DirectoryInfo]) {
                # remove read-only attribute on the link
                attrib -R /L $file
                # remove the junction
                $filepath = Resolve-Path $file
                & "$env:COMSPEC" /c "rmdir /s /q $filepath"
            }
        }
        Remove-Item $dir -ErrorAction Stop -Recurse -Force
    }
    write-host ''
}

if($apps) {
    $verbose = $true
    if ($apps -eq '*') {
        $verbose = $false
        $apps = applist (installed_apps $false) $false
        if ($global) {
            $apps += applist (installed_apps $true) $true
        }
    }
    else {
        $apps = ensure_all_installed $apps $global
    }

    # $apps is now a list of ($app, $global) tuples
    $apps | ForEach-Object { cleanup @_ $verbose }

    if(!$verbose) {
        success 'Everything is shiny now!'
    }
}

exit 0

{'fraction_non_alphanumeric': 0.14279569892473118, 'fraction_numerical': 0.005161290322580645, 'mean_word_length': 2.3874726875455208, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4300678', 'n_tokens_mistral': 1561, 'n_tokens_neox': 1490, 'n_words': 452}