Linux之旅(1): diff, patch和quilt (下)

Linux之旅(1): diff, patch和quilt (下)

Linux之旅(1): diff, patch和quilt (下)

2 quilt

我们自己的项目能够用cvs或svn管理所有代码。但有时我们要使用其它开发人员维护的项目。我们须要改动一些文件,但又不能直接向版本号管理工具提交代码。自己用版本号管理工具重建整个项目是不合适的,由于大多数代码都是别人维护的,比如Linux内核。我们仅仅是想管理好自己的补丁。这时能够使用quilt。

2.1 基本概念

quilt是一个帮助我们管理补丁的程序。quilt的命令格式相似于cvs:

quilt 子命令 [參数]

0.46版的quilt有29个子命令。

掌握quilt的关键是了解使用quilt的流程。使用quilt时,我们会在一个完整的源码树里工作。仅仅要我们在源码树里使用了quilt命令,quilt就会在源码树的根文件夹建立两个特殊文件夹:patches和.pc。quilt在patches文件夹保存它管理的全部补丁。quilt用.pc文件夹保存自己的内部工作状态,用户不须要了解这个文件夹。

patches/series文件记录了quilt当前管理的补丁。补丁依照添�的顺序排列,早添�的补丁在前。quilt用堆栈的概念管理补丁的应用。

<span>Linux之旅(1): diff, patch和quilt (下)</span>

我们在应用补丁A前,必须先应用全部早于补丁A的补丁。所以,patches/series中的补丁总是从上向下应用。比如:上图中,补丁1到补丁5是已经应用的补丁。我们能够将已应用的补丁想象成一个向下生长的堆栈,栈顶就是已应用的最新补丁。应用补丁就是将补丁入栈,撤销补丁就是将补丁出栈。

我们在源码树中作不论什么改动前,必须用”quilt add”命令将要改动的文件与一个补丁联系起来。在完毕改动后,用”quilt refresh”命令将改动保存到已联系的补丁。以下我们通过一篇流程攻略来认识一下quilt的命令。

2.2 导入补丁

我们把 old-prj.tar.bz2 想象成Linux内核,我们把它解压后,进入代码树的根文件夹:

$ mkdir qtest; cd qtest; tar xvjf ../old-prj.tar.bz2; mv old-prj prj; cd prj

在改动代码前,我们通常要先打上官方补丁。在quilt中,能够用import命令导入补丁:

$ quilt import ../../prj.diff

Importing patch ../../prj.diff (stored as prj.diff)

运行improt命令后, prj 文件夹会多出一个叫 patches 的子文件夹:

$ find patches/ -type f

patches/prj.diff

patches/series

quilt在这个文件夹存放全部补丁和前面介绍的series文件。quilt的大多数命令都能够在代码树的随意子文件夹执行,不一定要从根文件夹执行。我们能够用applied命令查询当前已应用的补丁。

$ quilt applied

No patches applied

眼下还没有应用不论什么补丁。unapplied命令查询当前还没有应用的补丁,top命令查询栈顶补丁,即已应用的最新补丁:

$ quilt unapplied

prj.diff

$ quilt top

No patches applied

我们能够使用push命令应用补丁,比如:

$ quilt push -a

Applying patch prj.diff

patching file src/drv/drv1.h

patching file src/sys/sys1.c

patching file src/sys/sys1.h

patching file src/usr/usr1.c

patching file src/usr/usr1.h

Now at patch prj.diff

push的”-a”參数表示应用全部补丁。在使用push命令后,prj 文件夹会多了一个叫.pc的隐含子文件夹。quilt用这个文件夹保存内部状态,用户不须要了解这个文件夹。应用补丁后,我们再使用applied、unapplied和top命令查看:

$ quilt applied

prj.diff

$ quilt unapplied

File series fully applied, ends at patch prj.diff

$ quilt top

prj.diff

2.3 改动文件

我们必须将对源码树所作的不论什么修改都和一个补丁联系起来。add命令将文件的当前状态与补丁联系起来。add命令的格式为:

quilt add [-P 补丁名] 文件名称

假设未指定补丁名,文件就与栈顶补丁联系起来。眼下,我们的栈顶补丁是官方补丁。我们不想改动这个补丁,能够用new命令新建一个补丁:

$ quilt new drv_p1.diff

Patch drv_p1.diff is now on top

$ quilt top

drv_p1.diff

$ quilt applied

prj.diff

drv_p1.diff

$ quilt unapplied

File series fully applied, ends at patch drv_p1.diff

然后用add命令向栈顶补丁加入�一个准备改动的文件:

$ cd src/drv; quilt add drv2.h

File src/drv/drv2.h added to patch drv_p1.diff

