diff --git a/scripts/count_assisted_by.sh b/scripts/count_assisted_by.sh new file mode 100755 index 000000000..57cdf65d2 --- /dev/null +++ b/scripts/count_assisted_by.sh @@ -0,0 +1,79 @@ +#!/bin/bash +############################################################################## +# Copyright (C) 2026 Eclipse ThreadX contributors +# +# This program and the accompanying materials are made available under the +# terms of the MIT License which is available at +# https://opensource.org/licenses/MIT. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Report the Assisted-by attributions in a repository's history. +# +# scripts/count_assisted_by.sh # HEAD, grouped by value +# scripts/count_assisted_by.sh origin/dev # a branch +# scripts/count_assisted_by.sh origin/dev -- ports # a path +# scripts/count_assisted_by.sh --list origin/dev # one line per commit +# +# Why not git's own trailer parser: git reads trailers only from a block at the +# very end of a message. A squash merge concatenates the branch's commit +# messages, which leaves every trailer but the last one buried mid-message, and +# an indented trailer is skipped as well. Both forms are real attributions and +# both are invisible to --format='%(trailers:key=Assisted-by)'. This reads whole +# commit bodies instead, so the count is complete. + +set -u + +list=0 +if [ "${1:-}" = "--list" ]; then + list=1 + shift +fi + +rev="${1:-}" +if [ -n "$rev" ] && [ "$rev" != "--" ]; then + shift +else + rev="HEAD" +fi + +if [ "${1:-}" = "--" ]; then + shift +fi + +# %x02 opens a record and %x01 separates the hash from the body, so bodies +# containing blank lines survive the pass through awk. +git log "$rev" --format='%x02%H%x01%B' ${1+"$@"} \ + | tr '\n' '\003' | tr '\002' '\n' \ + | awk -F'\001' -v list="$list" ' + NF >= 2 { + body = $2 + gsub(/\003/, "\n", body) + n = split(body, line, "\n") + for (i = 1; i <= n; i++) { + if (line[i] ~ /^[[:space:]]*Assisted-by:[[:space:]]*/) { + value = line[i] + sub(/^[[:space:]]*Assisted-by:[[:space:]]*/, "", value) + sub(/[[:space:]]+$/, "", value) + if (value == "") + continue + if (list) + print substr($1, 1, 8) " " value + else + count[value]++ + } + } + } + END { + if (list) + exit + for (value in count) + printf "%6d %s\n", count[value], value + }' \ + | { if [ "$list" -eq 1 ]; then cat; else sort -rn; fi; }