Skip to content

Instantly share code, notes, and snippets.

@vheidari
Last active June 4, 2024 15:16
Show Gist options
  • Save vheidari/9f95c3b588de8ad9ef12608fa057e7fc to your computer and use it in GitHub Desktop.
Save vheidari/9f95c3b588de8ad9ef12608fa057e7fc to your computer and use it in GitHub Desktop.
In this tutorial I try to explain how patch utility could help us during development , fixing a bug or etc

What is patch and how we could take its advantage to our code ?

Unix-based systems carry a lot of useful tool. actually they made them to help us improve our productivity. patch is one of useful tool that help programer update a existing codebase.

Note

A patch is a file that contains the differences between two sets of code or files. It is used to update an existing codebase by applying changes without rewriting the entire code. The patch utility is a useful tool for programmers to apply updates to codebases.

When we work on a existing codebase we might update and do some change to it to fix a bug then we can use patch utility to add update to codebase. I try to explain its advantage with an example like this :

An example

suppose I recently I develop a library in C++. inside my library i have a file like object.h. and inside this file I already defined a classe like this :

class Object {
    public:
     
     Object() {}
    ~Object() {}

    void setfObject(int _f) { fObject = _f;}
    void setbObject(int _b) { bObject = _b;}
    int getfObject() {return fObject;}
    int getbObject() {return bObject;}
    private :
    int fObject;
    int bObject;
}

Now, suppose I'm working on another library that requires a class similar to Object but with a different name, GlobalObject. What should I do?

1.) I should declare a new GlobalObject class inside newLib with the same properties as the Object class (meaning I should rewrite the existing class with a new name).

2.) Alternatively, I could use the existing Object class, make the necessary changes, create a patch for it, and then generate a new class with the new name GlobalObject through the patch.

personally I prefer to choose item 2. but how ? we will learn how to make patch through git diff in the next section.

how to create patch through git diff

indeed to make a .pach file and use it we could use git and diff. as you might familiar with git and diff I try to make a patch file for class Object and ready it to be GlobalObject class whiout implement whole GlobalObject class.

let look at this sample:

1.) I create a project and named it patchDemo. also inside it I a create 2 directories and named them libA and libB :

if you want do with me you can use this bash script to create directory structure.

#!/bin/sh

wDir=patchDemo
libADir=libA
libBDir=libB
mkdir $wDir && cd $wDir && mkdir $LibADir $libBDir 
 

2.) inside libA directory I created Object.h file then added this simple class within it.

class Object {
    public:
     
     Object() {}
    ~Object() {}

    void setfObject(int _f) { fObject = _f;}
    void setbObject(int _b) { bObject = _b;}
    int getfObject() {return fObject;}
    int getbObject() {return bObject;}
    private :
    int fObject;
    int bObject;
}

3.) after save save our class our libA is ready. i just use git to add it and commit a message to libA :

you can also do it through below command in libA directroy.

git init && git add . && git commit -m "init libA"

4.) now I want create libB and my class GlobalObject.h as we know. GlobalObject class is really similar to Object class for that reasone I try to use libA/Object.h to create libB/GlobalObject.h.

5.) I switch to libB directory and try to make a clone from libA through git clone.

inside libB directroy you can use this command :

git clone ../libA

6.) last command will create a clone from libA inside libB directory. now we can edit Object class and add new feature to it to make our GlobalObject.

you can with me :

# inside path/patchDemo/libB/libA
vim ./Object.h

7.) I edit Object class and replace it with this snippet code for GlobalObject class :

class GlobalObject {                                                                                                              
     public:
  
      GlobalObject() {}
     ~GlobalObject() {}
  
     void setfGlobalObject(int _f) { fObject = _f;}
     void getfGlobalObject() {return fObject;}
     void setbGlobalObjectName(std::string goName) { bGlobalObjectName = goName}
     std::string getbGlobalObjectName() { return bGlobalObjectName; }
  
     private :
     int fGlobalObject;
     std::string bGlobalObjectName;
}

as you can see properties and methods are similar to Object class. when I done with it we are ready to create patch from it. before we create our patch file. I use git to add changes to libB for this purpose you can use this below command :

git add . && git commit -m "init libB"

now if check git log I should see something like this :

commit 02c3b3f7d16c6384872efeb0f6f631af7ac09546 (HEAD -> master)
Author: vheidari <v**********i@gmail.com>
Date:   Fri May 31 19:36:01 2024 -0400

    init libB

commit e88f74b1d9646122487fe450f5c1fd75f9c126c3  (origin/master, origin/HEAD)
Author: vheidari <v**********i@gmail.com>
Date:   Fri May 31 19:30:42 2024 -0400

    init libA

as you can see we did change and update project and ready it for libB. 8.) now we could create patch file through git diff command you can also use this below command :

# This command run under path/patchDemo/libB/libA
git diff e88f74b1d9646122487fe450f5c1fd75f9c126c3 > ../../libB.patch

9.) above command will create a patch file through commait id. if I do change my directory to project root directory patchDemo with this command cd ../../ we could find libB.patch.

now we have patch file. but how we could use it. we will learn about it in the next section.

if you are curious about this file and you want see what git diff made you can open it within vim ./libB.patch :

diff --git a/Object.h b/Object.h
index 8a6b5e5..19d4ac4 100644
--- a/Object.h
+++ b/Object.h
@@ -1,14 +1,16 @@
-class Object {
-    public:
-     
-     Object() {}
-    ~Object() {}
+class GlobalObject {                                                                                                              
+     public:
+  
+      GlobalObject() {}
+     ~GlobalObject() {}
+  
+     void setfGlobalObject(int _f) { fObject = _f;}
+     void getfGlobalObject() {return fObject;}
+     void setbGlobalObjectName(std::string goName) { bGlobalObjectName = goName}
+     std::string getbGlobalObjectName() { return bGlobalObjectName; }
+  
+     private :
+     int fGlobalObject;
+     std::string bGlobalObjectName;
+};
 
-    void setfObject(int _f) { fObject = _f;}
-    void setbObject(int _b) { bObject = _b;}
-    int  getfObject() {return fObject;}
-    int  getbObject() {return bObject;}
-    private :
-    int fObject;
-    int bObject;
-}

how to use a patch file inside our project

Ok we made libB.patch file. now I want use it to create my libB from libA but how ?

before we do anything I will remove directory libB then I try make GlobalObject.h file from Object.h with patch and libB.patch.

in patchDemo directory I remove libB and with this command :

rm -rf ./libB

Now we should create a new libB directroy then clone libA to it then patch Object.h with patch tool and libB.patch.

below bash script show steps that we should do to create GlobalObject.h from Object.h.

#!bin/sh

# crete libB directory
mkdir libB  

# change current directroy to libB
cd libB  

# crete a clone from libA and put it in libB directroy
git clone ../libA  

# switch to libA 
cd ./libA

# copy libB.patch from root (patchDemo) to current directroy (path/patchDemo/libB/libA) 
cp ../../libB.patch ./libB.patch

# patch Object.h through libB.patch
patch -p1 ./Objet.h ./libB.patch

# rename Object.h and move it from this directory to path/patchDemo/libB directroy
mv ./Object.h ../GlobalObject.h

# back to libB directory from pathDemo/libB/libA 
cd .. 

# remove libA directory 
rm -rf ./libA

Good to read :

- https://docs.gitlab.com/omnibus/development/creating-patches.html
- Project to review :
    - https://github.com/linusg/libjs-bindings/blob/master/patches/jsb.patch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment