SANER 2020 Mining Version Control Systems and Issue Trackers with LibVCS4j
项目地址 github

1. 背景

随着需求的增长,软件的开发变得越来越复杂。 不仅需要执行更多的要求。 此外,越来越多的人参与到软件开发过程中。 为了管理工件(源代码文件、文档等),可能会使用版本控制系统 (VCS),例如 Git、Mercurial 和 Subversion。 此外,还集成了问题跟踪系统 (ITS),以书面形式记录错误,跟踪开发状态,从而简化团队之间的沟通。

挖掘这些(软件)存储库对于分析软件演化是值得的。 例如,之前的研究工作

An empirical study of code clone genealogies. 2005 ESEC/FSE A study of consistent and inconsistent changes to code clones. WCRE 2007 Evolution of type-1 clones. SCAM2009

研究了在不同 VCS 中管理的几个开源项目,通过跟踪项目历史源代码文件中的发现来分析软件中的克隆如何随时间变化。 尽管软件演化分析是一个不断发展的研究领域,但一组公共的工具可以帮助提取必要的数据,而不必每个研究都提出自己的数据分析方法。

现有的几项研究通过跟踪源代码文件的更改历史记录结果来分析软件中的克隆如何演变。 通过链接问题(在问题跟踪系统中报告和讨论),可以进一步完善结果——例如,识别删除长期存在的克隆和修复已知问题的提交。
然而,由于缺乏合适的工具,这些研究中的大多数都采用了自己的数据提取方法。

在本文中,作者提出了 LibVCS4j,这是一个 Java 程序,它可以集成到现有的分析工具(例如,检测源代码文件中的代码异味的工具)中。

  1. 遍历软件存储库的历史记录。
  2. 在选定的一组修订上运行所需的分析 。
  3. 在处理存储库时获取附加信息(提交消息、文件差异等)。

    该库将不同的版本控制系统和问题跟踪系统统一在一个通用接口下,因此非常适合将数据分析与数据提取分离。

2. 设计与实现

LibVCS4j 可在 GitHub 上公开获得。 二进制版本定期在 Maven Central 上发布。 该库的设计目标如下:

  1. 为不同类型的版本控制系统和问题跟踪系统提供单一 API。
  2. 版本控制系统的修订被迭代处理(它们被一个接一个地检出)。
  3. 对于每个修订版,相应的文件在磁盘上物理可用,因此分析工具无需进一步操作即可处理这些文件。
  4. 对于每个修订版,附加信息(例如从一个修订版更改为另一个修订版的文件)由一个全面且可扩展的数据模型提供。
  5. 问题处理(在专用问题跟踪系统中管理)是一项可选功能。
  6. 如果启用了问题处理,它们会自动链接到提交。

UML 组件图
image.png

libvcs4j-api : 统一的api接口设计模块
libvcs4j :各接口的具体实现模块
libvcs4j-tools :拓展模块

数据模型的UML类图

image.png

  1. Revision, RevisionRange


  • Revision 表示 vcs 在某个时间点的状态,两个 Revision(当前版本和前一个版本)之间的转换由 RevisionRange 表示。

  • 从用户的角度来看,RevisionRange 构成了数据模型的根节点。在迭代检出存储库时,在每个迭代步骤中都会创建一个 RevisionRange 实例。 RevisionRange ordinal 字段存储可用于唯一标识单个实例的序列号。 例如,第一个 RevisionRange 的序号为 1,第二个 RevisionRange 的序号为 2,依此类推。

  1. VCSFile, Position, Range


  • VCSFile 对应某个时间点 vcs 中的文件

  • Position 表示文件中的特定位置,支持三种不同类型的位置

    • 行和列(具有相应的制表符大小)
    • 行和行偏移量(一行中的字符数)
    • 偏移量(从文件开头的字符数)
  • range 在上述的基础上将两个位置组成一个文件中的一个部分。

image.png
PositionRange 实例可以分别使用 apply 方法从一个修订版映射到另一个修订版。

List 1 显示了一个包含四行代码的 Revision n 的文件。 清单 2 显示了 Revision n+1 的同一个文件,其中添加了两行代码(public String foobar;一个空行)。

