Wednesday, July 09, 2008

使用diff和patch来制作补丁

首先说明使用diff和patch一般使用来处理文本文件的,对于开源项目,这两个工具是很好的帮手,比如linux的内核发布就包含很多patch,这样你不用每次都下载完整的源代码包,只需要下载目标版本和你已有版本之间的patch。
我会通过一个实际的操作示例来说明这两个工具的使用。有一个项目,名字叫testproject,已经发布了两个版本,2.2.0和2.2.1,其中上海生产环境部署了2.2.0,深圳开发中心已经发布了新版的2.2.1,现在生产环境需要升级到2.2.1,因为新版本修复了重要的bug。 方法有很多种,这里我们说明使用diff和patch的方式。
* 首先在当前工作目录下(假设为/home/jack/),从subversion上export两个版本。
> svn export http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.0/sourcecode 2.2.0
>svn export http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.1/sourcecode 2.2.1
* 执行diff
>diff -Nur 2.2.0 2.2.1 >220-221.patch
上面的命令会生成一个patch文件,其中-N表示如果目标目录不包含源目录中的文件,那么认为目标目录存在一个内容为空的同名文件。 -u表示生成统一的有上下文的patch文件(后面再说patch格式)。 -r表示递归处理,在处理目录的时候需要这个参数。
* 接下来,我们开始使用patch
>cp 220_221.patch 2.2.0
>cd 2.2.0
>patch -p1<220_221.patch>rm 220_221.patch
>cd ..
>diff -Nur 2.2.0 2.2.1 >220-221_new.patch
可以看到这次得到的220-221_new.patch是空文件,这就说明现在2.2.0的源代码已经被升级到2.2.1了。
* 好了,现在我们可以将这个patch文件从深圳发到上海,然后上海更新源代码,再次编译,测试,打包,部署....

===========================
subverion的diff
===========================
接下来我要试试patch能不能处理subversion的diff得到的patch文件。
* 生成subversion的diff文件,在当前工作目录下(假设为/home/jack/).
> svn diff http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.0/sourcecode http://192.168.0.253/svn/TcCenter/TcCenter/tag/2.2.1/sourcecode > diff.patch
>cp diff.patch 2.2.0
>patch -p0rm diff.patch
>cd ..
>>diff -Nur 2.2.0 2.2.1 >220-221_new.patch
可以看到,220-221_new.patch文件为空,说明2.2.0已经升级到2.2.1了。
这里使用diff命令和使用‘svn diff’得到的patch文件格式有点不一样,使用diff得到的为:
diff -Nur 2.2.0/build.properties 2.2.1/build.properties
--- 2.2.0/build.properties 2008-04-30 15:09:14.000000000 +0800
+++ 2.2.1/build.properties 2008-06-27 15:39:36.000000000 +0800
@@ -8,7 +8,7 @@
#--------------------------------------------#
project.name=CentralPool
#DO NOT modify below setting.
-app.version=2.2.0
+app.version=2.2.1
app.vendor=Shenzhen Helper Science & Technology Co., Ltd.
builder.name=${project.name} Team

diff -Nur 2.2.0/CHANGELOG.txt 2.2.1/CHANGELOG.txt
--- 2.2.0/CHANGELOG.txt 2008-04-08 17:02:58.000000000 +0800
+++ 2.2.1/CHANGELOG.txt 2008-06-27 15:39:36.000000000 +0800
@@ -1,16 +1,16 @@
-CENTRALPOOL PROJECT CHANGELOG
+CENTRALPOOL PROJECT CHANGELOG
--------------------------------------
ChangeLog定义了当前版本相对于上一个版本之间系统发生的变更. 这些变更包括修正的bug, 系统新增的
功能,或者系统添加的补丁等等.

而使用‘svn diff’得到的patch文件为:
Index: sub-core/src/com/hengpeng/ante/game/GameFactory.java
===================================================================
--- sub-core/src/com/hengpeng/ante/game/GameFactory.java (.../2.2.0/sourcecode) (revision 241)
+++ sub-core/src/com/hengpeng/ante/game/GameFactory.java (.../2.2.1/sourcecode) (revision 241)
@@ -51,6 +51,9 @@

case Game.GAME_TYPE_SSC:
return new SSCGame(gameData);
+
+ case Game.GAME_TYPE_NUMLOTTO:
+ return new NumLottoGame(gameData);

default:
throw new HPException(AnteException.ErroCode_NoGame,
Index: sub-core/src/com/hengpeng/ante/game/Game.java
===================================================================
--- sub-core/src/com/hengpeng/ante/game/Game.java (.../2.2.0/sourcecode) (revision 241)
+++ sub-core/src/com/hengpeng/ante/game/Game.java (.../2.2.1/sourcecode) (revision 241)
@@ -75,7 +75,13 @@
*/
public static final int GAME_TYPE_SSC = 9;

+ /**
+ * 东方6+1玩法 {@value}
+ * @value 9
+ */
+ public static final int GAME_TYPE_NUMLOTTO = 10;

+
// GAME DEFINITION
public static final int GAME336 = 11;
public static final int GAME155 = 23;
幸运的是patch命令都可以处理,实际上两种都是正确的格式。

diff和patch在linux操作系统中是自带的,但是进入windows环境就没有那么容易了。不过好在有一个gunwin32的开源项目(gunwin32.sourceforge.net),gnu下的diff和patch都可以运行在window上了。

No comments: