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