otter 1.2.1

Otter game system; main data structures Rust crate.
Documentation
#!/bin/bash
# usage:
#   ./update-versions 0.5.0

set -e

fail () { echo >&2 "${0##*/}: error: $*"; exit 12; }

case "$1" in
-*)		fail "unknown option $1" ;;
esac

version="$1"
case "$version" in
'')         fail 'need new version number' ;;
*[^0-9.]*)  fail 'version number contains bad character' ;;
[^0-9]*)    fail 'version number starts with non-digit' ;;
esac

files=$(git ls-files :\*/Cargo.toml :Cargo.toml)
dirty=$(git status -u --porcelain $files)

if [ "x$dirty" != x ]; then
    printf >&2 "%s\n" "$dirty"
    fail 'some Cargo.toml[s] are dirty.'
fi

names=""
for f in $files; do
    name=$(perl -i~ -pe '
        BEGIN { open N, ">&STDOUT" or die $!; }
        if (m{^\[package\]\s*$}...m{^\[}) {
            $y=1 if s{^version=".*}{version="'$version'"};
            print N "$1" if m{^name="(.*)"};
        }
	if (m{^\[dependencies\]\s*$}...m{^\[}) {
            s{^(otter[-\w]*)\.path=.*}{$&\n$1.version="='$version'"};
            s{^(otter[-\w]*)\.version.*\n}{};
        }
        END {
            $y or die "appropriate line not found in '$f'";
            close N or die $!;
        }
    ' "$f")
    case "$name" in
    ''|*' '*) fail "bad name(s) for $f: $name" ;;
    esac
    names+="$name "
done

perl -i~ -pe '
    BEGIN {
        $/ = "\n\n";
        foreach my $name (qw('"$names"')) { $done{$name} = 0; }
    }
    next unless m{^\[\[package\]\]};
    next unless m{^name\s*=\s*"([-\w+]*)"\s*$}m;
    my $name = $1;
    next unless exists $done{$name};
    $done{$name}++;
    s{^(version\s*=\s*)"[^"]+"}{$1"'$version'"}m or die "$name no vsn ?";
    END {
        foreach my $name (sort keys %done) {
            die "$name missing ?" unless $done{$name} == 1;
        }
    }
' Cargo.lock

git commit -s -m "Cargo.toml: Update all versions to $version

Commit made automatically by update-versions.
" $files Cargo.lock