用于分布式版本控制的高效注释系统的制作方法

文档序号:11236531阅读:426来源:国知局
用于分布式版本控制的高效注释系统的制造方法与工艺



背景技术:

在开发软件应用时,个体软件工程师通常针对该软件应用的特定特征进行工作。一旦该特征被开发并测试,包含该特征的源代码就可以被登记并提交至该软件应用的代码存储库,以使得可以与针对该软件应用进行工作的其它软件工程师共享该特征。为了将功能提交至代码存储库,软件工程师登记使该特征在其它机器上工作所必需的所有文件变化和文件添加。向软件应用代码存储库的提交可以仅包括一个文件,或者可以包括针对软件工程师的单独机器上的特定源代码文件所作出的一组修改,这些修改应当被添加至该软件应用代码存储库中所保持的代码库。每个提交通常被给定标识符。由其标识符所标识的特定提交可以在给定时间提供代码存储库的快照。该提交内的每个文件可以接收与该提交相关联的文件修订编号。软件工程师可以从代码存储库中拉取并接受更新,以便获得包含代码存储库中的最新版本文件的最新提交并确保它们正在代码库的源代码文件的当前版本上进行工作。

在软件应用开发的过程中,在查看代码时,与代码相关的附加信息对于理解该代码的目的、功能、或者对于找到修改该代码或修复损坏代码的方式而可能是相关的。集成开发环境(ide)或文本编辑器可以将该附加信息显示为对源代码的注释。例如,可以突出显示拼写错误的词,可以在产生错误的代码旁示出编译器错误,并且可以示出对源代码文件或目录的最近更改的列表。注释可能来自多个来源,诸如静态代码分析、生产系统、拼写检查器、或协作工具。提供注释的工具针对一个特定文件修订或提交进行操作。然而,只要在稍后提交中的后续代码修改不会使该注释过时,所生成的注释就可以跨文件修订或存储库快照而保持相关。

只要所生成的注释对于软件工程师有用就使它们能够跨源代码文件修订和代码提交可用将会是有利的。如发明人所认识到的,应当存在一种在源代码存储库中跨软件代码的提交而有效率且正确地生成并显示注释的方式。



技术实现要素:

本说明书大体上描述了涉及显示源代码的技术,并且具体涉及用于使源代码注释跨软件代码存储库提交而可用的方法和系统。

大体上,本说明书中所描述主题的一个方面能够以计算机实现的方法和系统来体现。一种示例系统包括:一个或多个处理设备和一个或多个存储指令的存储设备,该指令在被该一个或多个处理设备执行时使得该一个或多个处理设备实现一种示例方法。一种示例方法包括:接收提交,该提交包括至少一个相对于父提交该已经有所更新的文件;识别该至少一个文件的父文件修订;确定该至少一个文件和所识别的父文件修订之间的差异;基于所确定的差异来追溯该文件中的每一行的起源;响应于确定行已经被添加或更改而将该行标示为起源并且在该文件的增量责任数据结构中将该行链接至其自身;以及将该行上的标识符以及该行的起源添加至该文件的增量责任数据结构。

另一种用于跨文件的多个修订显示相关注释的示例方法包括:接收文件的当前修订;查询责任结构以获得与该文件相关联的责任数据,以便根据先前修订来确定所述当前修订中的可见行;根据该先前修订确定与当前修订中的该可见行相关联的注释;以及显示所确定的注释。

这些和其它实施例能够可选地包括以下特征中的一个或多个特征。追溯行的起源可以包括:将与该行相关联的父文件修订追溯至一个父文件修订,并且将起源信息从该父文件修订复制到该行。追溯行的起源可以包括:将与该行相关联的父文件修订追溯至多个父文件修订,并且在该增量责任数据结构中将起源信息从被确定为最旧的父文件修订复制到该行。被确定为最旧的父文件修订可以基于与父文件修订相关联的时间戳来被找到。响应于确定至少一个文件中的两行包含相同的起源,这两行中的后者可以被标示为新的起源行。基于所确定的差异,至少一个文件的行可以被标示为所添加的行和所去除的行。可以构建布尔查询以检查行是否在提交中可见。可以存在判断布尔查询是否变得过于复杂(例如,当它超过预定长度时)的确定,并且如果是,则该查询可以由快捷标签替换以降低查询大小和复杂度。替选地,可以使用二元决策图来替代布尔查询,并且可以针对每个提交来创建标签。可以沿着边从下到上对该二元决策图进行评估以确定行在提交中是否可见。

本发明的一个或多个实施例的细节在仅作为说明而给出的附图和下面的描述中被给出。本发明的其它特征、方面、和优点将根据说明书、附图、和权利要求书而变得显而易见。各图中相似的附图标记和名称指示相似的元素。

附图说明

图1是源代码内的注释的示例。

图2是源代码的提交的示例。

图3是文件的示例责任数据结构。

图4是图示对代码存储库的代码变化的示例登记的框图。

图5a是用于跨文件的多个修订显示注释的示例方法的流程图。

图5b是用于创建增量责任数据结构的示例方法的流程图。

图6a是文件的父提交的示例。

