Mercurial: "Advanced uses of Mercurial Queues" を読む
Tagged:  •    •  

今回は "13. Advanced uses of Mercurial Queues" を読みます。

この章では、 筆者(Bryan O'Sullivan)が Linux infiniband デバイスドライバ開発を通して得た経験を元に、 より踏み込んだ MQ 利用が紹介されています。 「込み入った開発環境でも使えるようにするには、 あまり利用されない機能の説明が必要」との方針に違わず、 読み込むのに苦労する章です (前章に比べれば分量的にも全然少ないのですが…)。

13.1 The problem of many targets

カーネルの思い切った変更により、 コンパイルすらできなくなることが度々あるため、 カーネルモジュールやデバイスドライバの開発の際には、 カーネルのリビジョンを相当意識する必要があるらしいです。 日々 Linux の恩恵を受けている者として、開発に携わる諸氏に感謝。

13.1.1 Tempting approaches that don't work well

「複数環境への対応を、 それぞれの環境向けのブランチで保守しようとすると、 機能追加/バグ修正におけるマージの管理が大変」ですが、 かといって 「ifdef で環境依存部を切り替えるようにすると、 ”鼠の巣”状態になってしまう」というのも勘弁して欲しいものです。 個人的には、 ifdef で可読性の落ちたソースを保守するぐらいなら、 複数ブランチの間でマージ管理をする方がマシな気がしますが、 いずれにしても程度が問題ですね。

確かに、このような局面には MQ はうってつけです。

13.2 Conditionally applying patches with guards

個々のパッチの条件付き適用を実現する「ガード(guard)」の紹介です。 良いですね、こういう仕組み。

ちなみに、 13.3 ~ 13.5 は、 13.2 配下であった方が構成上適切な気がしますが、どうでしょうか。

13.3 Controlling the guards on a patch

まずは各パッチへのガードの設定です。

13.2 で「(原文では "tag" ですが、 SCM で一般に用いられる「タグ」と区別する意味で「札」と呼んでいます) を付与する」と言っておいて、 この節では「ガードを設定する」と記述するのは、 一貫性という点でちょっとどうか、と…。

13.4 Selecting the guards to use

hg qselect でガードを選択したなら、 hg qpush -a でパッチ適用です。

hg qselectガード選択だけしか行わないので、 「hg qselect 実施により、適用済みパッチの取り消しも行われる」 といった勘違いをしないように注意が必要です。

13.5 MQ's rules for applying patches

「ネガティブガードによりパッチ不適用を積極的に指定」できるのは、 はなかなか便利そうです。

13.6 Trimming the work environment

「フルセットのカーネルソースではなく、 関連性の有る部分的なソースに対して作業する」 という趣旨はわかるのですが、 前提としている状況に今ひとつ馴染みが無いこともあり、 この節は上手く翻訳できないでいます (言わんとしていることも良く理解できていません)。 分量自体はそれほどでもないのですが…。

参考までに、原文を以下に引用します。

In working on the device driver I mentioned earlier, I don’t apply the patches to a normal Linux kernel tree. Instead, I use a repository that contains only a snapshot of the source files and headers that are relevant to Infiniband development. This repository is 1% the size of a kernel repository, so it’s easier to work with.

I then choose a “base” version on top of which the patches are applied. This is a snapshot of the Linux kernel tree as of a revision of my choosing. When I take the snapshot, I record the changeset ID from the kernel repository in the commit message. Since the snapshot preserves the “shape” and content of the relevant parts of the kernel tree, I can apply my patches on top of either my tiny repository or a normal kernel tree.

Normally, the base tree atop which the patches apply should be a snapshot of a very recent upstream tree. This best facilitates the development of patches that can easily be submitted upstream with few or no modifications.

13.7 Dividing up the series file

以下のパッチ分類は、さすが「なるほど」と思わせるものです。 やはりこういうものには経験がものを言いますね。

  • 受理済み(accepted)
  • 再作業(rework)
  • 保留(pending)
  • 作業中(in progress)
  • バックポート(backport)
  • 内部用(do not ship)
13.8 Maintaining the patch series

せっかく前節で "pending" という分類を定義したのですから、 "finished" という呼称を用いなくても…。

13.8、13.8.1 に関しては、 13.7 配下にあった方が構成上適切な気がします。

13.8.1 The art of writing backport patches

実際はそんなに簡単な事ではないのでしょうが、 ここまで読んでくると、MQ (特にガードの機能)があれば、 私にでも複数環境向けのバックポートパッチが書けそうな気になってしまいます。 恐るべし Mercurial + MQ。

13.9 Useful tips for developing with MQ
13.9.1 Organising patches in directories

MQ が「パッチの内容をパッチ名と同名のファイルに格納」することと、 「パッチ名にパス区切りを使用可能」ということを活かして、 パッチをディレクトリごとに分類する、 というのはなかなか良いですね。

13.9.2 Viewing the history of a patch

「パッチ同士の差分」即ち「diff 出力の diff」となりますから、 パッチを履歴管理した際の hg log -p 出力は、 それはもうわけがわからなくなることでしょう。

そこで extdiff の出番です。なるほど。


以上で "13 Advanced uses of Mercurial Queues" 節は終了です。 前回までに読んだ "12 Managing change with Mercurial Queues" とあわせて、 MQ に関してはだいぶわかってきました。

私が Mercurial を使用しているプロジェクトでは、 (今のところ)使う必要が無かったのですが、 構成管理を行う上では避けて通れない「ブランチ」の Mercurial における用法を理解するために、 "8 Managing releases and branchy development" を読もうと思います。


"Distributed revision control with Mercurial" 関連エントリの一覧は、BOSBook(Bryan O’Sullivan Book)タグで参照できます。