Aller au contenu principal

Correctifs dans Electron

Electron est construit sur deux grands projets : Chromium et Node.js. Chacun de ces projets a également plusieurs dépendances propres. Nous faisons de notre mieux pour utiliser ces dépendances exactement telles qu'elles sont, mais parfois nous ne pouvons pas atteindre nos objectifs sans apporter des modifications à ces dépendances pour les adapter à nos cas d'utilisation.

Justification des correctifs

Chaque correctif (patch) dans Electron est un fardeau pour la maintenance. Lorsque le code en amont est modifié, les correctifs peuvent être cassés — parfois même sans créer de conflit ou d'erreur de compilation. C'est un effort continu pour garder à jour et performant nos correctifs. Nous nous efforçons donc de réduire au maximum le nombre de patchs. À cette fin, chaque patch doit décrire sa raison d'être dans son message de commit. Cette raison doit être l'une des suivantes :

  1. Le correctif est temporaire, et est destiné à être (ou a été) validé en amont ou éventuellement supprimé. Inclure un lien vers une Pull Request ou un code en amont si disponible, ou une procédure pour vérifier si le correctif est toujours nécessaire à une date ultérieure.
  2. Le correctif permet au code de compiler dans l'environnement Electron, mais ne peut pas être intégré car il est spécifique à Electron (ex: correction des références à la version Profile de Chrome). Inclure la raison pour laquelle le changement ne peut pas être implémenté sans un correctif (par exemple en sous-classant ou en copiant le code).
  3. Le correctif produit des changements de fonctionnalités spécifiques à Electron fondamentalement incompatibles avec l'existant en amont.

In general, all the upstream projects we work with are friendly folks and are often happy to accept refactorings that allow the code in question to be compatible with both Electron and the upstream project. (See e.g. this change in Chromium, which allowed us to remove a patch that did the same thing, or this change in Node, which was a no-op for Node but fixed a bug in Electron.) Nous devons viser les changements en amont chaque fois que nous le pouvons, et éviter les patchs de vie.

Système de correctifs

Si vous vous retrouvez dans la position malheureuse de devoir faire un changement qui ne peut être fait qu'en patchant un projet amont, vous aurez besoin de savoir comment gérer les correctifs dans Electron.

All patches to upstream projects in Electron are contained in the patches/ directory. Each subdirectory of patches/ contains several patch files, along with a .patches file which lists the order in which the patches should be applied. Think of these files as making up a series of git commits that are applied on top of the upstream project after we check it out.

patches
├── config.json <-- ceci décrit quel répertoire d'ensemble de correctifs (patchset) est appliqué à quel projet
├── 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
│   ⋮

Pour aider à gérer ces jeux de correctifs, nous fournissons deux outils : git-import-patches et git-export-patches. git-import-patches importe un ensemble de fichiers de correctifs dans un dépôt git en appliquant chaque correctif dans le bon ordre et en créant un commit pour chacun. git-export-patches fait l'inverse ; il exporte une série de commits d'un dépôt git vers un ensemble de fichiers dans un répertoire et un fichier accompagnant .patches.

Remarque : la raison pour laquelle nous utilisons un fichier .patches pour maintenir l'ordre des correctifs appliqués, plutôt que de préfixer un nombre comme 001- à chaque fichier, est que cela réduit les conflits liés à l'ordre des correctifs. Cela empêche la situation où deux PRs ajoutent un correctif à la fin de la série avec la même numérotation et ils finissent par être fusionnés avec un identifiant dupliqué. Cela réduit aussi l'attrition quand un correctif est ajouté ou enlevé en milieu de série.

Utilisation

Ajout d'un nouveau correctif

$ 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 ignore tous les fichiers non validés, donc vous devez créer un commit si vous voulez que vos modifications soient exportées. La ligne de sujet du message de commit sera utilisée pour dériver le nom du fichier de correctif, et le corps du message de commit devrait inclure la raison de l'existence du patch.

La réexportation des patchs provoquera parfois un changement de shasums dans les patchs non liés. Ceci est généralement inoffensif et peut être ignoré (mais allez plus loin et ajoutez ces modifications à votre PR, cela empêchera le cas de se présenter pour les autres).

Modification d'un patch existant

$ cd src/v8
$ vim some/code/file.cc
$ git log
# Trouver le SHA du commit du patch que vous souhaitez modifier.
$ git commit --fixup [COMMIT_SHA]
$ git rebase --autosquash -i [COMMIT_SHA]^
$ ../electron/script/git-export-patches -o ../electron/patches/v8

Note that the ^ symbol can cause trouble on Windows. The workaround is to either quote it "[COMMIT_SHA]^" or avoid it [COMMIT_SHA]~1.

Suppression d'un patch

$ vim src/electron/patches/node/. atches
# Supprime la ligne avec le nom du patch que vous voulez supprimer
$ 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

Notez que git-import-patches marquera le commit qui était HEAD lorsqu'il a été exécuté en tant que refs/patches/upstream-head. Cela vous permet de garder une trace de quels commits sont à partir de correctifs Electron (ceux qui viennent après refs/patches/upstream-head) et quels commits sont en amont (ceux antérieurs à refs/patches/upstream-head).

Résolution des conflits

Lors de la mise à jour d'une dépendance en amont, les correctifs peuvent échouer à s'appliquer proprement. Souvent, le conflit peut être résolu automatiquement par git avec une fusion à 3 voies. Vous pouvez indiquer à git-import-patches d'utiliser l'algorithme de fusion 3 voies en passant l'argument -3:

$ cd src/third_party/electron_node
# Si l'application du patch a échoué à mi-parcours, vous pouvez le réinitialiser avec :
$ git am --abort
# Puis recommencer avec la fusion 3 directions :
$ . /../electron/script/git-import-patches -3 ../../electron/patches/node

Si git-import-patches -3 rencontre un conflit de fusion qu'il ne peut pas résoudre automatiquement, il mettra en pause et vous permettra de résoudre le conflit manuellement. Une fois que vous avez résolu le conflit, git add les fichiers résolus et continuer à appliquer le reste des correctifs en exécutant git am --continue.