@marcel91200 / caddy Mirror · read-only
Fork 0

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

master
sh 60 lines 2.56 KB
Raw
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