convert_edge_to_commit.sh #1

  • //
  • guest/
  • tom_tyler/
  • sw/
  • main/
  • rename_edge/
  • convert_edge_to_commit.sh
  • View
  • Commits
  • Open Download .zip Download (9 KB)
#!/bin/bash
set -u

#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# this package.
#------------------------------------------------------------------------------

#==============================================================================
# Declarations and Environment

declare -i ErrorCount=0
declare -i WarningCount=0
declare -i Debug=0
declare -i NoOp=1
declare ThisScript=${0##*/}
declare ThisUser=
declare ThisHost=${HOSTNAME%%.*}
declare Version=1.0.1
declare CmdLine="$0 $*"
declare LogsDir="${LOGS:-${HOME:-/tmp}}"
declare LogDatestamp=
declare LogLink=
declare Log=
declare H1="=============================================================================="
declare H2="------------------------------------------------------------------------------"
declare RequiredUtils="awk bc date grep id ls tail wc"

#==============================================================================
# Local Functions

function msg () { echo -e "$*"; }
function dbg () { [[ "$Debug" -eq 0 ]] || msg "DEBUG: $*"; }
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}"; exit "$ErrorCount"; }

#------------------------------------------------------------------------------
# Function: terminate
function terminate
{
   # Disable signal trapping.
   trap - EXIT SIGINT SIGTERM

   dbg "$ThisScript: EXITCODE: $ErrorCount"

   # Stop logging.
   [[ "$Log" == off ]] || msg "\\nLog is: $Log\\n${H1}"

   # With the trap removed, exit.
   exit "$ErrorCount"
}

#------------------------------------------------------------------------------
# Function: usage (documentation)
#
# Input:
# $1 - style, '-h' (for short usage synopsis) or '-man' (for full man-page
# documentation).  Default is -h.
#
# $2 - error message (optional).  Specify this if usage() is called due to
# usage error, in which case the given message displayed first, followed by
# the standard usage message (short or long depending on $1).  If displaying an
# error, usually $1 should be -h so that the longer usage message doesn't
# obscure the supplied usage error message.
#
# Sample Usage:
# usage
# usage -h
# usage -man
# usage -h "Incorrect command line usage."
#------------------------------------------------------------------------------
function usage
{
   declare style=${1:--h}
   declare errorMessage=${2:-}

   [[ -n "$errorMessage" ]] && \
      errmsg "\\n\\nUsage Error:\\n\\n$errorMessage\\n\\n"

   msg "USAGE for $ThisScript v$Version:

$ThisScript -L <log>] [-y] [-d|-D]

or

$ThisScript [-h|-man]
"
   if [[ $style == -man ]]; then
      msg "
DESCRIPTION:
	This script will convert an edge server into a commit server.

	WARNING: THIS IS NOT A STANDARD OPERATION!  This is only suitable
	in a server split scenario. It supports a method of server splitting
	that can be thought of as an alternative to using the perfsplit tool.

	The edge server can optionally be configured as a filtered edge server,
	using the RevisionDataFilter field of the the server spec to reduce set
	of files from the commit server that will be available on the edge
	server.

	The gist is:

OPERATIONAL PROCEDURE:

	The start state for this script is:
	There is a commit server

	WHAT THIS DOES NOT HANDLE:
	* Authentication
	* Swarm
	* Impact on other integrated systems.


OPTIONS:
 -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
	EDITME_DEFAULT_LOG
	$LogsDir/

	NOTE: This script is self-logging.  That is, all standard and error
	output displayed is also captured in the log file.  Use of 'tee' and
	redirection with '>' and '2>&1' are unnecessary.

 -si	Operate silently.  All output (stdout and stderr) is redirected to the log
	only; no output appears on the terminal.  This cannot be used with
	'-L off'.
      
	EDITME: This is useful when running from cron, as it prevents automatic
	email from being sent by cron directly, as it does when a script called
	from cron generates any output.  This script is then responsible for
	email handling, if any is to be done.

 -n	No-Op.  Prints commands instead of running them.

DEBUGGING OPTIONS:
 -d     Enable additional debug output.

 -D     Set extreme debugging verbosity using bash 'set -x' mode. Implies '-d'.

HELP OPTIONS:
 -h	Display short command line usage synopsis.
 -man	Display this documentation manual page.

EXAMPLES:

SEE ALSO:
"
   fi

   exit 2
}

#------------------------------------------------------------------------------
# Function: get_old_log_timestamp ($log)
#
# Get the last modified timestamp of the old log in a cross-platform manner.
# If we don't get a correct value using 'stat' (which varies across the
# UNIX/Linux/MacOSX spectrum), use the current time as a fallback. In that
# case, the timestamp will reflect the time the log was moved rather than when
# it was last modified, but that's still reasonable.  The file timestamp will
# still have the correct last-modified time.
#------------------------------------------------------------------------------
function get_old_log_timestamp () {
   local log=${1:-}
   local oldLogTimestamp=
   [[ -n "$log" ]] || return

   if [[ "$(uname -s)" == "Darwin" ]]; then
      oldLogTimestamp=$(stat -L -f %Sm -t '%Y-%m-%d-%H%M%S' "$log" 2>/dev/null)
   else
      oldLogTimestamp="$(stat -L -c '%10y' "$log" | sed -e 's@[.].*$@@g' -e 's@:@@g' -e 's@ @-@g')"
   fi

   [[ "$oldLogTimestamp" =~ ^[2-9]{1}[0-9]{3}- ]] ||
      oldLogTimestamp=$(date +'%Y-%m-%d-%H%M%S')

   echo "$oldLogTimestamp"
}

