]> git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/build_tools/format-diff.sh
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / rocksdb / build_tools / format-diff.sh
1 #!/usr/bin/env bash
2 # Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
3 # If clang_format_diff.py command is not specfied, we assume we are able to
4 # access directly without any path.
5
6 print_usage () {
7 echo "Usage:"
8 echo "format-diff.sh [OPTIONS]"
9 echo "-c: check only."
10 echo "-h: print this message."
11 }
12
13 while getopts ':ch' OPTION; do
14 case "$OPTION" in
15 c)
16 CHECK_ONLY=1
17 ;;
18 h)
19 print_usage
20 exit 1
21 ;;
22 ?)
23 print_usage
24 exit 1
25 ;;
26 esac
27 done
28
29 REPO_ROOT="$(git rev-parse --show-toplevel)"
30
31 if [ "$CLANG_FORMAT_DIFF" ]; then
32 echo "Note: CLANG_FORMAT_DIFF='$CLANG_FORMAT_DIFF'"
33 # Dry run to confirm dependencies like argparse
34 if $CLANG_FORMAT_DIFF --help >/dev/null < /dev/null; then
35 true #Good
36 else
37 exit 128
38 fi
39 else
40 # First try directly executing the possibilities
41 if clang-format-diff --help &> /dev/null < /dev/null; then
42 CLANG_FORMAT_DIFF=clang-format-diff
43 elif clang-format-diff.py --help &> /dev/null < /dev/null; then
44 CLANG_FORMAT_DIFF=clang-format-diff.py
45 elif $REPO_ROOT/clang-format-diff.py --help &> /dev/null < /dev/null; then
46 CLANG_FORMAT_DIFF=$REPO_ROOT/clang-format-diff.py
47 else
48 # This probably means we need to directly invoke the interpreter.
49 # But first find clang-format-diff.py
50 if [ -f "$REPO_ROOT/clang-format-diff.py" ]; then
51 CFD_PATH="$REPO_ROOT/clang-format-diff.py"
52 elif which clang-format-diff.py &> /dev/null; then
53 CFD_PATH="$(which clang-format-diff.py)"
54 else
55 echo "You didn't have clang-format-diff.py and/or clang-format available in your computer!"
56 echo "You can download clang-format-diff.py by running: "
57 echo " curl --location https://raw.githubusercontent.com/llvm/llvm-project/main/clang/tools/clang-format/clang-format-diff.py -o ${REPO_ROOT}/clang-format-diff.py"
58 echo "You should make sure the downloaded script is not compromised."
59 echo "You can download clang-format by running:"
60 echo " brew install clang-format"
61 echo " Or"
62 echo " apt install clang-format"
63 echo " This might work too:"
64 echo " yum install git-clang-format"
65 echo "Then make sure clang-format is available and executable from \$PATH:"
66 echo " clang-format --version"
67 exit 128
68 fi
69 # Check argparse pre-req on interpreter, or it will fail
70 if echo import argparse | ${PYTHON:-python3}; then
71 true # Good
72 else
73 echo "To run clang-format-diff.py, we'll need the library "argparse" to be"
74 echo "installed. You can try either of the follow ways to install it:"
75 echo " 1. Manually download argparse: https://pypi.python.org/pypi/argparse"
76 echo " 2. easy_install argparse (if you have easy_install)"
77 echo " 3. pip install argparse (if you have pip)"
78 exit 129
79 fi
80 # Unfortunately, some machines have a Python2 clang-format-diff.py
81 # installed but only a Python3 interpreter installed. Unfortunately,
82 # automatic 2to3 migration is insufficient, so suggest downloading latest.
83 if grep -q "print '" "$CFD_PATH" && \
84 ${PYTHON:-python3} --version | grep -q 'ython 3'; then
85 echo "You have clang-format-diff.py for Python 2 but are using a Python 3"
86 echo "interpreter (${PYTHON:-python3})."
87 echo "You can download clang-format-diff.py for Python 3 by running: "
88 echo " curl --location https://raw.githubusercontent.com/llvm/llvm-project/main/clang/tools/clang-format/clang-format-diff.py -o ${REPO_ROOT}/clang-format-diff.py"
89 echo "You should make sure the downloaded script is not compromised."
90 exit 130
91 fi
92 CLANG_FORMAT_DIFF="${PYTHON:-python3} $CFD_PATH"
93 # This had better work after all those checks
94 if $CLANG_FORMAT_DIFF --help >/dev/null < /dev/null; then
95 true #Good
96 else
97 exit 128
98 fi
99 fi
100 fi
101
102 # TODO(kailiu) following work is not complete since we still need to figure
103 # out how to add the modified files done pre-commit hook to git's commit index.
104 #
105 # Check if this script has already been added to pre-commit hook.
106 # Will suggest user to add this script to pre-commit hook if their pre-commit
107 # is empty.
108 # PRE_COMMIT_SCRIPT_PATH="`git rev-parse --show-toplevel`/.git/hooks/pre-commit"
109 # if ! ls $PRE_COMMIT_SCRIPT_PATH &> /dev/null
110 # then
111 # echo "Would you like to add this script to pre-commit hook, which will do "
112 # echo -n "the format check for all the affected lines before you check in (y/n):"
113 # read add_to_hook
114 # if [ "$add_to_hook" == "y" ]
115 # then
116 # ln -s `git rev-parse --show-toplevel`/build_tools/format-diff.sh $PRE_COMMIT_SCRIPT_PATH
117 # fi
118 # fi
119 set -e
120
121 uncommitted_code=`git diff HEAD`
122
123 # If there's no uncommitted changes, we assume user are doing post-commit
124 # format check, in which case we'll try to check the modified lines vs. the
125 # facebook/rocksdb.git main branch. Otherwise, we'll check format of the
126 # uncommitted code only.
127 if [ -z "$uncommitted_code" ]
128 then
129 # Attempt to get name of facebook/rocksdb.git remote.
130 [ "$FORMAT_REMOTE" ] || FORMAT_REMOTE="$(LC_ALL=POSIX LANG=POSIX git remote -v | grep 'facebook/rocksdb.git' | head -n 1 | cut -f 1)"
131 # Fall back on 'origin' if that fails
132 [ "$FORMAT_REMOTE" ] || FORMAT_REMOTE=origin
133 # Use main branch from that remote
134 [ "$FORMAT_UPSTREAM" ] || FORMAT_UPSTREAM="$FORMAT_REMOTE/$(LC_ALL=POSIX LANG=POSIX git remote show $FORMAT_REMOTE | sed -n '/HEAD branch/s/.*: //p')"
135 # Get the common ancestor with that remote branch. Everything after that
136 # common ancestor would be considered the contents of a pull request, so
137 # should be relevant for formatting fixes.
138 FORMAT_UPSTREAM_MERGE_BASE="$(git merge-base "$FORMAT_UPSTREAM" HEAD)"
139 # Get the differences
140 diffs=$(git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -p 1)
141 echo "Checking format of changes not yet in $FORMAT_UPSTREAM..."
142 else
143 # Check the format of uncommitted lines,
144 diffs=$(git diff -U0 HEAD | $CLANG_FORMAT_DIFF -p 1)
145 echo "Checking format of uncommitted changes..."
146 fi
147
148 if [ -z "$diffs" ]
149 then
150 echo "Nothing needs to be reformatted!"
151 exit 0
152 elif [ $CHECK_ONLY ]
153 then
154 echo "Your change has unformatted code. Please run make format!"
155 if [ $VERBOSE_CHECK ]; then
156 clang-format --version
157 echo "$diffs"
158 fi
159 exit 1
160 fi
161
162 # Highlight the insertion/deletion from the clang-format-diff.py's output
163 COLOR_END="\033[0m"
164 COLOR_RED="\033[0;31m"
165 COLOR_GREEN="\033[0;32m"
166
167 echo -e "Detect lines that doesn't follow the format rules:\r"
168 # Add the color to the diff. lines added will be green; lines removed will be red.
169 echo "$diffs" |
170 sed -e "s/\(^-.*$\)/`echo -e \"$COLOR_RED\1$COLOR_END\"`/" |
171 sed -e "s/\(^+.*$\)/`echo -e \"$COLOR_GREEN\1$COLOR_END\"`/"
172
173 echo -e "Would you like to fix the format automatically (y/n): \c"
174
175 # Make sure under any mode, we can read user input.
176 exec < /dev/tty
177 read to_fix
178
179 if [ "$to_fix" != "y" ]
180 then
181 exit 1
182 fi
183
184 # Do in-place format adjustment.
185 if [ -z "$uncommitted_code" ]
186 then
187 git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -i -p 1
188 else
189 git diff -U0 HEAD | $CLANG_FORMAT_DIFF -i -p 1
190 fi
191 echo "Files reformatted!"
192
193 # Amend to last commit if user do the post-commit format check
194 if [ -z "$uncommitted_code" ]; then
195 echo -e "Would you like to amend the changes to last commit (`git log HEAD --oneline | head -1`)? (y/n): \c"
196 read to_amend
197
198 if [ "$to_amend" == "y" ]
199 then
200 git commit -a --amend --reuse-message HEAD
201 echo "Amended to last commit"
202 fi
203 fi