#!/bin/bash
#------------------------------------------------------------------------------
set -u
#==============================================================================
# Declarations and Environment
declare ThisScript="${0##*/}"
declare Version=1.5.1
declare SDPRoot=
declare DocDir=
declare -i DoP4Reconcile=0
declare -i DoP4Submit=0
declare -i CancelP4Submit=0
declare -i Debug="${DEBUG:-0}"
declare -i i
declare -i ErrorCount=0
declare -i WarningCount=0
declare -i ScriptCount=0
declare -a ScriptList
declare -a ScriptInterpreter
declare -a ScriptUsageFlag
declare Script=
declare UserSpecifiedScripts=
declare Cmd=
declare DocGenDir=
declare ManPageFile=
declare Log=Unset
# Store location of all known scripts, with paths relative to
# the SDP branch root directory.
ScriptList[$ScriptCount]="doc/gen/gen_script_man_pages.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="helix_binaries/get_helix_binaries.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/ccheck.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/load_checkpoint.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/mkrep.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/p4login"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/p4pcm.pl"
ScriptInterpreter[$ScriptCount]="perl"
ScriptUsageFlag[$ScriptCount]="h"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/p4verify.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/sdp_health_check.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/upgrade.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/bin/verify_sdp.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/sdp_upgrade/sdp_upgrade.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/setup/mkdirs.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
ScriptList[$ScriptCount]="Server/Unix/p4/common/sdp_upgrade/clear_depot_Map_fields.sh"
ScriptInterpreter[$ScriptCount]="bash"
ScriptUsageFlag[$ScriptCount]="man"
ScriptCount+=1
#==============================================================================
# Local Functions
function msg () { echo -e "$*"; }
function dbg () { [[ "$Debug" -eq 1 ]] || return; msg "$*"; }
function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; }
function warnmsg () { msg "\\nWarning: ${1:-Unknown Warning}\\n"; WarningCount+=1; }
function bail () { errmsg "${1:-Unknown Error}\\n"; exit "${2:-1}"; }
#------------------------------------------------------------------------------
# Function: usage (required function)
#
# Input:
# $1 - style, either -h (for short form) or -man (for man-page like format).
# The default is -h.
#
# $2 - error message (optional). Specify this if usage() is called due to
# user error, in which case the given message displayed first, followed by the
# standard usage message (short or long depending on $1). If displaying an
# errror, usually $1 should be -h so that the longer usage message doesn't
# obsure the error message.
#
# Sample Usage:
# usage
# usage -h
# usage -man
# usage -h "Incorrect command line usage."
#------------------------------------------------------------------------------
function usage
{
declare style="${1:--h}"
declare errorMessage="${2:-Unset}"
if [[ "$errorMessage" != Unset ]]; then
msg "\\n\\nUsage Error:\\n\\n$errorMessage\\n\\n"
fi
echo "USAGE for $ThisScript v$Version:
$ThisScript [<Script> [<Script2> ...]] [-rec | -submit] [-L <log>] [-d|-D]
or
$ThisScript [-h|-man|-V]
"
if [[ $style == -man ]]; then
msg "
DESCRIPTION:
This script generates man pages for SDP shell scripts. This is done by
executing scripts with the '-man' argument for each script (or '-h'
depending on the script). This helps ensure the latest in-code
documentation from the scripts is included in the SDP Guide using
an include directive in the AsciiDoc.
This script generates docs in SDP doc/gen folder, where they are
referenced in AsciiDoc (*.adoc) files.
It can update files in version control (using 'p4 rec') if the '-rec'
option is used. Alternately, if '-submit' is specified (which implies
'-rec'), any files opened by reconcile are automatically submitted with
a description of 'Updated generated script man pages.'
After this script is executed, the AsciiDoc can be updated by
executing the following in the SDP 'doc' folder, the local folder
corresponding to //guest/perforce_software/sdp/dev/doc:
make clean
make
OPTIONS:
<Script> [<Script2> ...]
Specify a space-delimited list of scripts to generate docs for. If no
script is specified, man pages are generated for all configured scripts.
Only the script basename, e.g. mkrep.sh or load_checkpoint.sh, should be
given. This script knows where all documented scripts exist in the SDP
structure, so the user need only specify the basename.
-rec
Specify '-rec' to reconcile of generated files.
-s[ubmit]
Specify '-s' (or '-submit') to submit any generated doc files with a
changelist description of: 'Updated generate script man pages.'
The '-submit' is ignored if associated script are checked out.
The '-submit' option implies '-rec'.
Files may submitted to:
//guest/perforce_software/sdp/dev/doc/gen/...
-L <log>
Specify the path to a log file, or the special value 'off' to disable
logging. By default, all output (stdout and stderr) goes to
/tmp/gen_script_man_page.<datestamp>.log
NOTE: This script is self-logging. That is, output displayed on the screen
is simultaneously captured in the log file. Do not run this script with
redirection operators like '> log' or '2>&1', and do not use 'tee.'
-d Debug mode, generates more verbose output.
-D Set extreme debugging verbosity using bash 'set -x' mode. Implies '-d'.
HELP OPTIONS:
-h Display short help message
-man Display man-style help message
-V Dispay version info for this script and its libraries.
"
fi
exit 1
}
#==============================================================================
# Command Line Processing
declare -i shiftArgs=0
set +u
while [[ $# -gt 0 ]]; do
case $1 in
(-L) Log="$2"; shiftArgs=1;;
(-h) usage -h;;
(-rec) DoP4Reconcile=1;;
(-s|-submit) DoP4Submit=1;;
(-man) usage -man;;
(-V) msg "\\n$ThisScript v$Version\\n"; exit 1;;
(-d) Debug=1;; # Debug, call dbg() functions with more verbose debug output.
(-D) Debug=1; set -x;; # Extreme debug; use bash 'set -x' mode.
(-*) usage -h "Unknown option '$1'.";;
(*)
if [[ -z "$UserSpecifiedScripts" ]]; then
UserSpecifiedScripts="$1"
else
UserSpecifiedScripts="$UserSpecifiedScripts 1"
fi
;;
esac
# Shift (modify $#) the appropriate number of times.
shift; while [[ $shiftArgs -gt 0 ]]; do
[[ $# -eq 0 ]] && usage -h "Incorrect number of arguments."
shiftArgs=$shiftArgs-1
shift
done
done
set -u
#==============================================================================
# Command Line Verification
[[ "$PWD" == *"/doc/gen" ]] || \
usage -h "\\n\\tRun this from the 'doc/gen' dir under the SDP root dir, not \\n\\t$PWD"
[[ "${Log:-Unset}" == Unset ]] && \
Log="/tmp/${ThisScript%.sh}.$(date +'%Y%m%d-%H%M%S').log"
[[ -n "$UserSpecifiedScripts" ]] || UserSpecifiedScripts=all
# The '-submit' option implies '-rec'.
[[ "$DoP4Submit" -eq 1 ]] && DoP4Reconcile=1
#==============================================================================
# Main Program
if [[ "$Log" != "off" ]]; then
touch "$Log" || bail "Couldn't touch log file [$Log]."
# Redirect stdout and stderr to a log file.
exec > >(tee "$Log")
exec 2>&1
msg "\\nLog is: $Log\\n"
fi
msg "Running $ThisScript v$Version as $USER@${HOSTNAME%%.*} at $(date)."
# This runs from the SDP 'doc/gen' folder for whatever branch we are in.
# dir.
if [[ "$PWD" == *"/doc/gen" ]]; then
# Calculate the 'SDPRoot', up one dir level if we started in 'doc'.
DocGenDir="$PWD"
DocDir="${PWD%/gen}"
SDPRoot="${DocDir%/*}"
else
bail "Bad start dir [$PWD], should be 'doc/gen' subdirector under SDP branch root."
fi
# Setup just enough environment to be able to run the scripts with the '-man' option
# to generate a man page from in-script docs. These values must be exported.
export P4U_HOME="${SDPRoot}/Server/Unix/p4/common/bin"
export P4U_LIB="${SDPRoot}/Server/Unix/p4/common/lib"
dbg "P4U_HOME=$P4U_HOME"
dbg "P4U_LIB=$P4U_LIB"
msg "Generating docs in dir: $DocGenDir"
if [[ "$UserSpecifiedScripts" == "all" ]]; then
i=0; while [[ "$i" -lt "${#ScriptList[@]}" ]]; do
ManPageFile="${ScriptList[$i]}.man.txt"
ManPageFile="${DocGenDir}/${ManPageFile##*/}"
msg "Generating doc for: ${ScriptList[$i]}"
Cmd="${ScriptInterpreter[$i]} $SDPRoot/${ScriptList[$i]} -${ScriptUsageFlag[$i]}"
# Abort submit of the generated script man page if the script itself
# is opened for edit.
if [[ -n "$(p4 -ztag -F %rev% opened "$SDPRoot/${ScriptList[$i]}")" && "$DoP4Submit" -eq 1 ]]; then
warnmsg "The '-submit' will be ignored because this file is checked out: $SDPRoot/${ScriptList[$i]}"
CancelP4Submit=1
fi
dbg "Running: $Cmd"
# Note: Several scripts generate a non-zero exit code when '-man' or '-h'
# are used, and so checking the exit code isn't helpful in determining if
# we successfully generated docs. Instead we check if the generated doc
# file is empty or not, with stderr discarded.
$Cmd > "$ManPageFile" 2>/dev/null
if [[ -s "$ManPageFile" ]]; then
dbg "Doc content generated."
else
errmsg "No doc content generated for: ${ScriptList[$i]}"
fi
i+=1
done
else
for Script in $UserSpecifiedScripts; do
dbg "Searching for docs for script: $Script"
Cmd=
i=0; while [[ "$i" -lt "${#ScriptList[@]}" ]]; do
dbg "COMPARING [${ScriptList[i]}] vs. [*$Script]"
if [[ "${ScriptList[i]}" == *"$Script" ]]; then
Cmd="SDPRoot/${ScriptInterpreter[$i]} ${ScriptList[$i]} -${ScriptUsageFlag[$i]}"
# Abort submit of the generated script man page if the script itself
# is opened for edit.
if [[ -n "$(p4 -ztag -F %rev% opened "$SDPRoot/${ScriptList[$i]}")" && "$DoP4Submit" -eq 1 ]]; then
warnmsg "The '-submit' will be ignored because this file is checkec out: $SDPRoot/${ScriptList[$i]}"
CancelP4Submit=1
fi
break
fi
i+=1
done
if [[ -n "$Cmd" ]]; then
msg "Generating doc for $Script"
dbg "Running: $Cmd"
ManPageFile="${DocGenDir}/${Script}.man.txt"
$Cmd > "$ManPageFile" 2>&1
if [[ -s "$ManPageFile" ]]; then
dbg "Doc content generated."
else
errmsg "No doc content generated for: ${ScriptList[$i]}"
fi
else
errmsg "No script docs available for script: $Script"
fi
done
fi
if [[ "$ErrorCount" -eq 0 ]]; then
msg "\\nInterim script docs generated successfully."
else
bail "Encountered $ErrorCount errors generating intermim script docs."
fi
if [[ "$DoP4Reconcile" -eq 1 ]]; then
Cmd="p4 -d $DocGenDir rec"
msg "Reconciling in $DocGenDir with: $Cmd"
if ! $Cmd; then
bail "Reconcile in $DocGenDir failed!"
fi
if [[ -n "$(p4 -ztag -F %rev% opened "$DocGenDir/..." | head -1)" ]]; then
Cmd="p4 -s reopen -t +w $DocGenDir/..."
msg "Ensuring generated files have +w file type modifier with:\\n$Cmd"
if ! $Cmd; then
errmsg "Error running 'p4 reopen' command."
fi
Cmd="p4 -s -d $DocGenDir submit -d \"Updated generated script man pages.\" ..."
if [[ "$DoP4Submit" -eq 1 ]]; then
if [[ "$CancelP4Submit" -eq 1 ]]; then
msg "Opened files detected in $DocGenDir, but '-submit' ignored due to checkout out script files. When ready and after submitting script files, submit with:\\n\\t$Cmd"
else
# shellcheck disable=SC2090
if p4 -s -d "$DocGenDir" submit -d "Updated generated script man pages." ...; then
msg "\\nSubmit complete."
else
bail "Submit of genreated man pages in $DocGenDir failed."
fi
fi
else
msg "Opened files detected in $DocGenDir. Submit with:\\n\\t$Cmd"
fi
else
msg "No versioned files need to be updated in: $DocGenDir"
fi
else
msg "\\nNo reconcile or submit attempted. Consider running with '-rec' and/or '-submit' options."
fi
exit "$ErrorCount"