ファイルが指定された形式を満たしているかどうかを報告するモードでclang-format
を実行できる方法はありますか?変更が必要かどうかを報告するが、変更を行わない一種の予行モード。ファイルの変更が必要な場合、clang-formatがゼロ以外の終了コードを返すようにすることが理想です。または、さらに理想的には、ゼロ以外の終了コードと、標準出力の変更が必要なファイルのリスト。
より多くの人が答えられるように、私は質問を一般的なものにしようとしていますが、私がやろうとしているのは、予想される.clang-formatに一致しないコミットを拒否するgit pre-commitフックを書くことです。インデックス内のファイルのリストに対してclang-formatを実行するのは簡単です。しかし、clang-formatが実際に何かを変更したかどうかを知ることは困難です。
-output-replacements-xml
(回答として投稿します)に基づいた1つの潜在的なソリューションがありますが、それはハックであり、これはもっと簡単なはずだと感じています。コメント/提案、編集、さまざまな回答/アプローチはすべて歓迎します。
run-clang-format は、フックまたは継続的統合スクリプトとして使用するために正確に設計されたclang-format
の単純なラッパーです。diffを出力し、適切なステータスで終了します。
ホームページにある例は、それ自体を物語っています:
-output-replacements-xmlが基本的に必要な答えを提供してくれるだけでなく、使いやすい方法でそれを提供してくれるからです。ただし、置換が不要な場合の出力は非常に予測可能であるため、出力の解析はそれほど難しくありません。
私が今持っているのは
clang-format -style=file -output-replacements-xml | grep -c "<replacement " >/dev/null
Grepは何かが一致すると0を返し、何も一致しないと1を返すため、これは実際に必要な終了コードの逆を返します。しかし、それは対処するのに十分簡単です。
したがって、私のgit pre-commitフックの関連ビットは
git diff --cached --name-only --diff-filter=ACMRT |
grep "\.[cmh]$" |
xargs -n1 clang-format -style=file -output-replacements-xml |
grep "<replacement " >/dev/null
if [ $? -ne 1 ]; then
echo "Commit did not match clang-format"
exit 1
fi
あなたのユースケースが何であるかは完全にはわかりませんが、git-clang-format( https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git- clang-format )。それは基本的にgitのclang形式の統合を提供し、おそらくあなたが探しているものです。
この投稿のphsからのコメント を少し調整しました:
find embedded/ -regex '.*\.\(ino\|cpp\|hpp\|cc\|cxx\|h\)' -exec cat {} \; | diff -u <(find embedded/ -regex '.*\.\(ino\|cpp\|hpp\|cc\|cxx\|h\)' -exec clang-format-3.9 -style=file {} \;) -
あれは..
cat
すべてのcpp-ishファイルとdiff
へのパイプ(最後に-
を指定するため、diff
はstdin
を受け入れます)<( .. )
構文)を使用して、それらの同じファイルでclang-format
を実行します。ここではインプレースフォーマットを使用しないでください。これは、diff
に送信される残りの半分です。diff
が出力なしで終了した場合、成功です! $?
経由で終了コードを確認することもできます-ゼロでなければなりません。CIサービス(travis)でbashスクリプトのこの行を実行して、適切にフォーマットされていることを確認します。実際にフォーマッタをインプレースで実行するための別のスクリプトがあります。これは、警告を思い出させます。サブ処理を実行できるシェルを使用する必要があります( posix Shellはそうではありません )。
git-clang-format
と、Mike Rhodesのブログの事前コミットスクリプトを使用します。
#!/bin/python
import subprocess
output = subprocess.check_output(["git", "clang-format", "--diff"])
if output not in ['no modified files to format\n', 'clang-format did not modify any files\n']:
print "Run git clang-format, then commit.\n"
exit(1)
else:
exit(0)
このスクリプトには小さなエラーがあり、コミットがない場合は動作しません(HEADこれはまだ存在していません)。これをバイパスするには、-n
または--no-verify
オプション。
-n
を使用してpre-commitスクリプトをスキップすると、大規模なコードベースでは時間がかかるため、チェックをバイパスするときに役立ちます。
元の投稿はこちら: http://www.dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html
David Ogrenの投稿 に触発されてから、段階的な変更に対応できるpre-commit
フックを作成しました。これにより、pre-commit
フックが実際にコミットの内容を構成するコードで動作し、ステージングされなかったclang-format
実行にだまされないようになります。
#!/bin/bash
files=()
for file in `git diff --cached --name-only --diff-filter=ACMRT | grep -E "\.(cpp|hpp)$"`; do
if ! cmp -s <(git show :${file}) <(git show :${file}|clang-format); then
files+=("${file}")
fi
done
if [ -n "${files}" ]; then
echo Format error within the following files:
printf "%s\n" "${files[@]}"
exit 1
fi