|
| 1 | +#! /bin/bash |
| 2 | + |
| 3 | +function id_current_tag() { |
| 4 | + local INPUT="${1}" |
| 5 | + git describe --tags --abbrev=0 ${INPUT} |
| 6 | +} |
| 7 | + |
| 8 | +function enumerate_tag_history() { |
| 9 | + local HEAD_TAG=$(id_current_tag HEAD) |
| 10 | + { git rev-list --tags --ancestry-path "$(git tag --no-contains "${HEAD_TAG}" | sort -V | head -n1)^..HEAD" ; wait ;} | xargs -I{} git tag --points-at "{}" 2>/dev/null ; |
| 11 | + wait ; |
| 12 | +} |
| 13 | + |
| 14 | +# step 1: is designed to determine the current and previous Git tags and |
| 15 | +# then construct a Git range based on these tags. If no argument is provided, it defaults to |
| 16 | +# using the tags. |
| 17 | +if [[ -z "${1}" ]] ; then |
| 18 | +GIT_CURRENT_TAG=$(id_current_tag) |
| 19 | +GIT_PREVIOUS_TAG=$(enumerate_tag_history | grep -A 1 -F -f <(git describe --tags --abbrev=0 "${GIT_CURRENT_TAG}") | tail -n1 ) |
| 20 | +FALLBACK_GIT_RANGE="${GIT_CURRENT_TAG}...${GIT_PREVIOUS_TAG}" |
| 21 | +fi ; |
| 22 | +GIT_RANGE="${1:-${FALLBACK_GIT_RANGE}}" |
| 23 | + |
| 24 | +# cache the git log |
| 25 | +CHANGELOG_BUFFER=".chagelog_buffer.txt" |
| 26 | +cat <(git log "${GIT_RANGE}" --reverse --pretty=format:"COMMIT_START%n%h%n%B%nCOMMIT_END") >"${CHANGELOG_BUFFER}" ; wait ; |
| 27 | + |
| 28 | +printf "%s\n\n" "## What Changed between \`${GIT_RANGE}\`" ; |
| 29 | + |
| 30 | +# auto-collect gitlog |
| 31 | +for FILE_INPUT in $(git log --pretty=format:"%n" --name-only "${GIT_RANGE}" | sort -id | uniq) ; do |
| 32 | + |
| 33 | +if [[ ( -n "$FILE_INPUT" ) ]] ; then |
| 34 | + |
| 35 | +awk -v RS='' -v ORS='\n\n\n' -v filename="$FILE_INPUT" ' |
| 36 | + { |
| 37 | + # Check if the block contains a valid change-log entry |
| 38 | + if ($0 ~ /((Changes in)|(Additions with)|(Deletions from)) file/ && $0 ~ filename) { |
| 39 | + # Ensure that there is no content before the match |
| 40 | + if ($0 ~ /^[[:space:]]*((Changes in)|(Additions with)|(Deletions from))/) { |
| 41 | + # Extract the header (first line) and the content |
| 42 | + header = $0; |
| 43 | + header_line = substr(header, 1, index(header, ":") - 1); # Get the header |
| 44 | + if (header_line ~ filename) { |
| 45 | + content = substr(header, index(header, ":") + 1); # Get the content after the header |
| 46 | + # Combine the header and content |
| 47 | + combined[header_line] = (combined[header_line] ? combined[header_line] "\n" : "") content; |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + } |
| 52 | + END { |
| 53 | + # Print combined entries |
| 54 | + for (h in combined) { |
| 55 | + print h ":" combined[h] |
| 56 | + } |
| 57 | + } |
| 58 | +' <"${CHANGELOG_BUFFER}" | sort -id | uniq | sort -rd |
| 59 | + |
| 60 | +fi ; |
| 61 | + |
| 62 | +done ; |
| 63 | + |
| 64 | +# remove the buffer |
| 65 | +rm -f "${CHANGELOG_BUFFER}" 2>/dev/null || : ; |
0 commit comments