「再構築すれども上書きせず」とその理由

yujiroさんのブログ「小粋空間」で、「Movable Typeの再構築の出力制御について」という記事がアップされていました。
再構築されたファイルの出力(保存)についての記事です。

ところが、記事の最後に「すいません。ちょっと疲れてます。」とあり、考察を途中でやめられたようです。
そこで、yujiroさんの記事をネタにさせていただいて、補足をさせていただきます。

1.再構築からファイル出力までの流れ

まず、「再構築」の用語の定義を明確にしておきます。
この記事では、「テンプレートを解析し、テンプレートタグをデータに置き換える処理」を、「(狭義の)再構築」と呼ぶことにします。
また、「(狭義の)再構築」には、生成されたHTMLをファイルとして出力(保存)する処理は含みません。

Movable Typeでは、記事を保存したときや、「サイトの再構築」のリンクをクリックしたときには、たとえブログに何も変更がなくても、常に(狭義の)再構築の処理が行われます。
ただ、ブログに何も変更がなければ、(狭義の)再構築を行っても、出力されるファイルの内容は、(狭義の)再構築を行う前と変化しません。
このようなときには、以前のファイルに上書きせずに、以前のファイルをそのまま残すようになっています。

例えば、インデックステンプレートを再構築した直後に、インデックステンプレートに一切手を加えずに、再構築を再度行うとします。
また、この2回の再構築の間に、コメントやトラックバックを受信するなど、ブログに変化が生じるようなことは起こらないものとします。

この場合、(狭義の)再構築の処理自体は行われます。
しかし、出力されるファイルの内容は変化しません。
そのため、ファイルは上書きされず、前回の(狭義の)再構築時点のファイルがそのまま残ります。

2.WeblogPublisher.pmでの処理

(狭義の)再構築の処理は、MT_DIR/lib/MT/WeblogPublisher.pmというモジュールで行われています。
最終的な(狭義の)再構築と、出来上がったHTMLをファイルに保存する処理は、以下のサブルーチンで行われます。

テンプレートの種類サブルーチン
インデックステンプレートrebuild_indexes
アーカイブテンプレート(から出力される個々のファイル)rebuild_file

これらのサブルーチンを見ると、(狭義の)再構築の処理と、HTMLをファイルに出力する処理の間に、以下の2つのことが行われています。

  • build_pageコールバックの呼び出し
  • (狭義の)再構築でできたHTMLと、現在ハードディスクにあるHTMLを比較して、内容が変化していなければ、ファイルへの出力を行わずに、次の(狭義の)再構築の処理に進む

この後者の処理があるために、(狭義の)再構築が行われても、前回の再構築時とファイルの内容がまったく同じであれば、出力されないようになっています。

3.強制的にファイルを出力するには

yujiroさんの記事に、「プログラムをハックすれば出力できる手段があるはずですが」というくだりがあります。
この文章からは、「(狭義の)再構築を行ったときには、ファイルの内容が変化したかどうかにかかわらず、強制的に出力(元のファイルに上書き)したい」という意図が読み取れます。

上の「2.WeblogPublisher.pmでの処理」のところで述べましたが、(狭義の)再構築と、ファイルの出力との間に、「build_pageコールバックの呼び出し」の処理があります。
このコールバックを処理するプラグインを作れば、「強制的にファイル出力」が可能になります。

4.上書きしない理由

では、(狭義の)再構築の前後でファイルの内容が変化していない場合、なぜファイルを上書きしない仕様になっているのでしょうか。
おそらく、これは条件付getを働かせるためだと思います。

WebサーバーのApacheでは、クライアント(Webブラウザ等)から静的なHTMLのページにアクセスがあった場合、条件付getが働くようになっています。
そのため、同じクライアントから同じページに再度アクセスがあった場合、無駄な通信を抑えることができます。

この条件付getを動作させるために、HTMLファイルのタイムスタンプがチェックされています。
もし、(狭義の)再構築の後にファイルを強制的に上書きしてしまうと、タイムスタンプが変化し、条件付getが利かなくなってしまいます。
このような問題が起こらないようにするために、「(狭義の)再構築の前後でファイルの内容が変化していなければ、上書きしない」という仕様になっているのだと思います。