曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4642|回复: 0
打印 上一主题 下一主题

quilt

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2015-9-6 22:18:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我们自己的项目可以用 cvs 或 svn 管理全部代码。但有时我们要使用其他开发者维护的项目。我们需要修改一些文件,但又不能直接向版本管理工具提交代码。自己用版本管理工具重建整个项目是不合适的,因为大多数代码都是别人维护的,例如 Linux 内核。我们只是想管理好自己的补丁。这时可以使用 quilt。

基本概念

quilt 是一个帮助我们管理补丁的程序。quilt 的命令格式类似于cvs:
quilt 子命令 [参数]


0.46 版的 quilt 有29个子命令。

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

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



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

我们在源代码树中作任何修改前,必须用 "quilt add" 命令将要修改的文件与一个补丁联系起来。在完成修改后,用 "quilt refresh" 命令将修改保存到已联系的补丁。下面我们通过一篇流程攻略来认识一下 quilt 的命令。

导入补丁

我们把 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)


执行 import 命令后, 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


修改文件

我们必须将对源代码树所作的任何改动都和一个补丁联系起来。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" 显示所有的差异,不管是否保存过。

再做几个补丁

在增加文件前,我们要先将准备增加的文件与补丁联系起来。我们新建一个补丁,然后新增两个文件 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 参数强制刷新。

管理补丁

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



发布补丁
只要将 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


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

转自:http://blog.csdn.net/fmddlmyy/article/details/2140097

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

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

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-7 01:11 , Processed in 0.065540 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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