#!/usr/bin/env bash # Usage: scripts/check-progression.sh # Progression checkpoint: for each module N (that has tests in the track), build a temp copy where src/ holds the # reference solutions of modules <= N and the untouched student stubs for the rest, then run the tests of modules # M01..MN. All must pass: this proves a student who has finished module N has a green suite up to N, and that # no earlier solution secretly depends on a later one. set -uo pipefail track="${1:?usage: check-progression.sh }" repo="$(cd "$(dirname "$0")/.." && pwd)" export PATH="$HOME/.dotnet:$HOME/.local/bin:$PATH" # Module -> files (relative to src/ and solutions/) that the module introduces. A directory entry copies it whole. # Later tasks: extend the entries for m07+ in the Scala and F# tables. files_for() { case "$track:$1" in js:01) echo "util.js todo.js" ;; js:02) echo "model.js" ;; js:03) echo "rules.js" ;; js:04) echo "random.js spawn.js" ;; js:05) echo "game.js" ;; js:06) echo "view.js" ;; js:07) echo "io.js" ;; js:08) echo "stream.js" ;; js:09) echo "input.js app.js runtime.js browser.js main.js" ;; js:10) echo "" ;; # edits game/input/app, already included by m05/m09 js:11) echo "pong" ;; scala:01) echo "Util.scala" ;; scala:02) echo "Model.scala" ;; scala:03) echo "Rules.scala" ;; scala:04) echo "Random.scala Spawn.scala" ;; scala:05) echo "Game.scala" ;; scala:06) echo "View.scala" ;; scala:07) echo "IO.scala" ;; scala:08) echo "Stream.scala" ;; scala:09) echo "Input.scala App.scala Runtime.scala" ;; scala:10) echo "" ;; scala:11) echo "pong" ;; fsharp:*) echo "" ;; # added by the F# tasks *) echo "" ;; esac } case "$track" in js) has() { compgen -G "$repo/js/test/m$1-*.test.js" >/dev/null; } ;; scala) has() { compgen -G "$repo/scala/test/M$1*.test.scala" >/dev/null; } ;; fsharp) has() { compgen -G "$repo/fsharp/tests/M$1*.fs" >/dev/null; } ;; *) echo "unknown track: $track" >&2; exit 2 ;; esac status=0 for n in 01 02 03 04 05 06 07 08 09 10 11; do has "$n" || continue tmp="$(mktemp -d)" tar -C "$repo" --exclude=.git --exclude=node_modules --exclude=bin --exclude=obj \ --exclude=.scala-build --exclude=.bsp --exclude=.superpowers -cf - . | tar -C "$tmp" -xf - for m in 01 02 03 04 05 06 07 08 09 10 11; do [ "$m" -le "$n" ] || break for f in $(files_for "$m"); do [ -e "$tmp/$track/solutions/$f" ] || continue # module not (yet) present in this track rm -rf "$tmp/$track/src/$f" cp -r "$tmp/$track/solutions/$f" "$tmp/$track/src/$f" done done ok=1 for m in 01 02 03 04 05 06 07 08 09 10 11; do [ "$m" -le "$n" ] || break has "$m" || continue if ! out="$(cd "$tmp/$track" && ./test.sh "M$m" 2>&1)"; then echo "checkpoint M$n: FAIL (M$m tests fail with solutions up to M$n)" echo "$out" | tail -40 ok=0; status=1; break fi done [ $ok -eq 1 ] && echo "checkpoint M$n: ok (M01..M$n pass)" rm -rf "$tmp" done exit $status