-
Notifications
You must be signed in to change notification settings - Fork 0
/
git-diff-story
executable file
·151 lines (133 loc) · 3.13 KB
/
git-diff-story
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
#!/bin/bash
source config
# messages
NO_STORY_ID="No story id supplied"
NO_STORY_COMMITS="There are not any commits for this story"
NO_GIT_REPOSITORY="Not a git repository"
NO_FILTERED_FILES="None files match with the filters"
if ! git rev-parse --is-inside-work-tree -q > /dev/null 2>&1; then
echo $NO_GIT_REPOSITORY
exit 1
fi
# default options
NAME_ONLY=false
STAT=false
PATTERN=.*
ONE_BY_ONE=true
CUSTOM_START=
TEST_OPTION=
SKIP_TESTS=false
ONLY_TESTS=false
# sets options
for i in "$@"; do
case $i in
-n|--name-only)
NAME_ONLY=true
shift
;;
-s|--stat)
STAT=true
shift
;;
-a|--all)
ONE_BY_ONE=false
shift
;;
-t=*|--tests=*)
TEST_OPTION="${i#*=}"
shift
;;
-p=*|--pattern=*)
PATTERN="${i#*=}"
shift
;;
--start=*)
CUSTOM_START="${i#*=}"
shift
;;
*)
STORY_ID=$1
;;
esac
done
if [ -z $STORY_ID ]; then
echo $NO_STORY_ID
exit 1
fi
if $STAT || $NAME_ONLY; then
ONE_BY_ONE=false
fi
case $TEST_OPTION in
s|skip)
SKIP_TESTS=true
shift
;;
o|only)
ONLY_TESTS=true
shift
;;
esac
# finds start and last commit
if [ ! -z $CUSTOM_START ]; then
DATE_CUSTOM_START=$(git log --pretty=%at -n 1 $CUSTOM_START)
DATE_AFTER_START=$((DATE_CUSTOM_START+1))
SINCE_CMD="--since=\"$DATE_AFTER_START\""
fi
STORY_ID_PATTERN="$PREFIX_STORY_ID$STORY_ID$STORY_ID_END_PATTERN"
COMMITS_CMD="git log --pretty=%h --grep=$STORY_ID_PATTERN $SINCE_CMD"
COMMITS=$($COMMITS_CMD)
REVERSE_COMMITS=$($COMMITS_CMD --reverse)
read -r FIRST_COMMIT <<< "$REVERSE_COMMITS"
read -r LAST_COMMIT <<< "$COMMITS"
if [ -z $FIRST_COMMIT ]; then
echo $NO_STORY_COMMITS
exit 1
fi
ALL_COMMITS=$(git log --pretty=%h --reverse)
read -r INITIAL_REPO_COMMIT <<< "$ALL_COMMITS"
if [ $FIRST_COMMIT = $INITIAL_REPO_COMMIT ]; then
START_COMMIT=$FIRST_COMMIT
else
START_COMMIT=$FIRST_COMMIT~1
fi
# creates diff command
DIFF_BASIC_CMD="git diff $START_COMMIT $LAST_COMMIT"
DIFF_CMD=$DIFF_BASIC_CMD
if $STAT; then
DIFF_CMD="$DIFF_CMD --stat"
fi
if $NAME_ONLY; then
DIFF_CMD="$DIFF_CMD --name-only"
fi
# filters files
MODIFIED_FILES_SCRIPT="git files-story"
MODIFIED_FILES=$($MODIFIED_FILES_SCRIPT $STORY_ID)
FILTERED_FILES=()
while IFS='' read -ra FILES; do
for file in "${FILES[@]}"; do
if [[ $file =~ $PATTERN ]] && (! $SKIP_TESTS || ! [[ $file =~ $TEST_PATTERN ]]) && (! $ONLY_TESTS || [[ $file =~ $TEST_PATTERN ]]); then
DIFF_FILE="$DIFF_BASIC_CMD -- $file"
if [[ ! -z $($DIFF_FILE) ]]; then
FILTERED_FILES+=($file)
fi
fi
done
done <<< "$MODIFIED_FILES"
if [ -z $FILTERED_FILES ]; then
echo $NO_FILTERED_FILES
exit 1
fi
# execute command
if $ONE_BY_ONE; then
for file in "${FILTERED_FILES[@]}"; do
DIFF_CMD_BY_FILE="$DIFF_CMD -- $file"
$DIFF_CMD_BY_FILE
done
else
FILES_STRING=""
for file in "${FILTERED_FILES[@]}"; do
FILES_STRING+=" $file"
done
DIFF_CMD_ALL="$DIFF_CMD -- $FILES_STRING"
$DIFF_CMD_ALL
fi