add命令为指定补丁保存了指定文件的当前快照,当我们运行refresh命令时,quilt就会检查文件的变化,将差异保存到指定补丁中。使用”quilt diff -z [-P 补丁名] [文件名称]”能够查看指定补丁指定文件的当前修改。省略-P參数表示查看当前补丁的修改,省略文件名称表示查看全部修改。我们修改drv2.h后,运行diff命令:

$ quilt diff -z

Index: prj/src/drv/drv2.h

===================================================================

— prj.orig/src/drv/drv2.h 2008-03-02 13:37:34.000000000 +0800

+++ prj/src/drv/drv2.h 2008-03-02 13:38:53.000000000 +0800

@@ -1,7 +1,7 @@

-#ifndef APP1_H

-#define APP1_H

+#ifndef DRV2_H

+#define DRV2_H

 

-#include “def1.h”+#include “def2.h” #endif

 

仅仅要文件已经与我们希望保存修改的补丁联系过了,我们就能够多次修改文件。使用”quilt files [补丁名]”命令能够查看与指定补丁关联的文件。使用”quilt files -val”能够查看全部补丁联系的全部文件。”-v”參数表示更友好的显示,”-a”參数表示显示全部补丁,”-l”參数显示补丁名。比如:

$ quilt files

src/drv/drv2.h

$ quilt files -val

[prj.diff] src/drv/drv1.h

[prj.diff] src/sys/sys1.c

[prj.diff] src/sys/sys1.h

[prj.diff] src/usr/usr1.c

[prj.diff] src/usr/usr1.h

[drv_p1.diff] src/drv/drv2.h

“quilt refresh [补丁名]”刷新补丁,即将指定补丁的文件变化保存到补丁。省略文件名称表示刷新栈顶补丁。我们refresh后,查看补丁文件:

$ quilt refresh

Refreshed patch drv_p1.diff

$ cat ../../patches/drv_p1.diff

Index: prj/src/drv/drv2.h

===================================================================

— prj.orig/src/drv/drv2.h 2008-03-02 12:42:21.000000000 +0800

+++ prj/src/drv/drv2.h 2008-03-02 12:46:25.000000000 +0800

@@ -1,7 +1,7 @@

-#ifndef APP1_H

-#define APP1_H

+#ifndef DRV2_H

+#define DRV2_H

 

-#include “def1.h”

+#include “def2.h”

 

#endif

 

“quilt diff -z”命令不会显示已经保存的差异。”quilt diff”显示全部的差异,无论是否保存过。

2.4 再做几个补丁

在添加�文件前,我们要先将准备添加�的文件与补丁联系起来。我们新建一个补丁,然后新增两个文件src/applet/applet1.h和src/applet/applet1.c。

$ cd ..; quilt new more_p1.diff

Patch more_p1.diff is now on top

$ quilt add applet/applet.c

File src/applet/applet.c added to patch more_p1.diff

$ quilt add applet/applet.1

File src/applet/applet.1 added to patch more_p1.diff

 

看看我们添加�的文件:

$ quilt files

src/applet/applet.1

src/applet/applet.c

 

哎呀,文件名称写错了。我们能够用”remove”命令从补丁中删除关联文件:

$ quilt remove applet/applet.1

rm: remove write-protected regular empty file `.pc/more_p1.diff/src/applet/applet.1′? y

File src/applet/applet.1 removed from patch more_p1.diff

$ quilt remove applet/applet.c

rm: remove write-protected regular empty file `.pc/more_p1.diff/src/applet/applet.c’? y

File src/applet/applet.c removed from patch more_p1.diff

$ quilt files

$ quilt add applet/applet1.h

File src/applet/applet1.h added to patch more_p1.diff

$ quilt add applet/applet1.c

File src/applet/applet1.c added to patch more_p1.diff

$ quilt files

src/applet/applet1.c

src/applet/applet1.h

 

好了,如今能够创建新文件:

$ mkdir applet

$ echo -e “#ifndef APPLET1_H/n#define APPLET1_H/n#include /”def1.h/”/n#endif”>applet/applet1.h

$ echo -e “#include /”applet1.h/””>applet/applet1.c

$ quilt refresh more_p1.diff

Refreshed patch more_p1.diff

 

刷新补丁后,我们再改动文件drv2.h。改动前一定要先将文件与准备保存改动的补丁联系起来:

$ quilt add drv/drv2.h

File src/drv/drv2.h added to patch more_p1.diff

$ vi drv/drv2.h

$ quilt diff -z drv/drv2.h

Index: prj/src/drv/drv2.h

===================================================================

— prj.orig/src/drv/drv2.h 2008-03-02 14:19:35.000000000 +0800

+++ prj/src/drv/drv2.h 2008-03-02 14:31:28.000000000 +0800

@@ -1,7 +1,7 @@

#ifndef DRV2_H

#define DRV2_H

 

-#include “def2.h”

+#include “def1.h”

 

#endif

 

