#!/bin/sh
#
# track.sh -- keep track of what you are changing in crappy VC systems.
# Copyright (C) 2006  Casey Marshall <csm@gnu.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

if [ $# -lt 2 ]; then
    echo "usage: track co|ci|stat [--help] file [file ...]"
    exit 1
fi

function co_usage()
{
    echo "usage: track checkout|co file [file ...]"
    echo
    echo "\"Check out\" a file. This will, for each file, change the permissions"
    echo "so you can write the file, and will ask you to enter a quick note"
    echo "to explain why you are checking out this file."
    echo
    echo "If any file given is already checked out, you will be asked to augment"
    echo "the change note for that file."
}

function ci_usage()
{
    echo "usage: track ci file [file ...]"
    echo
    echo "\"Check in\" a file. This will, for each file, change the permissions"
    echo "so you can't write the file, and will save the current change notes"
    echo "(if any) of that file to 'file.changes'."
}

function st_usage()
{
    echo "usage: track stat file [file ...]"
    echo
    echo "Display the current tracked status of each file, along with the current"
    echo "change notes, if any."
}

function checkin()
{
    if [ "$1" = "--help" -o "$1" = "-h" ]; then
        ci_usage
        exit
    fi

    while [ $# -gt 0 ]; do
        file="$1"
        shift
        if [ \! -f "$file" ] ; then
            echo $file: no such file.
            exit 1
        fi
        dir=$(dirname "$file")
        fname=$(basename "$file")
        test -f "$dir/.track/$fname" && mv "$dir/.track/$fname" "${file}.changes"
        test -w "$file" && chmod u-w "$file"
    done
}

function checkout()
{
    if [ "$1" = "--help" -o "$1" = "-h" ]; then
        co_usage
        exit
    fi

    ed=$EDITOR
    if [ "$ed" = "" ]; then
        ed=$VISUAL
    fi
    if [ "$ed" = "" ]; then
        echo "track: Neither \$EDITOR nor \$VISUAL are set."
        exit 1
    fi

    while [ $# -gt 0 ]; do
        file="$1"
        shift
        if [ \! -f "$file" ] ; then
            echo $file: no such file.
            exit 1
        fi
        dir=$(dirname "$file")
        fname=$(basename "$file")
        test -d "$dir/.track" || mkdir "$dir/.track" || exit 1
        test -w "$file" || chmod u+w "$file" || exit 1
        # FIXME use better temp file name.
        tmpfile="/tmp/track-$fname"
        echo "track: Please enter (or augment) the change notes for this file." > "$tmpfile"
        echo "track: Lines that begin with 'track:' will be discarded." >> "$tmpfile"
        echo "track: file: $file" >> "$tmpfile"
        echo >> "$tmpfile"
        test -f "$dir/.track/$fname" && cat "$dir/.track/$fname" >> "$tmpfile"
        $ed "$tmpfile"
        grep -v '^track:' "$tmpfile" > "$dir/.track/$fname"
        rm "$tmpfile"
    done
}

function status()
{
    if [ "$1" = "--help" -o "$1" = "-h" ]; then
        st_usage
        exit
    fi

    while [ $# -gt 0 ]; do
        file="$1"
        shift
        if [ \! -f "$file" ] ; then
            echo $file: no such file.
            exit 1
        fi
        dir=$(dirname "$file")
        fname=$(basename "$file")
        if [ -w "$file" ]; then
            echo $file is writable.
        else
            echo $file is not writable.
        fi
        if [ -f "$dir/.track/$fname" ]; then
            echo "Change notes:"
            cat "$dir/.track/$fname"
        fi
    done
}

case "$1" in
    ci|checkin)
        shift
        checkin "$@"
        st=$?
        ;;

    co|checkout)
        shift
        checkout "$@"
        st=$?
        ;;

    st|stat|status)
        shift
        status "$@"
        st=$?
        ;;
esac

exit $st
