LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 03-29-2012, 01:36 AM   #1
towheedm
Member
 
Registered: Sep 2011
Location: Trinidad & Tobago
Distribution: Debian Stretch
Posts: 612

Rep: Reputation: 125Reputation: 125
Creating a diff file when the lines in the input files are slightly different


I've been googling this and trying different options in diff both without success.

I'll be very specific so it's easier to understand. I want to create a single patchfile for this.

In both Fedora and Debian, the /etc/grub.d/10_linux are slightly different, but I would like to create a single patchfile that will work on both distros.

Here's a snippet of the file from Debian:
Code:
prefix=/usr
exec_prefix=${prefix}
bindir=${exec_prefix}/bin
libdir=${exec_prefix}/lib
. ${libdir}/grub/grub-mkconfig_lib

export TEXTDOMAIN=grub
export TEXTDOMAINDIR=${prefix}/share/locale

CLASS="--class gnu-linux --class gnu --class os"

if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
  OS=GNU/Linux
else
  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
  CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
fi

# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
And this is from Fedora:
Code:
prefix=/usr
exec_prefix=/usr
bindir=/usr/bin
libdir=/usr/lib
. ${libdir}/grub/grub-mkconfig_lib

export TEXTDOMAIN=grub
export TEXTDOMAINDIR=${prefix}/share/locale

CLASS="--class gnu-linux --class gnu --class os"

if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
  OS=Linux
else
  OS="${GRUB_DISTRIBUTOR} Linux"
  CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
fi

# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
I only want to patch the lines shown in red with:
Code:
using_submenu=false
CLASS="--class gnu-linux --class gnu --class os"
if [ "x${GRUB_THEME}" != "x" ] && [ -d "`dirname ${GRUB_THEME}`" ]; then
  recovery_icon="`dirname ${GRUB_THEME}`/icons/recovery.png"
fi

if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
  OS=GNU/Linux
else
  OS="$(echo ${GRUB_DISTRIBUTOR} | cut -d' ' -f1) $(echo ${GRUB_DISTRIBUTOR_CODENAME} | \
      sed 's,^.,\u&,')"
  DISTRIBUTOR_CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
fi
Is it possible to create a single patchfile so users on either distro can apply it successfully?

Thanks.
 
Old 04-05-2012, 12:26 PM   #2
ProtoformX
Member
 
Registered: Feb 2004
Location: Canada
Distribution: LFS SVN
Posts: 334

Rep: Reputation: 34
Yes it is, before the variables use an if statement to check what distro you are using if its deb use debs variables, ifs fedoras then use fedoras variables. That should work for what you are doing.

Last edited by ProtoformX; 04-05-2012 at 12:27 PM.
 
Old 04-07-2012, 08:28 PM   #3
towheedm
Member
 
Registered: Sep 2011
Location: Trinidad & Tobago
Distribution: Debian Stretch
Posts: 612

Original Poster
Rep: Reputation: 125Reputation: 125
You lost me with that. Do you mean to use an if statement within the diff file?
 
Old 04-07-2012, 08:48 PM   #4
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
I think ProtoformX may have misinterpreted your question--maybe not.

It gave me pause to think about it though. I am "thinking out loud" here...

Consider this file as your final, "end-product:"
Code:
. /etc/this_machine_distro
if [ ${THIS_DISTRO} = "RED_HAT" ] ; then
  prefix=/usr
  exec_prefix=/usr
  bindir=/usr/bin
  libdir=/usr/lib
else
  prefix=/usr
  exec_prefix=${prefix}
  bindir=${exec_prefix}/bin
  libdir=${exec_prefix}/lib
fi
. ${libdir}/grub/grub-mkconfig_lib

export TEXTDOMAIN=grub
export TEXTDOMAINDIR=${prefix}/share/locale

CLASS="--class gnu-linux --class gnu --class os"

if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
  OS=GNU/Linux
else
  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
  CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
fi

# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
Create a file named /etc/this_machine_distro. In it, place:
Code:
THIS_DISTRO=RED_HAT
or
Code:
THIS_DISTRO=DEBIAN
as appropriate for the particular machine. You could substitute some other method of determining the distribution--just so long as you can use it in the if statement.

Create your patch file against one of the machines by using an original/start-from copy that does not include any of the variable assignments (e.g. prefix, exec, bindir, and libdir)--rip those lines out entirely.

Try to patch against a test file using patch's '-N' option. With luck, when you try to patch a "real" file (that includes the assignments), patch will assume that those assignments are "previously applied patches" to ignore via the -N option.

Again, thinking out loud... I haven't tried it myself.

EDIT:
I think I got dragged off-track as well. Let me think about it some more. There's something percolating...

Last edited by Dark_Helmet; 04-07-2012 at 08:52 PM.
 
Old 04-07-2012, 09:06 PM   #5
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Let me start over...

I would say that your easiest option would be to submit a shell script rather than trying to force it through patch. You could easily plug in a sequence of head/tail/sed commands/awk commands to do what you need.

If you must use patch, then (correct me if I am wrong) your problem is that patch refuses to make changes because the context check fails. The context check fails because of the different variable assignments.

So, again, if you are forced to use patch, you need to do something to make the entire file uniform. That's the idea I was getting at in my earlier reply. You include the variable assignments in an if structure to coax patch into believing part of the patch had already been applied. Therefore, the context check would not fail, the existing variable assignment lines would be considered a previously applied patch, and then the file would be updated with the rest of your needed changes (specifically, replacing the text in red).

