【问题标题】:How to apply static analysis rules after a certain commit如何在某个提交后应用静态分析规则
【发布时间】:2017-03-20 15:19:10
【问题描述】:

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

谢谢

【问题讨论】:

    标签: git maven static-analysis software-quality


    【解决方案1】:

    我无法解决任何 maven 方面的问题,但“文件在某些提交之后创建”的一般概念存在一个相当明显的问题,即:每个 Git 提交都是一个完整的快照本身。您将如何判断哪些文件是何时创建的?

    血统测试

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

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

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

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

    对于这个特定的目的,测试实际上是 而不是<,也就是说,如果你用8ac9f31 8ac9f31 重复它,答案将是“是的,8ac9f318ac9f31 的祖先。如果需要独占小于属性,可以加上“and not equal”,例如:

    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
    

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

    快照问题

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

    Git 也确实如此。 Git 为git diff 目的所做的默认情况是假设如果这两个文件具有相同的路径名,则它们是“相同的实体”,除非您使用-B 标志来@ 987654343@。同时,如果某个路径名在祖先中 missing,而另一个路径名在后代中是 new,则该路径对成为 重命名检测的候选者。重命名检测基于相似度索引。如果您添加 -B 选项,如果相同的相似性指数低于某个阈值,则在两个有问题的提交中,具有 same 路径名的两个文件将被“分开”。如果打开重命名检测,任何未配对的文件(包括由于-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 遍历祖先路径中的每个提交,除了在分支和的情况下您需要注意任何合并-merge 祖先路径 DAGlet(子图)中的结构。可能不值得这样做:Git 的相似性测试可能更可靠。)

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

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

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

    【讨论】:

      猜你喜欢
      • 2012-08-01
      • 2013-09-20
      • 1970-01-01
      • 2012-07-17
      • 2023-04-02
      • 1970-01-01
      • 2014-05-30
      • 2013-09-20
      • 1970-01-01
      相关资源
      最近更新 更多