#!/usr/bin/env bash #============================================================================= # Copyright 2015-2017 Kitware, Inc. # # 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='usage: clang-format.bash [] [--] --help Print usage plus more detailed help. --clang-format Use given clang-format tool. --amend Filter files changed by HEAD. --cached Filter files locally staged for commit. --modified Filter files locally modified from HEAD. --tracked Filter files tracked by Git. ' help="$usage"' Example to format locally modified files: Utilities/Scripts/clang-format.bash --modified Example to format locally modified files staged for commit: Utilities/Scripts/clang-format.bash --cached Example to format files modified by the most recent commit: Utilities/Scripts/clang-format.bash --amend Example to format all files tracked by Git: Utilities/Scripts/clang-format.bash --tracked Example to format the current topic: git filter-branch \ --tree-filter "Utilities/Scripts/clang-format.bash --tracked" \ master.. ' die() { echo "$@" 1>&2; exit 1 } #----------------------------------------------------------------------------- # Parse command-line arguments. clang_format='' mode='' while test "$#" != 0; do case "$1" in --amend) mode="amend" ;; --cached) mode="cached" ;; --clang-format) shift; clang_format="$1" ;; --help) echo "$help"; exit 0 ;; --modified) mode="modified" ;; --tracked) mode="tracked" ;; --) shift ; break ;; -*) die "$usage" ;; *) break ;; esac shift done test "$#" = 0 || die "$usage" # Find a default tool. tools=' clang-format-15 clang-format ' if test "x$clang_format" = "x"; then for tool in $tools; do if type -p "$tool" >/dev/null; then clang_format="$tool" break fi done fi # Verify that we have a tool. if ! type -p "$clang_format" >/dev/null; then echo "Unable to locate a 'clang-format' tool." exit 1 fi if ! "$clang_format" --version | grep 'clang-format version 15' >/dev/null 2>/dev/null; then echo "clang-format version 15 is required (exactly)" exit 1 fi # Select listing mode. case "$mode" in '') echo "$usage"; exit 0 ;; amend) git_ls='git diff-tree --diff-filter=AM --name-only HEAD -r --no-commit-id' ;; cached) git_ls='git diff-index --diff-filter=AM --name-only HEAD --cached' ;; modified) git_ls='git diff-index --diff-filter=AM --name-only HEAD' ;; tracked) git_ls='git ls-files' ;; *) die "invalid mode: $mode" ;; esac # List files as selected above. $git_ls | # Select sources with our attribute. git check-attr --stdin format.clang-format | sed -n '/: format\.clang-format: \(set\|15\)$/ {s/:[^:]*:[^:]*$//p}' | # Update sources in-place. xargs -d '\n' "$clang_format" -i