# 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 : ```c++ 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. ```bash #!/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. ```c++ 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. ```bash 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 : ```bash 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 : ```bash # inside path/patchDemo/libB/libA vim ./Object.h ``` 7.) I edit `Object` class and replace it with this snippet code for `GlobalObject` class : ```c++ 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 : ```bash git add . && git commit -m "init libB" ``` now if check `git log` I should see something like this : ```bash commit 02c3b3f7d16c6384872efeb0f6f631af7ac09546 (HEAD -> master) Author: vheidari Date: Fri May 31 19:36:01 2024 -0400 init libB commit e88f74b1d9646122487fe450f5c1fd75f9c126c3 (origin/master, origin/HEAD) Author: vheidari 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 : ```bash # 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 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 : ```bash 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`. ```bash #!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