Linux Tour (1): diff, Patch and quilt (bottom) 2 quilt
Our own projects can manage all the code with CVS or SVN. But sometimes we use projects that other developers maintain. We need to change some files, but we cannot submit the code directly to the version number management tool. It is inappropriate to rebuild the entire project with version number management tools, because most of the code is maintained by others, such as the Linux kernel. We just want to manage our own patches. You can use quilt at this time.
2.1 Basic Concepts
Quilt is a program that helps us manage patches. The quilt command format is similar to CVS:
Quilt Sub-command [number of references]
Version 0.46 of quilt has 29 subcommands.
The key to mastering quilt is to understand the process of using quilt. When using quilt, we will work in a full source tree. Just for us to use the Quilt command in the source tree, quilt will create two special folders in the root folder of the source tree: patches and. PC. Quilt Save All the patches it manages in the Patches folder. Quilt use. PC folder to save your own internal working status, users do not need to know this folder.
The patches/series file records the patches currently managed by quilt. Patches are arranged in ascending order, and the patches are added earlier. Quilt uses the concept of stacks to manage patches of application.
Before we apply patch A, we must first apply a patch that is earlier than patch a. Therefore, patches in patches/series are always applied from top to bottom. For example, patches 1 through patch 5 are patches that have already been applied. We can think of the applied patches as a downward-growing stack, and the top of the stack is the latest patches that have been applied. Applying patches is to put patches into the stack, and undo patches is to put patches out of the stack.
Before we make any changes in the source tree, we must use the "quilt Add" command to link the files that will be changed to a patch. After the changes have been made, use the "quilt Refresh" command to save the changes to the patch that has been contacted. Below we have a process guide to understand the quilt command.
2.2 Importing Patches
We think of old-prj.tar.bz2 as the Linux kernel, and when we unzip it, we go to the root folder of the code tree:
$ mkdir qtest; CD qtest; Tar xvjf. /old-prj.tar.bz2; MV Old-prj PRJ; CD PRJ
We usually have to make an official patch before we change the code. In quilt, the ability to import patches with the import command:
$ Quilt Import: /.. /prj.diff
Importing Patch: /.. /prj.diff (stored as Prj.diff)
After running the Improt command, the PRJ folder will have one more subfolder called patches:
$ find patches/-type F
Patches/prj.diff
Patches/series
Quilt in this folder to store all the patches and the series files described earlier. Most commands in quilt can be executed in a random subfolder of the code tree, not necessarily from the root folder. We are able to query the currently applied patches with the applied command.
$ quilt Applied
No Patches Applied
No patches are applied at this moment. Unapplied Command query currently not applied patches, top command query stack top patch, that is the latest patch applied:
$ Quilt Unapplied
Prj.diff
$ quilt Top
No Patches Applied
We can apply patches using the push command, such as:
$ 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
The "-a" parameter of push indicates that all patches are applied. After using the push command, the PRJ folder will have one more hidden subfolder called. PC. Quilt Use this folder to save the internal state, the user does not need to know this folder. After applying the patches, we use the applied, unapplied, and top commands to view:
$ quilt Applied
Prj.diff
$ Quilt Unapplied
File series fully applied, ends at Patch Prj.diff
$ quilt Top
Prj.diff
2.3 Changing files
We must associate any modification to the source tree with a patch. The add command links the current state of the file to the patch. The format of the Add command is:
Quilt Add [-P patch name] file name
Assuming the patch name is not specified, the file is associated with the top-of-stack patch. For now, our top-of-the-stack patches are official patches. We do not want to change this patch to create a new patch with the new command:
$ 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
Then use the Add command to add a ready-to-change file to the stack top patch:
$ CD src/drv; Quilt Add Drv2.h
File Src/drv/drv2.h added to patch Drv_p1.diff
The add command saves the current snapshot of the specified file for the specified patch, and when we run the Refresh command, quilt checks the file for changes and saves the difference to the specified patch. Use "Quilt diff-z [-P patch name] [file name]" To view the current modification of the specified patch specified file. Omitting the-P-parameter means viewing changes to the current patch, omitting the file name to see all changes. After we modify Drv2.h, run the diff command:
$ 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
Just because the file has been contacted with the patch we want to save the changes to, we can modify the file multiple times. Use the quilt files [patch name] command to view the files associated with the specified patch. Use "Quilt Files-val" to see all the files that are contacted by the patch. The "-V" parameter indicates a more friendly display, and the "-a" parameter indicates that all patches are displayed, and the "-L" parameter shows the patch name. Like what:
$ 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 [patch name]" Refresh the patch, the file changes to the specified patch saved to the patch. Omitting the file name indicates the refresh stack top patch. After we refresh, check the patch file:
$ 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
The "Quilt diff-z" command does not show the differences that have been saved. "Quilt diff" shows all the differences, whether or not they were saved.
2.4 Make a few more patches
Before adding a file, we will first link the files that are being added to the patches. We created a new patch and then added two files Src/applet/applet1.h and 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
Look at the files we added:
$ quilt Files
Src/applet/applet.1
Src/applet/applet.c
Oops, the file name was wrong. We were able to remove the associated file from the patch using the "Remove" command:
$ 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
OK, now you are able to create a new file:
$ 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
After the patch is refreshed, we can change the file drv2.h. Be sure to associate the file with the patch where you want to save the changes before you change it:
$ 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
We'll create a new patch and then delete two files. You must also associate a file before deleting it:
$ 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
We'll change 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" launches the editor itself after calling "quilt add". Refresh the patch with the Refresh command.
Yes, the front for more_p1.diff changes Drv2.h has not been refreshed yet. We review the changes and refresh:
$ 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 will complain that the updated patches have changed the patch more_p1.diff files. This is saying that More_p2.diff changed the Applet1.h. We know this is okay with the drv2.h we're going to refresh, so we can force the flush with the-f parameter.
2.5 Managing Patches
The series command can view patches in a series file:
$ Quilt Series
Prj.diff
Drv_p1.diff
More_p1.diff
More_p2.diff
The "Quilt patches file name" Displays all patches that have changed the specified file, such as:
$ Quilt Patches Drv/drv2.h
Drv_p1.diff
More_p1.diff
The quilt annotate file name displays changes to the specified file, indicating which patch has changed which line. Like what:
$ 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
We can apply patches or undo patches using push and pop commands, such as:
$ 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" undo all patches. The top command displays the top command, which is the latest patch currently applied. The next command shows the next patch that can be applied. Previous shows the last patch applied. "Push patch A" will apply a patch from top to bottom that is earlier than patch a, and finally apply patch A. Like what:
$ 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" applies all patches:
$ 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" can generate a dot file for the dependencies of the stack top patch. Graphviz Dot can produce images based on dot files, such as:
$ quilt Graph--all >. /.. /more_p2.dot
$ CD. /..; Dot-tpng More_p2.dot-o More_p2.png
2.6 Release Patches
Simply package the patches folder to advertise it. Like what:
$ CD prj; Tar cvjf prj-0.1-patches.tar.bz2 patches; MV Prj-0.1-patches.tar.bz2. /..
The user first downloads, unzip the patch package corresponding source tree:
$ CD. /..; mkdir user; CD user; Tar xvjf. /old-prj.tar.bz2; MV Old-prj/prj
Then download and unzip the patch:
$ CD. /..; Tar xvjf prj-0.1-patches.tar.bz2; CD USER/PRJ
Finally, link the patch folder to the patches folder of the source tree and apply all the 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.happlying 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.DIFF3 closing
In the above process guide, we demonstrated 19 quilt commands: Add, Annotate, applied, diff, Edit, files, graph, import, new, Next, patches, pop, previous, pus h, refresh, remove, series, top, unapplied.
This Linux tour is over and you are welcome to join the Linux tour to explore the vast world of Linux.
Linux Tour (1): diff, Patch and quilt (bottom)