-
Notifications
You must be signed in to change notification settings - Fork 1.5k
/
check.sh
executable file
·300 lines (243 loc) · 7.86 KB
/
check.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
#!/bin/bash
# Copyright 2019 Google
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Checks that the current state of the tree is sane and optionally auto-fixes
# errors automatically. Meant for interactive use.
function usage() {
cat <<EOF
USAGE: scripts/check.sh [--allow-dirty] [--commit] [<revision>]
Runs auto-formatting scripts, source-tree checks, and linters on any files that
have changed since origin/main.
By default, any changes are left as uncommitted changes in the working tree. You
can review them with git diff. Pass --commit to automatically commit any changes.
Pass an alternate revision to use as the basis for checking changes.
OPTIONS:
--allow-dirty
By default, check.sh requires a clean working tree to keep any generated
changes separate from logical changes.
--commit
Commit any auto-generated changes with a message indicating which tool made
the changes.
--amend
Commit any auto-generated changes by amending the HEAD commit.
--fixup
Commit any auto-generated changes with a fixup! message for the HEAD
commit. The next rebase will squash these fixup commits.
--test-only
Run all checks without making any changes to local files.
<revision>
Specifies a starting revision other than the default of origin/main.
EXAMPLES:
check.sh
Runs automated checks and formatters on all changed files since
origin/main. Check for changes with git diff.
check.sh --commit
Runs automated checks and formatters on all changed files since
origin/main and commits the results.
check.sh --amend HEAD
Runs automated checks and formatters on all changed files since the last
commit and amends the last commit with the difference.
check.sh --allow-dirty HEAD
Runs automated checks and formatters on all changed files since the last
commit and intermingles the changes with any pending changes. Useful for
interactive use from an editor.
EOF
}
set -euo pipefail
unset CDPATH
# Change to the top-directory of the working tree
top_dir=$(git rev-parse --show-toplevel)
cd "${top_dir}"
ALLOW_DIRTY=false
COMMIT_METHOD="none"
CHECK_DIFF=true
START_REVISION="origin/main"
TEST_ONLY=false
VERBOSE=false
# Default to verbose operation if this isn't an interactive build.
if [[ ! -t 1 ]]; then
VERBOSE=true
fi
# When travis clones a repo for building, it uses a shallow clone. After the
# first commit on a non-main branch, TRAVIS_COMMIT_RANGE is not set, main
# is not available and we need to compute the START_REVISION from the common
# ancestor of $TRAVIS_COMMIT and origin/main.
if [[ -n "${TRAVIS_COMMIT_RANGE:-}" ]] ; then
CHECK_DIFF=true
START_REVISION="$TRAVIS_COMMIT_RANGE"
elif [[ -n "${TRAVIS_COMMIT:-}" ]] ; then
if ! git rev-parse origin/main >& /dev/null; then
git remote set-branches --add origin main
git fetch origin
fi
CHECK_DIFF=true
START_REVISION=$(git merge-base origin/main "${TRAVIS_COMMIT}")
fi
while [[ $# -gt 0 ]]; do
case "$1" in
--)
# Do nothing: explicitly allow this, but ignore it
;;
-h | --help)
usage
exit 1
;;
--allow-dirty)
ALLOW_DIRTY=true
;;
--amend)
COMMIT_METHOD=amend
;;
--fixup)
COMMIT_METHOD=fixup
;;
--commit)
COMMIT_METHOD=message
;;
--verbose)
VERBOSE=true
;;
--test-only)
# In test-only mode, no changes are made, so there's no reason to
# require a clean source tree.
ALLOW_DIRTY=true
TEST_ONLY=true
;;
*)
START_REVISION="$1"
shift
break
;;
esac
shift
done
if [[ "${TEST_ONLY}" == true && "${COMMIT_METHOD}" != "none" ]]; then
echo "--test-only cannot be combined with --amend, --fixup, or --commit"
exit 1
fi
if [[ "${ALLOW_DIRTY}" == true && "${COMMIT_METHOD}" == "message" ]]; then
echo "--allow-dirty and --commit are mutually exclusive"
exit 1
fi
if ! git diff-index --quiet HEAD --; then
if [[ "${ALLOW_DIRTY}" != true ]]; then
echo "You have local changes that could be overwritten by this script."
echo "Please commit your changes first or pass --allow-dirty."
exit 2
fi
fi
# Show Travis-related environment variables, to help with debugging failures.
if [[ "${VERBOSE}" == true ]]; then
env | egrep '^TRAVIS_(BRANCH|COMMIT|PULL|REPO)' | sort || true
fi
if [[ "${START_REVISION}" == *..* ]]; then
RANGE_START="${START_REVISION/..*/}"
RANGE_END="${START_REVISION/*../}"
# Figure out if we have access to main. If not add it to the repo.
if ! git rev-parse origin/main >& /dev/null; then
git remote set-branches --add origin main
git fetch origin
fi
# Try to come up with a more accurate representation of the merge, so that
# checks will operate on just the differences the PR would merge into main.
# The start of the revision range that Travis supplies can sometimes be a
# seemingly random value.
NEW_RANGE_START=$(git merge-base origin/main "${RANGE_END}" || echo "")
if [[ -n "$NEW_RANGE_START" ]]; then
START_REVISION="${NEW_RANGE_START}..${RANGE_END}"
START_SHA="${START_REVISION}"
else
# In the shallow clone that Travis has created there's no merge base
# between the PR and main. In this case just fall back on checking
# everything.
echo "Unable to detect base commit for change detection."
echo "Falling back on just checking everything."
CHECK_DIFF=false
START_REVISION="origin/main"
START_SHA="origin/main"
fi
else
START_SHA=$(git rev-parse "${START_REVISION}")
fi
if [[ "${VERBOSE}" == true ]]; then
echo "START_REVISION=$START_REVISION"
echo "START_SHA=$START_SHA"
fi
# If committing --fixup, avoid messages with fixup! fixup! that might come from
# multiple fixup commits.
HEAD_SHA=$(git rev-parse HEAD)
function maybe_commit() {
local message="$1"
if [[ "${COMMIT_METHOD}" == "none" ]]; then
return
fi
echo "${message}"
case "${COMMIT_METHOD}" in
amend)
git commit -a --amend -C "${HEAD_SHA}"
;;
fixup)
git commit -a --fixup="${HEAD_SHA}"
;;
message)
git commit -a -m "${message}"
;;
*)
echo "Unknown commit method ${COMMIT_METHOD}" 1>&2
exit 2
;;
esac
}
style_cmd=("${top_dir}/scripts/style.sh")
if [[ "${TEST_ONLY}" == true ]]; then
style_cmd+=(test-only)
fi
if [[ "$CHECK_DIFF" == true ]]; then
style_cmd+=("${START_SHA}")
fi
# Restyle and commit any changes
"${style_cmd[@]}"
if ! git diff --quiet; then
maybe_commit "style.sh generated changes"
fi
# If there are changes to the Firestore project, ensure they're ordered
# correctly to minimize conflicts.
if [ -z "${GITHUB_WORKFLOW-}" ]; then
if [[ "$CHECK_DIFF" == "false" ]] || \
! git diff --quiet "${START_SHA}" -- Firestore; then
sync_project_cmd=("${top_dir}/scripts/sync_project.rb")
if [[ "${TEST_ONLY}" == true ]]; then
sync_project_cmd+=(--test-only)
fi
"${sync_project_cmd[@]}"
if ! git diff --quiet; then
maybe_commit "sync_project.rb generated changes"
fi
fi
fi
set -x
# Print the versions of tools being used.
python --version
# Check lint errors.
"${top_dir}/scripts/check_whitespace.sh"
"${top_dir}/scripts/check_filename_spaces.sh"
"${top_dir}/scripts/check_copyright.sh"
"${top_dir}/scripts/check_test_inclusion.py"
"${top_dir}/scripts/check_imports.swift"
# Google C++ style
lint_cmd=("${top_dir}/scripts/check_lint.py")
if [[ "$CHECK_DIFF" == true ]]; then
lint_cmd+=("${START_SHA}")
fi
"${lint_cmd[@]}"