Skip to content

Commit 9211202

Browse files
Add git merge scripts
1 parent e384f2d commit 9211202

2 files changed

Lines changed: 278 additions & 0 deletions

File tree

tools/git/git-fwd-merge

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/bin/bash
2+
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
# Var
21+
tmpMessageFile="${PWD}/.git-tmp-message.txt"
22+
23+
# Check if branch was specified
24+
branch=$1
25+
if [ -z ${branch} ]; then
26+
echo "Usage: git fwd-merge branch-name"
27+
echo
28+
exit 1
29+
fi
30+
31+
# Construct merge message
32+
currentBranch=$(git branch | grep "^*" | sed -e "s/^[*] //")
33+
echo "Merge release branch ${branch} to ${currentBranch}" > ${tmpMessageFile}
34+
35+
# Are you sure?
36+
echo "Merging release branch ***${branch}*** into ***${currentBranch}*** branch in 5 seconds. CTRL+c to abort.."
37+
sec=5
38+
while [ $sec -ge 0 ]; do
39+
echo -n "${sec} "
40+
sec=$((sec-1))
41+
sleep 1
42+
done
43+
echo "There we go!"
44+
45+
# Do the actual merge
46+
git merge --no-ff --log -m "$(cat .git-tmp-message.txt)" ${branch}
47+
if [ $? -gt 0 ]; then
48+
echo "ERROR: Merge failed, aborting."
49+
git merge --abort
50+
fi
51+
52+
# Clean up
53+
rm -fr ${tmpMessageFile}
54+
55+
# What's next
56+
echo "We're done! Please double check using 'git log -p' and 'git push' when you're sure."

