Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .tool-versions
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ uv 0.4.18
copilot-cli 1.0.69
squad-cli 0.10.0
gh 2.92.0
delta 0.19.2
111 changes: 111 additions & 0 deletions scripts/linux/tools/delta.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
# scripts/linux/tools/delta.sh -- Install git-delta (syntax-highlighting git pager) at pinned version
#
# Called by: scripts/linux/setup.sh
# Idempotent: yes -- version-aware; upgrades if installed version != pinned version.
# Opt-in: NOT in DEFAULT_TOOLS; only runs when requested via --only=delta.
#
# Ubuntu 22.04+: installs via apt-get (git-delta package).
# Older/non-apt Linux: downloads the pinned release tarball from GitHub releases.
# macOS: brew install git-delta (warns if brew version differs from pin).
#
# Defines apply_delta_git_config() for testability.
# Main install block is guarded by BASH_SOURCE/argv0 check so this file can
# be sourced in tests to call apply_delta_git_config in isolation.

# shellcheck disable=SC1091
. "$(dirname "${BASH_SOURCE[0]}")/../lib/log.sh"

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DELTA_VERSION="$(sh "${SCRIPT_DIR}/../../lib/read-tool-version.sh" delta)"

apply_delta_git_config() {
log_info "Applying global git config for delta..."
git config --global core.pager delta
git config --global interactive.diffFilter 'delta --color-only'
git config --global delta.navigate true
git config --global delta.dark true
# Light-mode override: git config --global delta.dark false
git config --global merge.conflictStyle zdiff3
log_ok "delta git config applied (core.pager=delta, dark=true)"
}

if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
set -euo pipefail

# Detect installed version
INSTALLED_VERSION=""
if command -v delta &>/dev/null; then
INSTALLED_VERSION="$(delta --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || true)"
fi

if [ "${INSTALLED_VERSION}" = "${DELTA_VERSION}" ]; then
log_ok "git-delta already at pinned version ${DELTA_VERSION}"
apply_delta_git_config
exit 0
fi

if [ -n "${INSTALLED_VERSION}" ]; then
log_info "git-delta ${INSTALLED_VERSION} installed; upgrading to pinned ${DELTA_VERSION}..."
else
log_info "Installing git-delta ${DELTA_VERSION}..."
fi

PLATFORM="$(uname -s)"
if [[ "$PLATFORM" == "Darwin" ]]; then
# Homebrew: versioned formulae for git-delta are not reliably pinnable.
if command -v delta &>/dev/null; then
brew upgrade git-delta || true
else
brew install git-delta
fi
ACTUAL_VERSION="$(delta --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo 'unknown')"
if [ "${ACTUAL_VERSION}" != "${DELTA_VERSION}" ]; then
log_warn "git-delta ${ACTUAL_VERSION} installed (pinned: ${DELTA_VERSION}); brew cannot guarantee exact version"
else
log_ok "git-delta installed at ${DELTA_VERSION}"
fi
else
# Linux: prefer apt-get (Ubuntu 22.04+), fall back to pinned tarball
APT_OK=0
if command -v apt-get &>/dev/null; then
log_info "Trying apt-get install git-delta..."
sudo apt-get install -y git-delta 2>/dev/null && APT_OK=1 || APT_OK=0
fi

if [ "$APT_OK" -eq 1 ]; then
ACTUAL_VERSION="$(delta --version 2>&1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo 'unknown')"
if [ "${ACTUAL_VERSION}" != "${DELTA_VERSION}" ]; then
log_warn "apt installed git-delta ${ACTUAL_VERSION} (pinned: ${DELTA_VERSION}); use tarball for exact pin"
fi
log_ok "git-delta installed via apt at ${ACTUAL_VERSION}"
else
# Tarball: asset name delta-<version>-<arch-triple>.tar.gz
ARCH="$(uname -m)"
case "$ARCH" in
x86_64) ARCH_TRIPLE="x86_64-unknown-linux-gnu" ;;
aarch64|arm64) ARCH_TRIPLE="aarch64-unknown-linux-gnu" ;;
*) log_error "Unsupported architecture: ${ARCH}"; exit 1 ;;
esac

