patchコマンド-pオプションの覚え書き

patchコマンドは、元ファイルと差分情報からファイルを更新してくれる素晴らしいコマンドだが、patchコマンドを実行するディレクトリと-pオプションの設定で悩むことが多い。そこで今後のために、自分用の覚え書き。

ファイルにパッチを当てる

  • 様々なオプションが設定できるが、基本は以下の書式。
$ patch 元ファイルのパス < patchファイル(差分情報)のパス
  • 元ファイルが存在するディレクトリに移動すれば、「元ファイルのパス」は省略できる。(以下synergy-1.3.1の例)
$ cd ~/Downloads/synergy-1.3.1/lib/platform
$ patch < ~/Downloads/OSX_BusError.patch
  • synergy-1.3.1に対するパッチファイル、OSX_BusError.patchをサンプルに考えてみる。
Index: COSXKeyState.cpp
===================================================================
RCS file: /cvsroot/synergy2/synergy/lib/platform/COSXKeyState.cpp,v
retrieving revision 1.11
diff -u -p -r1.11 COSXKeyState.cpp
--- COSXKeyState.cpp	23 Mar 2006 06:03:20 -0000	1.11
+++ COSXKeyState.cpp	17 Aug 2006 05:02:39 -0000
@@ -790,6 +790,12 @@ COSXKeyState::CKeyResource::getKeyID(UIn
 							str, GetScriptManagerVariable(smKeyScript),
 							kCFAllocatorNull);
 
+		// sometimes CFStringCreate returns NULL, (e.g., Apple Korean encoding with char 
+		// value 214 when start up.) if so, make it no key. otherwise, that NULL is given to 
+		// CFStringCreateMutableCopy down Below, which makes a BUS ERROR.
+		if (cfString == 0x0) 
+		  return kKeyNone; 
+
 		// convert to precomposed
 		CFMutableStringRef mcfString =
 			CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfString);
  • 6行目「--- COSXKeyState.cpp」の部分から判断して、ファイル名だけが指定されているので、ファイルに対するパッチと判断できる。
  • 3行目「RCS file:」にソースコードを管理している環境でのパスが表示されている。ダウンロードした元ファイルも相対的に同じ構造なので、目指すファイルがどこに存在するか簡単に予想できる。

ディレクトリごとパッチを当てる

  • ディレクトリ以下のすべてのファイルに対してパッチを当てることができる。その基本は以下のオプション指定。
  • ディレクトリは、ダウンロードしたソースコードが保存されているプロジェクトフォルダと考えることができる。
$ patch -p0 -d 元ディレクトリのパス < patchファイル(差分情報)のパス
$ cd ~/Downloads/synergy-1.3.1
$ patch -p0 < ~/Downloads/synergy.patch
  • synergy-1.3.1に対するパッチファイル、synergy.patchをサンプルに考えてみる。
Index: cmd/synergyc/synergyc.cpp
===================================================================
RCS file: /cvsroot/synergy2/synergy/cmd/synergyc/synergyc.cpp,v
retrieving revision 1.20
diff -u -p -r1.20 synergyc.cpp
--- cmd/synergyc/synergyc.cpp	23 Mar 2006 06:03:00 -0000	1.20
+++ cmd/synergyc/synergyc.cpp	28 Jan 2008 07:25:39 -0000
@@ -435,7 +435,7 @@ standardStartup(int argc, char** argv)
 
 	// daemonize if requested
 	if (ARG->m_daemon) {
-		return ARCH->daemonize(DAEMON_NAME, &daemonMainLoop);
+      return ARCH->daemonize(DAEMON_NAME, argc, argv, &daemonMainLoop);
 	}
 	else {
 		return mainLoop();
...(中略)...
  • 6行目「--- cmd/synergyc/synergyc.cpp」の部分から判断して、ディレクトリが指定されているので、ディレクトリに対するパッチと判断できる。
  • 「-p0」オプションは、上記ディレクトリをそのまま適用してパッチを当てる。
    • つまり現在位置のカレントディレクトリと合わせて「~/Downloads/synergy-1.3.1/cmd/synergyc/synergyc.cpp」というファイルがパッチの対象になる*1
    • 上記ファイルは存在するので、パッチは素早く正常に終了する。
  • 「-p1」オプションの場合は、最上位のディレクトリ「cmd/」が省略される。
    • つまり現在位置のカレントディレクトリと合わせて「~/Downloads/synergy-1.3.1/synergyc/synergyc.cpp」というファイルがパッチの対象になる。
    • しかし、そのようなファイルは存在しないので、「File to patch:」と表示され、パッチ対象のファイルの指定を求められる。
  • 同様に「-p2」では「cmd/synergyc/」2階層が省略され、「-p3」では3階層が省略され...という処理が行われる。

「-p数値」オプションは何のために?

  • 「-p数値」オプションは、パッチファイルのディレクトリ環境と、パッチ対象ファイルが存在するディレクトリ環境の違いを調整したい時に役立ちそう。
    • 例えば、もし6行目が「--- cvsroot/synergy2/synergy/cmd/synergyc/synergyc.cpp」となっていたら、「-p3」を指定するとうまく行くはず。

参考ページ

以下のページがたいへん参考になりました。感謝です!

*1:もし、「-d 元ディレクトリのパス」が指定されていれば、「元ディレクトリのパス/cmd/synergyc/synergyc.cpp」というファイルがパッチの対象になるはず。