#!/usr/bin/env bash # review-note: manage code-review notes under refs/notes/review. # The protocol lives in REVIEW.md. set -euo pipefail NOTES_REF=refs/notes/review REMOTE=origin die() { echo "review-note: $*" >&2; exit 1; } usage() { cat >&2 <<'EOF' usage: review-note show [commit] review-note write [--force] review-note latest [branch] review-note push EOF exit 1 } validate() { local file="$1" grep -q '^branch: .\+' "$file" || die "missing or empty 'branch:' header" grep -Eq '^round: [0-9]+$' "$file" || die "missing or invalid 'round:' header" grep -Eq '^verdict: (approve|request-changes)$' "$file" \ || die "verdict must be 'approve' or 'request-changes'" } cmd_show() { local commit="${1:-HEAD}" git notes --ref="$NOTES_REF" show "$commit" 2>/dev/null \ || die "no review note for $commit" } cmd_write() { local force="" file="" local arg for arg in "$@"; do case "$arg" in --force) force=1 ;; *) file="$arg" ;; esac done [ -n "$file" ] || usage [ -f "$file" ] || die "no such file: $file" local tip tip=$(git rev-parse HEAD) if [ -z "$force" ] && git notes --ref="$NOTES_REF" show "$tip" >/dev/null 2>&1; then die "tip $tip already has a review note; pass --force to replace" fi validate "$file" if [ -n "$force" ]; then git notes --ref="$NOTES_REF" add -f -F "$file" "$tip" else git notes --ref="$NOTES_REF" add -F "$file" "$tip" fi } cmd_latest() { local branch="${1:-$(git branch --show-current)}" local blob obj note br rnd best="" best_round=-1 while read -r blob obj; do note=$(git notes --ref="$NOTES_REF" show "$obj") || continue br=$(sed -n '/^$/q; s/^branch: //p' <<<"$note") [ "$br" = "$branch" ] || continue rnd=$(sed -n '/^$/q; s/^round: //p' <<<"$note") [[ "$rnd" =~ ^[0-9]+$ ]] || continue if [ "$rnd" -gt "$best_round" ]; then best_round=$rnd best=$note fi done < <(git notes --ref="$NOTES_REF" list) [ -n "$best" ] || die "no review notes for branch: $branch" printf '%s\n' "$best" } cmd_push() { git rev-parse -q --verify "$NOTES_REF" >/dev/null || die "no review notes to push" git push "$REMOTE" "$NOTES_REF" } main() { local cmd="${1:-}" if [ $# -gt 0 ]; then shift; fi case "$cmd" in show) cmd_show "$@" ;; write) cmd_write "$@" ;; latest) cmd_latest "$@" ;; push) cmd_push "$@" ;; *) usage ;; esac } main "$@"