-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdiff.sh
More file actions
executable file
·120 lines (98 loc) · 3.72 KB
/
diff.sh
File metadata and controls
executable file
·120 lines (98 loc) · 3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env bash
# Shows what's in the repo but not installed locally.
# The repo is the source of truth. Run with: bash diff.sh
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_DIR="$SCRIPT_DIR/packages"
RED='\033[0;31m'
BOLD='\033[1m'
RESET='\033[0m'
section() { echo; echo "━━ $1"; }
compute_missing() {
local repo_file="$1"
local current_file="$2"
local tmp_repo tmp_current
tmp_repo=$(mktemp)
tmp_current=$(mktemp)
sort "$repo_file" > "$tmp_repo"
sort "$current_file" > "$tmp_current"
comm -23 "$tmp_repo" "$tmp_current"
rm "$tmp_repo" "$tmp_current"
}
print_missing() {
while IFS= read -r pkg; do
[[ -n "$pkg" ]] && printf " ${RED}%s${RESET}\n" "$pkg"
done
}
# ── Brew ──────────────────────────────────────────────────────────────────────
section "Brew (taps + formulae + casks)"
tmp_brew=$(mktemp)
{ brew tap; brew leaves; brew list --cask; } 2>/dev/null > "$tmp_brew"
not_installed=$(compute_missing "$PACKAGES_DIR/brew.txt" "$tmp_brew")
rm "$tmp_brew"
if [[ -z "$not_installed" ]]; then
echo " (all installed)"
else
print_missing <<< "$not_installed"
available_casks=$(brew casks 2>/dev/null)
taps=(); tap_formulae=(); casks=(); formulae=()
while IFS= read -r pkg; do
[[ -z "$pkg" ]] && continue
slashes=${pkg//[^\/]/}
if [[ ${#slashes} -eq 1 ]]; then
taps+=("$pkg")
elif [[ ${#slashes} -ge 2 ]]; then
tap_formulae+=("$pkg")
elif echo "$available_casks" | grep -qx "$pkg"; then
casks+=("$pkg")
else
formulae+=("$pkg")
fi
done <<< "$not_installed"
for tf in "${tap_formulae[@]}"; do formulae+=("${tf##*/}"); done
echo
printf " ${BOLD}To install:${RESET}\n"
for tap in "${taps[@]}"; do printf " brew tap %s\n" "$tap"; done
[[ ${#formulae[@]} -gt 0 ]] && printf " brew install %s\n" "${formulae[*]}"
[[ ${#casks[@]} -gt 0 ]] && printf " brew install --cask %s\n" "${casks[*]}"
fi
# ── npm ───────────────────────────────────────────────────────────────────────
section "npm (global)"
parse_npm() {
grep -E '[├└]──' | sed 's/.*── //' | sed 's/@[^@]*$//'
}
tmp_npm_repo=$(mktemp)
tmp_npm_current=$(mktemp)
parse_npm < "$PACKAGES_DIR/npm.txt" > "$tmp_npm_repo"
npm list -g --depth=0 2>/dev/null | parse_npm > "$tmp_npm_current"
not_installed=$(compute_missing "$tmp_npm_repo" "$tmp_npm_current")
rm "$tmp_npm_repo" "$tmp_npm_current"
if [[ -z "$not_installed" ]]; then
echo " (all installed)"
else
print_missing <<< "$not_installed"
echo
printf " ${BOLD}To install:${RESET}\n"
printf " npm install -g %s\n" "$(echo "$not_installed" | tr '\n' ' ')"
fi
# ── uv tools ──────────────────────────────────────────────────────────────────
section "uv tools (Python)"
parse_uv() {
grep -v '^\s*-' | grep -v '^\s*$' | awk '{print $1}'
}
tmp_uv_repo=$(mktemp)
tmp_uv_current=$(mktemp)
parse_uv < "$PACKAGES_DIR/uv_tools.txt" > "$tmp_uv_repo"
uv tool list 2>/dev/null | parse_uv > "$tmp_uv_current"
not_installed=$(compute_missing "$tmp_uv_repo" "$tmp_uv_current")
rm "$tmp_uv_repo" "$tmp_uv_current"
if [[ -z "$not_installed" ]]; then
echo " (all installed)"
else
print_missing <<< "$not_installed"
echo
printf " ${BOLD}To install:${RESET}\n"
while IFS= read -r pkg; do
[[ -n "$pkg" ]] && printf " uv tool install %s\n" "$pkg"
done <<< "$not_installed"
fi
echo