259 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
		
		
			
		
	
	
			259 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
|   | #! /bin/bash | |||
|  | # Downloaded from: http://code.google.com/p/cj-overlay/source/browse/cwdiff?repo=evergreens | |||
|  | #(C) 2009-2012 C. Junghans | |||
|  | # junghans@votca.org | |||
|  | # | |||
|  | # This program is free software; you can redistribute it and/or modify | |||
|  | # it under the terms of the GNU General Public License as published by | |||
|  | # the Free Software Foundation; either version 2 of the License, or | |||
|  | # (at your option) any later version. | |||
|  | # | |||
|  | # This program is distributed in the hope that it will be useful, | |||
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | |||
|  | # GNU General Public License for more details. | |||
|  | # | |||
|  | # You should have received a copy of the GNU General Public License | |||
|  | # along with this program; if not, write to the Free Software | |||
|  | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | |||
|  | # | |||
|  | #version 0.1    04.08.10 -- initial version | |||
|  | #version 0.1.1, 05.08.10 -- added -D and -o | |||
|  | #version 0.1.2, 04.10.10 -- make -D work again and better help | |||
|  | #version 0.1.3, 10.05.11 -- added --text to diff_opts to allow diff of binary files (issue #3) | |||
|  | #version 0.1.4, 10.05.11 -- removed --text again and handle case of binary files | |||
|  | #version 0.2.0, 15.04.12 -- clean up + bugfix thanks to Arne | |||
|  | #version 0.2.1, 15.04.12 -- clean up + new bug report address | |||
|  | #version 0.2.2, 20.04.12 -- fixed a bug if argument were dirs | |||
|  | #version 0.2.3, 18.12.12 -- replace usage of mktemp with bash built-ins | |||
|  | #version 0.2.4, 31.08.13 -- fixed deleted leading spaces | |||
|  | #version 0.2.5, 06.09.13 -- do not expand escape sequences in diff | |||
|  | #version 0.2.6, 18.09.13 -- allow 1st argument begin a file with --filter | |||
|  | 
 | |||
|  | FAT_GREEN="[32;01m" | |||
|  | GREEN="[32m" | |||
|  | FAT_RED="[31;01m" | |||
|  | RED="[31m" | |||
|  | MAGENTA="[35m" | |||
|  | FAT_BLACK="[1m" | |||
|  | OFF="[0m" | |||
|  | NL=" | |||
|  | " | |||
|  | 
 | |||
|  | usage="Usage: ${0##*/} [OPTIONS] FILE1 FILE2" | |||
|  | quiet="no" | |||
|  | diff="no" | |||
|  | filter="no" | |||
|  | diff_opts='--new-file --unified --show-c-function --recursive' | |||
|  | ab="no" | |||
|  | out="-" | |||
|  | style="wdiff" | |||
|  | a2ps="" | |||
|  | a2ps_opts="--prologue=color" | |||
|  | color="yes" | |||
|  | 
 | |||
|  | color_filter() { | |||
|  |   if [[ $a2ps ]]; then | |||
|  |     #seems like a bug in the a2ps style file | |||
|  |     sed -e "s/\[-/[wd-/g" -e "s/-\]/-wd]/g" -e "s/{+/{wd+/g" -e "s/+}/+wd}/g" $1 | |||
|  |   elif [[ $color = yes ]]; then | |||
|  |     sed -e "s/\[-/$RED/g" -e "s/-\]/$OFF/g" -e "s/{+/$GREEN/g" -e "s/+}/$OFF/g" $1 | |||
|  |   else | |||
|  |     cat $1 | |||
|  |   fi | |||
|  | } | |||
|  | 
 | |||
|  | die() { | |||
|  |   [[ $* ]] && echo "$*" | |||
|  |   exit 1 | |||
|  | } | |||
|  | 
 | |||
|  | qecho() { | |||
|  |   [[ $quiet = yes ]] || echo "$*" | |||
|  | } | |||
|  | 
 | |||