我们再新建一个补丁,然后删除两个文件。删除文件前也要先为文件建立关联:

$ quilt new more_p2.diff

Patch more_p2.diff is now on top

$ quilt add app/*

File src/app/app1.c added to patch more_p2.diff

File src/app/app1.h added to patch more_p2.diff

File src/app/app2.c added to patch more_p2.diff

File src/app/app2.h added to patch more_p2.diff

$ rm -rf app

$ quilt refresh

Refreshed patch more_p2.diff

 

我们再改动applet/applet1.h:

$ quilt edit applet/applet1.h

File src/applet/applet1.h added to patch more_p2.diff

$ quilt refresh

Refreshed patch more_p2.diff

 

“quilt edit”在调用”quilt add”后自己主动启动编辑器。用refresh命令刷新补丁。

对了,前面为more_p1.diff改动drv2.h后还没有刷新呢。我们查看改动并刷新:

$ quilt diff -z -P more_p1.diff

Index: prj/src/drv/drv2.h

===================================================================

— prj.orig/src/drv/drv2.h 2008-03-02 14:19:35.000000000 +0800

+++ prj/src/drv/drv2.h 2008-03-02 14:31:28.000000000 +0800

@@ -1,7 +1,7 @@

#ifndef DRV2_H

#define DRV2_H

 

-#include “def2.h”

+#include “def1.h”

 

#endif

 

Warning: more recent patches modify files in patch more_p1.diff

$ quilt refresh more_p1.diff

More recent patches modify files in patch more_p1.diff. Enforce refresh with -f.

$ quilt refresh -f more_p1.diff

Refreshed patch more_p1.diff

quilt会抱怨更新的补丁改动了补丁more_p1.diff的文件。这是在说more_p2.diff改动了applet1.h。我们知道这和我们要刷新的drv2.h没关系,所以能够用-f參数强制刷新。

2.5 管理补丁

series命令能够查看series文件里的补丁:

$ quilt series

prj.diff

drv_p1.diff

more_p1.diff

more_p2.diff

“quilt patches 文件名称”显示改动了指定文件的全部补丁,比如:

$ quilt patches drv/drv2.h

drv_p1.diff

more_p1.diff

“quilt annotate 文件名称”显示指定文件的改动情况,它会指出哪个补丁改动了哪一行。比如:

$ quilt annotate drv/drv2.h

1 #ifndef DRV2_H

1 #define DRV2_H

 

2 #include “def1.h”

#endif

1 drv_p1.diff

2 more_p1.diff

我们能够使用push和pop命令应用补丁或撤销补丁,比如:

$ quilt pop -a

Removing patch more_p2.diff

Restoring src/app/app1.c

Restoring src/app/app2.c

Restoring src/app/app2.h

Restoring src/app/app1.h

Restoring src/applet/applet1.h

 

Removing patch more_p1.diff

Restoring src/drv/drv2.h

Removing src/applet/applet1.h

Removing src/applet/applet1.c

 

Removing patch drv_p1.diff

Restoring src/drv/drv2.h

 

Removing patch prj.diff

Restoring src/sys/sys1.c

Restoring src/sys/sys1.h

Restoring src/drv/drv1.h

Removing src/usr/usr1.c

Removing src/usr/usr1.h

No patches applied

$ quilt top

No patches applied

$ quilt next

prj.diff

$ quilt previous

No patches applied

“quilt pop -a”撤销全部补丁。top命令显示栈顶命令,即当前应用的最新的补丁。next命令显示下一个能够应用的补丁。previous显示上一条应用过的补丁。”push 补丁A”将从上到下依次应用全部早于补丁A的补丁,最后应用补丁A。比如:

$ quilt push more_p1.diff

Applying patch prj.diff

patching file src/drv/drv1.h

patching file src/sys/sys1.c

patching file src/sys/sys1.h

patching file src/usr/usr1.c

patching file src/usr/usr1.h

Applying patch drv_p1.diff

patching file src/drv/drv2.h

Applying patch more_p1.diff

patching file src/applet/applet1.c

patching file src/applet/applet1.h

patching file src/drv/drv2.h

Now at patch more_p1.diff

$ quilt top

more_p1.diff

$ quilt next

more_p2.diff

$ quilt previous

drv_p1.diff

“quilt push -a”应用全部补丁:

$ quilt push -a

Applying patch more_p2.diff

patching file src/app/app1.c

patching file src/app/app1.h

patching file src/app/app2.c

patching file src/app/app2.h

patching file src/applet/applet1.h

Now at patch more_p2.diff

“quilt graph -all”能够为栈顶补丁的依赖关系生成dot文件。Graphviz的dot能够依据dot文件产生图片,比如:

$ quilt graph –all > ../../more_p2.dot

$ cd ../..; dot -Tpng more_p2.dot -o more_p2.png

<span>Linux之旅(1): diff, patch和quilt (下)</span>

2.6 公布补丁

仅仅要将patches文件夹打包公布就能够了。比如:

$ cd prj; tar cvjf prj-0.1-patches.tar.bz2 patches; mv prj-0.1-patches.tar.bz2 ../..

用户先下载、解压补丁包相应的源码树:

$ cd ../..; mkdir user; cd user; tar xvjf ../old-prj.tar.bz2; mv old-prj/ prj

然后下载、解压补丁:

$ cd ../..; tar xvjf prj-0.1-patches.tar.bz2; cd user/prj

最后把补丁文件夹链接到源码树的patches文件夹,然后应用全部补丁:

$ ln -sfn ../../patches/ patches

$ quilt push -a

Applying patch prj.diff

patching file src/drv/drv1.h

patching file src/sys/sys1.c

patching file src/sys/sys1.h

patching file src/usr/usr1.c

patching file src/usr/usr1.h Applying patch drv_p1.diff

patching file src/drv/drv2.h

Applying patch more_p1.diff

patching file src/applet/applet1.c

patching file src/applet/applet1.h

patching file src/drv/drv2.h

Applying patch more_p2.diff

patching file src/app/app1.c

patching file src/app/app1.h

patching file src/app/app2.c

patching file src/app/app2.h

patching file src/applet/applet1.h

Now at patch more_p2.diff

3 结束语

在上面的流程攻略中,我们演示了19个quilt命令:add, annotate, applied, diff, edit, files, graph, import, new, next, patches, pop, previous, push, refresh, remove, series, top, unapplied。

本次Linux之旅到此结束,欢迎您再次參加Linux之旅,一起探索浩瀚的Linux世界。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119229.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • vbs代码未结束的字符串常量[通俗易懂]

    vbs代码未结束的字符串常量问题描述:  执行vbs脚本时提示“vbs代码未结束的字符串常量”原因:  vba的BUG,在连接字符串的最后一个字符是单个或多个“行”字(我这里是把“行”字删除就不报错)或者其他原因,会出现未结束的字符串常量解决:  这里使用的是notepadd++在编码或者格式里面将文件编码改成“转为ANSI编码”解决问题…

    2022年4月9日
    247
  • er图和uml图_数据库表结构er图

    er图和uml图_数据库表结构er图ER图:实体-联系图(Entity-RelationDiagram)用来建立数据模型,在数据库系统概论中属于概念设计阶段,ER图提供了表示实体(即数据对象)、属性和联系的方法,用来描述现实世界的概念模型构成E-R图的基本要素是实体、属性和联系,其表示方法为:实体型:用矩形表示,矩形框内写明实体名;属性:用椭圆形或圆角矩形表示,并用无向边将其与相应的实体连接起来;多值属性由双线连接;主属性名称下加…

    2022年9月17日
    0
  • datetime.date()_datenum函数使用

    datetime.date()_datenum函数使用比如在windowscmd命令行窗口执行date命令后这个环境变量的值为当前日期:2014-03-01 星期六那么如下的各个操作的意义如下:%date:~0,4% 表示从左向右指针向右偏0位,然后从指针偏移到的位置开始提取4位字符,结果是2014(年的值)%date:~5,2% 表示指针从左向右偏移5位,然后从偏移处开始提取2位字符,结果是03(月的值)%date:~8,

    2022年9月20日
    0
  • iostat命令详解参数_iostat命令的dm

    iostat命令详解参数_iostat命令的dmiostat命令详解iostat用于输出CPU和磁盘输入输出、分区、网络文件系统NFS相关的统计信息。iostat命令用于监控系统设备的输入/输出情况,并生成报告,以便根据统计报告修改系统配置,获取更优的性能。命令格式:iostat[-c][-d][-N][-n][-h][-k|-m][-t][-V][-x][-z][device

    2022年10月6日
    0
  • 矩阵特征值和特征向量怎么求_矩阵的特征值例题详解

    矩阵特征值和特征向量怎么求_矩阵的特征值例题详解设A是n阶方阵,如果存在数m和非零n维列向量 x,使得Ax=mx成立,则称m是A的一个特征值(characteristicvalue)或本征值(eigenvalue)。非零

    2022年8月5日
    3
  • Java + Ajax跨域解决方案整理

    Java + Ajax跨域解决方案整理为什么会跨域呢?简单来说就是前端页面与后台服务没有部署在同一个服务器上。产生跨域的情况有:1.域名不同,端口也不同;2.域名相同但是端口不同;3.域名不同,端口相同。解决方案:一、JSONP方式1.只支持get方法,不支持postfang方法;使用时需修改前端和后端代码,用起来也不太方便,本文不推荐使用。二、使用springMVC架构的,使用版本4.2以上…

    2022年8月24日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号