how to get diff filenames with output - diff

is there a way for diff to return the filenames of the files being compared aswell as the output, for example:
instead of :
17c17
< free ((qu -> vals) - 1);
---
> free (qu -> vals);
I am looking for:
17c17
file1.c
< free ((qu -> vals) - 1);
---
file2.c
> free (qu -> vals);
is it possible?
THanks

the -u switch does include the filenames:
#!/bin/bash
echo " free ((qu -> vals) - 1);" > file1.c
echo " free (qu -> vals);" > file2.c
diff -u file1.c file2.c
output:
--- file1.c 2014-03-13 17:46:43.000000000 -0500
+++ file2.c 2014-03-13 17:46:43.000000000 -0500
## -1 +1 ##
- free ((qu -> vals) - 1);
+ free (qu -> vals);

Related

Can I patch the patch?

In our CI we are patching files, the problem appears when we make changes in files which we patch, can I applay commit changes to patch file?
example:
text.txt
A
B
C
D
patch.patch
+++ b/text2.txt
## -1,4 +1,4 ##
A
B
-C
+X
D
new.txt:
Y
Y
B
C
D
diff text.txt new.txt > text_to_new.diff
diff --git a/text.txt b/new.txt
index 8422d40..4780582 100644
--- a/text.txt
+++ b/new.txt
## -1,4 +1,5 ##
-A
+Y
+Y
B
C
D
Can I update patch.patch with text_to_new.diff?

Is there any way to get the diff tool to report only the relative path of files in a recursive diff?

