#!/bin/bash
#------------------------------------------------------------------------------

set -u

#------------------------------------------------------------------------------
# This broker filter script limits commands of a given type to one process
# running at a time for the same user.  It relies on 'p4 montior' having been
# enabled with 'p4 configure set monitor=1' ( or higher than 1).
#
# This is called by the 'p4broker' process.  The p4broker provides an array
# of fields on STDIN, e.g. "command: populate" and "user: joe", which get
# parsed to inform the business logic of this script.
#
# This is enabled by adding a block like the following to a broker config
# file, with this example limiting the 'p4 populate' command:
#------------------------------------------------------------------------------
# command: ^populate$
# {
#     action  = filter;
#     execute = /p4/common/bin/triggers/p4broker_one_per_user.sh;
# }
#------------------------------------------------------------------------------
#
# If this script encounters errors, such as not being able to parse the input
# properly, it logs the errors and silently exits, so as not to interrupt
# user interactions with the server unduly.
function log () { echo -e "$ThisScript v$Version $Timestamp: $*" >> "$Log"; }

declare ThisScript=${0##*/}
declare Version=1.1.0
declare Cmd=Unset
declare User=Unset
declare Timestamp=
declare Log=
declare RunningCmd=

Log="${LOGS:-/tmp}/p4broker_one_per_user.log"
Timestamp="$(date +'%Y/%m/%d:%H:%M:%S')"

while read -r line; do
   [[ "$line" == "command:"* ]] && Cmd="${line#command: }"
   [[ "$line" == "user:"* ]] && User="${line#user: }"
done

if [[ "$Cmd" == Unset || "$User" == Unset ]]; then
   log "Error: Couldn't get cmd/user ($Cmd/$User) from input. Ignoring."
   echo -e "action: PASS\\n"
   exit 0
fi

# Use 'p4 monitor show -ael' to determine if the given user has another command of the
# same type running.
log "Info: Looking for command $Cmd by user $User in this output:"
RunningCmd="$("$P4BIN" monitor show -ael 2>/dev/null | grep -E " R $User .* populate " 2>/dev/null)"

if [[ -z "$RunningCmd" ]]; then
   log "PASS for $Cmd command by user $User."
   echo -e "action: PASS\\n"
   exit 0
else
   log "REJECT for $Cmd command by user $User, another command is already running."
   echo -e "action: REJECT"
   echo -e "message: There is already one $Cmd command running for user $User. Please wait until that completes before starting another."
   exit 1
fi

exit 0