图6b是要针对图5a中所表示的文件提交的当前代码的示例。

图6c是标记确定如图5b所表示的文件的当前状态与如图5a所表示的父提交之间的差异之后的提交的示例。

图7a是对于图2的提交#1的标记的示例。

图7b是对于图2的提交#2的标记的示例。

图7c是对于图2的提交#3的标记的示例。

图7d是对于图2的提交#4的标记的示例。

图8a是示例提交图。

图8b是提交#1的示例二元描述图。

图8c是提交#2的示例二元描述图。

图8d是提交#3的示例二元描述图。

图8e是提交#4的示例二元描述图。

图8f是提交#5的示例二元描述图。

图8g是主压缩的示例。

图8h是提交#6的示例二元描述图。

图8i是提交#7的示例二元描述图。

图9a是具有注释的示例提交图。

图9b是图9a中所示的注释的标签的示例。

图9c是图9a中所示的提交图的示例倒排索引;

图9d图示了具有图9a所示的注释的与其相对应的文档的正标记。

图10图示了示例迭代器类。

图11图示了用于找出所有匹配文档的示例二元描述示图的实施方式。

图12是用于跨源代码文件修订显示注释的示例方法的流程图。

图13是图示示例计算设备的框图。

具体实施方式

如以上所讨论的,注释提供关于源代码的有用信息,并且只要它们适用于它们所附加的文件行的当前版本就应当可以能够跨提交使用。注释能够视情况而从特定代码行进行添加(或去除)。如图1所图示,注释(103)可以向用户警示在代码中仍然存在todo的情况。然而通常而言,当代码行或文件被修改时,难以确定注释是否仍然能够适用于该行代码。因此,常规系统并不保留跨文件版本的注释。示例系统可以通过提供在责任层(blamelayer)存储注释的特殊数据结构来允许注释跨提交可用。另外,可以在示例递增责任数据结构之上实现标记方案以使得能够对特定提交的注释进行搜索和汇总。

在创建源代码时,软件开发者可以对代码存储库执行若干提交。例如,如图2所图示,根提交可以包括两个文件:文件#1和文件#2。来自根提交的文件#1的内容可以包括行1上的“aaa”,行2上的“bbb”,以及行3上的“ccc”。来自根提交的文件#2的内容可以包括在行1上的“aaa”和行2上的“aaa”。第二提交可以从提交#1得出,并通过删除“aaa”、更改“ccc”、和添加“ddd”来更改文件#1。则文件#1的内容可以是:在行1上的“bbb”(来自提交#1),行2上的“cccc”(来自提交#2),以及行3上的“ddd”(来自提交#2)。文件#2可以被更改已包括行1上的“aaa”(来自提交#1),行2上的“aaa”(来自提交#2),行3上的“aaa”(来自提交#1),以及行4上的“bbb”(来自提交#1)。

第三提交可以从提交#1得出,并通过删除“aaa”、更改“ccc”、添加“ddd”、并添加“eee”来更改文件#1。文件#1的内容可以是:行1上的“bbb”(来自提交#1),行2上的“ccccc”(来自提交#3),行3上的“ddd”(来自提交#3),以及行4上的“eee”(来自提交#3)。文件#2可以被更改以包括行1上的“aaa”(来自提交#1),行2上的“aaa”(来自提交#1),在行3上的“aaa”(来自提交#3),以及行4上的“bbb”(来自提交#3)。

第四提交可以是来自提交#2和提交#3二者的子提交(childcommit)。文件#1可以由用户或版本控制系统融合。文件#1可以包括:行1上的“bbb”(来自提交#1),“cccc”(来自提交#2,用户可以通过挑选“cccc”而不是“ccccc”来解决冲突的行数据),行3上的“ddd”(来自提交#2)——其由于该数据可能来自提交#2或提交#3而导致了责任冲突,以及行4上的“eee”(来自提交#3)。文件#2可以包括:行1上的“aaa”(来自提交#1的行1),行2上的“aaa”(来自提交#1的行2),行3上的“aaa”(来自提交#3的行3),以及行4上的“bbb”(来自提交#2的行3)。

一行源代码的责任数据包括标识该行被引入或被最后修改的提交的信息。例如,在图2所图示以及上文所讨论的示例中,在提交#4中,文件#1具有行1上的内容“bbb”。该内容在提交#1中被引入文件#1,因此文件#1的行1的责任数据包括对来自提交#1的文件#1的行2的引用。图3示出了示例责任数据结构,其包括作为行1的代表行(301)的对修订1(提交#1),行2的引用。

可以在特定提交的一行或多行处创建注释。关于特定注释的任何信息—包括注释的附件—可以被存储在该注释的示例数据结构中的责任层。责任层将来自一个文件修订的行映射至其首次被引入的祖先修订处的行。如果新添加了行,则责任层将该行映射至其自身。该起源行(或多个起源行)可以对应于代码的后续修订中不同的实际行。因此,注释可以被存储在最初引入该行的地方。在应当检索文件的注释时,示例系统可以查找存储在由当前文件修订所引用的行处的所有注释。