#==============================================================================
# Command Line Processing

declare -i shiftArgs=0

set +u
while [[ $# -gt 0 ]]; do
   case $1 in
      (-h) usage -h;;
      (-V) msg "$ThisScript v$Version"; exit 2;;
      (-man) usage -man;;
      (-y) NoOp=0;;
      (-L) Log="$2"; shiftArgs=1;;
      (-d) Debug=1;; # Debug mode.
      (-D) Debug=1; set -x;; # Use bash 'set -x' extreme debugging mode.
      (*) usage -h "Unknown arg: $1)";;
   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

if [[ -z "$Log" ]]; then
   LogDatestamp=$(date +'%Y-%m-%d-%H%M%S')
   LogLink="${LogsDir}/${ThisScript%.sh}.log"
   Log="${LogsDir}/${ThisScript%.sh}.${LogDatestamp}.log"
fi

#==============================================================================
# Main Program

for u in $RequiredUtils; do
   [[ -n "$(command -v "$u")" ]] || errmsg "Missing required utility: $u"
done
[[ "$ErrorCount" -eq 0 ]] || bail "Aborted early due to missing required utilitiies."

trap terminate EXIT SIGINT SIGTERM

if [[ "$Log" != off ]]; then
   if [[ -e "$Log" ]]; then
      # shellcheck disable=SC2012
      OldLogTimestamp="$(ls -l --time-style +'%Y%m%d-%H%M%S' "$Log" 2>/dev/null | awk '{print $6}')"
      # shellcheck disable=SC2012
      [[ -n "$OldLogTimestamp" ]] ||\
         OldLogTimestamp="$(ls -l -D '%Y%m%d-%H%M%S' "$Log" 2>/dev/null | awk '{print $6}')"
      [[ -n "$OldLogTimestamp" ]] ||\
         OldLogTimestamp="$(date +'%Y%m%d-%H%M%S' "$Log" 2>/dev/null)"
      [[ -n "$OldLogTimestamp" ]] ||\
         OldLogTimestamp="old"
      OldLog="${LogsDir}/${ThisScript%.sh}.${OldLogTimestamp}.log"
      mv -f "$Log" "$OldLog" || bail "Could not do: mv -f \"$Log\" \"$OldLog\""
      dbg "Rotated $Log to $OldLog"
   fi

   if [[ -e "$LogLink" ]]; then
      if [[ -L "$LogLink" ]]; then
         rm -f "$LogLink"
      else
         # If the name that should be a symlink is not a symlink, move it aside before
         # creating the symlink.
         OldLogTimestamp=$(get_old_log_timestamp "$LogLink")
         mv -f "$LogLink" "${LogLink%.log}.${OldLogTimestamp}.log" ||\
            bail "Could not move old log file aside; tried: mv -f \"$LogLink\" \"${LogLink%.log}.${OldLogTimestamp}.log\""
      fi
   fi

   touch "$Log" || bail "Couldn't touch log file [$Log]."

   # Use a subshell so the 'cd' doesn't persist.
   ( cd "$LogsDir"; ln -s "${Log##*/}" "${LogLink##*/}"; ) ||\
       bail "Couldn't initialize log symlink; tried: ln -s \"$Log\" \"$LogLink\""

   # Redirect stdout and stderr to a log file.
   exec > >(tee "$Log")
   exec 2>&1

   msg "${H1}\\nLog is: $Log\\n"
fi

ThisUser=$(id -n -u)
msg "Started $ThisScript v$Version as $ThisUser@$ThisHost at $(date).\\nCommand Line was: $CmdLine"

[[ "$NoOp" -eq 1 ]] && msg "NO_OP: Operating in DRY RUN mode."

if [[ $ErrorCount -eq 0 && $WarningCount -eq 0 ]]; then
   msg "${H2}\\nAll processing completed successfully.\\n"
elif [[ $ErrorCount -eq 0 ]]; then
   msg "${H2}\\nProcessing completed, but with $WarningCount warning.  Review the output above carefully.\\n" 
else
   msg "${H2}\\nProcessing completed, but with $ErrorCount errors and $WarningCount warnings.  Scan above output carefully.\\n" 
fi

# Display runtime.
msg "That took $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\\n"

# See the terminate() function, where this script exits.
exit "$ErrorCount"
# Change User Description Committed
#1 31284 Perforce maintenance Added initial files.
Nothing working yet; this is just the start of development.

Files included:
* rename_edge_serverid.sh - Script to rename an edge ServerID.
* convert_edge_to_commit.sh - Script to convert a filtered edge into a commit.
* cli_test.cfg - Test Suite (using SDP run_cli_tests.sh script).
* r - Test suite wrapper.
* .p4ignore - Just a typical P4IGNORE file.