alpar@38: #!/bin/bash alpar@38: alpar@538: YEAR=`date +%Y` alpar@38: HGROOT=`hg root` alpar@38: alpar@538: function hg_year() { alpar@538: if [ -n "$(hg st $1)" ]; then alpar@538: echo $YEAR alpar@702: else alpar@702: hg log -l 1 --template='{date|isodate}\n' $1 | alpar@702: cut -d '-' -f 1 alpar@702: fi alpar@675: } alpar@675: deba@336: # file enumaration modes deba@336: deba@336: function all_files() { deba@336: hg status -a -m -c | deba@336: cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | deba@336: while read file; do echo $HGROOT/$file; done deba@336: } deba@336: deba@336: function modified_files() { deba@336: hg status -a -m | deba@336: cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | deba@336: while read file; do echo $HGROOT/$file; done deba@336: } deba@336: deba@336: function changed_files() { deba@336: { deba@336: if [ -n "$HG_PARENT1" ] deba@336: then deba@336: hg status --rev $HG_PARENT1:$HG_NODE -a -m deba@336: fi deba@336: if [ -n "$HG_PARENT2" ] deba@336: then deba@336: hg status --rev $HG_PARENT2:$HG_NODE -a -m deba@336: fi deba@336: } | cut -d ' ' -f 2 | grep -E '(\.(cc|h|dox)$|Makefile\.am$)' | deba@336: sort | uniq | deba@336: while read file; do echo $HGROOT/$file; done deba@336: } deba@336: deba@336: function given_files() { deba@336: for file in $GIVEN_FILES deba@336: do deba@336: echo $file deba@336: done deba@336: } deba@336: deba@336: # actions deba@336: deba@336: function update_action() { deba@336: if ! diff -q $1 $2 >/dev/null deba@336: then deba@336: echo -n " [$3 updated]" deba@336: rm $2 deba@336: mv $1 $2 deba@336: CHANGED=YES alpar@538: fi alpar@538: } alpar@538: deba@336: function update_warning() { deba@336: echo -n " [$2 warning]" deba@336: WARNED=YES deba@336: } deba@336: deba@336: function update_init() { deba@336: echo Update source files... deba@336: TOTAL_FILES=0 deba@336: CHANGED_FILES=0 deba@336: WARNED_FILES=0 deba@336: } deba@336: deba@336: function update_done() { deba@336: echo $CHANGED_FILES out of $TOTAL_FILES files has been changed. alpar@337: echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings. deba@336: } deba@336: deba@336: function update_begin() { deba@336: ((TOTAL_FILES++)) deba@336: CHANGED=NO deba@336: WARNED=NO deba@336: } deba@336: deba@336: function update_end() { deba@336: if [ $CHANGED == YES ] deba@336: then deba@336: ((++CHANGED_FILES)) deba@336: fi deba@336: if [ $WARNED == YES ] deba@336: then deba@336: ((++WARNED_FILES)) deba@336: fi deba@336: } deba@336: deba@336: function check_action() { kpeter@353: if [ "$3" == 'tabs' ] kpeter@353: then kpeter@601: if echo $2 | grep -q -v -E 'Makefile\.am$' kpeter@601: then kpeter@601: PATTERN=$(echo -e '\t') kpeter@601: else kpeter@601: PATTERN=' ' kpeter@601: fi kpeter@353: elif [ "$3" == 'trailing spaces' ] kpeter@353: then kpeter@353: PATTERN='\ +$' kpeter@353: else kpeter@353: PATTERN='*' kpeter@353: fi kpeter@353: deba@336: if ! diff -q $1 $2 >/dev/null deba@336: then kpeter@353: if [ "$PATTERN" == '*' ] kpeter@353: then kpeter@353: diff $1 $2 | grep '^[0-9]' | sed "s|^\(.*\)c.*$|$2:\1: check failed: $3|g" | kpeter@353: sed "s/:\([0-9]*\),\([0-9]*\):\(.*\)$/:\1:\3 (until line \2)/g" kpeter@353: else kpeter@353: grep -n -E "$PATTERN" $2 | sed "s|^\([0-9]*\):.*$|$2:\1: check failed: $3|g" kpeter@353: fi kpeter@353: FAILED=YES deba@336: fi deba@336: } deba@336: deba@336: function check_warning() { kpeter@341: if [ "$2" == 'long lines' ] kpeter@341: then kpeter@353: grep -n -E '.{81,}' $1 | sed "s|^\([0-9]*\):.*$|$1:\1: warning: $2|g" kpeter@341: else kpeter@353: echo "$1: warning: $2" kpeter@341: fi deba@336: WARNED=YES deba@336: } deba@336: deba@336: function check_init() { deba@336: echo Check source files... deba@336: FAILED_FILES=0 deba@336: WARNED_FILES=0 deba@336: TOTAL_FILES=0 deba@336: } deba@336: deba@336: function check_done() { deba@336: echo $FAILED_FILES out of $TOTAL_FILES files has been failed. alpar@337: echo $WARNED_FILES out of $TOTAL_FILES files triggered warnings. deba@336: kpeter@411: if [ $WARNED_FILES -gt 0 -o $FAILED_FILES -gt 0 ] deba@336: then deba@336: if [ "$WARNING" == 'INTERACTIVE' ] deba@336: then kpeter@411: echo -n "Are the files with errors/warnings acceptable? (yes/no) " deba@336: while read answer deba@336: do deba@336: if [ "$answer" == 'yes' ] deba@336: then deba@336: return 0 deba@336: elif [ "$answer" == 'no' ] deba@336: then deba@336: return 1 deba@336: fi kpeter@411: echo -n "Are the files with errors/warnings acceptable? (yes/no) " deba@336: done deba@336: elif [ "$WARNING" == 'WERROR' ] deba@336: then deba@336: return 1 deba@336: fi deba@336: fi deba@336: } deba@336: deba@336: function check_begin() { deba@336: ((TOTAL_FILES++)) deba@336: FAILED=NO deba@336: WARNED=NO deba@336: } deba@336: deba@336: function check_end() { deba@336: if [ $FAILED == YES ] deba@336: then deba@336: ((++FAILED_FILES)) deba@336: fi deba@336: if [ $WARNED == YES ] deba@336: then deba@336: ((++WARNED_FILES)) deba@336: fi deba@336: } deba@336: deba@336: deba@336: deba@336: # checks deba@336: deba@336: function header_check() { deba@336: if echo $1 | grep -q -E 'Makefile\.am$' deba@336: then deba@336: return deba@336: fi deba@336: 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@538: * Copyright (C) 2003-"$(hg_year $1)" 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@336: 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@336: ) >$TMP_FILE alpar@208: deba@336: "$ACTION"_action "$TMP_FILE" "$1" header alpar@38: } alpar@38: deba@336: function tabs_check() { deba@336: if echo $1 | grep -q -v -E 'Makefile\.am$' deba@336: then deba@336: OLD_PATTERN=$(echo -e '\t') deba@336: NEW_PATTERN=' ' deba@336: else deba@336: OLD_PATTERN=' ' deba@336: NEW_PATTERN=$(echo -e '\t') deba@336: fi alpar@208: TMP_FILE=`mktemp` deba@336: cat $1 | sed -e "s/$OLD_PATTERN/$NEW_PATTERN/g" >$TMP_FILE alpar@38: deba@336: "$ACTION"_action "$TMP_FILE" "$1" 'tabs' alpar@208: } alpar@208: deba@336: function spaces_check() { alpar@208: TMP_FILE=`mktemp` deba@336: cat $1 | sed -e 's/ \+$//g' >$TMP_FILE alpar@208: kpeter@340: "$ACTION"_action "$TMP_FILE" "$1" 'trailing spaces' alpar@208: } alpar@208: deba@336: function long_lines_check() { deba@336: if cat $1 | grep -q -E '.{81,}' alpar@208: then deba@336: "$ACTION"_warning $1 'long lines' alpar@208: fi alpar@208: } alpar@208: deba@336: # process the file deba@336: deba@336: function process_file() { kpeter@353: if [ "$ACTION" == 'update' ] kpeter@353: then kpeter@353: echo -n " $ACTION $1..." kpeter@353: else kpeter@353: echo " $ACTION $1..." kpeter@353: fi deba@336: deba@336: CHECKING="header tabs spaces long_lines" deba@336: deba@336: "$ACTION"_begin $1 deba@336: for check in $CHECKING alpar@38: do deba@336: "$check"_check $1 alpar@38: done deba@336: "$ACTION"_end $1 kpeter@353: if [ "$ACTION" == 'update' ] kpeter@353: then kpeter@353: echo kpeter@353: fi deba@336: } deba@336: deba@336: function process_all { deba@336: "$ACTION"_init deba@336: while read file alpar@38: do deba@336: process_file $file deba@336: done < <($FILES) deba@336: "$ACTION"_done deba@336: } deba@336: deba@336: while [ $# -gt 0 ] deba@336: do deba@336: deba@336: if [ "$1" == '--help' ] || [ "$1" == '-h' ] deba@336: then deba@336: echo -n \ deba@336: "Usage: deba@336: $0 [OPTIONS] [files] deba@336: Options: deba@336: --dry-run|-n alpar@337: Check the files, but do not modify them. deba@336: --interactive|-i alpar@337: If --dry-run is specified and the checker emits warnings, alpar@337: then the user is asked if the warnings should be considered alpar@337: errors. deba@336: --werror|-w alpar@337: Make all warnings into errors. deba@336: --all|-a kpeter@340: Check all source files in the repository. deba@336: --modified|-m alpar@337: Check only the modified (and new) source files. This option is alpar@337: useful to check the modification before making a commit. deba@336: --changed|-c deba@336: Check only the changed source files compared to the parent(s) of alpar@337: the current hg node. This option is useful as hg hook script. alpar@337: To automatically check all your changes before making a commit, alpar@337: add the following section to the appropriate .hg/hgrc file. deba@336: deba@336: [hooks] deba@336: pretxncommit.checksources = scripts/unify-sources.sh -c -n -i deba@336: deba@336: --help|-h deba@336: Print this help message. deba@336: files kpeter@340: The files to check/unify. If no file names are given, the modified kpeter@340: source files will be checked/unified (just like using the kpeter@340: --modified|-m option). deba@336: " deba@336: exit 0 deba@336: elif [ "$1" == '--dry-run' ] || [ "$1" == '-n' ] deba@336: then kpeter@340: [ -n "$ACTION" ] && echo "Conflicting action options" >&2 && exit 1 deba@336: ACTION=check deba@336: elif [ "$1" == "--all" ] || [ "$1" == '-a' ] deba@336: then kpeter@340: [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1 deba@336: FILES=all_files deba@336: elif [ "$1" == "--changed" ] || [ "$1" == '-c' ] deba@336: then kpeter@340: [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1 deba@336: FILES=changed_files deba@336: elif [ "$1" == "--modified" ] || [ "$1" == '-m' ] deba@336: then kpeter@340: [ -n "$FILES" ] && echo "Conflicting target options" >&2 && exit 1 deba@336: FILES=modified_files deba@336: elif [ "$1" == "--interactive" ] || [ "$1" == "-i" ] deba@336: then kpeter@340: [ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1 deba@336: WARNING='INTERACTIVE' deba@336: elif [ "$1" == "--werror" ] || [ "$1" == "-w" ] deba@336: then kpeter@340: [ -n "$WARNING" ] && echo "Conflicting warning options" >&2 && exit 1 deba@336: WARNING='WERROR' kpeter@340: elif [ $(echo x$1 | cut -c 2) == '-' ] deba@336: then deba@336: echo "Invalid option $1" >&2 && exit 1 deba@336: else deba@336: [ -n "$FILES" ] && echo "Invalid option $1" >&2 && exit 1 deba@336: GIVEN_FILES=$@ deba@336: FILES=given_files deba@336: break deba@336: fi deba@336: deba@336: shift deba@336: done deba@336: deba@336: if [ -z $FILES ] deba@336: then deba@336: FILES=modified_files alpar@38: fi deba@336: deba@336: if [ -z $ACTION ] deba@336: then deba@336: ACTION=update alpar@208: fi deba@336: deba@336: process_all