Repository navigation
Expand file tree
/
Copy pathupdate-packages.sh
More file actions
executable file
·353 lines (302 loc) · 11.3 KB
/
Copy pathupdate-packages.sh
File metadata and controls
executable file
·353 lines (302 loc) · 11.3 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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#!/usr/bin/env bash
# Package update script for NixOS flake
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Script directory - handle both direct execution and flake app execution
if [[ -n "${FLAKE_ROOT:-}" ]]; then
SCRIPT_DIR="$FLAKE_ROOT"
elif [[ -f "${BASH_SOURCE[0]}" ]]; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
else
# When run as flake app, try to find flake root
SCRIPT_DIR="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
fi
PKGS_DIR="$SCRIPT_DIR/pkgs"
# Function to print colored output
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Function to check if we're in a git repo
check_git() {
if ! git rev-parse --git-dir > /dev/null 2>&1; then
print_error "Not in a git repository!"
exit 1
fi
}
# Function to create a backup commit
create_backup_commit() {
if [[ -n $(git status --porcelain) ]]; then
print_warning "Working directory has uncommitted changes. Creating backup commit..."
git add -A
git commit -m "backup: before package updates $(date +%Y-%m-%d_%H:%M:%S)" || true
fi
}
# Function to update a Go package
update_go_package() {
local pkg_file="$1"
local pkg_name
pkg_name="$(basename "$pkg_file" .nix)"
print_info "Updating Go package: $pkg_name"
# Extract current version and repo info
local owner repo
owner=$(grep -oP 'owner = "\K[^"]+' "$pkg_file" || echo "")
repo=$(grep -oP 'repo = "\K[^"]+' "$pkg_file" || echo "")
if [[ -z "$owner" || -z "$repo" ]]; then
print_warning "Could not extract owner/repo for $pkg_name"
return 1
fi
# Get latest release
local latest_tag
latest_tag=$(curl -s "https://api.github.com/repos/$owner/$repo/releases/latest" | jq -r .tag_name)
if [[ -z "$latest_tag" || "$latest_tag" == "null" ]]; then
print_warning "No releases found for $owner/$repo, checking tags..."
latest_tag=$(curl -s "https://api.github.com/repos/$owner/$repo/tags" | jq -r '.[0].name')
fi
if [[ -z "$latest_tag" || "$latest_tag" == "null" ]]; then
print_error "Could not find latest version for $pkg_name"
return 1
fi
# Clean version (remove 'v' prefix if present)
local version
version="${latest_tag#v}"
print_info "Latest version: $version"
# Update version in file
sed -i "s/version = \"[^\"]*\"/version = \"$version\"/" "$pkg_file"
# Update hash (this will fail, but we'll get the correct hash)
sed -i "s/hash = \"[^\"]*\"/hash = \"sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\"/" "$pkg_file"
print_info "Building to get correct hash..."
if ! nix build -f "$SCRIPT_DIR" "$pkg_name" 2>&1 | tee /tmp/nix-build-output; then
local correct_hash
correct_hash=$(grep -oP 'got:\s+\K[^\s]+' /tmp/nix-build-output | tail -1)
if [[ -n "$correct_hash" ]]; then
sed -i "s/hash = \"[^\"]*\"/hash = \"$correct_hash\"/" "$pkg_file"
print_success "Updated $pkg_name to version $version"
else
print_error "Could not extract correct hash for $pkg_name"
return 1
fi
else
print_success "Package built successfully (hash was already correct)"
fi
}
# Function to update an NPM package
update_npm_package() {
local pkg_file="$1"
local pkg_dir pkg_name
pkg_dir="$(dirname "$pkg_file")"
pkg_name="$(basename "$pkg_dir")"
print_info "Updating NPM package: $pkg_name"
# Extract package name from npmjs
local npm_name
npm_name=$(grep -oP 'registry\.npmjs\.org/\K[^/]+/[^/]+' "$pkg_file" | head -1 || echo "")
if [[ -z "$npm_name" ]]; then
npm_name=$(grep -oP 'pname = "\K[^"]+' "$pkg_file" || echo "")
fi
if [[ -z "$npm_name" ]]; then
print_warning "Could not extract npm package name for $pkg_name"
return 1
fi
# Get latest version from npm
local latest_version
latest_version=$(npm view "$npm_name" version 2>/dev/null || echo "")
if [[ -z "$latest_version" ]]; then
print_error "Could not fetch latest version for $npm_name"
return 1
fi
print_info "Latest version: $latest_version"
# Update version in file
sed -i "s/version = \"[^\"]*\"/version = \"$latest_version\"/" "$pkg_file"
# Update URL hash
sed -i "s/hash = \"sha256-[^\"]*\"/hash = \"sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\"/" "$pkg_file"
# If there's a package-lock.json, we need to update it
if [[ -f "$pkg_dir/package-lock.json" ]]; then
print_info "Updating package-lock.json..."
(
cd "$pkg_dir"
# Create a temporary package.json
echo "{\"name\": \"temp\", \"version\": \"1.0.0\", \"dependencies\": {\"$npm_name\": \"$latest_version\"}}" > package.json
npm install --package-lock-only
rm package.json
)
# Update npmDepsHash
sed -i "s/npmDepsHash = \"[^\"]*\"/npmDepsHash = \"sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\"/" "$pkg_file"
fi
print_info "Building to get correct hashes..."
if ! nix build -f "$SCRIPT_DIR" "$pkg_name" 2>&1 | tee /tmp/nix-build-output; then
# Extract both hashes if needed
local url_hash deps_hash
url_hash=$(grep -oP 'got:\s+\K[^\s]+' /tmp/nix-build-output | head -1)
deps_hash=$(grep -oP 'got:\s+\K[^\s]+' /tmp/nix-build-output | tail -1)
if [[ -n "$url_hash" ]]; then
sed -i "0,/hash = \"sha256-[^\"]*\"/{s/hash = \"sha256-[^\"]*\"/hash = \"$url_hash\"/}" "$pkg_file"
fi
if [[ -f "$pkg_dir/package-lock.json" && -n "$deps_hash" && "$deps_hash" != "$url_hash" ]]; then
sed -i "s/npmDepsHash = \"[^\"]*\"/npmDepsHash = \"$deps_hash\"/" "$pkg_file"
fi
# Try building again
if nix build -f "$SCRIPT_DIR" "$pkg_name" 2>&1; then
print_success "Updated $pkg_name to version $latest_version"
else
print_error "Failed to update $pkg_name"
return 1
fi
else
print_success "Package built successfully"
fi
}
# Function to update a Python package
update_python_package() {
local pkg_file="$1"
local pkg_name
pkg_name="$(basename "$pkg_file" .nix)"
print_info "Updating Python package: $pkg_name"
# Check if it's using unstableGitUpdater
if grep -q "unstableGitUpdater" "$pkg_file"; then
print_info "Package uses unstableGitUpdater, running nix-update..."
if command -v nix-update >/dev/null 2>&1; then
nix-update "$pkg_name" --flake
else
print_warning "nix-update not found, skipping $pkg_name"
fi
return
fi
# For other Python packages, try to extract GitHub info
local owner repo
owner=$(grep -oP 'owner = "\K[^"]+' "$pkg_file" || echo "")
repo=$(grep -oP 'repo = "\K[^"]+' "$pkg_file" || echo "")
if [[ -n "$owner" && -n "$repo" ]]; then
update_go_package "$pkg_file" # Similar process for GitHub-based packages
else
print_warning "Could not determine update method for $pkg_name"
fi
}
# Function to detect package type and update
update_package() {
local pkg_file="$1"
if grep -q "buildGoModule" "$pkg_file"; then
update_go_package "$pkg_file"
elif grep -q "buildNpmPackage" "$pkg_file"; then
update_npm_package "$pkg_file"
elif grep -q "buildPythonApplication\|buildPythonPackage" "$pkg_file"; then
update_python_package "$pkg_file"
else
print_warning "Unknown package type for $(basename "$pkg_file")"
fi
}
# Function to list all packages
list_packages() {
print_info "Available packages:"
for pkg in "$PKGS_DIR"/*.nix "$PKGS_DIR"/*/default.nix; do
if [[ -f "$pkg" ]]; then
local name
name=$(basename "$(dirname "$pkg")")
if [[ "$name" == "pkgs" ]]; then
name=$(basename "$pkg" .nix)
fi
echo " - $name"
fi
done
}
# Main function
main() {
local package_name=""
local no_commit=false
local list_only=false
# Parse arguments
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
echo "Usage: $0 [OPTIONS] [PACKAGE_NAME]"
echo ""
echo "Update custom packages in the pkgs directory"
echo ""
echo "Options:"
echo " -h, --help Show this help message"
echo " -l, --list List available packages"
echo " -n, --no-commit Don't create backup commit"
echo ""
echo "Examples:"
echo " $0 Update all packages"
echo " $0 opencode Update only opencode package"
echo " $0 --list List all available packages"
exit 0
;;
-l|--list)
list_only=true
shift
;;
-n|--no-commit)
no_commit=true
shift
;;
*)
package_name="$1"
shift
;;
esac
done
# Check if we're in a git repo
check_git
# List packages if requested
if [[ "$list_only" == true ]]; then
list_packages
exit 0
fi
# Create backup commit unless disabled
if [[ "$no_commit" == false ]]; then
create_backup_commit
fi
# Update packages
if [[ -n "$package_name" ]]; then
# Update specific package
local found=false
# Check direct .nix file
if [[ -f "$PKGS_DIR/$package_name.nix" ]]; then
update_package "$PKGS_DIR/$package_name.nix"
found=true
# Check for directory with default.nix
elif [[ -f "$PKGS_DIR/$package_name/default.nix" ]]; then
update_package "$PKGS_DIR/$package_name/default.nix"
found=true
fi
if [[ "$found" == false ]]; then
print_error "Package '$package_name' not found"
list_packages
exit 1
fi
else
# Update all packages
print_info "Updating all packages..."
# Process direct .nix files
for pkg in "$PKGS_DIR"/*.nix; do
if [[ -f "$pkg" && "$(basename "$pkg")" != "overlay.nix" ]]; then
update_package "$pkg" || print_warning "Failed to update $(basename "$pkg" .nix)"
fi
done
# Process directories with default.nix
for dir in "$PKGS_DIR"/*/; do
if [[ -f "$dir/default.nix" ]]; then
update_package "$dir/default.nix" || print_warning "Failed to update $(basename "$dir")"
fi
done
fi
print_success "Update process completed!"
# Show git status
if [[ -n $(git status --porcelain) ]]; then
print_info "Changes made:"
git status --short
echo ""
print_info "To revert all changes: git reset --hard HEAD"
print_info "To commit changes: git add -A && git commit -m 'chore: update packages'"
else
print_info "No changes were made"
fi
}
# Run main function
main "$@"