Following system colour scheme - Python 增强提案 Selected dark colour scheme - Python 增强提案 Selected light colour scheme - Python 增强提案

Python 增强提案

PEP 385 – 从 Subversion 迁移到 Mercurial

作者:
Dirkjan Ochtman <dirkjan at ochtman.nl>, Antoine Pitrou <solipsis at pitrou.net>, Georg Brandl <georg at python.org>
状态:
最终版
类型:
流程
创建日期:
2009年5月25日

目录

动机

在决定切换到 Mercurial DVCS 之后,实际的迁移工作仍需进行。对于像 Python 这样大型分布式项目的版本控制系统这种重要的基础设施而言,这是一项艰巨的任务。本 PEP 旨在描述必须采取的步骤以供进一步讨论。它与 PEP 347 有些类似,该 PEP 讨论了向 SVN 的迁移。

为了充分利用 hg,我们希望进行高保真转换,以便 (a) 尽可能多地保留 svn 元数据,并且 (b) 所有元数据都转换为 Mercurial 中常见的格式。这样,为 Mercurial 编写的工具可以得到最佳利用。为了做到这一点,我们希望使用 hgsubversion 软件进行初步转换。这个 hg 扩展专注于提供高质量的 Subversion 到 Mercurial 转换,用于双向通信,这意味着它不会像其他解决方案那样丢弃大量可用元数据。

这样的转换似乎也是重新审视仓库内容并确定某些内容是否仍然有价值的好时机。本着这种精神,以下各节还提议丢弃一些较旧的元数据。

时间线

当前的转换里程碑时间表

  • 2011-02-24:在 hg.python.org 提供测试仓库

    将允许(并鼓励)所有 Subversion 仓库的提交者进行测试提交。一旦最终转换完成,测试仓库和所有测试提交都将被删除。服务器端钩子将安装在测试仓库中,以测试 buildbot、diff-email 和空格检查集成。

  • 2011-03-05:最终转换(暂定)

    将阻止向当前在 Mercurial 中维护的 Subversion 分支进行提交。开发人员应避免推送到 Mercurial 仓库,直到所有基础设施在切换到新仓库后都能正常工作。

过渡计划

分支策略

Mercurial 有两种基本的分支使用方式:克隆分支,每个分支都保存在一个单独的仓库中;以及命名分支,每个修订版本都保留元数据以记录其所属的分支。前者更容易区分分支,但代价是客户端需要更多的磁盘空间。后者使得在分支之间切换更容易,但所有分支名称都是历史的持久部分。[1]

命名分支和克隆分支之间的区别

  • 不同(维护)克隆中的标签在本地克隆中不可用
  • 带有命名分支的克隆将更大,因为它们包含更多数据

我们建议将命名分支用于发布分支,并将克隆分支用于特性分支。

历史管理

为了最大程度地减少由于转换造成的信息丢失,我们建议提供几个仓库作为转换结果

  • 一个修剪到主线主干(和 py3k)以及过去和现在维护分支的仓库——这被称为“工作”仓库,是开发继续进行的地方。该仓库包含开发工作所需的所有历史记录,包括用可追溯到 1990 年的更改注释源文件以及其他常见的历史挖掘操作。

    该仓库中的 default 分支是 Subversion 中所知的 py3k,而 Subversion 主干则以分支名称 legacy-trunk 存在;但在 Mercurial 中,此分支将被关闭。发布分支以其主要.次要版本命名,例如 3.2

  • 一个包含 Subversion 仓库(实际上是其 /python 子目录)的完整、未编辑转换的仓库——这被称为“历史”或“存档”仓库,并将作为只读资源提供。[2]
  • 每个活跃特性分支一个额外的仓库;“活跃”意味着至少有一位核心开发人员要求提供该分支。每个这样的仓库将包含特性分支以及主线中的所有祖先变更集(来自 SVN 中的 trunk 和/或 py3k)。

