Solved Patching from a heredoc

I'm triying to create an inline patchfile using heredoc and having some difficulty figuring out how to do this.

According to patch()

patch will take a patch file containing any of the four forms of differ-
ence listing produced by the diff(1) program and apply those differences
to an original file, producing a patched version. If patchfile is omit-
ted, or is a hyphen, the patch will be read from the standard input.

So how do I pipe a heredoc into patch?


Bash:
cat <<EOF

some patch stuff

EOF

patch abc -o abc -i -


Am I close?
 
The file being patched is included in patch header, from patch(1):
Code:
     For a unified diff,
     the “old” file is specified in the line beginning with "---" and the
     “new” file is specified in the line beginning with "+++".

So given that you have the following diff (saved to baz.patch):
Code:
--- baz.orig    2023-08-07 10:55:11.982023000 +0200
+++ baz 2023-08-07 10:55:19.014296000 +0200
@@ -1 +1 @@
-foo
+bar
...patch will apply to file named baz:
Code:
$ echo foo > baz
$ patch < baz.patch
Hmm...  Looks like a unified diff to me...
The text leading up to this was:
--------------------------
|--- baz.orig   2023-08-07 10:55:11.982023000 +0200
|+++ baz        2023-08-07 10:55:19.014296000 +0200
--------------------------
Patching file baz using Plan A...
Hunk #1 succeeded at 1.
done
$ cat baz
bar
 
The file being patched is included in patch header, from patch(1):
Code:
     For a unified diff,
     the “old” file is specified in the line beginning with "---" and the
     “new” file is specified in the line beginning with "+++".

So given that you have the following diff (saved to baz.patch):
Code:
--- baz.orig    2023-08-07 10:55:11.982023000 +0200
+++ baz 2023-08-07 10:55:19.014296000 +0200
@@ -1 +1 @@
-foo
+bar
...patch will apply to file named baz:
The point of my post was that I ddn't want to create a patch file, baz.patch. I wanted the patch to be created by the 'heredoc' immediately preceeding the patching. I don't even if this is possible, that's why I'm asking. The manpage for patch says that the patchfile can be read from standard input, so will the second line of the patchfile consist of

Bash:
--- baz.orig
+++ -
 
The manpage for patch says that the patchfile can be read from standard input, so will the second line of the patchfile consist of
No, the file patch reads from and the file patch applies to are different unrelated things.

Still I don't understand the problem you are trying to solve with this (that famous XY problem).
 
I'll try to better explain what I want to do.

I can use this to create the require patchfile:

Bash:
cat <<EOF.

--- prereq-build.mk<--->2023-08-06 22:17:22.975025000 +0000
+++ prereq-build.mk.new>2023-08-06 22:33:12.005513000 +0000
@@ -147,6 +147,7 @@
 <----->Please install an extended getopt version that supports --long, \\
 <----->gnugetopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->getopt -o t --long test -- --test | grep '^ *--test *--', \\
+<----->/usr/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/usr/local/opt/gnu-getopt/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--'))
.
EOF

This produces:-

--- prereq-build.mk 2023-08-06 22:17:22.975025000 +0000
+++ prereq-build.mk.new 2023-08-06 22:33:12.005513000 +0000
@@ -147,6 +147,7 @@
Please install an extended getopt version that supports --long, \
gnugetopt -o t --long test -- --test | grep '^ *--test *--', \
getopt -o t --long test -- --test | grep '^ *--test *--', \
+ /usr/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \
/usr/local/opt/gnu-getopt/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \
/opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--'))

I want to change:

Bash:
patch include/prereq-build.mk -i /tmp/patch -o include/prereq-build.mk

to:

Bash:
patch include/prereq-build.mk - -o include/prereq-build.mk


Would/should this work if I change the heredoc to start with

cat <<EOF > (?????? - some character?)

If patch will take input from standard in then I assume the heredoc should look something like

Bash:
cat <<EOF.

--- prereq-build.mk<--->2023-08-06 22:17:22.975025000 +0000
+++ -
@@ -147,6 +147,7 @@
 <----->Please install an extended getopt version that supports --long, \\
 <----->gnugetopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->getopt -o t --long test -- --test | grep '^ *--test *--', \\
+<----->/usr/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/usr/local/opt/gnu-getopt/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--'))
.
EOF
 
This works,

Bash:
cat <<EOF > patchfile
--- prereq-build.mk<--->2023-08-06 22:17:22.975025000 +0000
+++.
@@ -147,6 +147,7 @@
 <----->Please install an extended getopt version that supports --long, \\
 <----->gnugetopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->getopt -o t --long test -- --test | grep '^ *--test *--', \\
+<----->/usr/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/usr/local/opt/gnu-getopt/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--'))
EOF

patch include/prereq-build.mk -i patchfile -o include/prereq-build.mk

but I'm trying figure out if I can do without the intermediate patchfile and pipe the output of cat directly into patch. patch is supposed to be able to read from stdin:-

If patchfile is omit-
ted, or is a hyphen, the patch will be read from the standard input
I'm not sure if that means I should use '-i -' or omit '-i' altogether.

And how would I specify the output of cat to stdout?
 
Eureka! It works.

Bash:
cat <<EOF |
--- prereq-build.mk<--->2023-08-06 22:17:22.975025000 +0000
+++.
@@ -147,6 +147,7 @@
 <----->Please install an extended getopt version that supports --long, \\
 <----->gnugetopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->getopt -o t --long test -- --test | grep '^ *--test *--', \\
+<----->/usr/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/usr/local/opt/gnu-getopt/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\
 <----->/opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--'))
EOF


patch include/prereq-build.mk -i - -o include/prereq-build.mk
 
Changing -i /tmp/patch to -i - is not necessary to change the line beginning with "+++".
Leave the "+++" lines as they are.
Just change cat <<EOF to patch include/prereq-build.mk -i - -o include/prerereq-build.mk <<EOF.
 
Here's what I finally settled on:-

Bash:
patch  <<EOF                                                                                                                                                
--- include/prereq-build.mk     2023-08-26 09:03:31.437266000 +0100                                                                                        
+++ -                                                                                                                                                      
@@ -149,6 +149,7 @@                                                                                                                                        
        Please install an extended getopt version that supports --long, \\                                                                                  
        gnugetopt -o t --long test -- --test | grep '^ *--test *--', \\                                                                                    
        getopt -o t --long test -- --test | grep '^ *--test *--', \\                                                                                        
+       /usr/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\                                                                        
        /usr/local/opt/gnu-getopt/bin/getopt -o t --long test -- --test | grep '^ *--test *--', \\                                                          
        /opt/local/bin/getopt -o t --long test -- --test | grep '^ *--test *--'))                                                                          
EOF

Many thanks for the suggestions provided. Much appreciated!
 
Back
Top