alpar@38: #!/bin/bash alpar@38: alpar@38: YEAR=`date +2003-%Y` alpar@38: HGROOT=`hg root` alpar@38: deba@324: # file enumaration modes deba@324: deba@324: function all_files() { deba@324: hg status -a -m -c | deba@324: cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | deba@324: while read file; do echo $HGROOT/$file; done deba@324: } deba@324: deba@324: function modified_files() { deba@324: hg status -a -m | deba@324: cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | deba@324: while read file; do echo $HGROOT/$file; done deba@324: } deba@324: deba@324: function changed_files() { deba@324: { deba@324: if [ -n "$HG_PARENT1" ] deba@324: then deba@324: hg status --rev $HG_PARENT1:$HG_NODE -a -m deba@324: fi deba@324: if [ -n "$HG_PARENT2" ] deba@324: then deba@324: hg status --rev $HG_PARENT2:$HG_NODE -a -m deba@324: fi deba@324: } | cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | deba@324: sort | uniq | deba@324: while read file; do echo $HGROOT/$file; done deba@324: } deba@324: deba@324: function given_files() { deba@324: for file in $GIVEN_FILES deba@324: do deba@324: echo $file deba@324: done deba@324: } deba@324: deba@324: # actions deba@324: deba@324: function update_action() { deba@324: if ! diff -q $1 $2 >/dev/null deba@324: then deba@324: echo -n " [$3 updated]" deba@324: rm $2 deba@324: mv $1 $2 deba@324: CHANGED=YES deba@324: fi deba@324: } deba@324: deba@324: function update_warning() { deba@324: echo -n " [$2 warning]" deba@324: WARNED=YES deba@324: } deba@324: deba@324: function update_init() { deba@324: echo Update source files... deba@324: TOTAL_FILES=0 deba@324: CHANGED_FILES=0 deba@324: WARNED_FILES=0 deba@324: } deba@324: deba@324: function update_done() { deba@324: echo $CHANGED_FILES out of $TOTAL_FILES files has been changed. deba@324: echo $WARNED_FILES out of $TOTAL_FILES files has been warned. deba@324: } deba@324: deba@324: function update_begin() { deba@324: ((TOTAL_FILES++)) deba@324: CHANGED=NO deba@324: WARNED=NO deba@324: } deba@324: deba@324: function update_end() { deba@324: if [ $CHANGED == YES ] deba@324: then deba@324: ((++CHANGED_FILES)) deba@324: fi deba@324: if [ $WARNED == YES ] deba@324: then deba@324: ((++WARNED_FILES)) deba@324: fi deba@324: } deba@324: deba@324: function check_action() { deba@324: if ! diff -q $1 $2 >/dev/null deba@324: then kpeter@329: echo kpeter@329: echo -n " $3 failed at line(s): " kpeter@329: echo -n $(diff $1 $2 | grep '^[0-9]' | sed "s/^\(.*\)c.*$/ \1/g" | kpeter@329: sed "s/,/-/g" | paste -s -d',') deba@324: FAILED=YES deba@324: fi deba@324: } deba@324: deba@324: function check_warning() { kpeter@329: echo kpeter@329: if [ "$2" == 'long lines' ] kpeter@329: then kpeter@329: echo -n " $2 warning at line(s): " kpeter@329: echo -n $(grep -n -E '.{81,}' $1 | sed "s/^\([0-9]*\)/ \1\t/g" | kpeter@329: cut -f 1 | paste -s -d',') kpeter@329: else kpeter@329: echo -n " $2 warning" kpeter@329: fi deba@324: WARNED=YES deba@324: } deba@324: deba@324: function check_init() { deba@324: echo Check source files... deba@324: FAILED_FILES=0 deba@324: WARNED_FILES=0 deba@324: TOTAL_FILES=0 deba@324: } deba@324: deba@324: function check_done() { deba@324: echo $FAILED_FILES out of $TOTAL_FILES files has been failed. deba@324: echo $WARNED_FILES out of $TOTAL_FILES files has been warned. deba@324: deba@324: if [ $FAILED_FILES -gt 0 ] deba@324: then deba@324: return 1 deba@324: elif [ $WARNED_FILES -gt 0 ] deba@324: then deba@324: if [ "$WARNING" == 'INTERACTIVE' ] deba@324: then deba@324: echo -n "Assume as normal behaviour? (yes/no) " deba@324: while read answer deba@324: do deba@324: if [ "$answer" == 'yes' ] deba@324: then deba@324: return 0 deba@324: elif [ "$answer" == 'no' ] deba@324: then deba@324: return 1 deba@324: fi deba@324: echo -n "Assume as normal behaviour? (yes/no) " deba@324: done deba@324: elif [ "$WARNING" == 'WERROR' ] deba@324: then deba@324: return 1 deba@324: fi deba@324: fi deba@324: } deba@324: deba@324: function check_begin() { deba@324: ((TOTAL_FILES++)) deba@324: FAILED=NO deba@324: WARNED=NO deba@324: } deba@324: deba@324: function check_end() { deba@324: if [ $FAILED == YES ] deba@324: then deba@324: ((++FAILED_FILES)) deba@324: fi deba@324: if [ $WARNED == YES ] deba@324: then deba@324: ((++WARNED_FILES)) deba@324: fi deba@324: } deba@324: deba@324: deba@324: deba@324: # checks deba@324: deba@324: function header_check() { deba@324: if echo $1 | grep -q -E 'Makefile\.am$' deba@324: then deba@324: return deba@324: fi deba@324: alpar@38: TMP_FILE=`mktemp` alpar@38: alpar@208: (echo "/* -*- mode: C++; indent-tabs-mode: nil; -*- alpar@38: * alpar@208: * This file is a part of LEMON, a generic C++ optimization library. alpar@38: * alpar@38: * Copyright (C) "$YEAR" alpar@38: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport alpar@38: * (Egervary Research Group on Combinatorial Optimization, EGRES). alpar@38: * alpar@38: * Permission to use, modify and distribute this software is granted alpar@38: * provided that this copyright notice appears in all copies. For alpar@38: * precise terms see the accompanying LICENSE file. alpar@38: * alpar@38: * This software is provided \"AS IS\" with no warranty of any kind, alpar@38: * express or implied, and with no claim as to its suitability for any alpar@38: * purpose. alpar@38: * alpar@38: */ alpar@38: " deba@324: awk 'BEGIN { pm=0; } alpar@38: pm==3 { print } alpar@38: /\/\* / && pm==0 { pm=1;} alpar@38: /[^:blank:]/ && (pm==0 || pm==2) { pm=3; print;} alpar@38: /\*\// && pm==1 { pm=2;} alpar@38: ' $1 deba@324: ) >$TMP_FILE alpar@208: deba@324: "$ACTION"_action "$TMP_FILE" "$1" header alpar@38: } alpar@38: deba@324: function tabs_check() { deba@324: if echo $1 | grep -q -v -E 'Makefile\.am$' deba@324: then deba@324: OLD_PATTERN=$(echo -e '\t') deba@324: NEW_PATTERN=' ' deba@324: else deba@324: OLD_PATTERN=' ' deba@324: NEW_PATTERN=$(echo -e '\t') deba@324: fi alpar@208: TMP_FILE=`mktemp` deba@324: cat $1 | sed -e "s/$OLD_PATTERN/$NEW_PATTERN/g" >$TMP_FILE alpar@38: deba@324: "$ACTION"_action "$TMP_FILE" "$1" 'tabs' alpar@208: } alpar@208: deba@324: function spaces_check() { alpar@208: TMP_FILE=`mktemp` deba@324: cat $1 | sed -e 's/ \+$//g' >$TMP_FILE alpar@208: kpeter@328: "$ACTION"_action "$TMP_FILE" "$1" 'trailing spaces' alpar@208: } alpar@208: deba@324: function long_lines_check() { deba@324: if cat $1 | grep -q -E '.{81,}' alpar@208: then deba@324: "$ACTION"_warning $1 'long lines' alpar@208: fi alpar@208: } alpar@208: deba@324: # process the file deba@324: deba@324: function process_file() { kpeter@328: echo -n " $ACTION $1..." deba@324: deba@324: CHECKING="header tabs spaces long_lines" deba@324: deba@324: "$ACTION"_begin $1 deba@324: for check in $CHECKING alpar@38: do deba@324: "$check"_check $1 alpar@38: done deba@324: "$ACTION"_end $1 deba@324: echo deba@324: } deba@324: deba@324: function process_all { deba@324: "$ACTION"_init deba@324: while read file alpar@38: do deba@324: process_file $file deba@324: done < <($FILES) deba@324: "$ACTION"_done deba@324: } deba@324: deba@324: while [ $# -gt 0 ] deba@324: do deba@324: deba@324: if [ "$1" == '--help' ] || [ "$1" == '-h' ] deba@324: then deba@324: echo -n \ deba@324: "Usage: deba@324: $0 [OPTIONS] [files] deba@324: Options: deba@324: --dry-run|-n deba@324: Check the given files, but do not modify them. deba@324: --interactive|-i kpeter@328: If --dry-run is specified and files are warned, then a message is deba@324: prompted whether the warnings should be turned to errors. deba@324: --werror|-w kpeter@328: If --dry-run is specified, the warnings are turned to errors. deba@324: --all|-a kpeter@328: Check all source files in the repository. deba@324: --modified|-m deba@324: Check only the modified source files. This option is proper to deba@324: use before a commit. E.g. all files which are modified or added deba@324: into the repository will be updated. deba@324: --changed|-c deba@324: Check only the changed source files compared to the parent(s) of deba@324: the current hg node. This option is proper to use as hg hook deba@324: script. E.g. to check all your commited source files with this deba@324: script add the following section to the appropriate .hg/hgrc deba@324: file. deba@324: deba@324: [hooks] deba@324: pretxncommit.checksources = scripts/unify-sources.sh -c -n -i deba@324: deba@324: --help|-h deba@324: Print this help message. deba@324: files kpeter@328: The files to check/unify. If no file names are given, the modified kpeter@328: source files will be checked/unified (just like using the kpeter@328: --modified|-m option). deba@324: " deba@324: exit 0 deba@324: elif [ "$1" == '--dry-run' ] || [ "$1" == '-n' ] deba@324: then kpeter@328: [ -n "$ACTION" ] && echo "Conflicting action options" >&2 && exit 1 deba@324: ACTION=check deba@324: elif [ "$1" == "--all" ] || [ "$1" == '-a' ] deba@324: then kpeter@328: [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1 deba@324: FILES=all_files deba@324: elif [ "$1" == "--changed" ] || [ "$1" == '-c' ] deba@324: then kpeter@328: [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1 deba@324: FILES=changed_files deba@324: elif [ "$1" == "--modified" ] || [ "$1" == '-m' ] deba@324: then kpeter@328: [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1 deba@324: FILES=modified_files deba@324: elif [ "$1" == "--interactive" ] || [ "$1" == "-i" ] deba@324: then kpeter@328: [ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1 deba@324: WARNING='INTERACTIVE' deba@324: elif [ "$1" == "--werror" ] || [ "$1" == "-w" ] deba@324: then kpeter@328: [ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1 deba@324: WARNING='WERROR' kpeter@328: elif [ $(echo x$1 | cut -c 2) == '-' ] deba@324: then deba@324: echo "Invalid option $1" >&2 && exit 1 deba@324: else deba@324: [ -n "$FILES" ] && echo "Invalid option $1" >&2 && exit 1 deba@324: GIVEN_FILES=$@ deba@324: FILES=given_files deba@324: break deba@324: fi deba@324: deba@324: shift deba@324: done deba@324: deba@324: if [ -z $FILES ] deba@324: then deba@324: FILES=modified_files alpar@38: fi deba@324: deba@324: if [ -z $ACTION ] deba@324: then deba@324: ACTION=update alpar@208: fi deba@324: deba@324: process_all