由于所有分支都存在于历史仓库中,因此如果证明有必要,它们可以在任何时候作为单独的仓库提取。

SVN 修订号、Mercurial 变更集和 SVN 分支名称之间的最终修订映射将以文件形式存储在 Misc 目录中。其格式如下:

[...]
88483 e65daae6cf4499a0863cb7645109a4798c28d83e issue10276-snowleopard
88484 835cb57abffeceaff0d85c2a3aa0625458dd3e31 py3k
88485 d880f9d8492f597a030772c7485a34aadb6c4ece release32-maint
88486 0c431b8c22f5dbeb591414c154acb7890c1809df py3k
88487 82cda1f21396bbd10db8083ea20146d296cb630b release32-maint
88488 8174d00d07972d6f109ed57efca8273a4d59302c release27-maint
[...]

转换标签

SVN 标签目录包含许多旧内容。其中一些实际上并不是完整的标签,只包含仓库的一个较小子集。所有发布标签都将保留;其他标签将根据开发人员社区的请求包含在内。我们建议使标签命名方案保持一致,采用这种样式:v3.2.1a2

作者映射

为了以 hg 中常见的用户名方式(以“First Last <user@example.org>”格式)提供用户名,我们需要一个作者映射,将 cvs 和 svn 用户名映射到真实姓名及其电子邮件地址。我们在迁移工具仓库中有一个该映射的完整版本(不公开访问以避免地址泄露给采集者)。其中的电子邮件地址可能已过期;这必然会发生,尽管尝试让尽可能多的人审阅它以查找过期的地址会很好。当前版本似乎仍然包含一些编码问题。

生成 .hgignore

Mercurial 仓库可以使用 .hgignore 文件来帮助忽略不符合版本控制的文件。它通过采用多种可能的模式匹配形式来实现这一点。当前的 Python 仓库已经包含一个基本的 .hgignore 文件,以帮助使用 hg 镜像。

由于当前的 Python 仓库已经包含一个 .hgignore 文件(用于 hg 镜像),我们将直接使用它。生成文件的完整历史记录曾被讨论,但被认为不切实际(因为它相对困难且收益甚微,因为对于较旧的修订版本,忽略的重要性较低)。

仓库大小

当前 Python 仓库的裸转换结果重达 1.9 GB;尽管这比 Subversion 仓库(2.7 GB)小,但仍不可行。

通过对工作仓库进行修剪,以及通过一种称为“revlog reordering”的进程,该进程能非常有效地优化内部 Mercurial 存储的布局,仓库大小变得更易于管理。

经过所有优化后,工作仓库在磁盘上的大小约为 180 MB。克隆时通过网络传输的数据量估计约为 80 MB。

其他仓库

svn.python.org 的“projects”仓库中托管着许多其他项目。“peps”目录将与主要的 Python 目录一起转换。Richard Tew 表示他希望 Stackless 仓库也能被转换。svn.python.org 仓库中的其他哪些项目应该被转换?

现在已经初步尝试转换 Jython 仓库。不幸的是,hgsubversion 的当前版本在某个时候失败了。正在调查中。

其他希望转换为 Mercurial 的仓库可以在主 Python 迁移完成后通知我,我将处理他们的需求。

基础设施

hg-ssh

开发人员应该通过 ssh 访问仓库,类似于当前的设置。可以使用公共密钥授予人员访问共享 hg@ 帐户的权限。还在 hg.python.org 设置了一个 hgwebdir 实例,以便于浏览和只读访问。它已配置为开发人员可以轻松启动新的克隆(用于从单独仓库开发中受益的长期功能)。

此外,核心开发人员可以直接创建公共仓库,尽管尚未决定将强制执行哪种命名方案

$ hg init ssh://hg@hg.python.org/sandbox/mywork
repo created, public URL is http://hg.python.org/sandbox/mywork

钩子