|  | show_help () { | |||
|  |   cat << eof | |||
|  | A colorized version of wdiff | |||
|  | $usage | |||
|  | 
 | |||
|  | OPTIONS: | |||
|  | -f, --filter        Act as a wdiff color filter only and don't excute diff/wdiff | |||
|  |                     internally, just colorize input (no ARGS = read from stdin) | |||
|  | -d, --diff          Preprocess input with diff and before giving it to wdiff | |||
|  |                     (very useful for dirs). Option can be used in combination | |||
|  |                     with --filter option meaning input is a patch. | |||
|  | -D, --diffonly      Process input with diff, but NOT with wdiff, so ${0##*/} | |||
|  |                     basically acts like a colorized version of diff. Option | |||
|  |                     can be used in combination with --filter option meaning | |||
|  |                     input is a patch. | |||
|  |     --diffopts XXX  Change opts of diff | |||
|  |                     Default: '$diff_opts' | |||
|  |     --ab            replace trunc of dirname by 'a' and 'b' | |||
|  |     --no-color      Disable color | |||
|  |                     (implies --a2psopts '--prologue=ul') | |||
|  | -a, --a2ps          Pipe the output to a2ps, which will produce ps code | |||
|  |                     (also work with --filter) | |||
|  |     --a2psopts XXX  Change opts of a2ps | |||
|  |                     Default: '$a2ps_opts' | |||
|  | -o, --out FILE      Change output file | |||
|  |                     Default: stdout | |||
|  |     --              Stop parsing options | |||
|  | -h, --help          Show this help | |||
|  | -v, --version       Show version | |||
|  |     --hg            Show last log message for hg (or cvs) | |||
|  | 
 | |||
|  | Examples:  ${0##*/} -d dir1 dir2 | |||
|  |            ${0##*/} file1 file2 | |||
|  |            ${0##*/} --ab -D dir1 dir2 | |||
|  | 	   ${0##*/} -a --ab -D dir1 dir2 > file.ps | |||
|  | 	   wdiff file1 file2 | ${0##*/} -f | |||
|  | 	   diff -u file1 file2 | ${0##*/} -D -f | |||
|  | 
 | |||
|  | 
 | |||
|  | Report bugs and comments at https://code.google.com/p/cj-overlay/issues/list | |||
|  |                          or junghans@votca.org | |||
|  | eof | |||
|  | } | |||
|  | 
 | |||
|  | shopt -s extglob | |||
|  | while [[ ${1} = -?* ]]; do | |||
|  |   if [[ ${1} = --??*=* ]]; then # case --xx=yy | |||
|  |     set -- "${1%%=*}" "${1#*=}" "${@:2}" # --xx=yy to --xx yy | |||
|  |   elif [[ ${1} = -[^-]?* ]]; then # case -xy split | |||
|  |     if [[ ${1} = -[o]* ]]; then #short opts with arguments | |||
|  |        set -- "${1:0:2}" "${1:2}" "${@:2}" # -xy to -x y | |||
|  |     else #short opts without arguments | |||
|  |        set -- "${1:0:2}" "-${1:2}" "${@:2}" # -xy to -x -y | |||
|  |     fi | |||
|  |   fi | |||
|  |   case $1 in | |||
|  |    --ab) | |||
|  |     ab="yes" | |||
|  |     shift;; | |||
|  |    --no-color) | |||
|  |     unset FAT_GREEN GREEN FAT_RED RED MAGENTA OFF FAT_BLACK | |||
|  |     a2ps_opts="--prologue=ul" | |||
|  |     color="no" | |||
|  |     shift;; | |||
|  |    -f | --filter) | |||
|  |     filter="yes" | |||
|  |     shift ;; | |||
|  |    -d | --diff) | |||
|  |     diff="yes" | |||
|  |     shift ;; | |||
|  |    -D | --diffonly) | |||
|  |     diff="only" | |||
|  |     shift ;; | |||
|  |    -a | --a2ps) | |||
|  |     a2ps="a2ps" | |||
|  |     unset FAT_GREEN GREEN FAT_RED RED MAGENTA OFF FAT_BLACK | |||
|  |     shift ;; | |||
|  |   --a2psopts) | |||
|  |     a2ps_opts="$2" | |||
|  |     shift 2;; | |||
|  |    -o | --out) | |||
|  |     out="$2" | |||
|  |     [[ ! $out ]] && die "Missing filename after --out option" | |||
|  |     shift 2;; | |||
|  |    --diffopts) | |||
|  |     diff_opts="$2" | |||
|  |     shift ;; | |||
|  |    -q | --quiet) | |||
|  |     quiet="yes" | |||
|  |     shift ;; | |||
|  |    -h | --help) | |||
|  |     show_help | |||
|  |     exit 0;; | |||
|  |    --hg) | |||
|  |     echo "${0##*/}: $(sed -ne 's/^#version.* -- \(.*$\)/\1/p' $0 | sed -n '$p')" | |||
|  |     exit 0;; | |||
|  |    -v | --version) | |||
|  |     echo "${0##*/}, $(sed -ne 's/^#\(version.*\) -- .*$/\1/p' $0 | sed -n '$p') by C. Junghans" | |||
|  |     exit 0;; | |||
|  |    --) | |||
|  |     shift | |||
|  |     break;; | |||
|  |   *) | |||
|  |    die "Unknown option '$1'";; | |||
|  |   esac | |||
|  | done | |||
|  | 
 | |||
