scripts/unify-sources.sh
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 12 Apr 2010 16:52:48 +0200
branch1.1
changeset 973 290f3ca599d6
parent 675 586b65073025
child 780 abf31e4af617
permissions -rwxr-xr-x
Merge bugfix #366 to branch 1.1
     1 #!/bin/bash
     2 
     3 YEAR=`date +%Y`
     4 HGROOT=`hg root`
     5 
     6 function hg_year() {
     7     if [ -n "$(hg st $1)" ]; then
     8         echo $YEAR
     9     else
    10         hg log -l 1 --template='{date|isodate}\n' $1 |
    11         cut -d '-' -f 1
    12     fi
    13 }
    14 
    15 # file enumaration modes
    16 
    17 function all_files() {
    18     hg status -a -m -c |
    19     cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' |
    20     while read file; do echo $HGROOT/$file; done
    21 }
    22 
    23 function modified_files() {
    24     hg status -a -m |
    25     cut -d ' ' -f 2 | grep -E  '(\.(cc|h|dox)$|Makefile\.am$)' |
    26     while read file; do echo $HGROOT/$file; done
    27 }
    28 
    29 function changed_files() {
    30     {
    31         if [ -n "$HG_PARENT1" ]
    32         then
    33             hg status --rev $HG_PARENT1:$HG_NODE -a -m
    34         fi
    35         if [ -n "$HG_PARENT2" ]
    36         then
    37             hg status --rev $HG_PARENT2:$HG_NODE -a -m
    38         fi
    39     } | cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | 
    40     sort | uniq |
    41     while read file; do echo $HGROOT/$file; done
    42 }
    43 
    44 function given_files() {
    45     for file in $GIVEN_FILES
    46     do
    47 	echo $file
    48     done
    49 }
    50 
    51 # actions
    52 
    53 function update_action() {
    54     if ! diff -q $1 $2 >/dev/null
    55     then
    56 	echo -n " [$3 updated]"
    57 	rm $2
    58 	mv $1 $2
    59 	CHANGED=YES
    60     fi
    61 }
    62 
    63 function update_warning() {
    64     echo -n " [$2 warning]"
    65     WARNED=YES
    66 }
    67 
    68 function update_init() {
    69     echo Update source files...
    70     TOTAL_FILES=0
    71     CHANGED_FILES=0
    72     WARNED_FILES=0
    73 }
    74 
    75 function update_done() {
    76     echo $CHANGED_FILES out of $TOTAL_FILES files has been changed.
    77     echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
    78 }
    79 
    80 function update_begin() {
    81     ((TOTAL_FILES++))
    82     CHANGED=NO
    83     WARNED=NO
    84 }
    85 
    86 function update_end() {
    87     if [ $CHANGED == YES ]
    88     then
    89 	((++CHANGED_FILES))
    90     fi
    91     if [ $WARNED == YES ]
    92     then
    93 	((++WARNED_FILES))
    94     fi
    95 }
    96 
    97 function check_action() {
    98     if [ "$3" == 'tabs' ]
    99     then
   100         if echo $2 | grep -q -v -E 'Makefile\.am$'
   101         then
   102             PATTERN=$(echo -e '\t')
   103         else
   104             PATTERN='        '
   105         fi
   106     elif [ "$3" == 'trailing spaces' ]
   107     then
   108         PATTERN='\ +$'
   109     else
   110         PATTERN='*'
   111     fi
   112 
   113     if ! diff -q $1 $2 >/dev/null
   114     then
   115         if [ "$PATTERN" == '*' ]
   116         then
   117             diff $1 $2 | grep '^[0-9]' | sed "s|^\(.*\)c.*$|$2:\1: check failed: $3|g" |
   118               sed "s/:\([0-9]*\),\([0-9]*\):\(.*\)$/:\1:\3 (until line \2)/g"
   119         else
   120             grep -n -E "$PATTERN" $2 | sed "s|^\([0-9]*\):.*$|$2:\1: check failed: $3|g"
   121         fi
   122         FAILED=YES
   123     fi
   124 }
   125 
   126 function check_warning() {
   127     if [ "$2" == 'long lines' ]
   128     then
   129         grep -n -E '.{81,}' $1 | sed "s|^\([0-9]*\):.*$|$1:\1: warning: $2|g"
   130     else
   131         echo "$1: warning: $2"
   132     fi
   133     WARNED=YES
   134 }
   135 
   136 function check_init() {
   137     echo Check source files...
   138     FAILED_FILES=0
   139     WARNED_FILES=0
   140     TOTAL_FILES=0
   141 }
   142 
   143 function check_done() {
   144     echo $FAILED_FILES out of $TOTAL_FILES files has been failed.
   145     echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
   146 
   147     if [ $WARNED_FILES -gt 0 -o $FAILED_FILES -gt 0 ]
   148     then
   149 	if [ "$WARNING" == 'INTERACTIVE' ]
   150 	then
   151 	    echo -n "Are the files with errors/warnings acceptable? (yes/no) "
   152 	    while read answer
   153 	    do
   154 		if [ "$answer" == 'yes' ]
   155 		then
   156 		    return 0
   157 		elif [ "$answer" == 'no' ]
   158 		then
   159 		    return 1
   160 		fi
   161 		echo -n "Are the files with errors/warnings acceptable? (yes/no) "
   162 	    done
   163 	elif [ "$WARNING" == 'WERROR' ]
   164 	then
   165 	    return 1
   166 	fi
   167     fi
   168 }
   169 
   170 function check_begin() {
   171     ((TOTAL_FILES++))
   172     FAILED=NO
   173     WARNED=NO
   174 }
   175 
   176 function check_end() {
   177     if [ $FAILED == YES ]
   178     then
   179 	((++FAILED_FILES))
   180     fi
   181     if [ $WARNED == YES ]
   182     then
   183 	((++WARNED_FILES))
   184     fi
   185 }
   186 
   187 
   188 
   189 # checks
   190 
   191 function header_check() {
   192     if echo $1 | grep -q -E 'Makefile\.am$'
   193     then
   194 	return
   195     fi
   196 
   197     TMP_FILE=`mktemp`
   198 
   199     (echo "/* -*- mode: C++; indent-tabs-mode: nil; -*-
   200  *
   201  * This file is a part of LEMON, a generic C++ optimization library.
   202  *
   203  * Copyright (C) 2003-"$(hg_year $1)"
   204  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
   205  * (Egervary Research Group on Combinatorial Optimization, EGRES).
   206  *
   207  * Permission to use, modify and distribute this software is granted
   208  * provided that this copyright notice appears in all copies. For
   209  * precise terms see the accompanying LICENSE file.
   210  *
   211  * This software is provided \"AS IS\" with no warranty of any kind,
   212  * express or implied, and with no claim as to its suitability for any
   213  * purpose.
   214  *
   215  */
   216 "
   217     awk 'BEGIN { pm=0; }
   218      pm==3 { print }
   219      /\/\* / && pm==0 { pm=1;}
   220      /[^:blank:]/ && (pm==0 || pm==2) { pm=3; print;}
   221      /\*\// && pm==1 { pm=2;}
   222     ' $1
   223     ) >$TMP_FILE
   224 
   225     "$ACTION"_action "$TMP_FILE" "$1" header
   226 }
   227 
   228 function tabs_check() {
   229     if echo $1 | grep -q -v -E 'Makefile\.am$'
   230     then
   231         OLD_PATTERN=$(echo -e '\t')
   232         NEW_PATTERN='        '
   233     else
   234         OLD_PATTERN='        '
   235         NEW_PATTERN=$(echo -e '\t')
   236     fi
   237     TMP_FILE=`mktemp`
   238     cat $1 | sed -e "s/$OLD_PATTERN/$NEW_PATTERN/g" >$TMP_FILE
   239 
   240     "$ACTION"_action "$TMP_FILE" "$1" 'tabs'
   241 }
   242 
   243 function spaces_check() {
   244     TMP_FILE=`mktemp`
   245     cat $1 | sed -e 's/ \+$//g' >$TMP_FILE
   246 
   247     "$ACTION"_action "$TMP_FILE" "$1" 'trailing spaces'
   248 }
   249 
   250 function long_lines_check() {
   251     if cat $1 | grep -q -E '.{81,}'
   252     then
   253 	"$ACTION"_warning $1 'long lines'
   254     fi
   255 }
   256 
   257 # process the file
   258 
   259 function process_file() {
   260     if [ "$ACTION" == 'update' ]
   261     then
   262         echo -n "    $ACTION $1..."
   263     else
   264         echo "	  $ACTION $1..."
   265     fi
   266 
   267     CHECKING="header tabs spaces long_lines"
   268 
   269     "$ACTION"_begin $1
   270     for check in $CHECKING
   271     do
   272 	"$check"_check $1
   273     done
   274     "$ACTION"_end $1
   275     if [ "$ACTION" == 'update' ]
   276     then
   277         echo
   278     fi
   279 }
   280 
   281 function process_all {
   282     "$ACTION"_init
   283     while read file
   284     do
   285 	process_file $file
   286     done < <($FILES)
   287     "$ACTION"_done
   288 }
   289 
   290 while [ $# -gt 0 ]
   291 do
   292     
   293     if [ "$1" == '--help' ] || [ "$1" == '-h' ]
   294     then
   295 	echo -n \
   296 "Usage:
   297   $0 [OPTIONS] [files]
   298 Options:
   299   --dry-run|-n
   300      Check the files, but do not modify them.
   301   --interactive|-i
   302      If --dry-run is specified and the checker emits warnings,
   303      then the user is asked if the warnings should be considered
   304      errors.
   305   --werror|-w
   306      Make all warnings into errors.
   307   --all|-a
   308      Check all source files in the repository.
   309   --modified|-m
   310      Check only the modified (and new) source files. This option is
   311      useful to check the modification before making a commit.
   312   --changed|-c
   313      Check only the changed source files compared to the parent(s) of
   314      the current hg node.  This option is useful as hg hook script.
   315      To automatically check all your changes before making a commit,
   316      add the following section to the appropriate .hg/hgrc file.
   317 
   318        [hooks]
   319        pretxncommit.checksources = scripts/unify-sources.sh -c -n -i
   320 
   321   --help|-h
   322      Print this help message.
   323   files
   324      The files to check/unify. If no file names are given, the modified
   325      source files will be checked/unified (just like using the
   326      --modified|-m option).
   327 "
   328         exit 0
   329     elif [ "$1" == '--dry-run' ] || [ "$1" == '-n' ]
   330     then
   331 	[ -n "$ACTION" ] && echo "Conflicting action options" >&2 && exit 1
   332 	ACTION=check
   333     elif [ "$1" == "--all" ] || [ "$1" == '-a' ]
   334     then
   335 	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   336 	FILES=all_files
   337     elif [ "$1" == "--changed" ] || [ "$1" == '-c' ]
   338     then
   339 	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   340 	FILES=changed_files
   341     elif [ "$1" == "--modified" ] || [ "$1" == '-m' ]
   342     then
   343 	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   344 	FILES=modified_files
   345     elif [ "$1" == "--interactive" ] || [ "$1" == "-i" ]
   346     then
   347 	[ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
   348 	WARNING='INTERACTIVE'
   349     elif [ "$1" == "--werror" ] || [ "$1" == "-w" ]
   350     then
   351 	[ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
   352 	WARNING='WERROR'
   353     elif [ $(echo x$1 | cut -c 2) == '-' ]
   354     then
   355 	echo "Invalid option $1" >&2 && exit 1
   356     else
   357 	[ -n "$FILES" ] && echo "Invalid option $1" >&2 && exit 1
   358 	GIVEN_FILES=$@
   359 	FILES=given_files
   360 	break
   361     fi
   362     
   363     shift
   364 done
   365 
   366 if [ -z $FILES ]
   367 then
   368     FILES=modified_files
   369 fi
   370 
   371 if [ -z $ACTION ]
   372 then
   373     ACTION=update
   374 fi
   375 
   376 process_all