tools/git/git-pr

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/bin/bash
2+
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
20+
# Should we clean-up?
21+
cleanup=1
22+
23+
clean_up_and_exit() {
24+
if [ "${cleanup}" -eq 1 ]; then
25+
echo
26+
git branch -D pr/${prId} >/dev/null 2>&1
27+
rm ${jsonTmp} ${tmpMessageFile} >/dev/null 2>&1
28+
fi
29+
exit $1
30+
}
31+
32+
# Arguments
33+
argument=$1
34+
prId=${argument}
35+
force=0
36+
if [[ "${2}" == "--force" ]]; then
37+
force=1
38+
fi
39+
40+
# Some of us got used to a git pr alias that you had to feed with the PR url
41+
# Let's make this script backwards compatible with the previous one.
42+
if [[ ${argument} =~ https://github.com.* ]]; then
43+
prId=$(echo "${argument}" | awk -F/ {'print $7'})
44+
echo "INFO: Found PR id ${prId} from url"
45+
fi
46+
47+
# Check the arguments
48+
if [ -z ${prId} ]; then
49+
echo "Usage: git pr pool-request-number [ --force ]"
50+
clean_up_and_exit 1
51+
fi
52+
53+
# Vars we need
54+
jsonTmp="${PWD}/${prId}.json"
55+
tmpMessageFile="${PWD}/.git-tmp-message.txt"
56+
57+
# We need UTF-8 to support the GitHub '...' 3-dots-in-1-char, for example.
58+
export LANG="en_EN.UTF-8"
59+
60+
if [ "${prId}" -eq "${prId}" 2>/dev/null ]; then
61+
# Get json data from Github API
62+
curl -s https://api.github.com/repos/apache/cloudstack/pulls/${prId} > ${jsonTmp}
63+
else
64+
echo "ERROR: Pull-request id must be an integer, not '${prId}'"
65+
clean_up_and_exit 1
66+
fi
67+
68+
# Get vars from the GitHub API and parse the returned json
69+
prAuthor=$(cat ${jsonTmp} | python -c "
70+
try:
71+
import sys, json
72+
print json.load(sys.stdin)['user']['login'].encode('utf-8').decode('ascii','ignore')
73+
except:
74+
print ''
75+
")
76+
77+
prTitle=$(cat ${jsonTmp} | python -c "
78+
try:
79+
import sys, json
80+
print json.load(sys.stdin)['title'].encode('utf-8').decode('ascii','ignore')
81+
except:
82+
print ''
83+
")
84+
85+
prBody=$(cat ${jsonTmp} | python -c "
86+
try:
87+
import sys, json
88+
print json.load(sys.stdin)['body'].encode('utf-8').decode('ascii','ignore')
89+
except:
90+
print ''
91+
")
92+
93+
prOriginBranch=$(cat ${jsonTmp} | python -c "
94+
try:
95+
import sys, json
96+
print json.load(sys.stdin)['head']['label'].encode('utf-8').decode('ascii','ignore')
97+
except:
98+
print ''
99+
" | sed -e "s/:/\//")
100+
101+
prState=$(cat ${jsonTmp} | python -c "
102+
try:
103+
import sys, json
104+
print json.load(sys.stdin)['state'].encode('utf-8').decode('ascii','ignore')
105+
except:
106+
print 'Unknown'
107+
")
108+
109+
prMergeableState=$(cat ${jsonTmp} | python -c "
110+
try:
111+
import sys, json
112+
print json.load(sys.stdin)['mergeable_state'].encode('utf-8').decode('ascii','ignore')
113+
except:
114+
print 'Unknown'
115+
")
116+
117+
prDestinationBranch=$(cat ${jsonTmp} | python -c "
118+
try:
119+
import sys, json
120+
print json.load(sys.stdin)['base']['ref'].encode('utf-8').decode('ascii','ignore')
121+
except:
122+
print 'Unknown'
123+
")
124+
125+
prCommits=$(cat ${jsonTmp} | python -c "
126+
try:
127+
import sys, json
128+
print json.load(sys.stdin)['commits']
129+
except:
130+
print 'Unknown'
131+
")
132+
133+
# Do some sanity checking
134+
if [ ${#prAuthor} -eq 0 ]; then
135+
echo "ERROR: We couldn't grab the PR author. Something went wrong querying the GitHub API."
136+
clean_up_and_exit 1
137+
fi
138+
139+
if [ ${#prTitle} -eq 0 ]; then
140+
echo "ERROR: We couldn't grab the PR title. Something went wrong querying the GitHub API."
141+
clean_up_and_exit 1
142+
fi
143+
144+
if [ ${#prOriginBranch} -eq 0 ]; then
145+
echo "ERROR: We couldn't grab the PR branch name. Something went wrong querying the GitHub API."
146+
clean_up_and_exit 1
147+
fi
148+
149+
currentBranch=$(git branch | grep "^*" | sed -e "s/^[*] //")
150+
if [ "${prDestinationBranch}" != "${currentBranch}" ] && [ ${force} -lt 1 ]; then
151+
echo "ERROR: This PR is made against branch '${prDestinationBranch}' while your current checked out branch is '${currentBranch}'."
152+
echo "ERROR: Please make sure you're in the right branch and run this scipt again."
153+
clean_up_and_exit 1
154+
elif [ "${prDestinationBranch}" != "${currentBranch}" ] && [ ${force} -eq 1 ]; then
155+
echo "WARNING: You used --force to merge to '${currentBranch}' while this PR is for branch '${prDestinationBranch}'."
156+
fi
157+
158+
if [ "${prState}" != "open" ] && [ ${force} -lt 1 ]; then
159+
echo "ERROR: We couldn't merge the PR because the state is not 'open' but '${prState}'."
160+
echo "ERROR: In general it's a bad idea to merge closed PRs!"
161+
echo "ERROR: Run this script again with --force if you know what you're doing"
162+
echo "ERROR: (continuing work on an abandoned PR in which case you'd merge to a branch in your fork"
163+
echo "ERROR: and send that as a new PR). Ask for help on @dev if unsure."
164+
clean_up_and_exit 1
165+
elif [ "${prState}" != "open" ] &&[ ${force} -eq 1 ]; then
166+
echo "WARNING: You used --force to merge a PR with state '${prState}'."
167+
fi
168+
169+
if [ "${prMergeableState}" != "clean" ] && [ ${force} -lt 1 ]; then
170+
echo "ERROR: We couldn't merge the PR because it cannot be merged 'clean' (GitHub reports '${prMergeableState}')."
171+
echo "ERROR: This can be caused by a Travis build in progress, a failed Travis build or an unclean merge (conflicts)"
172+
echo "ERROR: Run this script again with --force if you know what you're doing. Ask for help on @dev if unsure."
173+
clean_up_and_exit 1
174+
elif [ "${prMergeableState}" != "clean" ] && [ ${force} -eq 1 ]; then
175+
echo "WARNING: You used --force to merge a PR with non-clean merge state '${prMergeableState}'."
176+
fi
177+
178+
github_remote=$(git remote -v | grep "apache/cloudstack.git" | head -n 1 | cut -f1)
179+
if [ ${#github_remote} -eq 0 ]; then
180+
echo "ERROR: We couldn't find a git remote pointing to 'apache/cloudstack.git' to merge the PR from."
181+
echo "INFO: Current remotes:"
182+
git remote -v
183+
clean_up_and_exit 1
184+
fi
185+
186+
echo "INFO: Using remote repository '${github_remote}' to fetch PR (should point to github.com/apache/cloudstack.git)"
187+
echo "INFO: PR #${prId} against branch '${prDestinationBranch}' from '${prAuthor}': '${prTitle}'"
188+
echo "INFO: has state '${prState}' and mergable state '${prMergeableState}', about to be merged in branch '${currentBranch}'."
189+
190+
# Construct commit merge message
191+
echo "Merge pull request #${prId} from ${prOriginBranch}" > ${tmpMessageFile}
192+
echo "" >> ${tmpMessageFile}
193+
echo "${prTitle}${prBody}" >> ${tmpMessageFile}
194+
195+
# Are you sure?
196+
echo "ATTENTION: Merging pull request #${prId} from ${prOriginBranch} into '${currentBranch}' branch in 5 seconds. CTRL+c to abort.."
197+
sec=5
198+
while [ $sec -ge 0 ]; do
199+
echo -n "${sec} "
200+
sec=$((sec-1))
201+
sleep 1
202+
done
203+
echo "INFO: Executing the merge now.. Git output below:"
204+
echo "INFO: ***********************************************************************************"
205+
206+
# Do the actual merge
207+
git fetch ${github_remote} pull/${prId}/head:pr/${prId}
208+
git merge --no-ff --log -m "$(cat .git-tmp-message.txt)" pr/${prId}
209+
if [ $? -eq 0 ]; then
210+
git commit --amend -s --allow-empty-message -m ''
211+
else
212+
echo "ERROR: Merge failed, aborting."
213+
git merge --abort
214+
fi
215+
216+
# What's next
217+
echo "INFO: ***********************************************************************************"
218+
echo "INFO: Merged successfully! Please double check using 'git log -p' and 'git push' when you're sure."
219+
echo "INFO: About commits: there should be ${prCommits} from the PR plus 1 merge commit."
220+
echo
221+
222+
clean_up_and_exit 0

0 commit comments

Comments
 (0)