How to create patch for a new file, and patch it back to the original directory? - diff

Suppose I have a directory dir1, and have files f1.c and f2.c in it.
I copy all to directory dir2, modify both f1 and f2, and add a new file f3.c.
Then I do the diff to create patch:
diff -ruN dir1/ dir2/ > diff.patch
Now I want to apply the patch back to dir1. However the changes in f1 and f2 are successfully patched. but I don't get a new file f3.c in dir1:
[/local/home/tmp]$ patch -p0 < diff.patch
patching file dir1/f1.c
Hunk #1 succeeded at 1 with fuzz 2.
patching file dir1/f2.c
The next patch would create the file dir2/f3.c,
which already exists! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored
How to apply the patch, so that I can add f3.c in dir1 too?

OK, i've figured out, that you must cd into dir1, and use the -p1 parameter:
cd dir1
patch -p1 < ../diff.patch

Related

How to assign patch to specified git source?

In my foo_git.bb:
SRC_URI = "git://github.com/foo/foo.git;branch=main;protocol=https;name=${BPN};destsuffix=git \
git://github.com/foo2/foo2;branch=main;protocol=https;name=${FOO2};destsuffix=${FOO2} \
file://0001-Modify-A_value.patch\
"
I want my patch to apply to foo2 but it always applied to foo. ( patch failed )
I found patchdir appended after the patch can work.
ex:
file://0001-Modify-A_value.patch;patchdir=${WORKDIR}/${FOO2_path}
From the OE manual
Patch files will be copied to ${S}/patches and then applied to source from within the source directory, ${S}. so for your use case to work your patch filenames should include their base repo name.
For example let’s say 0001-Modify-A_value.patch is as follows:
diff --git a/my.txt b/my.txt
index fa5cb9a..59369cc 100644
--- a/my.txt
+++ b/my.txt
## -1 +1 ##
-I am foo who lives in bar
+I am bar who lives in foo
To make it apply to foo2 you must modify it as follows:
--- foo2/my.txt
+++ foo2/my.txt
## -1 +1 ##
-I am foo who lives in bar
+I am bar who lives in foo
Bitbake uses Quilt for patching so for errors and so on look at its manual.
Another handy tool by bitbake to help you further is the devtool which is designed to handle tasks like updating a recipe or patching it.

How to update modules.conf for SELINUX in BUILDROOT?

