Identities live in ~/.git-identities (alias|Name|email). Interactive menu to select, add, or remove identities; direct mode via alias argument; --global/-g scope flag (defaults to local inside a repo, global fallback outside); --list/--current helpers. Full --dryrun support and a 27-assertion test suite driven through dryrun. GIT_IDENTITIES_FILE env override for testability.
121 lines
4.2 KiB
Bash
Executable File
121 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -uo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
|
GIT_IDENTITY="$SCRIPT_DIR/scripts/git-identity"
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
NC='\033[0m'
|
|
|
|
pass=0
|
|
fail=0
|
|
|
|
assert_match() {
|
|
local desc="$1" pattern="$2" actual="$3"
|
|
if [[ "$actual" =~ $pattern ]]; then
|
|
echo -e "${GREEN}PASS${NC}: $desc"
|
|
((pass++))
|
|
else
|
|
echo -e "${RED}FAIL${NC}: $desc"
|
|
echo " pattern: $pattern"
|
|
echo " actual: $actual"
|
|
((fail++))
|
|
fi
|
|
}
|
|
|
|
assert_exit() {
|
|
local desc="$1" expected="$2" actual="$3"
|
|
if [[ "$expected" == "$actual" ]]; then
|
|
echo -e "${GREEN}PASS${NC}: $desc"
|
|
((pass++))
|
|
else
|
|
echo -e "${RED}FAIL${NC}: $desc (expected exit $expected, got $actual)"
|
|
((fail++))
|
|
fi
|
|
}
|
|
|
|
# Fixture: temp identities file and a temp git repo
|
|
TMPDIR_T=$(mktemp -d)
|
|
trap 'rm -rf "$TMPDIR_T"' EXIT
|
|
IDFILE="$TMPDIR_T/identities"
|
|
cat > "$IDFILE" <<'EOF'
|
|
# alias|Name|email
|
|
personal|Test Person|test@example.net
|
|
work|Test Person|test.person@corp.example
|
|
EOF
|
|
REPO="$TMPDIR_T/repo"
|
|
mkdir -p "$REPO" && git -C "$REPO" init -q
|
|
|
|
run() { GIT_IDENTITIES_FILE="$IDFILE" "$GIT_IDENTITY" "$@"; }
|
|
|
|
# --help
|
|
out=$(run --help); rc=$?
|
|
assert_exit "--help exits 0" 0 "$rc"
|
|
assert_match "--help shows usage" "Usage: git-identity" "$out"
|
|
|
|
# --list
|
|
out=$(run --list); rc=$?
|
|
assert_exit "--list exits 0" 0 "$rc"
|
|
assert_match "--list shows personal" "personal.*test@example\.net" "$out"
|
|
assert_match "--list shows work" "work.*test\.person@corp\.example" "$out"
|
|
|
|
# direct apply, dryrun, inside repo -> local scope
|
|
out=$(cd "$REPO" && run -n work); rc=$?
|
|
assert_exit "dryrun apply exits 0" 0 "$rc"
|
|
assert_match "dryrun apply previews local set" \
|
|
"\[dryrun\] Would set user.name 'Test Person' and user.email 'test.person@corp.example' \(--local in " "$out"
|
|
|
|
# dryrun apply did not change config
|
|
name=$(git -C "$REPO" config --local user.name 2>/dev/null || echo "UNSET")
|
|
assert_match "dryrun did not write config" "UNSET" "$name"
|
|
|
|
# direct apply, dryrun, outside repo -> global fallback note
|
|
out=$(cd "$TMPDIR_T" && run -n personal); rc=$?
|
|
assert_exit "dryrun global fallback exits 0" 0 "$rc"
|
|
assert_match "notes global fallback" "not inside a git repository" "$out"
|
|
assert_match "previews global set" "\(--global\)" "$out"
|
|
|
|
# --global flag, dryrun
|
|
out=$(cd "$REPO" && run -n -g personal); rc=$?
|
|
assert_match "dryrun --global previews global scope" "\(--global\)" "$out"
|
|
|
|
# unknown alias
|
|
out=$(cd "$REPO" && run -n nosuch 2>&1); rc=$?
|
|
assert_exit "unknown alias exits 1" 1 "$rc"
|
|
assert_match "unknown alias error names file" "No identity 'nosuch'" "$out"
|
|
assert_match "unknown alias lists available" "Available: personal work" "$out"
|
|
|
|
# missing file, direct mode
|
|
out=$(GIT_IDENTITIES_FILE="$TMPDIR_T/absent" "$GIT_IDENTITY" -n work 2>&1); rc=$?
|
|
assert_exit "missing file exits 1" 1 "$rc"
|
|
assert_match "missing file error" "No identities file" "$out"
|
|
|
|
# interactive menu: select identity 2 via stdin, dryrun
|
|
out=$(cd "$REPO" && printf '2\n' | run -n); rc=$?
|
|
assert_exit "interactive select exits 0" 0 "$rc"
|
|
assert_match "interactive shows menu" "1\) personal" "$out"
|
|
assert_match "interactive select previews apply" "\[dryrun\] Would set user.name 'Test Person' and user.email 'test.person@corp.example'" "$out"
|
|
|
|
# interactive: something else -> add, dryrun
|
|
out=$(cd "$REPO" && printf 's\na\nnewalias\nNew Name\nnew@example.net\nn\n' | run -n); rc=$?
|
|
assert_exit "interactive add exits 0" 0 "$rc"
|
|
assert_match "add previews append" "\[dryrun\] Would append 'newalias\|New Name\|new@example.net'" "$out"
|
|
grep -q "newalias" "$IDFILE" && added=yes || added=no
|
|
assert_match "dryrun add did not write file" "no" "$added"
|
|
|
|
# interactive: something else -> remove, dryrun
|
|
out=$(cd "$REPO" && printf 's\nr\n1\n' | run -n); rc=$?
|
|
assert_exit "interactive remove exits 0" 0 "$rc"
|
|
assert_match "remove previews deletion" "\[dryrun\] Would remove identity 'personal'" "$out"
|
|
grep -q "^personal|" "$IDFILE" && still=yes || still=no
|
|
assert_match "dryrun remove did not write file" "yes" "$still"
|
|
|
|
# duplicate alias rejected during add (then cancel with empty alias)
|
|
out=$(cd "$REPO" && printf 's\na\nwork\n\n' | run -n); rc=$?
|
|
assert_match "duplicate alias rejected" "Alias 'work' already exists" "$out"
|
|
|
|
echo ""
|
|
echo "Results: $pass passed, $fail failed"
|
|
[[ $fail -eq 0 ]]
|