目前正在使用许多钩子。应该开发和部署这些钩子的 hg 等效项。正在使用以下钩子:

  • 检查空格:一个钩子,用于在空格不符合 Python 代码库规则时拒绝提交。在一个变更组中,只检查头部(这允许清理从第三方仓库拉取的更改的提交)。我们还可以提供一个空格钩子,供客户端仓库使用;它可以警告空格问题和/或截断更改行中的尾随空格。
  • 推送邮件:邮件将包含推送到公共仓库的每个变更集的差异,包括推送变更集的用户名(这不一定与变更集中记录的作者相同)。
  • buildbots:python.org 构建主站将收到推送到 cpython 仓库的每个变更集的通知,并将为变更集所在的分支上的每个构建从站触发适当的构建。

钩子仓库包含这些服务器端钩子到 Mercurial 的移植,以及一些额外的钩子:

  • 检查分支头:一个钩子,用于拒绝在现有分支上创建新头的推送。推送者必须合并多余的头并再次尝试推送。
  • 检查分支:一个钩子,用于拒绝所有不在允许的命名分支上的变更集。当我们想要创建新的维护分支时,必须更新此钩子的白名单。
  • 检查行尾:一个基于 eol 扩展 的钩子,用于拒绝所有提交错误行尾文件的变更集。然后必须剥离并重做提交,可能在提交者的计算机上启用 eol 扩展

一个额外的钩子可能是有益的

  • 检查贡献者:在当前设置中,所有变更集都带有提交者的用户名,他们必须已签署贡献者协议。如果我们保留已注册贡献者的列表,我们可能希望使用钩子来检查提交者是否是贡献者。然后,该钩子可能会警告推送包含来自未知贡献者的变更集的用户。

行尾转换

关于 Mercurial 中缺少行尾转换支持的讨论,最初由 win32text 扩展提供,导致开发了新的 eol 扩展,该扩展支持按文件进行版本化管理行尾约定,类似于 Subversion 的 svn:eol-style 属性。此信息保存在名为 .hgeol 的版本化文件中,并且此文件已签入 Subversion 仓库。

服务器端还存在一个钩子,用于拒绝任何引入不一致换行数据的变更集(参见上文)。

hgwebdir

应设置一个或多或少标准的 hgwebdir 安装。我们可能希望想出一种与 Python 网站匹配的样式。

已经编写了一个小型 WSGI 应用程序,可以查找 Subversion 修订版并重定向到给定变更集的相应 hgweb 页面,无论转换后的修订版最终在哪一个仓库中(因为一个大型 Subversion 仓库被转换为几个 Mercurial 仓库)。它还可以通过其十六进制 ID 查找 Mercurial 变更集。

roundup

通过将 Roundup 指向上面提到的查找脚本的 URL,指向 SVN 修订版的链接将继续有效,并且还可以创建指向 Mercurial 变更集的链接,而无需提供仓库 *和* 变更集 ID。

迁移后

代码获取位置

迁移后,hgwebdir 将位于 hg.python.org。这是许多组织接受的标准,也是 svn.python.org 的一个简单并行。例如,工作仓库可能位于 http://hg.python.org/cpython/,而存档仓库位于 http://hg.python.org/cpython-archive/。对于写入访问,开发人员将不得不使用 ssh,例如 ssh://hg@hg.python.org/cpython/

code.python.org 也曾被提议作为主机名。我们认为在主机名中使用 VCS 名称很好,因为它能避免混淆:应该清楚,您不能将 svn 或 bzr 用于 hg.python.org。

hgwebdir 已经可以为每个变更集提供 tarball。这使得每天的快照不再必要;我们可以直接将用户指向 tip.tar.gz,这意味着他们将获得最新版本。如果需要,我们甚至可以使用 buildbot 结果指向最后一个好的变更集。

Python 特有文档

hg 附带了良好的内置文档(可通过 hg help 获得)以及一个充满有用信息和技巧的 wiki,更不用说一本受欢迎的 书籍(可在线阅读)。

除此之外,最近大修过的 Python 开发人员指南 已经有一个分支包含了 Mercurial 而非 Subversion 的说明;该分支的在线 构建 也已可用。

