#!/bin/bash
#
# Usage: t4verify.sh [-y] [-full]
#
#  -y    Actually perform the verify instead of printing usage. 
#  -full Verify all depot files, not just those that exist on disk
#
# Verifies the perforce depot files via p4 verify.
#
# Verification compares hashes stored in the database files with the actual
# depot files and is used to detect corruption of revisioned files.
#
# This verification script can operation in one of two modes.  The first
# mode is used by default, and scans the file store to determine which
# files exist on disk.  It then translates the filestore names into depot
# syntax and requests that these files be verified.  Due to lazy branching,
# this may be much faster than attempting to verify all files that exist
# in the database.
#
# The second mode of verification is to simply verify all files by passing
# wildcards to the Perforce server.  This is done depot by depot and in
# sections under each depot to avoid consuming too much memory on the 
# server while the verification is ran.  This mode is much slower, and used
# only when the -full option is passed to the script.
#
# This script requires the following environment variables to be set:
#
#  P4USER, P4PASSWD, P4ROOT
#
# Author: Michael McTernan, www.mcternan.co.uk
#
# END OF USAGE

function showusage
{
  if [ -n "$1" ] ; then
    LINES=`grep -n -m 1 "# END OF USAGE" $1 | cut -d ':' -f 1`
    let LINES=$LINES-1
    head -n $LINES $1 | grep -v "^#!/bin/bash" | sed "s/# \?//"
  else
    echo "Script error - showusage called without argument."
  fi
}


if [ "$1" != "-y" ] ; then
  showusage $0
  exit 1
else
  shift
fi

P4="p4 -u $P4USER -P $P4PASSWD"

if [ "$1" == "-full" ] ; then

  # Iterate the depots
  for DEPOT in `$P4 -Ztag -s depots | grep "info1: name" | cut -d " " -f  3`; do

    # Log the start of the verify
    logger -p info -t t4verify "Started verification of $DEPOT"
  
    # Add hashes to the first 1000 files without hashes
    $P4 verify -m 1000 -qu //$DEPOT/... 2>&1 | grep -v " - file(s) already have digests."

    # Check any files right under the depot
    if $P4 -s files //$DEPOT/* | grep -q "^info: " ; then
      $P4 verify -q //$DEPOT/*
    fi

    # Now each directory in the depot in turn
    $P4 dirs //$DEPOT/* |
    while read DIR ; do
      $P4 verify -q "$DIR/..."
    done
  
  done
  
  # Log that verification has completed
  logger -p info -t t4verify "Verification complete (full)"

else

  LIST=`mktemp`

  for DEPOT in `$P4 -Ztag -s depots | grep "^info1: name" | cut -d " " -f 3`; do

    # Get the local mapping and remove Perforce wildcard
    DEPOTPATH=`$P4 -Ztag -s depot -o $DEPOT | grep "^info1: Map" | cut -d " " -f 3 | sed "s/\/\.\.\.$//"`

    # Create list of files to verify
    rm -f $LIST && touch $LIST
    #  Note that empty directories maybe left after binary files have been obliterated 
    cd $P4ROOT/$DEPOTPATH && find . -name "*,d" -type d -not -empty | sed "s/,[vd]$//" | sed "s/^\./\/\/$DEPOT/" > $LIST
    cd $P4ROOT/$DEPOTPATH && find . -name "*,v" -type f | sed "s/,[vd]$//" | sed "s/^\./\/\/$DEPOT/" >> $LIST

    # Log the start of the verify
    LIST_COUNT=`cat $LIST | wc -l`
    logger -p info -t t4verify "Started verification of physical files in $DEPOT ($LIST_COUNT physical files)"

    # Add hashes to the first 1000 files without hashes
    $P4 verify -m 1000 -qu //$DEPOT/... 2>&1 | grep -v " - file(s) already have digests."

    # Start the verify
    cat $LIST | $P4 -x- verify -q

  done
  
  logger -p info -t t4verify "Verification complete (physical files)"

  rm -f $LIST

fi

# END OF SCRIPT

