Skip to content

Commit c74ac25

Browse files
committed
New and improved cherry-pick support
1 parent 044dcf5 commit c74ac25

File tree

3 files changed

+151
-6
lines changed

3 files changed

+151
-6
lines changed

README.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,14 @@ Eg. you can run the gradle build like this - ./gradlew clean -Pddprof.jar=file:/
129129
## Working with upstream
130130
131131
Although this project still shares the git history with the upstream the code structure is different. This makes it dificult to reliably
132-
cherry-pick the upstream changes. To make this easier we have a script that will prepare a filtered version of the upstream repository
133-
and add it as 'cherry' remote to this repository. This way you can cherry-pick the changes from the upstream repository with (relative) ease.
132+
cherry-pick the upstream changes. To make this easier we have a script that will prepare the upstream repository
133+
and add it as 'cherry' remote to this repository.
134+
This way you can cherry-pick the changes from the upstream repository with (relative) ease.
135+
136+
```bash
137+
./utils/init_cherrypick_repo.sh # you need to run this only once
138+
139+
./utils/cherry.sh <commit>
140+
# ... resolve conflicts, if any
141+
./utils/cherry.sh --continue # to commit the resolved conflicts
142+
```

utils/cherry.sh

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
6+
if [ $# -ne 1 ]; then
7+
echo "Usage: $0 [<upstream-commit-hash> | --continue | --abort]"
8+
exit 1
9+
fi
10+
11+
CMD=$1
12+
13+
if [[ "$CMD" == "--continue" ]] || [[ "$CMD" == "--abort" ]]; then
14+
GIT_DIR="$HERE/../.git"
15+
if [ -f "$GIT_DIR/CHERRY_PICK_HEAD" ] && [ -f "$GIT_DIR/CHERRY_COMMIT_EDITMSG" ]; then
16+
if [[ "$CMD" == "--continue" ]]; then
17+
git commit -F "$GIT_DIR/CHERRY_COMMIT_EDITMSG" --author "$(cat $GIT_DIR/COMMIT_AUTHOR_NAME) <$(cat $GIT_DIR/COMMIT_AUTHOR_EMAIL)>)" --date "$(cat $GIT_DIR/COMMIT_AUTHOR_DATE)"
18+
else
19+
git reset --hard HEAD
20+
fi
21+
rm -f $GIT_DIR/CHERRY_PICK_HEAD $GIT_DIR/CHERY_COMMIT_EDITMSG $GIT_DIR/COMMIT_AUTHOR_NAME $GIT_DIR/COMMIT_AUTHOR_EMAIL $GIT_DIR/COMMIT_AUTHOR_DATE
22+
exit 0
23+
else
24+
echo "No cherry-pick in progress."
25+
exit 1
26+
fi
27+
fi
28+
29+
UPSTREAM_COMMIT=$1
30+
31+
PATCH_FILE=$(mktemp)
32+
TMP_REWRITTEN=$(mktemp)
33+
34+
cleanup() {
35+
rm -f "$PATCH_FILE" "$TMP_REWRITTEN"
36+
}
37+
trap cleanup EXIT
38+
39+
# Step 1: Generate patch from upstream commit (only src/)
40+
git diff-tree -p "$UPSTREAM_COMMIT" -- src/ > "$PATCH_FILE"
41+
42+
# Step 2: Rewrite and filter paths
43+
awk '
44+
function is_cpp_or_header(path) {
45+
return path ~ /\.(cpp|cc|cxx|h|hpp)$/
46+
}
47+
function is_api_java(path) {
48+
return path ~ /^src\/api\/.*\.java$/
49+
}
50+
function translate_path(path) {
51+
if (is_cpp_or_header(path)) {
52+
sub(/^src\//, "ddprof-lib/src/main/cpp/", path)
53+
return path
54+
} else if (is_api_java(path)) {
55+
sub(/^src\/api\//, "ddprof-lib/src/main/java/", path)
56+
return path
57+
}
58+
return ""
59+
}
60+
61+
BEGIN {
62+
skip = 0
63+
}
64+
65+
/^diff --git a\// {
66+
a = substr($3, 3)
67+
b = substr($4, 3)
68+
a_new = translate_path(a)
69+
b_new = translate_path(b)
70+
if (a_new == "" || b_new == "") {
71+
skip = 1
72+
next
73+
}
74+
print "diff --git a/" a_new " b/" b_new
75+
skip = 0
76+
next
77+
}
78+
79+
/^--- a\// {
80+
if (skip) next
81+
path = substr($0, 7)
82+
newpath = translate_path(path)
83+
if (newpath == "") { skip = 1; next }
84+
print "--- a/" newpath
85+
next
86+
}
87+
88+
/^\+\+\+ b\// {
89+
if (skip) next
90+
path = substr($0, 7)
91+
newpath = translate_path(path)
92+
if (newpath == "") { skip = 1; next }
93+
print "+++ b/" newpath
94+
next
95+
}
96+
97+
{
98+
if (!skip) print
99+
}
100+
' "$PATCH_FILE" > "$TMP_REWRITTEN"
101+
102+
# Step 3: Apply the rewritten patch if it's not empty
103+
if ! grep -q '^diff --git' "$TMP_REWRITTEN"; then
104+
echo "No applicable changes after path filtering. Skipping commit $UPSTREAM_COMMIT"
105+
exit 0
106+
fi
107+
108+
# Step 4: Commit using original metadata
109+
tree=$(git write-tree)
110+
parent=$(git rev-parse HEAD)
111+
author_name=$(git show -s --format='%an' "$UPSTREAM_COMMIT")
112+
author_email=$(git show -s --format='%ae' "$UPSTREAM_COMMIT")
113+
author_date=$(git show -s --format='%aI' "$UPSTREAM_COMMIT")
114+
commit_message=$(git show -s --format='%s%n%n%b' "$UPSTREAM_COMMIT")
115+
116+
if ! grep -q "$UPSTREAM_COMMIT" <<< "$commit_message"; then
117+
commit_message="$commit_message
118+
119+
(cherry picked from commit $UPSTREAM_COMMIT)"
120+
fi
121+
122+
if ! git apply --3way "$TMP_REWRITTEN"; then
123+
echo "Patch had conflicts. Please resolve manually, then run:"
124+
echo "./utils/cherry.sh --continue"
125+
echo " or "
126+
echo " git add <resolved files>"
127+
echo " git commit --author=\"$author_name <$author_email>\" --date=\"$author_date\" -m \"$commit_message\""
128+
echo
129+
echo "$author_date" > .git/COMMIT_AUTHOR_DATE
130+
echo "$author_email" > .git/COMMIT_AUTHOR_EMAIL
131+
echo "$author_name" > .git/COMMIT_AUTHOR_NAME
132+
echo "$UPSTREAM_COMMIT" > .git/CHERRY_PICK_HEAD
133+
echo "$commit_message" > .git/CHERRY_COMMIT_EDITMSG
134+
exit 1
135+
fi
136+
137+
GIT_AUTHOR_NAME="$author_name" \
138+
GIT_AUTHOR_EMAIL="$author_email" \
139+
GIT_AUTHOR_DATE="$author_date" \
140+
git commit-tree "$tree" -p "$parent" -m "$commit_message" | xargs git reset --hard

utils/init_cherypick_repo.sh

-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ if [ ! -d "$PATH_REPO" ]; then
1616
git clone https://github.com/async-profiler/async-profiler.git $PATH_REPO
1717

1818
cd "$PATH_REPO" || exit 1
19-
git filter-repo --path-rename src/:ddprof-lib/src/main/cpp/
20-
21-
# filter-repo will remove the remote origin, so we need to add it back but as 'upstream' to avoid
22-
# accidental pushes to the original repo
2319

2420
git remote add upstream https://github.com/async-profiler/async-profiler.git
2521
fi

0 commit comments

Comments
 (0)