TARBALL="delta-${DELTA_VERSION}-${ARCH_TRIPLE}.tar.gz"
TARBALL_URL="https://github.com/dandavison/delta/releases/download/${DELTA_VERSION}/${TARBALL}"
INSTALL_DIR="${HOME}/.local/bin"
WORK_DIR="${HOME}/.local/share/dev-setup-install/delta"

mkdir -p "$INSTALL_DIR"
mkdir -p "$WORK_DIR"

log_info "Downloading ${TARBALL}..."
curl -fsSL "$TARBALL_URL" -o "${WORK_DIR}/${TARBALL}"
tar -xzf "${WORK_DIR}/${TARBALL}" -C "$WORK_DIR"
cp "${WORK_DIR}/delta-${DELTA_VERSION}-${ARCH_TRIPLE}/delta" "${INSTALL_DIR}/delta"
chmod +x "${INSTALL_DIR}/delta"
rm -rf "$WORK_DIR"

log_ok "git-delta ${DELTA_VERSION} installed to ${INSTALL_DIR}/delta"
fi
fi

apply_delta_git_config
fi
2 changes: 2 additions & 0 deletions scripts/windows/setup.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ $ErrorActionPreference = 'Stop'
. "$PSScriptRoot\tools\profile.ps1"
. "$PSScriptRoot\tools\auth.ps1"
. "$PSScriptRoot\tools\git-hook.ps1"
. "$PSScriptRoot\tools\delta.ps1"

# ---------------------------------------------------------------------------
# $DefaultTools -- single ordered source of truth for a no-arg default run.
Expand Down Expand Up @@ -85,6 +86,7 @@ $ToolRegistry = [ordered]@{
'dotfiles' = { Install-Dotfiles }
'profile' = { Write-PowerShellProfile }
'git-hook' = { Install-GitHook }
'delta' = { Install-Delta }
}

# ---------------------------------------------------------------------------
Expand Down
73 changes: 73 additions & 0 deletions scripts/windows/tools/delta.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# scripts/windows/tools/delta.ps1 - git-delta installer
#
# Installs git-delta at pinned version from .tool-versions.
# Opt-in: NOT in $DefaultTools; only runs when requested via -Only 'delta'.
# winget preferred (id dandavison.delta); scoop fallback when winget unavailable.
#
# Defines Set-DeltaGitConfig for testability: applies global git config for
# delta without requiring a full install run.
# PS 5.1 ASCII-only: no smart quotes, em-dashes, or non-ASCII characters.

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

. "$PSScriptRoot\..\lib\logging.ps1"
. "$PSScriptRoot\..\lib\path.ps1"
. "$PSScriptRoot\..\..\lib\Read-ToolVersion.ps1"

function Set-DeltaGitConfig {
[CmdletBinding(SupportsShouldProcess)]
param()
if (-not $PSCmdlet.ShouldProcess('global git config', 'Set delta pager settings')) { return }
Write-Info "Applying global git config for delta..."
git config --global core.pager delta
git config --global interactive.diffFilter 'delta --color-only'
git config --global delta.navigate true
git config --global delta.dark true
# Light-mode override: git config --global delta.dark false
git config --global merge.conflictStyle zdiff3
Write-Ok "delta git config applied (core.pager=delta, dark=true)"
}

