-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgit.sh
executable file
·359 lines (314 loc) · 9.13 KB
/
git.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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#!/usr/bin/env bash
SCRIPT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source ${SCRIPT_PATH}/colors.sh
# ascii art :)
function __presentation
{
echo " _____ ______ __ __ __ __ ______ __ __ ______"
echo "/\ __-. /\ ___\ /\ \ / / /\ \/\ \ /\__ _\ /\ \ /\ \ /\ ___\\"
echo "\ \ \/\ \ \ \ __\ \ \ \'/ \ \ \_\ \ \/_/\ \/ \ \ \ \ \ \____ \ \___ \\"
echo " \ \____- \ \_____\ \ \__| \ \_____\ \ \_\ \ \_\ \ \_____\ \/\_____\\"
echo " \/____/ \/_____/ \/_/ \/_____/ \/_/ \/_/ \/_____/ \/_____/"
green "# ${1}"
}
# perform log commit command
function commit()
{
__presentation "commit"
__commitPerform
if [[ ! -d .git ]]; then
red "## This folder is not a working tree"
return
fi
# check if repo is empty
if [[ ! "$(git branch -vv)" ]];then
red "## No branches available"
_red "## Create the first commit? [y/n] $ "
read -n 1 READ_START
echo ""
if [[ ${READ_START} = "y" ]]; then
git commit -m "[init] Just init the repo" --allow-empty >/dev/null 2>&1
else
return
fi
fi
}
# commit command body instructions
function __commitPerform
{
ISSUE_TRACKER=""
BRANCH_AS_ISSUE_ID="0"
if [[ -f ${SCRIPT_PATH}/.env ]]; then
source ${SCRIPT_PATH}/.env
fi
if [[ -f .du ]]; then
source .du
fi
MODIFIED=$(git status --short)
if [[ ! ${MODIFIED} ]]; then
red "## No changes available"
return
fi
# get modified files
COMMIT_FILES_OPTIONS=($(git ls-files --others --exclude-standard --modified))
# check if repo is empty
COMMIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# start COMMIT_FILES_CHOSEN as empty array
COMMIT_FILES_CHOSEN=()
# start selected file with EMPTY
SELECTED_FILE="EMPTY"
# start index with 0
INDEX=0
# flag control to select all
SELECT_ALL=0
# while the user select a file
while [[ "${SELECTED_FILE}" ]]; do
# show menu (COMMIT_FILES_OPTIONS and COMMIT_FILES_CHOSEN are used as global)
__commitMenu
yellow "# Enter the file number in the list to toggle selection"
yellow "# [separate with ',' when more than 9 options]"
_yellow "# [type enter with empty to go ahead] $ "
# if there is more than 10 files will be necessary type enter
if (( ${#COMMIT_FILES_OPTIONS[@]} > 10 )); then
read SELECTED_FILE
# otherwise the value will be picked up automatically after typing
else
read -n 1 SELECTED_FILE
fi
echo ""
# stop selection if the value entered is empty
if [[ ! "${SELECTED_FILE}" ]]; then
break
fi
# stop selection if the value entered is 0
if [[ "${SELECTED_FILE}" = "0" ]]; then
SELECT_ALL=1
break
fi
# scroll through the selected files input to apply the option that came from the menu
while IFS=',' read -ra ITEM; do
for i in "${ITEM[@]}"; do
INDEX=${i}
# test if selected option is valid
((INDEX--))
if (( INDEX < 0 || INDEX >= ${#COMMIT_FILES_OPTIONS[@]} )); then
# show a message of invalid input
red " ~> Invalid option: ${SELECTED_FILE}"
continue
fi
# if the option is already selected...
if [[ "${COMMIT_FILES_CHOSEN[INDEX]}" ]]; then
# ...unselected the option
COMMIT_FILES_CHOSEN[INDEX]=""
continue
fi
# select the option
COMMIT_FILES_CHOSEN[INDEX]="x"
done
# apply the SELECTED_FILE to for
done <<< "${SELECTED_FILE}"
done
# if SELECT_ALL was selected...
if [[ "${SELECT_ALL}" = 1 ]]; then
# ...clear the selection
SELECT_ALL=0
# ...scroll through all file options...
for i in ${!COMMIT_FILES_OPTIONS[@]}; do
# ...and select each one
COMMIT_FILES_CHOSEN[i]="x"
done
fi
yellow "# Log"
# scroll through all file options
for i in ${!COMMIT_FILES_OPTIONS[@]}; do
# if is not selected ignore
if [[ ! "${COMMIT_FILES_CHOSEN[i]}" ]]; then
continue;
fi
# else perform git add command
MUTE=$(git add ${COMMIT_FILES_OPTIONS[i]})
done
# get the git changes to create a log with the changes in commit
COMMIT_CHANGES=$(git diff --cached --name-only)
# convert the changes in an array
ADDED=(${COMMIT_CHANGES})
# if there is no changes...
if [[ ! "$ADDED" ]]; then
# ...abort commit
red "## No changes available to perform a commit"
return
fi
# default log message
message=" ~> nothing of anything"
# scroll through the added files in git
for i in ${!ADDED[@]}; do
# show message with the name of file listed to be in commit
cyan " ~> git add ${ADDED[i]}"
# reset the default log message
message=""
done
# show the default log message
cyan "$message"
yellow "# Commit type (use the numbers for the options listed below)"
yellow "# [if the option you entered is not in the list, the 'feature' option will be used] "
_yellow "# 1:feature, 2:fix, 3:review, 4:doc, 5:test, 6:devops, 7:merge or 8:finish $ "
read -n 1 READ_COMMIT_TYPE
# get commit type
case ${READ_COMMIT_TYPE} in
2)
COMMIT_TYPE="fix"
;;
3)
COMMIT_TYPE="review"
;;
4)
COMMIT_TYPE="doc"
;;
5)
COMMIT_TYPE="test"
;;
6)
COMMIT_TYPE="devops"
;;
7)
COMMIT_TYPE="merge"
;;
8)
COMMIT_TYPE="finish"
;;
*)
COMMIT_TYPE="feature"
;;
esac
if [[ ${READ_COMMIT_TYPE} ]]; then
echo ""
fi
cyan " ~> selected type: ${COMMIT_TYPE}"
# initialize message of commit
COMMIT_MESSAGE=""
# repeat until get a message
until [[ "${COMMIT_MESSAGE}" ]]
do
_yellow "# Commit message $ "
read COMMIT_MESSAGE
# validate message
if [[ ! ${COMMIT_MESSAGE} ]]; then
red "## Message is required"
fi
done
# init commit reference with the branch name
COMMIT_REFERENCE=$(echo $(basename ${COMMIT_BRANCH}) | tr a-z A-Z)
# if the flag BRANCH_AS_ISSUE_ID is active ...
if [[ ${BRANCH_AS_ISSUE_ID} = "1" ]]; then
# ... use the branch name as reference
READ_COMMIT_RELATED=${COMMIT_REFERENCE}
# else ask user the issue ID
else
yellow "# Related issue"
yellow "# [enter the ID of issue]"
_yellow "# [if empty will use the branch name as reference in commit] $ "
# concat related with a text to be human readable
COMMIT_RELATED="> current branch: ${COMMIT_BRANCH}"
# read commit related info
read READ_COMMIT_RELATED
fi
# if commit related was entered...
if [[ ${READ_COMMIT_RELATED} ]]; then
# convert related to uppercase
READ_COMMIT_RELATED=$(echo ${READ_COMMIT_RELATED} | tr a-z A-Z)
# use related as commit reference
COMMIT_REFERENCE="#${READ_COMMIT_RELATED}"
COMMIT_RELATED_ISSUE_LINK="#${COMMIT_RELATED}"
## get issue tracker from .env
if [[ ${ISSUE_TRACKER} ]]; then
# concat related with a text to be human readable
COMMIT_RELATED_ISSUE_LINK="${ISSUE_TRACKER}/${READ_COMMIT_RELATED}"
fi
COMMIT_RELATED="> current branch: ${COMMIT_BRANCH}, issue link: ${COMMIT_RELATED_ISSUE_LINK}"
fi
COMMIT_MESSAGE="[${COMMIT_REFERENCE}/${COMMIT_TYPE}] ${COMMIT_MESSAGE}"
green " ~> git commit -m '${COMMIT_MESSAGE}'"
git commit -q -F- <<EOF
${COMMIT_MESSAGE}
${COMMIT_RELATED}
${COMMIT_CHANGES}
EOF
# git ls-files --others --exclude-standard --modified
if [[ "$(git status --short)" ]]; then
_yellow "# Do you want to commit again? [y/n] $ "
read -n 1 READ_DO_AGAIN
echo ""
if [[ ${READ_DO_AGAIN} = "y" ]]; then
__commitPerform
fi
fi
}
# show commit menu file options
function __commitMenu
{
yellow "# Select the files to be added in the commit"
printf " 0 [ ] All\n"
for i in ${!COMMIT_FILES_OPTIONS[@]}; do
printf "%3d [%s] %s\n" $((i+1)) "${COMMIT_FILES_CHOSEN[i]:- }" "${COMMIT_FILES_OPTIONS[i]}"
done
fixes=($(git diff --cached --name-only))
for i in ${!fixes[@]}; do
printf " [x] %s\n" "${fixes[i]}"
done
}
# perform status git command
function status
{
__presentation "status"
if [[ ! -d .git ]]; then
red "## This folder is not a working tree"
return
fi
STATUS=$(git status --short)
if [[ ! ${STATUS} ]]; then
yellow "## No changes"
return
fi
git status --short
}
# perform log git command
function log
{
__presentation "log"
if [[ ! -d .git ]]; then
red "## This folder is not a working tree"
return
fi
if [[ ! "$(git branch -vv)" ]];then
red "## There are no branches or commits to generate log"
return
fi
git log \
--pretty=format:"%C(yellow)%h %cd%Creset | %C(green)%ae%Creset | %<(90,trunc)%s " \
--date=short \
--graph \
--grep="${1}"
# --invert-grep \
}
# push the changes to remote repo
function push
{
DU_ORIGIN=${1}
if [[ ! ${DU_ORIGIN} ]]; then
DU_ORIGIN="origin"
fi
DU_BRANCH=$(echo $(basename ${COMMIT_BRANCH}) | tr a-z A-Z)
git config credential.helper store
git push ${DU_ORIGIN} ${DU_BRANCH}
}
# push the changes to remote repo
function pull
{
DU_ORIGIN=${1}
if [[ ! ${DU_ORIGIN} ]]; then
DU_ORIGIN="origin"
fi
DU_BRANCH=$(echo $(basename ${COMMIT_BRANCH}) | tr a-z A-Z)
git config credential.helper store
git pull ${DU_ORIGIN} ${DU_BRANCH}
}