第10章  升级一个 port

目录
10.1 使用 CVS 制作补丁
10.2 UPDATING 和 MOVED 文件

  如果您发现某个 port 相对原作者所发布的版本已经过时, 则首先需要确认的是您的 port 是最新的。 您可以在 FreeBSD FTP 镜像的 ports/ports-current 目录中找到它们。 但是, 如果您正在使用较多的 port, 则可能使用 CVSup 来保持 Ports Collection 最新更为简单, 这在 使用手册 中进行了介绍。 此外, 这样做也有助于保持 port 依赖关系的正确性。

  下一步是检查是否已经有在等待的更新。 要完成这项工作, 可以采用下列两种方法之一。 有一个用于搜索 FreeBSD 问题报告 (PR) 数据库 (也被称作 GNATS)。 在下拉框中选择 ports, 然后输入 port 的名字。

  但是, 有些时候人们会忘记将避免混淆的 port 的名字放到 Synopsis 字段中。 这种时候, 您可以试试看 FreeBSD Ports 监视系统 (也被叫做 portsmon)。 这个系统会尝试按照 port 的名字来进行分类。 要搜索和某个特定 port 有关的 PR, 可以使用 port概览

  如果没有候审的 PR, 下一步是给 port 的维护者写信, 这可以通过执行 make maintainer 看到。 这个人可能正在进行升级工作, 或者由于某种理由暂时没有升级 (例如, 新版本有稳定性问题); 一般您不希望重复他们的工作。 注意没有维护者的 port 的维护者会显示为 ports@FreeBSD.org, 这是一般性 port 问题的邮件列表, 因此发邮件给它一般没什么意义。

  如果维护者要求您去完成升级, 或者没有维护者, 您就有机会通过自行完成升级来帮助 FreeBSD 了! 请使用基本系统提供的 diff(1) 命令来完成相关的工作。

  如果只修改一个文件, 可以直接使用 diff 来生成补丁, 将需要修改的文件复制成 something.orig, 并将改动放进 something, 接着生成补丁:

% /usr/bin/diff something.orig something > something.diff

  如果不是这样的话, 则您应使用 cvs diff 的方法 (第 10.1 节), 或将目录整个复制到另一个目录, 并使用 diff(1) 比较两个目录时在目录中递归产生的输出结果 (例如, 如果您修改后的 port 目录的名字是 superedit 而原始文件的目录是 superedit.bak, 则应保存 diff -ruN superedit.bak superedit 的结果)。 一致式 (unified) 或 上下文式 (context) diff 都是可以的, 但一般来说 port committer 会更喜欢一致式 diff。 请注意这里使用的选项 -N, 它的目的是强制 diff 正确地处理出现新文件, 或老文件被删除的情形。 在把 diff 发给我们之前, 请再次检查输出, 以便确认每一个修改都是有意义的。 (特别注意, 在对比目录之前要用 make clean 清理一下)。

  为了简化常用的补丁文件操作, 您可以使用 /usr/ports/Tools/scripts/patchtool.py。 使用之前, 请首先阅读 /usr/ports/Tools/scripts/README.patchtool

  如果 port 目前还无人维护, 而且您自己经常使用它, 请考虑自荐为它的维护者。 FreeBSD 有超过 4000 个没有维护者的 port, 而这正是最需要志愿人员的领域。 (要了解关于维护者的任务描述, 请参见 开发手册中的相关部分。)

  将 diff 发送给我们的最佳方式是通过 send-pr(1) (category 一栏写 ports)。 如果您正维护那个 port, 请务必在 synopsis 的开头写上 [maintainer update], 并将您的 PR 的 “Class” 设置为 maintainer-update。 反之, 您的 PR 的 “Class” 就应该是 change-request。 请在信中逐个提及每一个删除或增加的文件, 因为这些都必须明确地在使用 cvs(1) 进行 commit 时明确地指定。 如果 diff 超过了 20K, 请考虑压缩并对其进行 uuencode; 否则, 简单地将其原样加入 PR 即可。

  在您 send-pr(1) 之前, 请再次阅读 Problem Reports 一文中的 如何撰写问题报告 小节; 它给出了丰富的关于如何撰写更好的问题报告的介绍。

