mirror of
https://github.com/ohmyzsh/ohmyzsh.git
synced 2026-08-07 06:08:39 +02:00
fix(semver-tag): show latest tag before confirmation prompt
Also include the test suite (test.zsh), which was missing from the initial commit despite being referenced in the PR description.
This commit is contained in:
parent
4a8082e028
commit
992574077a
2 changed files with 229 additions and 1 deletions
|
|
@ -54,7 +54,9 @@ _semver_tag_bump() {
|
|||
local newtag="${prefix}${major}.${minor}.${patch}"
|
||||
|
||||
if $mismatch; then
|
||||
print -n "Running this will create $newtag, but your existing tags are formatted $latest, are you sure? [y/N] "
|
||||
print -n "The latest tag is $latest. This will create tag $newtag, but that doesn't match the existing format, are you sure? [y/N] "
|
||||
elif [[ -n "$latest" ]]; then
|
||||
print -n "The latest tag is $latest. This will create tag $newtag, continue? [y/N] "
|
||||
else
|
||||
print -n "This will create tag $newtag, continue? [y/N] "
|
||||
fi
|
||||
|
|
|
|||
226
plugins/semver-tag/test.zsh
Normal file
226
plugins/semver-tag/test.zsh
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
#!/usr/bin/env zsh
|
||||
# Test suite for semver-tag.plugin.zsh
|
||||
# Run: zsh test.zsh
|
||||
set -uo pipefail
|
||||
|
||||
PLUGIN_DIR="${0:A:h}"
|
||||
PLUGIN="$PLUGIN_DIR/semver-tag.plugin.zsh"
|
||||
|
||||
pass_count=0
|
||||
fail_count=0
|
||||
typeset -a tmp_dirs
|
||||
|
||||
cleanup() {
|
||||
local d
|
||||
for d in "${tmp_dirs[@]}"; do
|
||||
rm -rf "$d"
|
||||
done
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# --- test harness -----------------------------------------------------
|
||||
|
||||
# make_repo [tag ...] -> creates a fresh temp git repo, cds into it,
|
||||
# and creates any given tags (all pointing at the same initial commit).
|
||||
make_repo() {
|
||||
local dir
|
||||
dir=$(mktemp -d)
|
||||
tmp_dirs+=("$dir")
|
||||
cd "$dir"
|
||||
git init -q >/dev/null
|
||||
git commit --allow-empty -q -m "init"
|
||||
local t
|
||||
for t in "$@"; do
|
||||
git tag "$t"
|
||||
done
|
||||
}
|
||||
|
||||
# run <stdin-line> <command...> -> sources the plugin and runs command
|
||||
# with the given line piped to stdin. Sets $OUT and $STATUS.
|
||||
run() {
|
||||
local stdin_line="$1"; shift
|
||||
# Newline (not `;`) between source and command: zsh parses a `;`-joined
|
||||
# -c line as one unit before executing any of it, so aliases defined by
|
||||
# `source` wouldn't yet be recognized when the rest of that line parses.
|
||||
OUT=$(print -r -- "$stdin_line" | zsh -c "source '$PLUGIN'
|
||||
$*" 2>&1)
|
||||
STATUS=$?
|
||||
}
|
||||
|
||||
assert_contains() {
|
||||
local desc="$1" haystack="$2" needle="$3"
|
||||
if [[ "$haystack" == *"$needle"* ]]; then
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
fail_count=$((fail_count + 1))
|
||||
echo "FAIL: $desc"
|
||||
echo " expected to contain: $needle"
|
||||
echo " actual output: $haystack"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_not_contains() {
|
||||
local desc="$1" haystack="$2" needle="$3"
|
||||
if [[ "$haystack" != *"$needle"* ]]; then
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
fail_count=$((fail_count + 1))
|
||||
echo "FAIL: $desc"
|
||||
echo " expected NOT to contain: $needle"
|
||||
echo " actual output: $haystack"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_tag_exists() {
|
||||
local desc="$1" tag="$2"
|
||||
if git rev-parse "$tag" >/dev/null 2>&1; then
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
fail_count=$((fail_count + 1))
|
||||
echo "FAIL: $desc - tag '$tag' does not exist"
|
||||
echo " tags present: $(git tag)"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_tag_absent() {
|
||||
local desc="$1" tag="$2"
|
||||
if ! git rev-parse "$tag" >/dev/null 2>&1; then
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
fail_count=$((fail_count + 1))
|
||||
echo "FAIL: $desc - tag '$tag' should not exist"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_tag_type() {
|
||||
local desc="$1" tag="$2" expected_type="$3"
|
||||
local actual_type
|
||||
actual_type=$(git cat-file -t "$tag" 2>/dev/null)
|
||||
if [[ "$actual_type" == "$expected_type" ]]; then
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
fail_count=$((fail_count + 1))
|
||||
echo "FAIL: $desc - expected tag type '$expected_type', got '$actual_type'"
|
||||
fi
|
||||
}
|
||||
|
||||
assert_status() {
|
||||
local desc="$1" expected="$2" actual="$3"
|
||||
if [[ "$actual" == "$expected" ]]; then
|
||||
pass_count=$((pass_count + 1))
|
||||
else
|
||||
fail_count=$((fail_count + 1))
|
||||
echo "FAIL: $desc - expected exit $expected, got $actual"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- tests --------------------------------------------------------------
|
||||
|
||||
# Alias definitions (checked via the alias table directly, not by invoking
|
||||
# them in the same non-interactive buffer - see note on `run()` above;
|
||||
# in a real interactive shell these invoke fine, as already confirmed live).
|
||||
alias_defs=$(zsh -c "source '$PLUGIN'
|
||||
alias gtvM gtvm gtvp" 2>&1)
|
||||
assert_contains "gtvM alias is gtM -v" "$alias_defs" "gtvM='gtM -v'"
|
||||
assert_contains "gtvm alias is gtm -v" "$alias_defs" "gtvm='gtm -v'"
|
||||
assert_contains "gtvp alias is gtp -v" "$alias_defs" "gtvp='gtp -v'"
|
||||
|
||||
# Not a git repo
|
||||
tmpdir=$(mktemp -d)
|
||||
tmp_dirs+=("$tmpdir")
|
||||
cd "$tmpdir"
|
||||
run "y" gtM
|
||||
assert_contains "gtM outside a git repo errors" "$OUT" "Not inside a git repository."
|
||||
assert_status "gtM outside a git repo exits 1" 1 "$STATUS"
|
||||
|
||||
# Decline aborts, creates nothing
|
||||
make_repo
|
||||
run "n" gtM
|
||||
assert_contains "decline shows Aborted" "$OUT" "Aborted."
|
||||
assert_status "decline exits 1" 1 "$STATUS"
|
||||
assert_tag_absent "decline creates no tag" "1.0.0"
|
||||
|
||||
# Bootstrap: no tags
|
||||
make_repo
|
||||
run "y" gtM
|
||||
assert_tag_exists "gtM bootstrap creates 1.0.0" "1.0.0"
|
||||
assert_tag_type "gtM bootstrap is lightweight" "1.0.0" "commit"
|
||||
assert_not_contains "bootstrap prompt has no 'latest tag' line (nothing to show)" "$OUT" "The latest tag is"
|
||||
|
||||
make_repo
|
||||
run "y" gtm
|
||||
assert_tag_exists "gtm bootstrap creates 0.1.0" "0.1.0"
|
||||
|
||||
make_repo
|
||||
run "y" gtp
|
||||
assert_tag_exists "gtp bootstrap creates 0.0.1" "0.0.1"
|
||||
|
||||
make_repo
|
||||
run "y" gtM -v
|
||||
assert_tag_exists "gtvM (gtM -v) bootstrap creates v1.0.0" "v1.0.0"
|
||||
|
||||
# Extra args are forwarded straight to `git tag` after the computed name
|
||||
make_repo
|
||||
run "y" gtM --annotate -m '"passthrough message"'
|
||||
assert_tag_exists "gtM --annotate -m creates 1.0.0" "1.0.0"
|
||||
assert_tag_type "gtM --annotate produces a real annotated tag object" "1.0.0" "tag"
|
||||
assert_contains "annotated tag carries the forwarded message" "$(git cat-file -p 1.0.0)" "passthrough message"
|
||||
|
||||
# -v and passthrough args compose together
|
||||
make_repo "v0.1.1"
|
||||
run "y" gtM -v --annotate -m '"combo message"'
|
||||
assert_tag_exists "gtM -v --annotate keeps v prefix" "v1.0.0"
|
||||
assert_tag_type "gtM -v --annotate still produces an annotated tag object" "v1.0.0" "tag"
|
||||
|
||||
# No mismatch: gtM on non-v tags
|
||||
make_repo "0.1.1"
|
||||
run "y" gtM
|
||||
assert_not_contains "gtM on non-v tags shows no mismatch warning" "$OUT" "are you sure"
|
||||
assert_contains "prompt shows the latest tag before confirming" "$OUT" "The latest tag is 0.1.1"
|
||||
assert_tag_exists "gtM bumps major on non-v tags" "1.0.0"
|
||||
|
||||
# Mismatch: gtM on v-tags
|
||||
make_repo "v0.1.1"
|
||||
run "y" gtM
|
||||
assert_contains "gtM on v-tags shows mismatch warning" "$OUT" "are you sure"
|
||||
assert_contains "mismatch warning names existing format" "$OUT" "The latest tag is v0.1.1"
|
||||
assert_tag_exists "gtM on v-tags still bumps using real v prefix" "v1.0.0"
|
||||
|
||||
# No mismatch: gtvM (gtM -v) on v-tags
|
||||
make_repo "v0.1.1"
|
||||
run "y" gtM -v
|
||||
assert_not_contains "gtvM (gtM -v) on v-tags shows no mismatch warning" "$OUT" "are you sure"
|
||||
assert_tag_exists "gtvM (gtM -v) bumps major keeping v prefix" "v1.0.0"
|
||||
|
||||
# Mismatch: gtvM (gtM -v) on non-v tags
|
||||
make_repo "0.1.1"
|
||||
run "y" gtM -v
|
||||
assert_contains "gtvM (gtM -v) on non-v tags shows mismatch warning" "$OUT" "are you sure"
|
||||
assert_tag_exists "gtvM (gtM -v) on non-v tags still bumps using real (no) prefix" "1.0.0"
|
||||
|
||||
# Invalid tag format on latest -> refuse to guess
|
||||
make_repo "release-42"
|
||||
run "y" gtM
|
||||
assert_contains "non-semver latest tag refuses to guess" "$OUT" "refusing to guess"
|
||||
assert_status "non-semver latest tag exits 1" 1 "$STATUS"
|
||||
|
||||
# Latest-by-creation-date selection with multiple tags: the higher version
|
||||
# number (5.0.0) is created first; the lower one (1.0.0) is created after,
|
||||
# so it should win as "latest" despite being numerically smaller.
|
||||
# Explicit dates avoid a same-second tie between the two commits.
|
||||
make_repo
|
||||
GIT_COMMITTER_DATE="2020-01-01T00:00:00" GIT_AUTHOR_DATE="2020-01-01T00:00:00" \
|
||||
git commit --allow-empty -q -m "c1" --amend --date="2020-01-01T00:00:00"
|
||||
git tag 5.0.0
|
||||
GIT_COMMITTER_DATE="2021-01-01T00:00:00" GIT_AUTHOR_DATE="2021-01-01T00:00:00" \
|
||||
git commit --allow-empty -q -m "c2"
|
||||
git tag 1.0.0
|
||||
run "y" gtM
|
||||
assert_tag_exists "bumps from the most recently created tag, not highest version" "2.0.0"
|
||||
assert_tag_absent "does not bump the numerically-higher but older tag" "6.0.0"
|
||||
|
||||
# --- summary --------------------------------------------------------------
|
||||
|
||||
echo
|
||||
echo "Passed: $pass_count, Failed: $fail_count"
|
||||
[[ "$fail_count" -eq 0 ]]
|
||||
Loading…
Reference in a new issue