Current Behavior
The current install.sh performs a "blind reinstall" on every execution:
- Always downloads the latest release without checking if it's necessary
- Executes
rm -rf "$APP_DIR" before verifying the new download integrity
- No backup mechanism — if extraction fails after removal, user is left with broken installation
- No version comparison feedback ("Already up to date" vs "Updated to X")
Proposed Implementation
Stage 1: Version Tracking
Add a .version file in $APP_DIR containing the installed version tag (e.g., v1.2.3).
Implementation:
- During install, write
echo "$VERSION" > "${APP_DIR}/.version"
- On update, read current version:
CURRENT_VERSION=$(cat "${APP_DIR}/.version" 2>/dev/null || echo "unknown")
Stage 2: Pre-flight Version Check
Before any destructive operation, compare remote vs local:
if [ "$CURRENT_VERSION" = "$VERSION" ]; then
echo "✓ thin-wrap $VERSION is already installed and up to date."
exit 0
fi
echo "Updating: $CURRENT_VERSION → $VERSION"
Stage 3: Atomic Update with Backup
Replace the dangerous rm -rf + mv sequence with atomic operations:
# 1. Create backup
BACKUP_DIR="${APP_DIR}.backup.$(date +%s)"
cp -r "$APP_DIR" "$BACKUP_DIR"
# 2. Extract to temporary location first
TEMP_EXTRACT="${TMPDIR}/thin-wrap-new-$$"
mkdir -p "$TEMP_EXTRACT"
unzip -o "${ARCHIVE}" -d "$TEMP_EXTRACT"
# 3. Verify extraction success
if [ ! -f "$TEMP_EXTRACT/thin-wrap" ] && [ ! -f "$TEMP_EXTRACT/thin-wrap/thin-wrap" ]; then
echo "ERROR: Extraction failed, keeping current version"
rm -rf "$TEMP_EXTRACT"
exit 1
fi
# 4. Atomic swap (remove old, move new)
rm -rf "$APP_DIR"
mv "$TEMP_EXTRACT" "$APP_DIR"
Stage 4: Integrity Verification
Add checksum verification (if available in GitHub releases):
# Download checksum file if available
if curl -fsL "${DOWNLOAD_URL}.sha256" -o "${ARCHIVE}.sha256" 2>/dev/null; then
sha256sum -c "${ARCHIVE}.sha256" || {
echo "ERROR: Checksum verification failed"
exit 1
}
fi
Stage 5: Cleanup and Rollback Strategy
- On success: Remove backup after 24h (or keep last 3 versions)
- On failure: Auto-restore from backup:
cleanup_failed_update() {
echo "Update failed, restoring previous version..."
rm -rf "$APP_DIR"
mv "$BACKUP_DIR" "$APP_DIR"
exit 1
}
trap cleanup_failed_update ERR
Detailed Acceptance Criteria
Optional Enhancements (Future PRs)
- Delta updates: Use
zsync or rsume for partial downloads if release > 50MB
- Release notes: Display changelog between old and new version using GitHub API
- Self-update command: Add
thin-wrap --update that spawns the installer (requires wrapper script modification)
Testing Checklist for PR
# Test 1: Fresh install
rm -rf ~/.local/lib/thin-wrap ~/.local/bin/thin-wrap
./install.sh
# Verify: .version file exists, config.json created
# Test 2: Re-run same version
./install.sh
# Verify: Should exit immediately with "already up to date"
# Test 3: Simulate failed download (corrupt zip)
# (requires manual network cut or invalid URL test)
# Test 4: Verify backup works
ls ~/.local/lib/thin-wrap.backup.*
./install.sh --force # hypothetical flag to test reinstall
# Verify old version restorable
Priority: Medium
Effort: Small (1-2 hours for basic implementation, 4-6 hours with full rollback)
Breaking changes: None (backwards compatible)
Current Behavior
The current
install.shperforms a "blind reinstall" on every execution:rm -rf "$APP_DIR"before verifying the new download integrityProposed Implementation
Stage 1: Version Tracking
Add a
.versionfile in$APP_DIRcontaining the installed version tag (e.g.,v1.2.3).Implementation:
echo "$VERSION" > "${APP_DIR}/.version"CURRENT_VERSION=$(cat "${APP_DIR}/.version" 2>/dev/null || echo "unknown")Stage 2: Pre-flight Version Check
Before any destructive operation, compare remote vs local:
Stage 3: Atomic Update with Backup
Replace the dangerous
rm -rf + mvsequence with atomic operations:Stage 4: Integrity Verification
Add checksum verification (if available in GitHub releases):
Stage 5: Cleanup and Rollback Strategy
Detailed Acceptance Criteria
.versionfile exists in$APP_DIRafter any install/update$APP_DIRis empty or partially populated~/.local/lib/thin-wrap.backups/, auto-cleanup older ones--versiontest (optional post-install check), auto-restore previous versioncurl ... | shwithout promptsOptional Enhancements (Future PRs)
zsyncor rsume for partial downloads if release > 50MBthin-wrap --updatethat spawns the installer (requires wrapper script modification)Testing Checklist for PR
Priority: Medium
Effort: Small (1-2 hours for basic implementation, 4-6 hours with full rollback)
Breaking changes: None (backwards compatible)