258 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			258 lines
		
	
	
	
		
			8.2 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
| #! /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
 | 
