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