diff --git a/Makefile b/Makefile index d2efba9..177337e 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,14 @@ help: ## Show this help install: ## Install devflow to PREFIX (~/.local by default) @mkdir -p $(BINDIR) $(LIBDIR) @cp -R lib templates skills config docker $(LIBDIR)/ + @rm -f $(LIBDIR)/devflow-bin @cp bin/devflow $(LIBDIR)/devflow-bin @chmod 755 $(LIBDIR)/devflow-bin + @# rm -f BEFORE the redirect: if $(BINDIR)/devflow is a leftover `make link` SYMLINK, + @# `printf > symlink` follows it and overwrites the TARGET (the source bin/devflow), + @# gutting the checkout while leaving the symlink in place. Removing it first makes + @# install REPLACE the symlink with a real launcher (idempotent + symlink-safe). + @rm -f $(BINDIR)/devflow @printf '#!/usr/bin/env bash\nexport DEVFLOW_ROOT="%s"\nexec "%s/devflow-bin" "$$@"\n' \ "$(LIBDIR)" "$(LIBDIR)" > $(BINDIR)/devflow @chmod 755 $(BINDIR)/devflow diff --git a/tests/unit/init.bats b/tests/unit/init.bats index e2d378e..e228e44 100644 --- a/tests/unit/init.bats +++ b/tests/unit/init.bats @@ -88,3 +88,23 @@ teardown() { assert_output --partial "Skip" refute_output --partial "Added" } + +# ── make install: symlink-safe (regression for the write-through-symlink bug) ── + +@test "make install replaces a leftover 'make link' symlink instead of writing through it" { + local prefix="${BATS_TEST_TMPDIR}/prefix" + mkdir -p "$prefix/bin" + # sentinel standing in for the source bin/devflow a leftover symlink would point at + local sentinel="${BATS_TEST_TMPDIR}/source-bin-devflow" + printf 'FULL SOURCE SCRIPT — must not be overwritten\n' > "$sentinel" + ln -sf "$sentinel" "$prefix/bin/devflow" # leftover `make link` symlink + + run make -C "$DEVFLOW_ROOT" install PREFIX="$prefix" + assert_success + + # BINDIR/devflow must be a REAL launcher now, not the symlink... + [ ! -L "$prefix/bin/devflow" ] || fail "BINDIR/devflow is still a symlink (wrote through it)" + # ...and the symlink target (stand-in for the source checkout) must be UNTOUCHED + run cat "$sentinel" + assert_output --partial "FULL SOURCE SCRIPT" +}