aboutsummaryrefslogtreecommitdiff
path: root/toolchain_utils_githooks/check-format
blob: 372cc4839bc9b31385ce5c671a005b0a18a98bd3 (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
#!/bin/bash -e
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# This script checks the format of the given files. If any look incorrectly
# formatted, this will complain about them and exit. At the moment, it only
# checks the format of Python.
#
# FIXME: It would be nice if YAPF supported tweaking quotes:
# https://github.com/google/yapf/issues/399

if [[ $# -eq 0 ]]; then
  echo "No files were given to check the format of." >&2
  echo "Usage: $0 file1 file2 ..." >&2
  exit 1
fi

yapf=yapf
gofmt=gofmt

if ! type "${yapf}" >/dev/null 2>&1; then
  echo "${yapf} isn't on your \$PATH. Please either enter a chroot, or place" \
    "depot_tools on your \$PATH." >&2
  exit 1
fi

if ! type "${gofmt}" >/dev/null 2>&1; then
  echo "${gofmt} isn't on your \$PATH. Please either enter a chroot, or add " \
    "the go binaries to your \$PATH." >&2
  exit 1
fi

status_to_tf() {
  if "$@" >& /dev/null; then
    echo true
  else
    echo false
  fi
}

complain_about_missing=$(status_to_tf test -z "${IGNORE_MISSING}")

check_python_file_header() {
  local py_file="$1"
  local needs_hashbang=$(status_to_tf test -x "${py_file}")
  local has_hashbang=$(status_to_tf grep -q '^#!' <(head -n1 "${py_file}"))

  if [[ "${needs_hashbang}" == "${has_hashbang}" ]]; then
    return 0
  fi

  if "${needs_hashbang}"; then
    echo "File ${py_file} needs a #!; please run" \
      "\`sed -i '1i#!/usr/bin/env python' ${py_file}\`"
  else
    echo "File ${py_file} has an unnecessary #!; please run" \
      "\`sed -i 1d ${py_file}\`"
  fi
  return 1
}

everything_passed=true
python_files=()
go_files=()

for f in "$@"; do
  if [[ ! -e "${f}" ]]; then
    if "${complain_about_missing}"; then
      echo "error: no such file: ${f}" >&2
      everything_passed=false
    fi
    continue
  fi

  if [[ "${f}" == *.py ]]; then
    python_files+=( "${f}" )

    if ! check_python_file_header "${f}"; then
      everything_passed=false
    fi
  elif [[ "${f}" == *.go ]]; then
    go_files+=( "${f}" )
  fi
done

if [[ "${#python_files[@]}" -ne 0 ]]; then
  # yapf will give us a full unified (git-like) diff. We parse out the file
  # names, e.g.,
  #
  # --- foo (original)
  #
  # Sed makes it so that bad_files consists only of those lines, but with the
  # leading '--- ' and trailing ' (original)' removed.
  #
  # FIXME: Ideally, we should pass yapf the `-p` arg, so it'll format things in
  # parallel. This requires concurrent.futures in python2 (which isn't
  # available in the chroot by default), and is purely an optimization, so we
  # can handle it later.
  bad_files=(
    $("${yapf}" -d "${python_files[@]}" |
      sed -n '/^--- /{ s/^--- //; s/ *(original)$//p }')
  )
  if [[ "${#bad_files[@]}" -ne 0 ]]; then
    echo "One or more python files appear to be incorrectly formatted."
    echo "Please run \`${yapf} -i ${bad_files[@]}\` to rectify this."
    everything_passed=false
  fi
fi

if [[ "${#go_files[@]}" -ne 0 ]]; then
  bad_files=(
    $("${gofmt}" -l "${go_files[@]}")
  )
  if [[ "${#bad_files[@]}" -ne 0 ]]; then
    echo "One or more go files appear to be incorrectly formatted."
    echo "Please run \`${gofmt} -w ${bad_files[@]}\` to rectify this."
    everything_passed=false
  fi
fi

"${everything_passed}"