#!/bin/bash # Collect a log of candidate commits for consideration of commit authors as # active developers according to https://www.wesnoth.org/constitution/ # ("tangible output [...] at least once every three months within the last 12 calendar months" # for project manager: "increased to 18 calendar months") # # Note: Devs not committing their work themselves or devs performing # housekeeping are naturally not considered here! # # First optional argument is the stable release date in ISO 8601 format. # Default: 2021-10-24 (1.16 release date) # Second optional argument is the path to a wesnoth repo checkout. # Default: . (current dir) # The repo checkout must contain local tracking branches of all relevant stable # branches or they won't be considered. # # Output is written to a new dir: wesnoth-election- # - There will be a complete commit log (commits-by-author.log) of the 18 # months before the stable release. # - A subdir "dev_candidate" with files that contain the commit log of single # authors that have at least one commit in each 3 month time span in the last # 12 months. # - A subdir "pm_candidate" with files that contain the commit log of single # authors that have at least one commit in each 3 month time span in the last # 18 months (only commits from 12 to 18 months back are in the file so only # what's not already in the dev log). # # Github commit graphs can be used to somewhat double check against: # https://github.com/wesnoth/wesnoth/graphs/contributors?from=2020-04-24&to=2021-10-24&type=c # Though the graph just shows the default branch (master) while this script # considers master and stable branches (1.*). # # Expects GNU date for the date calculations. # stable release date in ISO 8601 format release_date=${1-2021-10-24} # location of wesnoth repo checkout, default to current dir repo_dir=${2-.} git -C "$repo_dir" rev-parse --git-dir >/dev/null 2>&1 || { printf '"%s" is not a git repository!\n' "$repo_dir" >&2; exit 1; } start_date=$(date -d "$release_date - 18 months - 1 week" +%F) year=${release_date%%-*} output_dir=wesnoth-election-"$year" # calculate start and end UNIX epoch for 3 month time spans with a week grace period date6=$(date -d "$release_date - 18 months" +%s) date6s=$(date -d "$release_date - 18 months - 1 week" +%s) date6e=$(date -d "$release_date - 15 months+1 week" +%s) date5=$(date -d "$release_date - 15 months" +%s) date5s=$(date -d "$release_date - 15 months - 1 week" +%s) date5e=$(date -d "$release_date - 12 months+1 week" +%s) date4=$(date -d "$release_date - 12 months" +%s) date4s=$(date -d "$release_date - 12 months - 1 week" +%s) date4e=$(date -d "$release_date - 9 months+1 week" +%s) date3=$(date -d "$release_date - 9 months" +%s) date3s=$(date -d "$release_date - 9 months - 1 week" +%s) date3e=$(date -d "$release_date - 6 months+1 week" +%s) date2=$(date -d "$release_date - 6 months" +%s) date2s=$(date -d "$release_date - 6 months - 1 week" +%s) date2e=$(date -d "$release_date - 3 months+1 week" +%s) date1=$(date -d "$release_date - 3 months" +%s) date1s=$(date -d "$release_date - 3 months - 1 week" +%s) date1e=$(date -d "$release_date" +%s) commitlog=commits-by-author.log #printf '%s - %s\n' "$date1s" "$date1e" "$date2s" "$date2e" "$date3s" "$date3e" "$date4s" "$date4e" mkdir "$output_dir" || exit cd "$output_dir" || exit # get all commits in tsv-format: () # GIT_TEST_DATE_NOW makes the relative dates relative to that timestamp gitlog() { GIT_TEST_DATE_NOW=$date1e git -C "$repo_dir" log --branches=master --branches='1.*' $'--pretty=format:%an\t%ct\t%ci (%cr)\t%h\t%s\t(%cn)' --before="$release_date" "$@" } gitlog --since="$start_date" | sort > "$commitlog" # get authors with commits in each time span declare -A span1 span2 span3 span4 span5 span6 while IFS=$'\t' read -r author date rest do author=${author,,} # there is no a >= b so need to write ! a < b if [[ ! $date < $date1s && ! $date > $date1e ]]; then span1[$author]=1; continue; fi if [[ ! $date < $date2s && ! $date > $date2e ]]; then span2[$author]=1; continue; fi if [[ ! $date < $date3s && ! $date > $date3e ]]; then span3[$author]=1; continue; fi if [[ ! $date < $date4s && ! $date > $date4e ]]; then span4[$author]=1; continue; fi if [[ ! $date < $date5s && ! $date > $date5e ]]; then span5[$author]=1; continue; fi if [[ ! $date < $date6s && ! $date > $date6e ]]; then span6[$author]=1; continue; fi done < "$commitlog" # check for at least one commit in the last 4 3 month time spans dev_candidate() { [[ ${span1[$author]+exists} && ${span2[$author]+exists} && ${span3[$author]+exists} && ${span4[$author]+exists} ]]; } # check for at least one commit in the last 6 3 month time spans pm_candidate() { [[ ${span1[$author]+exists} && ${span2[$author]+exists} && ${span3[$author]+exists} && ${span4[$author]+exists} && ${span5[$author]+exists} && ${span6[$author]+exists} ]]; } mkdir {dev,pm}_candidate || exit print_commit() { if [[ $1 ]] then # print timestamp if date crosses a 3 month date limit if [[ $1 < $date1 && ! $2 < $date1 ]] then printf '%(%F %T)T 3 months back\n' "$date1" elif [[ $1 < $date2 && ! $2 < $date2 ]] then printf '%(%F %T)T 6 months back\n' "$date2" elif [[ $1 < $date3 && ! $2 < $date3 ]] then printf '%(%F %T)T 9 months back\n' "$date3" elif [[ $1 < $date4 && ! $2 < $date4 ]] then printf '%(%F %T)T 12 months back\n' "$date4" elif [[ $1 < $date5 && ! $2 < $date5 ]] then printf '%(%F %T)T 15 months back\n' "$date5" elif [[ $1 < $date6 && ! $2 < $date6 ]] then printf '%(%F %T)T 18 months back\n' "$date6" fi fi printf '%s\t%s\n' "$3" "$4" } # write commits of each active dev candidate to its own file, write commits in the extended project manager period to a separate pm file # appending each commit instead of opening the file just once so we don't get empty files for authors not passing the checks. prev_date= prev_author= while IFS=$'\t' read -r author date rest do author=${author,,} if [[ $prev_author != $author ]] then prev_date= fi prev_author=$author if [[ ! $date > $date4s ]] then if pm_candidate "$author" then print_commit "$prev_date" "$date" "$author" "$rest" >> "pm_candidate/$author" prev_date=$date fi continue fi if dev_candidate "$author" then print_commit "$prev_date" "$date" "$author" "$rest" >> "dev_candidate/$author" prev_date=$date fi done < "$commitlog"