git clang-format 可以告诉我是否需要更改格式吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22866609/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can clang-format tell me if formatting changes are necessary?
提问by David Ogren
Is there an way that you can run clang-format
in a mode where it reports if the file meets the specified format? A kind of dry-run mode where it reports if a change is needed, but doesn't make the change. Ideally I'd like clang-format to just return a non-zero exit code if the file needs changes. Or, even more ideally, a non-zero exit code and a list of the files that need changes on standard output.
有没有办法可以clang-format
在报告文件是否符合指定格式的模式下运行?一种试运行模式,它报告是否需要更改,但不进行更改。理想情况下,如果文件需要更改,我希望 clang-format 只返回一个非零退出代码。或者,更理想的是,非零退出代码和需要在标准输出上更改的文件列表。
I'm trying to keep the question generic, so that more people can answer, but what I am trying to do is write a git pre-commit hook that will reject any commits that don't match the expected .clang-format . It's easy to run clang-format on the list of files in the index. But it's hard to know if clang-format actually changed anything.
我试图保持问题的通用性,以便更多人可以回答,但我想要做的是编写一个 git pre-commit 钩子,它会拒绝任何与预期 .clang-format 不匹配的提交。在索引中的文件列表上运行 clang-format 很容易。但是很难知道 clang-format 是否真的改变了任何东西。
I have one potential solution based on -output-replacements-xml
(that I will post as an answer), but it's a hack and I feel like this should be more straightforward. Comments/suggestions, edits, different answers/approaches are all welcome.
我有一个基于-output-replacements-xml
(我将作为答案发布)的潜在解决方案,但这是一种黑客行为,我觉得这应该更简单。欢迎评论/建议、编辑、不同的答案/方法。
采纳答案by Matthieu Moy
run-clang-formatis a simple wrapper around clang-format
designed precisely to be used as a hook or as a continuous integration script: it outputs a diff and exits with a sensible status.
run-clang-format是一个简单的包装器,clang-format
专门用作挂钩或持续集成脚本:它输出一个差异并以合理的状态退出。
The example given on the home page speaks for itself:
主页上给出的示例不言自明:
回答by David Ogren
One of the reasons I feel like this should be easier than it is because -output-replacements-xml essentially gives me the answer that I want, it just doesn't give it to me in an easy to consume way. However, since the output if no replacements are needed is very predictable, parsing the output isn't too hard.
我觉得这应该比它更容易的原因之一是因为 -output-replacements-xml 本质上给了我想要的答案,它只是没有以一种易于使用的方式给我。然而,由于不需要替换的输出是非常可预测的,解析输出并不太难。
What I have right now is
我现在拥有的是
clang-format -style=file -output-replacements-xml | grep -c "<replacement " >/dev/null
This actually returns the inverse of the exit code I want, since grep returns 0 if something matches, 1 if nothing does. But that is easy enough to deal with.
这实际上返回了我想要的退出代码的逆,因为如果匹配,grep 返回 0,如果没有匹配,则返回 1。但这很容易处理。
So the relevant bit of my git pre-commit hook would be
所以我的 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
- Get the full filenames of the files in the index (excluding files that are being deleted and other unusual cases where I might not want to process the file)
- Only keep the filenames of things I want to check the formatting of (in my case just c,m, and h files)
- Run the results through xargs to essentially "for each" the next command
- Run clang-format with the -output-replacements-xml option on all of the files
- Search for replacement (as opposed to replacements) that indicates that clang-format has found a replacement that it wants to make. (Discarding all output as the XML won't be meaningful to the user.)
- The last command exits 1 (grep says we found nothing) we are done and things are fine.
- If not, display a message and exit 1, which cancels the commit. Unfortunately we don't have an easy way to tell the user which file was the problem, but they can run clang-format themselves and see.
- 获取索引中文件的完整文件名(不包括正在删除的文件和其他我可能不想处理文件的异常情况)
- 只保留我想检查格式的文件名(在我的例子中只有 c、m 和 h 文件)
- 通过 xargs 运行结果基本上“为每个”下一个命令
- 在所有文件上运行带有 -output-replacements-xml 选项的 clang-format
- 搜索表示 clang-format 已找到它想要进行的替换的替换(而不是替换)。(丢弃所有输出,因为 XML 对用户没有意义。)
- 最后一个命令退出 1(grep 说我们什么也没找到)我们已经完成了,一切都很好。
- 如果没有,则显示一条消息并退出 1,这将取消提交。不幸的是,我们没有一种简单的方法来告诉用户哪个文件有问题,但他们可以自己运行 clang-format 并查看。
回答by djasper
I am not entirely sure what your use case is, but check out git-clang-format (https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git-clang-format). It basically provides a clang-format integration for git and maybe that is what you are looking for.
我不完全确定您的用例是什么,但请查看 git-clang-format ( https://llvm.org/svn/llvm-project/cfe/trunk/tools/clang-format/git-clang-format) . 它基本上为 git 提供了一个 clang 格式的集成,也许这就是你正在寻找的。
回答by Matt
I slightly adjusted the comment from phs in this postto come up with:
我稍微调整了这篇文章中来自 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 {} \;) -
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 {} \;) -
that is..
那是..
cat
all cpp-ish files and pipe that todiff
(diff
will acceptstdin
because I specify-
at the end)- use process substitution (the
<( .. )
syntax) to runclang-format
on those same files. Don't use in-place formatting here. This is the other half that's sent todiff
- if
diff
exits with no output, success! You can also check the exit code via$?
-- it should be zero.
cat
所有 cpp-ish 文件和管道diff
(diff
会接受,stdin
因为我-
在最后指定)- 使用进程替换(
<( .. )
语法)clang-format
在这些相同的文件上运行。不要在此处使用就地格式。这是发送给的另一半diff
- 如果
diff
退出没有输出,成功!您还可以通过以下方式检查退出代码$?
- 它应该为零。
I have my CI service (travis) run this line in a bash script to make sure things are formatted properly. I have another script for actually running the formatter in-place. This reminds me of a caveat: you must use a shell that can do process sub (the posix shell does not).
我让我的 CI 服务 (travis) 在 bash 脚本中运行这一行,以确保格式正确。我有另一个脚本来实际运行格式化程序。这让我想起了一个警告:你必须使用一个可以处理 sub的 shell(posix shell 没有)。
回答by Daniel
I use git-clang-format
and a pre-commit script from Mike Rhodes' blog:
我使用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)
The script has a small error in that it doesn't work when there are no commits (trying to check against HEAD which doesn't exist yet). To bypass this, use the -n
or --no-verify
option.
该脚本有一个小错误,因为它在没有提交时不起作用(尝试检查尚不存在的 HEAD)。要绕过这一点,请使用-n
或--no-verify
选项。
Using -n
to skip the pre-commit script can also be helpful when you what to bypass the check because it can take a long time for a large codebase.
-n
当您绕过检查时,使用跳过预提交脚本也很有帮助,因为大型代码库可能需要很长时间。
The original post is here: http://www.dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html
原帖在这里:http: //www.dx13.co.uk/articles/2015/4/3/Setting-up-git-clang-format.html
回答by Martin
After I got inspired by David Ogren's postI made a pre-commit
hook that is able to work on the staged changes. This will ensure that the pre-commit
hook will work on the code that will actual make up the content of the commit and can't be fooled by a clang-format
run that didn't get staged.
在我受到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