#! /bin/sh

revision=`echo '$Revision: 1.1 $' | sed -e 's/[a-zA-Z \t$:]//g'`

generate_patch_script_head()
{
    _pre_req=$1
    _post_req=$2
    _name=$3
    _files=$4
    _description_file="$5"
    _patch_filename="$6"
    _patch_date=`date -u`

    # patch-specific script info
    cat <<EOF
#! /bin/sh
prereq=$_pre_req
postreq=$_post_req
name=$_name
files="$_files"
revision="$revision"
patch_filename="$_patch_filename"
patch_date="$_patch_date"
EOF
    if [ -r "$_description_file" ]; then
       echo 'description=`cat <<"EOF"'
       cat $_description_file
       echo 'EOF'
       echo '`'
    else
       echo 'description="*no description*"'
    fi

    # generic patch info
    cat <<"EOF"
patch_cmd="patch"
remove=0

usage() {
    echo "Usage: $name [--remove] directory"
    echo "    install or remove the patch to/from the specified directory"
    echo "       $name --name"
    echo "    print out the patch name"
    echo "       $name --prereq"
    echo "    print out globus patchlevel the patch applies to"
    echo "       $name --postreq"
    echo "    print out globus patchlevel the patch results in"
    echo "       $name --description"
    echo "    print out a description of changes contained in the patch"
    echo "       $name --files"
    echo "    print out a list of the files modified by the patch"
    echo "       $name --notes"
    echo "    print out most of the above information"
    echo "Patch file generated by globus-generate-patch $revision"
    exit 1
}
 
print_description()
{
    echo "This patch addresses the following issues";
    echo "";
    echo "$description";
    echo ""
    echo "After applying this patch, your source tree will be at patch level";
    echo "$postreq";
    echo ""
}

print_files()
{
    echo "This patch updates the following files:";
    echo "$files"
    echo ""
}

print_generator()
{
    echo "This patch was created by globus-generate-patch $revision"
}

if [ $# = 1 ] && [ $1 = "--name" ]; then
    echo "$name";
    exit 0;
fi

if [ $# = 1 ] && [ $1 = "--postreq" ]; then
    echo "$postreq";
    exit 0;
fi

if [ $# = 1 ] && [ $1 = "--prereq" ]; then
    echo "$prereq";
    exit 0;
fi

if [ $# = 1 ] && [ $1 = "--description" ]; then
    print_description
    exit 0;
fi

if [ $# = 1 ] && [ $1 = "--files" ]; then
    print_files
    exit 0;
fi

if [ $# = 1 ] && [ $1 = "--notes" ]; then
    echo "$patch_filename ($patch_date)"
    echo ""
    print_description
    print_files
    echo
    print_generator
    exit 0;
fi

if [ $# = 2 ] && [ $1 = "--remove" ]; then
   patch_cmd="patch -R";
   remove=1
   shift;
fi

if [ $# != 1 ]; then
    usage;
fi

globus_dir=$1

if [ ! -d "${globus_dir}" ] || [ ! -r "${globus_dir}/VERSION" ]; then
   echo "Invalid globus directory $globus_dir"
   usage;
fi

# Verify patch version is compatible
prev=`cat ${globus_dir}/VERSION`

ok=0
if [ "$remove" = 0 ] && [ "$prev" = "$prereq" ] ; then
   ok=1;
fi

if [ "$remove" = 1 ] && [ "$prev" = "$postreq" ] ; then
   ok=1;
fi

if [ $ok = 0 ]; then
    if [ "$remove" = 1 ]; then
	echo "Cannot remove patch, because version $prev != $postreq"
	exit 1
    else
	echo "Cannot install patch, because version $prev != $prereq"
	exit 1
    fi
fi

cd $globus_dir
EOF
}

generate_patch_script_tail()
{
    _name=$1
    echo "\$patch_cmd -p0 <<\"end_of_patch_${_name}\""
}

generate_creates()
{
    _diff=$1
    echo "# If files are added, patch may fail, so add them (use the default"
    echo "# permissions of umask & 0700)"
    echo 'if [ "$remove" = 0 ]; then'

    awk < "${_diff}" \
    '/^Index: / { filename=$2; }
    /^diff -N/ {
       printf("    touch %s\n", filename);
       printf("    chmod u+rwx %s\n", filename);
     }' 
    echo "fi"
}

generate_removes()
{
    _diff=$1
    echo "# If files are removed, patch may leave them around."

    echo 'if [ "$remove" = 1 ]; then'
    awk < "$_diff" \
    '/^Index: / { filename=$2; }
    /^diff -N/ {
       printf("    rm -f %s\n", filename);
     }'
    echo "fi"
}

make_diff()
{
    _tag1=$1
    _tag2=$2
    _name=$3

    if [ "${_tag2}" = "-" ]; then
	_tag2_param=""
    else
	_tag2_param="-r $_tag2"
    fi
    cvs diff -kk -r $_tag1 $_tag2_param -N 2> /dev/null 
    echo "end_of_patch_${_name}"
}

check_tag()
{
    _tag=$1
    cvs log VERSION | awk "/^symbolic_names:\$/ { check=1; }
			   /^\t${_tag}\$/ && check==1 { exit 0; }
			   /^keyword_substitution:/ { exit 1; }"
    return $?
}

die()
{
    echo "$*"
    exit 1;
}

usage()
{
    echo "Usage: $0 prev_tag new_tag patch_file [description file]"
    exit 1
}

# main()
{
    if [ $# -lt 3 ]; then
	usage
    fi

    prev_tag=$1
    shift;
    new_tag=$1
    shift
    patch_file=$1
    shift
    description_file=$1

    check_tag "${prev_tag}" || die "Invalid tag $prev_tag"
    [ "${new_tag}" = "-" ] || check_tag "${new_tag}" || die "Invalid tag $prev_tag"

    make_diff "${prev_tag}" "${new_tag}" \
		  "${prev_tag}-${new_tag}" > \
		  "globus-patch-${prev_tag}-${new_tag}".diff

    files=`awk < "globus-patch-${prev_tag}-${new_tag}".diff \
	      '/^Index:/ {printf("    %s\n", $2);}'`
    generate_patch_script_head $prev_tag $new_tag \
			       globus-patch-${prev_tag}-${new_tag} \
			       "$files" \
			       "$description_file" \
			       "$patch_file"> \
	"$patch_file"

    generate_creates "globus-patch-${prev_tag}-${new_tag}".diff \
		  >> "$patch_file"

    generate_patch_script_tail globus-patch-${prev_tag}-${new_tag} >> \
	"$patch_file"

    cat "globus-patch-${prev_tag}-${new_tag}".diff >> \
	"$patch_file"

    generate_removes "globus-patch-${prev_tag}-${new_tag}".diff >> \
	"$patch_file"
    chmod a+x "$patch_file"
}
