-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit-clog
More file actions
executable file
·221 lines (186 loc) · 5.25 KB
/
git-clog
File metadata and controls
executable file
·221 lines (186 loc) · 5.25 KB
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
#!/bin/bash
set -e
print_usage() {
cat << EOM
Usage: $(basename $0) [options] [revision-range]
Outputs a summarized list of changes in the revision-range.
Optimized for retrieving Assembla-specific information from git logs
such as ticket or merge request URLs. Also formats squashed merge commits
so that the title of the merge request is used as the changelog.
Options
-o <format> The output format (default=changes).
-v Enables verbose output.
-h Displays this message.
Output formats
commits Hash identifiers for the commits.
changes Log of the changes.
tickets,ticket Referenced Assembla ticket numbers.
ticket_urls,urls URLs to the referenced tickets.
merge_requests,mr URLs to the merge requests.
Examples
Prints a list of changes since the last tag:
$(basename $0)
Prints a list of tickets impacted between bug/1234 and master:
$(basename $0) -o tickets bug/1234..master
Prints URLs of tickets impacted between two specific commits:
$(basename $0) -o urls 90bb49b..be98809
Environment variables
GIT_PREVIOUS_SUCCESSFUL_COMMIT
If revision-range is not specified, the range will default to changes since
this value (this is populated automatically by Jenkins). If empty,
the range will default to changes since the most recent tag.
ASSEMBLA_SPACE_URL
The base Assembla space URL. If empty, this will attempted to be
derived based on the git remote URL.
See also
Selecting a range of revisions
https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection
Authors
Daniel Pfeiffer, Float (https://gowithfloat.com)
EOM
}
abort() {
>&2 echo "$(tput setaf 1)$1$(tput sgr0)"
>&2 echo ""
print_usage 1>&2
exit 1
}
output="changes"
while getopts ":o:hv" opt; do
case ${opt} in
o)
output=$OPTARG
;;
v)
verbose=true
;;
h)
print_usage
exit 0
;;
\?)
abort "Invalid option: -$OPTARG"
;;
:)
abort "-$OPTARG requires an argument"
;;
esac
done
shift $((OPTIND -1))
info() {
if [ $verbose ]; then
>&2 echo "$(tput setaf 3)$1$(tput sgr0)"
fi
}
guess_space_url(){
info "Guessing at space URL based on git remote"
#
# The Assembla space URL can _probably_ be guessed from the git remote.
# The git remote will include the space name and could appear in one
# of the following formats:
#
# git@git.assembla.com:portflio/space-name.label.git
# git@git.assembla.com:space-name.label.git
#
remote=$(git remote -v | grep fetch | awk '{print $2}')
repo=${remote##*[:/]}
space=${repo%%.*}
if [ -z $space ]; then
info "Failed to determine Assembla space from remote: ${remote}"
exit 1
fi
space_url="https://app.assembla.com/spaces/${space}"
info "git repo: ${repo}"
info "Resolved Assembla space URL: ${space_url}"
echo "$space_url"
}
# The default range of commits will be changes since
# GIT_PREVIOUS_SUCCESSFUL_COMMIT or the most recent tag.
recent_tag=$(git describe --abbrev=0 --tags 2>/dev/null) || true
default_range_start=${GIT_PREVIOUS_SUCCESSFUL_COMMIT:-$recent_tag}
if [ -n "$default_range_start" ]; then
default_range=$default_range_start..HEAD
fi
range=${1:-$default_range}
space_url=${ASSEMBLA_SPACE_URL:-$(guess_space_url)}
get_commits(){
# List hashes in reverse order (oldest first) and skips over merge commits.
git log $range --pretty=format:'%H' --reverse --no-merges
}
# When assembla squashes a merge, the commit messages look like the following.
# To make the list of changes useful, the log message for squash merge commits
# should come from the first line of the body instead of the summary.
#
# Example:
#
# Merge branch 'bug/various' into 'master'
#
# Avoids handling “double navigation” (re #1708)
#
# done #1707, #1708
#
# +1: John Doe
#
# Merged-on: https://assembla.com/code/space-name/git/merge_requests/1234567
#
get_change(){
if is_merge_commit $1; then
info "[$1] Using first line of body"
git show --quiet $1 --pretty=format:'%b' | head -n 1
else
info "[$1] Using summary"
git show --quiet $1 --pretty=format:'%s%n'
fi
}
is_merge_commit(){
# Assembla includes the string "Merged-on" when it creates a merge commit.
# A merge commit is created when a merge request is squashed before merging.
if [[ $(git show --quiet $1) == *"Merged-on"* ]]; then
return 0
fi
return 1
}
get_mr_url(){
git show --quiet $1 | grep "Merged-on" | sed 's/.*Merged-on: \(.*\)/\1/'
}
get_tickets(){
for string in $(git show --quiet $1)
do
if [[ $string =~ \#[0-9]+ ]]; then
echo "${BASH_REMATCH[0]}"
fi
done
}
get_ticket_url(){
while read ticket
do
if [ -n "$space_url" ]; then
echo "${space_url}/tickets/${ticket/\#/}"
else
echo $ticket
fi
done
}
info "Outputting $range as $output..."
for commit in $(get_commits); do
case ${output} in
commits)
echo $commit
;;
changes)
get_change $commit
;;
ticket|tickets)
get_tickets $commit | sort -u
;;
urls|ticket_urls)
get_tickets $commit | get_ticket_url | sort -u
;;
mr|pr|merge_requests)
get_mr_url $commit
;;
*)
error "Invalid output format: $output"
;;
esac
done