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