跳转至

拉取请求文件修订

在自身不保存已查看文件记录的主机上,此环境保存标记并询问主机每个被标记文件的版本,以便推送能够将已清除的文件报告为已更改。该版本在四层之间传递,每一层中缺失条目都意味着不同的含义。没有类型能区分这些含义,也没有单个文件能说明整条路径,这正是本页的用途。

这个失败是有记录而非假设的。上面 GitLab 的 getFileRevisions 的接口文档曾与底层代码描述相反,因为它按照下一层的含义来描述缺失的路径。任何基于那种理解编写的内容,都会把主机拒绝提供的版本当作变更请求删除的文件,从而将读者已清除的每个文件都报告为已更改,而这一切发生在一个 Token 无法看到的项目中。

缺失在提供者边界处含义改变

在边界之下,在补丁解析器或响应解码器中,缺失的路径意味着该修订版本不携带那个文件。在边界之上,在 ProviderFileRevisions 中,缺失的路径意味着读取无法给出答案。提供者的 getFileRevisions 在向上传递时进行转换:主机查看过但没有任何版本的路径以空字符串的形式到达,而缺失则保留给提供者从未有机会查看的内容。边界之下的缺失不会越过边界。

"从未有机会查看"的内容属于主机,契约无法知道其中任何一个:

  • Azure DevOps 从一次迭代列表中读取所有版本,因此一个过长的变更无法跟踪到结尾时,超出该点的路径就会被遗漏。
  • Bitbucket 从拉取请求自身的补丁中读取这些版本,这是它唯一声明文件版本的地方,因此在字节上限处被截断的补丁会使截断之后的路径被遗漏。
  • GitLab 分批询问,因此一个无法读取的批次会遗漏该批次中的路径。

这三个事实只属于各自的提供者。契约只声明缺失意味着读取无法给出答案,这就是提供者必须转换到的那一侧。

三种空值,空字符串不在其中

空字符串是一个答案:主机查看过,而 HEAD 没有版本,被删除的文件就处于这种状态。它与带有该值戳记的标记比较相等,因此针对删除所做的标记会被清除一次,并一直保持清除状态。下面的所有内容都是答案的缺失,而这三种形式不可互换。

空映射来自服务对整个范围的读取,它使这些标记失去时效感知。它们仍然报告为已清除,但不再感知推送。这种情况发生在提供者根本不提供 getFileRevisions 时,并且在这两条路径上,当调用失败并被记录日志时也是如此。没有得到答案的标记操作不会拒绝读者的勾选:它存储了没有基线的标记,这就是下面的第三种形式。

路径在已应答的映射中缺失是逐路径的情况,也是绝不能解读为删除的那种情况。HeldFileRevisions 既记录它所询问的内容,也记录它所听到的内容,因此缺失的路径会保留之前为它给出的最后一个版本,而不是失去一个。

存储标记上的空值是第三种,也是此环境唯一自行制造的一种。PullRequestFileViewedMark 将 revision 存储为可空,因此对于一个路径没有得到答案的标记操作可以完全不存储基线。如果改为存储空字符串,那么一旦主机最终被发现有版本,文件就会被报告为已更改。没有基线的标记读取为已清除,直到读者再次标记它。

在写入路径上,读取端的两种空值都会归结为第三种形式:无论映射是空,还是路径只是从映射中缺失,标记操作都会存储一个没有基线的标记。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 t3/t3code