使用 CVS
此页面包含历史信息或已弃用的文章。
警告:PostgreSQL 主存储库现已切换为使用 Git,而非 CVS。虽然仍可以通过 CVS 获取存储库的副本,但开发工作和修补程序的生成应与 Git 合作。
本地 CVS 存储库的重要性
破解 PostgreSQL 的关键之一是处理 CVS。CVS 负责跟踪两件事:源代码和修订历史记录。根据其结构,修订信息存储在名为 CVS 的目录中,与文件本身位于同一目录之下。在使用诸如 rsync 或 CVSup 等工具制作自己的完整本地副本时,主要目标通常是能够进行诸如差异化等操作,以查看本地更改,而无需依赖主存储库。但您还可以再现用于构建代码的开发过程。您将拥有执行各种任务所需的所有修订历史记录,例如检查应用的各个修补程序或还原到 PostgreSQL 代码的早期版本。
问题在于,对于对代码进行的更改,该怎么做并不完全明确。您不能只是将您的修订历史记录放入主存储库的副本中,因为在您下次同步时,您的本地更改将被清除——被对官方源代码所做的更改替换掉。而且您不能只忽略主存储库。在您完成修改后,所涉及的代码可能已在您下方移动,从而强制在您的修补程序能够被其他人使用之前对这两个更改集进行协调(“合并”)。
开发人员使用各种技术进行自己的本地开发,同时关注对主存储库所做的更改。此页面收集了一些流行的方法和配方,用于成功管理此问题。
复杂的本地提交
使用中心仓库的项目面临的一个基本问题是如何处理在开发人员系统中进行的复杂工作。开发人员执行的本地工作会产生一个 diff 文件,可以作为补丁应用。如果代码相当直观、自包含且完整,那么该开发模型就能正常工作。此方法有两种类型的失效情况。第一种是当补丁与其他正在执行的工作相冲突时,因此必须将两组代码进行某种合并。另一种困难的情况是只有补丁的一部分得到应用,也许是因为其中有好的想法,但其他部分仍需要解决。有时,明显的新开发从开始时就分解成逻辑部分,但按照这种方式进行构建并非易事。
从最近的一些开发中挑选一个实际示例,假设您有一段代码对 PostgreSQL 内部组件进行检测,然后将此信息公开到其中一个 pg_statXXX 视图中。此代码可能非常复杂,但完全独立且易于应用。在此基础上,您可能还要构建一项有争议的调整功能,它使用收集的数据来完成不太可能被接受(甚至是工作!)的功能。
此处的实际编码流程会如下所示
- HEAD -> diff A -> 仪检测功能 -> diff B -> 调整功能
执行此工作并最终生成一个包含 diff A 的补丁相对简单,而第二个补丁包含 diff A+B。但是,如果没有办法在提交点处中止,则很难只能获取 diff B。虽然在 PostgreSQL CVS 模型的范围内有一些简单的解决方法,但如果您发现 diff A 中存在一个 bug,并且只能在深入涉及 B 之后才能修复,那么您仍会遇到麻烦。您可能会轻易陷入这样的境地:处理此问题的唯一简单方法是保存两个 diff,回滚到原始仓库,重新应用 diff A,解决问题,生成一个新的 diff A-2,重新应用 B,合并与 A-2 相关的冲突,然后生成新的 B-2。
如您所想,此操作比应有的要复杂,但是此类场景对于基于 CVS 的开发而言很常见。
一般 CVS 信息
有一份关于 CVS 的大型手册和免费书籍
- 并发版本控制系统手册:因其作者而俗称“Cederqvist”。
- 使用 CVS 进行开源开发
如需快速入门,请改读以下其中一页
CVS+rsync 解决方案
如果您希望能够快速为代码更改生成 diff,则拥有本地 CVS 仓库必不可少。它还允许脱机工作。
通过 rsync 的完整存储库、签出区域中的局部变更
如果你想要一个包含修订历史的 PostgreSQL 存储库副本,为了开发或测试新代码,你需要签出一个副本然后在该区域工作。对于参与 PostgreSQL 提交过程的开发人员而言,这是流行的工作方法,因为它可以轻松监控其他人对主树所做的工作。
初始设置
可以使用单行 rsync 命令复制存储库。此处我们假设 $HOME 是你的主目录,并且那里有一个名为 pgrepo 的目录, 要在其中存储你的完整存储库的本地副本
export CVSROOT=$HOME/pgrepo rsync --progress -avzCH --delete anoncvs.postgresql.org::pgsql-cvs $CVSROOT
在开始编写新内容时,签出一个目录树的新副本并从中进行工作。这里建议的结构是为每个项目创建一个以其命名的目录;我们在此假设此名称仅为“project”。以下是如何将该项目的代码副本签入有用的构建环境,然后编译、构建和使用该副本的完整示例。(注意:它假设 $CVSROOT 已如上所述定义。)
$ cd ~ ~/$ mkdir project ~/$ cd project ~/project$ cvs co pgsql # could do "cvs co -d pgsql.project pgsql" instead of these two lines ~/project$ mv pgsql pgsql.project ~/project$ cd pgsql.project ~/project/pgsql.project$ cvs update -dP ~/project/pgsql.project$ ./configure --prefix=$HOME/project --enable-depend --enable-cassert --enable-debug ~/project/pgsql.project$ make ~/project/pgsql.project$ make install ~/project/pgsql.project$ export PGDATA=<your database directory> ~/project/pgsql.project$ export PATH=$HOME/project/bin:$PATH ~/project/pgsql.project$ initdb ~/project/pgsql.project$ pg_ctl start ~/project/pgsql.project$ psql
请注意,可以在第一次签出的 cvs update 中简化语法,但养成好习惯只使用与最终用于保持其内容最新的完全相同的行。将 pgsql 重命名为 pgsql.project 的原因在于,你可以区分你遇到的随机 diff 补丁来自哪个项目;如果你同时启动多个项目,你将意识到这有多重要。
- 警告:enable-cassert 和 enable-debug 标志将帮助你发现你的代码中的问题,但使用这些参数构建的 PostgreSQL 副本将比不使用这些参数构建的副本慢得多。如果你正在从事与性能相关的工作,请务必在测试执行速度之前不使用这些标志进行构建。你可以在服务器启动时通过在 postgresql.conf 中输入 debug_assertions = false 来关闭断言测试(较大的减速因素)。有关该设置的更多详细信息,请参见 开发者选项;在使用 --enable-cassert 进行构建时,默认为 true。
- 如果你对已经构建了早期版本的树进行更新,则在某些条件下,你将无法获得完全正确的构建。建议的做法是确保你已删除所有构建成品,即在使用“cvs update”重新与更新的存储库同步之前,在你的项目目录中执行“make distclean”。
一种使 CVS 默认为正确行为的方法是在你的主目录中设置一个 .cvsrc 文件。下面是一个带有该工作的良好默认值的示例。如果你仅在本地使用 CVS,则可能不需要“-z3” ,例如,如果你正在使用 rsync 维护本地副本
cvs -z3 update -d -P checkout -P diff -c
使用此项目环境
设置此环境后,您下次重新登录时,您可以切换到使用此子集。一种好的技术方法是将这些行作为脚本放在每个项目的目录根目录中。这是一个示例会话,显示了一个执行此操作的脚本以及如何使用它。
~/project/pgsql.project$ cat setup #!/bin/bash export CVSROOT=$HOME/cvsrepo export PATH=$HOME/project/bin:$PATH export PGDATA=<your database directory> if [ ! -f "$PGDATA/postmaster.pid" ] ; then pg_ctl start fi ~/project/pgsql.project $ source ./setup server starting ~/project/pgsql.project $
跟踪本地更改
对于原始版本控制,您可以在任何重大更改后进行差异比较。
~/project/pgsql.project$ cvs diff -cN > project-1.patch
最后一个数字是修订号,每次进行差异比较后加一。
由于您在这里操作自己主存储库的个人副本,因此实际上可以将这些更改提交到自己的本地目录树中(如果您只是签出树的一个副本而不是使用 rsync,这是不可能的)。这使得为分阶段执行的复杂工作生成差异更轻松——在不执行此类操作的情况下,很难在分阶段处理代码时获得增量差异。您甚至可以使用 CVS 的标记功能来简化管理。
这里的问题是,一旦您针对主存储库重新同步,您所有的本地提交、标记或分支信息都会被清除。您只能将这些提交视为临时提交,如果您想要保留更改,则必须手动保存实际差异信息副本。
对于长期运行的项目,某些喜欢此方法的人会保存自己所做更改的增量差异的快照,针对主存储库重新同步,然后使用补丁实用程序再次“重新播放”这些差异,在每次补丁后重复提交,并在某些点处进行标记。这是重建下方“第三方源”方法解决的一些功能的手动方法,同时仍然为主存储库保留一个完整副本。对于不希望或不需要经常与 PostgreSQL HEAD 同步的人来说,此方法是最理想的。
更新存储库和项目副本
~/$ rsync --progress -avzCH --delete anoncvs.postgresql.org::pgsql-cvs $CVSHOME ~/$ cd $HOME/project/pgsql.project ~/project/pgsql.project$ cvs update -dP
仅通过 rsync 从存储库中获取源代码,将本地更改放入分支
如果您真的很不在乎对主存储库所做的具体更改,只想与之保持最新状态,让您自己的补丁始终针对当前 CVS HEAD 发挥作用,那么还有一种替代方法可以使用 CVS 和 rsync。在此方法中,您自己的 CVS 存储库成为主要工作区域。您的 CVS 树不是复制整个主存储库,而是复制 PostgreSQL CVS HEAD 作为主干,而您自己的所有更改都发生在分支中。
在这里,您可以定期仅复制主存储库中的源代码(具体来说,忽略其修订历史记录而优先考虑您自己的修订记录),偶尔将这些更改签入主干。
此方法的主要优点在于它能为您自行进行的更改提供非常强大的版本控制。使用另一种基于 rsync 的方法,生成和管理补丁 diff 的过程更多的是一个手动过程。对于在部分中应用的相对常见开发补丁任务,它尤其不合适。
如果本地编码是您的主要目标,有一系列技术可以在执行此操作的同时与主存储库保持同步。这称为管理或跟踪第三方源。在这种情况下,PostgreSQL 存储库将被视为您希望在自定义的同时跟踪的“供应商”代码。
更多信息的链接
- 跟踪第三方源
- 跟踪第三方源(供应商分支)
- 使用 CVS 管理第三方源代码
- 了解更多关于 CVS的内容具有一个复杂的结构图示例
- 使用 CVS 跟踪第三方源的机制和方法
- 如何管理 PostgreSQL CVS 分支?
- CVS 中的 Linux Kernel 源
使用其他版本控制系统,同步整个存储库
扩展上一部分,一旦您理解了您对 PostgreSQL 源代码的检出是仅更新本地开发树的主干这一想法,那么您不再需要使用 CVS 处理的本地开发。例如,您可以轻松地使用 Subversion 托管所有本地代码,使用标准 Subversion 主干/分支/标签目录结构进行组织,并像这样操作
- 将本地主干副本检出到工作目录中
- 使用 rsync 来进行更新以匹配当前的 PostgreSQL 存储库。您甚至不必忽略 CVS 文件,因为 Subversion 不会使用它们
- 运行 svn status 或一些其他处理已添加文件的进程
- svn commit 此更新到主干
- svn update 您其他副本并根据需要合并更改
- svn checkout 您用于您自己开发的分支,对它进行修改。将树的副本创建到标签目录结构的有用部分断点中。
- 完成之后,svn diff --diff-cmd /usr/bin/diff -x '-cN' 生成正确格式的 diff。
使用这种方法,您甚至不会丢失跟踪存储库历史所需的 CVS 信息;只需将 CVSROOT 指向主干的本地检出,您可以运行 cvs 对其进行查看。
Subversion 没有什么特别之处,其他系统也同样适用。例如,您可以将 Git 用于本地存储库,利用其对本地分支的所有支持,然后仅使用 cg-update 将当前活动分支与 PostgreSQL CVS 存储库同步。
pgbuildfarm HOWTO 中的 rsync 注释
一旦其所有有用的见解合并到其他部分,此部分应被删除
首先,我建立了一个存储库位置,并获取了初始存储库副本
mkdir -p /home/cvsmirror/pg rsync -avzCH --delete anoncvs.postgresql.org::pgsql-cvs /home/cvsmirror/pg
然后删除 sup 目录并设置 rsync 排除文件
rm -rf /home/cvsmirror/pg/sup echo /sup/ > /home/cvsmirror/pg-exclude echo '/CVSROOT/loginfo*' >> /home/cvsmirror/pg-exclude echo '/CVSROOT/commitinfo*' >> /home/cvsmirror/pg-exclude echo '/CVSROOT/config*' >> /home/cvsmirror/pg-exclude
通过设置 CVSROOT 切换到使用此存储库。
然后向 cron 添加一个作业,如下所示
43 * * * * rsync -avzCH --delete --exclude-from=/home/cvsmirror/pg-exclude anoncvs.postgresql.org::pgsql-cvs /home/cvsmirror/pg
其他 rsync+CVS 资源
有关用于保持本地树同步的一个有趣方法,请参阅网址为 如何创建 rsync 存储库的 CVS 镜像 上的脚本
CVSup 解决方案
CVSup 的优点和缺点
使用 CVSup 处理 PostgreSQL 代码的一些独特之处值得讨论,因此,很明显使用它作为工具的适当情况是什么。在 PostgreSQL 源代码控制的上下文中,CVSup 的主要吸引力在于它支持 CVS 存储库中的本地修改 的方式。这使用了一种技术,使你自己的本地 CVS 分支与原始存档中的分支保持不同。它依赖于设置一个称为 CVS_LOCAL_BRANCH_NUM 的 CVS 环境变量,以防止版本号冲突。当针对主版更新时,CVSup 帮助协调存储库更改与本地更改。使用 CVSup 以这种方式操作的良好示例工作流程位于网址为 维护和同步本地 CVS 存储库 上。
虽然这一切对于 PostgreSQL 黑客来说似乎都是理想的,但使用它还有几个障碍
- CVSup 用 Modula-3 编写,这需要在大多数操作系统上安装大量工作,甚至可能无法在其他操作系统上编译/安装。
- 使 cvsupfile 配置正确很困难,并且由于该软件并不流行,因此如果你遇到问题,就很难获得帮助。
- 复杂的 CVSup 配置比基于 rsync 的对应配置更脆弱,原因既在于代码没有得到广泛使用,也在于配置过于复杂。听到有人报告说完全正常的 CVSup 配置在一些表面上微不足道的更新之后突然停止工作并非罕见,并且对这些问题进行故障排除可能会非常令人沮丧。
- CVS_LOCAL_BRANCH_NUM 功能最初是 CVS 的 FreeBSD 版本的一个黑客手段,但它进入了从 GNU CVS 获得的当前 CVS 1.2。但是,此时大多数操作系统附带的 CVS 仍然是 CVS 1.1,因此你可能需要自己升级该软件包。
pgbuildfarm HOWTO 中的 CVSup 注释
一旦其所有有用的见解合并到其他部分,此部分应被删除
在几次错误开始后,我让其成功运行起来,复制了整个 postgresql.org 中的 repo,包括 CVSROOT 目录。然后我注释了 CVSROOT/loginfo 和 CVSROOT/commitinfo 中的条目,并且按我想象的那样在 CVSROOT/config 中设置了 LockDir 指令。然后我签出了 CVSROOT 模块,并且再次进行了上述操作,然后签回了该模块。然后为了确保 CVSup 不会覆盖这些文件,我在 <mirror-home>/sup/repository/refuse. 中为它们创建了条目。完成这些后,我能够更改该计算机上的构建配置,以便配置变量“cvsrepo”只是镜像根目录的名称。所有内容都按预期正常工作了。然后我针对此镜像设置了一个匿名 cvs pserver,这样我的其他计算机也可以从此镜像获取资源,而不是从 postgresql.org 获取。我执行了“cvs login”,更改了该计算机上的“cvsrepo”配置变量,而且它也运行得很顺利。最后,我在镜像计算机上设置了一个 cron 作业来更新镜像。仅从主设备每小时更新一次匿名存储库,因此没有必要比此更频繁地运行 cron 作业。这应该不会成为大问题,因为 CVSup 极其高效,即便如此频繁地执行也不应产生大量的带宽使用。
PostgreSQL 存储库的其他版本
有几个项目正在调查 CVS 的替代品,它们正在将现有存储库转换为新的格式。按照地理位置将它们列在了这里,因为这些网站并不一定具有大量全局带宽设置。
Subversion
有将 CVS 存储库直接转换为 Subversion 的内容:美国
Git
PostgreSQL 存储库的主要 Git 转换是 git.postgresql.org,它由法国托管,每 30 分钟更新一次。有关其他内容,请参阅 其他 Git 存储库。 使用 Git 涵盖与本文类似的材料,但采用了 Git 工具链。
Kernel.org 和 此博客 介绍了在 CVS 和 Git 之间进行转换。
Mercurial
- 智利:每小时更新一次
其他版本控制工具
cvsutils
要创建原本需要您对 CVS 存储库具有写访问权限的补丁,例如添加或移除文件的补丁,您可以使用 cvsutils。cvsutils 工具链针对许多操作系统打包,并且以 源代码 的形式提供。
Tailor
有一个名为 Tailor 的工具,可帮助在 ArX、Bazaar、Bazaar-NG、CVS、Codeville、Darcs、Git、Mercurial、Monotone、Subversion 和 Tla 存储库之间迁移更改集。
鸣谢
本文档中的信息来自多种来源。初始文档的贡献者包括 Heikki Linnakangas、Pavan Deolasee、Florian Pflug、Jim Nasby、David Fetter 和 Greg Smith。