#!/bin/bash
set -u
declare ShelvedCL=
declare -i ErrorCount=0
declare CfgDir=~/.config/vshelf
declare CfgFile="$CfgDir/vshelf.cfg"
declare -A Files
function msg () { echo -e "$*"; }
function errmsg () { msg "\nError: ${1:-Unknown Error}\n"; ErrorCount+=1; }
function bail () { errmsg "${1:-Unknown Error}"; exit "$ErrorCount"; }
function usage () {
msg "\nUSAGE: vshelf [<PendingCL>]
This script display diffs between current local workspace fiels in numbered
pending changelist and shelved changelist of the same number.
If no PendingCL is specified, the last PendingCL specified in the most recent
prior run of this script is used."
exit 2
}
#------------------------------------------------------------------------------
# Verify shelf. Display diffs between current local workspace fiels in numbered
# pending changelist and shelved changelist of the same number.
#
# Usage Example: vshelf 27800
#------------------------------------------------------------------------------
function vshelf () {
local shelf="${1:-}"
local -i diffCount=0
local tmpFile=
for df in $(p4 -ztag -F %depotFile% files @="$shelf"); do
# Warning: If the client spec 'View:' field contains ditto mappings,
# there will be more than one 'path' value returned by 'p4 where', with
# one entry returned per line. We rather arbitrarily choose the first
# returned path mapping (ala 'head -1'), hoping that's the correct one.
# TO DO: If possible, find a reliable way to determine which is the
# correct, or at least most likely to be correct, path mapping if ditto
# mappings are used and 'p4 where' returns more than one value.
path="$(p4 -ztag -F %path% where "$df" | head -1)"
Files[$path]=1
msg "Checking: $path"
tmpFile="${path}.${shelf}.diff.tmp"
rm -f "$tmpFile"
p4 print -q -o "$tmpFile" "${path}@=${shelf}"
if ! diff -q "${path}.$shelf.diff.tmp" "${path}"; then
msg "Warning: Differences detected for: $path"
diff "${path}.$shelf.diff.tmp" "${path}"
diffCount+=1
fi
rm -f "$tmpFile"
done
while IFS= read -r df; do
path="$(p4 -ztag -F %path% where "$df" | head -1)"
if [[ -z "${Files[$path]:-}" ]]; then
msg "Warning: File '$path' is in pending CL @$shelf but is not in the shelf."
diffCount+=1
fi
done < <(p4 -ztag change -o "$shelf" | awk '/^\.\.\. Files[0-9]+/ {print substr($0, index($0, "//"))}')
if [[ "$diffCount" -eq 0 ]]; then
msg "\nNo diffs found.\n"
else
msg "\nWarning: found $diffCount diffs. Maybe force-reshelve or replace?\n"
fi
}
# If no ShelvedCL was provided on the command line, see if we can extract the most recent
# ShelvedCL from config file.
if [[ -z "${1:-}" ]]; then
if [[ -r "$CfgFile" ]]; then
if [[ $(cat "$CfgFile") =~ ^[[:space:]]*ShelvedCL[[:space:]]*=[[:space:]]*(.*[^[:space:]]) ]]; then
ShelvedCL="${BASH_REMATCH[1]}"
[[ "$ShelvedCL" =~ ^[0-9]+$ ]] ||\
bail "Malformed ShelvedCL found in config file: $CfgFile\nContents:$(cat "$CfgFile")\n"
else
bail "Could not extract ShelvedCL from config file: $CfgFile"
fi
else
errmsg "No shelved CL provied and no previous shelves found."
usage
fi
elif [[ "$1" =~ ^[0-9]+$ ]]; then
ShelvedCL="$1"
else
usage
fi
vshelf "$ShelvedCL"
[[ -d "$CfgDir" ]] || mkdir -p "$CfgDir" || bail "Could not do: mkdir -p \"$CfgDir\""
echo "ShelvedCL=$ShelvedCL" > "$CfgFile" || errmsg "Could not update $CfgFile with ShelvedCL=$ShelvedCL"
exit "$ErrorCount"