Skip to content
Merged
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
10 changes: 9 additions & 1 deletion bin/fm-nm-watch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,15 @@ cmd_register_clone() { # <task-id> <path>
lock=$(fm_meta_lock_path "$META") || die "cannot resolve the task record lock"
fm_lock_acquire_wait "$lock" || die "cannot lock the task record"
tmp=$(mktemp "$STATE/.fm-nm-meta.XXXXXX") || { fm_lock_release "$lock"; die "cannot stage the task record"; }
if ! { { grep -v '^nm_clone=' "$META" || true; printf 'nm_clone=%s\n' "$path"; } > "$tmp" \
# The PR block (pr=, pr_head=, x_* lines) must stay last: fm_pr_metadata_identity_parse
# rejects any other line after the first pr=, so nm_clone= goes before it.
if ! { awk -v clone="$path" '
/^nm_clone=/ { next }
seen_pr && (/^pr=/ || /^pr_head=/ || /^x_(request|request_ts|followups|platform|reply_max_chars)=/) { tail = tail $0 "\n"; next }
/^pr=/ && !seen_pr { seen_pr = 1; tail = $0 "\n"; next }
{ head = head $0 "\n" }
END { printf "%s", head; printf "nm_clone=%s\n", clone; printf "%s", tail }
' "$META" > "$tmp" \
&& mv -f -- "$tmp" "$META"; }; then
rm -f -- "$tmp"
fm_lock_release "$lock"
Expand Down
23 changes: 23 additions & 0 deletions tests/fm-nm-watch.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,31 @@ test_register_clone_records_and_rearms() {
pass "register-clone records the clone and re-arms the watch on it, refusing unusable paths"
}

test_register_clone_keeps_pr_block_last() {
local home id=clone-b clone meta
home=$(new_task_home prblock "$id")
clone="$TMP_ROOT/prblock-clone"
git clone -q "$home/wt" "$clone"
meta="$home/state/$id.meta"
# shellcheck source=bin/fm-pr-lib.sh
. "$ROOT/bin/fm-pr-lib.sh"

FM_HOME="$home" "$NMW" register-clone "$id" "$clone" >/dev/null 2>&1 || fail "register-clone failed without a PR block"
[ "$(tail -n 1 "$meta")" = "nm_clone=$clone" ] || fail "without a PR block nm_clone= is not last"

printf 'pr=https://github.com/example/repo/pull/7\npr_head=%s\n' "$(git -C "$home/wt" rev-parse HEAD)" >> "$meta"
for _ in 1 2; do
FM_HOME="$home" "$NMW" register-clone "$id" "$clone" >/dev/null 2>&1 || fail "register-clone failed with a PR block"
[ "$(grep -c '^nm_clone=' "$meta")" = 1 ] || fail "nm_clone= is not present exactly once"
[ "$(tail -n 2 "$meta" | cut -d= -f1 | paste -sd,)" = "pr,pr_head" ] || fail "the PR block is not last"
fm_pr_metadata_identity_parse "$meta" || fail "the merge-poll validator rejects the record after registration"
done
pass "register-clone keeps the PR block last so the merge poll stays valid"
}

test_rearm_converges_on_existing_watch
test_arm_failure_raises_check_wake
test_register_clone_records_and_rearms
test_register_clone_keeps_pr_block_last

echo "all fm-nm-watch tests passed"
Loading