package_downloads.sh #4

  • //
  • guest/
  • perforce_software/
  • helix-installer/
  • tools/
  • package_downloads.sh
  • View
  • Commits
  • Open Download .zip Download (12 KB)
#!/bin/bash
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Helix Installer, and also available online:
# https://swarm.workshop.perforce.com/projects/perforce_software-helix-installer/view/main/LICENSE
#------------------------------------------------------------------------------

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

declare ThisScript=${0##*/}
declare Version=1.4.4.HI.1
declare AppHome=${PWD%/*}
declare ExcludesCfg=$AppHome/tools/excludes.downloads.cfg
declare HIBranch=main
declare TmpDir=
declare HIVersion=
declare DownloadsDir=
declare TarFile=
declare WorkingDir=
declare ChangeFile=
declare OutputFile=
declare Changelist=
declare -i ErrorCount=0
declare -i Debug=0
declare Log=
declare H="\\n=============================================================================="

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

function msg () { echo -e "$*"; }
function errmsg () { msg "\\nError: ${1:-Unknown Error}\\n"; ErrorCount+=1; }
function bail () { errmsg "${1:-Unknown Error}"; exit "${2:-1}"; }
function dbg () { [[ "$Debug" -ne 0 ]] && msg "DEBUG: $*"; }
function run () {
   local cmdAndArgs="${1:-echo}";
   local desc="${2:-}";
   local -i exitCode

   [[ -n "$desc" ]] && msg "$desc"
   msg "Running: $cmdAndArgs"
   $cmdAndArgs > "$OutputFile" 2>&1
   exitCode=$?

   cat "$OutputFile"
   OutputString="$(cat "$OutputFile")"

   return "$exitCode"
}

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

   dbg "$ThisScript: EXITCODE: $ErrorCount"

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

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

#------------------------------------------------------------------------------
# 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 [-o] [-L <log>] [-d|-D]

or

$ThisScript [-h|-man|-V]
"
   if [[ $style == -man ]]; then
      echo -e "
DESCRIPTION:
	Create an Helix Installer distribution package file from the
	latest files in the main branch (or dev branch for a pre-release).

	Prior to packaging, a variety of checks are done to ensure
	the latest files are synced, the user is logged in, no
	files are checked out in the main branch, etc.

	An exclusion config file defines files and directories
	to be excluded from packaging.  This exclusion config
	file has file name per line, which may include the
	'*' wild card. This helps ensure only files that belong
	in the package are shipped.

	The exclusion config file can also specify directories to be
	excluded, which start with a 'D:' prefix.

	The exclusion config file is:
	$ExcludesCfg

	The generated tar files is helix_installer.tgz.

OPTIONS:
 -o	Proceed even if files are opened in Perforce and/or not synced
 	to the head revision.  This may be useful for testing purposes.

	By default, we abort if any files are checked out, or if files
	are not syncd to the head revision.  This option is not suitable
	for creating a distribution file that will be submitted.

 -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/${ThisScript%.sh}.<timestamp>.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     Set debugging verbosity.

 -D     Set extreme debugging verbosity.

HELP OPTIONS:
 -h	Display short help message
 -man	Display man-style help message

FILES:
	Exclusions Config File, listing files to exclude from all packages:
	$ExcludesCfg

EXAMPLES:
	Typical Usage is with no arguments:
	cd $AppHome/tools
	./package_downloads.sh

	Thus must be run from a workspace that maps at least the folder
	//guest/perforce_software/helix-installer/...
"
   fi

   exit 1
}

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

declare -i shiftArgs=0
declare -i AllowOpenedFiles=0

set +u
while [[ $# -gt 0 ]]; do
   case $1 in
      (-o) AllowOpenedFiles=1;;
      (-h) usage -h;;
      (-man) usage -man;;
      (-L) Log="$2"; shiftArgs=1;;
      (-d) Debug=1;; # Debug mode.
      (-D) Debug=1; set -x;; # Debug; use bash 'set -x' extreme debug mode.
      (*) usageError "Unknown arg ($1).";;
   esac

   # Shift (modify $#) the appropriate number of times.
   shift; while [[ $shiftArgs -gt 0 ]]; do
      [[ $# -eq 0 ]] && usageError "Bad usage."
      shiftArgs=$shiftArgs-1
      shift
   done
done
set -u

#==============================================================================
# Command Line Verification

[[ -z "$Log" ]] && Log="/tmp/${ThisScript%.sh}.$(date +'%Y%m%d-%H%M').log"

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

trap terminate EXIT SIGINT SIGTERM

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 "${H}\\nLog is: $Log\\n";
fi

msg "\\nStarting $ThisScript v$Version as $(whoami)@${HOSTNAME%%.*} on $(date)."
TmpDir=$(mktemp -d)
OutputFile="$TmpDir/out.txt"

HIVersion=$(cut -d '/' -f 3 < ../main/Version).$(cut -d '/' -f 4 < ../main/Version | cut -d ' ' -f 1)

# shellcheck disable=SC2116 disable=SC2086
HIVersion=$(echo $HIVersion)
DownloadsDir=$AppHome/downloads
TarFile=$DownloadsDir/helix_installer.tgz
WorkingDir=/tmp/$HIVersion
ChangeFile=$TmpDir/change.p4s
OutputFile=$TmpDir/output.txt
Changelist=

if run "p4 -ztag -F %TicketExpiration% login -s" \
   "Checking login status."; then
   msg "Verified: Logged into Perforce."
else
   bail "Not logged into Perforce."
fi

run "p4 -F %depotFile% -ztag opened ../$HIBranch/..." \
   "Checking for opened files in Helix Installer $HIBranch branch."

if [[ -n "$OutputString" ]]; then
   if [[ $AllowOpenedFiles -eq 1 ]]; then
      msg "Proceeding despite opened files being detected, due to -o flag."
   else
      if [[ $OutputString == *"//"* ]]; then
         bail "These files are checked out in the $HIBranch branch:\\n$OutputString\\n\\nAborting."
      else
         bail "Could not determine if files are checked out in the $HIBranch branch. Output was:\\n$OutputString\\n\\nAborting."
      fi
   fi
else
   msg "Verified: No files checked out in Helix Installer $HIBranch branch."
fi

run "p4 -F %depotFile% -ztag sync -n ../..." \
   "Checking for unsynced Helix Installer files."

if [[ -n "$OutputString" ]]; then
   if [[ $AllowOpenedFiles -eq 1 ]]; then
      msg "Proceeding despite unsynced files, due to -o flag."
   else
      if [[ $OutputString == *"//"* ]]; then
         bail "These files need to be synced:\\n$OutputString\\n\\nAborting."
      else
         bail "Could not determine if files need to be synced. Output was:\\n$OutputString\\n\\nAborting."
      fi
   fi
else
   msg "Verified: No unsynced Helix Installer files."
fi

msg "AppHome=[$AppHome] TF=[$TarFile] WD=[$WorkingDir]."

# Cleanup from prior half-start runs if needed.
run "rm -rf $WorkingDir" "Removing dir from earlier run: $WorkingDir"

if [[ -r "$TarFile" ]]; then
   run "rm -f $TarFile" \
      "Removing existing tar file [$TarFile]." ||\
         bail "Failed to remove existing tar file [$TarFile].  Aborting."
fi

msg "Creating empty working directories."
if [[ -d "$WorkingDir" ]]; then
   run "rm -rf $WorkingDir" \
      "Removing old working dir [$WorkingDir]." ||\
      bail "Failed to remove old working dir [$WorkingDir]. Aborting."
fi

run "mkdir -p $WorkingDir" "Initializing empty working dir [$WorkingDir]." 0 ||\
   bail "Failed to create empty working dir [$WorkingDir]. Aborting."

if [[ ! -d "$DownloadsDir" ]]; then
   run "mkdir -p $DownloadsDir" "Initializing empty downloads dir [$DownloadsDir]." 0 ||\
      bail "Failed to create downloads dir [$DownloadsDir]. Aborting."
fi

#------------------------------------------------------------------------------
HIRoot="$WorkingDir/hi"

run "cp -pr ${AppHome}/$HIBranch $HIRoot" \
   "Copying Helix Installer package from $HIBranch branch to working dir." 0 ||\
   bail "The copy to the working dir failed.  Aborting."

cd "$HIRoot" || bail "Failed to cd to Helix Installer root in Working Dir [$HIRoot]."

if [[ -r "$ExcludesCfg" ]]; then
   while read -r excludeFile; do
      [[ "$excludeFile" == "" || "$excludeFile" == "#"* ]] && continue
      if [[ "$excludeFile" == "D:"* ]]; then
         excludeDir=${excludeFile#D:}
         msg "find $HIRoot/ -type d -name \"$excludeDir\" -print -exec rm -r -f {} \\;"
         find "$HIRoot/" -type d -name "$excludeDir" -print -exec rm -r -f {} \;
      else
         msg "find $HIRoot/ -type f -name \"$excludeFile\" -print -exec rm -f {} \\;"
         find "$HIRoot/" -type f -name "$excludeFile" -print -exec rm -f {} \;
      fi
   done < "$ExcludesCfg"
fi

cd "$WorkingDir" || bail "Failed to cd to Working Dir [$WorkingDir]."

# shellcheck disable=SC2071
if [[ "$(uname -s)" == Darwin && "$(uname -r)" > "18" ]]; then
   run "tar -cz --no-xattrs -f $TarFile hi" ||\
      bail "Failed to create tar file [$TarFile]. Aborting."
else
   run "tar -cz -f $TarFile hi" ||\
      bail "Failed to create tar file [$TarFile]. Aborting."
fi

cd "$HIRoot" || bail "Failed to cd to Helix Installer root in Working Dir [$HIRoot]."

msg "\\nProcessing excludes from $ExcludesCfg:\\n$(cat "$ExcludesCfg")\\n"

if [[ -r "$ExcludesCfg" ]]; then
   while read -r excludeFile; do
      [[ "$excludeFile" == "" || "$excludeFile" == "#"* ]] && continue
      if [[ "$excludeFile" == "D:"* ]]; then
         excludeDir=${excludeFile#D:}
         msg "find $HIRoot/ -type d -name \"$excludeDir\" -print -exec rm -r -f {} \\;"
         find "$HIRoot/" -type d -name "$excludeDir" -print -exec rm -r -f {} \;
      else
         msg "find $HIRoot/ -type f -name \"$excludeFile\" -print -exec rm -f {} \\;"
         find "$HIRoot/" -type f -name "$excludeFile" -print -exec rm -f {} \;
      fi
   done < "$ExcludesCfg"
fi

# Convert ASCII text files to Windows line endings before packaging.
for textFile in $(find . -type f -exec file {} \; | grep -E -i '(ascii|text)'| cut -d: -f1); do
   convertedTextFile=.tmp.converted
   awk 'sub("$", "\r")' "$textFile" > "$convertedTextFile"
   mv -f "$convertedTextFile" "$textFile"
done

run "tar -tzf $TarFile" \
   "Tar file [$TarFile] contains these elements:"

cd "$DownloadsDir" || bail "Failed to cd to downloads dir [$DownloadsDir]."

echo -e "Change: new\\n
Description:\\n\\tPackaged Helix Installer $HIVersion." > "$ChangeFile"

p4 change -i < "$ChangeFile" > "$OutputFile" 2>&1

if ! grep -E 'Change \d+ created.' "$OutputFile"; then
   cat "$OutputFile"
   rm -f "$OutputFile"
   bail "Failed to create pending changelist. Aborting."
fi

# Parse the generated changelist number from the output file.
Changelist=$(cat "$OutputFile")
Changelist=${Changelist#Change }
Changelist=${Changelist%% *}
# shellcheck disable=SC2086 disable=SC2116
Changelist=$(echo $Changelist)

run "p4 -s rec -c $Changelist" \
   "Reconciling in downloads dir [$DownloadsDir]." ||\
   bail" Failed to reconcile changes."

run "p4 describe -s $Changelist" \
   "Showing generated change $Changelist." 1 1 0 ||\
   bail" Failed to describe change $Changelist."

msg "To complete packaging, run:\\n\\tp4 -s submit -c $Changelist\\n"

[[ -d "$TmpDir" ]] && rm -rf "$TmpDir"

if [[ "$ErrorCount" -eq 0 ]]; then
   msg "${H}\\nAll processing completed successfully.\\n"
else
   msg "${H}\\nProcessing completed, but with errors.  Scan above output carefully.\\n" 
fi

msg "\\nThat took about $((SECONDS/3600)) hours $((SECONDS%3600/60)) minutes $((SECONDS%60)) seconds.\\n"

# See the terminate() function, which is really where this script exits.
exit 0
# Change User Description Committed
#4 29705 C. Thomas Tyler Updated package_downloads.sh for HI to match 2 recent changes in SDP version.
#3 29463 C. Thomas Tyler Tweaked tarball create command to avoid getting annoying
warning on tarball extract that looks someting like:

tar: Ignorning unknown extended header keyword 'LIBARCHIVE.xattr.com.microsoft.defender.dlp.marker#C'
#2 27434 C. Thomas Tyler Refined timestamp.
#1 27433 C. Thomas Tyler Added packaging util for Helix Installer.