I'm trying to get a unified diff between many pairs of directories so I can ensure the comparison between pairs is consistent, and I want to know if there's a way to get diff to format the output with relative rather than absolute paths.
Right now if I use diff -r -u PATH1 PATH2 then I get this kind of output:
diff -r -u PATH1/some/subfile.txt PATH2/some/subfile.txt
--- PATH1/some/subfile.txt Tue Feb 07 09:16:31 2017
+++ PATH2/some/subfile.txt Tue Feb 07 09:16:32 2017
## -70,7 +70,7 ##
*
* some stuff
*
- * I am Tweedledee and you are not
+ * I am Tweedledum and you are not
*/
void twiddle(void)
{
## -88,7 +88,7 ##
* check whether we should destroy everything
* and then destroy everything in either case
*/
-inline static void Tweedledee(void)
+inline static void Tweedledum(void)
{
if (should_destroy_everything())
{
I would rather get just the relative paths... is there any way to get diff to do this? example:
diff -r -u PATH1/some/subfile.txt PATH2/some/subfile.txt
--- some/subfile.txt
+++ some/subfile.txt
## -70,7 +70,7 ##
*
* some stuff
*
- * I am Tweedledee and you are not
+ * I am Tweedledum and you are not
*/
void twiddle(void)
{
## -88,7 +88,7 ##
* check whether we should destroy everything
* and then destroy everything in either case
*/
-inline static void Tweedledee(void)
+inline static void Tweedledum(void)
{
if (should_destroy_everything())
{
This would make it easier to compare diff reports which are expected to be the same. (in my case PATH1 and PATH2 differ in each case, whereas the relative paths to files, and the exact content differences are the same)
Otherwise I have to filter this information out (either manually or with a script)
I would pipe the output of your diff command to a sed script something like this:
$ diff -r -u PATH1/some/subfile.txt PATH2/some/subfile.txt | sed '1s/PATH1\///' | sed '2s/PATH2\///'
The script says": on line 1, replace "PATH1", followed by a single forward slash, by nothing, then, on line 2, replace "PATH2", followed by a single forward slash, by nothing. I'd have to create some content to test it, so I haven't tested it.
I bit the bullet and did this parsing in Python; it removes the diff blah blah blah statements and relativizes the paths to a pair of specified root directories, also removing timestamps:
udiff_re = re.compile(r'^## -(\d+),(\d+) \+(\d+),(\d+) ##$')
diffitem_re = re.compile(r'^(\+\+\+|---) (.*)\s+.{7} \d\d \d\d:\d\d:\d\d \d{4}$')
def process_diff_output(output, dir1, dir2):
state = 0
lines_pending = [0,0]
result = []
for line in output.splitlines():
if state == 0:
if line.startswith('##'):
m = udiff_re.search(line)
if m:
nums = [int(n) for n in m.groups()]
else:
raise ValueError('Huh?\n' + line)
result.append(line)
lines_pending = [nums[1],nums[3]]
state = 1
elif line.startswith('--- ') or line.startswith('+++ '):
m = diffitem_re.search(line)
whichone = m.group(1)
filename = m.group(2)
dirx = dir1 if whichone == '---' else dir2
result.append('%s %s' % (whichone, os.path.relpath(filename, dirx)))
elif line.startswith('diff '):
pass # leave the diff cmd out
else:
raise ValueError('unknown header line\n'+line)
elif state == 1:
result.append(line)
if line.startswith('+'):
lines_pending[1] -= 1
elif line.startswith('-'):
lines_pending[0] -= 1
else:
lines_pending[0] -= 1
lines_pending[1] -= 1
if lines_pending == [0,0]:
state = 0
return '\n'.join(result)

Compile a static version of pngquant

I'm trying to create a statically linked version of pngquant in Oracle Linux Server release 7.1. I've compiled the static version of zlib and the static version of libpng.
Then, when I configure pngquant, I always get the information that it will be linked with a shared version of zlib.
$ ./configure --with-libpng=../libpng-1.6.21 --extra-cflags="-I../zlib-1.2.8" --extra-ldflags="../zlib-1.2.8/libz.a"
Compiler: gcc
Debug: no
SSE: yes
OpenMP: no
libpng: static (1.6.21)
zlib: shared (1.2.7)
lcms2: no
If I execute make, in the output it seems that the options are correctly passed to the compiler. However, the resulting binary requires libz.so to be executed. It seems that my directives are ignored or that the installed version always takes precedence.
Is there any way of forcing pngquant to be compiled with the static version of zlib?
I'm not sure, if I got it right, but here's a patch to pngquant's configure that worked for me. configure now accepts --with-zlib=<dir> as parameter. Store it to pngquant.patch and apply it with patch -uN -p1 -i pngquant.patch.
diff -ur pngquant-2.9.0/configure pngquant-2.9.0.fixed/configure
--- pngquant-2.9.0/configure 2017-03-06 09:37:30.000000000 +0100
+++ pngquant-2.9.0.fixed/configure 2017-03-07 09:57:20.246012152 +0100
## -48,6 +48,7 ##
help "--with-cocoa/--without-cocoa use Cocoa framework to read images"
fi
help "--with-libpng=<dir> search for libpng in directory"
+ help "--with-zlib=<dir> search for zlib in directory"
echo
help "CC=<compiler> use given compiler command"
help "CFLAGS=<flags> pass options to the compiler"
## -97,6 +98,9 ##
--with-libpng=*)
LIBPNG_DIR=${i#*=}
;;
+ --with-zlib=*)
+ ZLIB_DIR=${i#*=}
+ ;;
--prefix=*)
PREFIX=${i#*=}
;;
## -238,6 +242,19 ##
echo "${MAJ}${MIN}"
}
+# returns full zlib.h version string
+zlibh_string() {
+ echo "$(grep -m1 "define ZLIB_VERSION" "$1" | \
+ grep -Eo '"[^"]+"' | grep -Eo '[^"]+')"
+}
+
+# returns major minor version numbers from png.h
+zlibh_majmin() {
+ local MAJ=$(grep -m1 "define ZLIB_VER_MAJOR" "$1" | grep -Eo "[0-9]+")
+ local MIN=$(grep -m1 "define ZLIB_VER_MINOR" "$1" | grep -Eo "[0-9]+")
+ echo "${MAJ}${MIN}"
+}
+
error() {
status "$1" "error ... $2"
echo
## -420,11 +437,42 ##
error "libpng" "not found (try: $LIBPNG_CMD)"
fi
-# zlib
-if ! find_library "zlib" "z" "zlib.h" "libz.a" "libz.$SOLIBSUFFIX*"; then
- error "zlib" "not found (please install zlib-devel package)"
+# try if given flags are enough for zlib
+HAS_ZLIB=0
+if echo "#include \"zlib.h\"
+ int main(){
+ uLong test = zlibCompileFlags();
+ return 0;
+}" | "$CC" -xc -std=c99 -o /dev/null $CFLAGS $LDFLAGS - &> /dev/null; then
+ status "zlib" "custom flags"
+ HAS_ZLIB=1
fi
+if [ "$HAS_ZLIB" -eq 0 ]; then
+ # try static in the given directory
+ ZLIBH=$(find_h "$ZLIB_DIR" "zlib.h")
+ if [ -n "$ZLIBH" ]; then
+ ZLIBH_STRING=$(zlibh_string "$ZLIBH")
+ ZLIBH_MAJMIN=$(zlibh_majmin "$ZLIBH")
+ if [[ -n "$ZLIBH_STRING" && -n "$ZLIBH_MAJMIN" ]]; then
+ ZLIBA=$(find_f "$ZLIB_DIR" "libz${ZLIBH_MAJMIN}.a")
+ if [ -z "$ZLIBA" ]; then
+ ZLIBA=$(find_f "$ZLIB_DIR" "libz.a")
+ fi
+ if [ -n "$ZLIBA" ]; then
+ cflags "-I${ZLIBH%/*}"
+ lflags "${ZLIBA}"
+ status "zlib" "static (${ZLIBH_STRING})"
+ HAS_ZLIB=1
+ fi
+ fi
+ fi
+fi
+# zlib
+if ! find_library "zlib" "z" "zlib.h" "libz.a" "zlib.$SOLIBSUFFIX*"; then
+ error "zlib" "not found (please install zlib-devel package)"
+fi
+
# lcms2
if [ "$LCMS2" != 0 ]; then
if find_library "lcms2" "lcms2" "lcms2.h" "liblcms2.a" "liblcms2.$SOLIBSUFFIX*"; then
Sorry, the configure script does not support it. It shouldn't be too hard to modify configure to pass appropriate flags to pkg-config or do the same workaround it does for libpng.

How to get the exact, full version number of Perl that's installed?

I know I've got Perl 5.20.1.1 installed. But can I determine that programmatically?
$] only gives the revision, version and sub-version, i.e. 5.020001 for me, meaning 5.20.1.
The Config module (documented here) doesn't seem to give anything deeper than that. For me:
perl -MConfig -e 'foreach (sort keys %Config) { print "$_ -> $Config{$_}\n" if /version|revision/io; }'
gives:
PERL_API_REVISION -> 5
PERL_API_SUBVERSION -> 0
PERL_API_VERSION -> 20
PERL_REVISION -> 5
PERL_SUBVERSION -> 1
PERL_VERSION -> 20
Revision -> $Revision
SUBVERSION -> 1
api_revision -> 5
api_subversion -> 0
api_version -> 20
api_versionstring -> 5.20.0
ccversion ->
d_inc_version_list ->
d_libm_lib_version ->
db_version_major -> 0
db_version_minor -> 0
db_version_patch -> 0
gccversion -> 4.8.3
gnulibc_version ->
ignore_versioned_solibs ->
inc_version_list ->
inc_version_list_init -> 0
revision -> 5
subversion -> 1
version -> 5.20.1
version_patchlevel_string -> version 20 subversion 1
versiononly ->
I don't think there's anything in there that gives any more information, but it probably doesn't help that in my case the sub-version number is the same as the sub-sub-version number!
Is there anywhere else I can look? Or have I perhaps missed something in %Config?
Official Perl releases only have three parts. "5" is the language, "20" is the major version and "1" is the minor version. Anything more than that was added by someone else (at a guess, whoever packaged the Perl you're using), so you probably will not find it from inside Perl.

How does one extract a unified-diff style patch subset?

Every time I want to take a subset of a patch, I'm forced to write a script to only extract the indices that I want.
e.g. I have a patch that applies to sub directories
'yay' and 'foo'.
Is there a way to create a new patch or apply only a subset of a patch? i.e. create a new patch from the existing patch that only takes all indices that are under sub directory 'yay'. Or all indices that are not under sub directory 'foo'
If I have a patch like ( excuse the below pseudo-patch):
Index : foo/bar
yada
yada
- asdf
+ jkl
yada
yada
Index : foo/bah
blah
blah
- 28
+ 29
blah
blah
blah
Index : yay/team
go
huskies
- happy happy
+ joy joy
cougars
suck
How can I extract or apply only the 'yay' subdirectory like:
Index : yay/team
go
huskies
- happy happy
+ joy joy
cougars
suck
I know if I script up a solution I'll be re-inventing the wheel...
Take a look at the filterdiff utility, which is part of patchutils.
For example, if you have the following patch:
$ cat example.patch
diff -Naur orig/a/bar new/a/bar
--- orig/a/bar 2009-12-02 12:41:38.353745751 -0800
+++ new/a/bar 2009-12-02 12:42:17.845745951 -0800
## -1,3 +1,3 ##
4
-5
+e
6
diff -Naur orig/a/foo new/a/foo
--- orig/a/foo 2009-12-02 12:41:32.845745768 -0800
+++ new/a/foo 2009-12-02 12:42:25.697995617 -0800
## -1,3 +1,3 ##
1
2
-3
+c
diff -Naur orig/b/baz new/b/baz
--- orig/b/baz 2009-12-02 12:41:42.993745756 -0800
+++ new/b/baz 2009-12-02 12:42:37.585745735 -0800
## -1,3 +1,3 ##
-7
+z
8
9
Then you can run the following command to extract the patch for only things in the a directory like this:
$ cat example.patch | filterdiff -i 'new/a/*'
--- orig/a/bar 2009-12-02 12:41:38.353745751 -0800
+++ new/a/bar 2009-12-02 12:42:17.845745951 -0800
## -1,3 +1,3 ##
4
-5
+e
6
--- orig/a/foo 2009-12-02 12:41:32.845745768 -0800
+++ new/a/foo 2009-12-02 12:42:25.697995617 -0800
## -1,3 +1,3 ##
1
2
-3
+c
Here's my quick and dirty Perl solution.
perl -ne '#a = split /^Index :/m, join "", <>; END { for(#a) {print "Index :", $_ if (m, yay/team,)}}' < foo.patch
In response to sigjuice's request in the comments, I'm posting my script solution. It isn't 100% bullet proof, and I'll probably use filterdiff instead.
base_usage_str=r'''
python %prog index_regex patch_file
description:
Extracts all indices from a patch-file matching 'index_regex'
e.g.
python %prog '^evc_lib' p.patch > evc_lib_p.patch
Will extract all indices which begin with evc_lib.
-or-
python %prog '^(?!evc_lib)' p.patch > not_evc_lib_p.patch
Will extract all indices which do *not* begin with evc_lib.
authors:
Ross Rogers, 2009.04.02
'''
import re,os,sys
from optparse import OptionParser
def main():
parser = OptionParser(usage=base_usage_str)
(options, args) = parser.parse_args(args=sys.argv[1:])
if len(args) != 2:
parser.print_help()
if len(args) == 0:
sys.exit(0)
else:
sys.exit(1)
(index_regex,patch_file) = args
sys.stderr.write('Extracting patches for indices found by regex:%s\n'%index_regex)
#print 'user_regex',index_regex
user_index_match_regex = re.compile(index_regex)
# Index: verification/ring_td_cte/tests/mmio_wr_td_target.e
# --- sw/cfg/foo.xml 2009-04-30 17:59:11 -07:00
# +++ sw/cfg/foo.xml 2009-05-11 09:26:58 -07:00
index_cre = re.compile(r'''(?:(?<=^)|(?<=\n))(--- (?:.*\n){2,}?(?![ #\+\-]))''')
patch_file = open(patch_file,'r')
all_patch_sets = index_cre.findall(patch_file.read())
patch_file.close()
for file_edit in all_patch_sets:
# extract index subset
index_path = re.compile('\+\+\+ (?P<index>[\w_\-/\.]+)').search(file_edit).group('index').strip()
if user_index_match_regex.search(index_path):
sys.stderr.write("Index regex matched index: "+index_path+"\n")
print file_edit,
if __name__ == '__main__':
main()