@node 贡献
@chapter 贡献

这个项目是大家合作的成果，需要你的帮助才能发展壮大！请通过 @email{guix-devel@@gnu.org} 和 Libera Chat IRC
上的 @code{#guix} 联系我们。我们欢迎各种想法、bug
反馈、补丁以及任何对项目有帮助的内容，尤其是打包方面的帮助(@pxref{打包指导}).

@cindex 贡献者行为准则
@cindex 贡献者契约
我们希望提供一个温暖、友好、无骚扰的环境，让任何人都能尽其所能贡献。为此，我们的项目采用了“贡献者契约”，该契约改编自
@url{https://contributor-covenant.org/}。在源代码目录里的 @file{CODE-OF-CONDUCT}
文件中可以找到一份本地版。

贡献者不必在提交补丁和在线交流时使用法定姓名。他们可以使用自己选择的任何名字或者笔名。

@menu
* 需求::                       构建和运行 Guix 需要的软件。
* 从 Git 构建::                 最新的并且最好的。
* 运行测试套件::                   测试 Guix。
* 在安装之前运行 Guix::             黑客技巧。
* 完美的配置::                    正确的工具。
* 替代配置::                     其他可能用于完成任务的工具。
* 源码树结构::                    源码导览。
* 打包指导::                     帮助发行版成长。
* 代码风格::                     贡献者代码卫生守则。
* 提交补丁::                     分享你的工作。
* 跟踪程序漏洞及改动::                保持井井有条。
* 团队::                       协调努力。
* 做出决定::                     共同选择前进的方向。
* 提交权利::                     推送到官方仓库。
* 审阅他人的工作::                  分享评论的一些指导方针。
* 更新 Guix 软件包::              更新 Guix 的软件包定义。
* 弃用策略::                     用于弃用的提交和工具。
* 撰写文档::                     完善 GNU Guix 中的文档。
* 翻译 Guix::                  用您的母语翻译 Guix。
* 为 Guix 的基础设施做贡献::          让 Guix 生态系统更好地运作。
@end menu

@node 需求
@section 需求

你可以轻松地使用 Guix 和 Git 来折腾 Guix 本身，我们将其用于版本控制。(@pxref{从 Git 构建}).

但是，在为外国发行版打包 Guix 或在没有 Guix 的系统上引导时，如果您决定不要直接信任并安装我们现成的二进制文件（@pxref{二进制文件安装}），您可以下载一份我们可复现的源码包的发布版并继续阅读。

这个小节列举了从源代码构建 Guix 的要求。构建 Guix 的步骤和其它 GNU 软件相同，这里不介绍。请阅读 Guix 源码树里的
@file{README} 和 @file{INSTALL} 文件以了解更多细节。

@cindex 官方网站
GNU Guix 可以从它的网站下载 @url{https://guix.gnu.org}。

GNU Guix 依赖以下软件包：

@itemize
@item @url{https://gnu.org/software/guile/, GNU Guile}，版本 3.0.x，
版本 3.0.3 或更新；
@item @url{https://notabug.org/cwebber/guile-gcrypt, Guile-Gcrypt}，版本
0.1.0 或更新；
@item
@uref{https://gitlab.com/gnutls/guile/, Guile-GnuTLS}（@pxref{Guile
Preparations, 如何为 Guile 安装 GnuTLS 绑定, gnutls-guile,
GnuTLS-Guile}）@footnote{关于 @uref{https://gnutls.org/, GnuTLS} 的 Guile 绑定作为
GnuTLS 直到（含）版本 3.7.8 的一部分分发。}；
@item
@uref{https://notabug.org/guile-sqlite3/guile-sqlite3, Guile-SQLite3}, 版本
0.1.0 或更新；
@item @uref{https://notabug.org/guile-zlib/guile-zlib, Guile-zlib},
版本 0.1.0 或更新；
@item @uref{https://notabug.org/guile-lzlib/guile-lzlib, Guile-lzlib};
@item @uref{https://www.nongnu.org/guile-avahi/, Guile-Avahi};
@item
@uref{https://gitlab.com/guile-git/guile-git, Guile-Git}，版本 0.10.0 或更新；
@item @uref{https://git-scm.com, Git}（是的，两个都是！）；
@item @uref{https://github.com/aconchillo/guile-json, Guile-JSON}
4.3.0 或更新；
@item @url{https://www.gnu.org/software/make/, GNU Make}.
@end itemize

这些依赖是可选的：

@itemize
@item
@c ===========================================================================
@c
@c This file was generated with po4a. Translate the source file.
@c
@c ===========================================================================

@c Note: We need at least 0.13.0 for #:nodelay.
对构建下发（@pxref{下发工作给后台进程的设置}）和 @command{guix copy} （@pxref{调用 guix copy}）的支持依赖于 @uref{https://github.com/artyom-poptsov/guile-ssh,
Guile-SSH}，版本 0.13.0 或更新。

@item
@uref{https://notabug.org/guile-zstd/guile-zstd, Guile-zstd}，用于在
@command{guix publish} 中进行 zstd 压缩和解压缩，以及用于 substitutes (@pxref{调用 guix publish}).

@item
@uref{https://ngyro.com/software/guile-semver.html, Guile-Semver} 用于
@code{crate} 导入器（@pxref{调用 guix import}）。

@item
@uref{https://www.nongnu.org/guile-lib/doc/ref/htmlprag/, Guile-Lib} 用于
@code{go} 导入器（@pxref{调用 guix import}）以及一些“升级器”（@pxref{调用 guix refresh}）。

@item
当 @url{http://www.bzip.org, libbz2} 可用时，@command{guix-daemon} 可以用它来压缩构建日志。
@end itemize

除非 @option{--disable-daemon} 被传给 @command{configure}，以下软件包也被需要：

@itemize
@item @url{https://gnupg.org/, GNU libgcrypt};
@item @url{https://sqlite.org, SQLite 3};
@item @url{https://gcc.gnu.org, GCC's g++}，带有支持对于
C++11 标准。
@end itemize

@node 从 Git 构建
@section 从 Git 构建

If you want to hack Guix itself, it is recommended to use the latest version
from the Git repository:

@example
git clone https://git.guix.gnu.org/guix.git
cd guix
@end example

@cindex Guix 签出的身份认证
如何确保已获得存储库的真实副本？为此请运行 @command{guix git authenticate}，将 @dfn{channel
introduction}（@pxref{调用 guix git authenticate}）的提交和 OpenPGP 指纹传给它：

@c The commit and fingerprint below must match those of the channel
@c introduction in '%default-channels'.
@example
git fetch origin keyring:keyring
guix git authenticate 9edb3f66fd807b096b48283debdcddccfea34bad \
  "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"
@end example

@noindent
此命令完成后，若成功则退出代码为零；否则打印一条错误消息，以非零代码退出。

正如你所看到的，这里存在一个先决条件的问题：你首先需要安装 Guix。典型地，你会安装 Guix 系统（@pxref{系统安装}）或在 另一个发行版上安装 Guix（@pxref{二进制文件安装}）；无论哪种情况，你
都需要在安装介质上验证 OpenPGP 签名。这“引导”了信任链。

设置 Guix 开发环境的最简单的方式当然是使用 Guix！下面这些命令启动一个 shell，所有的依赖和环境变量都为折腾 Guix 设置好了：

@example
guix shell -D guix -CPW
@end example

或者，从一个 Git worktree 内部使用 Guix：

@example
echo $(pwd) >> ~/.config/guix/shell-authorized-directories
guix shell -CPW
@end example

如果 @option{-C}（@option{--container} 的缩写）在你的系统上不被支持，请尝试使用 @command{--pure}
来代替 @option{-CPW}。有关该命令的更多信息见 @xref{调用 guix shell}.

Most of the test suite runs without an internet connection. The @option{-N}
(short for @option{--network}) can be added to the @code{guix shell} command
to run the tests that require internet access.

如果在从检出中构建 Guix 时无法使用 Guix，则除了安装说明中提到的 软件包（@pxref{需求}）外，以下是所需的软件包。

@itemize
@item @url{https://gnu.org/software/autoconf/, GNU Autoconf};
@item @url{https://gnu.org/software/automake/, GNU Automake};
@item @url{https://gnu.org/software/gettext/, GNU Gettext};
@item @url{https://gnu.org/software/texinfo/, GNU Texinfo};
@item @url{https://www.graphviz.org/, Graphviz};
@item @url{https://www.gnu.org/software/help2man/, GNU Help2man（可选）}。
@end itemize

On Guix, other development tools, like @code{strace}, can be included by
giving them as extra arguments to @command{guix shell}:

@example
guix shell -D guix -CPW strace
@end example

在这里你可以使用 Autoconf 和 Automake 生成构建系统的基础设施：

@example
./bootstrap
@end example

若你得到一个像这样的错误：

@example
configure.ac:46: error: possibly undefined macro: PKG_CHECK_MODULES
@end example

@noindent
它可能意味着 Autoconf 无法找到由 pkg-config 提供的 @file{pkg.m4}。请确保 @file{pkg.m4} 可用。由
Guile 提供的 @file{guile.m4} 宏也类似。假如你的 Automake 安装在 @file{/usr/local}，那么它不会从
@file{/usr/share} 里寻找 @file{.m4} 文件。这种情况下，你必须执行下面这个命令：

@example
export ACLOCAL_PATH=/usr/share/aclocal
@end example

更多信息请参考 @xref{Macro Search Path,,, automake, The GNU Automake Manual}.

@cindex state 目录
@cindex localstatedir
@cindex 系统配置目录
@cindex sysconfdir
然后，运行：

@example
./configure
@end example

@noindent
如果你愿意，@code{--localstatedir} 和 @code{--sysconfdir}
也能作为参数被提供。在默认情况下，@code{localstatedir} 是 @file{/var}（如欲了解更多信息，@pxref{存储区}）和 @code{sysconfdir} 是 @file{/etc}。请注意，即使最后不运行 @command{make
install}（因为没有必要），传递正确的 @code{localstatedir} 和 @code{sysconfdir}
参数值依然是重要的，因为它们会被记录在 Guile 的 @code{(guix config)} 模块内。

最后，你可以构建 Guix。若你希望，还可以运行测试 (@pxref{运行测试套件}）：

@example
make
make check
@end example

@noindent
如果遇到任何错误，请参考“安装指导”（@pxref{安装}）或者给@email{guix-devel@@gnu.org,
邮件列表}发邮件。

从这开始，你可以运行下面的命令认证检出中的所有提交：

@example
guix git authenticate \
  9edb3f66fd807b096b48283debdcddccfea34bad \
  "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"
@end example

第一次运行需要几分钟，但后续运行会更快。在后续运行中，您可以不带任何参数运行命令，因为 @dfn{介绍}（上面的提交 ID 和 OpenPGP
指纹）将被记录@footnote{这需要 2024 年 5 月或更高版本的 Guix。}：

@example
guix git authenticate
@end example

或者，当你的本地 Git 仓库与默认的不符时，你可以通过环境变量 @code{GUIX_GIT_KEYRING} 提供一个对@code{keyring}
分支的引用。下面的例子假设你有一个名为 @samp{myremote} 的 Git 远程分支，它指向官方仓库：

@example
guix git authenticate \
  -k myremote/keyring \
  9edb3f66fd807b096b48283debdcddccfea34bad \
  "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"
@end example

@xref{调用 guix git authenticate}，以获得关于此命令的更多信息。

@quotation 注
钩子被默认配置以便在@command{git pull} 或 @command{git push}运行时自动调用 @command{guix git
authenticate}.
@end quotation

在每次更新仓库后，@command{make} 可能会因为一个错误而失败，就像下面的例子：

@example
error: failed to load 'gnu/packages/linux.scm':
ice-9/eval.scm:293:34: In procedure abi-check: #<record-type <origin>>: record ABI mismatch; recompilation needed
@end example

它的意思是 Guix 定义的一个记录类型变动了（在这个例子中，为 @code{origin} 记录），并且全部 guix
都需要重编译来让这个变动生效。运行 @command{make clean-go} 和 @command{make} 来重新编译。

如果 @command{make} 在更新后伴随着 Automake 报错而失败，您需要重复本节中概述的步骤，从
@command{./bootstrap} 开始。

@node 运行测试套件
@section 运行测试套件

@cindex 测试套件
成功执行 @command{configure} 和 @code{make} 之后，最好运行测试套件。它可以帮助查找设置和环境的错误，或者是 Guix
自身的 bug－－并且，报告测试错误是帮助改进软件的好方法。输入下面的命令以运行测试套件：

@example
make check
@end example

测试用例可以并行运行：你可以用 GNU@tie{}make 的 @code{-j}
参数来加速运行。在一台较新的机器上第一次运行可能会花几分钟，后续的运行会更快，因为为测试创建的仓库已经包含了各种缓存。

你还可以通过定义 makefile 的 @code{TESTS} 变量来运行测试的一个子集，如同以下示例：

@example
make check TESTS="tests/store.scm tests/cpio.scm"
@end example

默认情况下，测试结果只展示到文件层级。为了查看每个独立的测试用例的详情，可以像这样定义 @code{SCM_LOG_DRIVER_FLAGS}
makefile 变量：

@example
make check TESTS="tests/base64.scm" SCM_LOG_DRIVER_FLAGS="--brief=no"
@end example

The underlying SRFI 64 custom Automake test driver used for the 'check' test
suite (located at @file{build-aux/test-driver.scm}) also allows selecting
which test cases to run at a finer level, via its @option{--select} and
@option{--exclude} options.  Here's an example, to run all the test cases
from the @file{tests/packages.scm} test file whose names start with
``transaction-upgrade-entry'':

@example
export SCM_LOG_DRIVER_FLAGS="--select=^transaction-upgrade-entry"
make check TESTS="tests/packages.scm"
@end example

那些希望直接通过命令行检查失败测试结果的用户可以将 @option{--errors-only=yes} 选项添加到
@code{SCM_LOG_DRIVER_FLAGS} makefile 变量中，并设置 @code{VERBOSE} Automake
makefile 变量，如下所示：

@example
make check SCM_LOG_DRIVER_FLAGS="--brief=no --errors-only=yes" VERBOSE=1
@end example

当与 @option{--brief=no} 结合使用时，可以使用 @option{--show-duration=yes}
选项来输出单个测试用例的持续时间：

@example
make check SCM_LOG_DRIVER_FLAGS="--brief=no --show-duration=yes"
@end example

@xref{Parallel Test Harness,,,automake,GNU Automake} for more information
about the Automake Parallel Test Harness.

遇到错误时，请给 @email{bug-guix@@gnu.org} 发邮件，并附带 @file{test-suite.log}
文件。请在消息里说明使用的 Guix 的版本信息和依赖（@pxref{需求}）的版本信息。

Guix 还附带了一个可以测试整个 Guix 系统实例的全系统测试套件。它只能在已经安装 Guix 的系统上运行，使用：

@example
make check-system
@end example

@noindent
或者再次，通过定义 @code{TESTS} 选择测试的一个子集来运行：

@example
make check-system TESTS="basic mcron"
@end example

这些系统测试在 @code{(gnu tests @dots{})} 模块中定义。原理是，在一个虚拟机（virtual machine,
VM）中，以轻量级的仪表运行待测试的操作系统。它们的计算密集程度可能很高，也可能相对较低，这取决于其依赖项是否有 substitues
可用（@pxref{替代品}）。其中一些需要大量存储空间来保存 VM 镜像。

若你遇到一个像这样的错误：

@example
Compiling Scheme modules...
ice-9/eval.scm:142:16: In procedure compile-top-call:
error: all-system-tests: unbound variable
提示：你是否忘记了 `(use-modules (gnu tests))'？
@end example

@noindent
工作树中可能存在来自先前构建的不一致处。要解决此问题，尝试运行 @command{make clean-go}，再运行 @command{make}。

再次，若遇到测试错误，请向 @email{bug-guix@@gnu.org} 发送所有细节信息。

@node 在安装之前运行 Guix
@section 在安装之前运行 Guix

为了保持一个正常的工作环境，你会发现在不实际安装的情况下测试本地源码树签出中的更改是非常有用的。这样你可以更好地区分自己作为“最终用户”和“测试员”的角色。

这样，即使你没有运行 @code{make install}，所有的命令行工具都可以使用。为此，你先要有一个全部依赖都可用的环境（@pxref{从 Git 构建}），然后简单地为每个命令添加前缀 @command{./pre-inst-env}（@file{pre-inst-env} 脚本在
Guix 构建树的最顶层，@pxref{从 Git 构建}来生成它）。作为例子，以下是你如何构建 @code{hello}
包，如同在你的工作树中定义的那样（这假设了 @command{guix-daemon} 正在运行于你的系统上；如果是不同的版本也可以）：

@example
$ ./pre-inst-env guix build hello
@end example

@noindent
类似地，一个使用 Guix 模块的 Guile 会话的例子：

@example
$ ./pre-inst-env guile -c '(use-modules (guix utils)) (pk (%current-system))'

;;; ("x86_64-linux")
@end example

@noindent
@cindex REPL
@cindex 读取 - 估值 - 打印（read-eval-print）循环
@dots{} 以及为了一个 REPL（@pxref{交互式使用 Guix}）：

@example
$ ./pre-inst-env guile
scheme@@(guile-user)> ,use(guix)
scheme@@(guile-user)> ,use(gnu)
scheme@@(guile-user)> (define snakes
                       (fold-packages
                         (lambda (package lst)
                           (if (string-prefix? "python"
                                               (package-name package))
                               (cons package lst)
                               lst))
                         '()))
scheme@@(guile-user)> (length snakes)
$1 = 361
@end example

如果你在折腾守护进程及其支持代码，或者 @command{guix-daemon}
尚未在系统中运行，你可以直接从构建树中启动它@footnote{@command{sudo} 的 @option{-E} 选项保证了
@code{GUILE_LOAD_PATH} 被正确设置，以便 @command{guix-daemon} 及其使用的工具可以找到它们所需的 Guile
模块。}：

@example
$ sudo -E ./pre-inst-env guix-daemon --build-users-group=guixbuild
@end example

@command{pre-inst-env} 脚本设置好了为了支持这个的所有必要的环境变量，包括 @env{PATH} 和
@env{GUILE_LOAD_PATH}。

注意，@command{./pre-inst-env guix pull} @emph{不}会更新本地源代码树；它只是简单地更新
@file{~/.config/guix/current} 符号链接（@pxref{调用 guix pull}）。如果你想更新本地源码树，请运行 @command{git pull}。

有时，特别是刚刚更新过你的仓库时，运行 @command{./pre-inst-env} 将会打印一个消息，类似于下面的例子：

@example
;;; note: source file /home/user/projects/guix/guix/progress.scm
;;;       newer than compiled /home/user/projects/guix/guix/progress.go
@end example

这仅仅是一个提示，你可以安全地忽略它，可以通过运行 @command{make -j4} 来避免这条消息。若你不这么做，Guile
就会运行的稍微慢一些，因为它会解释代码而不是使用预备的 Guile 对象 (@file{.go}) 文件。

你可以使用 @code{watchexec} 包中的 @command{watchexec} 在你干活时自动运行
@command{make}。例如，若要在每次更新一个包文件后都再次构建，运行@samp{watchexec -w gnu/packages --
make -j4}.

@node 完美的配置
@section 完美的配置

折腾 Guix 的完美配置也是折腾 Guile 的完美配置 @pxref{Using Guile in Emacs,,, guile, Guile
Reference Manual})。首先，你需要的不仅是一个编辑器，你需要
@url{https://www.gnu.org/software/emacs, Emacs}，以及美妙的
@url{http://nongnu.org/geiser/, Geiser}。为此，运行：

@example
guix install emacs guile emacs-geiser emacs-geiser-guile
@end example

Geiser 允许在 Emacs 里进行交互增量式的开发：buffer 里的代码编译和执行，即时文档 获取
(docstrings)，根据上下文补全，@kbd{M-.} 跳转到对象定义，用来尝试代码的
REPL，及更多（@pxref{Introduction,,, geiser, Geiser User Manual}）。如果你允许 Emacs
在项目根目录加载@file{.dir-locals.el}中的文件，Geiser 将会自动将项目根目录下的 guix 资源添加到 Guile
加载路径中。

真正编辑代码时别忘了 Emacs 自带了方便的 Scheme 模式。而且，一定不要错过
@url{https://www.emacswiki.org/emacs/ParEdit, Paredit}。它提供了直接操作语法树的的功能，例如，用
S- 表达式替换父节点，为 S- 表达式添加、删除前后的括号，删除后面的 S- 表达式，等等。

@cindex 代码片段
@cindex 模板
@cindex 减少样板
We also provide templates for common git commit messages and package
definitions in the @file{etc/snippets} directory.  These templates can be
used to expand short trigger strings to interactive text snippets. If you
use @url{https://joaotavora.github.io/yasnippet/, YASnippet}, you may want
to add the @file{etc/snippets/yas} snippets directory to the
@var{yas-snippet-dirs} variable.  If you use
@url{https://github.com/minad/tempel/, Tempel}, you may want to add the
@file{etc/snippets/tempel/*} path to the @var{tempel-path} variable in
Emacs.

@lisp
;; @r{假设 Guix 签出在 ~/src/guix 中。}
;; @r{Yasnippet 配置}
(with-eval-after-load 'yasnippet
  (add-to-list 'yas-snippet-dirs "~/src/guix/etc/snippets/yas"))
;; @r{Tempel 配置}
(with-eval-after-load 'tempel
   ;; 确保 tempel-path 是一个列表——它也可以是一个字符串。
   (unless (listp 'tempel-path)
     (setq tempel-path (list tempel-path)))
   (add-to-list 'tempel-path "~/src/guix/etc/snippets/tempel/*"))
@end lisp

commit 信息片段显示 staged 文件需要依赖@url{https://magit.vc/, Magit}。编辑commit
信息时，输入@code{add}，然后按@kbd{TAB}就可以插入一段用于新增软件包的模板；输入@code{update}，然后按@kbd{TAB}可以插入一段更新软件包的模板；输入@code{https}然后按@kbd{TAB}可以插入一段修改主页
URI 为 HTTPS 的模板。

@code{scheme-mode}最重要的模板可以通过输入@code{package...}，然后按@kbd{TAB}触发。这个片段还插入了触发字符串@code{origin...}，以进一步展开。@code{origin}片段更进一步的可能插入其它以@code{...}结尾的触发字符串，它们可以被继续展开。

@cindex 插入或更新版权
@cindex @code{M-x guix-copyright}
@cindex @code{M-x copyright-update}
我们在@file{etc/copyright.el} 中额外提供了版权的插入和自动更新。你也许会想要设置你的全名，邮箱以及加载一个文件。

@lisp
(setq user-full-name "Alice Doe")
(setq user-mail-address "alice@@mail.org")
;; @r{假设 Guix 签出在 ~/src/guix。}
(load-file "~/src/guix/etc/copyright.el")
@end lisp

要在当前行插入版权信息，调用@code{M-x guix-copyright}。

要更新一个版权信息，你需要指定 @code{copyright-names-regexp}。

@lisp
(setq copyright-names-regexp
      (format "%s <%s>" user-full-name user-mail-address))
@end lisp

你可以通过执行 @code{M-x copyright-update} 检查版权信息是否已更新。若你想要在每次缓存区保存后自动做这件事，就在 Emacs
中添加 @code{(add-hook 'after-save-hook 'copyright-update)}.

@node 在 Emacs 内部浏览漏洞
@subsection 在 Emacs 内部浏览漏洞

Emacs has a nice minor mode called @code{bug-reference}, which, when
combined with @samp{emacs-debbugs} (the Emacs package), can be used to open
links such as @samp{<https://bugs.gnu.org/58697>} or
@samp{<https://issues.guix.gnu.org/58697>} as bug report buffers.  From
there you can easily consult the email thread via the Gnus interface, reply
or modify the bug status, all without leaving the comfort of Emacs! Below is
a sample configuration to add to your @file{~/.emacs} configuration file:

@lisp
;;; Bug references.
(require 'bug-reference)
(add-hook 'prog-mode-hook #'bug-reference-prog-mode)
(add-hook 'gnus-mode-hook #'bug-reference-mode)
(add-hook 'erc-mode-hook #'bug-reference-mode)
(add-hook 'gnus-summary-mode-hook #'bug-reference-mode)
(add-hook 'gnus-article-mode-hook #'bug-reference-mode)

;;; 这扩展了默认表达式 (最上面的第一个表达式提供给'or') 来匹配
;;; url，例如 <https://issues.guix.gnu.org/58697>或
;;; <https://bugs.gnu.org/58697>。它也被扩展到检测
;;; “Fixes: #NNNNN” git trailers.
(setq bug-reference-bug-regexp
      (rx (group (or (seq word-boundary
                          (or (seq (char "Bb") "ug"
                                   (zero-or-one " ")
                                   (zero-or-one "#"))
                              (seq (char "Pp") "atch"
                                   (zero-or-one " ")
                                   "#")
                              (seq (char "Ff") "ixes"
                                   (zero-or-one ":")
                                   (zero-or-one " ") "#")
                              (seq "RFE"
                                   (zero-or-one " ") "#")
                              (seq "PR "
                                   (one-or-more (char "a-z+-")) "/"))
                          (group (one-or-more (char "0-9"))
                                 (zero-or-one
                                  (seq "#" (one-or-more
                                            (char "0-9"))))))
                     (seq (? "<") "https://bugs.gnu.org/"
                          (group-n 2 (one-or-more (char "0-9")))
                          (? ">"))
                     (seq (? "<") "https://issues.guix.gnu.org/"
                          (? "issue/")
                          (group-n 2 (one-or-more (char "0-9")))
                          (? ">"))))))
(setq bug-reference-url-format "https://issues.guix.gnu.org/%s")

(require 'debbugs)
(require 'debbugs-browse)
(add-hook 'bug-reference-mode-hook #'debbugs-browse-mode)
(add-hook 'bug-reference-prog-mode-hook #'debbugs-browse-mode)

;; 下面的命令允许 Emacs Debbugs 用户直接在 Emacs 中打开问题（issue）。
(setq debbugs-browse-url-regexp
      (rx line-start
          "http" (zero-or-one "s") "://"
          (or "debbugs" "issues.guix" "bugs")
          ".gnu.org" (one-or-more "/")
          (group (zero-or-one "cgi/bugreport.cgi?bug="))
          (group-n 3 (one-or-more digit))
          line-end))

;; 修改当运行 'M-x debbugs-gnu' 时的默认值.
(setq debbugs-gnu-default-packages '("guix" "guix-patches"))

;; 显示功能需求。
(setq debbugs-gnu-default-severities
 '("serious" "important" "normal" "minor" "wishlist"))
@end lisp

更多信息，请查询@ref{Bug Reference,,, emacs, The GNU Emacs Manual}和@ref{Minor
Mode,,, debbugs-ug, The Debbugs User Guide}.

@node 替代配置
@section 替代配置

Emacs 的替代设置可能让您以类似的开发体验在 Guix 上工作，并且它们可能与您当前使用的工具更兼容，或者帮助您过渡到 Emacs。

下面列出的选项仅提供基于 Emacs 的配置的替代方案，这是 Guix 社区使用最广泛的配置。如果想要真正了解 Guix
开发的完美配置如何工作，建议阅读前面的章节，无论选择使用哪种编辑器。

@menu
* Guile Studio::             First step in your transition to Emacs.
* Vim 和 NeoVim::             When you are evil to the root.
@end menu

@node Guile Studio
@subsection Guile Studio

Guile Studio 是预配置的 Emacs 环境，已集成 Guile 开发所需的主要组件。即便您不熟悉 Emacs，亦可助您轻松过渡开发实践。

@example
guix install guile-studio
@end example

Guile Studio 预装了 Geiser，可随时使用。

@node Vim 和 NeoVim
@subsection Vim 和 NeoVim


Vim(和 NeoVim) 也打包在 Guix 中，以防您决定走上邪路。

@example
guix install vim
@end example

If you want to enjoy a similar development experience to that in the perfect
setup, you should install several plugins to configure the editor. Vim (and
NeoVim) have the equivalent to Paredit,
@uref{https://www.vim.org/scripts/script.php?script_id=3998,
@code{paredit.vim}}, that will help you with the structural editing of
Scheme files (the support for very large files is not great, though).

@example
guix install vim-paredit
@end example

建议运行 @code{:set autoindent}，以便在输入代码时自动缩进。

@uref{https://www.vim.org/scripts/script.php?script_id=2975,
@code{fugitive.vim}} 是最常用的 Git 交互插件：

@example
guix install vim-fugitive
@end example

当然，如果你想直接在 vim 中使用内置终端模拟器与 Guix 交互，我们还有自己的 @code{guix.vim} 软件包！

@example
guix install vim-guix-vim
@end example

在 NeoVim 中，你甚至可以使用 @url{https://conjure.fun/, Conjure} 进行与 Geiser
类似的配置，从而连接到正在运行的 Guile 进程，并在其中实时注入代码（遗憾的是 Guix 还没有打包）。


@node 源码树结构
@section 源码树结构

@cindex 源代码树的结构
如果您愿意在 Guix 中贡献超出软件包范畴的内容，或者如果您想了解它是如何结合在一起的，本节提供了代码库的导览，或许对您有用。

总体而言，Guix 源树几乎只包含 Guile @dfn{模块}，每个模块都可以视为一个独立的库（@pxref{Modules,,, guile,
GNU Guile Reference Manual}）。

The following table gives an overview of the main directories and what they
contain.  Remember that in Guile, each module name is derived from its file
name---e.g., the module in file @file{guix/packages.scm} is called
@code{(guix packages)}.

@table @file
@item guix
这是 Guix 核心机理的存放位置。这里有几个例子说明“核心”是什么意思，从底层工具到高层工具：

@table @code
@item (guix store)
连接并与负责构建的守护进程交互（@pxref{存储区}）。
@item (guix derivations)
创建衍生物（@pxref{派生}）。
@item (guix gexps)
Writing G-expressions (@pxref{G 表达式}).
@item (guix packages)
定义软件包及来源 (@pxref{软件包引用}).
@item (guix download)
@itemx (guix git-download)
@code{url-fetch} 和 @code{git-fetch} 来源的下载方法 (@pxref{origin 参考手册}).
@item (guix swh)
从 @uref{https://archive.softwareheritage.org,Software Heritage archive}
拿取源代码。
@item (guix search-paths)
Implementing search paths (@pxref{搜索路径}).
@item (guix build-system)
负责构建的系统的接口 (@pxref{构建系统})。
@item (guix profiles)
实现 profiles。
@end table

@cindex build system, directory structure
@item guix/build-system
This directory contains specific build system implementations (@pxref{构建系统}), such as:

@table @code
@item (guix build-system gnu)
GNU 构建系统
@item (guix build-system cmake)
CMake 构建系统；
@item (guix build-system pyproject)
Python 的“pyproject”构建系统。
@end table

@item guix/build
这包含通常在“构建端”使用的代码 (@pxref{G 表达式, strata of code}).
这包括用于构建包或其他操作系统组件的代码，以及其他一些工具：

@table @code
@item (guix build utils)
关于软件包定义的工具和更多（@pxref{构建工具}）。
@item (guix build gnu-build-system)
@itemx (guix build cmake-build-system)
@itemx (guix build pyproject-build-system)
构建系统的实现，具体来说是定义其构建阶段@pxref{Build Phases}（@pxref{Build Phases}).
@item (guix build syscalls)
到 C 库和 Linux 系统调用的接口。
@end table

@cindex 作为 Guile 模块的命令行工具
@cindex 命令模块
@item guix/scripts
这包括了相应于 @command{guix} 子命令的模块。例如，@code{(guix scripts shell)} 模块导出了
@code{guix-shell} 过程，这直接对应于 @command{guix shell} 命令（@pxref{调用 guix shell}）。

@cindex 导入器模块
@item guix/import
这包含了对于导入器和升级器的支持代码（@pxref{调用 guix import}，以及 @pxref{调用 guix refresh}）。例如，@code{(guix import pypi)} 定义了 PyPI 的接口，这由 @command{guix import
pypi} 命令使用。
@end table

到目前为止我们看到的所有文件夹都位于 @file{guix/} 下。另一个重要的地方是 @file{gnu/} 目录，它主要包含包定义以及 Guix
系统 (@pxref{系统配置}) 和 Guix Home (@pxref{Home Configuration})
的库和工具，所有这些都建立在 @code{(guix @dots{})} 模块提供的功能之上@footnote{因此，@code{(guix
@dots{})} 模块通常不应依赖于 @code{(gnu @dots{})} 模块，尽管有一些显著的例外：@code{(guix
build-system @dots{})} 模块可以在运行时查找包——例如，@code{(guix build-system cmake)}
需要在运行时访问 @code{cmake} 变量——，@code{(guix scripts @dots{})} 通常依赖于 @code{(gnu
@dots{})} 模块，@code{(guix import @dots{})} 模块中的某些模块也是如此。}。

@table @file
@cindex 软件包模块
@item gnu/packages
这是源代码树中最拥挤的文件夹：它包含导出包定义（@pxref{软件包模块}）的 @dfn{包模块}。举几个例 子：

@table @code
@item (gnu packages base)
提供“基础”包的模块：@code{glibc}, @code{coreutils}, @code{grep}, 等等。
@item (gnu packages guile)
Guile 和核心 Guile 包。
@item (gnu packages linux)
Linux-libre 内核及相关软件包。
@item (gnu packages python)
Python 和核心 Python 软件包。
@item (gnu packages python-xyz)
杂项 Python 软件包（不是开玩笑）。
@end table

无论何时，您都可以使用@command{guix edit}跳转到软件包定义（@pxref{调用 guix edit}），并使用@command{guix show}查看其位置（@pxref{调用 guix package}).

@findex search-patches
@item gnu/packages/patches
This directory contains patches applied against packages and obtained using
the @code{search-patches} procedure.

@item gnu/services
这包含服务的定义，主要用于 Guix 系统（@pxref{服务}），但其中一些被调整并重用于 Guix Home，如下所示。示例：

@table @code
@item (gnu services)
The service framework itself, which defines the service and service type
data types (@pxref{合成服务}).
@item (gnu services base)
``Base'' services (@pxref{基础服务}).
@item (gnu services desktop)
桌面服务（@pxref{桌面服务}）。
@item (gnu services shepherd)
Support for Shepherd services (@pxref{Shepherd 服务}).
@end table

You can jump to a service definition using @command{guix system edit} and
view its location with @command{guix system search} (@pxref{调用 guix system}).

@item gnu/system
These are core Guix System modules, such as:

@table @code
@item (gnu system)
Defines @code{operating-system} (@pxref{operating-system 参考}).
@item (gnu system file-systems)
Defines @code{file-system} (@pxref{文件系统}).
@item (gnu system mapped-devices)
Defines @code{mapped-device} (@pxref{映射的设备}).
@end table

@item gnu/build
These are modules that are either used on the ``build side'' when building
operating systems or packages, or at run time by operating systems.

@table @code
@item (gnu build accounts)
Creating @file{/etc/passwd}, @file{/etc/shadow}, etc. (@pxref{用户帐户}).
@item (gnu build activation)
在启动或者重新配置（reconfigure）时激活一个操作系统。
@item (gnu build file-systems)
Searching, checking, and mounting file systems.
@item (gnu build linux-boot)
@itemx (gnu build hurd-boot)
启动 GNU/Linux 和 GNU/Hurd 操作系统。
@item (gnu build linux-initrd)
Creating a Linux initial RAM disk (@pxref{初始化内存盘}).
@end table

@item gnu/home
This contains all things Guix Home (@pxref{Home Configuration}); examples:

@table @code
@item (gnu home services)
诸如@code{home-files-service-type}的核心服务。
@item (gnu home services ssh)
SSH-related services (@pxref{Secure Shell}).
@end table

@item gnu/installer
This contains the text-mode graphical system installer (@pxref{向导式图形安装}).

@item gnu/machine
这些是被@command{guix deploy}使用到@dfn{机器抽象}（@pxref{调用 guix deploy}).

@item gnu/tests
This contains system tests---tests that spawn virtual machines to check that
system services work as expected (@pxref{运行测试套件}).
@end table

Last, there's also a few directories that contain files that are @emph{not}
Guile modules:

@table @file
@item nix
This is the C++ implementation of @command{guix-daemon}, inherited from Nix
(@pxref{调用 guix-daemon}).

@item tests
These are unit tests, each file corresponding more or less to one module, in
particular @code{(guix @dots{})} modules (@pxref{运行测试套件}).

@item doc
This is the documentation in the form of Texinfo files: this manual and the
Cookbook.  @xref{Writing a Texinfo File,,, texinfo, GNU Texinfo}, for
information on Texinfo markup language.

@item po
This is the location of translations of Guix itself, of package synopses and
descriptions, of the manual, and of the cookbook.  Note that @file{.po}
files that live here are pulled directly from Weblate (@pxref{翻译 Guix}).

@item etc
Miscellaneous files: shell completions, support for systemd and other init
systems, Git hooks, etc.
@end table

With all this, a fair chunk of your operating system is at your fingertips!
Beyond @command{grep} and @command{git grep}, @pxref{完美的配置} on
how to navigate code from your editor, and @pxref{交互式使用 Guix}
for information on how to use Scheme modules interactively.  Enjoy!

@node 打包指导
@section 打包指导

@cindex 软件包，创建
这个 GNU 发行版正在开发的早期阶段，可能缺少一些你喜欢的软件。这个章节介绍你可以怎样帮助这个发行版成长。

自由软件通常以@dfn{源代码包}的形式分发，通常是包含完整代码的@file{tar.gz}包。添加软件包到这个发行版意味着两件事：添加描述如何构建包的@dfn{配方}和一系列依赖软件，以及添加配方之外的@dfn{软件包元数据}，如一段文字描述和证书信息。

在 Guix 里所有这些信息都包含在@dfn{软件包定义}里。软件包定义提供了软件包的高层视角。它们使用 Scheme
编程语言编写，事实上，对每个软件包我们都定义一个绑定到软件包定义的的变量，并且从模块（@pxref{软件包模块}）中导出那个变量。然而，深入的 Scheme
知识@emph{不}是创建软件包的前提条件。若要了解软件包的更多信息，@pxref{定义软件包}.

一旦软件包定义准备好了，并且包存在 Guix 代码树的一个文件里，你可以用@command{guix build} (@pxref{调用 guix build}) 命令测试它。假设这个新软件包的名字叫做@code{gnew}，你可以在 Guix 构建树里运行这个命令
(@pxref{在安装之前运行 Guix}):

@example
./pre-inst-env guix build gnew --keep-failed
@end example

使用@code{--keep-failed}参数会保留失败的构建树，这可以使调试构建错误更容易。@code{--log-file}也是一个调试时很有用的参数，它可以用来访问构建日志。

如果@command{guix}命令找不到这个软件包，那可能是因为源文件包含语法错误，或者缺少导出软件包的@code{define-public}语句。为了查找错误，你可以用
Guile 导入这个模块以了解这个错误的详情：

@example
./pre-inst-env guile -c '(use-modules (gnu packages gnew))'
@end example

一旦你的软件包可以正确构建，请给我们发送补丁 (@pxref{提交补丁})。当然，如果你需要帮助，我们也会很乐意帮助你。一旦补丁被提交到 Guix
仓库里，这个新的软件包会由@url{https://@value{SUBSTITUTE-SERVER-1}, our continuous
integration system}自动地在支持的平台上构建。

@cindex substitutes
Users can obtain the new package definition simply by running @command{guix
pull} (@pxref{调用 guix pull}).  When @code{@value{SUBSTITUTE-SERVER-1}}
is done building the package, installing the package automatically downloads
binaries from there (@pxref{替代品}).  The only place where human
intervention is needed is to review and apply the patch.


@menu
* 软件自由::                     什么可以进入这个发行版。
* 软件包命名::                    名字里包含什么？
* 版本号::                      当名字不够时。
* 简介和描述::                    帮助用户寻找合适的软件包。
* 原始片段 vs. 构建阶段::            用片段，还是用构建阶段。
* 模块的循环依赖::                  Going full circle.
* Bulk Updates::             This Little Maneuver's Gonna Cost Us 51 Years.
* Emacs 包::                  你的 Elisp 补丁。
* Python 模块::                一点英式喜剧。
* Perl 模块::                  小珍珠。
* Java 包::                   喝咖啡休息。
* Rust Crates::              谨防氧化。
* Elm 包::                    树状浏览器代码
* 字体::                       字体的乐趣。
@end menu

@node 软件自由
@subsection 软件自由

@c Adapted from http://www.gnu.org/philosophy/philosophy.html.
@cindex 自由软件
开发 GNU 操作系统是为了用户拥有计算的自由。GNU
是@dfn{自由软件}，这意味着它有@url{https://www.gnu.org/philosophy/free-sw.html，四项重要的自由}：运行程序的自由，以源代码形式学习和修改程序的自由，原样重新分发副本的自由，和分发修改后的版本的自由。GNU
发行版里包含的软件包只提供遵守这四项自由的软件。

此外，GNU
发行版遵循@url{https://www.gnu.org/distros/free-system-distribution-guidelines.html，自由软件发行版准则}。这些准则拒绝非自由的固件和对非自由软件的推荐，并讨论解决商标和专利的方法。

某些上游的软件包源代码包含一小部分违反上述准则的可选的子集，比如这个子集本身就是非自由代码。这时，这些讨厌的代码需要用合适的补丁或者软件包定义（@pxref{定义软件包}）里的@code{origin}里的代码片段移除。这样，@code{guix build
--source}就可以返回自由的源代码而不是未经修改的上游源代码。


@node 软件包命名
@subsection 软件包命名

@cindex 软件包名字
一个软件包事实上有两个名字：第一个是@emph{Scheme
变量}的名字，即用@code{define-public}定义的名字。通过这个名字，软件包可以被 Scheme
代码找到，如用作其它软件包的输入。第二个名字是软件包定义里的@code{name}属性的字符串值。这个名字用于软件包管理命令，如：@command{guix
package}，@command{guix build}。

两个名字通常是相同的，常是上游项目名字转成小写字母并把下划线替换成连字符的结果。比如，GNUnet 转成@code{gnunet}，SDL_net
转成@code{sdl-net}。

这条规则有一个值得注意的例外，那就是当工程名只有一个字符，或与它同名的一个旧工程已经存在——不论是否已经被打为 Guix
包。你应该动用常识来让这些名字无歧义且有意义。比如说，上游称为 ``s'' 的 shell 程序在 Guix 中称为 @code{s-shell} 而
@emph{不是} @code{s}。你可以随便问问你的黑客伙计们来获得一些启发。

我们不给库软件包添加@code{lib}前缀，除非它是项目官方名字的一部分。但是@pxref{Python 模块}和@ref{Perl 模块}有关于 Python 和 Perl 语言的特殊规则。

字体软件包的名字处理起来不同，@pxref{字体}.


@node 版本号
@subsection 版本号

@cindex 软件包版本
我们通常只为每个自由软件的最新版本打包。但是有时候，比如对于版本不兼容的库，需要有同一个软件包的两个或更多版本。它们需要使用不同的 Scheme
变量名。我们为最新的版本使用@ref{软件包命名}里规定的名字，旧的版本使用加上后缀的名字，后缀是@code{-}和可以区分开版本号的版本号的最小前缀。

软件包定义里的名字对于同一个软件包的所有版本都是相同的，并且不含有版本号。

例如，GTK+ 的 2.24.20 和 3.9.12 两个版本可以这样打包：

@lisp
(define-public gtk+
  (package
    (name "gtk+")
    (version "3.9.12")
    ...))
(define-public gtk+-2
  (package
    (name "gtk+")
    (version "2.24.20")
    ...))
@end lisp
如果我们还需要 GTK+ 3.8.2，就这样打包
@lisp
(define-public gtk+-3.8
  (package
    (name "gtk+")
    (version "3.8.2")
    ...))
@end lisp

@c See <https://lists.gnu.org/archive/html/guix-devel/2016-01/msg00425.html>,
@c for a discussion of what follows.
@cindex 用于版本控制快照的版本号
有时候，我们为软件包上游的版本控制系统（VCS）的快照而不是正式发布版打包。这是特殊情况，因为决定哪个是稳定版的权力应该属于上游开发者。然而，有时候这是必须的。那么，我们该如何决定写在@code{version}里的版本号呢？

显然，我们需要让 VCS 快照的 commit ID 在版本号中体现出来，但是我们也需要确保版本号单调递增，以便@command{guix
package --upgrade}决定哪个版本号更新。由于commit ID，尤其是 Git 的 commit
ID，不是单调递增的，我们添加一个每次升级快照时都手动增长的 revision 数字。最后的版本号字符串看起来是这样：

@example
2.0.11-3.cabba9e
  ^    ^    ^
  |    |    `-- 上游的 commit ID
  |    |
  |    `--- Guix 软件包的 revision
  |
最新的上游版本号
@end example

把@code{版本号}里的 commit ID 截短，比如只取 7
个数字，是一个好主意。它避免了美学上的烦恼（假设美学在这里很重要），以及操作系统限制引起的问题（比如 Linux 内核的127
字节）。尽管如此，在@code{origin}里最好使用完整的 commit ID，以避免混淆。通常一个软件包应该看起来是下面这样：


@lisp
(define my-package
  (let ((commit "c3f29bc928d5900971f65965feaae59e1272a3f7")
        (revision "1"))          ;Guix 软件包的 revision
    (package
      (version (git-version "0.9" revision commit))
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url "git://example.org/my-package.git")
                      (commit commit)))
                (sha256 (base32 "1mbikn@dots{}"))
                (file-name (git-file-name name version))))
      ;; @dots{}
      )))
@end lisp

@deffn {过程} git-version @var{VERSION} @var{REVISION} @var{COMMIT}
返回包的版本字符串，利用 @code{git-fetch}。

@lisp
(git-version "0.2.3" "0" "93818c936ee7e2f1ba1b315578bde363a7d43d05")
@result{} "0.2.3-0.93818c9"
@end lisp
@end deffn

@deffn {过程} hg-version @var{VERSION} @var{REVISION} @var{CHANGESET}
返回包的版本字符串，利用  @code{hg-fetch}，就像 @code{git-version} 那样。
@end deffn

@node 简介和描述
@subsection 简介和描述

@cindex 软件包描述
@cindex 软件包简介
我们已经看到，GNU@tie{}Guix
里的每个软件包都包含一个简介（synopsis）和一个描述（description）（@pxref{定义软件包}）。简介和描述很重要：它们是@command{guix package
--search}搜索的信息，并且是帮助用户决定一个软件包是否符合自己需求的重要信息。因此，打包的人应该关注怎样写它们的内容。

简介必须以大写字母开头，并且不能以句号结尾。它们不能以 ``a'' 或者 ``the'' 等没有意义的词开头。例如 ``File-frobbing
tool'' 要比 ``A tool that frobs files'' 更好。简介需要说明软件包是什么－－如 ``Core GNU
utilities (file, text, shell)''，或者它的用途－－如 GNU@tie{}grep 的简介是 ``Print lines
matching a pattern''.

记住，简介必须能被广大的听众理解。例如，“以 SAM
格式修改对齐”可能对经验丰富的生物信息科研工作者来说能理解，但是对普通对听众则是无用的甚至是令人误解的。简介最好说明软件包应用的领域。在这个例子中，应该这样描述“修改核苷酸序列的对齐格式”，这会让用户更容易判断这是不是他们想要的。

描述应该在 5 至 10
句话之间。使用完整的句子，并且避免在未介绍的情况下使用缩写。请避免推广营销性对词汇，如“世界领先”，“行业最强”，“下一代”，并且避免高级的形容词，如“最先进的”--他们对用户寻找软件包是无用的，甚至是可疑的。相反的，尽量务实，提及用例和功能。

@cindex 软件包描述里的 Texinfo 标记
Descriptions can include Texinfo markup, which is useful to introduce
ornaments such as @code{@@code} or @code{@@dfn}, bullet lists, or hyperlinks
(@pxref{Overview,,, texinfo, GNU Texinfo}).  However you should be careful
when using some characters for example @samp{@@} and curly braces which are
the basic special characters in Texinfo (@pxref{Special Characters,,,
texinfo, GNU Texinfo}).  User interfaces such as @command{guix show} take
care of rendering it appropriately.

简介和描述@uref{https://translate.codeberg.org/projects/guix/packages, 由
Weblate}项目的志愿者翻译，从而使尽可能多的用户可以用母语阅读。用户界面用当前区域设置的语言搜索和展示这些信息。

为了让@command{xgettext}可以把它们提取成待翻译的字符串，简介和描述@emph{必须是文字字符串}。这意味着你不能使用@code{string-append}或@code{format}来合成字符串：

@lisp
(package
  ;; @dots{}
  (synopsis "这是可以翻译的")
  (description (string-append "这是" "*不可以*" "翻译的")))
@end lisp

翻译是很繁重的工作，所以，作为打包者请更加注意你的简介和介绍，每一个改动都会增加翻译的工作量。为了帮助他们，你可以插入这类可以被他们看到的建议和指示(@pxref{xgettext
Invocation,,, gettext, GNU Gettext}):

@lisp
;; TRANSLATORS: "X11 resize-and-rotate"不需要翻译。
(description "ARandR 为 X11 resize-and-rotate (RandR) 扩展提供简单的图形界面。@dots{}")
@end lisp

@node 原始片段 vs. 构建阶段
@subsection 原始片段 vs. 构建阶段

@cindex 何时使用片段
原始片段和构建阶段的边界比较难以理解。原始片段通常用来移除不想要的文件，比如捆绑的库，非自由源，或者用于应用简单的替换。从原始源迭代出的源应该在上游包支持的系统上都能成功构建包（就是说，像对应的原始源那样动作）。尤其是，原始片段一定不能内嵌有
store 中的项目；这样的补丁更应该在构建阶段完成。参考@code{origin} 记录文档获取更多信息（@pxref{origin 参考手册}）。

@node 模块的循环依赖
@subsection 模块的循环依赖

While there cannot be circular dependencies between packages, Guile's lax
module loading mechanism allows circular dependencies between Guile modules,
which doesn't cause problems as long as the following conditions are
followed for two modules part of a dependency cycle:

@cindex rules to cope with circular module dependencies
@enumerate
@item
Macros are not shared between the co-dependent modules
@item
Top-level variables are only referenced in delayed (@i{thunked}) package
fields: @code{arguments}, @code{native-inputs}, @code{inputs},
@code{propagated-inputs} or @code{replacement}
@item
Procedures referencing top-level variables from another module are not
called at the top level of a module themselves.
@end enumerate

Straying away from the above rules may work while there are no dependency
cycles between modules, but given such cycles are confusing and difficult to
troubleshoot, it is best to follow the rules to avoid introducing problems
down the line.

@noindent
这是一个需要避免的常见问题：

@lisp
(define-public avr-binutils
  (package
    (inherit (cross-binutils "avr"))
    (name "avr-binutils")))
@end lisp

In the above example, the @code{avr-binutils} package was defined in the
module @code{(gnu packages avr)}, and the @code{cross-binutils} procedure in
@code{(gnu packages cross-base)}.  Because the @code{inherit} field is not
delayed (thunked), it is evaluated at the top level at load time, which is
problematic in the presence of module dependency cycles.  This could be
resolved by turning the package into a procedure instead, like:

@lisp
(define (make-avr-binutils)
  (package
    (inherit (cross-binutils "avr"))
    (name "avr-binutils")))
@end lisp

Care would need to be taken to ensure the above procedure is only ever used
in a package delayed fields or within another procedure also not called at
the top level.

@node Bulk Updates
@subsection Bulk Updates

@cindex packaging, maintenance
Sometimes you may need to update a monotonic collection of grouped packages,
in a particular module---e.g., @code{(gnu packages astronomy)}.  Doing so
requires refreshing package versions, creating commits following guidelines
and testing them.  Let's say there are 200+ packages with fresh versions,
you may deal with this task by applying the following technique.

Enter a development shell in your local Guix checkout, assuming you already
ran @code{bootstrap} and @code{configure}:

@example
~$ guix shell --development guix
[env: /gnu/store/@dots{}-profile]
> ./pre-inst-env guix refresh --select=module:astronomy --update
> ./pre-inst-env etc/committer.scm
@end example

The first command updates all packages in @code{(gnu packages astronomy)} to
the latest versions and writes changes back to the file.  The second invokes
@code{etc/committer.scm} script, a helper script for larger scale updates;
it identifies each package diff and creates corresponding commits with the
correct style.

If your machine is powerful enough, you may check that the whole collection
has no regressions and can still be built successfully:
@example
[env: /gnu/store/@dots{}-profile]
> ./pre-inst-env guix build $(./pre-inst-env guix package -A | awk '/astronomy.scm/@{print $1"@@"$2@}')
@end example

@node Emacs 包
@subsection Emacs 包

@cindex emacs，打包
@cindex elisp，打包
为统一化以及享受构建阶段的方便，比如自动生成 autoloads 文件、字节编译源文件，Emacs 包应该选择 Emacs
构建系统（@pxref{emacs-build-system}）。由于没有标准化的方法运行 Emacs
包的测试用例，测试默认是禁用的。当一个测试用例可用时，可以通过设置 @code{#:tests?} 参数为 @code{#true}
启用。默认条件下，运行测试的命令是 @command{make check}，不过其它的命令也可以用 @code{#:test-command}
参数指定。参数 @code{#:test-command} 应当由包含命令和命令参数的列表，并在 @code{check} 阶段调用。

Emacs 包的 Elisp 依赖项通常在运行时需要时作为 @code{propagated-inputs}
提供。对于其他包，构建或测试依赖项应指定为@code{native-inputs}。

Emacs 包有时依赖于应与 Elisp 文件一并安装的资源目录。 @code{#:include}
参数可用于此目的，方法是指定要匹配的正则表达式列表。使用 @code{#:include}
参数时的最佳实践是扩展而不是覆盖它的默认值（可通过@code{%default-include} 变量访问）。 例如，yasnippet
扩展包通常包含一个 @file{snippets} 目录，可以使用以下命令将其复制到安装目录：

@lisp
#:include (cons "^snippets/" %default-include)
@end lisp

当遇到问题时，明智的做法是检查包主要源文件中是否存在 @code{Package-Requires}
扩展标头，以及是否满足其中列出的任何依赖项及其版本。

@node Python 模块
@subsection Python 模块

@cindex python
我们目前为 Python 2 和 Python 3 打包，如@ref{版本号}的规则所述，它们的Scheme
变量名分别是@code{python-2}和@code{python}。为了避免和其他编程语言的冲突，Python
模块的软件包名字最好含有@code{python}。

某些模块仅和一个版本的 Python 兼容，而某些模块和两个版本都兼容。如果一个叫做 Foo的软件包用 Python3
编译，我们叫它@code{python-foo}；如果它用 Python2 编译，我们叫它@code{python2-foo}。Python2
的软件包正从本发行版清除；请不要提交任何新的Python2 软件包。

如果一个项目的名字已经含有@code{python}这个单词，我们把它丢掉；例如，python-dateutil
模块打包后的名字是@code{python-dateutil}和@code{python2-dateutil}。如果项目的名字以@code{py}开头（如@:
@code{pytz}），我们把它保留，并且添加上面所述的前缀。

@quotation 注
目前在 Guix 中有两种不同的 Python 包构建系统：@var{python-build-system}
和@var{pyproject-build-system}。在很长的一段时间里，Python 包是从非正式指定的 @file{setup.py}
文件构建的。考虑到 Python 的成功，这工作得非常好，但很难围绕它构建工具。结果，出现了许多替代构建系统，社区最终确定了一个
@url{https://peps.python.org/pep-0517/, 正式标准} 来指定构建要求。
@var{pyproject-build-system} 是 Guix 对该标准的实现。它被认为是“实验性的”，因为它还不支持所有不同的 PEP-517
@emph{编译后端}，但我们鼓励您为新的 Python 包尝试它并报告任何问题。它最终将被弃用并合并到
@var{python-build-system} 中。
@end quotation

@subsubsection 指定依赖
@cindex Python 软件包的输入

Python
软件包的依赖信息通常在包的源代码树里，各种文件有不同的准确度：@file{setup.py}文件，@file{requirements.txt}文件，或在
@file{tox.ini}文件（后者主要用于测试依赖项）。

你在写软件包配方时的任务是把这些依赖转换成相应的“输入”（@pxref{软件包引用,
inputs}）。尽管@code{pypi}导入工具通常可以做得很好（@pxref{调用 guix import}），你可能想检查下面这个清单，以决定每个依赖放在哪儿。

@itemize

@item
我们目前将 Python 打包为默认安装的 @code{setuptools} 和 @code{pip}。这即将改变，如果用户想要 Python
的构建环境，我们鼓励他们使用@code{python-toolchain}。

如果将 @code{setuptools} 或 @code{pip} 添加为本机输入，@command{guix lint}
将发出警告，因为通常它们不是必需的。

@item
运行时需要的 Python
依赖要放进@code{propagated-inputs}。它们通常由@file{setup.py}文件里的@code{install_requires}关键字或@file{requirements.txt}文件定义。

@item
Python packages required only at build time---e.g., those listed under
@code{build-system.requires} in @file{pyproject.toml} or with the
@code{setup_requires} keyword in @file{setup.py}---or dependencies only for
testing---e.g., those in @code{tests_require} or @file{tox.ini}---go into
@code{native-inputs}.  The rationale is that (1) they do not need to be
propagated because they are not needed at run time, and (2) in a
cross-compilation context, it's the ``native'' input that we'd want.

例如@code{pytest}，@code{mock}，@code{nose}测试框架。当然，如果在运行时需要这里的任何一个包，它需要被加进@code{propagated-inputs}。

@item
任何不属于上述类别的包都要被加进@code{inputs}，如，构建含有 C 语言扩展的 Python包所需的程序和 C 语言库。

@item
如果一个 Python
软件包由可选的依赖（@code{extras_require}），由你根据它们的性价比（用处/负担）决定是否添加它们（@pxref{提交补丁, @command{guix size}}).

@end itemize


@node Perl 模块
@subsection Perl 模块

@cindex perl
Perl 程序和其它软件包的命名规则类似，用小写的上游名字命名。对于仅包含一个类的Perl
包，我们使用小写的类名，把所有的@code{::}替换成破折号，并且添加@code{perl-}前缀。所以类@code{XML::Parser}变成@code{perl-xml-parser}。包含多个类的模块保留它们上游的名字，并且添加@code{perl-}前缀。这类模块的名字通常含有@code{perl}，这个单词需要被删掉。例如，@code{libwww-perl}变成@code{perl-libwww}.


@node Java 包
@subsection Java 包

@cindex java
Java 程序和其它软件包的命名规则类似，用小写的上游名字命名。

为了避免和其它编程语言混淆和命名冲突，Java
软件包的名字最好有@code{java-}前缀。如果一个项目的名字已经含有@code{java}，我们把它删掉；例如，@code{ngsjava}打包后的名字是@code{java-ngs}。

对于仅包含一个或很少几个类的 Java
软件包，我们使用小写的类名，把所有的@code{.}替换成破折号，并且添加@code{java-}前缀。因此，类@code{apache.commons.cli}打包后的名字是@code{java-apache-commons-cli}。


@node Rust Crates
@subsection Rust Crates

@cindex rust
Rust applications (binary crates) and libraries (library crates) are
packaged separately.  We put our main efforts into applications and only
package libraries as sources, utilizing automation with a manual focus on
unbundling vendored dependencies.

Rust applications are treated like any other package and named using the
lowercase upstream name.  When using the Cargo build system (@pxref{构建系统, @code{cargo-build-system}}), Rust applications should have the
@code{#:install-source?} parameter set to @code{#f}, as this parameter only
makes sense for libraries.  When the package source is a Cargo workspace,
@code{#:cargo-install-paths} must be set to enable relevant support.

Rust libraries are hidden from the user interface and managed in two
modules:

@table @code
@item (gnu packages rust-crates)
Source definitions imported from Rust packages' @file{Cargo.lock} via the
@code{crate} importer (@pxref{调用 guix import}).

Imported definitions must be checked and have vendored dependencies
unbundled before being contributed to Guix.

@item (gnu packages rust-sources)
More complex definitions that need to be full packages.  This includes Rust
libraries requiring external inputs to unbundle and Cargo workspaces.

These libraries should have the @code{#:skip-build?} parameter set to
@code{#t}.  For Cargo workspaces, @code{#:cargo-package-crates} must be set.

Since they are added manually, they follow the usual naming convention for
Guix packages (@pxref{软件包命名}), with a @code{rust-} prefix.

In the Rust community it is common for multiple incompatible versions of a
package to be used at any given time, so all libraries should have a
versioned suffix.  The versioned suffix is the left-most non-zero digit (and
any leading zeros, of course).  This follows the ``caret'' version scheme
intended by Cargo.  Examples@: @code{rust-clap-2}, @code{rust-rand-0.6}.

In practice we often package development snapshots of Rust libraries and
can't simply identify them by version.  In this case, the complete version
information can be turned into a version string via @code{git-version}, for
example @code{rust-pipewire-0.8.0.fd3d8f7} and
@code{rust-pubgrub-0.3.0.b70cf70}.
@end table

To avoid merge conflicts with changes from multiple branches, these two
modules are maintained by the Rust team (@pxref{团队}).

Rust libraries are not referenced directly.  @code{(guix build-sytem cargo)}
provides a @code{cargo-inputs} procedure to lookup input lists generated by
the lockfile importer.

@cindex cargo inputs
@findex define-cargo-inputs
@findex lookup-cargo-inputs
@deffn {Procedure} cargo-inputs name [#:module '(gnu packages rust-crates)]
Lookup Cargo inputs for @var{name} in @var{module}, return an empty list if
unavailable.

@var{name} must be consistent with the one used in lockfile importer
invocation, usually matching the variable name of the package:

@example
$ guix import -i @file{gnu/packages/rust-crates.scm} crate -f @file{/path/to/Cargo.lock} @var{name}
@end example

@var{module} must export a public interface @code{lookup-cargo-inputs}, a
template is available in the @file{etc/teams/rust} directory of Guix source
tree.
@end deffn

@xref{Packaging Rust Crates,,, guix-cookbook, GNU Guix Cookbook}, for
packaging workflow.


@node Elm 包
@subsection Elm 包

@cindex Elm
Elm applications can be named like other software: their names need not
mention Elm.

Packages in the Elm sense (see @code{elm-build-system} under @ref{构建系统}) are required use names of the format
@var{author}@code{/}@var{project}, where both the @var{author} and the
@var{project} may contain hyphens internally, and the @var{author} sometimes
contains uppercase letters.

To form the Guix package name from the upstream name, we follow a convention
similar to Python packages (@pxref{Python 模块}), adding an @code{elm-}
prefix unless the name would already begin with @code{elm-}.

In many cases we can reconstruct an Elm package's upstream name
heuristically, but, since conversion to a Guix-style name involves a loss of
information, this is not always possible.  Care should be taken to add the
@code{'upstream-name} property when necessary so that @samp{guix import elm}
will work correctly (@pxref{调用 guix import}). The most notable
scenarios when explicitly specifying the upstream name is necessary are:

@enumerate
@item
When the @var{author} is @code{elm} and the @var{project} contains one or
more hyphens, as with @code{elm/virtual-dom}; and

@item
When the @var{author} contains hyphens or uppercase letters, as with
@code{Elm-Canvas/raster-shapes}---unless the @var{author} is
@code{elm-explorations}, which is handled as a special case, so packages
like @code{elm-explorations/markdown} do @emph{not} need to use the
@code{'upstream-name} property.
@end enumerate

The module @code{(guix build-system elm)} provides the following utilities
for working with names and related conventions:

@deffn {Procedure} elm-package-origin @var{elm-name} @var{version} @
  @var{hash} Returns a Git origin using the repository naming and tagging
regime required for a published Elm package with the upstream name
@var{elm-name} at version @var{version} with sha256 checksum @var{hash}.

For example:
@lisp
(package
  (name "elm-html")
  (version "1.0.0")
  (source
   (elm-package-origin
    "elm/html"
    version
    (base32 "15k1679ja57vvlpinpv06znmrxy09lbhzfkzdc89i01qa8c4gb4a")))
  ...)
@end lisp
@end deffn

@deffn {Procedure} elm->package-name @var{elm-name}
Returns the Guix-style package name for an Elm package with upstream name
@var{elm-name}.

Note that there is more than one possible @var{elm-name} for which
@code{elm->package-name} will produce a given result.
@end deffn

@deffn {Procedure} guix-package->elm-name @var{package}
Given an Elm @var{package}, returns the possibly-inferred upstream name, or
@code{#f} the upstream name is not specified via the @code{'upstream-name}
property and can not be inferred by @code{infer-elm-package-name}.
@end deffn

@deffn {Procedure} infer-elm-package-name @var{guix-name}
Given the @var{guix-name} of an Elm package, returns the inferred upstream
name, or @code{#f} if the upstream name can't be inferred.  If the result is
not @code{#f}, supplying it to @code{elm->package-name} would produce
@var{guix-name}.
@end deffn

@node 字体
@subsection 字体

@cindex 字体
对于通常不会被用户安装用于排版的字体，或者随更大的软件包分发的字体，我们使用通常的命名规则。例如，这适用于 X.Org 系统附带的字体或 TeX
Live 附带的字体。

为了让用户更容易搜索字体，其它仅含有字体的软件包按以下规则命名，不管上游的包名是什么。

仅含有一个字体家族的软件包需要以@code{font-}开头；如果作者名字已知，则添加作者名字和@code{-}，接着是字体家族名字（把空格替换成破折号），（和通常一样，把所有的大写字母转换成小写字母）。例如，由
SIL 设计的 Gentium 字体家族打包后的名字是@code{font-sil-gentium}。

对于一个含有多个字体家族的软件包，用集合的名字替换字体家族的名字。例如，Liberation 字体含有三个家族，Liberation
Sans、Liberation Serif 和 Liberation
Mono。它们可以用@code{font-liberation-sans}等名字分开打包；但是由于它们以一个共同的名字分发，我们倾向于以@code{font-liberation}名字统一打包。

当同一个字体家族或字体集合的不同格式分开打包时，把破折号和格式（缩写）添加在软件包名字后面。我们用@code{-ttf}代表 TrueType
字体，@code{-otf}代表 OpenType 字体，@code{-type1}代表 PostScript Type 1 字体。


@node 代码风格
@section 代码风格

总的来说，我们的代码遵循 GNU 代码规范（@pxref{Top,,, standards, GNU 代码规范}）。但是，这个规范对 Scheme
的介绍不多，所以这儿提供一些额外的规则。

@menu
* 编程范例::                     怎样合成元素。
* 模块::                       在哪里保存代码？
* 数据类型和模式匹配::                实现数据结构。
* 格式化代码::                    书写规范。
@end menu

@node 编程范例
@subsection 编程范例

Guix 里的 Scheme 代码是以纯函数的风格写的。一个例外是有关输入/输出的代码，和实现底层概念的过程，如@code{memoize}过程。

@node 模块
@subsection 模块
@cindex build-side modules
@cindex host-side modules
Guile modules that are meant to be used on the builder side must live in the
@code{(guix build @dots{})} name space.  They must not refer to other Guix
or GNU modules.  However, it is OK for a ``host-side'' module to use a
build-side module.  As an example, the @code{(guix search-paths)} module
should not be imported and used by a package since it isn't meant to be used
as a ``build-side'' module.  It would also couple the module with the
package's dependency graph, which is undesirable.

关于更广的 GNU 系统的模块应该在@code{(gnu @dots{})}命名空间里而不是@code{(guix @dots{})}.

@node 数据类型和模式匹配
@subsection 数据类型和模式匹配

经典的 Lisp
倾向于用列表表示所有的东西，然后用@code{car}，@code{cdr}，@code{cadr}等手动浏览它们。这种风格有几个问题，特别是难以阅读，易出错，并且妨碍生成合适的类型错误报告。

@findex define-record-type*
@findex match-record
@cindex pattern matching
Guix code should define appropriate data types (for instance, using
@code{define-record-type*}) rather than abuse lists.  In addition, it should
use pattern matching, via Guile’s @code{(ice-9 match)} module, especially
when matching lists (@pxref{Pattern Matching,,, guile, GNU Guile Reference
Manual}); pattern matching for records is better done using
@code{match-record} from @code{(guix records)}, which, unlike @code{match},
verifies field names at macro-expansion time.

When defining a new record type, keep the @dfn{record type descriptor} (RTD)
private (@pxref{Records,,, guile, GNU Guile Reference Manual}, for more on
records and RTDs).  As an example, the @code{(guix packages)} module defines
@code{<package>} as the RTD for package records but it does not export it;
instead, it exports a type predicate, a constructor, and field accessors.
Exporting RTDs would make it harder to change the application binary
interface (because code in other modules might be matching fields by
position) and would make it trivial for users to forge records of that type,
bypassing any checks we may have in the official constructor (such as
``field sanitizers'').

@node 格式化代码
@subsection 格式化代码

@cindex 格式化代码
@cindex 代码风格
When writing Scheme code, we follow common wisdom among Scheme programmers.
In general, we follow the
@url{https://mumble.net/~campbell/scheme/style.txt, Riastradh's Lisp Style
Rules}.  This document happens to describe the conventions mostly used in
Guile’s code too.  It is very thoughtful and well written, so please do read
it.

一些 Guix 添加的 special
form，如@code{substitute*}宏，有特殊的缩进规则。它们的规则在@file{.dir-locals.el}文件里定义，Emacs
会自动使用。另外，Emacs-Guix 提供的@code{guix-devel-mode}模式可以正确地缩进和高亮 Guix
代码（@pxref{Development,,, emacs-guix, Emacs-Guix 参考手册}）。

@cindex 代码缩进
@cindex 代码格式化
If you do not use Emacs, please make sure your editor knows these rules.  To
automatically indent a package definition, you can also run:

@example
./pre-inst-env guix style @var{package}
@end example

@noindent
@xref{调用 guix style}, for more information.

我们要求所有的顶级过程附带一个 docstring。这个要求对@code{(guix build @dots{})}命名空间里的简单的私有过程可以放宽。

过程不应该有多于四个定位参数。对于接收多于四个定位参数的过程应使用关键字参数。


@node 提交补丁
@section 提交补丁

Development is done using the Git distributed version control system.  Thus,
access to the repository is not strictly necessary.  We welcome
contributions in one of the following forms:

@itemize
@item
@cindex pull request, for contributions
As a @dfn{pull request} (PR) at
@url{https://codeberg.org/guix/guix/pulls/}.  This is now the preferred
form.

@item
Until December 31st, 2025@footnote{This date is the result of a decision
made collectively in
@uref{https://codeberg.org/guix/guix-consensus-documents/src/branch/main/002-codeberg.md,
Guix Consensus Document 002} in May 2025.}, you may also send patches as
produced by @code{git format-patch} to the @email{guix-patches@@gnu.org}
mailing list (@pxref{Submitting patches to a project,,, git, Git User
Manual}).

This mailing list is backed by a Debbugs instance, which allows us to keep
track of submissions (@pxref{跟踪程序漏洞及改动}).  Each message sent
to that mailing list gets a new tracking number assigned; people can then
follow up on the submission by sending email to
@code{@var{ISSUE_NUMBER}@@debbugs.gnu.org}, where @var{ISSUE_NUMBER} is the
tracking number (@pxref{发送补丁系列}).
@end itemize

Either way, contributors are encouraged to take a moment to set some Git
repository options (@pxref{配置 Git}) first, which can improve the
readability of patches.  Seasoned Guix developers may also want to look at
the section on commit access (@pxref{提交权利}).

请以 ChangeLog 格式（@pxref{Change Logs,,, standards, GNU 代码规范}）写 commit 日志；你可以浏览
commit 历史里的例子。

You can help make the review process more efficient, and increase the chance
that your patch will be reviewed quickly, by describing the context of your
patch and the impact you expect it to have.  For example, if your patch is
fixing something that is broken, describe the problem and how your patch
fixes it.  Tell us how you have tested your patch.  Will users of the code
changed by your patch have to adjust their workflow at all? If so, tell us
how.  In general, try to imagine what questions a reviewer will ask, and
answer those questions in advance.

提交添加或者修改软件包定义的补丁之前，请过一遍这个检查列表：

@enumerate
@item
如果软件包的作者为发布的文件包提供了密码学签名，请验证文件的真实性。对于独立的 GPG 签名文件，这可以通过 @code{gpg --verify}
命令完成。

@item
花些时间为软件包提供一个合适的简介和描述。更多指导，@xref{简介和描述}.

@item
运行@command{guix lint
@var{软件包}}，@var{软件包}是新添加的或修改过的软件包的名字，修复它报告的错误（@pxref{调用 guix lint}）。

@item
Run @command{guix style @var{package}} to format the new package definition
according to the project's conventions (@pxref{调用 guix style}).

@item
Make sure the package builds on your platform, using @command{guix build
@var{package}}.  Also build at least its direct dependents with
@command{guix build --dependents=1 @var{package}} (@pxref{build-dependents,
@command{guix build}}).

@item
We recommend you also try building the package on other supported
platforms.  As you may not have access to actual hardware platforms, we
recommend using the @code{qemu-binfmt-service-type} to emulate them.  In
order to enable it, add the @code{virtualization} service module and the
following service to the list of services in your @code{operating-system}
configuration:

@lisp
(service qemu-binfmt-service-type
 (qemu-binfmt-configuration
   (platforms (lookup-qemu-platforms "arm" "aarch64"))))
@end lisp

然后重新配置你的系统。

You can then build packages for different platforms by specifying the
@code{--system} option.  For example, to build the "hello" package for the
armhf or aarch64 architectures, you would run the following commands,
respectively:
@example
guix build --system=armhf-linux --rounds=2 hello
guix build --system=aarch64-linux --rounds=2 hello
@end example

@item
@cindex 构建
请确保软件包里不捆绑出现已经被打过包的软件的副本。

有时，软件包为了方便用户，捆绑了依赖库的源代码。然而，当依赖库在发行版里已经存在时，做为一个发行版，我们希望确保这些软件包使用发行版里已有的副本。这提高资源使用率（依赖库只构建一次，存储一份），并且使发行版更容易管理，如仅在一个地方对某个软件包进行安全更新就可以影响整个系统－－捆绑软件会妨碍这么做。

@item
Take a look at the profile reported by @command{guix size} (@pxref{调用 guix size}).  This will allow you to notice references to other packages
unwillingly retained.  It may also help determine whether to split the
package (@pxref{有多个输出的软件包}), and which optional
dependencies should be used.  In particular, avoid adding @code{texlive} as
a dependency: because of its extreme size, use @code{texlive-local-tree}
procedure instead.

@item
Check that dependent packages (if applicable) are not affected by the
change; @command{guix refresh --list-dependent @var{package}} will help you
do that (@pxref{调用 guix refresh}).

@item
@cindex 构建过程的确定性
@cindex 检查可复现的构建
检查软件包的构建过程是不是确定性的。这通常意味着检查对软件包的独立构建是否能得到每一个比特都完全相同的结果。

为此，一个简单的做法是在你的机器上多次构建同一个软件包（@pxref{调用 guix build}):

@example
guix build --rounds=2 <我的软件包>
@end example

这足以查出一批普通的不确定性问题，如构建结果里存在时间戳或随机生成的输出。

另一个选择是使用@command{guix challenge}（@pxref{调用 guix challenge}）。当软件包被提交并且被@code{@value{SUBSTITUTE-SERVER-1}}构建之后，你可以运行这个命令检查你是否得到相同的构建结果。更好的：找另一台可以构建的机器，运行@command{guix
publish}。由于远程的构建机器很可能和你的机器不同，这可以捕捉到由硬件不同引起的不确定性问题－－如，使用不同的指令集－－或不同操作系统内核引起的问题－－如，对@code{uname}或@file{/proc}文件的依赖。

@item
在编写文档时，请用性别中立的词语指代人，如@uref{https://en.wikipedia.org/wiki/Singular_they,
“他”@comma{} “他的”}，等。

@item
检查你的补丁只包含一些相关的更改。把不相关的更改捆绑在一起会让评审更困难和更慢。

不相关的更改的例子有：同时新增多个软件包，或更新软件包同时修补这个软件包。

@item
Please follow our code formatting rules, possibly running @command{guix
style} script to do that automatically for you (@pxref{格式化代码}).

@item
当可能时，请在源 URL 里使用镜像@pxref{调用 guix download}。使用可靠的而不是生成的 URL。例如，GitHub
的下载文件每次生成时不一定是相同的，所以这时最好克隆仓库。不要在 URL 里使用@code{name}变量：这没有什么用，而且如果名字变了，URL
很可能就错了。

@item
Check if Guix builds (@pxref{从 Git 构建}) and address the warnings,
especially those about use of undefined symbols.

@item
Make sure your changes do not break Guix and simulate a @command{guix pull}
with:
@example
guix pull --url=/path/to/your/checkout --profile=/tmp/guix.master --disable-authentication
@end example

@end enumerate

When posting a patch to the mailing list, use @samp{[PATCH] @dots{}} as a
subject, if your patch is to be applied on a branch other than
@code{master}, say @code{core-updates}, specify it in the subject like
@samp{[PATCH core-updates] @dots{}}.

You may use your email client, the @command{git send-email} command
(@pxref{发送补丁系列}) or the @command{mumi send-email} command
(@pxref{Debbugs User Interfaces}).  We prefer to get patches in plain text
messages, either inline or as MIME attachments.  You are advised to pay
attention if your email client changes anything like line breaks or
indentation which could potentially break the patches.

Expect some delay when you submit your very first patch to
@email{guix-patches@@gnu.org}. You have to wait until you get an
acknowledgement with the assigned tracking number. Future acknowledgements
should not be delayed.

When a bug is resolved, please close the thread by sending an email to
@email{@var{ISSUE_NUMBER}-done@@debbugs.gnu.org}.

@menu
* 配置 Git::                   配置 Git
* 发送补丁系列::                   发送补丁系列
@end menu

@node 配置 Git
@subsection 配置 Git
@cindex git configuration
@cindex @code{git format-patch}
@cindex @code{git send-email}

If you have not done so already, you may wish to set a name and email that
will be associated with your commits (@pxref{telling git your name, ,
Telling Git your name, git, Git User Manual}).  If you wish to use a
different name or email just for commits in this repository, you can use
@command{git config --local}, or edit @file{.git/config} in the repository
instead of @file{~/.gitconfig}.

@cindex commit-msg hook
Other important Git configuration will automatically be configured when
building the project (@pxref{从 Git 构建}).  A
@file{.git/hooks/commit-msg} hook will be installed that embeds
@samp{Change-Id} Git @emph{trailers} in your commit messages for
traceability purposes.  It is important to preserve these when editing your
commit messages, particularly if a first version of your proposed changes
was already submitted for review.  If you have a @file{commit-msg} hook of
your own you would like to use with Guix, you can place it under the
@file{.git/hooks/commit-msg.d/} directory.

@node 发送补丁系列
@subsection 发送补丁系列
@cindex 补丁系列
@cindex @code{git send-email}
@cindex @code{git format-patch}

@quotation 警告
This section is about contributing code by sending patches by email.  This
option is supported until December 31st, 2025, but we recommend getting
familiar with the @dfn{pull request} workflow, which will become the norm
after that date.  @xref{提交补丁}, for more info.
@end quotation

@unnumberedsubsubsec Single Patches
@anchor{Single Patches}
The @command{git send-email} command is the best way to send both single
patches and patch series (@pxref{Multiple Patches}) to the Guix mailing
list.  Sending patches as email attachments may make them difficult to
review in some mail clients, and @command{git diff} does not store commit
metadata.

@quotation 注
The @command{git send-email} command is provided by the @code{send-email}
output of the @code{git} package, i.e. @code{git:send-email}.
@end quotation

The following command will create a patch email from the latest commit, open
it in your @var{EDITOR} or @var{VISUAL} for editing, and send it to the Guix
mailing list to be reviewed and merged.  Assuming you have already
configured Git according to @xref{配置 Git}, you can simply use:

@example
$ git send-email --annotate -1
@end example

@quotation Tip
要在补丁的主题前添加前缀，可以使用 @option{--subject-prefix} 选项。Guix 项目使用此选项来指定补丁是针对
@url{https://codeberg.org/guix/guix.git} 的 @code{master} 分支以外的分支或仓库。

@example
git send-email --annotate --subject-prefix='PATCH core-updates' -1
@end example
@end quotation

The patch email contains a three-dash separator line after the commit
message.  You may ``annotate'' the patch with explanatory text by adding it
under this line.  If you do not wish to annotate the email, you may drop the
@option{--annotate} option.

If you need to send a revised patch, don't resend it like this or send a
``fix'' patch to be applied on top of the last one; instead, use
@command{git commit --amend} or @url{https://git-rebase.io, @command{git
rebase}} to modify the commit, and use the
@email{@var{ISSUE_NUMBER}@@debbugs.gnu.org} address and the @option{-v} flag
with @command{git send-email}.

@example
$ git commit --amend
$ git send-email --annotate -v@var{REVISION} \
      --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org -1
@end example

@quotation 注
Due to an apparent bug in @command{git send-email}, @option{-v
@var{REVISION}} (with the space) will not work; you @emph{must} use
@option{-v@var{REVISION}}.
@end quotation

You can find out @var{ISSUE_NUMBER} either by searching on the mumi
interface at @url{https://issues.guix.gnu.org} for the name of your patch or
reading the acknowledgement email sent automatically by Debbugs in reply to
incoming bugs and patches, which contains the bug number.

@unnumberedsubsubsec Notifying Teams
@anchor{Notifying Teams}
@cindex teams
If your git checkout has been correctly configured (@pxref{配置 Git}), the @command{git send-email} command will automatically notify the
appropriate team members, based on the scope of your changes.  This relies
on the @file{etc/teams.scm} script, which can also be invoked manually if
you do not use the preferred @command{git send-email} command to submit
patches.  To list the available actions of the script, you can invoke it via
the @command{etc/teams.scm help} command.  For more information regarding
teams, @pxref{团队}.

@quotation 注
On foreign distros, you might have to use @command{./pre-inst-env git
send-email} for @file{etc/teams.scm} to work.
@end quotation

@unnumberedsubsubsec Multiple Patches
@anchor{Multiple Patches}
@cindex cover letter
While @command{git send-email} alone will suffice for a single patch, an
unfortunate flaw in Debbugs means you need to be more careful when sending
multiple patches: if you send them all to the @email{guix-patches@@gnu.org}
address, a new issue will be created for each patch!

When sending a series of patches, it's best to send a Git ``cover letter''
first, to give reviewers an overview of the patch series.  We can create a
directory called @file{outgoing} containing both our patch series and a
cover letter called @file{0000-cover-letter.patch} with @command{git
format-patch}.

@example
$ git format-patch -@var{NUMBER_COMMITS} -o outgoing \
      --cover-letter
@end example

@quotation 注
@code{git format-patch} accepts a wide range of
@uref{https://git-scm.com/docs/gitrevisions, revision range} specifiers.
For example, if you are working in a branch, you could select all commits in
your branch starting at @code{master}.

@example
$ git format-patch master..@var{MY_BRANCH} -o outgoing \
      --cover-letter
@end example
@end quotation

We can now send @emph{just} the cover letter to the
@email{guix-patches@@gnu.org} address, which will create an issue that we
can send the rest of the patches to.

@example
$ git send-email outgoing/0000-cover-letter.patch --annotate
$ rm outgoing/0000-cover-letter.patch # we don't want to resend it!
@end example

Ensure you edit the email to add an appropriate subject line and blurb
before sending it.  Note the automatically generated shortlog and diffstat
below the blurb.

Once the Debbugs mailer has replied to your cover letter email, you can send
the actual patches to the newly-created issue address.

@example
$ git send-email outgoing/*.patch --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org
$ rm -rf outgoing # 我们不再需要这些了
@end example

Thankfully, this @command{git format-patch} dance is not necessary to send
an amended patch series, since an issue already exists for the patchset.

@example
$ git send-email -@var{NUMBER_COMMITS} -v@var{REVISION} \
      --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org
@end example

If need be, you may use @option{--cover-letter --annotate} to send another
cover letter, e.g. for explaining what's changed since the last revision,
and why these changes are necessary.

@node 跟踪程序漏洞及改动
@section 跟踪程序漏洞及改动

This section describes how the Guix project tracks its bug reports, patch
submissions and topic branches.

@menu
* The Issue Tracker::        The official bug and patch tracker.
* Managing Patches and Branches::  How changes to Guix are managed.
* Debbugs User Interfaces::  Ways to interact with Debbugs.
* Debbugs Usertags::         Tag reports with custom labels.
* Cuirass Build Notifications::  Be alerted of any breakage via RSS feeds.
@end menu

@node The Issue Tracker
@subsection The Issue Tracker

@cindex bug reports, tracking
@cindex patch submissions, tracking
@cindex issue tracking
@cindex Debbugs, issue tracking system
Bug reports (@dfn{issues}) and patch submissions (@dfn{pull requests})  are
currently tracked at the @uref{https://codeberg.org/guix/guix, project's
home at Codeberg}.

Before May 25th, 2025, bug reports and patches were exclusively tracked
using the Debbugs instance at @uref{https://bugs.gnu.org}; it may still be
used for these purposes until December 31st, 2025, after which Codeberg will
become the sole option to report new bugs and propose new
changes@footnote{Check out
@uref{https://codeberg.org/guix/guix-consensus-documents/src/branch/main/002-codeberg.md,
Guix Consensus Document 002} for details on this decision.}.  With Debbugs,
bug reports are sent by email to @email{bug-guix@@gnu.org} and patches are
sent to @email{guix-patches@@gnu.org} (@pxref{提交补丁}).

@node Managing Patches and Branches
@subsection Managing Patches and Branches
@cindex 分支策略
@cindex 重新构建的调度策略

@c TODO: Update when qa.guix is hooked up to Codeberg.
Submitted patches are picked up and tested by the quality assurance service;
the result of that testing eventually shows up on the dashboard at
@indicateurl{https://qa.guix.gnu.org/issue/@var{ISSUE_NUMBER}}, where
@var{ISSUE_NUMBER} is the number assigned by the issue tracker, currently
Debbugs (work is in progress to support Codeberg pull requests).  Leave time
for a review, without committing anything.

As an exception, some changes considered ``trivial'' or ``obvious'' may be
pushed directly to the @code{master} branch.  This includes changes to fix
typos and reverting commits that caused immediate problems.  This is subject
to being adjusted, allowing individuals to commit directly on
non-controversial changes on parts they’re familiar with.

Changes which affect more than 300 dependent packages (@pxref{调用 guix refresh}) should first be pushed to a topic branch other than @code{master};
the set of changes should be consistent---e.g., ``GNOME update'', ``NumPy
update'', etc.  This allows for testing: the branch will automatically show
up at @indicateurl{https://qa.guix.gnu.org/branch/@var{branch}}, with an
indication of its build status on various platforms.

@cindex feature branches, coordination
To help coordinate the merging of branches, you must create a new
guix-patches issue each time you create a branch (@pxref{The Issue Tracker}).  The title of the issue requesting to merge a branch should have
the following format:

@cindex merge requests, template
@example
Request for merging "@var{name}" branch
@end example

The @url{https://qa.guix.gnu.org/, QA infrastructure} recognizes such issues
and lists the merge requests on its main page.  The following points apply
to managing these branches:

@enumerate
@item
The commits on the branch should be a combination of the patches relevant to
the branch.  Patches not related to the topic of the branch should go
elsewhere.

@item
Any changes that can be made on the master branch, should be made on the
master branch.  If a commit can be split to apply part of the changes on
master, this is good to do.

@item
It should be possible to re-create the branch by starting from master and
applying the relevant patches.

@item
Avoid merging master in to the branch.  Prefer rebasing or re-creating the
branch on top of an updated master revision.

@item
Minimise the changes on master that are missing on the branch prior to
merging the branch in to master.  This means that the state of the branch
better reflects the state of master should the branch be merged.

@item
If you don't have commit access, create the ``Request for merging'' issue
and request that someone creates the branch.  Include a list of
issues/patches to include on the branch.
@end enumerate

Normally branches will be merged in a ``first come, first merged'' manner,
tracked through the guix-patches issues.  If you agree on a different order
with those involved, you can track this by updating which issues
block@footnote{You can mark an issue as blocked by another by emailing
@email{control@@debbugs.gnu.org} with the following line in the body of the
email: @code{block XXXXX by YYYYY}.  Where @code{XXXXX} is the number for
the blocked issue, and @code{YYYYY} is the number for the issue blocking
it.} which other issues.  Therefore, to know which branch is at the front of
the queue, look for the oldest issue, or the issue that isn't @dfn{blocked}
by any other branch merges.  An ordered list of branches with the open
issues is available at @url{https://qa.guix.gnu.org}.

Once a branch is at the front of the queue, wait until sufficient time has
passed for the build farms to have processed the changes, and for the
necessary testing to have happened.  For example, you can check
@indicateurl{https://qa.guix.gnu.org/branch/@var{branch}} to see information
on some builds and substitute availability.

Once the branch has been merged, the issue should be closed and the branch
deleted.

@cindex work-in-progress branches, wip
@cindex wip branches
Sometimes, a branch may be a work in progress, for example for larger
efforts such as updating the GNOME desktop.  In these cases, the branch name
should reflect this by having the @samp{wip-} prefix.  The QA infrastructure
will avoid building work-in-progress branches, so that the available
resources can be better focused on building the branches that are ready to
be merged.  When the branch is no longer a work in progress, it should be
renamed, with the @samp{wip-} prefix removed, and only then should the merge
requests be created, as documented earlier.

@node Debbugs User Interfaces
@subsection Debbugs User Interfaces

@quotation 警告
This section is about bug reports and patches sent by email to
@uref{https://issues.guix.gnu.org, Debbugs}.  This option is supported until
December 31st, 2025, after which @uref{https://codeberg.org/guix/guix,
Codeberg} will be the only interface for submitting bug reports and
changes.  @xref{提交补丁}, for more info.
@end quotation

@subsubsection Web interface

@cindex mumi, web interface for issues
A web interface (actually @emph{two} web interfaces!) are available to
browse issues:

@itemize
@item
@url{https://issues.guix.gnu.org} provides a pleasant interface powered by
mumi@footnote{Mumi is a nice piece of software written in Guile, and you can
help! See @url{https://codeberg.org/guix/mumi}.} to browse bug reports and
patches, and to participate in discussions; mumi also has a command-line
interface as we will see below;
@item
@url{https://bugs.gnu.org/guix} lists bug reports;
@item
@url{https://bugs.gnu.org/guix-patches} lists patch submissions.
@end itemize

To view discussions related to issue number @var{n}, go to
@indicateurl{https://issues.guix.gnu.org/@var{n}} or
@indicateurl{https://bugs.gnu.org/@var{n}}.

@subsubsection Command-Line Interface

@cindex mumi command-line interface
@cindex mumi am
@cindex mumi compose
@cindex mumi send-email
@cindex mumi www
Mumi also comes with a command-line interface that can be used to search
existing issues, open new issues, compose replies, apply and send patches.
You do not need to use Emacs to use the mumi command-line client.  You
interact with it only on the command-line.

To use the mumi command-line interface, navigate to a local clone of the
Guix git repository, and drop into a shell with mumi, git and git:send-email
installed.

@example
$ cd guix
~/guix$ guix shell mumi git git:send-email
@end example

To search for issues, say all open issues about "zig", run

@example
~/guix [env]$ mumi search zig is:open

#60889 Add zig-build-system
opened on 17 Jan 17:37 Z by Ekaitz Zarraga
#61036 [PATCH 0/3] Update zig to 0.10.1
opened on 24 Jan 09:42 Z by Efraim Flashner
#39136 [PATCH] gnu: services: Add endlessh.
opened on 14 Jan 2020 21:21 by Nicol? Balzarotti
#60424 [PATCH] gnu: Add python-online-judge-tools
opened on 30 Dec 2022 07:03 by gemmaro
#45601 [PATCH 0/6] vlang 0.2 update
opened on  1 Jan 2021 19:23 by Ryan Prior
@end example

Pick an issue and make it the "current" issue.

@example
~/guix [env]$ mumi current 61036

#61036 [PATCH 0/3] Update zig to 0.10.1
opened on 24 Jan 09:42 Z by Efraim Flashner
@end example

Once an issue is the current issue, you can open the issue in a web browser,
compose replies, apply patches, send patches, etc. with short succinct
commands.

Open the issue in your web browser using

@example
~/guix [env]$ mumi www
@end example

Compose a reply using

@example
~/guix [env]$ mumi compose
@end example

Compose a reply and close the issue using

@example
~/guix [env]$ mumi compose --close
@end example

@command{mumi compose} opens your mail client by passing @samp{mailto:} URIs
to @command{xdg-open}.  So, you need to have @command{xdg-open} set up to
open your mail client correctly.

Apply the latest patchset from the issue using

@example
~/guix [env]$ mumi am
@end example

You may also apply a patchset of a specific version (say, v3) using

@example
~/guix [env]$ mumi am v3
@end example

Or, you may apply a patch from a specific e-mail message.  For example, to
apply the patch from the 4th message (message index starts from 0), run

@example
~/guix [env]$ mumi am @@4
@end example

@command{mumi am} is a wrapper around @command{git am}.  You can pass
@command{git am} arguments to it after a @samp{--}.  For example, to add a
Signed-off-by trailer, run

@example
~/guix [env]$ mumi am -- -s
@end example

Create and send patches to the issue using

@example
~/guix [env]$ git format-patch origin/master
~/guix [env]$ mumi send-email foo.patch bar.patch
@end example

Note that you do not have to pass in @samp{--to} or @samp{--cc} arguments to
@command{git format-patch}.  @command{mumi send-email} will put them in
correctly when sending the patches.

To open a new issue, run

@example
~/guix [env]$ mumi new
@end example

and send an email (using @command{mumi compose}) or patches (using
@command{mumi send-email}).

@command{mumi send-email} is really a wrapper around @command{git
send-email} that automates away all the nitty-gritty of sending patches.  It
uses the current issue state to automatically figure out the correct
@samp{To} address to send to, other participants to @samp{Cc}, headers to
add, etc.

Also note that, unlike @command{git send-email}, @command{mumi send-email}
works perfectly well with single and multiple patches alike.  It automates
away the debbugs dance of sending the first patch, waiting for a response
from debbugs and sending the remaining patches.  It does so by sending the
first patch, polling the server for a response, and then sending the
remaining patches.  This polling can unfortunately take a few minutes.  So,
please be patient.

@subsubsection Emacs Interface

If you use Emacs, you may find it more convenient to interact with issues
using @file{debbugs.el}, which you can install with:

@example
guix install emacs-debbugs
@end example

For example, to list all open issues on @code{guix-patches}, hit:

@example
@kbd{C-u} @kbd{M-x} debbugs-gnu @kbd{RET} @kbd{RET} guix-patches @kbd{RET} n y
@end example

For a more convenient (shorter) way to access both the bugs and patches
submissions, you may want to configure the
@code{debbugs-gnu-default-packages} and
@code{debbugs-gnu-default-severities} Emacs variables (@pxref{在 Emacs 内部浏览漏洞}).

To search for bugs, @samp{@kbd{M-x} debbugs-gnu-guix-search} can be used.

@xref{Top,,, debbugs-ug, Debbugs User Guide}，了解更多有关此实用工具的信息！

@node Debbugs Usertags
@subsection Debbugs Usertags

@cindex usertags, for debbugs
@cindex Debbugs usertags
Debbugs provides a feature called @dfn{usertags} that allows any user to tag
any bug with an arbitrary label.  Bugs can be searched by usertag, so this
is a handy way to organize bugs@footnote{The list of usertags is public
information, and anyone can modify any user's list of usertags, so keep that
in mind if you choose to use this feature.}.  If you use Emacs Debbugs, the
entry-point to consult existing usertags is the @samp{C-u M-x
debbugs-gnu-usertags} procedure.  To set a usertag, press @samp{C} while
consulting a bug within the *Guix-Patches* buffer opened with @samp{C-u M-x
debbugs-gnu-bugs} buffer, then select @code{usertag} and follow the
instructions.

For example, to view all the bug reports (or patches, in the case of
@code{guix-patches}) tagged with the usertag @code{powerpc64le-linux} for
the user @code{guix}, open a URL like the following in a web browser:
@url{https://debbugs.gnu.org/cgi-bin/pkgreport.cgi?tag=powerpc64le-linux;users=guix}.

For more information on how to use usertags, please refer to the
documentation for Debbugs or the documentation for whatever tool you use to
interact with Debbugs.

In Guix, we are experimenting with usertags to keep track of
architecture-specific issues, as well as reviewed ones.  To facilitate
collaboration, all our usertags are associated with the single user
@code{guix}.  The following usertags currently exist for that user:

@table @code

@item powerpc64le-linux
The purpose of this usertag is to make it easy to find the issues that
matter most for the @code{powerpc64le-linux} system type.  Please assign
this usertag to bugs or patches that affect @code{powerpc64le-linux} but not
other system types.  In addition, you may use it to identify issues that for
some reason are particularly important for the @code{powerpc64le-linux}
system type, even if the issue affects other system types, too.

@item reproducibility
For issues related to reproducibility.  For example, it would be appropriate
to assign this usertag to a bug report for a package that fails to build
reproducibly.

@item reviewed-looks-good
You have reviewed the series and it looks good to you (LGTM).

@end table

If you're a committer and you want to add a usertag, just start using it
with the @code{guix} user.  If the usertag proves useful to you, consider
updating this section of the manual so that others will know what your
usertag means.

@node Cuirass Build Notifications
@subsection Cuirass Build Notifications

@cindex build event notifications, RSS feed
@cindex notifications, build events
Cuirass includes @acronym{RSS, Really Simple Syndication} feeds as one of
its features (@pxref{Notifications,,,cuirass}).  Since
@url{https://ci.guix.gnu.org/, Berlin} runs an instance of Cuirass, this
feature can be used to keep track of recently broken or fixed packages
caused by changes pushed to the Guix git repository.  Any RSS client can be
used.  A good one, included with Emacs, is @xref{Gnus,,,gnus}.  To register
the feed, copy its URL, then from the main Gnus buffer, @samp{*Group*}, do
the following:

@cindex Gnus, configuration to read CI RSS feeds
@cindex RSS feeds, Gnus configuration
@example
@kbd{G R} https://ci.guix.gnu.org/events/rss/?specification=master RET
Guix CI - master RET Build events for specification master. RET
@end example

@noindent
Then, back at the @samp{*Group*} buffer, press @kbd{s} to save the newly
added RSS group.  As for any other Gnus group, you can update its content by
pressing the @kbd{g} key.  You should now receive notifications that read
like:

@example
 . [ ?: Cuirass ] Build tree-sitter-meson.aarch64-linux on master is fixed.
 . [ ?: Cuirass ] Build rust-pbkdf2.aarch64-linux on master is fixed.
 . [ ?: Cuirass ] Build rust-pbkdf2.x86_64-linux on master is fixed.
@end example

@noindent
where each RSS entry contains a link to the Cuirass build details page of
the associated build.

@node 团队
@section 团队
@cindex teams

To organize work on Guix, including but not just development efforts, the
project has a set of @dfn{teams}.  Each team has its own focus and interests
and is the primary contact point for questions and contributions in those
areas.  A team's primary mission is to coordinate and review the work of
individuals in its scope (@pxref{审阅他人的工作}); it can make
decisions within its scope, in agreement with other teams whenever there is
overlap or a close connection, and in accordance with other project rules
such as seeking consensus (@pxref{做出决定}).

As an example, the Python team is responsible for core Python packaging
matters; it can decide to upgrade core Python packages in a dedicated
@code{python-team} branch, in collaboration with any team whose scope is
directly dependent on Python---e.g., the Science team---and following
branching rules (@pxref{Managing Patches and Branches}).  The Documentation
team helps review changes to the documentation and can initiate overarching
documentation changes.  The Translations team organizes translation of Guix
and its manual and coordinates efforts in that area.  The Core team is
responsible for the development of core functionality and interfaces of
Guix; because of its central nature, some of its work may require soliciting
input from the community at large and seeking consensus before enacting
decisions that would affect the entire community.

Teams are defined in the @file{etc/teams.scm} file in the Guix repository.
The scope of each team is defined, when applicable, as a set of files or as
a regular expression matching file names.

@cindex team membership
Anyone with interest in a team's domain and willing to contribute to its
work can apply to become a member by contacting current members by email;
commit access is not a precondition.  Membership is formalized by adding the
person's name and email address to @file{etc/teams.scm}.  Members who have
not been participating in the team's work for one year or more may be
removed; they are free to reapply for membership later.

@cindex team creation
One or more people may propose the creation of a new team by reaching out to
the community by email at @email{guix-devel@@gnu.org}, clarifying the
intended scope and purpose.  When consensus is reached on the creation of
this team, someone with commit access formalizes its creation by adding it
and its initial members to @file{etc/teams.scm}.

To list existing teams, run the following command from a Guix checkout:

@example
$ ./etc/teams.scm list-teams
id: mentors
name: Mentors
description: A group of mentors who chaperone contributions by newcomers.
members:
+ Charlie Smith <charlie@@example.org>
@dots{}
@end example

@cindex mentoring
You can run the following command to have the Mentors team put in CC of a
patch series:

@example
$ git send-email --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org \
  --header-cmd='etc/teams.scm cc-mentors-header-cmd' *.patch
@end example

The appropriate team or teams can also be inferred from the modified files.
For instance, if you want to send the two latest commits of the current Git
repository to review, you can run:

@example
$ guix shell -D guix
[env]$ git send-email --to=@var{ISSUE_NUMBER}@@debbugs.gnu.org -2
@end example

@cindex teams, on Codeberg
To generate a @file{CODEOWNERS} file, which Forgejo---the software behind
Codeberg---uses to determine which team or person should review changes to a
given set of files, run:

@example
./etc/teams.scm codeowners > CODEOWNERS
@end example

Teams defined in @file{etc/teams.scm} are reflected
@uref{https://codeberg.org/guix/guix, on Codeberg}; the ``Owners'' team on
Codeberg, whose members have administration privileges over
@uref{https://codeberg.org/guix, the entire ``organization''}, is the only
one missing from this file.  To synchronize team changes with Codeberg, a
member of the ``Owners'' team can run:

@example
./etc/teams.scm sync-codeberg-teams @var{token}
@end example

@noindent
... where @var{token} is a token created via the
@url{https://codeberg.org/user/settings/applications, Codeberg applications
settings page}, granting read/write access to the @samp{organization}
permission.

@node 做出决定
@section 做出决定

@cindex decision making
@cindex consensus seeking
It is expected from all contributors, and even more so from committers, to
help build consensus and make decisions based on consensus.  By using
consensus, we are committed to finding solutions that everyone can live
with.  It implies that no decision is made against significant concerns and
these concerns are actively resolved with proposals that work for everyone.

A contributor (who may or may not have commit access) wishing to block a
proposal bears a special responsibility for finding alternatives, proposing
ideas/code or explain the rationale for the status quo to resolve the
deadlock.  To learn what consensus decision making means and understand its
finer details, you are encouraged to read
@url{https://www.seedsforchange.org.uk/consensus}.

@node 提交权利
@section 提交权利

@cindex commit access, for developers
Everyone can contribute to Guix without having commit access
(@pxref{提交补丁}).  However, for frequent contributors, having
write access to the repository can be convenient.  As a rule of thumb, a
contributor should have accumulated fifty (50) reviewed commits to be
considered as a committer and have sustained their activity in the project
for at least 6 months.  This ensures enough interactions with the
contributor, which is essential for mentoring and assessing whether they are
ready to become a committer.  Commit access should not be thought of as a
``badge of honor'' but rather as a responsibility a contributor is willing
to take to help the project.

Committers are in a position where they enact technical decisions.  Such
decisions must be made by @emph{actively building consensus} among
interested parties and stakeholders.  @xref{做出决定}, for more on
that.

The following sections explain how to get commit access, how to be ready to
push commits, and the policies and community expectations for commits pushed
upstream.

@subsection Applying for Commit Access

When you deem it necessary, consider applying for commit access by following
these steps:

@enumerate
@item
Find three committers who would vouch for you.  Each of them should email a
statement to @email{guix-maintainers@@gnu.org} (a private alias for the
collective of maintainers), signed with their OpenPGP key.

Committers are expected to have had some interactions with you as a
contributor and to be able to judge whether you are sufficiently familiar
with the project's practices.  It is @emph{not} a judgment on the value of
your work, so a refusal should rather be interpreted as ``let's try again
later''.

@item
Send @email{guix-maintainers@@gnu.org} a message stating your intent,
listing the three committers who support your application, signed with the
OpenPGP key you will use to sign commits, and giving its fingerprint (see
below).  See @uref{https://emailselfdefense.fsf.org/en/}, for an
introduction to public-key cryptography with GnuPG.

@c See <https://sha-mbles.github.io/>.
Set up GnuPG such that it never uses the SHA1 hash algorithm for digital
signatures, which is known to be unsafe since 2019, for instance by adding
the following line to @file{~/.gnupg/gpg.conf} (@pxref{GPG Esoteric
Options,,, gnupg, The GNU Privacy Guard Manual}):

@example
digest-algo sha512
@end example

@item
Maintainers ultimately decide whether to grant you commit access, usually
following your referrals' recommendation.

@item
@cindex OpenPGP, signed commits
If and once you've been given access, please send a message to
@email{guix-devel@@gnu.org} to say so, again signed with the OpenPGP key you
will use to sign commits (do that before pushing your first commit).  That
way, everyone can notice and ensure you control that OpenPGP key.

@quotation Important
Before you can push for the first time, maintainers must:

@enumerate
@item
add your OpenPGP key to the @code{keyring} branch;
@item
add your OpenPGP fingerprint to the @file{.guix-authorizations} file of the
branch(es) you will commit to.
@end enumerate
@end quotation

@item
Make sure to read the rest of this section and... profit!
@end enumerate

@quotation 注
Maintainers are happy to give commit access to people who have been
contributing for some time and have a track record---don't be shy and don't
underestimate your work!

However, note that the project is working towards a more automated patch
review and merging system, which, as a consequence, may lead us to have
fewer people with commit access to the main repository.  Stay tuned!
@end quotation

所有推送到 Codeberg 中央存储库的提交必须使用 OpenPGP 密钥签名，并且公钥应上传到您在 Codeberg
的用户帐户和公共密钥服务器，例如 @code{keys.openpgp.org}。要配置 Git 自动签署提交，请运行：

@example
git config commit.gpgsign true

# 替换为您的公共 PGP 密钥指纹。
git config user.signingkey CABBA6EA1DC0FF33
@end example

To check that commits are signed with correct key, use:

@example
guix git authenticate
@end example

@xref{从 Git 构建} for running the first authentication of a Guix
checkout.

为了避免意外将未签名或使用错误密钥签名的提交推送到 Codeberg，请确保根据 @xref{配置 Git} 配置 Git。

@subsection Commit Policy

If you get commit access, please make sure to follow the policy below
(discussions of the policy can take place on @email{guix-devel@@gnu.org}).

Ensure you're aware of how the changes should be handled (@pxref{Managing Patches and Branches}) prior to being pushed to the repository, especially
for the @code{master} branch.

If you're committing and pushing your own changes, try and wait at least one
week (two weeks for more significant changes, up to one month for changes
such as removing a package---@pxref{package-removal-policy, Package
Removal}) after you send them for review.  After this, if no one else is
available to review them and if you're confident about the changes, it's OK
to commit.

When pushing a commit on behalf of somebody else, please add a
@code{Signed-off-by} line at the end of the commit log message---e.g., with
@command{git am --signoff}.  This improves tracking of who did what.

When adding channel news entries (@pxref{频道, Writing Channel News}),
make sure they are well-formed by running the following command right before
pushing:

@example
make check-channel-news
@end example

@subsection Addressing Issues

Peer review (@pxref{提交补丁}) and tools such as @command{guix
lint} (@pxref{调用 guix lint}) and the test suite (@pxref{运行测试套件}) should catch issues before they are pushed.  Yet, commits that
``break'' functionality might occasionally go through.  When that happens,
there are two priorities: mitigating the impact, and understanding what
happened to reduce the chance of similar incidents in the future.  The
responsibility for both these things primarily lies with those involved, but
like everything this is a group effort.

Some issues can directly affect all users---for instance because they make
@command{guix pull} fail or break core functionality, because they break
major packages (at build time or run time), or because they introduce known
security vulnerabilities.

@cindex reverting commits
The people involved in authoring, reviewing, and pushing such commit(s)
should be at the forefront to mitigate their impact in a timely fashion: by
pushing a followup commit to fix it (if possible), or by reverting it to
leave time to come up with a proper fix, and by communicating with other
developers about the problem.

If these persons are unavailable to address the issue in time, other
committers are entitled to revert the commit(s), explaining in the commit
log and on the mailing list what the problem was, with the goal of leaving
time to the original committer, reviewer(s), and author(s)  to propose a way
forward.

Once the problem has been dealt with, it is the responsibility of those
involved to make sure the situation is understood.  If you are working to
understand what happened, focus on gathering information and avoid assigning
any blame.  Do ask those involved to describe what happened, do not ask them
to explain the situation---this would implicitly blame them, which is
unhelpful.  Accountability comes from a consensus about the problem,
learning from it and improving processes so that it's less likely to
reoccur.

@subsubsection Reverting commits

Like normal commits, the commit message should state why the changes are
being made, which in this case would be why the commits are being reverted.

If the changes are being reverted because they led to excessive number of
packages being affected, then a decision should be made whether to allow the
build farms to build the changes, or whether to avoid this. For the bordeaux
build farm, commits can be ignored by adding them to the
@code{ignore-commits} list in the @code{build-from-guix-data-service}
record, found in the bayfront machine configuration.

@subsection Commit Revocation

In order to reduce the possibility of mistakes, committers will have their
Codeberg account removed from the Guix Codeberg project and their key
removed from @file{.guix-authorizations} after 12 months of inactivity; they
can ask to regain commit access by emailing the maintainers, without going
through the vouching process.

Maintainers@footnote{See @uref{https://guix.gnu.org/en/about} for the
current list of maintainers.  You can email them privately at
@email{guix-maintainers@@gnu.org}.} may also revoke an individual's commit
rights, as a last resort, if cooperation with the rest of the community has
caused too much friction---even within the bounds of the project's code of
conduct (@pxref{贡献}).  They would only do so after public or
private discussion with the individual and a clear notice.  Examples of
behavior that hinders cooperation and could lead to such a decision include:

@itemize
@item repeated violation of the commit policy stated above;
@item repeated failure to take peer criticism into account;
@item breaching trust through a series of grave incidents.
@end itemize

When maintainers resort to such a decision, they notify developers on
@email{guix-devel@@gnu.org}; inquiries may be sent to
@email{guix-maintainers@@gnu.org}.  Depending on the situation, the
individual may still be welcome to contribute.

@subsection Helping Out

One last thing: the project keeps moving forward because committers not only
push their own awesome changes, but also offer some of their time
@emph{reviewing} and pushing other people's changes.  As a committer, you're
welcome to use your expertise and commit rights to help other contributors,
too!

@node 审阅他人的工作
@section 审阅他人的工作

Perhaps the biggest action you can do to help GNU Guix grow as a project is
to review the work contributed by others.  You do not need to be a committer
to do so; applying, reading the source, building, linting and running other
people's series and sharing your comments about your experience will give
some confidence to committers.  You must ensure the check list found in the
@ref{提交补丁} section has been correctly followed.  A reviewed
patch series should give the best chances for the proposed change to be
merged faster, so if a change you would like to see merged hasn't yet been
reviewed, this is the most appropriate thing to do! If you would like to
review changes in a specific area and to receive notifications for incoming
patches relevant to that domain, consider joining the relevant team(s)
(@pxref{团队}).

@cindex reviewing, guidelines
Review comments should be unambiguous; be as clear and explicit as you can
about what you think should be changed, ensuring the author can take action
on it.  Please try to keep the following guidelines in mind during review:

@enumerate
@item
@emph{Be clear and explicit about changes you are suggesting}, ensuring the
author can take action on it.  In particular, it is a good idea to
explicitly ask for new revisions when you want it.

@item
@emph{Remain focused: do not change the scope of the work being reviewed.}
For example, if the contribution touches code that follows a pattern deemed
unwieldy, it would be unfair to ask the submitter to fix all occurrences of
that pattern in the code; to put it simply, if a problem unrelated to the
patch at hand was already there, do not ask the submitter to fix it.

@item
@emph{Ensure progress.} As they respond to review, submitters may submit new
revisions of their changes; avoid requesting changes that you did not
request in the previous round of comments.  Overall, the submitter should
get a clear sense of progress; the number of items open for discussion
should clearly decrease over time.

@item
@emph{Aim for finalization.} Reviewing code is time-consuming.  Your goal as
a reviewer is to put the process on a clear path towards integration,
possibly with agreed-upon changes, or rejection, with a clear and
mutually-understood reasoning.  Avoid leaving the review process in a
lingering state with no clear way out.

@item
@emph{Review is a discussion.} The submitter's and reviewer's views on how
to achieve a particular change may not always be aligned.  To lead the
discussion, remain focused, ensure progress and aim for finalization,
spending time proportional to the stakes@footnote{The tendency to discuss
minute details at length is often referred to as ``bikeshedding'', where
much time is spent discussing each one's preference for the color of the
shed at the expense of progress made on the project to keep bikes dry.}.  As
a reviewer, try hard to explain the rationale for suggestions you make, and
to understand and take into account the submitter's motivation for doing
things in a certain way.  In other words, build consensus with everyone
involved (@pxref{做出决定}).
@end enumerate

When you deem the proposed change adequate and ready for inclusion in Guix,
you can explicitly say so for pull requests on Codeberg, for example by
selecting ``Approve changes'' in the ``Finish review'' dialog of the web
interface.

@cindex LGTM, Looks Good To Me
@cindex review tags
@cindex Reviewed-by, git trailer
The following well understood/codified
@samp{Reviewed-by:@tie{}Your@tie{}Name@tie{}<your-email@@example.com>}
@footnote{The @samp{Reviewed-by} Git trailer is used by other projects such
as Linux, and is understood by third-party tools such as the @samp{b4 am}
sub-command, which is able to retrieve the complete submission email thread
from a public-inbox instance and add the Git trailers found in replies to
the commit patches.} line should be used to sign off as a reviewer, meaning
you have reviewed the change and that it looks good to you:

@itemize
@item
If the @emph{whole} series (containing multiple commits) looks good to you,
reply with
@samp{Reviewed-by:@tie{}Your@tie{}Name@tie{}<your-email@@example.com>} to
the cover page if it has one, or to the last patch of the series otherwise,
adding another @samp{(for the whole series)} comment on the line below to
explicit this fact.

@item
If you instead want to mark a @emph{single commit} as reviewed (but not the
whole series), simply reply with
@samp{Reviewed-by:@tie{}Your@tie{}Name@tie{}<your-email@@example.com>} to
that commit message.
@end itemize

If you are not a committer, you can help others find a @emph{series} you
have reviewed more easily by adding a @code{reviewed-looks-good} usertag for
the @code{guix} user (@pxref{Debbugs Usertags}).

@node 更新 Guix 软件包
@section 更新 Guix 软件包

@cindex update-guix-package, updating the guix package
It is sometimes desirable to update the @code{guix} package itself (the
package defined in @code{(gnu packages package-management)}), for example to
make new daemon features available for use by the @code{guix-service-type}
service type.  In order to simplify this task, the following command can be
used:

@example
make update-guix-package
@end example

The @code{update-guix-package} make target will use the last known
@emph{commit} corresponding to @code{HEAD} in your Guix checkout, compute
the hash of the Guix sources corresponding to that commit and update the
@code{commit}, @code{revision} and hash of the @code{guix} package
definition.

To validate that the updated @code{guix} package hashes are correct and that
it can be built successfully, the following command can be run from the
directory of your Guix checkout:

@example
./pre-inst-env guix build guix
@end example

为了防止意外将 @code{guix} 包更新到其他人无法引用的提交，会检查所使用的提交是否已推送到 Codeberg 托管的 Guix Git 仓库。

This check can be disabled, @emph{at your own peril}, by setting the
@code{GUIX_ALLOW_ME_TO_USE_PRIVATE_COMMIT} environment variable.  When this
variable is set, the updated package source is also added to the store.
This is used as part of the release process of Guix.

@node 弃用策略
@section 弃用策略

@cindex deprecation policy
As any lively project with a broad scope, Guix changes all the time and at
all levels.  Because it's user-extensible and programmable, incompatible
changes can directly impact users and make their life harder.  It is thus
important to reduce user-visible incompatible changes to a minimum and, when
such changes are deemed necessary, to clearly communicate them through a
@dfn{deprecation period} so everyone can adapt with minimum hassle.  This
section defines the project's commitments for smooth deprecation and
describes procedures and mechanisms to honor them.

There are several ways to use Guix; how to handle deprecation will depend on
each use case.  Those can be roughly categorized like this:

@itemize
@item
package management exclusively through the command line;

@item
advanced package management using the manifest and package interfaces;

@item
Home and System management, using the @code{operating-system} and/or
@code{home-environment} interfaces together with the service interfaces;

@item
development or use of external tools that use programming interfaces such as
the @code{(guix ...)} modules.
@end itemize

These use cases form a spectrum with varying degrees of coupling---from
``distant'' to tightly coupled.  Based on this insight, we define the
following @dfn{deprecation policies} that we consider suitable for each of
these levels.

@table @asis
@item Command-line tools
Guix sub-commands should be thought of as remaining available ``forever''.
Once a Guix sub-command is to be removed, it should be deprecated first, and
then remain available for @b{at least one year} after the first release that
deprecated it.

Deprecation should first be announced in the manual and as an entry in
@file{etc/news.scm}; additional communication such as a blog post explaining
the rationale is welcome.  Months before the scheduled removal date, the
command should print a warning explaining how to migrate.  An example of
this is the replacement of @command{guix environment} by @command{guix
shell}, started in October 2021@footnote{For more details on the
@command{guix shell} transition, see
@uref{https://guix.gnu.org/en/blog/2021/from-guix-environment-to-guix-shell/}.}.

Because of the broad impact of such a change, we recommend conducting a user
survey before enacting a plan.

@cindex package deprecation
@item Package name changes
When a package name changes, it must remain available under its old name for
@b{at least one year}.  For example, @code{go-ipfs} was renamed to
@code{kubo} following a decision made upstream; to communicate the name
change to users, the package module provided this definition:

@findex deprecated-package
@findex define-deprecated-package
@lisp
(define-deprecated-package go-ipfs
  kubo)
@end lisp

That way, someone running @command{guix install go-ipfs} or similar sees a
deprecation warning mentioning the new package name; likewise, someone
referring to the @code{go-ipfs} @emph{variable} from their manifest or
package definition will see a warning.

Under the hood, @code{define-deprecated-package} combines
@code{define-deprecated/public-alias} to mark the variable as deprecated
(see below), and the @code{deprecated-package} procedure to mark the package
name as deprecated.

@cindex package removal policy
@anchor{package-removal-policy}
@item Package removal
Packages whose upstream developers have declared as having reached ``end of
life'' or being unmaintained may be removed; likewise, packages that have
been @b{failing to build for two months or more} may be removed.

There is no formal deprecation mechanism for this case, unless a replacement
exists, in which case the @code{define-deprecated-package} macro mentioned
above can be used.

If the package being removed is a ``leaf'' (no other packages depend on it),
it may be removed after a @b{one-month review period} of the patch removing
it (this applies even when the removal has additional motivations such as
security problems affecting the package).

@quotation 注
Learn about pending package removals by checking
@uref{https://codeberg.org/guix/guix/issues?labels=445131, issues and pull
requests with the @samp{deprecation} label}.
@end quotation

If the package has many dependent packages---as is the case for example with
Python version@tie{}2---the relevant team must propose a deprecation removal
agenda and seek consensus with other packagers for @b{at least one month}.
It may also invite feedback from the broader user community, for example
through a survey.  Removal of all impacted packages may be gradual, spanning
multiple months, to accommodate all use cases.

When the package being removed is considered popular, whether or not it is a
leaf, its deprecation must be announced as an entry in @code{etc/news.scm}.

@item Package upgrade
In the case of packages with many dependents and/or many users, an upgrade
may be treated like the @emph{removal} of the previous version.

Examples include major version upgrades of programming language
implementations, as we've seen above with Python, and major upgrades of
``big'' libraries such as Qt or GTK.

@cindex service deprecation
@item 服务
Changes to services for Guix Home and Guix System have a direct impact on
user configuration.  For a user, adjusting to interface changes is rarely
rewarding, which is why any such change must be clearly communicated in
advance through deprecation warnings and documentation.

Renaming of variables related to service, home, or system configuration must
be communicated for at least six months before removal using the @code{(guix
deprecation)} mechanisms.  For example, renaming of
@code{murmur-configuration} to @code{mumble-server-configuration} was
communicated through a series of definitions like this one:

@findex define-deprecated/public-alias
@lisp
(define-deprecated/public-alias
  murmur-configuration
  mumble-server-configuration)
@end lisp

Procedures slated for removal may be defined like this:

@findex define-deprecated
@lisp
(define-deprecated (elogind-service #:key (config (elogind-configuration)))
  elogind-service-type
  (service elogind-service-type config))
@end lisp

Record fields, notably fields of service configuration records, must follow
a similar deprecation period.  This is usually achieved through @i{ad hoc}
means though.  For example, the @code{hosts-file} field of
@code{operating-system} was deprecated by adding a @code{sanitized} property
that would emit a warning:

@lisp
(define-record-type* <operating-system>
  ;; @dots{}
  (hosts-file %operating-system-hosts-file         ;deprecated
              (default #f)
              (sanitize warn-hosts-file-field-deprecation)))

(define-deprecated (operating-system-hosts-file os)
  hosts-service-type
  (%operating-system-hosts-file os))
@end lisp

When deprecating interfaces in @code{operating-system},
@code{home-environment}, @code{(gnu services)}, or any popular service, the
deprecation must come with an entry in @code{etc/news.scm}.

@cindex deprecation of programming interfaces
@item Core interfaces
Core programming interfaces, in particular the @code{(guix ...)} modules,
may be relied on by a variety of external tools and channels.  Any
incompatible change must be formally deprecated with
@code{define-deprecated}, as shown above, for @b{at least one year} before
removal.  The manual must clearly document the new interface and, except in
obvious cases, explain how to migrate from the old one.

As an example, the @code{build-expression->derivation} procedure was
superseded by @code{gexp->derivation} and remained available as a deprecated
symbol:

@lisp
(define-deprecated (build-expression->derivation store name exp
                                                 #:key @dots{})
  gexp->derivation
  @dots{})
@end lisp

Sometimes bindings are moved from one module to another.  In those cases,
bindings must be reexported from the original module for at least one year.
@end table

This section does not cover all possible situations but hopefully allows
users to know what to expect and developers to stick to its spirit.  Please
email @email{guix-devel@@gnu.org} for any questions.

@cindex documentation
@node 撰写文档
@section 撰写文档

Guix is documented using the Texinfo system.  If you are not yet familiar
with it, we accept contributions for documentation in most formats.  That
includes plain text, Markdown, Org, etc.

Documentation contributions can be sent to @email{guix-patches@@gnu.org}.
Prepend @samp{[DOCUMENTATION]} to the subject.

When you need to make more than a simple addition to the documentation, we
prefer that you send a proper patch as opposed to sending an email as
described above.  @xref{提交补丁} for more information on how to
send your patches.

To modify the documentation, you need to edit @file{doc/guix.texi} and
@file{doc/contributing.texi} (which contains this documentation section), or
@file{doc/guix-cookbook.texi} for the cookbook.  If you compiled the Guix
repository before, you will have many more @file{.texi} files that are
translations of these documents.  Do not modify them, the translation is
managed through @uref{https://translate.codeberg.org/projects/guix,
Weblate}.  @xref{翻译 Guix} for more information.

To render documentation, you must first make sure that you ran
@command{./configure} in your source tree (@pxref{在安装之前运行 Guix}).  After that you can run one of the following commands:

@itemize
@item @samp{make doc/guix.info} to compile the Info manual.
      You can check it with @command{info doc/guix.info}.
@item @samp{make doc/guix.html} to compile the HTML version.
      You can point your browser to the relevant file in the @file{doc/guix.html}
directory.
@item @samp{make doc/guix-cookbook.info} for the cookbook Info manual.
@item @samp{make doc/guix-cookbook.html} for the cookbook HTML version.
@end itemize

@cindex translation
@cindex l10n
@cindex i18n
@cindex native language support
@node 翻译 Guix
@section 翻译 Guix

Writing code and packages is not the only way to provide a meaningful
contribution to Guix.  Translating to a language you speak is another
example of a valuable contribution you can make.  This section is designed
to describe the translation process.  It gives you advice on how you can get
involved, what can be translated, what mistakes you should avoid and what we
can do to help you!

Guix is a big project that has multiple components that can be translated.
We coordinate the translation effort on a
@uref{https://translate.codeberg.org/projects/guix/,Weblate instance} hosted
by Codeberg.  You will need an account to submit translations.

Some of the software packaged in Guix also contain translations.  We do not
host a translation platform for them.  If you want to translate a package
provided by Guix, you should contact their developers or find the
information on their website.  As an example, you can find the homepage of
the @code{hello} package by typing @command{guix show hello}.  On the
``homepage'' line, you will see @url{https://www.gnu.org/software/hello/} as
the homepage.

Many GNU and non-GNU packages can be translated on the
@uref{https://translationproject.org,Translation Project}.  Some projects
with multiple components have their own platform.  For instance, GNOME has
its own platform, @uref{https://l10n.gnome.org/,Damned Lies}.

Guix has five components hosted on Weblate.

@itemize
@item @code{guix} contains all the strings from the Guix software (the
      guided system installer, the package manager, etc), excluding packages.
@item @code{packages} contains the synopsis (single-sentence description
      of a package) and description (longer description) of packages in Guix.
@item @code{website} contains the official Guix website, except for
      blog posts and multimedia content.
@item @code{documentation-manual} corresponds to this manual.
@item @code{documentation-cookbook} is the component for the cookbook.
@end itemize

@subsubheading General Directions

Once you get an account, you should be able to select a component from
@uref{https://translate.codeberg.org/projects/guix/,the guix project}, and
select a language.  If your language does not appear in the list, go to the
bottom and click on the ``Start new translation'' button.  Select the
language you want to translate to from the list, to start your new
translation.

Like lots of other free software packages, Guix uses
@uref{https://www.gnu.org/software/gettext,GNU Gettext} for its
translations, with which translatable strings are extracted from the source
code to so-called PO files.

Even though PO files are text files, changes should not be made with a text
editor but with PO editing software.  Weblate integrates PO editing
functionality.  Alternatively, translators can use any of various
free-software tools for filling in translations, of which
@uref{https://poedit.net/,Poedit} is one example, and (after logging in)
@uref{https://docs.weblate.org/en/latest/user/files.html,upload} the changed
file.  There is also a special
@uref{https://www.emacswiki.org/emacs/PoMode,PO editing mode} for users of
GNU Emacs.  Over time translators find out what software they are happy with
and what features they need.

在 Weblate 上，您可以发现各种编辑器链接，这些链接将显示各种字符串子集（或全部）。
请访问@uref{https://docs.weblate.org/zh-cn/latest/,文档}以熟悉该平台。

@unnumberedsec 译者注意

各位热爱 Guix 本地化的朋友，当您进行本地化工作时，需注意：

中文标点符号的使用不能草率，应参考《标点符号用法》（GB/T 15834-2011）。

对于中英文混合标点符号用法，应参考教育部发布的《夹用英文的中文文本的标点符号用法（草案）》。

对于其他中文信息处理，应参考《汉语信息处理词汇 01部分：基本术语》（GB 12200.1-90）、《汉语信息处理词汇 02
部分：汉语和汉字》（GB/T 12200.2-94）、《出版物上数字用法》（GB/T
15835-2011）等教育部和国家语委发布的国家标准及语言文字规范。

对于 “and/or” 的译法，建议采用“和（或）”而不是“和/或”。

@subsubheading Translation Components

In this section, we provide more detailed guidance on the translation
process, as well as details on what you should or should not do.  When in
doubt, please contact us, we will be happy to help!

@table @asis
@item guix
Guix is written in the Guile programming language, and some strings contain
special formatting that is interpreted by Guile.  These special formatting
should be highlighted by Weblate.  They start with @code{~} followed by one
or more characters.

When printing the string, Guile replaces the special formatting symbols with
actual values.  For instance, the string @samp{ambiguous package
specification `~a'} would be substituted to contain said package
specification instead of @code{~a}.  To properly translate this string, you
must keep the formatting code in your translation, although you can place it
where it makes sense in your language.  For instance, the French translation
says @samp{spécification du paquet « ~a » ambiguë} because the adjective
needs to be placed in the end of the sentence.

If there are multiple formatting symbols, make sure to respect the order.
Guile does not know in which order you intended the string to be read, so it
will substitute the symbols in the same order as the English sentence.

例如，您不能将 @samp{package '~a' has been superseded by '~a'} 翻译为 @samp{'~a'
supersedes package '~a'}，因为意思会被颠倒。如果 @var{foo} 被 @var{bar} 取代，翻译将为
@samp{'foo' supersedes package
'bar'}。为了解决这个问题，可以使用更高级的格式来选择特定的数据，而不是遵循默认的英语顺序。有关 Guile 中格式的更多信息，请参阅
@pxref{Formatted Output,,, guile, GNU Guile Reference Manual}.

@item packages

Package descriptions occasionally contain Texinfo markup (@pxref{简介和描述}).  Texinfo markup looks like @samp{@@code@{rm -rf@}},
@samp{@@emph@{important@}}, etc.  When translating, please leave markup as
is.

The characters after ``@@'' form the name of the markup, and the text
between ``@{'' and ``@}'' is its content.  In general, you should not
translate the content of markup like @code{@@code}, as it contains literal
code that do not change with language.  You can translate the content of
formatting markup such as @code{@@emph}, @code{@@i}, @code{@@itemize},
@code{@@item}.  However, do not translate the name of the markup, or it will
not be recognized.  Do not translate the word after @code{@@end}, it is the
name of the markup that is closed at this position (e.g.@: @code{@@itemize
... @@end itemize}).

@item documentation-manual and documentation-cookbook

The first step to ensure a successful translation of the manual is to find
and translate the following strings @emph{first}:

@itemize
@item @code{version.texi}: Translate this string as @code{version-xx.texi},
      where @code{xx} is your language code (the one shown in the URL on weblate).
@item @code{contributing.texi}: Translate this string as
      @code{contributing.xx.texi}, where @code{xx} is the same language code.
@item @code{Top}: Do not translate this string, it is important for Texinfo.
      If you translate it, the document will be empty (missing a Top node).
Please look for it, and register @code{Top} as its translation.
@end itemize

Translating these strings first ensure we can include your translation in
the guix repository without breaking the make process or the @command{guix
pull} machinery.

The manual and the cookbook both use Texinfo.  As for @code{packages},
please keep Texinfo markup as is.  There are more possible markup types in
the manual than in the package descriptions.  In general, do not translate
the content of @code{@@code}, @code{@@file}, @code{@@var}, @code{@@value},
etc.  You should translate the content of formatting markup such as
@code{@@emph}, @code{@@i}, etc.

The manual contains sections that can be referred to by name by
@code{@@ref}, @code{@@xref} and @code{@@pxref}.  We have a mechanism in
place so you do not have to translate their content.  If you keep the
English title, we will automatically replace it with your translation of
that title.  This ensures that Texinfo will always be able to find the
node. If you decide to change the translation of the title, the references
will automatically be updated and you will not have to update them all
yourself.

When translating references from the cookbook to the manual, you need to
replace the name of the manual and the name of the section.  For instance,
to translate @code{@@pxref@{Defining Packages,,, guix, GNU Guix Reference
Manual@}}, you would replace @code{Defining Packages} with the title of that
section in the translated manual @emph{only} if that title is translated.
If the title is not translated in your language yet, do not translate it
here, or the link will be broken.  Replace @code{guix} with @code{guix.xx}
where @code{xx} is your language code.  @code{GNU Guix Reference Manual} is
the text of the link.  You can translate it however you wish.

@item website

The website pages are written using SXML, an s-expression version of HTML,
the basic language of the web.  We have a process to extract translatable
strings from the source, and replace complex s-expressions with a more
familiar XML markup, where each markup is numbered.  Translators can
arbitrarily change the ordering, as in the following example.

@example
#. TRANSLATORS: Defining Packages is a section name
#. in the English (en) manual.
#: apps/base/templates/about.scm:64
msgid "Packages are <1>defined<1.1>en</1.1><1.2>Defining-Packages.html</1.2></1> as native <2>Guile</2> modules."
msgstr "Pakete werden als reine <2>Guile</2>-Module <1>definiert<1.1>de</1.1><1.2>Pakete-definieren.html</1.2></1>."
@end example

Note that you need to include the same markups.  You cannot skip any.
@end table

In case you make a mistake, the component might fail to build properly with
your language, or even make guix pull fail.  To prevent that, we have a
process in place to check the content of the files before pushing to our
repository.  We will not be able to update the translation for your language
in Guix, so we will notify you (through weblate and/or by email) so you get
a chance to fix the issue.

@subsubheading Outside of Weblate

Currently, some parts of Guix cannot be translated on Weblate, help wanted!

@itemize
@item @command{guix pull} news can be translated in @file{news.scm}, but is not
      available from Weblate.  If you want to provide a translation, you can
prepare a patch as described above, or simply send us your translation with
the name of the news entry you translated and your language. @xref{撰写频道新闻}, for more information about channel news.
@item Guix blog posts cannot currently be translated.
@item The installer script (for foreign distributions) is entirely in English.
@item Some of the libraries Guix uses cannot be translated or are translated
      outside of the Guix project.  Guile itself is not internationalized.
@item Other manuals linked from this manual or the cookbook might not be
      translated.
@end itemize

@subsubheading Conditions for Inclusion

There are no conditions for adding new translations of the @code{guix} and
@code{guix-packages} components, other than they need at least one
translated string.  New languages will be added to Guix as soon as
possible.  The files may be removed if they fall out of sync and have no
more translated strings.

Given that the web site is dedicated to new users, we want its translation
to be as complete as possible before we include it in the language menu.
For a new language to be included, it needs to reach at least 80%
completion.  When a language is included, it may be removed in the future if
it stays out of sync and falls below 60% completion.

The manual and cookbook are automatically added in the default compilation
target.  Every time we synchronize translations, developers need to
recompile all the translated manuals and cookbooks.  This is useless for
what is essentially the English manual or cookbook.  Therefore, we will only
include a new language when it reaches 10% completion in the component.
When a language is included, it may be removed in the future if it stays out
of sync and falls below 5% completion.

@subsubheading Translation Infrastructure

Weblate is backed by a git repository from which it discovers new strings to
translate and pushes new and updated translations.  Normally, it would be
enough to give it commit access to our repositories.  However, we decided to
use a separate repository for two reasons.  First, we would have to give
Weblate commit access and authorize its signing key, but we do not trust it
in the same way we trust guix developers, especially since we do not manage
the instance ourselves.  Second, if translators mess something up, it can
break the generation of the website and/or guix pull for all our users,
independently of their language.

For these reasons, we use a dedicated repository to host translations, and
we synchronize it with our guix and artworks repositories after checking no
issue was introduced in the translation.

Developers can download the latest PO files from weblate in the Guix
repository by running the @command{make download-po} command.  It will
automatically download the latest files from weblate, reformat them to a
canonical form, and check they do not contain issues.  The manual needs to
be built again to check for additional issues that might crash Texinfo.

Before pushing new translation files, developers should add them to the make
machinery so the translations are actually available.  The process differs
for the various components.

@itemize
@item New po files for the @code{guix} and @code{packages} components must
      be registered by adding the new language to @file{po/guix/LINGUAS} or
@file{po/packages/LINGUAS}.
@item New po files for the @code{documentation-manual} component must be
      registered by adding the file name to @code{DOC_PO_FILES} in
@file{po/doc/local.mk}, the generated @file{%D%/guix.xx.texi} manual to
@code{info_TEXINFOS} in @file{doc/local.mk} and the generated
@file{%D%/guix.xx.texi} and @file{%D%/contributing.xx.texi} to
@code{TRANSLATED_INFO} also in @file{doc/local.mk}.
@item New po files for the @code{documentation-cookbook} component must be
      registered by adding the file name to @code{DOC_COOKBOOK_PO_FILES} in
@file{po/doc/local.mk}, the generated @file{%D%/guix-cookbook.xx.texi}
manual to @code{info_TEXINFOS} in @file{doc/local.mk} and the generated
@file{%D%/guix-cookbook.xx.texi} to @code{TRANSLATED_INFO} also in
@file{doc/local.mk}.
@item New po files for the @code{website} component must be added to the
      @code{guix-artwork} repository, in @file{website/po/}.
@file{website/po/LINGUAS} and @file{website/po/ietf-tags.scm} must be
updated accordingly (see @file{website/i18n-howto.txt} for more information
on the process).
@end itemize


@cindex infrastructure
@node 为 Guix 的基础设施做贡献
@section 为 Guix 的基础设施做贡献

Since its inception, the Guix project has always valued its autonomy, and
that reflects in its infrastructure: our servers run Guix System and
exclusively free software, and are administered by volunteers.

Of course this comes at a cost and this is why we need contributions.  Our
hope is to make infrastructure-related activity more legible so that maybe
you can picture yourself helping in one of these areas.


@menu
* Coding::                   Coding
* System Administration::    System Administration
* Day-to-Day System Administration::  Day-to-Day System Administration
* On-Site Intervention::     On-Site Intervention
* Hosting::                  Hosting
* Administrative Tasks::     Administrative Tasks
@end menu

@node Coding
@subsection Coding

The project runs many Guix-specific services; this is all lovely Scheme code
but it tends to receive less attention than Guix itself:

@itemize
@item
@url{https://git.cbaines.net/guix/bffe, Build Farm Front End}
@item
@url{https://codeberg.org/guix/cuirass/, Cuirass}
@item
@url{https://codeberg.org/guix/maintenance/src/branch/master/hydra/goggles.scm,
Goggles} (IRC logger)
@item
@url{https://codeberg.org/guix/build-coordinator, Guix Build Coordinator}
@item
@url{https://codeberg.org/guix/data-service, Guix Data Service}
@item
@url{https://codeberg.org/luis-felipe/guix-packages-website, Guix Packages
Website}
@item
@url{https://codeberg.org/guix/mumi, mumi}
@item
@url{https://codeberg.org/guix/nar-herder, Nar Herder}
@item
@url{https://codeberg.org/guix/qa-frontpage, QA Frontpage}
@end itemize

There is no time constraint on this coding activity: any improvement is
welcome, whenever it comes.  Most of these code bases are relatively small,
which should make it easier to get started.

Prerequisites: Familiarity with Guile, HTTP, and databases.

If you wish to get started, check out the README of the project of your
choice and get in touch with guix-devel and the primary developer(s) of the
tool as per @code{git shortlog -s | sort -k1 -n}.

@node System Administration
@subsection System Administration

Guix System configuration for all our systems is held in this repository:

@url{https://codeberg.org/guix/maintenance.git/src/branch/master/hydra/}

The two front-ends are @file{berlin.scm} (the machine behind
ci.guix.gnu.org)  and @file{bayfront.scm} (the machine behind
bordeaux.guix.gnu.org, guix.gnu.org, hpc.guix.info, qa.guix.gnu.org, and
more).  Both connect to a number of build machines and helpers.

Without even having SSH access to the machine, you can help by posting
patches to improve the configuration (you can test it with @code{guix system
vm}).  Here are ways you can help:

@itemize
@item
Improve infra monitoring: set up a dashboard to monitor all the
infrastructure, and an out-of-band channel to communicate about downtime.

@item
Implement web site redundancy: guix.gnu.org should be backed by several
machines on different sites.  Get in touch with us and/or send a patch!

@item
Implement substitute redundancy: likewise, bordeaux.guix.gnu.org and
ci.guix.gnu.org should be backed by several head nodes.

@item
Improve backup: there's currently ad-hoc backup of selected pieces over
rsync between the two head nodes; we can improve on that, for example with a
dedicated backup site and proper testing of recoverability.

@item
Support mirroring: We'd like to make it easy for others to mirror
substitutes from ci.guix and bordeaux.guix, perhaps by offering public rsync
access.

@item
Optimize our web services: Monitor the performance of our services and tweak
nginx config or whatever it takes to improve it.

There is no time constraint on this activity: any improvement is welcome,
whenever you can work on it.

Prerequisite: Familiarity with Guix System administration and ideally with
the infrastructure handbook:

@url{https://codeberg.org/guix/maintenance.git/src/branch/master/doc/infra-handbook.org,
Infra-Handbook}

@end itemize

@node Day-to-Day System Administration
@subsection Day-to-Day System Administration

We're also looking for people who'd be willing to have SSH access to some of
the infrastructure to help with day-to-day maintenance: restarting a build,
restarting the occasional service that has gone wild (that can happen),
reconfiguring/upgrading a machine, rebooting, etc.

This day-to-day activity requires you to be available some of the time
(during office hours or not, during the week-end or not), whenever is
convenient for you, so you can react to issues reported on IRC, on the
mailing list, or elsewhere, and synchronize with other sysadmins.

Prerequisite: Being a ``known'' member of the community, familiarity with
Guix System administration, with some of the services/web sites being run,
and with the infrastructure handbook:

@url{https://codeberg.org/guix/maintenance.git/src/branch/master/doc/infra-handbook.org,
Infra-Handbook}

@node On-Site Intervention
@subsection On-Site Intervention

The first front-end is currently generously hosted by the Max Delbrück
Center (MDC), a research institute in Berlin, Germany. Only authorized
personnel can physically access it.

The second one, bordeaux.guix.gnu.org, is hosted in Bordeaux, France, in a
professional data center shared with non-profit ISP Aquilenet.  If you live
in the region of Bordeaux and would like to help out when we need to go
on-site, please make yourself known by emailing
@email{guix-sysadmin@@gnu.org}.

On-site interventions are rare, but they're usually in response to an
emergency.

@node Hosting
@subsection Hosting

We're looking for people who can host machines and help out whenever
physical access is needed.  More specifically:

@itemize
@item
We need hosting of ``small'' machines such as single-board computers
(AArch64, RISC-V) for use as build machines.

@item
We need hosting for front-ends and x86_64 build machines in a data center
where they can be racked and where, ideally, several local Guix sysadmins
can physically access them.
@end itemize

The machines should be accessible over Wireguard VPN most of the time, so
longer power or network interruptions should be the exception.

Prerequisites: Familiarity with installing and remotely administering Guix
System.

@node Administrative Tasks
@subsection Administrative Tasks

The infra remains up and running thanks to crucial administrative tasks,
which includes:

@itemize
@item
Selecting and purchasing hardware, for example build machines.
@item
Renewing domain names.

@item
Securing funding, in particular via the Guix Foundation:
@url{https://foundation.guix.info, Guix Foundation}
@end itemize

Prerequisites: Familiarity with hardware, and/or DNS registrars, and/or
sponsorship, and/or crowdfunding.