function Install-Delta {
$DeltaVersion = Get-ToolVersion -Name 'delta'

# Detect installed version
$InstalledVersion = ''
if (Get-Command delta -ErrorAction SilentlyContinue) {
$raw = (delta --version 2>&1) | Select-Object -First 1 | Out-String
$m = [regex]::Match($raw, '[0-9]+\.[0-9]+\.[0-9]+')
if ($m.Success) { $InstalledVersion = $m.Value }
}

if ($InstalledVersion -eq $DeltaVersion) {
Write-Ok "git-delta already at pinned version $DeltaVersion"
Set-DeltaGitConfig
return
}

if ($InstalledVersion) {
Write-Info "git-delta $InstalledVersion installed; upgrading to pinned $DeltaVersion..."
} else {
Write-Info "Installing git-delta $DeltaVersion..."
}

# winget preferred; fall back to scoop if winget is unavailable
if (Get-Command winget -ErrorAction SilentlyContinue) {
winget install --id dandavison.delta --version $DeltaVersion --silent `
--accept-source-agreements --accept-package-agreements
Assert-LastExit -ToolName "git-delta" -AllowedExitCodes @(0, -1978335189)
Refresh-SessionPath
Write-Ok "git-delta installed via winget at $DeltaVersion"
} elseif (Get-Command scoop -ErrorAction SilentlyContinue) {
Write-Info "winget not available; falling back to scoop..."
scoop install delta
Assert-LastExit -ToolName "git-delta (scoop)"
Write-Warn "scoop installed latest delta; version may differ from pinned $DeltaVersion"
} else {
Write-Err "Neither winget nor scoop available; cannot install git-delta"
throw "git-delta install failed: no supported package manager found"
}

Set-DeltaGitConfig
}
157 changes: 157 additions & 0 deletions tests/test_delta_installer.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#!/usr/bin/env bash
# tests/test_delta_installer.sh -- parity tests for git-delta opt-in installer (#466)
#
# Tests:
# T_delta_in_list -- delta appears in --list output (opt-in discoverable)
# T_delta_not_default -- delta is NOT installed by a default no-arg run
# T_delta_gitconfig_iso -- apply_delta_git_config writes core.pager=delta under
# an isolated GIT_CONFIG_GLOBAL (does not touch ~/.gitconfig)
# T_delta_gitconfig_idem -- apply_delta_git_config is idempotent (safe to run twice)
#
# Usage: bash tests/test_delta_installer.sh
# Requires: bash 3.2+ (macOS compatible), git

set -uo pipefail

PASS=0
FAIL=0
SKIP=0
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RESET='\033[0m'

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
LINUX_SETUP="${REPO_ROOT}/scripts/linux/setup.sh"
DELTA_SH="${REPO_ROOT}/scripts/linux/tools/delta.sh"
STUB_DIR="${REPO_ROOT}/tests/fixtures/stub-tools/linux"

pass() { printf "${GREEN}PASS${RESET}: %s\n" "$1"; PASS=$((PASS + 1)); }
fail() { printf "${RED}FAIL${RESET}: %s\n" "$1"; FAIL=$((FAIL + 1)); }
# shellcheck disable=SC2329
skip() { printf "${YELLOW}SKIP${RESET}: %s -- %s\n" "$1" "$2"; SKIP=$((SKIP + 1)); }

# Log no-ops -- inherited by subshells; called indirectly by delta.sh when sourced.
# shellcheck disable=SC2329
log_info() { :; }
# shellcheck disable=SC2329
log_ok() { :; }
# shellcheck disable=SC2329
log_warn() { :; }
# shellcheck disable=SC2329
log_error(){ :; }

# ---------------------------------------------------------------------------
# T_delta_in_list: --list on real tools dir includes 'delta'
# Fails RED when scripts/linux/tools/delta.sh does not exist.
# ---------------------------------------------------------------------------
echo ""
echo "--- T_delta_in_list ---"
list_out="$(bash "$LINUX_SETUP" --list 2>&1)" && list_exit=$? || list_exit=$?
if [ "$list_exit" -ne 0 ]; then
fail "T_delta_in_list: --list exited $list_exit (expected 0)"
elif echo "$list_out" | grep -qF "delta"; then
pass "T_delta_in_list: delta appears in --list output (opt-in discoverable)"
else
fail "T_delta_in_list: delta missing from --list output (is delta.sh in tools/?)"
echo " --list output: $list_out"
fi

# ---------------------------------------------------------------------------
# T_delta_not_default: default no-arg run with stub dir does NOT run delta
# Delta is opt-in; it must not appear in defaults.txt.
# ---------------------------------------------------------------------------
echo ""
echo "--- T_delta_not_default ---"
RUN_LOG="$(mktemp)"
export RUN_LOG
bash "$LINUX_SETUP" "--tools-dir=${STUB_DIR}" >/dev/null 2>&1 || true
if grep -qF "delta" "$RUN_LOG" 2>/dev/null; then
fail "T_delta_not_default: delta ran in a default no-arg install (must be opt-in only)"
else
pass "T_delta_not_default: delta does NOT run in a default install (correctly opt-in)"
fi
rm -f "$RUN_LOG"
unset RUN_LOG

# ---------------------------------------------------------------------------
# T_delta_gitconfig_iso: apply_delta_git_config writes core.pager=delta under
# an isolated GIT_CONFIG_GLOBAL; real ~/.gitconfig is never touched.
# Fails RED when delta.sh does not exist (function not defined).
# ---------------------------------------------------------------------------
echo ""
echo "--- T_delta_gitconfig_iso ---"
if [ ! -f "$DELTA_SH" ]; then
fail "T_delta_gitconfig_iso: delta.sh not found at $DELTA_SH -- RED (pre-implementation)"
else
ISO_CFG="$(mktemp)"
# Run in a subshell so set -euo pipefail from delta.sh does not affect parent.
# GIT_CONFIG_GLOBAL is set inside the subshell intentionally; we read via inline
# env assignment after the subshell exits.
# shellcheck disable=SC2030
(
export GIT_CONFIG_GLOBAL="$ISO_CFG"
# shellcheck disable=SC1090
. "$DELTA_SH"
apply_delta_git_config
)
sub_exit=$?
if [ "$sub_exit" -ne 0 ]; then
fail "T_delta_gitconfig_iso: apply_delta_git_config subshell exited $sub_exit"
else
# shellcheck disable=SC2031
got_pager="$(GIT_CONFIG_GLOBAL="$ISO_CFG" git config --global --get core.pager 2>/dev/null || true)"
# shellcheck disable=SC2031
got_filter="$(GIT_CONFIG_GLOBAL="$ISO_CFG" git config --global --get interactive.diffFilter 2>/dev/null || true)"
if [ "$got_pager" = "delta" ] && [ "$got_filter" = "delta --color-only" ]; then
pass "T_delta_gitconfig_iso: core.pager=delta and interactive.diffFilter set under isolated config"
else
fail "T_delta_gitconfig_iso: unexpected config values (pager='${got_pager}', filter='${got_filter}')"
fi
fi
rm -f "$ISO_CFG"
fi

# ---------------------------------------------------------------------------
# T_delta_gitconfig_idem: running apply_delta_git_config twice does not error
# (git config --global is naturally idempotent).
# Fails RED when delta.sh does not exist.
# ---------------------------------------------------------------------------
echo ""
echo "--- T_delta_gitconfig_idem ---"
if [ ! -f "$DELTA_SH" ]; then
fail "T_delta_gitconfig_idem: delta.sh not found -- RED (pre-implementation)"
else
ISO_CFG2="$(mktemp)"
# shellcheck disable=SC2030,SC2031
(
# shellcheck disable=SC2031
export GIT_CONFIG_GLOBAL="$ISO_CFG2"
# shellcheck disable=SC1090
. "$DELTA_SH"
apply_delta_git_config # first run
apply_delta_git_config # second run -- must be a no-op / safe
)
idem_exit=$?
if [ "$idem_exit" -ne 0 ]; then
fail "T_delta_gitconfig_idem: second run of apply_delta_git_config exited $idem_exit"
else
# shellcheck disable=SC2031
got_dark="$(GIT_CONFIG_GLOBAL="$ISO_CFG2" git config --global --get delta.dark 2>/dev/null || true)"
if [ "$got_dark" = "true" ]; then
pass "T_delta_gitconfig_idem: idempotent double-run completed; delta.dark=true"
else
fail "T_delta_gitconfig_idem: delta.dark unexpected value after double-run: '${got_dark}'"
fi
fi
rm -f "$ISO_CFG2"
fi

# ---------------------------------------------------------------------------
echo ""
echo "Results: ${PASS} passed, ${FAIL} failed, ${SKIP} skipped"
if [ "$FAIL" -gt 0 ]; then
exit 1
fi
exit 0
Loading
Loading