Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 01:00 UTC
| 1 | #!/usr/bin/env bash |
| 2 | # Prints the commits that are new in <target> compared to the release <base>, |
| 3 | # oldest first, one SHA per line. |
| 4 | # |
| 5 | # Usage: changelog-commits.sh <base> <target> |
| 6 | # |
| 7 | # When <base> is an ancestor of <target>, that's simply base..target. When it |
| 8 | # isn't (e.g. base is a 2.11.x release cut from a maintenance branch and |
| 9 | # target is on master), base..target also contains the master commits whose |
| 10 | # fixes were already cherry-picked into the base release. Those are skipped |
| 11 | # when any of the following holds: |
| 12 | # |
| 13 | # 1. The commit has the same patch ID as a commit on the base side |
| 14 | # (a clean cherry-pick). |
| 15 | # 2. Cherry-picking it onto the base would change nothing, but |
| 16 | # cherry-picking it onto the merge base would. That is, the base |
| 17 | # already has the change, and it got there after the branches split. |
| 18 | # This catches clean picks whose lines were changed again later. The |
| 19 | # merge-base condition keeps a revert of something the base never had |
| 20 | # (which would also change nothing) in the list. |
| 21 | # 3. Its subject ends with a PR number, e.g. "(#1234)", and a commit on |
| 22 | # the base side has the identical subject. This catches backports that |
| 23 | # had to be adapted to apply. Subjects without a PR number are never |
| 24 | # matched this way: unrelated commits can share one (for example |
| 25 | # GitHub's "Merge commit from fork" for security advisories). |
| 26 | set -euo pipefail |
| 27 | |
| 28 | base=$(git rev-parse --verify "${1:?usage: $0 <base> <target>}^{commit}") |
| 29 | target=$(git rev-parse --verify "${2:?usage: $0 <base> <target>}^{commit}") |
| 30 | |
| 31 | if git merge-base --is-ancestor "$base" "$target"; then |
| 32 | git rev-list --reverse "$base..$target" |
| 33 | exit 0 |
| 34 | fi |
| 35 | |
| 36 | merge_base=$(git merge-base "$base" "$target") |
| 37 | base_tree=$(git rev-parse "$base^{tree}") |
| 38 | merge_base_tree=$(git rev-parse "$merge_base^{tree}") |
| 39 | backported_subjects=$(git log --format=%s "$merge_base..$base" | grep -E '\(#[0-9]+\)$' || true) |
| 40 | |
| 41 | # picking_changes_nothing <commit> <onto> <onto-tree> |
| 42 | picking_changes_nothing() { |
| 43 | local result |
| 44 | if ! result=$(git merge-tree --write-tree --merge-base="$1^" "$2" "$1" 2>/dev/null); then |
| 45 | return 1 # conflicts, so it would change something |
| 46 | fi |
| 47 | [ "$(head -n 1 <<< "$result")" = "$3" ] |
| 48 | } |
| 49 | |
| 50 | for commit in $(git rev-list --reverse --cherry-pick --right-only "$base...$target"); do |
| 51 | subject=$(git log -1 --format=%s "$commit") |
| 52 | if [[ $subject =~ \(#[0-9]+\)$ ]] && grep -qxF -- "$subject" <<< "$backported_subjects"; then |
| 53 | continue |
| 54 | fi |
| 55 | if picking_changes_nothing "$commit" "$base" "$base_tree" && |
| 56 | ! picking_changes_nothing "$commit" "$merge_base" "$merge_base_tree"; then |
| 57 | continue |
| 58 | fi |
| 59 | echo "$commit" |
| 60 | done |