|  | [[ $1 = - ]] && filter="yes" && shift | |||
|  | if [[ $filter = no ]]; then | |||
|  |   [[ ! $1 || ! $2 ]]  && die "Please specify two files/dirs or add --filter option" | |||
|  |   #use -e as it could be file or dir | |||
|  |   [[ -e $1 ]] || die "Could not read file/dir '$1'" | |||
|  |   [[ -e $2 ]] || die "Could not read file/dir '$2'" | |||
|  |   [[ $3 ]] && die "I don't know what to do with arguments '${@:3}'" | |||
|  | else | |||
|  |   [[ -n $1 && ! -f $1 ]] && die "Could not read file '$1'" | |||
|  |   [[ $2 ]] && die "I don't know what to do with arguments '$*' together --filter option" | |||
|  | fi | |||
|  | 
 | |||
|  | if [[ $diff != no ]]; then | |||
|  |   if [[ $filter = no ]]; then | |||
|  |     exec 3< <(diff $diff_opts "$1" "$2") | |||
|  |     #don't die here, because diff of binary files give exit code = 2 | |||
|  |   else | |||
|  |     [[ $1 ]] && exec 3<$1 || exec 3<&0 | |||
|  |   fi | |||
|  |   # don't do this if we have not files ;-) | |||
|  |   if [[ $ab = yes && $1 && $2 ]]; then | |||
|  |     #find the longest equal part in $1 and $2 from the end | |||
|  |     for ((i=1;i<=(${#1}<${#2}?${#1}:${#2});i++)); do | |||
|  |       [[ ${1:0-$i} != ${2:0-$i} ]] && break | |||
|  |     done | |||
|  |     ((i--)) | |||
|  |     a="${1:0:${#1}-$i}" | |||
|  |     b="${2:0:${#2}-$i}" | |||
|  |   else | |||
|  |     a=a; b=b | |||
|  |   fi | |||
|  |   # -r to not expand escape sequences in diff | |||
|  |   while read -r -u 3; do | |||
|  |     #small trick, because "read -u 3 i" would split the line and | |||
|  |     #leading space would be lost. | |||
|  |     i="${REPLY}" | |||
|  |     if [[ $i = "Files "*" and "*" differ" ]]; then # binary case | |||
|  |       i="${i/$a/a}" | |||
|  |       i="${i/$b/b}" | |||
|  |       echo "$i" | |||
|  |     elif [[ $i = diff* ]]; then # diff header line | |||
|  |       i="${i/ $diff_opts}" | |||
|  |       i="${i/$a/a}" | |||
|  |       echo "$FAT_BLACK${i/$b/b}$OFF" | |||
|  |     elif [[ $i = ---* ]]; then | |||
|  |       echo "${FAT_RED}${i/$a/a}${OFF}" | |||
|  |     elif [[ $i = +++* ]]; then | |||
|  |       echo "${FAT_GREEN}${i/$b/b}${OFF}" | |||
|  |     elif [[ $i = @@* ]]; then | |||
|  |       echo "${MAGENTA}${i}${OFF}" | |||
|  |     elif [[ $i = -* ]]; then | |||
|  |       [[ $diff = only ]] && echo "${RED}${i}${OFF}" || t1+="${i#-}$NL" | |||
|  |     elif [[ $i = +* ]]; then | |||
|  |       [[ $diff = only ]] && echo "${GREEN}${i}${OFF}" || t2+="${i#+}$NL" | |||
|  |     else | |||
|  |       # only true for diff != only | |||
|  |       # cut the last newline do avoid an empty line at the end (echo append newline) | |||
|  |       # echo -n would also work, but wdiff has strange behaviour if the 2nd file is | |||
|  |       # empty, it will not append newline, which make the output look strange | |||
|  |       [[ $t1 || $t2 ]] && { wdiff <(echo "${t1%$NL}") <(echo "${t2%$NL}") | color_filter; } | |||
|  |       t1= | |||
|  |       t2= | |||
|  |       [[ $diff = only ]] && echo "${i}" || echo "${i## }" | |||
|  |     fi | |||
|  |   done | |||
|  |   # thanks to Arne Babenhauserheide for pointing out this case is missing | |||
|  |   # if there was + or - lines at the end, which has not been printed yet | |||
|  |   [[ $t1 || $t2 ]] && { wdiff <(echo "${t1%$NL}") <(echo "${t2%$NL}") | color_filter; } | |||
|  | elif [[ $filter = yes ]]; then | |||
|  |   color_filter $1 | |||
|  | else | |||
|  |   wdiff "$1" "$2" | color_filter | |||
|  | fi | if [[ $a2ps ]]; then | |||
|  |   a2ps $a2ps_opts "--pretty-print=$style" -o "$out" | |||
|  | else | |||
|  |   [[ $out = - ]] && cat || cat > "$out" | |||
|  | fi |