LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1755|回复: 10

一分钟patch教程

[复制链接]
发表于 2005-6-17 19:55:43 | 显示全部楼层 |阅读模式
patch的使用:
//patch manual建议两个目录处于同一层次

dev/gcc-2.7
dev/gcc-2.8
cd dev

创建patch:
// patch manual建议:
// export LC_ALL=C
// export TZ=UTC0
//大概是为了时间戳保持标准的记法。

// diff -Naur oldDir newDir # patch manual建议两个目录名都不要包含'/'

diff -Naur gcc-2.7 gcc-2.8 >gcc-2.7_2.8.patch

打patch:

cd gcc-2.7; patch -Np1 -i ../gcc-2.7_2.8.patch
将2.7升到2.8
or

cd gcc-2.8; patch -Rp1 -i ../gcc-2.7_2.8 patch
将2.8降到2.7

-N 如果当前目录是新版本, 则忽略这个patch
-R 如果当前目录是新版本, 则降到旧版本 (reverse)
-pn 忽略掉patch文件中前几个目录分隔符, 比如/aa/bb在p1时就是aa/bb
    (比如patch文件中两行:
        +++ /u/aa/bb.txt ...
        --- /u/aa-new/bb.txt
        -p0则保持两个文件名不变
           -p1则上两行的文件名变为u/aa/bb.txt和u/aa-new/bb.txt
                -p2则上两行的文件名变为aa/bb.txt和aa-new/bb.txt
        -p3则上两行的文件名变为bb.txt和bb.txt
         到底指定多少要看当前所处目录层次和patch文件中的文件名目录层次是否匹配,
        比如cd aa, 对于上面的两行, 应该用p3了)
-i patchfile 指定输入文件,也可以用重定向输入指定patchfile

==============
对p参数的附加说明:
diff (GNU diffutils) 2.8.1,  patch (Larry Wall) 2.5.9
patch会自动判断p参数, 所以一般情况下只需要 patch -N <patchfile
试验, 以下情况p参数均未指定就能成功:
cd old;
(p1)
old/aa.txt
new/aa.txt
(p2)
xx/old/aa.txt
xx/new/aa.txt
(p2)
xx/old/aa.txt
yy/new/aa.txt
后面两个是我手工修改了patch文件.
============
//再次添加说明:
刚发现patch对目录名要求相当宽松, 估计是从后面往前面匹配的,

diff -Naur  path_to_your_old_top_dir   path_to_your_new_top_dir >p
cd path_to_your_old_top_dir; patch -N < path_to/p

# -N 只是保险起见, 如果在一个新版本上patch <p, 会提示是否Reverse.
or

cd path_to_your_new_top_dir; patch -R <path_to/p

==============
嗯, 又补充, 发现patch自动判断p参数时有误判:
+++ aa-old/cc/aa.txt ...
--- aa/cc/aa.txt ...
cd aa-old; patch -N<my.patch会出错,原因是patch把p参数设置成了p2。
当patch文件中第一笔记录的不包含路径名的文件名(上例中就是aa.txt)不在
运行patch的目录中(此处是aa)中时, patch会错误的将p参数设置成直到去掉
最后一个'/'(此处有aa.txt之前有两个'/',因此p参数为2,其实应该是1)。
我觉得这个p参数可以这样判断:
若命令行设置了,pold=pnew=parg;
若命令行没有设置, 则一次次增大pold(0~countOf('/', oldFile)), 判断
去掉了pold个'/'后在当前目录中存在这个文件名否, 如果存在则pold就是这个值,
而pnew就是就是在newFile中搜索上面这个文件名得到的索引值, 详细过程如下:

  1. pold = 0; pnew =0;
  2. if (命令行上没有-p选项) {
  3.      readpatchfile(); oldFile = "aa-old/cc/aa.txt"; newFile = "aa/cc/aa.txt";
  4.       int n = countOf('/', oldFile);
  5.       while (pold <= n) {
  6.           oldFile = 去掉第pold个'/'所处位置及之前字符后的字符串(比如pold=1, oldFile就是cc/aa.txt)
  7.           if (oldfile不存在于当前目录中) {++pold; continue;} //只能按照pold递增的方式查找,
  8.                                            //否则在aa-old/cc/aa.txt, aa-old/aa.txt的情况下会出错
  9.           比如pold=1, 在当前目录中找到cc/aa.txt了, 然后在newFile中查找cc/aa.txt
  10.              最后一次出现的位置, 得到的位置就是newfile中从0算起第3个位置, 统计一下之前
  11.         的'/'的个数, 此处pnew=1;
  12.         实际上pold和pnew可以分别记录在旧新版本的文件名中要忽略掉的前缀字符个数,
  13.        不用记录'/'的个数.
  14. }
复制代码

按照这种方式的话应该就可以废弃-p参数了.
呵呵,可以给patch打patch了.

一点笔记, 希望对大家有用, 参考了patch和diff的man, 以及LFS版的一篇帖子(搜索到的,
好多人问), 如有谬误, 欢迎指正  

===
第10次修改, 似乎一分钟看不完了
发表于 2005-6-17 20:46:14 | 显示全部楼层
回个帖,收藏!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-6-17 20:52:13 | 显示全部楼层
呜呜, 反复修改了近四十分钟, 终于有人顶一下....

期间有几个错别字和有一个2.8打成了2.7(这个实在太不应该了-_-),又添加了点说明。
回复 支持 反对

使用道具 举报

发表于 2005-6-17 20:59:54 | 显示全部楼层
哈哈 ,感谢,回头试试!!
回复 支持 反对

使用道具 举报

发表于 2005-6-17 22:38:11 | 显示全部楼层
一直没耐心看E文的man,楼主做了件好事啊
回复 支持 反对

使用道具 举报

发表于 2005-6-17 23:18:59 | 显示全部楼层
一直没能彻底弄明白-p的作用,这回终于懂了。
感谢dieken_qfz !希望这种好东西多贴。
回复 支持 反对

使用道具 举报

发表于 2005-6-18 00:59:51 | 显示全部楼层
不错。。。继续
回复 支持 反对

使用道具 举报

发表于 2005-6-18 16:12:58 | 显示全部楼层
好东西。
回复 支持 反对

使用道具 举报

发表于 2005-6-18 20:10:46 | 显示全部楼层
好贴~~~~~~~~~
回复 支持 反对

使用道具 举报

发表于 2005-6-19 11:08:05 | 显示全部楼层
谢谢楼主~~
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表