重要: 如果您的更新是由于安全考虑, 或修复已经 commit 的 port 中的严重问题, 请通知 Ports 管理团队 来申请立即重建和分发您的 port 的 package。 否则, 不愿怀疑的使用 pkg_add(1) 的用户, 可能会在未来数周之内继续通过使用 pkg_add -r 安装旧版本。

注意: 再次强调, 请使用 diff(1) 而非 shar(1) 来发送现有 port 的更新! 这可以帮助 ports committer 理解需要修改的内容。

  现在您已经了解了所需的所有操作, 您可能会像要阅读在 第 14 章 中关于如何保持最新的描述。

10.1 使用 CVS 制作补丁

  如果可能的话, 请提交cvs(1) diff; 这种情形要比直接比较 “新、旧” 目录要容易处理。 此外, 这种方法也让您更容易看出到底改了什么, 并在其他人更新了 Ports Collection 时容易合并这些改动, 在提交之前, 这可以减少维护补丁所需的工作。

% cd ~/my_wrkdir (1)
% cvs -d R_CVSROOT co pdnsd (2) (3)
% cd ~/my_wrkdir/pdnsd
(1)
当然, 这可以是您指定的任意目录; 联编 port 并不局限于 /usr/ports/ 的子目录。
(2)
R_CVSROOT 是任何一个公共的 cvs 镜像服务器, 您可以在 FreeBSD 使用手册 中挑选一个。
(3)
pdnsd 是 port 的模块名字; 通常说来它和 port 的名字一样, 不过也有些例外, 特别是那些本地化类别 (german/selfhtml 对应的模块名字是 de-selfhtml); 您可以通过 cvsweb 界面 查询, 或者也可以指定完整路径, 例如在我们这个例子中是 ports/dns/pdnsd

  在工作目录中, 您可以像往常一样进行任何更改。 如果您添加或删除了文件, 则需要告诉 cvs 来追踪这些改动:

% cvs add new_file
% cvs remove deleted_file

  请反复检查 第 3.4 节 列出的事项并使用 第 3.5 节 进行检查。

% cvs status
% cvs update (1)
(1)
这会合并 CVS 中其他人做的改动和您的补丁; 在这个过程中, 您需要仔细观察输出。 文件名前面的那个字母会显示做了什么, 请参阅 表 10-1 中给出的说明。

表 10-1. cvs update 文件名前字母前缀的含义

U 文件更新无误。
P 文件更新无误 (通常只有在使用远程代码库时才会看到)。
M 文件有本地修改, 并合并成功而未产生任何冲突。
C 文件有本地修改, 进行了合并并产生了冲突。

  如果您在执行 cvs update 时某些文件出现了 C, 则说明有其他人在 CVS 中做了修改, 而 cvs(1) 无法将这些改动与您本地的改动进行合并。 不过, 无论如何, 最好都检查一下合并的结果, 因为 cvs 并不知道 port 应该是什么样子, 因此它所做的合并无论是否产生了冲突, 都有可能 (并且并不罕见) 产生没有意义的结果。

  最后一步是以 CVS 中的文件为基础生成 unified diff(1)

% cvs diff -uN > ../`basename ${PWD}`.diff

注意: 指定 -N 十分重要, 因为它确保了添加或删除的文件也出现在补丁中。 补丁将包含删除的文件, 在打上补丁时, 这些文件会被清空, 所以最好在 PR 中提醒 committer 删除它们。

  根据 第 10 章 的指导提交您的补丁。

若您有关于 FreeBSD ports 系统的问题, 请发送电子邮件至 <ports@FreeBSD.org>。
关于此文档的任何问题, 请致函 <doc@FreeBSD.org>。