#!/bin/bash
#
# Homepage: http://code.google.com/p/coderev
# License: GPLv2, see "COPYING"
#
# Generate code review page of <workspace> vs <workspace>@HEAD, by using
# `codediff.py' - a standalone diff tool
#
# Usage: cd your-workspace; coderev.sh [file|subdir ...]
#
# $Id: coderev.sh 10 2008-08-23 09:02:26Z mattwyl $
PROG_NAME=$(basename $0)
BINDIR=$(cd $(dirname $0) && pwd -L) || exit 1
CODEDIFF=$BINDIR/codediff.py
function help
{
cat << EOF
Usage:
$PROG_NAME [-r revsion] [-w width] [file|subdir ...]
\`revision' is a revision number, or symbol (PREV, BASE, HEAD) in svn,
see svn books for details. Default revision is revision of your working
copy
\`width' is a number to make code review pages wrap in specific column
Default \`subdir' is working dir.
Example 1:
$PROG_NAME -w80 bin lib
Generate coderev based on your working copy, web pages wrap in column 80.
If you are working on the most up-to-date version, this is suggested way
(faster).
Example 2 (for SVN):
$PROG_NAME -r HEAD bin lib
Generate coderev based on HEAD revision (up-to-date version in repository),
this will retrive diffs from SVN server so it's slower, but most safely.
EOF
return 0
}
#################### VCS Operations Begin ####################
# Return code: 0 - Unknown, 1 - SVN, 2 - CVS
#
function detect_vcs
{
[[ -f .svn/entries ]] && return 1
[[ -f CVS/Entries ]] && return 2
return 0
}
function set_vcs_ops
{
local i=${1?}
local vcs_opt=${VCS_OPS_TABLE[i]}
eval vcs_get_banner=\${$vcs_opt[0]}
eval vcs_get_repository=\${$vcs_opt[1]}
eval vcs_get_project_path=\${$vcs_opt[2]}
eval vcs_get_working_revision=\${$vcs_opt[3]}
eval vcs_get_active_list=\${$vcs_opt[4]}
eval vcs_get_diff=\${$vcs_opt[5]}
eval vcs_get_diff_opt=\${$vcs_opt[6]}
}
# VCS Operations:
# get_banner - print banner, return 1 if not supported
# get_repository - print repository
# get_project_path - print project path without repository
# get_working_revision pathname ... - print working revision
# get_active_list pathname ... - print active file list
# get_diff [diff_opt] pathname ... - get diffs for active files
# get_diff_opt - print diff option and args
# Unknown ops just defined here, others see libxxx.sh
#
UNKNOWN_OPS=( unknown_get_banner : : : : : : )
function unknown_get_banner
{
echo "unknown"
return 1
}
VCS_OPS_TABLE=( UNKNOWN_OPS SVN_OPS CVS_OPS )
. $BINDIR/libsvn.sh || exit 1
. $BINDIR/libcvs.sh || exit 1
# Detect VCS (Version Control System) and set handler
#
detect_vcs
set_vcs_ops $?
#################### VCS Operations End ####################
# Main Proc
#
while getopts "hr:w:" op; do
case $op in
h) help; exit 0 ;;
r) REV_ARG="$OPTARG" ;;
w) CODEDIFF_OPT="-w $OPTARG" ;;
?) help; exit 1 ;;
esac
done
shift $((OPTIND - 1))
PATHNAME="${@:-.}"
BANNER=$($vcs_get_banner) || {
echo "Unsupported version control system ($BANNER)." >&2
exit 1
}
echo "Version control system \"$BANNER\" detected."
# Retrive information
#
echo "Retriving information ..."
PROJ_PATH=$($vcs_get_project_path)
WS_NAME=$(basename $PROJ_PATH)
WS_REV=$($vcs_get_working_revision $PATHNAME)
echo "Repository : $($vcs_get_repository)"
echo "Project path : $PROJ_PATH"
echo "Working revision : $WS_REV"
# Prepare file list and base source
#
TMPDIR=$(mktemp -d /tmp/coderev.XXXXXX) || exit 1
LIST="$TMPDIR/activelist"
DIFF="$TMPDIR/diffs"
BASE_SRC="$TMPDIR/$WS_NAME-base"
$vcs_get_active_list $PATHNAME > $LIST || exit 1
echo "========== Active file list =========="
cat $LIST
echo "========================================"
# Generate $BASE_SRC
#
mkdir -p $BASE_SRC || exit 1
tar -cf - $(cat $LIST) | tar -C $BASE_SRC -xf - || exit 1
echo "Retriving diffs ..."
VCS_REV_OPT=""
[[ -n $REV_ARG ]] && VCS_REV_OPT="$($vcs_get_diff_opt $REV_ARG)"
$vcs_get_diff $VCS_REV_OPT $(cat $LIST) > $DIFF || exit 1
patch -NER -p0 -d $BASE_SRC < $DIFF || exit 1
# Generate coderev
#
echo "Generating code review ..."
CODEREV=$TMPDIR/${WS_NAME}-r${WS_REV}-diff
$CODEDIFF $CODEDIFF_OPT -o $CODEREV -y -f- $BASE_SRC . < $LIST || exit 1
echo "Coderev pages generated at $CODEREV"
echo
# Cleanup
#
rm -rf $LIST $DIFF $BASE_SRC
# Copy to web host
#
[[ -r ~/.coderevrc ]] || {
echo "[*] Hint: if you want to copy coderev pages to a remote host"
echo " automatically, see coderevrc.sample"
echo
exit 0
}
. ~/.coderevrc || {
echo "Reading ~/.coderevrc failed." >&2
exit 1
}
: ${WEB_HOST?"WEB_HOST not defined."}
: ${SSH_USER?"SSH_USER not defined."}
: ${HOST_DIR?"HOST_DIR not defined."}
: ${WEB_URL?"WEB_URL not defined."}
scp -r $CODEREV ${SSH_USER}@${WEB_HOST}:$HOST_DIR/ || exit 1
echo
echo "Coderev link:"
echo "$WEB_URL/$(basename $CODEREV)"
echo
exit 0