#! /bin/bash

## Run uncrustify on all arguments.
##
## Arguments can be directories, in which case all *.cc and *.h in the
## given directories are selected (recursing into subdirectories).
## If no args are given, use the current directory.
##
## Reports statistics on all files where uncrustify changed the formatting.
## Does not report statistics for files where no changes are made.
##
## CAREFUL: The files are modified in place. This may mess up your
## code. You've been warned.

## Performance notes:
##
## On my machine, as of this writing, running this on the complete
## search code takes about 1.5 seconds, which is about 10 times longer
## than just running
##
##     uncrustify (options) {*,*/*}.{cc,h}
##
## There are two sources of overhead:
## 1. calling uncrustify separately for each source
## 2. the before/after comparison to see what was changed by uncrustify
##
## The reason why we have both of these is that it allows us to give
## detailed statistics on what happened. The before/after diffing
## itself introduces a factor 2 of overhead; the rest is due to
## calling uncrustify again for each argument. I think we can live
## with this for now.

CONFIG="$(dirname "$0")/../.uncrustify.cfg"

function run-on-arg {
    if [ -f "$1" ]; then
        run-on-file "$1"
    else
        for srcfile in $(find "$1" \( -name \*.h -o -name \*.cc \) -type f); do
            run-on-file "$srcfile"
        done
    fi
}

function run-on-file {
    BEFORE=$(cat "$1")
    uncrustify -L 1 --replace --no-backup -c "$CONFIG" "$1"
    DIFF=$(diff <(echo "$BEFORE") "$1")
    if [[ $? != 0 ]]; then
        ## This counts how many files start with "<" in the diff,
        ## i.e., how many "old" lines disappeared/changed. This means
        ## that it won't report lines *added* by uncrustify, so it's
        ## possible that we get an output "changing 0 lines", which
        ## means that the only changes were additions of blank lines.
        CHANGED=$(echo "$DIFF" | grep -c "^<")
        echo uncrustified "$1", changing $CHANGED lines.
    fi
}

if [[ $# == 0 ]]; then
    run-on-arg .
else
    for arg in "$@"; do
        run-on-arg "$arg";
    done
fi