为了针对源代码中的行的注释创建快速查找,应当获取预先计算的责任数据并将其存储在示例责任数据结构中。如上文所提到的,该责任数据结构是从实际行到代表行的映射。使用责任数据结构,示例系统可以确定对于其应当示出注释的文件的所有代表行。然后,可以找到存储在这些代表行处的注释。换言之,可以基于当前文件的代表行来确定是否在代码的特定版本中显示注释。责任数据可以包括示出负责对文件中的行的特定改变或修订的提交的数据。该增量责任数据结构可以提供快速的代表行查找以快速地确定文件的每一行的负责提交(responsiblecommit)。关于注释的任何信息—包括该注释的附件—可以被存储在责任层处。

如用于跨文件的多个修订来显示相关注释的示例方法可以从图5a所图示(520)的接收文件的当前修订开始。可以查询与该文件相关联的责任结构以获得当前文件中的每行的行引用(522)。然后,该方法可以查找存储在所引用行处的注释(524),并且显示所确定的注释(526)。

为了找到所有的责任数据,直接的方案可以是对于特定提交处可见的所有文件计算责任信息。如图4所图示,可以使用示例提交爬取器(407)来逐个处理提交以便对于应用的代码存储库内的每个文件确定责任。示例爬取器(407)可以使用接收后(post-receive)钩子或类似的通知机制与代码存储库(405)进行连接。当在代码存储库(405)中发生提交时,可以经由该接收后钩子或通知机制来通知提交爬取器(407)。然后,该提交的内容可以由该提交爬取器从代码存储库进行提取。提交的内容可以包括对文件的更改。例如,在图4中,最初在图1中图示的文件(100)已经被更改为在行15上包括注释(401)。虽然注释可以通过静态代码分析得出和/或直接来自于存储库变化,但是注释可以来自其它子系统或者其来源可以被存储在存储库之中的经部署且在执行的程序。

提交(100)中的文件可以在软件工程师的本地机器(403)上被改变并且然后被提交至代码存储库(405)。当文件(100)被提交至代码存储库(405)时,提交爬取器可以运行以确定需要被创建的责任数据。提交爬取器(407)可以以拓扑顺序处理提交,以使得父提交(parentcommit)先于子提交以便创建示例递增责任数据结构。

示例提交爬取器(407)可以创建代码文件的责任数据。所添加的文件仅由新的行组成,其中的每一行都可以标示为起源行。例如,如果来自图1的文件(100)被新提交至代码存储库(405),则所有的行都将在修订1中被标示为起源行。

,用于创建文件的责任数据结构的示例方法从如图5(501)所图示的接收至少一个文件开始。一个示例方法可以确定文件是否已经被修改(503)。对于被修改的文件,提交爬取器(407)可以识别所有父文件修订(505),并且找出当前文件内容和该文件的先前修订之间的差异以追溯该文件中的每一行的起源(507)。例如,在图2所图示以及上文所讨论的示例中,在提交#4中,文件#1具有在行3上的内容“ddd”。该内容在提交#2中被引入至文件#1的行3上,因此文件#1的行3的责任数据包括对来自提交#2的文件#3的行3的引用。图3示出了包括作为行3的代表行的对修订2(提交#2),行3的引用的示例责任数据结构。

