#!/bin/bash
#------------------------------------------------------------------------------
set -u
#==============================================================================
# Declarations and Environment
declare ThisScript="${0##*/}"
declare Version=1.0.0
declare WorkspaceRoot=
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 -a GenFileList=
declare -a GenFileCmd=
declare -i GenFileCount=0
declare GenFile=
declare Cmd=
declare DocGenDir=
declare ManPageFile=
declare Log=Unset
# Store location of all known scripts, with paths relative to
# the HMS stream workspace root directory.
ScriptList[ScriptCount]="p4/common/site/hms/doc/gen/gen_script_man_pages.sh"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/bin/hms"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/setup/hms_ts_setup.sh"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/bin/sdp_sync"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/bin/global_replica_status"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/bin/gtu"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/bin/hrun"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
ScriptList[ScriptCount]="p4/common/site/hms/bin/irun"
ScriptInterpreter[ScriptCount]="bash"
ScriptUsageFlag[ScriptCount]="man"
ScriptCount+=1
# Store location of all files to generate docs for.
### GenFileList[GenFileCount]="rel/path/to/file.cfg"
### GenFileCount+=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 HMS executables. This is done by
executing scripts with the '-man' argument for each (or '-h'
depending on the usage). This helps ensure the latest in-code
documentation from the programs/scripts is included in the HMS Guide
using an include directive in the AsciiDoc.
It can also generate sample config files such as the install_sdp.cfg
file that is generated by the install_sdp.sh script, so the sample
config file can be referenced in the AsciiDoc file.
This script generates docs in HMS 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 //p4-hms/<stream>/dev/doc:
make clean
make
OPTIONS:
<Program> [<Program2> ...]
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 WorkspaceRoot, up one dir level if we started in 'doc'.
DocGenDir="$PWD"
DocDir="${PWD%/gen}"
WorkspaceRoot="${DocDir%/p4/common/site/hms/doc}"
else
bail "Bad start dir [$PWD], should be 'doc/gen' subdirector under HMS workspace root."
fi
msg "Generating docs in dir '$DocGenDir' from workspace root '$WorkspaceRoot'."
if [[ "$UserSpecifiedScripts" == "all" && $ScriptCount -gt 0 ]]; 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]} $WorkspaceRoot/${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 "$WorkspaceRoot/${ScriptList[i]}")" && "$DoP4Submit" -eq 1 ]]; then
warnmsg "The '-submit' will be ignored because this file is checked out: $WorkspaceRoot/${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 in: $ManPageFile"
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="$WorkspaceRoot/${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 "$WorkspaceRoot/${ScriptList[i]}")" && "$DoP4Submit" -eq 1 ]]; then
warnmsg "The '-submit' will be ignored because this file is checkec out: $WorkspaceRoot/${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 [[ "$UserSpecifiedScripts" == "all" && $GenFileCount -gt 0 ]]; then
i=0; while [[ "$i" -lt "${#GenFileList[@]}" ]]; do
GenFile="${DocGenDir}/${GenFileList[i]}"
Cmd="bash $WorkspaceRoot/${GenFileCmd[i]}"
msg "Generating file [${GenFileList[i]}] with this command: $Cmd"
$Cmd > "$GenFile" 2>/dev/null
if [[ -s "$GenFile" ]]; then
dbg "File generated OK: $GenFile."
else
errmsg "Generated file is empty: ${GenFileList[i]}"
fi
i+=1
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"
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #2 | 33529 | C. Thomas Tyler |
Cosmetic: normalize double-backslash \\n / \\t to single-backslash \n / \t An older version of ShellCheck once recommended escaping backslash-n and backslash-t as \\n / \\t in double-quoted strings; a later version reversed that guidance since it was unnecessary. Both forms behave identically at runtime, but the double-backslash form is visual clutter. Applied via tools/sed_fixer.sh across the tree; no functional change. |
||
| #1 | 33516 | C. Thomas Tyler |
Consistency pass: fix absolute URLs, p4ms->hms renames, script/doc typos and bugs - Convert absolute workshop.perforce.com URLs to relative paths in dlp/ReadMe.md - Fix case-mismatch link to HMS_Product_Roadmap.md in README.md - Rename reset_p4ms.sh -> reset_hms.sh and p4broker_p4ms_test -> p4broker_hms_test - Fix .sh-suffix bugs: bin/hms calling global_replica_status.sh (should be no ext), and matching SEE ALSO / doc references for sdp_sync and global_replica_status - Add missing scripts (gtu, hrun, irun, global_replica_status) to gen_script_man_pages.sh - Add stub scripts: nj_help.sh, broker_njob.pl, broker_mkproj.pl, broker_jr.pl - Remove dangling absolute symlinks HostCM/p4 and HostCM/p4d (cruft) - Rename test/b -> test/broker_ctl.sh for clarity - Fix real bugs: broker_imply-u.pl broken regex match, gen_dlp_broker_cfg.sh and gen_nj_broker_cfg.sh copy-pasted Version-file existence check, garbled comment in broker_must_be_owner.pl, unclosed quote in tools/gsr.sh usage(), missing 'h' in HMS_SystemComponents.md broker command example (^ms$ -> ^hms$) - Fix broken sed command and incomplete sentence in HMS_Install_Notes.md and SDP_and_HMS_Update_Process.md - Fix broken markdown table in HMS_Product_Roadmap.md - Fix unclosed parenthesis, missing verb, and FKA Swarm mislabel in HMSDeploymentPlanning.adoc - Standardize //streams/main/... naming in HostCM/ReadMe.md - Numerous typo fixes across README.md, HMS_SystemComponents.md, SDP_and_HMS_Update_Process.md, HMS_TightShipManagement.adoc, HMSDeploymentPlanning.adoc, HostCM/ReadMe.md, and various scripts Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> |