Repository navigation
Expand file tree
/
Copy pathformat.sh
More file actions
executable file
·171 lines (151 loc) · 6 KB
/
Copy pathformat.sh
File metadata and controls
executable file
·171 lines (151 loc) · 6 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
#!/usr/bin/env bash
# Code formatter - runs targeted formatters based on what changed from trunk.
# Usage: format.sh [--all] [--pre-commit] [--pre-push] [--lint]
# (default) Check all changes relative to trunk including uncommitted work
# --all Format everything, skip change detection (previous behavior)
# --pre-commit Only check staged changes
# --pre-push Only check committed changes relative to trunk
# --lint Also run linters before formatting
set -eufo pipefail
run_lint=false
format_all=false
mode="default"
for arg in "$@"; do
case "$arg" in
--lint) run_lint=true ;;
--all) format_all=true ;;
--pre-commit|--pre-push)
[[ "$mode" == "default" ]] || { echo "Cannot use both --pre-commit and --pre-push" >&2; exit 1; }
mode="${arg#--}"
;;
*)
echo "Unknown option: $arg" >&2
echo "Usage: $0 [--all] [--pre-commit] [--pre-push] [--lint]" >&2
exit 1
;;
esac
done
section() {
echo "- $*" >&2
}
# Find what's changed compared to trunk (skip if --all)
# When on trunk, compare against origin/trunk instead.
current_branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")"
if [[ "$current_branch" == "trunk" ]]; then
trunk_ref="$(git rev-parse --verify origin/trunk 2>/dev/null || echo "")"
else
trunk_ref="$(git rev-parse --verify trunk 2>/dev/null || echo "")"
fi
if [[ "$format_all" == "false" && -n "$trunk_ref" ]]; then
base="$(git merge-base HEAD "$trunk_ref" 2>/dev/null || echo "")"
if [[ -n "$base" ]]; then
case "$mode" in
pre-commit)
changed="$(git diff --name-only --cached)"
;;
pre-push)
changed="$(git diff --name-only "$base" HEAD)"
;;
default)
committed="$(git diff --name-only "$base" HEAD)"
staged="$(git diff --name-only --cached)"
unstaged="$(git diff --name-only)"
untracked="$(git ls-files --others --exclude-standard)"
changed="$(printf '%s\n%s\n%s\n%s' "$committed" "$staged" "$unstaged" "$untracked" | sort -u)"
;;
esac
else
format_all=true
fi
elif [[ "$format_all" == "false" ]]; then
# No trunk ref found, format everything
format_all=true
fi
# Helper to check if a pattern matches changed files
changed_matches() {
[[ "$format_all" == "true" ]] || echo "$changed" | grep -qE "$1"
}
WORKSPACE_ROOT="$(bazel info workspace)"
# Capture baseline to detect formatter-introduced changes (allows pre-existing uncommitted work)
baseline="$(git status --porcelain)"
# The formatters run on the working tree, so a pushed file that also has uncommitted changes
# would hide its committed formatting behind the baseline above. Refuse rather than guess.
if [[ "$mode" == "pre-push" && "$format_all" == "false" && -n "$changed" ]]; then
dirty="$(printf '%s\n' "$changed" | tr '\n' '\0' | xargs -0 git status --porcelain --untracked-files=no --)"
if [[ -n "$dirty" ]]; then
echo "Cannot verify the formatting of the commits being pushed: these files also have uncommitted changes:" >&2
echo "$dirty" >&2
echo "Commit or stash them, then push again." >&2
exit 1
fi
fi
# Always run buildifier and copyright
section "Buildifier"
echo " buildifier" >&2
bazel run //:buildifier
section "Copyright"
echo " update_copyright" >&2
bazel run //scripts:update_copyright
# Run language formatters only if those files changed
if changed_matches '^java/'; then
section "Java"
echo " google-java-format" >&2
GOOGLE_JAVA_FORMAT="$(bazel run --run_under=echo //scripts:google-java-format)"
find "${WORKSPACE_ROOT}/java" -type f -name '*.java' -exec "$GOOGLE_JAVA_FORMAT" --replace {} +
fi
if changed_matches '^javascript/selenium-webdriver/'; then
section "JavaScript"
echo " prettier" >&2
NODE_WEBDRIVER="${WORKSPACE_ROOT}/javascript/selenium-webdriver"
bazel run //javascript:prettier -- "${NODE_WEBDRIVER}" --write "${NODE_WEBDRIVER}/.prettierrc" --log-level=warn
fi
if changed_matches '^rb/|^rake_tasks/|^Rakefile'; then
section "Ruby"
echo " rubocop -a" >&2
if [[ "$run_lint" == "true" ]]; then
bazel run //rb:rubocop -- -a
echo " steep check" >&2
bazel run //rb:steep
else
bazel run //rb:rubocop -- -a --fail-level F
fi
fi
if changed_matches '^rust/'; then
section "Rust"
echo " rustfmt" >&2
bazel run @rules_rust//:rustfmt
fi
if changed_matches '\.py$'; then
section "Python"
RUFF="$(bazel run --run_under=echo @multitool//tools/ruff)"
RUFF_COMMON=(--config=py/pyproject.toml --exclude '**/node_modules/**' --exclude '**/.bundle/**' --exclude '**/bidi/**' --exclude '**/devtools/**' py scripts common dotnet java javascript rb)
echo " ruff check" >&2
# Apply auto-fixable lint issues; don't fail on unfixable violations unless lint defined
"$RUFF" check --fix --show-fixes "${RUFF_COMMON[@]}" || [[ "$run_lint" != "true" ]]
echo " ruff format" >&2
"$RUFF" format "${RUFF_COMMON[@]}"
fi
if changed_matches '^dotnet/'; then
section ".NET"
echo " dotnet format" >&2
bazel run //dotnet:format -- style --severity warn
bazel run //dotnet:format -- whitespace
fi
# Run shellcheck and actionlint when --lint is passed
if [[ "$run_lint" == "true" ]]; then
section "Shell/Actions"
echo " actionlint (with shellcheck)" >&2
SHELLCHECK="$(bazel run --run_under=echo @multitool//tools/shellcheck)"
bazel run @multitool//tools/actionlint:cwd -- -shellcheck "$SHELLCHECK"
fi
# Check if formatting introduced new changes (comparing to baseline)
if [[ "$(git status --porcelain)" != "$baseline" ]]; then
echo "" >&2
echo "Formatters modified files:" >&2
git diff --name-only >&2
if [[ "$mode" == "pre-push" ]]; then
echo "Commit these changes (e.g. git commit --amend --no-edit), then push again." >&2
fi
exit 1
fi
echo "Format check passed." >&2