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. 5if [ -z $CLANG_FORMAT_DIFF ] 6then 7CLANG_FORMAT_DIFF="clang-format-diff.py" 8fi 9 10# Check clang-format-diff.py 11if ! which $CLANG_FORMAT_DIFF &> /dev/null 12then 13 echo "You didn't have clang-format-diff.py and/or clang-format available in your computer!" 14 echo "You can download clang-format-diff.py by running: " 15 echo " curl --location http://goo.gl/iUW1u2 -o ${CLANG_FORMAT_DIFF}" 16 echo "You can download clang-format by running:" 17 echo " brew install clang-format" 18 echo " Or" 19 echo " apt install clang-format" 20 echo " This might work too:" 21 echo " yum install git-clang-format" 22 echo "Then, move both files (i.e. ${CLANG_FORMAT_DIFF} and clang-format) to some directory within PATH=${PATH}" 23 echo "and make sure ${CLANG_FORMAT_DIFF} is executable." 24 exit 128 25fi 26 27# Check argparse, a library that clang-format-diff.py requires. 28python 2>/dev/null << EOF 29import argparse 30EOF 31 32if [ "$?" != 0 ] 33then 34 echo "To run clang-format-diff.py, we'll need the library "argparse" to be" 35 echo "installed. You can try either of the follow ways to install it:" 36 echo " 1. Manually download argparse: https://pypi.python.org/pypi/argparse" 37 echo " 2. easy_install argparse (if you have easy_install)" 38 echo " 3. pip install argparse (if you have pip)" 39 exit 129 40fi 41 42# TODO(kailiu) following work is not complete since we still need to figure 43# out how to add the modified files done pre-commit hook to git's commit index. 44# 45# Check if this script has already been added to pre-commit hook. 46# Will suggest user to add this script to pre-commit hook if their pre-commit 47# is empty. 48# PRE_COMMIT_SCRIPT_PATH="`git rev-parse --show-toplevel`/.git/hooks/pre-commit" 49# if ! ls $PRE_COMMIT_SCRIPT_PATH &> /dev/null 50# then 51# echo "Would you like to add this script to pre-commit hook, which will do " 52# echo -n "the format check for all the affected lines before you check in (y/n):" 53# read add_to_hook 54# if [ "$add_to_hook" == "y" ] 55# then 56# ln -s `git rev-parse --show-toplevel`/build_tools/format-diff.sh $PRE_COMMIT_SCRIPT_PATH 57# fi 58# fi 59set -e 60 61uncommitted_code=`git diff HEAD` 62 63# If there's no uncommitted changes, we assume user are doing post-commit 64# format check, in which case we'll try to check the modified lines vs. the 65# facebook/rocksdb.git master branch. Otherwise, we'll check format of the 66# uncommitted code only. 67if [ -z "$uncommitted_code" ] 68then 69 # Attempt to get name of facebook/rocksdb.git remote. 70 [ "$FORMAT_REMOTE" ] || FORMAT_REMOTE="$(git remote -v | grep 'facebook/rocksdb.git' | head -n 1 | cut -f 1)" 71 # Fall back on 'origin' if that fails 72 [ "$FORMAT_REMOTE" ] || FORMAT_REMOTE=origin 73 # Use master branch from that remote 74 [ "$FORMAT_UPSTREAM" ] || FORMAT_UPSTREAM="$FORMAT_REMOTE/master" 75 # Get the common ancestor with that remote branch. Everything after that 76 # common ancestor would be considered the contents of a pull request, so 77 # should be relevant for formatting fixes. 78 FORMAT_UPSTREAM_MERGE_BASE="$(git merge-base "$FORMAT_UPSTREAM" HEAD)" 79 # Get the differences 80 diffs=$(git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -p 1) 81else 82 # Check the format of uncommitted lines, 83 diffs=$(git diff -U0 HEAD | $CLANG_FORMAT_DIFF -p 1) 84fi 85 86if [ -z "$diffs" ] 87then 88 echo "Nothing needs to be reformatted!" 89 exit 0 90fi 91 92# Highlight the insertion/deletion from the clang-format-diff.py's output 93COLOR_END="\033[0m" 94COLOR_RED="\033[0;31m" 95COLOR_GREEN="\033[0;32m" 96 97echo -e "Detect lines that doesn't follow the format rules:\r" 98# Add the color to the diff. lines added will be green; lines removed will be red. 99echo "$diffs" | 100 sed -e "s/\(^-.*$\)/`echo -e \"$COLOR_RED\1$COLOR_END\"`/" | 101 sed -e "s/\(^+.*$\)/`echo -e \"$COLOR_GREEN\1$COLOR_END\"`/" 102 103if [[ "$OPT" == *"-DTRAVIS"* ]] 104then 105 exit 1 106fi 107 108echo -e "Would you like to fix the format automatically (y/n): \c" 109 110# Make sure under any mode, we can read user input. 111exec < /dev/tty 112read to_fix 113 114if [ "$to_fix" != "y" ] 115then 116 exit 1 117fi 118 119# Do in-place format adjustment. 120if [ -z "$uncommitted_code" ] 121then 122 git diff -U0 "$FORMAT_UPSTREAM_MERGE_BASE" | $CLANG_FORMAT_DIFF -i -p 1 123else 124 git diff -U0 HEAD^ | $CLANG_FORMAT_DIFF -i -p 1 125fi 126echo "Files reformatted!" 127 128# Amend to last commit if user do the post-commit format check 129if [ -z "$uncommitted_code" ]; then 130 echo -e "Would you like to amend the changes to last commit (`git log HEAD --oneline | head -1`)? (y/n): \c" 131 read to_amend 132 133 if [ "$to_amend" == "y" ] 134 then 135 git commit -a --amend --reuse-message HEAD 136 echo "Amended to last commit" 137 fi 138fi 139