f | #!/bin/bash | f | #!/bin/bash |
| # | | # |
| # Homepage: http://code.google.com/p/coderev | | # Homepage: http://code.google.com/p/coderev |
| # License: GPLv2, see "COPYING" | | # License: GPLv2, see "COPYING" |
| # | | # |
| # Generate code review page of <workspace> vs <workspace>@HEAD, by using | | # Generate code review page of <workspace> vs <workspace>@HEAD, by using |
| # `codediff.py' - a standalone diff tool | | # `codediff.py' - a standalone diff tool |
| # | | # |
n | # Usage: coderev.sh [file|subdir ...] | n | # Usage: cd your-workspace; coderev.sh [file|subdir ...] |
| # | | # |
n | # $Id: coderev.sh 4 2008-08-19 05:24:24Z mattwyl $ | n | # $Id: coderev.sh 10 2008-08-23 09:02:26Z mattwyl $ |
| | | |
| PROG_NAME=$(basename $0) | | PROG_NAME=$(basename $0) |
n | | n | BINDIR=$(cd $(dirname $0) && pwd -L) || exit 1 |
| | | CODEDIFF=$BINDIR/codediff.py |
| | | |
| function help | | function help |
| { | | { |
| cat << EOF | | cat << EOF |
| | | |
| Usage: | | Usage: |
n | $PROG_NAME [-r revsion] [file|subdir ...] | n | $PROG_NAME [-r revsion] [-w width] [file|subdir ...] |
| | | |
n | \`revision' is a revision number, or symbol (PREV, BASE, HEAD), see svn | n | \`revision' is a revision number, or symbol (PREV, BASE, HEAD) in svn, |
| books for details. Default revision is revision of your working copy | | see svn books for details. Default revision is revision of your working |
| (aka. BASE) | | copy |
| | | |
| | | \`width' is a number to make code review pages wrap in specific column |
| | | |
| Default \`subdir' is working dir. | | Default \`subdir' is working dir. |
| | | |
| Example 1: | | Example 1: |
n | $PROG_NAME bin lib | n | $PROG_NAME -w80 bin lib |
| | | |
n | Generate coderev based on your working copy. If you are working on the | n | Generate coderev based on your working copy, web pages wrap in column 80. |
| most up-to-date version, this is suggested way (faster). | | If you are working on the most up-to-date version, this is suggested way |
| | | (faster). |
| | | |
n | Example 2: | n | Example 2 (for SVN): |
| $PROG_NAME -r HEAD bin lib | | $PROG_NAME -r HEAD bin lib |
| | | |
| Generate coderev based on HEAD revision (up-to-date version in repository), | | 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. | | this will retrive diffs from SVN server so it's slower, but most safely. |
| | | |
| EOF | | EOF |
| | | |
| return 0 | | return 0 |
| } | | } |
| | | |
n | | n | #################### 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 "r:h" op; do | | while getopts "hr:w:" op; do |
| case $op in | | case $op in |
n | r) REV="$OPTARG" ;; | n | |
| h) help; exit 0 ;; | | h) help; exit 0 ;; |
n | | n | r) REV_ARG="$OPTARG" ;; |
| | | w) CODEDIFF_OPT="-w $OPTARG" ;; |
| ?) help; exit 1 ;; | | ?) help; exit 1 ;; |
| esac | | esac |
| done | | done |
n | | n | shift $((OPTIND - 1)) |
| | | PATHNAME="${@:-.}" |
| | | |
n | shift $((OPTIND - 1)) | n | BANNER=$($vcs_get_banner) || { |
| SUBDIRS="$@" | | echo "Unsupported version control system ($BANNER)." >&2 |
| | | exit 1 |
| | | } |
| | | echo "Version control system \"$BANNER\" detected." |
| | | |
n | [[ -n "$REV" ]] && SVN_OPT="-r $REV" | n | # Retrive information |
| | | |
| # Get codediff path | | |
| # | | # |
n | BINDIR=$(cd $(dirname $0) && pwd -L) || exit 1 | n | |
| CODEDIFF=$BINDIR/codediff.py | | |
| | | |
| # Retrive SVN information | | |
| # | | |
| echo "Retriving SVN information ..." | | echo "Retriving information ..." |
| URL=$(svn info | grep '^URL:' | awk '{print $2}') || exit 1 | | PROJ_PATH=$($vcs_get_project_path) |
| WS_NAME=$(basename "$URL") | | WS_NAME=$(basename $PROJ_PATH) |
| WS_REV=$(svn info | grep 'Revision:' | awk '{print $2}') || exit 1 | | WS_REV=$($vcs_get_working_revision $PATHNAME) |
| BASE_REV=$(svn info $SVN_OPT | grep 'Revision:' | awk '{print $2}') || exit 1 | | echo "Repository : $($vcs_get_repository)" |
| echo "URL : $URL" | | echo "Project path : $PROJ_PATH" |
| echo "WS_REV : $WS_REV" | | echo "Working revision : $WS_REV" |
| echo "BASE_REV: $BASE_REV" | | |
| | | |
| | | |
| # Prepare file list and base source | | # Prepare file list and base source |
| # | | # |
n | LIST=$(mktemp /tmp/list.XXXXXX) || exit 1 | n | |
| DIFF=$(mktemp /tmp/diff.XXXXXX) || exit 1 | | TMPDIR=$(mktemp -d /tmp/coderev.XXXXXX) || exit 1 |
| BASE_SRC="/tmp/${WS_NAME}@${BASE_REV}" | | LIST="$TMPDIR/activelist" |
| | | DIFF="$TMPDIR/diffs" |
| | | BASE_SRC="$TMPDIR/$WS_NAME-base" |
| | | |
n | for file in $(svn st $SUBDIRS | grep '^[A-Z]' | awk '{print $2}'); do | n | $vcs_get_active_list $PATHNAME > $LIST || exit 1 |
| [[ -d $file ]] && continue | | echo "========== Active file list ==========" |
| echo $file >> $LIST || exit 1 | | cat $LIST |
| done | | echo "========================================" |
| | | |
n | echo "Active file list:" | n | # Generate $BASE_SRC |
| echo "============================" | | |
| cat $LIST | | |
| echo "============================" | | |
| | | |
| # Generate $base_src | | |
| # | | # |
| mkdir -p $BASE_SRC || exit 1 | | mkdir -p $BASE_SRC || exit 1 |
| tar -cf - $(cat $LIST) | tar -C $BASE_SRC -xf - || exit 1 | | tar -cf - $(cat $LIST) | tar -C $BASE_SRC -xf - || exit 1 |
| | | |
| echo "Retriving diffs ..." | | echo "Retriving diffs ..." |
n | | n | VCS_REV_OPT="" |
| | | [[ -n $REV_ARG ]] && VCS_REV_OPT="$($vcs_get_diff_opt $REV_ARG)" |
| svn diff $SVN_OPT $(cat $LIST) > $DIFF || exit 1 | | $vcs_get_diff $VCS_REV_OPT $(cat $LIST) > $DIFF || exit 1 |
| cat $DIFF | patch -NER -p0 -d $BASE_SRC || exit 1 | | patch -NER -p0 -d $BASE_SRC < $DIFF || exit 1 |
| | | |
| # Generate coderev | | # Generate coderev |
| # | | # |
n | CODEREV=/tmp/${WS_NAME}-diff-${BASE_REV} | n | echo "Generating code review ..." |
| cat $LIST | $CODEDIFF -o $CODEREV -w80 -y -f- $BASE_SRC . || exit 1 | | CODEREV=$TMPDIR/${WS_NAME}-r${WS_REV}-diff |
| | | $CODEDIFF $CODEDIFF_OPT -o $CODEREV -y -f- $BASE_SRC . < $LIST || exit 1 |
| echo | | |
| echo "Coderev generated under $CODEREV" | | echo "Coderev pages generated at $CODEREV" |
| echo | | echo |
| | | |
| # Cleanup | | # Cleanup |
| # | | # |
| rm -rf $LIST $DIFF $BASE_SRC | | rm -rf $LIST $DIFF $BASE_SRC |
| | | |
n | | n | # 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 |
| | | } |
| | | |
n | ############################################################################## | n | . ~/.coderevrc || { |
| # | | echo "Reading ~/.coderevrc failed." >&2 |
| # Customize your webdir to save coderev: | | exit 1 |
| # | | } |
| # 1. define WEBHOST, SSH_USER, HOST_DIR and WEBDIR | | |
| # 2. Comment out the line ":<< \__copy_to_webserver__" below | | |
| # | | |
| ############################################################################## | | |
| | | |
n | : << __copy_to_webserver__ | n | : ${WEB_HOST?"WEB_HOST not defined."} |
| | | : ${SSH_USER?"SSH_USER not defined."} |
| | | : ${HOST_DIR?"HOST_DIR not defined."} |
| | | : ${WEB_URL?"WEB_URL not defined."} |
| | | |
n | WEBHOST=example.org | n | |
| SSH_USER=me | | |
| HOST_DIR='~/public_html/coderev' | | |
| WEBDIR="http://$WEBHOST/~$SSH_USER/coderev" | | |
| | | |
| scp -r $CODEREV ${SSH_USER}@${WEBHOST}:$HOST_DIR/ || exit 1 | | scp -r $CODEREV ${SSH_USER}@${WEB_HOST}:$HOST_DIR/ || exit 1 |
| | | |
| echo | | echo |
| echo "Coderev link:" | | echo "Coderev link:" |
n | echo "$WEBDIR/$(basename $CODEREV)" | n | echo "$WEB_URL/$(basename $CODEREV)" |
| echo | | echo |
| | | |
| exit 0 | | exit 0 |
t | | t | |
| __copy_to_webserver__ | | |