From 20509a30d88c250879fe1d586ee165d462540baa Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 20 Feb 2025 14:48:30 +0100 Subject: [PATCH] tools/git-grouped-log: add script to generated git log Signed-off-by: Karel Zak --- tools/git-grouped-log | 103 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100755 tools/git-grouped-log diff --git a/tools/git-grouped-log b/tools/git-grouped-log new file mode 100755 index 00000000000..78a27810bcf --- /dev/null +++ b/tools/git-grouped-log @@ -0,0 +1,103 @@ +#!/bin/bash +# +# git-grouped-log - generates a grouped list of commits based on subsystems +# prefix in commit messages. +# +# Copyright (C) 2025 Karel Zak +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. + +# Ensure we're in a Git repository +git rev-parse --is-inside-work-tree >/dev/null 2>&1 || { + echo "Error: Not inside a Git repository." >&2 + exit 1 +} + +# Display help message +if [[ "$1" == "--help" ]]; then + echo "Usage: $(basename $0) [--start ] [--end ]" + echo + echo "Generates a grouped list of commits based on subsystems." + exit 0 +fi + +declare -A commits +declare -A subsystems + +start_commit="HEAD" +end_commit="" + +while [[ $# -gt 0 ]]; do + case "$1" in + --start) + start_commit="$2" + shift 2 + ;; + --end) + end_commit="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" >&2 + exit 1 + ;; + esac +done + +# Verify end and start +if ! git rev-parse --verify "$start_commit" >/dev/null 2>&1; then + echo "Error: Start commit '$start_commit' not found." >&2 + exit 1 +fi +if [[ -n "$end_commit" ]] && ! git rev-parse --verify "$end_commit" >/dev/null 2>&1; then + echo "Error: End commit '$end_commit' not found." >&2 + exit 1 +fi + +# Construct git log range +if [[ -n "$end_commit" ]]; then + range="$end_commit..$start_commit" +else + range="$start_commit" +fi + +while IFS='|' read -r subj author; do + # Handle "Revert" commits separately + if [[ "$subj" =~ ^Revert\ \"([^:]+):.* ]]; then + subsys="${BASH_REMATCH[1]}" + desc="(reverted) "$(echo "$subj" | sed -E 's/^Revert \"[^:]+: //;s/\"$//') + else + # Extract subsystem name (everything before the first colon) + subsys=$(echo "$subj" | awk -F': ' '{print $1}') + desc=$(echo "$subj" | awk -F': ' '{$1=""; sub(/^ /, ""); print}') + fi + + # If no subsystem is detected, categorize under "Misc" + if [[ -z "$desc" ]]; then + subsys="Misc" + desc="$subj" + fi + + key=$(echo "$subsys" | sed 's|[^a-zA-Z0-9_]|_|g') + + subsystems["$key"]="$subsys" + commits["$key"]+=" - $desc (by $author) +" +done < <(git log --no-merges --pretty=format:'%s|%an' "$range" --) + +misc="" +for key in "${!commits[@]}"; do + if [[ "${subsystems[$key]}" == "Misc" ]]; then + misc="${subsystems[$key]}:\n${commits[$key]}" + else + echo "${subsystems[$key]}:" + echo -e "${commits[$key]}" + fi +done + +if [[ -n "$misc" ]]; then + echo -e "$misc" +fi