提议的工作流程

我们提出两种工作流程,用于在几个分支之间迁移补丁。

对于 2.x 或 3.x 分支内部的迁移,我们建议补丁始终首先提交到它适用的最旧分支。然后,可以使用 hg merge 将生成的变更集合并到该系列(2.x 或 3.x)中的所有较新分支。如果它不能按原样应用于较新的分支,可以使用 hg revert 轻松回溯到新分支的原始头部,然后打上补丁的替代版本(如果它不适用,则不打补丁),然后提交合并。前提是系列中较旧分支的所有变更集最终都合并到系列中所有较新的分支。

这样做的好处是它提供了最无痛的合并过程。这意味着在一般情况下,人们在实际应用补丁之前,必须考虑补丁应该应用于的最旧分支。通常,这只有两个分支:最新的维护分支和主干,除了适用于旧分支的仅限安全修复模式下的安全修复。

对于将 3.x 中的错误修复合并到 2.7 维护分支(2.6 和 2.5 处于仅安全修复模式,它们的维护将继续在 Subversion 仓库中),变更集应以其他方式移植(而非合并)。transplant 扩展、import/export 和 bundle/unbundle 在这里同样有效。

选择这种方法使得 3.x 不必携带所有 2.x 分支以来的历史记录,这意味着克隆不会那么大,合并也不会那么复杂。

Subversion 的未来

迁移后 Subversion 仓库会怎样?由于 svn 服务器包含许多仓库,而不仅仅是 CPython 仓库,因此它可能会持续一段时间,因为并非所有项目都希望迁移,或者其他项目需要更长时间才能迁移。为了防止人们滞后,我们可能希望将已迁移的项目从仓库移动到一个新的、只读的、具有新名称的仓库。

构建识别

Python 目前提供 sys.subversion 元组,允许 Python 代码准确找出它正在运行的 Python 版本。当前版本看起来像这样:

  • ('CPython', 'tags/r262', '71600')
  • ('CPython', 'trunk', '73128M')

C API 中的 Py_GetBuildInfo() 返回另一个值,并作为 sys.version 的一部分可供 Python 代码使用

  • 'r262:71600, Jun 2 2009, 09:58:33'
  • 'trunk:73128M, Jun 2 2009, 01:24:14'

我建议修订标识符将是 hg 修订哈希的短版本,例如“dd3ebf81af43”,如果构建它的工作目录已被修改,则附加“+”(而不是“M”)。这反映了 hg id 命令的输出,该命令旨在用于此类用途。sys.subversion 值也将重命名为 sys.mercurial,以反映 VCS 的更改。

对于标签/分支标识符,我建议 hg 将检查当前检出修订版上的标签,如果存在标签则使用标签(“tip”不计算在内),否则使用分支名称。sys.subversion 变为

  • ('CPython', 'v2.6.2', 'dd3ebf81af43')
  • ('CPython', 'default', 'af694c6a888c+')

构建信息字符串变为

  • 'v2.6.2:dd3ebf81af43, Jun 2 2009, 09:58:33'
  • 'default:af694c6a888c+, Jun 2 2009, 01:24:14'

这反映了 hg 中的默认分支名为“default”,而不是 Subversion 的“trunk”,并反映了提议的新标签格式。

Mercurial 还允许找出最新的标签以及当前变更集与该标签之间的变更集数量,从而生成描述性版本字符串

$ hg parent --template "{latesttag}+{latesttagdistance}-{node|short}\n"
v3.2+37-4b5d0d260e72
$ hg up 2.7
3316 files updated, 0 files merged, 379 files removed, 0 files unresolved
$ hg parent --template "{latesttag}+{latesttagdistance}-{node|short}\n"
v2.7.1+216-9619d21d8198

脚注


来源:https://github.com/python/peps/blob/main/peps/pep-0385.rst

最后修改:2025-02-01 08:59:27 GMT