-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate-patch.sh
executable file
·216 lines (180 loc) · 7.04 KB
/
create-patch.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/env bash
# Git patch creation tool
# v1.0
# (c) Copyright 2023 Adobe Commerce.
# 1. Check required system tools
_check_installed_tools() {
local tools=("git" "awk" "grep" "head" "pwd" "cat" "dirname" "basename")
for tool in "${tools[@]}"; do
if ! command -v "$tool" >/dev/null 2>&1; then
printf "ERROR: '%s' command is not found. Please install it to proceed.\n" "$tool"
exit 1
fi
done
}
_check_installed_tools
# Determine bin path for system tools
git_bin=$(command -v git)
awk_bin=$(command -v awk)
grep_bin=$(command -v grep)
head_bin=$(command -v head)
pwd_bin=$(command -v pwd)
cat_bin=$(command -v cat)
dirname_bin=$(command -v dirname)
basename_bin=$(command -v basename)
base_name=$($basename_bin "$0")
# 2. Load env variables
tool_dir=$($dirname_bin "$0")
env_file_path="$tool_dir"/.env
if [[ -f "$env_file_path" ]]; then
source "$env_file_path"
echo "Loaded .env from $env_file_path."
else
echo -e "$env_file_path was not found. Copy .env.example to .env and specify the path to the converter tool."
fi
# 3. Help menu
if [[ "$1" == "-?" || "$1" == "-h" || "$1" == "--help" ]]; then
"$cat_bin" <<EOFH
Usage: sh $base_name [--help] [-b <branch>] [-r <release version>] [-v <version>] [-c <commit>:<commit>]
Generate a patch by collecting changes from the latest tag to HEAD (by default).
The tool should be run from the directory containing the repository.
-b <branch> Specify the branch. Example: ABCD-1234.
-r <release version> [Optional] Specify the release version to use for the patch file name.
If not specified, the tool will use the latest tag to identify the release version.
-v <patch version> Specify the patch version. Examples: v2, v3. Omit for v1.
-c <commit>:<commit> [Optional] Generate a patch by using the changes between two arbitrary <commit>.
The patch will be generated by the "git diff" tool.
It will be treated the same way as the "git diff" command, for example,
if <commit> is omitted on one side, it will have the same effect as using HEAD instead.
If this option is omitted, the patch will be generated using the changes from the latest tag to HEAD.
--help Show this help message.
EOFH
exit 0
fi
# 4. Get options
branch=""
release_version=""
patch_version=""
collect_revisions_range=""
while getopts b:v:r:c: opt; do
case $opt in
b)
branch="$OPTARG"
;;
r)
release_version="$OPTARG"
;;
v)
patch_version="$OPTARG"
;;
c)
collect_revisions_range="$OPTARG"
;;
*)
printf "ERROR: Invalid option: -%s\n" "$OPTARG" >&2
exit 1
;;
esac
done
# 5. Git preparations
_check_git_revision() {
local commit="$1"
if ! git rev-parse --quiet --verify "$commit" >/dev/null 2>&1; then
printf "ERROR: Invalid revision '%s'.\n" "$commit"
exit 1
fi
}
# Determine if the current directory is under git control
is_under_git_control=777
"$git_bin" rev-parse -q >/dev/null 2>&1
is_under_git_control=$?
if [[ ! "$is_under_git_control" -eq 0 ]]; then
printf "ERROR: The patch can't be created because the current directory is not a Git repository.\n"
exit 1
fi
# Checkout branch
if [ -n "$branch" ]; then
$git_bin fetch
# Check for uncommitted changes
if ! $git_bin diff --quiet; then
printf "ERROR: There are uncommitted changes. Please commit or stash them before switching branches.\n"
exit 1
fi
# Attempt to checkout the branch
if ! $git_bin checkout "$branch" >/dev/null 2>&1; then
printf "ERROR: The branch '%s' does not exist.\n" "$branch"
exit 1
fi
$git_bin merge
fi
# Get the latest tag in the current branch
current_tag=$($git_bin describe --abbrev=0 --tags)
# If revisions range was omitted, then set the range from the current tag to HEAD
if [ -z "$collect_revisions_range" ]; then
collect_revisions_range="$current_tag..HEAD"
start_commit=$($git_bin rev-list "$current_tag" | $head_bin -n 1)
else
start_commit=$($awk_bin -F ":" '{print $1}' <<<"$collect_revisions_range")
end_commit=$($awk_bin -F ":" '{print $2}' <<<"$collect_revisions_range")
# Check if specified "start" and "end" commits exist
_check_git_revision "$start_commit"
# If "end" commit was specified (not empty), set the revisions range in the applicable format for "git diff" command
if [ ! -z "$end_commit" ]; then
_check_git_revision "$end_commit"
collect_revisions_range="$start_commit..$end_commit"
fi
fi
echo "======== Commits in the patch: ========"
"$git_bin" log --oneline --format='%C(auto)%h %Cgreen%ad%Creset %s%C(auto)%d' --color --decorate --date=iso -50 "$collect_revisions_range"
echo "======== Based on: ===================="
"$git_bin" log --oneline --format='%C(auto)%h %Cgreen%ad%Creset %s%C(auto)%d' --color --decorate --date=iso -1 "$("$git_bin" rev-parse "$start_commit")"
echo "======================================="
# 6. Patch tool file name
current_branch=$($git_bin rev-parse --abbrev-ref HEAD)
ticket_number=$(echo "$current_branch" | $grep_bin -oE '^[A-Z]*-[0-9]*')
debug_suffix=$(echo "$current_branch" | $grep_bin -i 'debug')
custom_suffix=$(echo "$current_branch" | $grep_bin -i 'custom')
if [ -n "$debug_suffix" ]; then
patch_id="${ticket_number}_DEBUG"
else
patch_id="$ticket_number"
fi
if [ -n "$custom_suffix" ]; then
patch_id="${patch_id}_CUSTOM"
fi
if [ -z "$release_version" ]; then
release_version=$($awk_bin '{gsub("v",""); print}' <<<"$current_tag")
fi
if [[ "$patch_version" == "v1" ]] || [[ -z "$patch_version" ]]; then
patch_version_suffix=
else
patch_version_suffix="_$patch_version"
fi
patch_file_name_git="${patch_id}_${release_version}${patch_version_suffix}.git.patch"
patch_file_name_composer="${patch_id}_${release_version}${patch_version_suffix}.patch"
# 7. Create the patch file
if ! $git_bin diff -a -p --no-renames "$collect_revisions_range" >"$patch_file_name_git"; then
echo "Error: Failed to create a git patch file."
exit 1
fi
# Create a composer version of the file
current_dir=$($pwd_bin)
patch_file_path_git="$current_dir/$patch_file_name_git"
patch_file_path_composer="$current_dir/$patch_file_name_composer"
if [ -n "$PATCH_CONVERTER_TOOL_BIN" ]; then
$PATCH_CONVERTER_TOOL_BIN "$patch_file_path_git" >"$patch_file_path_composer"
fi
# 8. Report results
if [ -f "$patch_file_path_git" ] && [ "$(wc -c <"$patch_file_path_git")" -gt 1 ]; then
echo "Git patch created successfully."
echo "The location of the git patch is: $patch_file_path_git"
else
echo "Something went wrong while generating the patch."
fi
if [ -f "$patch_file_path_composer" ] && [ "$(wc -c <"$patch_file_path_composer")" -gt 1 ]; then
echo -e "\e[32mComposer patch created successfully.\e[0m"
echo "The location of the composer patch is: $patch_file_path_composer"
else
echo "There was an error while generating the composer patch. Please recheck the converter tool location."
fi
exit 0