是否有办法在报告文件是否符合指定格式的模式下运行clang-format
?一种干运行模式,它报告是否需要更改,但不进行更改。理想情况下,如果文件需要更改,我希望clang-format只返回非零退出代码。或者,更理想的是,非零退出代码和需要在标准输出上进行更改的文件列表。
我正在尝试将问题保持通用,以便更多人可以回答,但我想要做的是编写一个git pre-commit钩子,它将拒绝任何与预期不匹配的提交.clang-格式。在索引中的文件列表上运行clang-format很容易。但是很难知道clang格式是否真的改变了什么。
我有一个基于-output-replacements-xml
的潜在解决方案(我将作为答案发布),但这是一个黑客,我觉得这应该更直接。评论/建议,编辑,不同的答案/方法都是受欢迎的。
答案 0 :(得分:38)
我觉得这样的原因之一应该比它更容易因为-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
答案 1 :(得分:6)
答案 2 :(得分:4)
我不完全确定您的用例是什么,但请查看git-clang-format(https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git-clang-format)。它基本上为git提供了clang格式的集成,也许这就是你要找的东西。
答案 3 :(得分:3)
使用--dry-run
和-Werror
命令行选项。如果任何输入文件的格式不正确,它们将导致ClangFormat将任何违反格式的内容输出到stdout并返回非零退出状态。
$ clang-format --dry-run --Werror foo.cpp
foo.cpp:129:23: error: code should be clang-formatted [-Wclang-format-violations]
if (rc <= 0) {
$ echo $?
1
答案 4 :(得分:2)
我稍微调整了comment from phs in this post来提出:
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脚本中运行此行以确保格式正确。我有另一个脚本实际上就地运行格式化程序。这让我想起了一个警告:你必须使用一个可以处理sub(the posix shell does not)的shell。
答案 5 :(得分:1)
我使用git-clang-format
和Mike Rhodes的预提交脚本&#39;博客:
#!/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
跳过预提交脚本在您绕过检查时也会有所帮助,因为大型代码库可能需要很长时间。
原始帖子位于:http://www.dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html
答案 6 :(得分:1)
您可以将 git diff
与 clang-format-diff
一起使用:
$ git diff -U0 --no-color --staged HEAD | clang-format-diff -p1
注意:
--staged
仅用于在暂存更改上运行 clang-format-diff
$ git diff -U0 --no-color --staged HEAD -- $PWD/dir1 $PWD/dir2 $PWD/dir3 | clang-format-diff -p1
pre-commit
现在你的预提交可以是这个:
#!/bin/bash
dir_list="$PWD" # Add the directories you want here
cmd="git diff -U0 --no-color --staged HEAD -- $dir_list | clang-format-diff -p1"
echo ""
echo "Running clang-format on this commit"
echo ""
# Execute the format command
diff=$(eval "$cmd")
if [[ $? -ne 0 ]]
then
echo "Command failed to execute."
exit 1
fi
# Print the outcome
if [[ -z "$diff" ]]
then
echo "Everything is clean"
exit 0
else
echo "$diff"
echo ""
echo "Commit aborted due to code format inconsistencies."
exit 1
fi
答案 7 :(得分:0)
在我受到David Ogren's post的启发后,我创建了一个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
答案 8 :(得分:0)
您可以简单地使用 -n 选项
clang-format -n <file>