looking to disable some SELinux modules (set to off) and create others in modules.conf. I don't see an obvious way of updating modules.conf as I tried adding my changes as a modules.conf patch but it failed given that the modules.conf file gets built and is not just downloaded by BR so it is not available for patching like other things under the refpolicy directory:
Build window output:
refpolicy 2.20190609 PatchingApplying 0001-refpolicy-update-modules-conf.patch using patch:
can't find file to patch at input line 3
I did see in the log that there is a support/sedoctool.py that autogenerates the policy/modules.conf file so that the file is NOT patchable like most other things in the ref policy.
The relevant section of the buildroot/output/build/refpolicy-2.20190609/Makefile:
# policy building support tools
support := support
genxml := $(PYTHON) $(support)/segenxml.py
gendoc := $(PYTHON) $(support)/sedoctool.py
<...snip...>
########################################
#
# Create config files
#
conf: $(mod_conf) $(booleans) generate$(booleans) $(mod_conf): conf.intermediate.INTERMEDIATE: conf.intermediate
conf.intermediate: $(polxml)
#echo "Updating $(booleans) and $(mod_conf)"
$(verbose) $(gendoc) -b $(booleans) -m $(mod_conf) -x $(polxml)
Part of the hsmlinux build.log showing the sedoctool.py (gendoc) being run:
Updating policy/booleans.conf and policy/modules.conf
.../build-buildroot-sawshark/buildroot/output/host/usr/bin/python3 support/sedoctool.py -b policy/booleans.conf -m policy/modules.conf -x doc/policy.xml
I'm sure there is a standard way of doing this, just doesn't seem to be documented anywhere I can find.
Thanks.
Turns out that the sedoctool.py script is reading the doc/policy.xml. Looking at sedoctool.py:
#modules enabled and disabled values
MOD_BASE = "base"
MOD_ENABLED = "module"
MOD_DISABLED = "off"
<...snip...>
def gen_module_conf(doc, file_name, namevalue_list):
"""
Generates the module configuration file using the XML provided and the
previous module configuration.
"""
# If file exists, preserve settings and modify if needed.
# Otherwise, create it.
<...snip...>
mod_name = node.getAttribute("name")
mod_layer = node.parentNode.getAttribute("name")
<...snip...>
if mod_name and mod_layer:
file_name.write("# Layer: %s\n# Module: %s\n" % (mod_layer,mod_name))
if required:
file_name.write("# Required in base\n")
file_name.write("#\n")
if [mod_name, MOD_DISABLED] in namevalue_list:
file_name.write("%s = %s\n\n" % (mod_name, MOD_DISABLED))
# If the module is set as enabled.
elif [mod_name, MOD_ENABLED] in namevalue_list:
file_name.write("%s = %s\n\n" % (mod_name, MOD_ENABLED))
# If the module is set as base.
elif [mod_name, MOD_BASE] in namevalue_list:
file_name.write("%s = %s\n\n" % (mod_name, MOD_BASE))
So sedoctool.py has the nice feature of: "# If file exists, preserve settings and modify if needed." and modules.conf can just be added whole here via a complete file patch and the modules that are not desired set as "off" : refpolicy-2.20190609/policy/modules.conf and the script will update as needed based on desired policy.
One more detail is that in the next stage of the refpolicy Makefile (Building) the modules.conf with the updates is deleted in the beginning which kind of clashes with the ability of sedoctool to preserve the patched version of modules.conf...so patched the removal in the Building stage of the Makefile.
[7m>>> refpolicy 2.20190609 Building^[
<...snip...>
rm -f policy/modules.conf
The Makefile in refpolicy-2.20190609 has this line that I patched out because we are patching in our own modules.conf:
bare: clean
<...snip...>
$(verbose) rm -f $(mod_conf)
That patch looks like:
--- BUILDROOT/Makefile 2020-08-17 13:25:06.963804709 -0400
+++ FIX/Makefile 2020-08-17 19:25:29.540607763 -0400
## -636,7 +636,6 ##
$(verbose) rm -f $(modxml)
$(verbose) rm -f $(tunxml)
$(verbose) rm -f $(boolxml)
- $(verbose) rm -f $(mod_conf)
$(verbose) rm -f $(booleans)
$(verbose) rm -fR $(htmldir)
$(verbose) rm -f $(tags)
BTW,
Creating a patch with a complete new file in pp1:q!:
diff -crB --new-file pp0 pp1 > pp0.patch

Weird behavior of patch when filename is changed

Recently, I am learning diff and patch. I created two files, file a with content abc and file b with content def. Then I used diff -u a b > p and patch < p, it behaved correctly, as shown in the following:
[joe#joe-pc c]$ ls
a b
[joe#joe-pc c]$ more a
abc
[joe#joe-pc c]$ more b
def
[joe#joe-pc c]$ diff -u a b > p
[joe#joe-pc c]$ more p
--- a 2018-12-20 22:56:33.865661540 +0800
+++ b 2018-12-20 22:54:15.241516269 +0800
## -1 +1 ##
-abc
+def
[joe#joe-pc c]$ patch < p
patching file a
[joe#joe-pc c]$ more a
def
[joe#joe-pc c]$ more b
def
[joe#joe-pc c]$ ls
a b p
[joe#joe-pc c]$
But if I changed the filename from a to ab, something strange happened. The patch < p command told me that
patching file b
Reversed (or previously applied) patch detected! Assume -R? [n]
[joe#joe-pc c]$ ls
ab b
[joe#joe-pc c]$ more ab
abc
[joe#joe-pc c]$ more b
def
[joe#joe-pc c]$ diff -u ab b > p
[joe#joe-pc c]$ more p
--- ab 2018-12-20 22:57:29.767980973 +0800
+++ b 2018-12-20 22:54:15.241516269 +0800
## -1 +1 ##
-abc
+def
[joe#joe-pc c]$ patch < p
patching file b
Reversed (or previously applied) patch detected! Assume -R? [n] ^C
[joe#joe-pc c]$
The file contents are the same, but why in the second situation the patch cannot find the right file ab to be patched?
The above operations were performed in a Linux machine with bash shell.
Thanks in advance.
It's a feature of GNU patch. As you haven't specific the file to patch, it has to be deduced from the input somehow. Basically, if you don't specify paths (only base names), it assumes that it has to patch the file with a shorter name, unless --posix command line argument is passed or POSIXLY_CORRECT environment variable is set:
patch --posix <p
# or
POSIXLY_CORRECT=1 patch <p
In your case, between a and b the first one is chosen correctly, but for ab and b the second one is chosen as patch target (as patching file b line suggests), but patching fails, hence the error.
You can also fix this behavior by either specifying patch target explicitly:
patch ab <p
Digging into docs
GNU patch uses the following logic (see patch's manual, "10.6 Multiple Patches in a File" section):
First, patch takes an ordered list of candidate file names as follows:
If the header is that of a context diff, patch takes the old and new file names in the header. ...
...
Then patch selects a file name from the candidate list as follows:
If some of the named files exist, patch selects the first name if conforming to POSIX, and the best name otherwise.
For "uniform context format" the "old" file is mentioned after --- (a or ab in your case), and the "new" file is mentioned after +++ (b in your case).
If both files exist and patch is not configured to be "confirming to POSIX" (e.g. by setting POSIXLY_CORRECT environment variable or --posix command line argument, see "10.12 patch and the POSIX Standard" section of the manual), then patch will choose "the best" name out of two. "Name" here includes full path obtain from the patch file (doesn't matter in your case). Details are specific later:
To determine the best of a nonempty list of file names, patch first takes all the names with the fewest path name components; of those, it then takes all the names with the shortest basename; of those, it then takes all the shortest names; finally, it takes the first remaining name.
"Name component" here is basically a folder/file name (e.g. /foo/bar/baz has three of them), "basename" is just the name of the file (baz).
So, if names are a (old) and b (new) and both files exist, there is no "best name", so the first one is patched.
But if names are ab (old) and b (new) and both files exist, then b is "better", so the tool tries to patch it and fails.
I have no idea why this behavior was made the default.

Patch semantics

I've made a patch by using diff:
diff -u /home/user/onderzoeksstage/omf/Rakefile /home/user/onderzoeksstage/Rakefile > rakefile2.patch
I've placed this rakefile2.patch in another directory: /home/user/onderzoeksstage/omf/confine/patches.
Now, I was under the assumption that I could go to that directory where all my patches are collected, call patch < rakefile2.patch and patch would known where to find the file to patch (the original file /home/user/onderzoeksstage/omf/Rakefile) by reading out the rakefile2.patch header.
But when doing that, patch says that it does not find the file to patch:
[user#localhost patches]$ patch < rakefile2.patch
can't find file to patch at input line 3
Perhaps you should have used the -p or --strip option?
The text leading up to this was:
--------------------------
|--- /home/user/onderzoeksstage/omf/Rakefile 2013-02-12 14:11:49.809792527 +0100
|+++ /home/user/onderzoeksstage/Rakefile 2013-02-12 12:17:50.314831492 +0100
--------------------------
File to patch: ...
...
So my assumption was obviously wrong, but so how does patch work?
When going to /home/user/onderzoeksstage/omf/ and calling patch < rakefile2.patch does work. Does patch only look at the header for the filename at the end of the path and not take in account the directory? And so what I try to accomplish will never work?
Why is this; is this because that way a patch could be applied to any file called Rakefile (e.g. in my case) and so make it a more "generic" patch?
Thanks
Does patch only look at the header for the filename at the end of the
path and not take in account the directory?
That's what it does by default. See the description of -p option in man patch. Looks like -p0 is what you want here.

recursive diff to create a patch and apply patch recursively

I'm running into trouble using patch. I have 2 folders with many subfolders and files.
diff -ur backup/www/ www/ > sync.patch
Next, I'm trying to apply the patch.
patch < sync.patch
It asks me File to patch: as you can see.
|diff -ur ./backup/www/members/categorize.php ./www/members/categorize.php
|--- ./backup/www/members/categorize.php 2012-12-13 15:19:41.000000000 -0500
|+++ ./www/members/categorize.php 2012-10-15 23:32:12.000000000 -0400
--------------------------
File to patch:
The file ./www/members/categorize.php exists.
You probably need to investigate the -p flag for patch, which controls the way that directory prefixes are treated. See the man page.