在示例责任结构中,被改变和/或添加的行可以被标示为起源并链接至它们自身。示例责任数据结构从当前的实际行映射至其起源行。起源行链接至自身。对起源行的引用可以是所引用修订处的文件修订编号和行编号的元组。因此,在如图3所图示的责任数据结构中,行3将被标示为修订2(提交#2)中的行3的起源行。

如图5所图示,未修改的行的起源可以通过追溯与该行相关联的父文件修订来确定(517)。行标识符以及该行的所确定的起源可以从父修订之一进行复制(519)。然后,该行标识符和该行的起源可以被添加至该文件的增量责任数据结构(521)。

追溯与文件行相关联的父文件修订以确定起源在一定程度上可能被涉及。如果行能够被追溯至仅一个父文件修订,则来自父文件修订的起源信息就被复制到该行。如果行可以被追溯到多个父文件修订,则可能存在责任冲突。

在存在行能够对其进行回引的两个或更多潜在的源行时,可能发生责任冲突。这些潜在源行可以来自不同的文件修订,并且在文件移动的情况下甚至可以具有不同的名称。当发生责任冲突时,可以基于时间戳选取最早提交来解决该冲突,因为该解决方案会导致分支之间的大连通。解决冲突的另一方式是使用基于提交时间戳来确定的最新近提交。此方法是版本控制系统中的缺省方法。替选地,在通过使用父标识符来解决冲突时,可以选择在该父提交列表中首先(或最后)出现的提交。每个提交(除了存储库中的最先的提交之外)至少具有一个父提交。在提交具有多个父提交时,用户可以指定父提交在提交的列表中(显式地或隐式地)的顺序。该顺序一旦被确立就不可以更改。

在图2中可以看到责任冲突的示例。文件#1的提交#4,行3。内容“ddd”可以来自提交#2或提交#3。然而,如果在冲突的情况下使用较早的提交来解决责任数据冲突,则提交#2的内容会被选择。

在一些实施例中,与父提交相比,文件的内容可能不改变,但是相关联的责任信息可能在提交之间相互不同。例如,在如图2所图示的文件#2的提交#4中,文件内容与提交#3和提交#2相比并无改变。然而,针对该提交所创建的责任层不仅仅是父提交commit#2或commit#3的副本。提交#4的行#3上的内容是“aaa”,其可能来自提交#1或提交#3。给定上文的一般规则,当发生责任冲突时,可以选取较早的提交来解决冲突,应当选择提交#1。

示例责任数据结构还可以(或者替选地)具有在责任数据结构内相同的行不可以被选择两次的规则。在这个示例中,提交#1已经被用作行1的责任起源,并且因此不应当针对行3而被选择。在责任数据数据结构内不两次选择择相同的行作为责任起源的对责任层级数据结构的限制可以防止注释被显示两次。如果相同的行在文件中被追责(引用)两次,则该行的关联注释只可以被计入(count)一次,但被示出两次。

还可能存在不同文件中的行引用相同的代表行的问题(这可能在文件被复制时发生)。例如,文件f可以从第一目录a/b被复制到第二目录a/c,从而创建第二文件g。这两个文件共享相同的代表行(源自文件f)。这两个文件可能具有完全相同的责任数据结构。如果诸如日志消息的信息被添加到文件f中,则该信息被存储在与文件g共享的责任层。该责任层行可以通过文件g可见。此外,如果任何信息被添加到文件g,则该信息将在文件f中可见。假设文件f和g是目录中的唯一文件,并且文件f中存在单个注释,则示例系统将计入目录a/的一个注释、目录a/b/的一个注释、以及目录a/c/的一个注释。在诸如a/的父目录上,根据汇总实施方式注释仅可以被示出一次,但是从一致性的角度则将预期有两个注释。

为了找到最早的起源,示例提交爬取器使用每个提交的时间戳(例如,当在分布式版本控制系统中创建提交时的时间戳)来确定在时间上最早的提交。如果相同文件修订中的两行包含相同的起源(这在融合后可能发生),则后一行将被标示为新的起源行。来自一个提交但是不同文件的两行在复制或移动之后可能指代相同的起源。在这种情况下,为了防止两个行具有相同的起源,可以采取多种方法之一。例如,文件移动可以全部被忽略。另一个示例是查找父提交之间的差异从而以了解该差异是否会向索引中带入不一致,并且维护所使用起源的集合以避免重复。一个提交的多个文件的所有被引用的行可以存储在一个集合中,以便创建所使用起源的集合。然后,可以完成简单查找以确定行是否已经被另一个文件引用。为了确定大量文件的起源行,应当创建在提交之间共享公共数据的集合实现。持久树是一个方案。然后,行以及它们的起源可以被添加到文件的责任数据结构。

虽然可以针对在提交处可见的所有文件计算责任信息,但是可能存在节省时间和存储器的可用捷径。例如,对于每个提交,可以存储从文件名到对应责任信息的指纹的映射。然后,仅对于在父提交中具有不同指纹的那些文件重新计算责任信息就足够了。此外,可以排除仅在两个分支中的一个上所接触到的文件。具有相同内容的两个文件可以具有不同的责任信息并且因此责任信息上的指纹与文件内容上的指纹相比更为不同。通过使用责任信息上的指纹,可以快速识别具有未修改内容但是具有改变的责任信息的文件。

在一个示例实施例中,可以使用标记方案来快速示出对于特定提交可见的所有行。识别文件的特定修订中的可见行的一个方式是利用所有提交散列(其标识该提交)来标示所有行,其中这些行是可见的。然后,对可见行集合的查询可以是通过该提交散列值来进行的简单过滤。然而,这种方法存在问题,特别是在存储器消耗和爬取时间的方面。每次对提交进行爬取时,都需要枚举来自该提交的所有行。该枚举可能包括未修改的行和文件。作为替代,可以创建使用较少的存储器和时间来识别特定提交中的可见行的示例标签方案。

在通过时间戳解决冲突的示例标签方案中,每个提交可以得到两个唯一标签:一个用于被添加行(+l),并且另一个用于被去除行(-l)。可以与文件的父提交之一相比来创建标签。出于标记的目的,已改变的行可以被视为被去除的行及被添加的行。例如,如图6a-6c所图示,图6a可以表示文件的父提交。可以使用图6b的代码来对于文件录入后续提交。比较图6a和6b的行4,打印语句从打印“helloworld”改变为打印“helloyou”。如图6c所图示,此提交会导致提交文件的行4的两个标签,用于去除“helloworld”打印的被去除行(-l)标签和用于添加“helloyou”打印的被添加行标签(+l)。标签可以被附加到起源行。能够看出,每个起源行包含在该起源行被引入处的提交的一个正标签以及在该起源行被删除处的后续提交的一组负标签。

对于每个提交,可以构建布尔查询表达式,其检查特定起源行是否属于该提交。递归公式可以是:isvisible(line,commit)=(isvisible(line,first_parent(commit))ornot-l(line,commit))or+l(line,commit)。此公式选取对于父提交可见的所有行,排除了当前文件修订中的所有被去除的行,并且包括在当前文件修订中新添加的行。此公式随着父提交的深度线性增长。如果提交没有使用标签(例如,没有添加行—不需要+l标签),则可以从查询中将其忽略。查询可以作为提交的元数据的一部分进行存储。

在通过时间戳解决冲突时,递归公式随着融合数目而指数增长。例如,递归公式可以是:isvisible(line,commit)=((isvisible(line,parent#1)orisvisible(line,parent#2)or...orisvisible(line,parent#n))&&not-l(line,commit))or+l(line,commit),其中n是提交的父的数目。该公式可以被表示为仅一次具有公共部分的布尔图。此图形可以随着祖先提交的数目而线性增长。

图7a-7d图示了对于图2的四个提交的示例标记。可以使用示例爬取器利用每个新的提交来对标签进行更新。如图7a所示,提交#1可以得到正标签a和负标签a。在该示例中,标签在行内容后面的圆括号中进行枚举。大写字母代表正标签,小写字母代表负标签。如果行在提交中可见,则可以使用正标签。如果行被删除,则可以使用负标签。修改可以被表示为删除以及然后的添加。满足以下布尔查询的经标记数据可以在提交#1:a处可见。

在文件#1中,所有行都可以利用标签(a)进行标记,这是因为所有行都被添加并且在根提交中是可见的。文件#2的所有行也可以利用(a)进行标记。提交#2可以具有正标签b和负标签b。由于提交#2的父是提交#1,因此对于提交#2的查询可以扩展提交#1的查询:(aand(notb))orb。提交#1的标签可以基于如图7b所图示的提交#2中的修订来变化。由于文件#1的行1在提交#2中被删除,所以行1被标记以a(在提交#1中可见)和b(在提交#2中不可见)。行2未改变,因此该行继承文件#1的行2的起源行标签。仅有起源行才得到标签。出于说明的目的,非起源行可以仅示出起源行的标签。这些标签可以被示出为加下划线。因为提交#2的行2并非起源行,所以该行从文件#1的提交#1的行2继承其标签。行3有所修改。修改可以被视为删除和添加。因此,行3的新标签可以是a、b(在提交#1中可见,但在提交#2中不可见)。新的内容可以被标记如下:行1可以利用a来标记,因为该行来自提交#1;行2可以利用b来标记,因为该行在提交#2中被添加;行3也可以利用b来标记,因为该行也在提交#2中被添加。

对于提交#2,文件#2的标签在提交#1处可能并未改变。在提交#2处的文件#2的标签可以是:行1,对于文件#2从提交#1的行1继承的a,因为该行来自提交#1;行2,b,因为该行来自提交#2;行3可以是从提交#1的行3继承的a,因为该起源行来自提交#1;并且行4可以被标记以b,因为该行在提交#2中被添加。

提交#3可以具有正标签c和负标签c。由于父提交是提交#1,因此对于提交#3的查询可以扩展对于提交#1的查询。(aand(notc))orc。如图7c所图示,提交#1处的文件#1的内容的标签变为:行1,(a,b,c),因为该行在提交#3以及提交#2中被删除;行2,a,其从提交#1的第2行所继承;以及行3,(a,b,c),因为该行在提交#3中有所改变并且修改可以被视为删除和添加。

提交#3处的文件#1的内容的标签可以是:行1,从提交#1的行1所继承的a;行2,c;行3,c;以及行4,c。提交#1处的文件#2标记可以不改变。然而,提交#3处的文件#2的标签可以是:行1,a,其从提交#1的行#1继承;行2,a,其从提交#1的行2所继承;行3,c;以及行4,c。

提交#4可以具有如图7d所示的正标签d和负标签d。提交#4可以具有两个父提交(提交#2和提交#3)。由于存在两个父提交,所以父提交查询可以被扩展如下:

1.(((aand(notb))orb)and(notd))ord

2.(((aand(notc))orc)and(notd))ord

可以根据责任策略而使用不同的查询。在大多数情况下,这两个查询应当是or(或)关系。例如,在简化之后:(((aand(notb))or(aand(notc))orborc)and(notd))ord。使用有向无环图来表达该查询,来自提交#1的公共部分可以更容易地被重复使用。针对提交#1处的文件#1的内容的标签可以不改变。提交#3处的文件#1的内容的标签可以是:行1,a,其从提交#1的行1继承;行2,c,d;行3,c,d;行4,c,其从提交#3的行4继承,如图7d所示(先前修订(提交#3)文件#1)。针对提交#2处的文件#1的内容的标签可以不发生改变。提交#4处的文件#1的当前内容的标签可以是:行1,a,其从提交#1的行1继承;行2,b,其从提交#2的行2继承;行3,b,其从提交#2的行3继承;以及行4,c,其从提交#3的行4继承。提交#1处的文件#2的标签不变。然而,提交#2处的文件#2的标签则变为:行1,a,其从提交#1的行1继承;行2,b,d;行3,a,其从提交#1的行2继承;以及行4,b,其从提交#2的行4继承。提交#3处的文件2的标签变为:行1,a,其从提交#1的行1继承;行2,a,其从提交#1的行2继承;行3,c,其从提交#3的行3继承;以及行4,c,d。最后,提交#4处的文件#2的标签为:行1,a,其从提交#1的行1继承;行2,a,其从提交#1的行2继承;行3,c,其从提交#3的行3继承;以及行4,b,其从提交#1的行4继承。提交#4的所有行都来自其它提交,并且因此标签并不被存储在提交#4中。

为了使查询更为有效率,示例标记方案可以偶尔执行主要压缩,其创建快捷标签。主要压缩可以在查询长度达到指定大小或满足某些其它准则时发生。可以在爬取期间对这些准则进行评估。在满足准则时,可以为查询存储快捷标签以使得该快捷标签可以在随后的提交中使用。满足原始查询的文件可以利用相对应的快捷标签进行更新。

这种重标记可能影响到来自各个提交的许多文件。因此,重标记可以与爬取异步进行。使用快捷标签的新的提交在异步的重标记完成之前可能无法工作。因此,长查询和短查询二者都可以被传播至提交。短的查询版本可以被保留,并且所调度查询的元组可以被跟踪。如果查询应当被评估并且其使用尚未完成的替换标签之一,则可以通过利用相对应的查询对该替换标签进行替换来扩展查询。

主要压缩可以包括找出所有长于预定义长度的查询并且构建应当利用新标签进行替换的查询集合的过程。对于集合的每个查询,枚举匹配的起源行并且将替换标签附加至它们。当压缩过程被触发并且在后续查询构造中被使用时可以引入替换标签。当爬取器遇到具有长查询的提交时,可以由提交爬取器来调度该压缩过程。该流程的优势在于压缩是确定性的并且重爬取将会创建相同的捷径。

除此之外或替选地,示例标记方案可以在使用快捷标签减少查询长度之前对它们进行预留。快捷标签可以被给予子提交。仅一个子提交能够从同一父提交继承所预留的快捷标签。这样的标签可以沿它们的传播路径对改变进行汇总,并且可以被用于缩短查询。这种方法可以将查询增长的阶从线性阶减少至对数阶。

图8中图示了标记的示例。在图8a中,显示了将提交1作为根提交的提交图。还有作为提交1的子和后代的若干其它提交。每个提交从其自己的标签以及其自己的二元决策图开始。图8b图示了提交1的二元决策图(bdd)。该bdd可以被用于查询与提交1相匹配的注释。可以沿着边从下至上对该bdd进行评估。在存在标签时,可以遵循实线箭头。在没有标签时,则可以沿虚线标签。示例方法可能仅对匹配(即1)感兴趣,因此可以跳过0标签。图8c-8e图示了提交2-4的二元决策图。对于提交5(如图8f所图示),可以通过简单地重用已经存在的节点来融合来自提交4和提交3的bdd。每个标签在图中最多存在一次,并且因此融合bdd是微不足道的。在该bdd中,可能存在非确定性,即沿两个边。当存在到达1的路径时bdd匹配。该图上存在从“-label5”到“+label3”的虚线。然而,通过沿该路径可以到达1。提交的bdd可能变得过大,如通过查询长度所确定。在发生这种情况时,可以引入能够替代提交5的当前标签使用的唯一标签,诸如“x”。该唯一标签在图8g中图示。图8h图示了提交6的标记。图8i图示了提交7的标记。在提交7中,可以使用快捷标签x而不是提交5的原始bdd。

图9a图示了与图8a相同的示例a,但其带有注释(在本示例中为docs)。每个提交都示出在该提交处可见的一组注释。在每个提交旁已经添加至该提交的注释被标记(仅出于示例目的)。例如,在提交2处,添加了对于doc2的注释。在每个边的旁边,对所连接提交之间已经被去除的注释进行标记(仅出于示例的目的)。例如,在提交2和提交3之间,已经去除了doc1的注释。在该示例中,注释可以如图9b所示进行标记。图9c图示了可以针对图9a中所示的注释进行创建的示例倒排索引。搜索索引可以创建倒排索引,其针对每个标签存储与该标签匹配的文档的有序列表。示例搜索可以检索具有查询的+标签的所有文档。可以针对这些文档评估二元决策图。例如,使用图8i的提交7,具有其相对应文档的正标签可以是图9d中所图示的标签。这些集合的并集可以是{1,2,3,4,5,6,7},并且可以对每个文档的二元决策图进行评估。

对于每个标签,搜索后端可以提供迭代器,其按顺序而遍历匹配每个标签的文档进行迭代。该搜索后端可以存储该迭代器当前正指向的文档标识符,并且可以提供前行功能(advancefunction),该前行功能将文档标识符作为输入并且将该迭代器移动至集合中不小于所提供文档标识符的下一个文档。如果下一个文档标识符小于或等于当前文档标识符,则该搜索后端可以不执行任何操作。图10中图示了迭代器类的简单示例实施方式。图11图示了用于基于迭代器来找出所有匹配文档的示例二元决策图的实施方式。

示例标签方案可以具有以下属性:标签改变的数目可以处于当前文件与其先前修订之间的差异数目的量级;任何行处的标签的数目可以处于接触特定行的提交以及与该行相关联的快捷标签的数目的量级;并且进行查询以确定行在提交处是否可见在每次主要压缩之后可以是恒定的,但是可以根据自从上一次主要压缩以来的提交图结构而随即将到来提交的数目而以线性或对数的方式增长。

示例的增量责任数据结构和标记方案在确定对于给定文件修订在给定时间应当在集成开发环境(ide)中显示哪些注释时是有用的工具。如上文所讨论的,注释可能来自多个来源,诸如静态代码分析、生产系统、拼写检查器、或协作工具,并且可以提供与代码相关的附加信息,后者对于理解代码的目的、功能、或者对于找出修改代码或修复损坏代码的方法而言可能是相关的。

在应当为特定文件版本的行创建注释时,可以在示例责任结构中找到行起源,并且该注释可以与该行起源相关联,如图12(1201-1205)所示。该注释还可以接收允许对该注释进行快速更新的唯一标识符。示例标识符可以是任何种类的指纹以便达到注释在整数空间中的随机分布。标识符可以在汇总期间被用于对解空间进行采样。

为了使注释可搜索,可以将注释置于在诸如数据库、散列表、或其它存储机制的搜索后端之中。每个注释可以从与其相关联的起源行继承所有提交标签(1205)。当ide或一些其它显示机制需要确定何时显示注释时,可以构造标签查询以经由提交标签找出与特定提交相关联的所有注释(1207)。可以向查询中添加其它过滤器。例如,搜索可以被限于特定类型的注释。可以构造标签查询以显示关于注释的汇总或概要,即在给定提交处存在多少一定类型的注释。可以通过使用标签查询找出具有与该标签查询匹配的提交标签的注释,来识别与某个提交相关联的所有注释(1209)。可以仅显示具有与标签查询准则匹配的提交标签的注释(1211)。当起源行的标签发生改变时,相关联的注释可能需要利用新的标签信息进行更新。

可以通过使用注释空间中的随机指纹进行采样来实现注释的快速聚合,直至已经找到足够的结果以向用户示出所要求的结果精度。例如,如果所有数据都在单个机器上,则文档可以以散列顺序进行迭代直至已经找到特定数目的结果,诸如1000个结果。然后,可以通过将所找到结果的数目—在该示例中为1000—除以散列空间的被搜索部分来估计结果的总数目。

数据可以在多个机器上分布,并且每个机器可以负责散列空间的闭区间。可以应用简单的流程。例如,如果存在100台机器,则每台机器可以寻找10个结果。每台机器可以返回所找到结果的数目以及所搜索的散列空间的大小。来自每台机器的结果可以被加总在一起并且可以计算出估计。如果结果的总数目明显小于指定数目,例如,如果应当找到1000个结果,但是只找到100个结果,则估计就可能不精确。为了实现更为精确的估计,可以再次开始该流程,其中每机器请求更多的结果。根据搜索后端,可以返回经汇总数值而不是搜索后端每个层处的个体注释。

该汇总还允许对来自针对任意版本运行的特定工具的注释进行追踪。不同于简单地创建新注释,示例方法可以确定注释是否自起源行处先前运行就已经存在。如果注释确实存在,则现有注释将简单地被重用,并且可能附加以来自新运行的附加数据。

如果工具产生许多注释,则可以为每个注释提供另一组标签—工具标签,并且示例方法可以确定该工具是否被执行。然后,该工具可以仅报告新的执行与先前执行之间的差异。并非新执行的一部分的每个注释可以利用对应的执行(或者在每提交只存在一个执行的情况下的提交)的(-l)标签进行标示,并且每个新的注释可以用(+l)标签进行标示。按照与针对提交的(label,query)配对的构造相同的方式(基于一个父提交),可以从之前的执行来构建新执行的(tool_label,tool_query)配对。对于执行的注释进行搜索可以包括简单地搜索注释的新标签集合上的特定(tool_label,tool_query)配对。针对另一个提交处的特定执行的注释的搜索可以简单地利用对应执行的(tool_label,tool_query)配对以及在该处应当对注释进行搜索的提交的(label,query)配对而对搜索加以限制。这种类型的搜索是有用的,因为工具可以覆盖一些提交,但并非全部的提交,并且示例实施例可能想要显示与未覆盖提交最为接近的结果。第二(tool_label,tool_query)配对可以来自定义在结构上类似于该提交图的线性图或有向无环图的执行。

所构思的索引可以使得对提交和/或执行之间的注释的交集、差集、和并集进行有效率的计算。在软件开发的情况下,这些种类的计算可能在分析生产问题时有所帮助。例如,可以为部署期间所发生的每个日志输出添加注释。这些注释可以自动示出在软件工程师尝试修复问题的开发分支上。此外,可以获得关于项目的日志语句数目或者两次部署之间出现的差异的统计数据。

另一个用例可能是代码评论,其中针对某些快照工具识别出潜在的编程错误。利用示例系统,在工具尚未运行的情况下,可以在稍后的快照处有效率地使注释可见。此外,可以有效率地针对整个存储库而随时间对这些注释进行追踪,以便给出关于代码健康的一些指示。注释可以仅针对稍后的提交而不是先前版本可见。注释可以会被标记为已解决以用于后续提交。即使行已经被修改或删除也可以对注释进行跟踪。例如,用户评论不应当在没有用户交互的情况下消失。

图13是被配置用于跨源代码文件修订来显示注释的示例性计算机(1300)的高级框图。在非常基本的配置(1301)中,计算设备(1300)通常包括一个或多个处理器(1310)和系统存储器(1320)。存储器总线(1330)可以被用于在处理器(1310)和系统存储器(1320)之间通信。

根据所期望的配置,处理器(1310)可以为任何类型,包括但不局限于微处理器(μp)、微控制器(μc)、数字信号处理器(dsp)或者它们的任意组合。处理器(1310)可以包括诸如一级高速缓存(1311)和二级高速缓存(1312)、处理器核心(1313)和寄存器(1314)的一个或多个级别的高速缓存。处理器核心(1313)可以包括算术逻辑单元(alu)、浮点单元(fpu)、数字信号处理核心(dsp核心)、或者它们的任何组合。存储器控制器(1316)也可以与处理器(1310)一起使用,或者在一些实施方式中,存储器控制器(1315)可以是处理器(1310)的内部部分。

根据所期望的配置,系统存储器(1320)可以是任何类型,包括但不局限于易失性存储器(诸如ram)、非易失性存储器(诸如rom、闪存等)、或者它们的任何组合。系统存储器(1320)通常包括操作系统(1321)、一个或多个应用(1322)、和程序数据(1324)。应用(1322)可以包括用于跨源代码文件修订显示注释的系统。程序数据(1324)包括存储指令,其在被一个或多个处理设备执行时实现用于创建增量责任数据结构和/或标记方案的系统和方法(1323)。在一些实施例中,应用(1322)可以被布置来与操作系统(1321)上的程序数据(1324)一起操作。

计算设备(1300)可以具有附加的特征或功能、以及附加的接口,以促进基本配置(1301)与任何所需设备和接口之间的通信。

系统存储器(1320)是计算机存储介质的示例。计算机存储介质包括但不局限于:ram、rom、eeprom、闪存或其它存储器技术,cd-rom、数字多功能盘(dvd)、或其它光学存储器,磁带盒、磁带、磁盘存储器或其它磁存储设备,或者可以被用于存储所期望信息并且可以由计算设备1300进行访问的任何其它介质。任何这样的计算机存储介质都可以是设备(1300)的一部分。

计算设备(1300)可以被实现为小封装技术(small-formfactor)便携式(或移动)电子设备的一部分,诸如蜂窝电话、智能电话、个人数字助理(pda)、个人媒体播放器设备、平板计算机(平板)、无线网络手表设备、个人头戴式送受话器设备、专用设备,或者包括上述功能中的任何一个的混合设备。计算设备(1300)还可以被实现为包括膝上型计算机和非膝上型计算机配置二者的个人计算机。

以上详细描述已经通过使用框图、流程图、和/或示例阐述了设备和/或过程的各种实施例。在这样的框图、流程图、和/或示例包含一个或多个功能和/或操作的情况下,本领域技术人员将理解,能够单独地和/或共同地通过广泛多种硬件、软件、固件、或几乎它们的任何组合来实现这样的框图、流程图、或示例中的每个功能和/或操作。在一个实施例中,本文所描述主题的若干部分可以经由专用集成电路(asic)、现场可编程门阵列(fpga)、数字信号处理器(dsp)、或者其它整合的格式来实现。然而,本领域技术人员将认识到,这里所公开的实施例的一些方面可以全部或部分等效地以集成电路被实现为在一个或多个计算机上运行的一个或多个计算机程序、在一个或多个处理器上运行的一个或多个计算机程序、固件、或者实几乎它们的任何组合,并且根据本公开,设计和/或编写该软件和/或固件的代码将完全在本领域技术人员的技能范围之内。此外,本领域技术人员将理解的是,本文所描述主题的机制能够作为程序产品以各种形式进行分发,并且无论被用来实际执行该分发的非瞬态信号承载介质的特定类型如何,本文所描述主题的说明性实施例都适用。非瞬时信号承载介质的示例包括但并不局限于以下:可记录型介质,诸如软盘、硬盘驱动器、压缩盘(cd)、数字视频盘(dvd)、数字磁带、计算机存储器等;以及诸如数字和/或模拟通信介质(例如,光纤电缆、波导、有线通信链路、无线通信链路等)的传输介质。

关于本文对基本上任何复数和/或单数术语的使用,只要适于场境(context)和/或应用,本领域技术人员就能够将复数转化为单数和/或将单数转化为复数。为了清楚起见,这里可以明确阐述各种单数/复数的排列组合。

因此,已经描述了主题的特定实施例。其它实施例处于所附权利要求书的范围之内。在一些情况下,权利要求中所记载的动作可以以不同的顺序执行而仍然达到所需的结果。此外,附图中所描绘的过程不一定要求所示出的特定顺次序或连续顺序来达到所期望的结果。在某些实施方式中,多任务和并行处理可能是有利的。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1