パッチをあてる(その3:patchコマンドの-pオプションについて)
「パッチをあてる」シリーズの第3回です。
サイトを検索すると、patch コマンド実行時に
C:¥work>patch -p0 < patch.txt
と青色の "-p0" を付与しているサンプルが一般的のようですが、この -pnumber というオプションの意味を調査・実験してみました。
このオプションはパッチファイルに記述されたディレクトリを無視する階層を示すものです。例えばパッチファイルの1?2行目の青色部分が
--- lib/MT/Util.pm.bak Fri Jan 06 14:19:44 2006
+++ lib/MT/Util.pm Fri Jan 06 14:20:48 2006
@@ -401,7 +401,7 @@
$str ||= '';
my @paras = split /\r?\n\r?\n/, $str;
for my $p (@paras) {
- if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)@) {
+ if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|menu|dir|p|pre|center|form|fieldset|select|address|div|hr)@) {
$p =~ s!\r?\n!<br />\n!g;
$p = "<p>$p</p>";
}
と、ディレクトリが記述されており、パッチをあてる対象のファイル(ここでは Util.pm)がカレントディレクトリに配置されている場合、パッチをあてるコマンドは
C:¥work>patch -p2 < patch.txt
と "-p2" を設定します。
解説すると、上記の例は「パッチファイルに記述されたディレクトリを2階層分無視して、カレントディレクトリ(の Util.pm)にパッチをあてよ」という指定をしている訳です。
つまり、最初の "-p0" というオプションは「ディレクトリを無視しない」という意味になります。上記のパッチファイルを Movable Type のいわゆる CGIPath に配置し、"-p0" を付与して patch コマンドを実行すると正常に行われる、という訳です。
逆にパッチで記述されたディレクトリに該当ファイルが存在しない状態で "-p0" オプションを付与してコマンドを実行すると、
C:¥work>patch -p0 < patch.txt
can't find file to patch at input line 3
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|--- lib/MT/Util.pm.bak Fri Feb 17 23:19:44 2006
|+++ lib/MT/Util.pm Fri Feb 17 23:20:48 2006
--------------------------
File to patch:
というメッセージが表示されますのでご注意ください。
また、-p オプションを付与しない場合、パッチファイルに記述されているディレクトリが全て無視されてファイル名だけが対象となりました。したがってカレントディレクトリにファイルを置いている場合は -p オプションを付与する必要がないということになります。
パッチファイルにディレクトリの指定がないのに、"-p2" とかつけて実行すると下記のようなメッセージが出力されます。
C:¥work>patch -p2 < patch.txt
missing header for unified diff at line 3 of patch
can't find file to patch at input line 3
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|--- Util.pm.bak Fri Feb 17 23:19:44 2006
|+++ Util.pm Fri Feb 17 23:20:48 2006
--------------------------
File to patch:
上記の内容を整理すると、patch コマンドにおける -p オプションの適用方法は下記のようになります。
| パッチをあてるファイル | |||
|---|---|---|---|
| カレントディレクトリにある | パッチファイルに記述された ディレクトリにある | ||
| パッチファイル | ディレクトリ 記述あり | -pnumber または不要 (numberは無視する階層数) | -p0 |
| ディレクトリ 記述なし | 不要 (-p0をつけても問題なし) | ー | |
-pnumber オプションの代わりに --strip=number でも同じ効果があります。
C:¥work>patch --strip=0 < patch.txt
こちらの方が直感的に分かりやすそうです。
| その1:適用方法 |
| その2:パッチを作る |
| その3:patchコマンドの-pオプションについて |
パッチをあてる(その2:パッチを作る)
パッチをあてる(その1:適用方法)の続きで(随分間があきましたが)、今回はパッチを作る方法をご紹介します。
パッチとはプログラムを修正するための差分、あるいは差分が記述されたファイルを指します。パッチを作るためには変更前のファイルと変更後のファイルを比較して、その差分を抽出します。比較するためには diff コマンドを利用します。
ここではその1の3.1項と同じ、下記のパッチを作ってみることにします。
--- Util.pm.bak Fri Jan 06 14:19:44 2006
+++ Util.pm Fri Jan 06 14:20:48 2006
@@ -401,7 +401,7 @@
$str ||= '';
my @paras = split /\r?\n\r?\n/, $str;
for my $p (@paras) {
- if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)@) {
+ if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|menu|dir|p|pre|center|form|fieldset|select|address|div|hr)@) {
$p =~ s!\r?\n!<br />\n!g;
$p = "<p>$p</p>";
}
作業ディレクトリは前回と同様、C:¥work とします。その1で作ったファイル類は全て削除しておいてください。
1.diff コマンドの準備
パッチの作成にあたっては diff コマンドを使用します。Linux ではデフォルトで用意されているようですが、Windows では用意されていません。
ということで、diff コマンドをソフトウェア工房αから入手します。
プログラミング・ツール(移植ソフト)に表示されている、
- diff272w.zip
- diff.exe
をPCの任意のディレクトリに配置します(他にファイルが色々入ってますが今回は使いません)。C:¥WINDOWS 配下または C:¥WINDOWS¥system32 配下に配置できれば、後述するMS-DOSコマンドプロンプトからの起動でパスを指定せずに実行することができます。
配置できない場合はとりあえず C:¥ 配下においてください。
2.ファイルのバックアップ
修正するファイルとなる、lib/MT/Util.pm をコピーして Util.pm.bak というファイル名で保存してください。なお修正前のファイル名が Util.pm.bak、修正後のファイル名が Util.pm となります。これは修正後のファイルを正規のファイルとして使用するためです。いずれも C:¥work 配下に配置してください。
3.ファイルの修正
任意のエディタで work 配下に配置した Util.pm を開き、404 行目の
if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)@) {
を
if ($p !~ m@^>/?(?:h1|h2|h3|h4|h5|h6|menu|dir|p|pre|center|form|fieldset|select|address|div|hr)@) {
に修正します。
4.diff 実行
次に MS-DOS コマンドプロンプトを開き、
C:¥>cd work
で、work ディレクトリへ移動し、diffコマンド
C:¥work>diff -u Util.pm.bak Util.pm
を実行します。Cドライブ直下に diff.exe を置いている場合は、
C:¥work>C:¥diff -u Util.pm.bak Util.pm
とします。
2つのファイルには、先程修正した差分がありますので、画面に
--- Util.pm.bak Fri Jan 06 14:19:44 2006
+++ Util.pm Fri Jan 06 14:20:48 2006
@@ -401,7 +401,7 @@
$str ||= '';
my @paras = split /\r?\n\r?\n/, $str;
for my $p (@paras) {
- if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)@) {
+ if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|menu|dir|p|pre|center|form|fieldset|select|address|div|hr)@) {
$p =~ s!\r?\n!<br />\n!g;
$p = "<p>$p</p>";
}
が表示されます。これがパッチとなります。diff コマンドの後の "-u" を省略すると差分の行だけが表示されます。
これをマウスコピーして任意のエディタで新しいファイルを開き、ペースト&保存しても良いのですが、
C:¥work>diff -u Util.pm.bak Util.pm > patch.txt
を実行すれば work 配下に patch.txt というファイル名で直接保存することができます。これがパッチファイルとなり、その1の3.1項で作ったパッチファイルと同じものになります。
他のファイルでも同様に差分を表示することができますので、色々とお試しください。
| その1:適用方法 |
| その2:パッチを作る |
| その3:patchコマンドの-pオプションについて |
パッチをあてる(その1:適用方法)
以前、カスタマイズを色々紹介する中で「パッチをあてる」という作業の具体的な方法について、認識不足のため誤った説明をしておりましたので、その適用方法についてお詫びを兼ねて改めて紹介したいと思います。ここでは Windows での作業について説明します。
1.パッチとは
「パッチ」はプログラムの一部を修正することです。「パッチワーク」を思い出して頂ければ分かりやすいと思います。「パッチファイル」はプログラムを修正するための差分が記述されたファイルです。
「パッチをあてる」というのは実際にプログラムを修正する行為を指します。
2.patch コマンドの準備
パッチの適用にあたっては patch コマンドを使用します。Linux ではデフォルトで用意されているようですが、Windows では用意されていません。
ということで、まず patch コマンドを入手します。
patch コマンドは Cygwin・ソフトウェア工房α・Vector 等で配布されていますが、ここではソフトウェア工房αから入手します。
プログラミング・ツール(移植ソフト)に表示されている、
- patc254w.zip
をクリックし、解凍した中にある
- patch.exe
をPCの任意のディレクトリに配置します。C:\WINDOWS 配下または C:\WINDOWS\system32 配下に
配置できれば、後述するMS-DOSコマンドプロンプトからの起動でパスを指定せずに実行することができます。
配置できない場合はとりあえず C:\ 配下においておきましょう。
3.パッチをあてる
パッチをあてる作業は、パッチファイル(またはパッチとなるテキスト)とパッチをあてる元のプログラムを用意し、その2つが用意された状態で patch コマンドを実施すると元のプログラムが書き換えられます。
以下、順を追って作業内容を説明します。
3.1 パッチファイルを保存する
下記のような内容のパッチファイルがあると想定します。
--- Util.pm.bak Fri Jan 06 14:19:44 2006
+++ Util.pm Fri Jan 06 14:20:48 2006
@@ -401,7 +401,7 @@
$str ||= '';
my @paras = split /\r?\n\r?\n/, $str;
for my $p (@paras) {
- if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)@) {
+ if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|menu|dir|p|pre|center|form|fieldset|select|address|div|hr)@) {
$p =~ s!\r?\n!<br />\n!g;
$p = "<p>$p</p>";
}
これは Movable Type の lib/MT/Util.pm の 404 行目あたりにある、エントリー保存時、エントリーに改行を付与する処理を修正するパッチで、プログラム内に改行タグを付与する基準となるタグが列挙されており、そのタグを一部変更するものです。
具体的な変更内容は、行頭に "-" のある行を "+" がある行に変更します。つまり並んでいるタグから、table/ul/ol/dl/blockquote が取り除かれます。
さて、ここで行う作業ですが、C:\ 配下に work ディレクトリを作り、patch.txt というファイル名で上記パッチの内容をマウスコピーして保存します。最初からファイルになっている場合はそのまま C:\ 配下に保存します。
実際に作業を行う場合、ディレクトリ・ファイル名は任意の名称で構いません。
注:ファイルの最後の行(上の例では "}")の末尾には必ず改行を含めてください。
3.2 パッチをあてるファイルを配置する
次に、パッチをあてる元のファイル lib/MT/Util.pm を先ほどの work ディレクトリにコピーします。ファイル名は Util.pm のままで結構です。
興味のある方は、このファイルを任意のエディタで開き、404 行目がパッチファイルの "-" と同じ内容であることを確認しましょう。
3.3 パッチをあてる
MS-DOS コマンドプロンプトを起動し、
C:¥>cd work
で、work ディレクトリへ移動し、patchコマンド
C:¥work>patch < patch.txt
を実行します。この実行イメージは patch コマンドが C:\WINDOWS 配下または C:\WINDOWS\system32 配下にある場合(つまり patch コマンドのパスが認識されている場合)を想定しています。コマンドが認識されない場合は、patch コマンドが置かれているパスを記述します(パスの設定する方法もありますがここでは省略します)。
C:\ 直下に patch を置いている場合は
C:¥work>C:¥patch < patch.txt
とします。
コマンド実行が成功すると画面の最後に
patching file Util.pm
と表示されます。これで完了です。
これで Util.pm の 404 行目が変更されていますので、この変更された Util.pm を元のディレクトリに上書きしてください。なお、patch コマンドに -p0 というオプションがついている場合がありますが、この使用方法については「パッチをあてる(その3:patchコマンドの-pオプションについて)」で説明します。
なお、以前の説明では、Utll.pm を任意のエディタで開き、「"-" の部分を削除して "+" の部分を追加する」という内容を記述してました。正常に動作すれば結果オーライなのですが、パッチの適用方法について適正な方法を最初にお伝えできていなかったことについては反省しております。
3.4 パッチをはずす
3.3項であてたパッチを外したい(元に戻したい)場合は、MS-DOS コマンドプロンプトで
C:¥work>patch -R < patch.txt
と入力してください。成功すると画面の最後に
patching file Util.pm
と表示されます。
4.パッチが分からない方&面倒な方へ
要は、パッチの行頭に「+」が記された行を追加して、「-」の行を削除すればOKです。3.1項のパッチを例に示します。赤色が削除行で青色が追加行です。この変更内容と3.1のパッチの表示を見比べ、どこを修正すればよいかを把握してください。
修正前
--- Util.pm.bak Fri Jan 06 14:19:44 2006
+++ Util.pm Fri Jan 06 14:20:48 2006
@@ -401,7 +401,7 @@
$str ||= '';
my @paras = split /\r?\n\r?\n/, $str;
for my $p (@paras) {
if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|table|ol|dl|ul|menu|dir|p|pre|center|form|fieldset|select|blockquote|address|div|hr)@) {
$p =~ s!\r?\n!<br />\n!g;
$p = "<p>$p</p>";
}
修正後
--- Util.pm.bak Fri Jan 06 14:19:44 2006
+++ Util.pm Fri Jan 06 14:20:48 2006
@@ -401,7 +401,7 @@
$str ||= '';
my @paras = split /\r?\n\r?\n/, $str;
for my $p (@paras) {
if ($p !~ m@^</?(?:h1|h2|h3|h4|h5|h6|menu|dir|p|pre|center|form|fieldset|select|address|div|hr)@) {
$p =~ s!\r?\n!<br />\n!g;
$p = "<p>$p</p>";
}
なおこの方法による修正の場合、事前に該当ファイルのバックアップをとっておきましょう。修正を誤るとMovable Type が正常に動作しなくなる可能性があります(失敗した場合は修正前のファイルに戻せば良いので心配することはありません)。
以上です。
参考サイトは下記です。ありがとうございました。
2007.04.25 追記
ファイルを保存する際の注意事項を追加しました。

