#!/usr/bin/env /bin/bash
#!/bin/bash -x
#
# Copyright (C) 2006 - 2007, Intel Corporation
#
PROJECT="iwlwifi"
DOCUMENTATION="README.${PROJECT} INSTALL ISSUES"
unset VERSION
unset SNAPSHOT

commit=1
unset ignore_uncommitted
unset leave_staging

function usage() {
[ "$1" ] && echo "Invalid argument: $1"
    cat <<EOF
usage: make_snapshot [options] VERSION"
options:
    --no-commit
    --ignore-uncommitted
    --leave-staging
EOF
    return 1
}

function check_args()
{
    unset args

    while [ "$1" ]; do
	arg=${1/--}
	[ "$arg" ] || arg=${1/-}
	[ "$arg" == "$1" ] && {
	    args="$args $1"
	    shift
	    continue
	}

	case $arg in
	    "no-commit" | "n") 
		unset commit
		shift
		;;

	    "ignore-uncommitted" | "i")
		ignore_uncommitted=1
		shift
		;;

	    "leave-staging" | "l")
		leave_staging=1
		shift
		;;

	    *)  usage $arg
		return 1
		;;
	esac
    done

    if [ "$args" ]; then
	args=($args)
	VERSION=${args[0]}
    else
	VERSION=$(grep -m 1 "$IWLWIFI_VERSION \".*\"" origin/iwl4965-base.c | 
	    sed -e "s#.*\"\([^\"]*\)\".*#\1#g")
    fi

    SNAPSHOT="${PROJECT}-${VERSION}"

    return 0
}

function is_version_updated()
{
    grep -m 1 -q "$IWLWIFI_VERSION \"${1}k\"" origin/iwl4965-base.c
}

function update_version_stamp()
{
    # Update the repository with version stamped entries
    ver="IWLWIFI_VERSION"
    if ! is_version_updated ${1}; then
	echo "Updating version stamp to ${1}"
	# 4965
	sed -i -e "s#$ver \"[^\"]*\"#$ver \"${1}k\"#g" \
	    origin/iwl4965-base.c || return 3
	cg-diff origin/iwl4965-base.c > /dev/null
	# 3945
	sed -i -e "s#$ver \"[^\"]*\"#$ver \"${1}k\"#g" \
	    origin/iwl3945-base.c || return 3
	cg-diff origin/iwl3945-base.c > /dev/null
	if [ "$(git-diff-files origin/iwl4965-base.c)" -a "$(git-diff-files origin/iwl3945-base.c)" ]; then
	    cg-commit -s -m"iwlwifi: Update iwlwifi version stamp to ${1}" \
		origin/iwl4965-base.c origin/iwl3945-base.c || return 4
	fi
    fi
}

function update_documentation()
{
    VERSION="${1}"
    for i in ${DOCUMENTATION}; do
	echo "Updating documentation: ${i}..."
	VERSION="$1" . stubs/${i} > ${i}
    done

    cg-diff ${DOCUMENTATION} > /dev/null
    changed=$(git-diff-files -q ${DOCUMENTATION} | 
	while read mode_old mode_new sha1_old sha1_new mode file; do
	    echo $file
	    done)

    if [ "$changed" ] && [ "$commit" ]; then
	cg-commit -s -m"Committing collateral updates to ${1}" $changed ||
	return 8
    fi

    return 0
}

function remove_version_postfix()
{
    ver="IWLWIFI_VERSION"
    sed -i -e "s#$ver \"[^\"]*\"#$ver \"${1}\"#g" \
	staging/${SNAPSHOT}/origin/iwl4965-base.c
    sed -i -e "s#$ver \"[^\"]*\"#$ver \"${1}\"#g" \
	staging/${SNAPSHOT}/origin/iwl3945-base.c
}

