main
 1# Miscellaneous utility functions
 2
 3# Allow pasting commands prefixed with $
 4# See https://vincent.bernat.ch/en/blog/2025-zsh-autoexpand-aliases
 5function \$() { "$@" }
 6
 7# Isolate commands in a bwrap sandbox
 8# Usage:
 9#   isolate                    — shell with only PWD writable
10#   isolate --share-net        — same but with network
11#   isolate --share-net -- cmd — run cmd in sandbox
12#   isolate --no-cwd -- cmd   — no PWD access
13(( $+commands[bwrap] )) && isolate() {
14    local -a options moreoptions nocwd
15    options=(
16        --ro-bind /{,}
17        --dev /dev
18        --proc /proc
19        --tmpfs /run
20        --tmpfs /tmp
21        --tmpfs /var/tmp
22        --tmpfs $HOME
23        --unshare-all
24        --die-with-parent
25    )
26    [[ $(sysctl -en dev.tty.legacy_tiocsti) == 0 ]] || options=($options --new-session)
27    [[ -n $XDG_RUNTIME_DIR ]] && options=($options --tmpfs $XDG_RUNTIME_DIR)
28    [[ -L /etc/resolv.conf ]] && options=($options --ro-bind ${${:-/etc/resolv.conf}:A}{,})
29    case $1 in
30        (--*)
31            while [[ $# -gt 0 ]] && [[ $1 != "--" ]]; do
32                case $1 in
33                    (--no-cwd) nocwd=1 ;;
34                    (*) moreoptions=($moreoptions $1) ;;
35                esac
36                shift
37            done
38            [[ $1 == "--" ]] && shift
39            ;;
40    esac
41    [[ -z $nocwd ]] && [[ $PWD != $HOME ]] && options=($options --bind $PWD{,})
42    options=($options $moreoptions)
43
44    if [[ $# -eq 0 ]]; then
45        options=(
46            $options
47            --setenv VDE_SHELL_ISOLATED true
48            --
49            zsh -i
50        )
51    else
52        options=($options -- "$@")
53    fi
54    bwrap $options
55}
56
57# Interactive system cleanup
58clean() {
59    local prompt() {
60        local what=$1
61        local prompt="${(%):-%B}Clean $what?${(%):-%b}"
62        read -sq "?$prompt "
63        case $? in
64            0)
65                print -P "%F{green}yes%F{default}"
66                return 0
67                ;;
68        esac
69        print -P "%F{red}no%F{default}"
70        return 1
71    }
72
73    (( $+commands[podman] )) && prompt "Podman unused data" && \
74        podman system prune -f
75    (( $+commands[docker] )) && prompt "Docker unused data" && \
76        sudo docker system prune -f
77    [[ -d /nix ]] && prompt "Nix store (older than 7d)" && \
78        nix-collect-garbage --delete-older-than 7d
79    [[ -d /var/log/journal ]] && prompt "journal logs (older than 2 months)" && \
80        sudo journalctl --vacuum-time='2 months'
81    (( $+commands[go] )) && {
82        [[ -d $(go env GOMODCACHE) ]] && prompt "Go module cache" && go clean -modcache
83        [[ -d $(go env GOCACHE) ]] && prompt "Go build cache" && go clean -cache
84    }
85    (( $+commands[flatpak] )) && prompt "Flatpak unused runtimes" && \
86        flatpak uninstall --unused
87    local d
88    for d in tmp src download; do
89        [[ -d ~/$d ]] && prompt "~/$d entries older than 60 days" && \
90            find ~/$d -maxdepth 1 -mindepth 1 -type d -mtime +60 -print0 | xargs -0r rm -rf && \
91            find ~/$d -maxdepth 1 -mindepth 1 -type f -mtime +60 -delete
92    done
93}