Skip to content
Open
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
15 changes: 13 additions & 2 deletions bin/omarchy-dev-add-migration
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,19 @@ done

cd "${OMARCHY_PATH:-$(pwd)}"
mkdir -p migrations
migration_file="migrations/$(git log -1 --format=%cd --date=unix).sh"
touch "$migration_file"

# Use wall-clock time, not HEAD's committer date, so two branches cut from the
# same commit do not mint the same migration id (#13516).
id=$(date +%s)
migration_file="migrations/${id}.sh"
# noclobber creates the file with O_EXCL, so concurrent runs cannot claim one id.
set -o noclobber
until { : >"$migration_file"; } 2>/dev/null; do
[[ -e $migration_file ]] || { echo "Cannot create $PWD/$migration_file" >&2; exit 1; }
id=$((id + 1))
migration_file="migrations/${id}.sh"
done
set +o noclobber

if (( ! no_edit )); then
nvim "$migration_file"
Expand Down
33 changes: 33 additions & 0 deletions test/shell.d/dev-add-migration-race-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT

# Pin the clock so both runs start from the same second.
stub_bin="$test_tmp/bin"
mkdir -p "$stub_bin"
cat >"$stub_bin/date" <<'SH'
#!/bin/bash
[[ ${1:-} == "+%s" ]] || exit 1
echo 1790700000
SH
chmod +x "$stub_bin/date"

for trial in $(seq 1 20); do
checkout="$test_tmp/omarchy-$trial"
mkdir -p "$checkout/migrations"

PATH="$stub_bin:$PATH" OMARCHY_PATH="$checkout" "$ROOT/bin/omarchy-dev-add-migration" --no-edit >"$test_tmp/$trial.a" &
first=$!
PATH="$stub_bin:$PATH" OMARCHY_PATH="$checkout" "$ROOT/bin/omarchy-dev-add-migration" --no-edit >"$test_tmp/$trial.b" &
second=$!
wait "$first" "$second"

[[ $(<"$test_tmp/$trial.a") != "$(<"$test_tmp/$trial.b")" ]] ||
fail "two concurrent runs in one checkout create distinct migrations" "trial $trial: both printed $(<"$test_tmp/$trial.a")"
done
pass "two concurrent runs in one checkout create distinct migrations"
41 changes: 41 additions & 0 deletions test/shell.d/dev-add-migration-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

test_tmp=$(mktemp -d)
trap 'rm -rf "$test_tmp"' EXIT

# A checkout whose HEAD was committed at 1789095456, the id #13516 saw reused.
checkout="$test_tmp/omarchy"
mkdir -p "$checkout/migrations"
git -C "$checkout" init -q
GIT_AUTHOR_NAME=test GIT_AUTHOR_EMAIL=test@example.invalid \
GIT_COMMITTER_NAME=test GIT_COMMITTER_EMAIL=test@example.invalid \
GIT_AUTHOR_DATE=@1789095456 GIT_COMMITTER_DATE=@1789095456 \
git -C "$checkout" commit --allow-empty -q -m base

# Pin the clock so the expected ids are exact.
stub_bin="$test_tmp/bin"
mkdir -p "$stub_bin"
cat >"$stub_bin/date" <<'SH'
#!/bin/bash
[[ ${1:-} == "+%s" ]] || exit 1
echo 1790700000
SH
chmod +x "$stub_bin/date"

add_migration() {
PATH="$stub_bin:$PATH" OMARCHY_PATH="$checkout" "$ROOT/bin/omarchy-dev-add-migration" --no-edit
}

created=$(add_migration)
[[ $created == "$checkout/migrations/1790700000.sh" && -f $created ]] ||
fail "a new migration is named after the current time, not HEAD's commit time" "created: $created"
pass "a new migration is named after the current time, not HEAD's commit time"

created=$(add_migration)
[[ $created == "$checkout/migrations/1790700001.sh" && -f $created ]] ||
fail "a second migration in the same second takes the next free id" "created: $created"
pass "a second migration in the same second takes the next free id"