scripts/unify-sources.sh
changeset 802 994c7df296c9
parent 628 586b65073025
child 733 abf31e4af617
     1.1 --- a/scripts/unify-sources.sh	Fri Nov 13 12:33:33 2009 +0100
     1.2 +++ b/scripts/unify-sources.sh	Thu Dec 10 17:05:35 2009 +0100
     1.3 @@ -1,17 +1,206 @@
     1.4  #!/bin/bash
     1.5  
     1.6 -YEAR=`date +2003-%Y`
     1.7 +YEAR=`date +%Y`
     1.8  HGROOT=`hg root`
     1.9  
    1.10 -function update_header() {
    1.11 +function hg_year() {
    1.12 +    if [ -n "$(hg st $1)" ]; then
    1.13 +        echo $YEAR
    1.14 +    else
    1.15 +        hg log -l 1 --template='{date|isodate}\n' $1 |
    1.16 +        cut -d '-' -f 1
    1.17 +    fi
    1.18 +}
    1.19 +
    1.20 +# file enumaration modes
    1.21 +
    1.22 +function all_files() {
    1.23 +    hg status -a -m -c |
    1.24 +    cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' |
    1.25 +    while read file; do echo $HGROOT/$file; done
    1.26 +}
    1.27 +
    1.28 +function modified_files() {
    1.29 +    hg status -a -m |
    1.30 +    cut -d ' ' -f 2 | grep -E  '(\.(cc|h|dox)$|Makefile\.am$)' |
    1.31 +    while read file; do echo $HGROOT/$file; done
    1.32 +}
    1.33 +
    1.34 +function changed_files() {
    1.35 +    {
    1.36 +        if [ -n "$HG_PARENT1" ]
    1.37 +        then
    1.38 +            hg status --rev $HG_PARENT1:$HG_NODE -a -m
    1.39 +        fi
    1.40 +        if [ -n "$HG_PARENT2" ]
    1.41 +        then
    1.42 +            hg status --rev $HG_PARENT2:$HG_NODE -a -m
    1.43 +        fi
    1.44 +    } | cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | 
    1.45 +    sort | uniq |
    1.46 +    while read file; do echo $HGROOT/$file; done
    1.47 +}
    1.48 +
    1.49 +function given_files() {
    1.50 +    for file in $GIVEN_FILES
    1.51 +    do
    1.52 +	echo $file
    1.53 +    done
    1.54 +}
    1.55 +
    1.56 +# actions
    1.57 +
    1.58 +function update_action() {
    1.59 +    if ! diff -q $1 $2 >/dev/null
    1.60 +    then
    1.61 +	echo -n " [$3 updated]"
    1.62 +	rm $2
    1.63 +	mv $1 $2
    1.64 +	CHANGED=YES
    1.65 +    fi
    1.66 +}
    1.67 +
    1.68 +function update_warning() {
    1.69 +    echo -n " [$2 warning]"
    1.70 +    WARNED=YES
    1.71 +}
    1.72 +
    1.73 +function update_init() {
    1.74 +    echo Update source files...
    1.75 +    TOTAL_FILES=0
    1.76 +    CHANGED_FILES=0
    1.77 +    WARNED_FILES=0
    1.78 +}
    1.79 +
    1.80 +function update_done() {
    1.81 +    echo $CHANGED_FILES out of $TOTAL_FILES files has been changed.
    1.82 +    echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
    1.83 +}
    1.84 +
    1.85 +function update_begin() {
    1.86 +    ((TOTAL_FILES++))
    1.87 +    CHANGED=NO
    1.88 +    WARNED=NO
    1.89 +}
    1.90 +
    1.91 +function update_end() {
    1.92 +    if [ $CHANGED == YES ]
    1.93 +    then
    1.94 +	((++CHANGED_FILES))
    1.95 +    fi
    1.96 +    if [ $WARNED == YES ]
    1.97 +    then
    1.98 +	((++WARNED_FILES))
    1.99 +    fi
   1.100 +}
   1.101 +
   1.102 +function check_action() {
   1.103 +    if [ "$3" == 'tabs' ]
   1.104 +    then
   1.105 +        if echo $2 | grep -q -v -E 'Makefile\.am$'
   1.106 +        then
   1.107 +            PATTERN=$(echo -e '\t')
   1.108 +        else
   1.109 +            PATTERN='        '
   1.110 +        fi
   1.111 +    elif [ "$3" == 'trailing spaces' ]
   1.112 +    then
   1.113 +        PATTERN='\ +$'
   1.114 +    else
   1.115 +        PATTERN='*'
   1.116 +    fi
   1.117 +
   1.118 +    if ! diff -q $1 $2 >/dev/null
   1.119 +    then
   1.120 +        if [ "$PATTERN" == '*' ]
   1.121 +        then
   1.122 +            diff $1 $2 | grep '^[0-9]' | sed "s|^\(.*\)c.*$|$2:\1: check failed: $3|g" |
   1.123 +              sed "s/:\([0-9]*\),\([0-9]*\):\(.*\)$/:\1:\3 (until line \2)/g"
   1.124 +        else
   1.125 +            grep -n -E "$PATTERN" $2 | sed "s|^\([0-9]*\):.*$|$2:\1: check failed: $3|g"
   1.126 +        fi
   1.127 +        FAILED=YES
   1.128 +    fi
   1.129 +}
   1.130 +
   1.131 +function check_warning() {
   1.132 +    if [ "$2" == 'long lines' ]
   1.133 +    then
   1.134 +        grep -n -E '.{81,}' $1 | sed "s|^\([0-9]*\):.*$|$1:\1: warning: $2|g"
   1.135 +    else
   1.136 +        echo "$1: warning: $2"
   1.137 +    fi
   1.138 +    WARNED=YES
   1.139 +}
   1.140 +
   1.141 +function check_init() {
   1.142 +    echo Check source files...
   1.143 +    FAILED_FILES=0
   1.144 +    WARNED_FILES=0
   1.145 +    TOTAL_FILES=0
   1.146 +}
   1.147 +
   1.148 +function check_done() {
   1.149 +    echo $FAILED_FILES out of $TOTAL_FILES files has been failed.
   1.150 +    echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
   1.151 +
   1.152 +    if [ $WARNED_FILES -gt 0 -o $FAILED_FILES -gt 0 ]
   1.153 +    then
   1.154 +	if [ "$WARNING" == 'INTERACTIVE' ]
   1.155 +	then
   1.156 +	    echo -n "Are the files with errors/warnings acceptable? (yes/no) "
   1.157 +	    while read answer
   1.158 +	    do
   1.159 +		if [ "$answer" == 'yes' ]
   1.160 +		then
   1.161 +		    return 0
   1.162 +		elif [ "$answer" == 'no' ]
   1.163 +		then
   1.164 +		    return 1
   1.165 +		fi
   1.166 +		echo -n "Are the files with errors/warnings acceptable? (yes/no) "
   1.167 +	    done
   1.168 +	elif [ "$WARNING" == 'WERROR' ]
   1.169 +	then
   1.170 +	    return 1
   1.171 +	fi
   1.172 +    fi
   1.173 +}
   1.174 +
   1.175 +function check_begin() {
   1.176 +    ((TOTAL_FILES++))
   1.177 +    FAILED=NO
   1.178 +    WARNED=NO
   1.179 +}
   1.180 +
   1.181 +function check_end() {
   1.182 +    if [ $FAILED == YES ]
   1.183 +    then
   1.184 +	((++FAILED_FILES))
   1.185 +    fi
   1.186 +    if [ $WARNED == YES ]
   1.187 +    then
   1.188 +	((++WARNED_FILES))
   1.189 +    fi
   1.190 +}
   1.191 +
   1.192 +
   1.193 +
   1.194 +# checks
   1.195 +
   1.196 +function header_check() {
   1.197 +    if echo $1 | grep -q -E 'Makefile\.am$'
   1.198 +    then
   1.199 +	return
   1.200 +    fi
   1.201 +
   1.202      TMP_FILE=`mktemp`
   1.203 -    FILE_NAME=$1
   1.204  
   1.205      (echo "/* -*- mode: C++; indent-tabs-mode: nil; -*-
   1.206   *
   1.207   * This file is a part of LEMON, a generic C++ optimization library.
   1.208   *
   1.209 - * Copyright (C) "$YEAR"
   1.210 + * Copyright (C) 2003-"$(hg_year $1)"
   1.211   * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
   1.212   * (Egervary Research Group on Combinatorial Optimization, EGRES).
   1.213   *
   1.214 @@ -25,110 +214,163 @@
   1.215   *
   1.216   */
   1.217  "
   1.218 -	awk 'BEGIN { pm=0; }
   1.219 +    awk 'BEGIN { pm=0; }
   1.220       pm==3 { print }
   1.221       /\/\* / && pm==0 { pm=1;}
   1.222       /[^:blank:]/ && (pm==0 || pm==2) { pm=3; print;}
   1.223       /\*\// && pm==1 { pm=2;}
   1.224      ' $1
   1.225 -	) >$TMP_FILE
   1.226 +    ) >$TMP_FILE
   1.227  
   1.228 -    HEADER_CH=`diff -q $TMP_FILE $FILE_NAME >/dev/null&&echo NO||echo YES`
   1.229 -
   1.230 -    rm $FILE_NAME
   1.231 -    mv $TMP_FILE $FILE_NAME
   1.232 +    "$ACTION"_action "$TMP_FILE" "$1" header
   1.233  }
   1.234  
   1.235 -function update_tabs() {
   1.236 +function tabs_check() {
   1.237 +    if echo $1 | grep -q -v -E 'Makefile\.am$'
   1.238 +    then
   1.239 +        OLD_PATTERN=$(echo -e '\t')
   1.240 +        NEW_PATTERN='        '
   1.241 +    else
   1.242 +        OLD_PATTERN='        '
   1.243 +        NEW_PATTERN=$(echo -e '\t')
   1.244 +    fi
   1.245      TMP_FILE=`mktemp`
   1.246 -    FILE_NAME=$1
   1.247 +    cat $1 | sed -e "s/$OLD_PATTERN/$NEW_PATTERN/g" >$TMP_FILE
   1.248  
   1.249 -    cat $1 |
   1.250 -    sed -e 's/\t/        /g' >$TMP_FILE
   1.251 -
   1.252 -    TABS_CH=`diff -q $TMP_FILE $FILE_NAME >/dev/null&&echo NO||echo YES`
   1.253 -
   1.254 -    rm $FILE_NAME
   1.255 -    mv $TMP_FILE $FILE_NAME
   1.256 +    "$ACTION"_action "$TMP_FILE" "$1" 'tabs'
   1.257  }
   1.258  
   1.259 -function remove_trailing_space() {
   1.260 +function spaces_check() {
   1.261      TMP_FILE=`mktemp`
   1.262 -    FILE_NAME=$1
   1.263 +    cat $1 | sed -e 's/ \+$//g' >$TMP_FILE
   1.264  
   1.265 -    cat $1 |
   1.266 -    sed -e 's/ \+$//g' >$TMP_FILE
   1.267 -
   1.268 -    SPACES_CH=`diff -q $TMP_FILE $FILE_NAME >/dev/null&&echo NO||echo YES`
   1.269 -
   1.270 -    rm $FILE_NAME
   1.271 -    mv $TMP_FILE $FILE_NAME
   1.272 +    "$ACTION"_action "$TMP_FILE" "$1" 'trailing spaces'
   1.273  }
   1.274  
   1.275 -function long_line_test() {
   1.276 -    cat $1 |grep -q -E '.{81,}'
   1.277 -}
   1.278 -
   1.279 -function update_file() {
   1.280 -    echo -n '    update' $i ...
   1.281 -
   1.282 -    update_header $1
   1.283 -    update_tabs $1
   1.284 -    remove_trailing_space $1
   1.285 -
   1.286 -    CHANGED=NO;
   1.287 -    if [[ $HEADER_CH = YES ]];
   1.288 +function long_lines_check() {
   1.289 +    if cat $1 | grep -q -E '.{81,}'
   1.290      then
   1.291 -	echo -n '  [header updated]'
   1.292 -	CHANGED=YES;
   1.293 -    fi
   1.294 -    if [[ $TABS_CH = YES ]];
   1.295 -    then
   1.296 -	echo -n ' [tabs removed]'
   1.297 -	CHANGED=YES;
   1.298 -    fi
   1.299 -    if [[ $SPACES_CH = YES ]];
   1.300 -    then
   1.301 -	echo -n ' [trailing spaces removed]'
   1.302 -	CHANGED=YES;
   1.303 -    fi
   1.304 -    if long_line_test $1 ;
   1.305 -    then
   1.306 -	echo -n ' [LONG LINES]'
   1.307 -	((LONG_LINE_FILES++))
   1.308 -    fi
   1.309 -    echo
   1.310 -    if [[ $CHANGED = YES ]];
   1.311 -    then
   1.312 -	((CHANGED_FILES++))
   1.313 +	"$ACTION"_warning $1 'long lines'
   1.314      fi
   1.315  }
   1.316  
   1.317 -CHANGED_FILES=0
   1.318 -TOTAL_FILES=0
   1.319 -LONG_LINE_FILES=0
   1.320 -if [ $# == 0 ]; then
   1.321 -    echo Update all source files...
   1.322 -    for i in `hg manifest|grep -E  '\.(cc|h|dox)$'`
   1.323 +# process the file
   1.324 +
   1.325 +function process_file() {
   1.326 +    if [ "$ACTION" == 'update' ]
   1.327 +    then
   1.328 +        echo -n "    $ACTION $1..."
   1.329 +    else
   1.330 +        echo "	  $ACTION $1..."
   1.331 +    fi
   1.332 +
   1.333 +    CHECKING="header tabs spaces long_lines"
   1.334 +
   1.335 +    "$ACTION"_begin $1
   1.336 +    for check in $CHECKING
   1.337      do
   1.338 -	update_file $HGROOT/$i
   1.339 -	((TOTAL_FILES++))
   1.340 +	"$check"_check $1
   1.341      done
   1.342 -    echo '  done.'
   1.343 -else
   1.344 -    for i in $*
   1.345 +    "$ACTION"_end $1
   1.346 +    if [ "$ACTION" == 'update' ]
   1.347 +    then
   1.348 +        echo
   1.349 +    fi
   1.350 +}
   1.351 +
   1.352 +function process_all {
   1.353 +    "$ACTION"_init
   1.354 +    while read file
   1.355      do
   1.356 -	update_file $i
   1.357 -	((TOTAL_FILES++))
   1.358 -    done
   1.359 +	process_file $file
   1.360 +    done < <($FILES)
   1.361 +    "$ACTION"_done
   1.362 +}
   1.363 +
   1.364 +while [ $# -gt 0 ]
   1.365 +do
   1.366 +    
   1.367 +    if [ "$1" == '--help' ] || [ "$1" == '-h' ]
   1.368 +    then
   1.369 +	echo -n \
   1.370 +"Usage:
   1.371 +  $0 [OPTIONS] [files]
   1.372 +Options:
   1.373 +  --dry-run|-n
   1.374 +     Check the files, but do not modify them.
   1.375 +  --interactive|-i
   1.376 +     If --dry-run is specified and the checker emits warnings,
   1.377 +     then the user is asked if the warnings should be considered
   1.378 +     errors.
   1.379 +  --werror|-w
   1.380 +     Make all warnings into errors.
   1.381 +  --all|-a
   1.382 +     Check all source files in the repository.
   1.383 +  --modified|-m
   1.384 +     Check only the modified (and new) source files. This option is
   1.385 +     useful to check the modification before making a commit.
   1.386 +  --changed|-c
   1.387 +     Check only the changed source files compared to the parent(s) of
   1.388 +     the current hg node.  This option is useful as hg hook script.
   1.389 +     To automatically check all your changes before making a commit,
   1.390 +     add the following section to the appropriate .hg/hgrc file.
   1.391 +
   1.392 +       [hooks]
   1.393 +       pretxncommit.checksources = scripts/unify-sources.sh -c -n -i
   1.394 +
   1.395 +  --help|-h
   1.396 +     Print this help message.
   1.397 +  files
   1.398 +     The files to check/unify. If no file names are given, the modified
   1.399 +     source files will be checked/unified (just like using the
   1.400 +     --modified|-m option).
   1.401 +"
   1.402 +        exit 0
   1.403 +    elif [ "$1" == '--dry-run' ] || [ "$1" == '-n' ]
   1.404 +    then
   1.405 +	[ -n "$ACTION" ] && echo "Conflicting action options" >&2 && exit 1
   1.406 +	ACTION=check
   1.407 +    elif [ "$1" == "--all" ] || [ "$1" == '-a' ]
   1.408 +    then
   1.409 +	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   1.410 +	FILES=all_files
   1.411 +    elif [ "$1" == "--changed" ] || [ "$1" == '-c' ]
   1.412 +    then
   1.413 +	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   1.414 +	FILES=changed_files
   1.415 +    elif [ "$1" == "--modified" ] || [ "$1" == '-m' ]
   1.416 +    then
   1.417 +	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   1.418 +	FILES=modified_files
   1.419 +    elif [ "$1" == "--interactive" ] || [ "$1" == "-i" ]
   1.420 +    then
   1.421 +	[ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
   1.422 +	WARNING='INTERACTIVE'
   1.423 +    elif [ "$1" == "--werror" ] || [ "$1" == "-w" ]
   1.424 +    then
   1.425 +	[ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
   1.426 +	WARNING='WERROR'
   1.427 +    elif [ $(echo x$1 | cut -c 2) == '-' ]
   1.428 +    then
   1.429 +	echo "Invalid option $1" >&2 && exit 1
   1.430 +    else
   1.431 +	[ -n "$FILES" ] && echo "Invalid option $1" >&2 && exit 1
   1.432 +	GIVEN_FILES=$@
   1.433 +	FILES=given_files
   1.434 +	break
   1.435 +    fi
   1.436 +    
   1.437 +    shift
   1.438 +done
   1.439 +
   1.440 +if [ -z $FILES ]
   1.441 +then
   1.442 +    FILES=modified_files
   1.443  fi
   1.444 -echo $CHANGED_FILES out of $TOTAL_FILES files has been changed.
   1.445 -if [[ $LONG_LINE_FILES -gt 1 ]]; then
   1.446 -    echo
   1.447 -    echo WARNING: $LONG_LINE_FILES files contains long lines!    
   1.448 -    echo
   1.449 -elif [[ $LONG_LINE_FILES -gt 0 ]]; then
   1.450 -    echo
   1.451 -    echo WARNING: a file contains long lines!
   1.452 -    echo
   1.453 +
   1.454 +if [ -z $ACTION ]
   1.455 +then
   1.456 +    ACTION=update
   1.457  fi
   1.458 +
   1.459 +process_all