Does that make sense? I may try to do some experimentation and let you know what I come up with.
 
Old 04-07-2012, 09:56 PM   #6
towheedm
Member
 
Registered: Sep 2011
Location: Trinidad & Tobago
Distribution: Debian Stretch
Posts: 612

Original Poster
Rep: Reputation: 125Reputation: 125
Quote:
If you must use patch, then (correct me if I am wrong) your problem is that patch refuses to make changes because the context check fails. The context check fails because of the different variable assignments.
Yes, this is exactly the problem. The initial var assignments libdir etc, is not the problem. They are excluded from the patchfile with the -U 3 option because export TEXTDOMAIN=grub, export TEXTDOMAINDIR=${prefix}/share/locale and CLASS="--class gnu-linux --class gnu --class os" are all the same across all distros.

The problem is with the var assignments to be changed. So I was thinking whether I could use some sort of directive in the patchfile so as to take the different variable assignment into account, eg:

Code:
if OS="${GRUB_DISTRIBUTOR} GNU/Linux"; then
-  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
elif OS="${GRUB_DISTRIBUTOR} Linux"; then
-  OS="${GRUB_DISTRIBUTOR} Linux"; then
fi
+    OS="$(echo ${GRUB_DISTRIBUTOR} | cut -d' ' -f1) $(echo ${GRUB_DISTRIBUTOR_CODENAME} | \
      sed 's,^.,\u&,')"
But after further reading and by the logical conclusion of what a diff file is, I realized that was not possible.
After even more reading of the man pages, I thought the -D option (--ifdef) would work, but after several attempts, I realized this option is only for ifdef statements within a C source file.

The whole purpose of the diff file was so that the user would not have to manually edit the files, which meant I did not have to provide detailed instructions on doing so. Note that the above snippets are just part of the patch. Some of the hunks are really quite lengthy. Also, this is just one of the file to be patched, there are about four or five others, so a patchfile is definitely a must.

What I eventually did was to create a different patchfile for each distro but I would still like to know if such a thing is at all possible (for future reference).

Thanks.
 
Old 04-07-2012, 10:08 PM   #7
Dark_Helmet
Senior Member
 
Registered: Jan 2003
Posts: 2,786

Rep: Reputation: 374Reputation: 374Reputation: 374Reputation: 374
Well, I came close, but still hit the same problem.

I was trying to use the -I option (which is more complicated than you might initially anticipate).

This command showed some promise when I was experimenting:
Code:
diff -Naur -I '^bindir=.*' -I '^[[:space:]]\+OS=.*' -I '^libdir=.*' -I 'exec_prefix=.*' testfile.txt final_format.txt > testfile_patch.txt
Unfortunately, the shortfall with this setup is that any line that matches one of the RE's is ignored unless it falls within a hunk containing other changes that do not match any of the RE's.

I initially thought the default context for a unified patch (3 lines) was the culprit and tried to disable context entirely:
Code:
diff -Nar -C 0 -I '^bindir=.*' -I '^[[:space:]]\+OS=.*' -I '^libdir=.*' -I 'exec_prefix=.*' testfile.txt final_format.txt > testfile_patch.txt
No luck.

So, I'm stuck at the moment... not throwing in the towel, but stuck.
 
Old 04-08-2012, 11:10 AM   #8
ProtoformX
Member
 
Registered: Feb 2004
Location: Canada
Distribution: LFS SVN
Posts: 334

Rep: Reputation: 34
Quote:
Originally Posted by Dark_Helmet View Post
I think ProtoformX may have misinterpreted your question--maybe not.

It gave me pause to think about it though. I am "thinking out loud" here...

Consider this file as your final, "end-product:"
Code:
. /etc/this_machine_distro
if [ ${THIS_DISTRO} = "RED_HAT" ] ; then
  prefix=/usr
  exec_prefix=/usr
  bindir=/usr/bin
  libdir=/usr/lib
else
  prefix=/usr
  exec_prefix=${prefix}
  bindir=${exec_prefix}/bin
  libdir=${exec_prefix}/lib
fi
. ${libdir}/grub/grub-mkconfig_lib

export TEXTDOMAIN=grub
export TEXTDOMAINDIR=${prefix}/share/locale

CLASS="--class gnu-linux --class gnu --class os"

if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then
  OS=GNU/Linux
else
  OS="${GRUB_DISTRIBUTOR} GNU/Linux"
  CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr 'A-Z' 'a-z' | cut -d' ' -f1) ${CLASS}"
fi

# loop-AES arranges things so that /dev/loop/X can be our root device, but
# the initrds that Linux uses don't like that.
This is the right idea.. I meant to rediff the diff, create a backup of the source file apply the patch to the source file, then edit it using if statements to something like the above to check what distro you are using then diff that from the original backup... now you have a patch file that has code in it to detect distros
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
how to use diff to only print lines fancylad Linux - General 10 06-17-2013 12:50 PM
Knoppix distro - diff file to clarify additional files on DVD? rstiphout Linux - Distributions 1 11-16-2011 11:24 AM
How to compare/diff a range of lines from two text files jedibrand Linux - Software 1 03-26-2010 01:54 PM
diff / patch ignoring changes to particular lines Kikazaru Linux - General 2 03-09-2009 10:57 AM
Using diff to compare file with common lines, but at different line numbers jimieee Linux - Newbie 3 05-10-2004 07:26 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 10:21 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration