scripts/unify-sources.sh
author Alpar Juttner <alpar@cs.elte.hu>
Wed, 01 Apr 2009 17:17:47 +0100
changeset 610 dad9db81ade2
parent 411 c5f010a5647a
child 675 586b65073025
permissions -rwxr-xr-x
Fix in .hgignore
     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         if echo $2 | grep -q -v -E 'Makefile\.am$'
    92         then
    93             PATTERN=$(echo -e '\t')
    94         else
    95             PATTERN='        '
    96         fi
    97     elif [ "$3" == 'trailing spaces' ]
    98     then
    99         PATTERN='\ +$'
   100     else
   101         PATTERN='*'
   102     fi
   103 
   104     if ! diff -q $1 $2 >/dev/null
   105     then
   106         if [ "$PATTERN" == '*' ]
   107         then
   108             diff $1 $2 | grep '^[0-9]' | sed "s|^\(.*\)c.*$|$2:\1: check failed: $3|g" |
   109               sed "s/:\([0-9]*\),\([0-9]*\):\(.*\)$/:\1:\3 (until line \2)/g"
   110         else
   111             grep -n -E "$PATTERN" $2 | sed "s|^\([0-9]*\):.*$|$2:\1: check failed: $3|g"
   112         fi
   113         FAILED=YES
   114     fi
   115 }
   116 
   117 function check_warning() {
   118     if [ "$2" == 'long lines' ]
   119     then
   120         grep -n -E '.{81,}' $1 | sed "s|^\([0-9]*\):.*$|$1:\1: warning: $2|g"
   121     else
   122         echo "$1: warning: $2"
   123     fi
   124     WARNED=YES
   125 }
   126 
   127 function check_init() {
   128     echo Check source files...
   129     FAILED_FILES=0
   130     WARNED_FILES=0
   131     TOTAL_FILES=0
   132 }
   133 
   134 function check_done() {
   135     echo $FAILED_FILES out of $TOTAL_FILES files has been failed.
   136     echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings.
   137 
   138     if [ $WARNED_FILES -gt 0 -o $FAILED_FILES -gt 0 ]
   139     then
   140 	if [ "$WARNING" == 'INTERACTIVE' ]
   141 	then
   142 	    echo -n "Are the files with errors/warnings acceptable? (yes/no) "
   143 	    while read answer
   144 	    do
   145 		if [ "$answer" == 'yes' ]
   146 		then
   147 		    return 0
   148 		elif [ "$answer" == 'no' ]
   149 		then
   150 		    return 1
   151 		fi
   152 		echo -n "Are the files with errors/warnings acceptable? (yes/no) "
   153 	    done
   154 	elif [ "$WARNING" == 'WERROR' ]
   155 	then
   156 	    return 1
   157 	fi
   158     fi
   159 }
   160 
   161 function check_begin() {
   162     ((TOTAL_FILES++))
   163     FAILED=NO
   164     WARNED=NO
   165 }
   166 
   167 function check_end() {
   168     if [ $FAILED == YES ]
   169     then
   170 	((++FAILED_FILES))
   171     fi
   172     if [ $WARNED == YES ]
   173     then
   174 	((++WARNED_FILES))
   175     fi
   176 }
   177 
   178 
   179 
   180 # checks
   181 
   182 function header_check() {
   183     if echo $1 | grep -q -E 'Makefile\.am$'
   184     then
   185 	return
   186     fi
   187 
   188     TMP_FILE=`mktemp`
   189 
   190     (echo "/* -*- mode: C++; indent-tabs-mode: nil; -*-
   191  *
   192  * This file is a part of LEMON, a generic C++ optimization library.
   193  *
   194  * Copyright (C) "$YEAR"
   195  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
   196  * (Egervary Research Group on Combinatorial Optimization, EGRES).
   197  *
   198  * Permission to use, modify and distribute this software is granted
   199  * provided that this copyright notice appears in all copies. For
   200  * precise terms see the accompanying LICENSE file.
   201  *
   202  * This software is provided \"AS IS\" with no warranty of any kind,
   203  * express or implied, and with no claim as to its suitability for any
   204  * purpose.
   205  *
   206  */
   207 "
   208     awk 'BEGIN { pm=0; }
   209      pm==3 { print }
   210      /\/\* / && pm==0 { pm=1;}
   211      /[^:blank:]/ && (pm==0 || pm==2) { pm=3; print;}
   212      /\*\// && pm==1 { pm=2;}
   213     ' $1
   214     ) >$TMP_FILE
   215 
   216     "$ACTION"_action "$TMP_FILE" "$1" header
   217 }
   218 
   219 function tabs_check() {
   220     if echo $1 | grep -q -v -E 'Makefile\.am$'
   221     then
   222         OLD_PATTERN=$(echo -e '\t')
   223         NEW_PATTERN='        '
   224     else
   225         OLD_PATTERN='        '
   226         NEW_PATTERN=$(echo -e '\t')
   227     fi
   228     TMP_FILE=`mktemp`
   229     cat $1 | sed -e "s/$OLD_PATTERN/$NEW_PATTERN/g" >$TMP_FILE
   230 
   231     "$ACTION"_action "$TMP_FILE" "$1" 'tabs'
   232 }
   233 
   234 function spaces_check() {
   235     TMP_FILE=`mktemp`
   236     cat $1 | sed -e 's/ \+$//g' >$TMP_FILE
   237 
   238     "$ACTION"_action "$TMP_FILE" "$1" 'trailing spaces'
   239 }
   240 
   241 function long_lines_check() {
   242     if cat $1 | grep -q -E '.{81,}'
   243     then
   244 	"$ACTION"_warning $1 'long lines'
   245     fi
   246 }
   247 
   248 # process the file
   249 
   250 function process_file() {
   251     if [ "$ACTION" == 'update' ]
   252     then
   253         echo -n "    $ACTION $1..."
   254     else
   255         echo "	  $ACTION $1..."
   256     fi
   257 
   258     CHECKING="header tabs spaces long_lines"
   259 
   260     "$ACTION"_begin $1
   261     for check in $CHECKING
   262     do
   263 	"$check"_check $1
   264     done
   265     "$ACTION"_end $1
   266     if [ "$ACTION" == 'update' ]
   267     then
   268         echo
   269     fi
   270 }
   271 
   272 function process_all {
   273     "$ACTION"_init
   274     while read file
   275     do
   276 	process_file $file
   277     done < <($FILES)
   278     "$ACTION"_done
   279 }
   280 
   281 while [ $# -gt 0 ]
   282 do
   283     
   284     if [ "$1" == '--help' ] || [ "$1" == '-h' ]
   285     then
   286 	echo -n \
   287 "Usage:
   288   $0 [OPTIONS] [files]
   289 Options:
   290   --dry-run|-n
   291      Check the files, but do not modify them.
   292   --interactive|-i
   293      If --dry-run is specified and the checker emits warnings,
   294      then the user is asked if the warnings should be considered
   295      errors.
   296   --werror|-w
   297      Make all warnings into errors.
   298   --all|-a
   299      Check all source files in the repository.
   300   --modified|-m
   301      Check only the modified (and new) source files. This option is
   302      useful to check the modification before making a commit.
   303   --changed|-c
   304      Check only the changed source files compared to the parent(s) of
   305      the current hg node.  This option is useful as hg hook script.
   306      To automatically check all your changes before making a commit,
   307      add the following section to the appropriate .hg/hgrc file.
   308 
   309        [hooks]
   310        pretxncommit.checksources = scripts/unify-sources.sh -c -n -i
   311 
   312   --help|-h
   313      Print this help message.
   314   files
   315      The files to check/unify. If no file names are given, the modified
   316      source files will be checked/unified (just like using the
   317      --modified|-m option).
   318 "
   319         exit 0
   320     elif [ "$1" == '--dry-run' ] || [ "$1" == '-n' ]
   321     then
   322 	[ -n "$ACTION" ] && echo "Conflicting action options" >&2 && exit 1
   323 	ACTION=check
   324     elif [ "$1" == "--all" ] || [ "$1" == '-a' ]
   325     then
   326 	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   327 	FILES=all_files
   328     elif [ "$1" == "--changed" ] || [ "$1" == '-c' ]
   329     then
   330 	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   331 	FILES=changed_files
   332     elif [ "$1" == "--modified" ] || [ "$1" == '-m' ]
   333     then
   334 	[ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1
   335 	FILES=modified_files
   336     elif [ "$1" == "--interactive" ] || [ "$1" == "-i" ]
   337     then
   338 	[ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
   339 	WARNING='INTERACTIVE'
   340     elif [ "$1" == "--werror" ] || [ "$1" == "-w" ]
   341     then
   342 	[ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1
   343 	WARNING='WERROR'
   344     elif [ $(echo x$1 | cut -c 2) == '-' ]
   345     then
   346 	echo "Invalid option $1" >&2 && exit 1
   347     else
   348 	[ -n "$FILES" ] && echo "Invalid option $1" >&2 && exit 1
   349 	GIVEN_FILES=$@
   350 	FILES=given_files
   351 	break
   352     fi
   353     
   354     shift
   355 done
   356 
   357 if [ -z $FILES ]
   358 then
   359     FILES=modified_files
   360 fi
   361 
   362 if [ -z $ACTION ]
   363 then
   364     ACTION=update
   365 fi
   366 
   367 process_all