Electron 中的补丁¶
Electron 基于两个主要的上游项目构建:Chromium 和 Node.js。这些项目各自也有若干依赖。我们尽力原样使用这些依赖,但有时如果不修补这些上游依赖以适配我们的使用场景,就无法实现目标。
补丁理由¶
Electron 中的每个补丁都是维护负担。当上游代码发生变化时,补丁可能会失效——有时甚至没有补丁冲突或编译错误。保持补丁集最新且有效是一项持续工作。因此,我们努力将补丁数量保持在最低水平。为此,每个补丁都必须在提交信息中说明其存在的原因。该原因必须是以下之一:
- 该补丁是临时的,并且计划(或已经)提交到上游,或以其他方式最终移除。如果可用,请包含指向上游 PR 或代码审查的链接,或者提供日后验证该补丁是否仍然需要的步骤。
- 该补丁使代码能够在 Electron 环境中编译,但由于它是 Electron 特有的,因此无法提交到上游(例如,移除对 Chrome 的
Profile的引用)。请说明为什么该更改无法在不使用补丁的情况下实现(例如,通过子类化或复制代码)。 - 该补丁对功能进行了 Electron 特有的更改,这些更改与上游从根本上不兼容。
通常,我们合作的所有上游项目团队都很友好,并且通常乐于接受重构,使相关代码能够同时兼容 Electron 和上游项目。(例如,参见 Chromium 中的此更改,它使我们能够移除一个做了相同事情的补丁;或者 Node 中的此更改,它对 Node 没有影响,但修复了 Electron 中的一个 bug。)我们应尽可能将更改提交到上游,并避免无限期存在的补丁。
补丁系统¶
如果你发现自己处于不得不通过修补上游项目才能进行更改的不幸境地,你需要了解如何在 Electron 中管理补丁。
Electron 中针对上游项目的所有补丁都包含在 patches/ 目录中。patches/ 的每个子目录包含若干补丁文件,以及一个 .patches 文件,该文件列出了补丁应应用的顺序。可以将这些文件视为一系列 git 提交,在我们检出上游项目后,应用于上游项目之上。
patches
├── config.json <-- this describes which patchset directory is applied to what project
├── chromium
│ ├── .patches
│ ├── accelerator.patch
│ ├── add_contentgpuclient_precreatemessageloop_callback.patch
│ ⋮
├── node
│ ├── .patches
│ ├── add_openssl_is_boringssl_guard_to_oaep_hash_check.patch
│ ├── build_add_gn_build_files.patch
│ ⋮
⋮
为了帮助管理这些补丁集,我们提供了两个工具:git-import-patches 和 git-export-patches。git-import-patches 通过按正确顺序应用每个补丁并为每个补丁创建一个提交,将一组补丁文件导入 git 仓库。git-export-patches 执行相反操作;它将仓库中的一系列 git 提交导出为目录中的一组文件以及一个配套的 .patches 文件。
附注:我们使用
.patches文件来维护已应用补丁的顺序,而不是在每个文件名前添加001-这样的编号,是因为这样可以减少与补丁顺序相关的冲突。它可以避免两个 PR 都在系列末尾添加具有相同编号的补丁,并且最终都被合并,从而导致标识符重复的情况;同时,当在系列中间添加或删除补丁时,也能减少变动。
用法¶
添加新补丁¶
$ cd src/third_party/electron_node
$ vim some/code/file.cc
$ git commit
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
[!NOTE]
git-export-patches会忽略任何未提交的文件,因此如果你想导出更改,必须创建一个提交。提交信息的主题行将用于派生补丁文件名,提交信息的正文应包含补丁存在的原因。
重新导出补丁有时会导致无关补丁中的 SHA 校验和发生变化。这通常是无害的,可以忽略(但请将这些更改添加到你的 PR 中,这样可以避免它们出现在其他人的 PR 中)。
编辑现有补丁¶
$ cd src/v8
$ vim some/code/file.cc
$ git log
# Find the commit sha of the patch you want to edit.
$ git commit --fixup [COMMIT_SHA]
$ git rebase --autosquash -i [COMMIT_SHA]^
$ ../electron/script/git-export-patches -o ../electron/patches/v8
请注意,^ 符号在 Windows 上可能会引发问题。解决方法是将其加引号 "[COMMIT_SHA]^",或者避免使用它 [COMMIT_SHA]~1。
移除补丁¶
$ vim src/electron/patches/node/.patches
# Delete the line with the name of the patch you want to remove
$ cd src/third_party/electron_node
$ git reset --hard refs/patches/upstream-head
$ ../../electron/script/git-import-patches ../../electron/patches/node
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
请注意,git-import-patches 会将运行时的 HEAD 提交标记为 refs/patches/upstream-head(以及一个检出特定的 refs/patches/upstream-head-<hash>,以便共享 .git/refs 目录的 gclient 工作树不会相互覆盖)。这让你能够跟踪哪些提交来自 Electron 补丁(位于 refs/patches/upstream-head 之后的提交),哪些提交在上游中(位于 refs/patches/upstream-head 之前的提交)。
解决冲突¶
更新上游依赖时,补丁可能无法干净地应用。通常,git 可以通过三方合并自动解决冲突。你可以通过传递 -3 参数来指示 git-import-patches 使用三方合并算法:
$ cd src/third_party/electron_node
# If the patch application failed midway through, you can reset it with:
$ git am --abort
# And then retry with 3-way merge:
$ ../../electron/script/git-import-patches -3 ../../electron/patches/node
如果 git-import-patches -3 遇到无法自动解决的合并冲突,它会暂停并允许你手动解决冲突。解决冲突后,使用 git add 添加已解决的文件,然后运行 git am --continue 继续应用其余补丁。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 el/electron