Chinaunix首页 | 论坛 | 博客
  • 博客访问: 29335449
  • 博文数量: 2065
  • 博客积分: 10377
  • 博客等级: 上将
  • 技术积分: 21525
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-04 17:50
文章分类

全部博文(2065)

文章存档

2012年(2)

2011年(19)

2010年(1160)

2009年(969)

2008年(153)

分类: LINUX

2010-07-17 10:20:48

内容转载自:
我们自己的项目可以用cvs或svn管理全部代码。但有时我们要使用其他开发者维护的项目。我们需要修改一些文件,但又不能直接向版本管理工具提交代码。 自己用版本管理工具重建整个项目是不合适的,因为大多数代码都是别人维护的,例如Linux内核。我们只是想管理好自己的补丁。这时可以使用quilt。
一、基本概念
是一个帮助我们管理补丁的程序。quilt的命令格式类似于cvs:

quilt 子命令 [参数] 0.46版的quilt有29个子命令。

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

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

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

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。




阅读(3668) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~