aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/style.sh
blob: f82af7798af607d668e32e32b962b3ca61a28cb7 (plain)
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
#!/bin/bash

# Copyright 2017 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.

# Usage:
# ./scripts/style.sh [branch-name | filenames]
#
# With no arguments, formats all eligible files in the repo
# Pass a branch name to format all eligible files changed since that branch
# Pass a specific file or directory name to format just files found there
#
# Commonly
# ./scripts/style.sh master

# Strip the clang-format version output down to the major version. Examples:
#   clang-format version 7.0.0 (tags/google/stable/2018-01-11)
#   clang-format version google3-trunk (trunk r333779)
version=$(clang-format --version)

# Remove leading "clang-format version"
version="${version/*version /}"
# Remove trailing parenthetical version details
version="${version/ (*)/}"
# Remove everything after the first dot (note this is a glob, not a regex)
version="${version/.*/}"

case "$version" in
  6 | 7)
    # Allow an older clang-format to accommodate Travis version skew.
    ;;
  google3-trunk)
    echo "Please use a publicly released clang-format; a recent LLVM release"
    echo "from http://releases.llvm.org/download.html will work."
    echo "Prepend to PATH when running style.sh."
    exit 1
    ;;
  *)
    echo "Please upgrade to clang-format version 7."
    echo "If it's installed via homebrew you can run: brew upgrade clang-format"
    exit 1
    ;;
esac

system=$(uname -s)
if [[ "$system" == "Darwin" ]]; then
  version=$(swiftformat --version)
  version="${version/*version /}"
  # Allow an older swiftformat because travis isn't running High Sierra yet
  # and the formula hasn't been updated in a while on Sierra :-/.
  if [[ "$version" != "0.32.0" && "$version" != "0.33"* ]]; then
    echo "Please upgrade to swiftformat 0.33.3"
    echo "If it's installed via homebrew you can run: brew upgrade swiftformat"
    exit 1
  fi
fi

# Joins the given arguments with the separator given as the first argument.
function join() {
  local IFS="$1"
  shift
  echo "$*"
}

clang_options=(-style=file)

# Rules to disable in swiftformat:
swift_disable=(
  # sortedImports is broken, sorting into the middle of the copyright notice.
  sortedImports

  # Too many of our swift files have simplistic examples. While technically
  # it's correct to remove the unused argument labels, it makes our examples
  # look wrong.
  unusedArguments
)

swift_options=(
  # Mimic Objective-C style.
  --indent 2

  --disable $(join , "${swift_disable[@]}")
)

if [[ $# -gt 0 && "$1" == "test-only" ]]; then
  test_only=true
  clang_options+=(-output-replacements-xml)
  swift_options+=(--dryrun)
  shift
else
  test_only=false
  clang_options+=(-i)
fi

files=$(
(
  if [[ $# -gt 0 ]]; then
    if git rev-parse "$1" -- >& /dev/null; then
      # Argument was a branch name show files changed since that branch
      git diff --name-only --relative --diff-filter=ACMR "$1"
    else
      # Otherwise assume the passed things are files or directories
      find "$@" -type f
    fi
  else
    # Do everything by default
    find . -type f
  fi
) | sed -E -n '
# find . includes a leading "./" that git does not include
s%^./%%

# Build outputs
\%/Pods/% d
\%^build/% d
\%^Debug/% d
\%^Release/% d

# Sources controlled outside this tree
\%/third_party/% d
\%/Firestore/Port/% d

# Generated source
\%/Firestore/core/src/firebase/firestore/util/config.h% d

# Sources pulled in by travis bundler
\%/vendor/bundle/% d

# Sources within the tree that are not subject to formatting
\%^(Example|Firebase)/(Auth|AuthSamples|Database|Messaging)/% d

# Checked-in generated code
\%\.pb(objc|rpc)\.% d
\%\.pb\.% d
\%\.nanopb\.% d

# Format C-ish sources only
\%\.(h|m|mm|cc|swift)$% p
'
)

needs_formatting=false
for f in $files; do
  if [[ "${f: -6}" == '.swift' ]]; then
    if [[ "$system" == 'Darwin' ]]; then
      swiftformat "${swift_options[@]}" "$f" 2> /dev/null | grep 'would have updated' > /dev/null
    else
      false
    fi
  else
    clang-format "${clang_options[@]}" "$f" | grep "<replacement " > /dev/null
  fi

  if [[ "$test_only" == true && $? -ne 1 ]]; then
    echo "$f needs formatting."
    needs_formatting=true
  fi
done

if [[ "$needs_formatting" == true ]]; then
  echo "Proposed commit is not style compliant."
  echo "Run scripts/style.sh and git add the result."
  exit 1
fi