如何在特定提交后应用静态分析规则

时间:2017-03-20 15:19:10

标签: git maven static-analysis software-quality

我已经搞好了一个需要大量重构的大型项目。我想添加静态分析方法来关注质量。 由于我不想让他们立即应用它们,我想知道如何在maven周期中应用这些规则(如pmd,findbugs,checkstyle ...)仅适用于在某个提交/时间戳之后创建的文件

THX

1 个答案:

答案 0 :(得分:0)

我无法解决任何maven问题,但是在一些提交之后创建的“files ”的一般概念存在一个相当明显的问题,即:每个Git提交都是一个完整的快照本身。你怎么知道什么时候创建了哪些文件?

祖先测试

相对容易判断某些提交(通过哈希ID或任何其他标识符)是否是其他提交的后代

git merge-base --is-ancestor 8ac9f31 33071ac

告诉您8ac9f31标识的提交是否在提交图中的“33071ac之前。对于这种事情,使用标签名称(轻量级或带注释,从使用角度来看,这无关紧要)可能是明智之举。假设您将此标记命名为“enable-static-analysis”,并希望测试来自名为$branch的分支的某个分支提示是否在该点之后:

if git merge-base --is-ancestor enable-static-analysis $branch; then
    ... run static analysis software ...
fi

出于此特定目的,测试实际上是而不是<,即如果您使用8ac9f31 8ac9f31重复测试,则答案为“是,8ac9f318ac9f31的祖先。如果你需要一个独有的少于属性,你可以添加“而不是相等”,例如:

if git merge-base --is-ancestor enable-static-analysis $branch &&
    [ $(git rev-parse enable-static-analysis) != $(git rev-parse $branch) ]; then

或者,如果标记适用于普通的单父提交,则在测试中使用它自己的直接祖先(这不太明显但效率更高):

# We do not want to run this on a newly created branch whose
# current commit *is* the static-analysis enablement commit,
# hence the hat suffix:
if git merge-base --is-ancestor enable-static-analysis^ $branch

但这只会让你获得“提交后来”部分,而不是“自”以来创建的文件。

快照问题

从根本上说,问题在于您无法知道提交path/to/file.ext中的文件$descendant是否与提交path/to/file.ext中的文件$ancestor有任何关系。此外,如果path/to/file.ext中的$descendant通过some/other/file.extpath/to/othername.otherext重命名(有或没有任何修改)到达那里会怎样?

Git也没有。默认情况下,Git为git diff目的所做的是假设这两个文件是相同路径名的“同一实体”,除非您使用-B }标记到git diff。同时,如果祖先中的某些路径名缺失,并且后代中的某些其他路径名为 new ,则该路径对将成为重命名检测的候选者。重命名检测基于相似性索引。如果添加-B选项,则在相同的两个提交中,具有相同路径名的两个文件如果相同的相似性指数低于某个阈值则会“分开”。如果启用了重命名检测,则任何未配对的文件(包括由于-B导致的任何结果导致的任何文件)都将通过重命名相似性测试运行,如果它们通过,则这两个路径将作为“重命名”连接文件”。您可以通过运行git diff-tree -r -M --name-status $ancestor $descendant并解析其输出来找到Git对此的决定(如果以编程方式执行此操作,请考虑添加-z)。

取决于你是想成为这种幻想,还是想以不同的方式表达(可能的方式主要受你的想象力限制,以及你愿意投入多少计算资源; maven本身可能提供更多方式,特别是如果它有“清单”文件)。或者您可以使用简单但显然有些缺陷的“在路径名称之前存在”测试以确定path/to/file.ext是否“创建自”祖先提交以来:

oldhash=$(git rev-parse --verify --quiet $ancestor:$path)

如果成功,之前路径确实存在,现在您在$oldhash中拥有blob的哈希ID。这将让你判断文件是否完全改变了:如果是这样,它解析$descendant:$path作为修订说明符的新哈希将会有所不同。

(除了重命名问题,在$path中存在$ancestor但在某些中间提交中完全删除,然后在后代提交中或之前重新创建时,这显然失败了。 可检测的,通过遍历来自`git rev-list --ancestry-path $ ancestor .. $ descendant的祖先路径中的每个提交,除了你需要注意任何合并以防万一在祖先路径DAGlet(子图)中的分支和合并结构。可能不值得做:Git的相似性测试可能更可靠。)

如果你将所有这些放在一起,你可能最终会想要这样做:

git diff-tree -r --name-status $ancestor $descendant

可能还有一些额外的--diff-filter和/或-M和/或-B标记。状态为A(已添加)的任何文件都是要分析的文件。状态为M的文件可能也是不错的选择:有人触摸它们,所以是时候让它们通过静态分析了。