例如,如果 Position 指向第二行的第一个字符(关键字 void 的字符 v),则可以通过使用相应的 FileChange 实例调用 apply 来更新其位置——这将返回另一个指向第四行第一个字符的 Position。

  1. Commit, FileChange, FileChange.Type
  • Commit 类对应于版本控制系统中的提交操作,并存储了哪些文件被更改的信息(文件更改依次由 FileChange 类表示)。 支持四种不同类型的文件更改:
    • 添加(添加文件)
    • 删除(删除文件)、
    • 修改(更改文件内容)
    • 重定位(文件的路径已更改)


  1. LineChange, LineChange.Type, LineInfo
  • FileChange 代表文件整体的变化,而 LineChange 代表文件中单行的变化。 支持两种不同类型的更改:插入(插入一行)和删除(删除一行)。

  • VCSFile 提供了一种方法来确定文件每一行的作者身份(LineInfo)——这对应于 gitblame、svn annotate 等。 LineChangesLineInfos 是惰性计算的。 也就是说,只有在调用相应的方法时,才会从存储库中提取相关数据。


  1. Issue, Comment


  • 这些类存储从问题跟踪系统(issue tracking system,ITS)中提取的数据。 通常,Issue, Comment与数据模型的其余部分无关。

  • 然而,大多数 ITS 允许参考特定的提交消息中的问题。例如,如果提交修复了问题跟踪系统中报告的错误,则可以通过如下引用 Issue ID 来自动关闭它:修复 #1(其中 1 是问题 ID)。 LibVCS4j 能够识别提交消息中的此类引用,并自动将问题链接到提交。


  1. VCSEngine, ITEngine
  • VCSEngine 指定了版本控制系统的接口,ITEngine 指定了问题跟踪系统的接口

  • VCSEngine 最相关的方法是 next,它检查下一个修订版并返回一个 RevisionRange 的实例(如果没有更多修订版可用,则返回的 Optional 为空)。

  • 如前所述,问题的处理是一个可选功能。 仅当将 ITEngine 分配给 VCSEngine 时才启用它。 如果没有引用 ITEngine,则 Commit 引用的问题列表为空。 同时,ITEngine 可以用作独立的提取引擎。

UML 活动图(虚线框标记了 LibVCS4j 的活动)image.png

客户端代码,使用 LibVCS4j 迭代存储库历史的代码

  • 首先需要设置一个 VCSEngine (vcs),如果应该启用问题处理,设置并分配一个 ITEngine (it)

  • 然后,在循环中调用 next 方法,直到没有可用的修订版为止(返回一个空的 Java Optional)。

  • 每次调用 next

    • 检查下一个修订版,以便相应的文件在磁盘上物理可用,
    • 创建 RevisionRange 的实例
    • 如果 ITEngine 分配给 vcs,则确定引用的 issue,comment 通过解析提交消息。 成功签出修订后,客户端代码可以运行所需的分析。

上述过程的伪代码展示
image.png

总结
在本文中,我们介绍了 LibVCS4j,这是一个用于存储库挖掘的 Java 编程库。 该库旨在供现有分析工具(例如,检测源代码文件中的代码异味的工具)使用,以将数据分析与数据提取分离并跟踪源代码中的发现修订之间的文件。 LibVCS4j 将不同的版本控制系统(Git、Mercurial 和 Subversion)以及不同的问题跟踪系统(GitHub 和 Gitlab)统一在一个通用 API 下,并从这些系统的技术细节中抽象出来。 除了将源代码文件检出到磁盘(允许分析工具立即处理这些文件)之外,还提供了一个综合数据模型,可用于在迭代时获取附加信息(例如提交消息、文件差异等) 通过一个软件的历史。 我们的代码在 GitHub 上公开提供,我们鼓励研究人员和开发人员请求和添加新功能。 LibVCS4j 的第一个版本于 2018 年 4 月 19 日在 Maven 中心发布。从那时起,我们不断改进我们的代码库。 根据Maven Central的下载统计,LibVCS4j今年的月下载量约为1000次。