#!/bin/bash
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Component Based Development (CBD) project, and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-cbd/view/main/LICENSE
#------------------------------------------------------------------------------
set -u
#==============================================================================
# Declarations and Environment
declare Version=1.0.6
declare -i SilentMode=0
declare -i OverwriteInstall=0
declare -i UpdateInstall=0
declare -i InstallSDPLib=0
declare -i OverallReturnStatus=0
declare OpMode=New
declare WorkshopCBDBranch=main
declare -i NO_OP=0
export CBD_HOME=/p4/common/bin/cbd
export P4CLIB=/p4/common/lib
#==============================================================================
# Local Functions
#------------------------------------------------------------------------------
# Function bail().
# Sample Usage:
# bail "Missing something important. Aborting."
# bail "Aborting with exit code 3." 3
function bail () { echo -e "\nError: ${1:-Unknown Error}\n"; exit ${2:-1}; }
#------------------------------------------------------------------------------
# Functions. The runCmd() function is similar to functions defined in SDP core
# libraries, but we need to duplicate them here since this script runs before
# the SDP is available on the machine (and we want no dependencies for this
# script.
function runCmd {
cmd=${1:-echo Testing runCmd}
desc=${2:-""}
[[ -n "$desc" ]] && echo -e "$desc"
echo Running: $cmd
if [[ $NO_OP -eq 0 ]]; then
$cmd
return $?
else
echo -e "NO_OP: Would run: $cmd"
return 0
fi
}
#------------------------------------------------------------------------------
# Function: usage (required function)
#
# Input:
# $1 - style, either -h (for short form) or -man (for man-page like format).
#------------------------------------------------------------------------------
function usage
{
declare style=${1:--h}
echo "USAGE for $THISSCRIPT v$Version:
$THISSCRIPT [-d <install_dir>] [-b <branch>>] [-o|-u] [-l] [-n] [-D]
or
$THISSCRIPT [-h|-man|-V]
"
if [[ $style == -man ]]; then
echo -e "
DESCRIPTION:
This script clones a branch of the Component Based Development (CBD)
scripts from The Workshop, a publicly available Perforce server.
See: https://swarm.workshop.perforce.com/projects/perforce-software-cbd
OPTIONS:
-d <install_dir>
Specify the installation directory, \$CBD_HOME. The default value
of $CBD_HOME aassumes CBD is deployed with the Server Deployment
Package (SDP), though CBD does not have a dependency on the SDP.
-b <branch>
Specify that CBD scripts are to be acquired from the specified
branch (e.g. main, dev, ntx64) for the CBD project in The Workshop.
-o By default, the script aborts if the \$CBD_HOME install directory
already exists. With '-o' (overwrite), the install directory
is removed if it exists to make way for a fresh install.
The '-o' and '-u' options are mutually exclusive.
-u Specify '-u' to use 'p4 fetch' to update an existing installation,
i.e. if the install directory exists already, rather than a full
'p4 clone'. If the install directory does not already exist, a
full clone is done anyway, and this argument is silently ignored
The '-o' and '-u' options are mutually exclusive.
-l Specify '-l' to also acquire the SDP lib dir, $P4CLIB, as may
be needed for scripts.
GENERAL OPTIONS:
-n NO-OP mode; shows commands that would be executed without
running commands that do anything significant.
-D Set extreme debugging verbosity.
HELP OPTIONS:
-h Display short help message
-man Display man-style help message
-V Dispay version info for this script and its libraries.
EXAMPLES:
For typical usage, no arguments are needed:
get_workshop_cbd.sh
To merely update an existing installation:
get_workshop_cbd.sh -u
To overwrite and replace an existing installation,
pulling from the dev branch:
get_workshop_cbd.sh -o -b dev
"
fi
exit 1
}
#------------------------------------------------------------------------------
# Function: get_workshop_cbd
# Install CBD to $CBD_HOME dir, which must be defined.
# Install from specified branch from The Workshop; default is 'main'.
#------------------------------------------------------------------------------
function get_workshop_cbd()
{
#echo "CALL get_workshop_cbd($*)"
declare branch=${1:-main} opMode=${2:-New}
export CBD_HOME=${CBD_HOME:-Unset}
# This should never happen ...
[[ $CBD_HOME == Unset ]] && bail "CBD_HOME is not defined."
# Deploy from a Perforce server. The user indicated should be a
# non-password user. Only read permissions are needed.
declare p4port=workshop.perforce.com:1666
declare p4user=ftp
declare remoteSpec=perforce_software-cbd_${branch}
declare fetchCmd="p4 -s -u $p4user fetch"
declare cloneCmd="p4 -s -u $p4user clone -p $p4port -r $remoteSpec"
if [[ $OpMode == Overwrite ]]; then
if [[ -d "$CBD_HOME" ]]; then
runCmd "/bin/rm -rf $CBD_HOME" "Removing existing CBD_HOME dir [$CBD_HOME] due to '-o'." ||\
bail "Failed to remove CBD_HOME dir [$CBD_HOME]."
fi
fi
if [[ $OpMode != Update ]]; then
[[ -d "$CBD_HOME" ]] && \
bail "The target install directory [$CBD_HOME] already exists."
fi
if [[ ! -d "$CBD_HOME" ]]; then
if [[ $OpMode == Update ]]; then
echo "Warning: Ignoring '-u' because \$CBD_HOME dir did not exist."
OpMode=New
fi
runCmd "/bin/mkdir -p $CBD_HOME" \
"Making CBD_HOME dir [$CBD_HOME]." ||\
bail "Failed to create dir \$CBD_HOME [$CBD_HOME]."
fi
if [[ $NO_OP -eq 0 ]]; then
cd "$CBD_HOME" ||\
bail "Failed to cd to \$CBD_HOME [$CBD_HOME]."
else
echo "NO_OP: Would cd to: $CBD_HOME"
fi
echo "Setting P4CONFIG=.p4config for cloning/fetching."
export P4CONFIG=.p4config
if [[ $OpMode == Update ]]; then
runCmd "$fetchCmd" \
"\nFetching updates from Workshop CBD in $CBD_HOME" ||\
bail "Failed to clone CBD from the Workshop."
else
runCmd "$cloneCmd" \
"\nCloning branch $branch of Workshop CBD in $CBD_HOME" ||\
bail "Failed to clone CBD from the Workshop."
fi
runCmd "p4 -s sync -f .p4ignore" \
"Force syncing CBD variant of .p4ignore, overriding default from 'p4 clone'." ||
echo "Warning: Failed to force sync CBD variant of P4IGNORE file."
return 1
}
#------------------------------------------------------------------------------
# Function: get_workshop_sdp_lib
# Install SDP lib dir to $P4CLIB (typically /p4/common/lib).
# Install from specified branch from The Workshop; default is 'main'.
#------------------------------------------------------------------------------
function get_workshop_sdp_lib()
{
#echo "CALL get_workshop_sdp_lib($*)"
declare branch=${1:-main} opMode=${2:-New}
export P4CLIB=${P4CLIB:-Unset}
# This should never happen ...
[[ $P4CLIB == Unset ]] && bail "P4CLIB is not defined."
# Deploy from a Perforce server. The user indicated should be a
# non-password user. Only read permissions are needed.
declare p4port=workshop.perforce.com:1666
declare p4user=ftp
declare remoteSpec=perforce_software-sdp_${branch}_lib
declare fetchCmd="p4 -s -u $p4user fetch"
declare cloneCmd="p4 -s -u $p4user clone -p $p4port -r $remoteSpec"
if [[ $OpMode == Overwrite ]]; then
if [[ -d "$P4CLIB" ]]; then
runCmd "/bin/rm -rf $P4CLIB" "Removing existing P4CLIB dir [$P4CLIB] due to '-o'." ||\
bail "Failed to remove P4CLIB dir [$P4CLIB]."
fi
fi
if [[ $OpMode != Update ]]; then
[[ -d "$P4CLIB" ]] && \
bail "The target install directory [$P4CLIB] already exists."
fi
if [[ ! -d "$P4CLIB" ]]; then
if [[ $OpMode == Update ]]; then
echo "Warning: Ignoring '-u' because \$P4CLIB dir did not exist."
OpMode=New
fi
runCmd "/bin/mkdir -p $P4CLIB" \
"Making P4CLIB dir [$P4CLIB]." ||\
bail "Failed to create dir \$P4CLIB [$P4CLIB]."
fi
if [[ $NO_OP -eq 0 ]]; then
cd "$P4CLIB" ||\
bail "Failed to cd to \$P4CLIB [$P4CLIB]."
else
echo "NO_OP: Would cd to: $P4CLIB"
fi
echo "Setting P4CONFIG=.p4config for cloning/fetching."
export P4CONFIG=.p4config
if [[ $OpMode == Update ]]; then
runCmd "$fetchCmd" \
"\nFetching updates from Workshop SDP lib dir in $P4CLIB" ||\
bail "Failed to clone SDP lib dir from the Workshop."
else
runCmd "$cloneCmd" \
"\nCloning branch $branch of Workshop SDP lib dir in $P4CLIB" ||\
bail "Failed to clone SDP lib dir from the Workshop."
fi
return 1
}
#==============================================================================
# Command Line Processing
declare -i shiftArgs=0
set +u
while [[ $# -gt 0 ]]; do
case $1 in
(-d) export CBD_HOME=$2; shiftArgs=1;;
(-b) WorkshopCBDBranch=$2; shiftArgs=1;;
(-o) OverwriteInstall=1; OpMode=Overwrite;;
(-u) UpdateInstall=1; OpMode=Update;;
(-l) InstallSDPLib=1;;
(-h) usage -h;;
(-man) usage -man;;
(-V) show_versions; exit 1;;
(-n) NO_OP=1;;
(-D) set -x;; # Debug; use 'set -x' mode.
(*) bail "Usage Error: Unknown arg ($1).";;
esac
# Shift (modify $#) the appropriate number of times.
shift; while [[ $shiftArgs -gt 0 ]]; do
[[ $# -eq 0 ]] && \
bail "Usage Error: Bad usage. Run '$(basename $0) -man'."
shiftArgs=$shiftArgs-1
shift
done
done
set -u
#==============================================================================
# Command Line Verification
[[ $OverwriteInstall -eq 1 && $UpdateInstall -eq 1 ]] && \
usageError "The '-o' and '-u' options are mutually exclusive."
# Ensure no whitespace is embedded in the path set in CBD_HOME.
export CBD_HOME=$(echo $CBD_HOME)
spacesCheck=$(echo $CBD_HOME|tr ' ' '\n'|wc -l)
spacesCheck=$(echo $spacesCheck)
[[ $spacesCheck != 1 ]] && \
usageError "The value specified for '-d <install_dir>' is invalid; it cannot contain spaces. Value is: [$CBD_HOME]."
#==============================================================================
# Main Program
# The get_workshop_cbd() is a do-or-die function that bails on any error.
get_workshop_cbd "$WorkshopCBDBranch" "$OpMode"
if [[ $InstallSDPLib -eq 1 ]]; then
get_workshop_sdp_lib "$WorkshopCBDBranch" "$OpMode"
fi
echo -e "\nAll processing completed successfully.\n"
# Illustrate using $SECONDS to display runtime of a script.
echo -e "That took $(($SECONDS/3600)) hours $(($SECONDS%3600/60)) minutes $(($SECONDS%60)) seconds.\n"
exit 0