function build()
{
    files=$(grep -r "^[^/[:space:]]" FILES | sed -e "s:\([^ \t]*\).*:\1:g")
    # Ensure that iwlwifi repository has been updated with any changes.
    cg-diff $files > /dev/null
    changed=$(git-diff-files -q $files | 
	while read mode_old mode_new sha1_old sha1_new mode file; do
	    echo $file
	    done)
    if [ "$changed" ] && [ ! "$ignore_uncommitted" ]; then
	cat <<EOF
Uncommitted changes detected in:

$changed

You must commit your changes prior to building a snapshot.

EOF

	unset doc_changed
	for file in $changed; do 
		if [ "${DOCUMENTATION//${file}}" != "${DOCUMENTATION}" ]; then
			doc_changed="$doc_changed $file"
		fi
	done
	if [ "$doc_changed" ]; then
		cat <<EOF
Some of the above changes are in the collateral.  You should not edit 
the collateral in the main project directory as it is dynamically 
generated by the make_snapshot script.  If you wish to change these 
files, you should instead update the files in the 'snapshot' 
directory.  

To see the current differences you can run:

	% cg-diff $doc_changed

You can try to automatically apply the patches via:

	% cg-diff $doc_changed | patch -p1 -d snapshot

If that succeeds, you can revert the files in the currenct directory 
via:

	% cg-diff $doc_changed | patch -p1 -R

Once you do the above, after creating a new snapshot you should check 
the regenerated contents of the files.
EOF
	fi
	return 2
    fi

    # Update documentation
    update_documentation $1

    if [ "$commit" ]; then
	update_version_stamp $1 || return $?
	
	git-ls-tree HEAD $files | while read mode type sha1 file; do 
	    [ "$sha1" ] && [ "$file" ] && echo $sha1 $file
	done > staging/${SNAPSHOT}/GIT_SHA1 || return 5
	
	cat staging/${SNAPSHOT}/GIT_SHA1 || return 6
    else
	if ! is_version_updated ${1}; then
	    cat <<EOF
WARNING:  Invoked with --no-commit; the snapshot being created will not 
have the version number updated to ${1}.  Do not distribute the 
generated snapshot beyond -pre testing.
EOF
	fi
    fi # commit-run

    cp -a --parents $files staging/${SNAPSHOT}/ || return 7
    
    # Remove the 'k' postfix from the version string for external
    # snapshots...
    remove_version_postfix $1 || return $?
    
    # Cleanup the snapshot sources
    # make -s -C staging/${SNAPSHOT} codingstyle || return 9
    
    rm -f $(find staging/${SNAPSHOT} -name "*.orig")
    rm -f $(find staging/${SNAPSHOT} -name "*~")
}

function make_snapshot()
{
	if [ -d staging ]; then
	    rm -rf staging || return 1
	fi
	mkdir staging || return 1

	echo "Building stage for ${SNAPSHOT}"
	mkdir -p staging/${SNAPSHOT}
	build ${1} || return 1

	# Ensure build target is clean
	echo "Cleaning snapshot..."
	make -C staging/${SNAPSHOT} clean > /dev/null 2>&1

	echo "Building tarball..."
	[ ! -d distros ] && mkdir distros
	tar -C staging -czvf distros/${SNAPSHOT}.tgz ${SNAPSHOT}

	[ "$commit" ] || return 0

	unset doc_updated
	files=$(grep -r "^[^/ \t]" FILES | sed -e "s:\([^ \t]*\).*:\1:g")
	cg-diff $files > /dev/null
	changed=$(git-diff-files -q $files | 
	    while read mode_old mode_new sha1_old sha1_new mode file; do
		if [ "${DOCUMENTATION//${file}}" == "${DOCUMENTATION}" ]; then
		    echo $file
		else
		    doc_updated=1
		fi
		done)
	
	[ "$changed" ] && {
	    cat <<EOF

Final commit can not be performed while ignoring other changes via
--ignore-uncommitted.  You must resolve those prior changes before 
committing and tagging a snapshot.  Files that must be resolved:

$changed

EOF
	    return 1
	}

	[ "$doc_updated" ] && {
	    echo "Comitting snapshot as ${SNAPSHOT}."
	    cg-commit -s -m"Auto-commit and tag as ${SNAPSHOT}." $changed || 
	    return 10
	}

	echo "Copying master as tag ${SNAPSHOT}."
	git tag ${SNAPSHOT}
}

function cleanup()
{
	[ ! "$leave_staging" ] && rm -rf staging
}

function update_web_mirror()
{
	file="${SNAPSHOT}.tgz"

	[ "$commit" ] || return 0

	[ ! -d web/downloads ] && mkdir -p web/downloads

	for i in $DOCUMENTATION; do 
	    cp $i web/$i
	done

	[ ! -d web/releases ] && mkdir -p web/releases

	cat <<EOF > web/releases/${SNAPSHOT}.git
md5sum of ${file}: $(output=$(md5sum distros/${file}) ; echo ${output/distros*})
git head: $(cat .git/refs/heads/master)
git sha1 of contents:
$(cat staging/${SNAPSHOT}/GIT_SHA1)
EOF

	cat << EOF >  web/downloads/${file}
http://prdownloads.sourceforge.net/${PROJECT}/${file}?download
$(output=$(md5sum distros/${file}) ; echo ${output/distros\/})
EOF
}

check_args $@ && 
make_snapshot $VERSION && 
update_web_mirror $VERSION && 
cleanup

