9c8131e417a15fccb15615e3b03ce44a53678fe0

Author
Marc Cornellà <hello@mcornella.com>
Committer
Marc Cornellà <hello@mcornella.com>
Date

Message

perf(changelog): use a single `git log` command to get all commit messages

Diff

  1diff --git a/tools/changelog.sh b/tools/changelog.sh
  2index ebdffba0a6b996408c52577f1bd03ee6bb0cd002..13cfb95304eb3f4568f48b42036dad8b2e53750c 100755
  3--- a/tools/changelog.sh
  4+++ b/tools/changelog.sh
  5@@ -1,5 +1,8 @@
  6 #!/usr/bin/env zsh
  7 
  8+cd "$ZSH"
  9+setopt extendedglob
 10+
 11 ##############################
 12 # CHANGELOG SCRIPT CONSTANTS #
 13 ##############################
 14@@ -114,15 +117,8 @@ function parse-commit {
 15     fi
 16   }
 17 
 18-  # Ignore commit if it is a merge commit
 19-  if [[ $(command git show -s --format=%p $1 | wc -w) -gt 1 ]]; then
 20-    return
 21-  fi
 22-
 23   # Parse commit with hash $1
 24-  local hash="$1" subject body warning rhash
 25-  subject="$(command git show -s --format=%s $hash)"
 26-  body="$(command git show -s --format=%b $hash)"
 27+  local hash="$1" subject="$2" body="$3" warning rhash
 28 
 29   # Commits following Conventional Commits (https://www.conventionalcommits.org/)
 30   # have the following format, where parts between [] are optional:
 31@@ -384,7 +380,8 @@ function main {
 32   # Commit classification arrays
 33   local -A commits subjects scopes breaking reverts
 34   local truncate=0 read_commits=0
 35-  local hash version tag
 36+  local version tag
 37+  local hash refs subject body
 38 
 39   # Get the first version name:
 40   # 1) try tag-like version, or
 41@@ -396,17 +393,40 @@ function main {
 42     || version=$(command git symbolic-ref --quiet --short $until 2>/dev/null) \
 43     || version=$(command git rev-parse --short $until 2>/dev/null)
 44 
 45-  # Get commit list from $until commit until $since commit, or until root
 46-  # commit if $since is unset, in short hash form.
 47-  command git rev-list --abbrev-commit --abbrev=7 ${since:+$since..}$until | while read hash; do
 48+  # Get commit list from $until commit until $since commit, or until root commit if $since is unset
 49+  local range=${since:+$since..}$until
 50+
 51+  # Git log options
 52+  # -z:             commits are delimited by null bytes
 53+  # --format:       [7-char hash]<field sep>[ref names]<field sep>[subject]<field sep>[body]
 54+  # --abbrev=7:     force commit hashes to be 7 characters long
 55+  # --no-merges:    merge commits are omitted
 56+  local SEP="0mZmAgIcSeP"
 57+  local -a raw_commits
 58+  raw_commits=(${(0)"$(command git log -z \
 59+    --format="%h${SEP}%D${SEP}%s${SEP}%b" --abbrev=7 \
 60+    --no-merges $range)"})
 61+
 62+  local raw_commit
 63+  local -a raw_fields
 64+  for raw_commit in $raw_commits; do
 65     # Truncate list on versions with a lot of commits
 66     if (( ++read_commits > 40 )); then
 67       truncate=1
 68       break
 69     fi
 70 
 71+    # Read the commit fields (@ is needed to keep empty values)
 72+    raw_fields=("${(@ps:$SEP:)raw_commit}")
 73+    hash="${raw_fields[1]}"
 74+    refs="${raw_fields[2]}"
 75+    subject="${raw_fields[3]}"
 76+    body="${raw_fields[4]}"
 77+
 78     # If we find a new release (exact tag)
 79-    if tag=$(command git describe --exact-match --tags $hash 2>/dev/null); then
 80+    if [[ "$refs" = *tag:\ * ]]; then
 81+      # Parse tag name (needs: setopt extendedglob)
 82+      tag="${${refs##*tag: }%%,# *}"
 83       # Output previous release
 84       display-release
 85       # Reinitialize commit storage
 86@@ -420,7 +440,7 @@ function main {
 87       read_commits=1
 88     fi
 89 
 90-    parse-commit "$hash"
 91+    parse-commit "$hash" "$subject" "$body"
 92   done
 93 
 94   display-release
 95@@ -431,8 +451,6 @@ function main {
 96   fi
 97 }
 98 
 99-cd "$ZSH"
100-
101 # Use raw output if stdout is not a tty
102 if [[ ! -t 1 && -z "$3" ]]; then
103   main "$1" "$2" --raw