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
11 # * http://www.apache.org/licenses/LICENSE-2.0
13 # * Unless required by applicable law or agreed to in writing, software
14 # * distributed under the License is distributed on an "AS IS" BASIS,
15 # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 # * See the License for the specific language governing permissions and
17 # * limitations under the License.
20 # Make a patch for the current branch based on its tracking branch
25 while getopts "ahtd:b:" opt
; do
27 a
) addendum
='-addendum'
33 tracking_branch
=$OPTARG
36 patch_version
=".$(date -u +%Y%m%d-%H%M%S)"
39 echo -e "Usage: $0 [-h] [-a] [-t] [-d] <directory> \n\
40 Must be run from within the git branch to make the patch against.\n\
41 -h - display these instructions.\n\
42 -a - Add an 'addendum' prefix to the patch name.\n\
43 -t - Use the current timestamp as the version indicator.\n\
44 -b - Specify the base branch to diff from. (defaults to the tracking branch or origin master)\n\
45 -d - specify a patch directory (defaults to ~/patches/)"
51 # Find what branch we are on
52 branch
=$
(git branch |
grep '^\*' | cut
-d' ' -f2- )
53 if [ ! "${branch}" ]; then
54 echo "Can't determine the git branch. Exiting." >&2
58 # Exit if git status is dirty
59 git_dirty
=$
(git
diff --shortstat 2> /dev
/null |
wc -l)
60 echo "git_dirty is ${git_dirty}"
61 if [ "${git_dirty}" -ne 0 ]; then
62 echo "Git status is dirty. Commit locally first.">&2
66 # Determine the tracking branch if needed.
67 # If it was passed in from the command line
68 # with -b then use dthat no matter what.
69 if [ ! "${tracking_branch}" ]; then
70 git log
-n 1 "origin/${branch}" > /dev
/null
2>&1
72 if [ "${status}" -eq 128 ]; then
73 # Status 128 means there is no remote branch
74 tracking_branch
='origin/master'
75 elif [ "${status}" -eq 0 ]; then
76 # Status 0 means there is a remote branch
77 tracking_branch
="origin/${branch}"
79 echo "Unknown error: $?" >&2
85 # Deal with invalid or missing ${patch_dir}
86 if [ ! "${patch_dir}" ]; then
87 echo -e "Patch directory not specified. Falling back to ~/patches/."
91 if [ ! -d "${patch_dir}" ]; then
92 echo "${patch_dir} does not exist. Creating it."
96 # If this is against a tracking branch other than master
97 # include it in the patch name
99 if [[ "${tracking_branch}" != "origin/master" \
100 && "${tracking_branch}" != "master" ]]; then
101 tracking_suffix
=".${tracking_branch#origin/}"
104 # Determine what to call the patch
105 if [[ "${patch_version}" == "" ]]; then
106 # If we do NOT have the timestamp we must find the version to use
108 # Check to see if any patch exists that includes the branch name
109 status
=$
(find "${patch_dir}" -maxdepth 1 -type f -name "${branch}${tracking_suffix}.v[0-9][0-9].patch" 2>/dev
/null|
grep -c -v addendum
)
110 if [[ "${status}" -eq 0 ]]; then
111 # This is the first patch we are making for this release
113 elif [[ "${status}" -ge 1 ]]; then
114 # At least one patch already exists -- find the last one
116 # Check to see the maximum version of patch that exists
117 versionfiles
=$
(find "${patch_dir}" -maxdepth 1 -type f -name "${branch}${tracking_suffix}.v$(printf "%02d
" "$i").patch" 2> /dev
/null |
wc -l)
118 if [ 0 -lt "${versionfiles}" ]; then
124 if [ -n "${addendum}" ]; then
125 # Don't increment the patch # if it is an addendum
126 echo "Creating an addendum"
127 if [ "${version}" -ge 1 ]; then
128 # We are making an addendum to a different version of the patch
129 version
=$
((version-1
))
132 patch_version
=".v$(printf "%02d
" "${version}")"
136 patch_name
="${branch}${tracking_suffix}${patch_version}${addendum}.patch"
138 # Do we need to make a diff?
139 git
diff --quiet "${tracking_branch}"
141 if [ "${status}" -eq 0 ]; then
142 echo "There is no difference between ${branch} and ${tracking_branch}."
143 echo "No patch created."
147 # Check whether we need to squash or not
148 local_commits
=$
(git log
"${tracking_branch}..${branch}" |
grep -c 'Author:')
149 if [ "$local_commits" -gt 1 ]; then
150 read -p "$local_commits commits exist only in your local branch. Interactive rebase?" yn
153 git rebase
-i "${tracking_branch}"
156 echo "Creating ${patch_dir}/${patch_name} using git diff."
157 git
diff "${tracking_branch}" > "${patch_dir}/${patch_name}"
163 echo "Creating patch ${patch_dir}/${patch_name} using git format-patch"
164 git format-patch
--no-prefix --stdout "${tracking_branch}" > "${patch_dir}/${patch_name}"