# bbi_actions.lib Version=3.7.11 #============================================================================== # Copyright and license info is available in the LICENSE file included with # the P4BBI tool, and also available online: # https://swarm.workshop.perforce.com/projects/perforce-software-baseline-and-branch-import/view/main/LICENSE #------------------------------------------------------------------------------ #============================================================================== # BBI Library Functions. #------------------------------------------------------------------------------ # Function: map_workspace_to_path # Parameters: # $1 - workspace # client workspace name # $2 - depotType # The depot type, i.e. 'stream' or 'local'. # $3 - depotDepth # For stream depots, the StreamDepth value of the stream depot, trimmed to # just the numeric value. So if the StreamDepth value is //FOO/1/2/3, this # will be just '3'. This is the number of directory levels down from the # root of the stream depot in which streams are rooted. The default is 1, # P4D 2015.1 introduced the StreamDepth field of the depot spec. # $4 - target path # The path to map in the workspace. #------------------------------------------------------------------------------ function map_workspace_to_path { vvmsg "CALL: map_workspace_to_path ($*)" declare workspace=${1:-Unset} declare depotType=${2:-Unset} declare depotDepth=${3:-1} declare targetPath=${4:-Unset} declare stream= [[ $workspace == Unset || $depotType == Unset || $targetPath == Unset ]] && \ return 1 declare cSpecFile=/tmp/bbi.cspec.$$.$RANDOM if [[ $NO_OP -eq 0 ]]; then msg "Mapping workspace $workspace to $depotType depot path $targetPath." if [[ $depotType == stream ]]; then vmsg "Path $targetPath is in a Stream depot of depth $depotDepth." stream=$(get_stream "$targetPath" "$depotDepth") $P4 client -o $workspace |\ $PERL -e "while(<>){s/^Stream:.*//; last if /^View:/; print;}" > $cSpecFile echo -e "\nStream: $stream\n\n" >> $cSpecFile $P4 -s client -i < $cSpecFile || return 1 runCmd "/bin/rm -f $cSpecFile" else vmsg "Path $targetPath is in a Classic local depot." $P4 client -o $workspace |\ $PERL -e "while(<>){s/^Stream:.*//; last if /^View:/; print;}" > $cSpecFile echo -e "\nView:\n $targetPath //$workspace/...\n\n" >> $cSpecFile $P4 -s client -i < $cSpecFile || return 1 runCmd "/bin/rm -f $cSpecFile" fi else if [[ $depotType == stream ]]; then msg "NO_OP: Would bind workspace $workspace to stream depot path $targetPath (StreamDepth=$depotDepth)." else msg "NO_OP: Would bind workspace $workspace to $depotType depot path $targetPath." fi fi } #------------------------------------------------------------------------------ # Function: prep_for_import function prep_for_import { vvmsg "CALL: prep_for_import ($*)" declare cSpecFile=/tmp/bbi.cspec.$$.$RANDOM declare dSpecFile=/tmp/bbi.dspec.$$.$RANDOM declare DemoWSRoot='C:\\\\p4\\\\bbi_demo' declare value= if [[ -n "$($P4BIN -ztag -F '%Access%' client -o $ImportWS)" ]]; then runCmd "$P4BIN -s client -df -Fs $ImportWS 2>&1" \ "Prepatory quiet cleanup of import workspace $ImportWS." 1 0 0 if [[ $CMDEXITCODE -ne 0 ]]; then errmsg "Failed to remove import workspace [$ImportWS]." return 1 fi fi if [[ -d "$ImportWSRoot" ]]; then runCmd "/bin/rm -rf $ImportWSRoot" \ "Prepatory cleanup of import workspace root dir [$ImportWSRoot]." 1 0 0 if [[ $CMDEXITCODE -ne 0 ]]; then runCmd "sudo /bin/rm -rf $ImportWSRoot" \ "Second try using sudo: Prepatory cleanup of import workspace root dir [$ImportWSRoot]." 1 0 0 ||\ bail "Second attempt to clean workspace using sudo failed." fi runCmd "/bin/mkdir -p $ImportWSRoot" \ "Initializing empty import workspace root dir: [$ImportWSRoot]." 1 0 0 ||\ bail "Failed to create import workspace root dir [$ImportWSRoot]." fi echo -e "Depot: depot\n\nOwner: p4import\n\nDescription:\n\tCreated by p4import.\n\nType: local\n\nMap: depot/...\n\n" > $dSpecFile vmsg "$(cat $dSpecFile)" if [[ $NO_OP -eq 0 ]]; then $P4 -s depot -i < $dSpecFile || return 1 fi echo -e "Client: $ImportWS\n\nOwner: $ImportUser\n\nDescription:\n\tBBI Import Workspace\n\nRoot: $ImportWSRoot\n\nOptions: noallwrite clobber nocompress unlocked modtime rmdir\n\nSubmitOptions: revertunchanged\n\nLineEnd: local\n\nView:\n\t//depot/... //$ImportWS/...\n\n" > $cSpecFile vmsg "$(cat $cSpecFile)" if [[ $NO_OP -eq 0 ]]; then $P4 -s client -i < $cSpecFile || return 1 fi echo -e "Client: $VerifyWS\n\nOwner: $ImportUser\n\nDescription:\n\tBBI Verify Workspace\n\nRoot: $VerifyWSRoot\n\nOptions: noallwrite clobber nocompress unlocked modtime rmdir\n\nSubmitOptions: leaveunchanged\n\nLineEnd: local\n\nView:\n\t//depot/... //$VerifyWS/...\n\n" > $cSpecFile vmsg "$(cat $cSpecFile)" if [[ $NO_OP -eq 0 ]]; then $P4 -s client -i < $cSpecFile || return 1 fi echo -e "Client: ${ImportUser}_bbi_demo\n\nOwner: $ImportUser\n\nDescription:\n\tDemo Workspace\n\nRoot: $DemoWSRoot\n\nOptions: allwrite noclobber nocompress unlocked nomodtime rmdir\n\nSubmitOptions: revertunchanged\n\nLineEnd: local\n\nView:\n\t//depot/... //${ImportUser}_bbi_demo/...\n\n" > $cSpecFile vmsg "$(cat $cSpecFile)" if [[ $NO_OP -eq 0 ]]; then $P4 -s client -i < $cSpecFile || return 1 fi # See if we can use parallel submits to enhance performance. echo $P4 -ztag -F '%Value%' configure show net.parallel.max $P4 -ztag -F '%Value%' configure show net.parallel.max value=$($P4 -ztag -F '%Value%' configure show net.parallel.max 2>/dev/null ||:) if [[ $value =~ ^[0-9]+$ ]]; then NetParallelMax=$value msg "Parallel submits enabled (net.parallel.max=$NetParallelMax)." else msg "Parallel submits disabled." fi runCmd "/bin/rm -f $cSpecFile" return 0 } #------------------------------------------------------------------------------ # Function: action_BRANCH_SPEC # # Input: # $1 - branchSpecFile # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_BRANCH_SPEC { vvmsg "CALL: action_BRANCH_SPEC ($*)" declare branchSpecFile=$1 msg "Loading hand-crafted branch spec from $branchSpecFile." if [[ $NO_OP -eq 0 ]]; then $P4 -s branch -i < $branchSpecFile if [[ $? -eq 0 ]]; then vmsg "Loaded this branch spec:\n$(cat $branchSpecFile)\n" else errmsg "Failed to load this branch spec:\n$(cat $branchSpecFile)\n" return 1 fi else msg "NO_OP: Would have loaded this branch spec:\n$(cat $branchSpecFile)\n" fi return 0 } #------------------------------------------------------------------------------ # Function: action_CLIENT_SPEC # # Input: # $1 - clientSpecFile # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_CLIENT_SPEC { vvmsg "CALL: action_CLIENT_SPEC ($*)" declare clientSpecFile=$1 msg "Loading hand-crafted branch spec from $branchSpecFile." if [[ $NO_OP -eq 0 ]]; then $P4 -s client -i < $branchSpecFile if [[ $? -eq 0 ]]; then vmsg "Loaded this client spec:\n$(cat $clientSpecFile)\n" else errmsg "Failed to load this client spec:\n$(cat $clientSpecFile)\n" return 1 fi else msg "NO_OP: Would have loaded this client spec:\n$(cat $clientSpecFile)\n" fi return 0 } #------------------------------------------------------------------------------ # Function: action_DEPOT_SPEC # # Input: # $1 - depotSpecFile # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_DEPOT_SPEC { vvmsg "CALL: action_DEPOT_SPEC ($*)" declare depotSpecFile=$1 msg "Loading hand-crafted depot spec from $depotSpecFile." if [[ $NO_OP -eq 0 ]]; then $P4 -s depot -i < $depotSpecFile if [[ $? -eq 0 ]]; then vmsg "Loaded this depot spec:\n$(cat $depotSpecFile)\n" else errmsg "Failed to load this depot spec:\n$(cat $depotSpecFile)\n" return 1 fi else msg "NO_OP: Would have loaded this depot spec:\n$(cat $depotSpecFile)\n" fi return 0 } #------------------------------------------------------------------------------ # Function: action_STREAM_SPEC # # Input: # $1 - streamSpecFile # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_STREAM_SPEC { vvmsg "CALL: action_STREAM_SPEC ($*)" declare streamSpecFile=$1 msg "Loading hand-crafted stream spec from $streamSpecFile." if [[ $NO_OP -eq 0 ]]; then $P4 -s stream -i < $streamSpecFile if [[ $? -eq 0 ]]; then vmsg "Loaded this stream spec:\n$(cat $streamSpecFile)\n" else errmsg "Failed to load this stream spec:\n$(cat $streamSpecFile)\n" return 1 fi else msg "NO_OP: Would have loaded this stream spec:\n$(cat $streamSpecFile)\n" fi return 0 } #------------------------------------------------------------------------------ # Function: action_DEPOT # # Input: # $1 - Depot Name # $2 - Depot Type # $3 - Depot Desc # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_DEPOT { vvmsg "CALL: action_DEPOT ($*)" declare depotName=$1 declare depotType=$2 declare depotDesc=$3 declare dSpecFile=/tmp/bbi.dspec.$$.$RANDOM msg "Creating $depotType depot //$depotName." if [[ $P4D_VERSION > 2015.2 ]]; then echo -e "Depot: $depotName\n\nOwner: $ImportUser\n\nDescription:\n\tCreated by $ImportUser.\n\nType: $depotType\n\nStreamDepth: //$depotName/1\n\nMap: $depotName/...\n\n" > $dSpecFile else echo -e "Depot: $depotName\n\nOwner: $ImportUser\n\nDescription:\n\tCreated by $ImportUser.\n\nType: $depotType\n\nMap: $depotName/...\n\n" > $dSpecFile fi vmsg "$(cat $dSpecFile)" if [[ $NO_OP -eq 0 ]]; then $P4 -s depot -i < $dSpecFile || return 1 runCmd "/bin/rm -f $dSpecFile" fi return 0 } #------------------------------------------------------------------------------ # Function: action_UPDATE # # Input: # $1 - Baseline Name # $2 - Path to baseline. Can be a directory, tar file, or zipped tar file. # $3 - Changelist description. # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_UPDATE { vvmsg "CALL: action_UPDATE ($*)" declare baseline=$1 declare targetPath=$2 declare changeDesc=$3 declare updateOptions=${4:-""} declare dir= declare subdir= declare startDir= declare streamSubdir= declare targetDepot= declare targetDepotType= declare stream= declare streamType= declare baselineOptions=${BaselineOptions[$baseline]} declare baselineSource=${Baselines[$baseline]} declare changeFormFile=/tmp/bbi.changeFormFile.$$.$RANDOM declare cSpecFile=/tmp/bbi.cspec.$$.$RANDOM declare lSpecFile=/tmp/bbi.lspec.$$.$RANDOM declare submitLog=/tmp/bbi.submit.$$.$RANDOM.log declare -i exitCode declare cmd= declare label= declare changelist= declare nonBranchingListFile= declare nonBranchingFile= declare astyleDirListFile= declare astyleTmpFile=/tmp/astyle.dl.$$.$RANDOM declare astyleTool= declare jsBeautifyTool= declare dos2unixExe= declare userCmd= declare userScript= declare file= action= rev= declare localFile= declare injectionScript= declare tmpFile=/tmp/bbi.tmp.$$.$RANDOM declare tmpFile2=/tmp/bbi.tmp2.$$.$RANDOM declare -i i=0 declare -i filesFound=0 declare -i jsCount=0 declare -i jsFailedCount=0 declare stagingDir=$WorkingDir/stage msg "Applying baseline $baseline to: $targetPath" if [[ $baselineSource == *.tar.gz || $baselineSource == *.tgz ||\ $baselineSource == *.tar || $baselineSource == *.zip ]]; then runCmd "/bin/rm -rf $stagingDir" \ "Cleaning up staging dir [$stagingDir]." 1 0 0 if [[ $CMDEXITCODE -ne 0 ]]; then runCmd "sudo /bin/rm -rf $stagingDir" \ "Second try using sudo: Cleaning up staging dir $stagingDir" 1 0 0 ||\ bail "Second attempt to clean staging dir [$stagingDir] using sudo failed." fi runCmd "/bin/mkdir -p $stagingDir" ||\ bail "Failed to create staging dir [$stagingDir]." if [[ $NO_OP -eq 0 ]]; then cd "$stagingDir" ||\ "Failed to cd to staging dir [$stagingDir]." msg "Now working in: $PWD" fi if [[ $baselineSource == *.tar ]]; then runCmd "tar -xpf $baselineSource" \ "Expanding tar file [$baselineSource]." ||\ bail "Failed to expand tar file [$baselineSource]." elif [[ $baselineSource == *.zip ]]; then runCmd "unzip $baselineSource" \ "Expanding zip file [$baselineSource]." ||\ bail "Failed to expand zipped tar file [$baselineSource]." else runCmd "tar -xzpf $baselineSource" \ "Expanding tar file [$baselineSource]." ||\ bail "Failed to expand zipped tar file [$baselineSource]." fi if [[ $baselineOptions == *RMTOP* ]]; then topDir=$(ls|head -1) vmsg "Removing top dir [$topDir] due to RMTOP option." runCmd "/bin/mv $topDir/* ." runCmd "/bin/rmdir $topDir" fi elif [[ $baselineSource == "CMD:"* ]]; then runCmd "/bin/rm -rf $stagingDir" \ "Cleaning up staging dir [$stagingDir]." 1 0 0 if [[ $CMDEXITCODE -ne 0 ]]; then runCmd "sudo /bin/rm -rf $stagingDir" \ "Second try using sudo: Cleaning up staging dir $stagingDir" 1 0 0 ||\ bail "Second attempt to clean staging dir [$stagingDir] using sudo failed." fi runCmd "/bin/mkdir -p $stagingDir" ||\ bail "Failed to create staging dir [$stagingDir]." cd "$stagingDir" || bail "Could not cd to staging dir [$stagingDir]." userCmd=${baselineSource#CMD:} userScript=/tmp/bbi.userScript.$$.$RANDOM.sh echo -e "#!/bin/bash\n\necho Running: $userCmd\n$userCmd\nExitCode=\$?\necho EXIT_CODE=\$ExitCode\nexit \$ExitCode\n" > $userScript chmod +x $userScript runCmd "$userScript" "Running script:\n$(cat $userScript)\n" 1 0 0 ||\ bail "User script to acquire baseline returned non-zero exit code." cd - > /dev/null elif [[ -d "$baselineSource" ]]; then stagingDir=$baselineSource else bail "Don't know how to handle baseline source [$baselineSource]. It is not a simple directory, tar file, or zipped tar file with a known extension." fi if [[ ! -d $ImportWSRoot ]]; then runCmd "/bin/mkdir -p $ImportWSRoot" "Re-initializing import workspace root dir [$ImportWSRoot]." ||\ bail "Failed to re-initialize import workspace root dir [$ImportWSRoot]." fi if [[ ! -d $VerifyWSRoot ]]; then runCmd "/bin/mkdir -p $VerifyWSRoot" "Re-initializing verify workspace root dir [$VerifyWSRoot]." ||\ bail "Failed to re-initialize verify workspace root dir [$VerifyWSRoot]." fi targetDepot=${targetPath#//} targetDepot=${targetDepot%%/*} targetDepotType=$($P4 -ztag -F %Type% depot -o $targetDepot) targetDepotDepth=$($P4 -ztag -F %StreamDepth% depot -o $targetDepot) targetDepotDepth=${targetDepotDepth##*/} map_workspace_to_path "$ImportWS" "$targetDepotType" "$targetDepotDepth" "$targetPath" ||\ bail "Failed to map workspace "$ImportWS" to path [$targetPath] $targetDepotType depot." map_workspace_to_path "$VerifyWS" "$targetDepotType" "$targetDepotDepth" "$targetPath" ||\ bail "Failed to map workspace "$VerifyWS" to path [$targetPath] $targetDepotType depot." runCmd "$P4C -s flush -q" "Flushing workspace with updated view." 1 0 0 ||\ return 1 if [[ $targetDepotType == stream ]]; then streamSubdir=$(get_stream_subdir "$targetPath" "$targetDepotDepth") else streamSubdir= fi if [[ -n "$streamSubdir" ]]; then if [[ ! -d "$ImportWSRoot/$streamSubdir" ]]; then runCmd "/bin/mkdir -p $ImportWSRoot/$streamSubdir" \ "Creating subdir under stream workspace root." ||\ bail "Failed to create subdir under workspace root: $ImportWSRoot/$streamSubdir" fi runCmd "$RSYNC -aq --delete $stagingDir/ $ImportWSRoot/$streamSubdir/." \ "Updating subdir of stream workspace root." else runCmd "$RSYNC -aq --delete $stagingDir/ $ImportWSRoot/." \ "Updating classic workspace root." fi if [[ $CMDEXITCODE -eq 0 ]]; then msg "Verified: rsync copied clean." else bail "The rsync exit code was $CMDEXITCODE. Do 'man rsync' to get details on rsync exit codes." fi if [[ -n "$streamSubdir" ]]; then cd "$ImportWSRoot/$streamSubdir" ||\ bail "Failed to cd to workspace stream subdir [$ImportWSRoot/$streamSubdir]." else cd "$ImportWSRoot" ||\ bail "Failed to cd to workspace root [$ImportWSRoot]." fi runCmd "chmod -R +w ." "Ensuring working area is writable." ||\ bail "Failed to do 'chmod -R +w .' in $PWD." msg "Now working in: $PWD\nP4Path: $($P4C -ztag -F '%depotFile%' where ...)\n" #--------------------------------------------------------------------------- msg "Seeking for usage of three consecutive dots in paths." # The original attempt here was to detect '...' in any arbitrary element of the # path name. But there was no immediate need for that, so for now I focused only # getting it to work for cases where '...' exists in a file name (but not any # directory in the fully qualified path). ### # Search in depth-first order, so we do replacements in the correct order. ### find $PWD -type d -name "*\.\.\.*" -print > $tmpFile ### ### if [[ -s $tmpFile ]]; then ### # Replace ellipses dirs. ### while read ed; do ### [[ -d "$ed" ]] || continue ### while [[ "$ed" == *"..."* ]]; do ### ned=${ed/\.\.\./___} ### [[ -d "$ned" ]] && warnmsg "Couldn't replace '...' to '___' for dir [$ed]; target already exists." ### warnmsg "Replacing detected occurences of '...' with '___' in dir [$ed]." ### mv -f "$ed" "$ned" ### ed=$ned ### done ### done < $tmpFile ### fi find $PWD -type f -name "*\.\.\.*" -print > $tmpFile if [[ -s $tmpFile ]]; then while read f; do [[ -f "$f" ]] || warnmsg "Find reported file [$f] with '...' but it disappeared." # Do a 'greedy match' replacement of all occurences of '...' with '___'. nf=${f//.../___} [[ -f "$nf" ]] && warnmsg "Couldn't replace '...' to '___' for file [$f]; target already exists." warnmsg "Replacing detected occurences of '...' with '___' in file [$f]." mv -f "$f" "$nf" done < $tmpFile fi /bin/rm -f $tmpFile #--------------------------------------------------------------------------- # Injection processing. # Run any hand-crafted injection scripts for this baseline. injectionScript="$BBIConfigDir/injections/before_UPDATE_${baseline}.sh" if [[ -r "$injectionScript" ]]; then runCmd "$injectionScript" "Executing this injection script:\n$injectionScript\nCONTENTS:\n$(cat $injectionScript)\nEND_CONTENTS\n" 1 0 0 ||\ bail "Injection Script Failed!" msg "Injection script completed OK." fi #--------------------------------------------------------------------------- # ASTYLE for C/C++/Java Processing, and beautify.sh for JavaScript. # ASTYLE and the JavaScript beautifier are not included in the BBI # package; they are 3rd party utils. if [[ "${updateOptions^^}" =~ ASTYLE ]]; then msg "Performing ASTYLE processing." startDir=$PWD astyleDirListFile=${BBIConfigDir}/astyle.${ImportTag}.dirs astyleTool=$(which astyle-new 2> /dev/null ||:) jsBeautifyTool=$(which beautify.sh 2> /dev/null ||:) [[ ! -x "$astyleTool" ]] && \ bail "Could not find executable astyle tool 'astyle-new' in PATH [$PATH]." [[ ! -x "$jsBeautifyTool" ]] && \ bail "Could not find executable JavaScript beautify tool 'beautify.sh' in PATH [$PATH]." [[ ! -r $astyleDirListFile ]] && \ bail "Could not find expected astyle directory list file [$astyleDirListFile]." # If the dir list file contains 'include:name' directive, process them. # Generate a temp dir list file. When including a directory from an included # file, prefix the path with 'name/', so 'include:foo' will prefix each path # with 'foo/'. grep -l '^include:' $astyleDirListFile > /dev/null 2>&1 if [[ $? -eq 0 ]]; then msg "Processing 'include:' directives in astyle dirs file $astyleDirListFile." grep -v '^include:' $astyleDirListFile > $astyleTmpFile for inc in $(grep '^include:' $astyleDirListFile); do incFile=${BBIConfigDir}/astyle.${inc#include:}.dirs # If we're importing into a subdirectory of the root of a Stream, ignore # 'include' directives for subdirectories other than the one we're importing. if [[ -n "$streamSubdir" ]]; then if [[ "$streamSubdir" != "${inc#include:}" ]]; then msg "Ignoring include directive [$inc] while in stream subdir $streamSubdir." continue fi fi [[ ! -r "$incFile" ]] && \ bail "Missing astyle dirs file $incFile referenced in $astyleDirListFile." echo -e "\n# BEGIN includes from $incFile:" >> $astyleTmpFile while read subdir; do [[ -z "$(echo $subdir)" ]] && continue [[ "$subdir" == "#"* ]] && continue styleType=${subdir%%:*} styleDir=${subdir##*:} # If we're importing into the stream root in a Stream depot, or in a Classic depot, # prefix the directory as listed in hte inluced file with the prefix directory specified # in the 'include' directive. However, if we're importing into a subdir of the stream # root, then we assume that subdir is the same as that in the include directive, # and we can use the directory as listed in the included file verbatim. if [[ -n "$streamSubdir" ]]; then echo "$styleType:$styleDir" >> $astyleTmpFile else echo "$styleType:${inc#include:}/$styleDir" >> $astyleTmpFile fi done < $incFile echo -e "\n# END includes from $incFile." >> $astyleTmpFile done else msg "Processing astyle dirs listed in $astyleDirListFile." astyleTmpFile="$astyleDirListFile" fi msg "Using this list of style processing directives:" cat $astyleTmpFile while read subdir; do [[ -z "$(echo $subdir)" ]] && continue [[ "$subdir" == "#"* ]] && continue styleType=${subdir%%:*} styleDir=${subdir##*:} dir="$startDir/$styleDir" if [[ -d "$dir" ]]; then cd "$dir" || bail "Could not cd to [$dir]." case ${styleType} in (C) astyleOpts="--style=allman --indent-switches --indent-namespaces --indent-classes --indent=spaces=4 --suffix=none" msg "Running $astyleTool for C/C++ files in $PWD\nArtistic Style Options: $astyleOpts" filesFound=0 if ls *.cpp > /dev/null 2>&1; then $astyleTool *.cpp $astyleOpts ||\ warnmsg "The $astyleTool tool failed processing *.cpp files in $PWD." filesFound=1 fi if ls *.c > /dev/null 2>&1; then $astyleTool *.c $astyleOpts ||\ warnmsg "The $astyleTool tool failed processing *.c files in $PWD." filesFound=1 fi if ls *.h > /dev/null 2>&1; then $astyleTool *.h $astyleOpts ||\ warnmsg "The $astyleTool tool failed processing *.h files in $PWD." filesFound=1 fi [[ $filesFound -eq 0 ]] && warnmsg "C/C++ files expected, but none were found in $PWD." ;; (Java) astyleOpts="--recursive --style=java --lineend=linux --indent=spaces=4 --suffix=none" find . -name "*.java" -print > $tmpFile if [[ -s $tmpFile ]]; then msg "Running $astyleTool for Java files in and under $PWD\nArtistic Style Options: $astyleOpts" $astyleTool '*.java' $astyleOpts ||\ warnmsg "The $astyleTool tool failed processing Java files in and under $PWD." else warnmsg "Java files expected, but none were found in $PWD." fi ;; (JavaScript) find $PWD -type f -name "*.js" -print | grep -v 'min.js$' > $tmpFile jsCount=0 jsFailedCount=0 if [[ -s $tmpFile ]]; then msg "Running $jsBeautifyTool for JavaScript (*.js) files (excluding *min.js) in $PWD." while read jsFile; do /bin/cp -f "$jsFile" "${jsFile}.tmp.$$" $jsBeautifyTool "${jsFile}.tmp.$$" if [[ $? -eq 0 ]]; then /bin/mv -f "${jsFile}.tmp.$$" "$jsFile" else warnmsg "The $jsBeautifyTool tool failed processing JavaScript file [$jsFile]. The original file was left unmodified." jsFailedCount=$((jsFailedCount+1)) /bin/rm -f "${jsFile}.tmp.$$" fi jsCount=$((jsCount+1)) done < $tmpFile if [[ $jsFailedCount -eq 0 ]]; then msg "Ran $jsBeautifyTool for $jsCount JavaScript file(s). All ran OK." else msg "Ran $jsBeautifyTool for $jsCount JavaScript file(s). $jsFailedCount of $jsCount failed." fi else warnmsg "JavaScript files expected, but none were found in $PWD." fi ;; (*) bail "Unrecognized style processing [$styleType]; must be C, Java, or JavaScript." ;; esac else warnmsg "Dir [$dir] specified for style processing did not exist and skipped." fi done < $astyleTmpFile if [[ -n "$streamSubdir" ]]; then cd "$ImportWSRoot/$streamSubdir" ||\ bail "Failed to cd to workspace stream subdir [$ImportWSRoot/$streamSubdir]." else cd "$ImportWSRoot" ||\ bail "Failed to cd to workspace root [$ImportWSRoot]." fi msg "The ASTYLE processing is complete. Returned to directory [$PWD]." fi [[ -f $tmpFile ]] && /bin/rm -f $tmpFile #--------------------------------------------------------------------------- # Do the reconcile. # The reconcile is performed in multiple steps to avoid triggering # rename detection, which can be very costly in a baseline & branch # import, where each import represents the culmination of perhaps # months of effort. Reconcile and specifically rename detection is # optimzed for a small amount of incremental change. if [[ $AttemptRenameDetection -eq 1 ]]; then runCmd "$P4C -s reconcile -f" "Reconciling adds/edits/deletes/renames" 1 0 0 ||\ bail "Failed to reconcile (adds/edits/deletes/renames)." else runCmd "$P4C -s reconcile -a -f" "Reconciling adds." 1 0 0 ||\ bail "Failed to reconcile (adds only)." runCmd "$P4C -s reconcile -d" "Reconciling deletes." 1 0 0 ||\ bail "Failed to reconcile (deletes only)." runCmd "$P4C -s reconcile -e" "Reconciling edits." 1 0 0 ||\ bail "Failed to reconcile (edits only)." fi #--------------------------------------------------------------------------- # Do DOS2UNIX processing if specified. if [[ "${updateOptions^^}" =~ DOS2UNIX ]]; then msg "Performing DOS2UNIX processing on text-based files opened for add, edit, or move/add." dos2unixExe=$(which dos2unix 2> /dev/null ||:) [[ ! -x "$dos2unixExe" ]] && \ bail "Could not find executable 'dos2unix' utility in PATH [$PATH]. Perahps try:\n\tsudo yum install -y dos2unix\n" tmpFile=/tmp/bbi.tmp.dos2unix_files.txt # For dos2unix processing, We ignore delete and move/delete for obvious # reasons. We ignore branch and integ; branch is a copy by def'n, and integ # will always be a copy in the context of this BBI script. We process files # opened for add, edit, and move/add actions. $P4C -ztag -F "%action% %type% %depotFile%" opened |\ egrep '^(add|move/add|edit) .*text.* //' > $tmpFile if [[ -s $tmpFile ]]; then i=0 while read file; do file="//${file#*//}" localFile=$($P4C -ztag -F '%path%' where "$file") $dos2unixExe "$localFile" $P4C revert -a "$localFile" i=$((i+1)) done < $tmpFile msg "Ran dos2unix on $i text file(s)." else msg "No files require DOS2UNIX processing for this update." fi /bin/rm -f $tmpFile fi #--------------------------------------------------------------------------- # Process Streams Non-Branching files, if any. Non-Branching files # are files in the //.nb depot, which must have the following behaviours: # # 1. If opened for 'edit', they must be larger than the prior version. # 2. They cannot be opened for delete. # # If either of these isn't true, the non-branching file is simply reverted. $P4C -ztag -F '%action%:%rev%:%depotFile%' opened > $tmpFile if [[ -s $tmpFile ]]; then while read data; do action=${data%%:*} rev=${data#*:} rev=${rev%%:*} file=${data##*:} action=$(echo $action) rev=$(echo $rev) file=$(echo $file) [[ $file == "//.nb/"* ]] || continue # For edits, make sure file size always grows. if [[ $action == edit ]]; then localFile=$($P4C -ztag -F '%path%' where $file) $P4C print -q -o $tmpFile2 ${file}#${rev} oldFileSize=$(wc -c $tmpFile2 | cut -d ' ' -f 1) newFileSize=$(wc -c $localFile | cut -d ' ' -f 1) if [[ $newFileSize -gt $oldFileSize ]]; then msg "Verified: New non-branching file $file size ($newFileSize) is\nbigger than the earlier version ($oldFileSize)." else msg "Reverting Non-branching file $file as size ($newFileSize) is\nnot bigger than the earlier version ($oldFileSize)." $P4C -s revert $file fi elif [[ $action == *"delete" ]]; then msg "Preventing delete of non-branching file $file." $P4C -s revert $file fi done < $tmpFile fi #--------------------------------------------------------------------------- # Submit any changes. if [[ -n "$($P4C -ztag -F "%depotFile%" opened -m1)" ]]; then $P4C change -o | sed "s/<enter description here>/$changeDesc/g" |\ $PERL -e "while(<>){last if /^Jobs:/; print;}" > $changeFormFile if [[ $NO_OP -eq 0 ]]; then if [[ $NetParallelMax -gt 1 ]]; then msg "Submitting in parallel ..." cmd="$P4C -s submit --parallel=threads=$NetParallelMax" else msg "Submitting ..." cmd="$P4C -s submit" fi echo Running: $cmd > $submitLog $cmd -i < $changeFormFile > $submitLog 2>&1 exitCode=$? cat $submitLog [[ $exitCode -ne 0 ]] && return 1 GARBAGE+=" $changeFormFile" # Do LABEL processing if specified. if [[ "${updateOptions^^}" =~ LABEL ]]; then label=$(echo ${updateOptions##*LABEL:}) label=${label%% *} if [[ -n "$label" ]]; then changelist=$($P4C -ztag -F '%change%' changes -c $ImportWS -s submitted -m 1 $targetPath) msg "Generating label $label for changelist $changelist." echo -e "Label: $label\n\nOwner: p4import\n\nDescription:\n\tCreated by p4import.\n\nView:\n\t$targetPath\n\nRevision: @$changelist\n\n" > $lSpecFile $P4C -s label -i < $lSpecFile || bail "Failed to load label spec:\n$(cat $lSpecFile)\n" else warnmsg "Could not determine label name. Ignoring." fi fi else msg "NO_OP: Would submit changelist with updates here." fi if [[ "${updateOptions^^}" =~ VERIFY ]]; then if [[ "${updateOptions^^}" =~ DOS2UNIX || "${updateOptions^^}" =~ ASTYLE ]]; then warnmsg "Skipping VERIFY for this baseline because VERIFY is not possible when ASTYLE or DOS2UNIX are used. Uptation options for this baseline are: $updateOptions." else msg "Performing VERIFY for imported baseline $baseline." runCmd "$P4VC -s flush -q @0" "Flushing verify workspace $VerifyWS." 1 0 0 ||\ bail "Failed to remove verification workspace [$VerifyWS]." if [[ -d "$VerifyWSRoot" ]]; then runCmd "/bin/rm -rf $VerifyWSRoot" "Pre-sync cleaning verify workspace $VerifyWS." 1 0 0 ||\ bail "Pre-sync cleaning of verify workspace $VerifyWS FAILED." fi runCmd "$P4VC -s sync -q" "Syncing verify workspace $VerifyWS." 1 0 0 ||\ bail "Failed to sync verify workspace!" if [[ -n "$streamSubdir" ]]; then diffTargetDir="$VerifyWSRoot/$streamSubdir" else diffTargetDir="$VerifyWSRoot" fi runCmd "$DIFF -qr --no-dereference $stagingDir $diffTargetDir" \ "Diffing $stagingDir vs. $diffTargetDir" ||\ bail "Verify for baseline $baseline FAILED." msg "Baseline $baseline Verified OK." fi fi else warnmsg "No changes detected for baseline $baseline." fi return 0 } #------------------------------------------------------------------------------ # Function: action_COPY # # Input: # $1 - Path 1 (or literal BRANCH_SPEC or BRANCH_SPEC-r) # $2 - Path 2 # $3 - Changelist Desc # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_COPY { vvmsg "CALL: action_COPY ($*)" declare path1=$1 declare path2=$2 declare sourcePath= declare targetPath= declare branchSpec= declare changeDesc=${3:-default} declare targetDepot= declare targetDepotType= declare changeFormFile=/tmp/bbi.changeFormFile.$$.$RANDOM declare submitLog=/tmp/bbi.submit.$$.$RANDOM.log declare -i exitCode declare cmd= cmd="$P4C -s copy" if [[ ${path1^^} == BRANCH_SPEC ]]; then branchSpec=$path2 cmd="$cmd -b $branchSpec" targetPath=$($P4 -ztag -F '%View0%' branch -o $branchSpec) targetPath=${targetPath#//} targetPath="//${targetPath##*//}" elif [[ ${path1^^} == BRANCH_SPEC-R ]]; then branchSpec=$path2 cmd="$cmd -r -b $branchSpec" echo "targetPath=\$($P4 -ztag -F '%View0%' branch -o $branchSpec)" targetPath=$($P4 -ztag -F '%View0%' branch -o $branchSpec) targetPath="${targetPath%% //*}" else sourcePath="$path1" targetPath="$path2" cmd="$cmd $sourcePath $targetPath" fi targetDepot="${targetPath#//}" targetDepot="${targetDepot%%/*}" targetDepotType=$($P4 -ztag -F %Type% depot -o $targetDepot) targetDepotDepth=$($P4 -ztag -F %StreamDepth% depot -o $targetDepot) targetDepotDepth=${targetDepotDepth##*/} msg "Copying to $targetPath ($targetDepotType depot)." map_workspace_to_path "$ImportWS" "$targetDepotType" "$targetDepotDepth" "$targetPath" ||\ bail "Failed to map workspace "$ImportWS" to path [$targetPath] $targetDepotType depot." runCmd "$P4C -s flush -q" "Flushing workspace with updated view." ||\ return 1 runCmd "$cmd" "Copying files using: $cmd" 1 0 0||\ return 1 if [[ -n "$($P4C -ztag -F "%depotFile%" opened -m1)" ]]; then $P4C change -o | sed "s/<enter description here>/$changeDesc/g" |\ $PERL -e "while(<>){last if /^Jobs:/; print;}" > $changeFormFile if [[ $NO_OP -eq 0 ]]; then if [[ $NetParallelMax -gt 1 ]]; then msg "Submitting in parallel ..." cmd="$P4C -s submit --parallel=threads=$NetParallelMax" else msg "Submitting ..." cmd="$P4C -s submit" fi echo Running: $cmd > $submitLog $cmd -i < $changeFormFile > $submitLog 2>&1 exitCode=$? cat $submitLog [[ $exitCode -ne 0 ]] && return 1 GARBAGE+=" $changeFormFile" else msg "NO_OP: Would submit changelist with updates here." fi else warnmsg "Copy to $targetPath resulted in no changes." fi return 0 } #------------------------------------------------------------------------------ # Function: action_RECORD_MERGE # # Input: # $1 - Path 1 (or literal BRANCH_SPEC or BRANCH_SPEC-r) # $2 - Path 2 # $3 - Changelist Desc # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_RECORD_MERGE { vvmsg "CALL: action_RECORD_MERGE ($*)" declare path1=$1 declare path2=$2 declare sourcePath= declare targetPath= declare branchSpec= declare changeDesc=${3:-default} declare targetDepot= declare targetDepotType= declare changeFormFile=/tmp/bbi.changeFormFile.$$.$RANDOM declare submitLog=/tmp/bbi.submit.$$.$RANDOM.log declare -i exitCode declare cmd= cmd="$P4C -s merge" if [[ ${path1^^} == BRANCH_SPEC ]]; then branchSpec=$path2 cmd="$cmd -b $branchSpec" targetPath=$($P4 -ztag -F '%View0%' branch -o $branchSpec) targetPath=${targetPath#//} targetPath="//${targetPath##*//}" elif [[ ${path1^^} == BRANCH_SPEC-R ]]; then branchSpec=$path2 cmd="$cmd -r -b $branchSpec" targetPath=$($P4 -ztag -F '%View0%' branch -o $branchSpec) targetPath="${targetPath%% //*}" else sourcePath="$path1" targetPath="$path2" cmd="$cmd $sourcePath $targetPath" fi targetDepot="${targetPath#//}" targetDepot="${targetDepot%%/*}" targetDepotType=$($P4 -ztag -F %Type% depot -o $targetDepot) targetDepotDepth=$($P4 -ztag -F %StreamDepth% depot -o $targetDepot) targetDepotDepth=${targetDepotDepth##*/} msg "Recording merge to $targetPath ($targetDepotType depot)." map_workspace_to_path "$ImportWS" "$targetDepotType" "$targetDepotDepth" "$targetPath" ||\ bail "Failed to map workspace "$ImportWS" to path [$targetPath] $targetDepotType depot." runCmd "$P4C -s sync -q" "Syncing workspace with updated view." 1 0 0 ||\ return 1 runCmd "$cmd" "Merging files using: $cmd" 1 0 0 ||\ return 1 if [[ -n "$($P4C -ztag -F "%depotFile%" opened -m1)" ]]; then runCmd "$P4C -s resolve -ay" "Resolving files." 1 0 0 ||\ return 1 $P4C change -o | sed "s/<enter description here>/$changeDesc/g" |\ $PERL -e "while(<>){last if /^Jobs:/; print;}" > $changeFormFile if [[ $NO_OP -eq 0 ]]; then if [[ $NetParallelMax -gt 1 ]]; then msg "Submitting in parallel ..." cmd="$P4C -s submit --parallel=threads=$NetParallelMax" else msg "Submitting ..." cmd="$P4C -s submit" fi echo Running: $cmd > $submitLog $cmd -i < $changeFormFile > $submitLog 2>&1 exitCode=$? cat $submitLog [[ $exitCode -ne 0 ]] && return 1 GARBAGE+=" $changeFormFile" else msg "NO_OP: Would submit changelist with updates here." fi else warnmsg "Record merge to $targetPath resulted in no changes." fi return 0 } #------------------------------------------------------------------------------ # Function: action_POPULATE # # Input: # $1 - Path 1 (or literal BRANCH_SPEC or BRANCH_SPEC-r) # $2 - Path 2 # $3 - Changelist Desc # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_POPULATE { vvmsg "CALL: action_POPULATE ($*)" declare path1=$1 declare path2=$2 declare changeDesc=${3:-default} declare cmd="$P4 -s populate -f" [[ $changeDesc != default ]] && cmd="$cmd -d '$changeDesc'" if [[ ${path1^^} == BRANCH_SPEC ]]; then cmd="$cmd -b $path2" elif [[ ${path1^^} == BRANCH_SPEC-R ]]; then cmd="$cmd -r -b $path2" else cmd="$cmd $path1 $path2" fi runCmd "$cmd" "Populating with command: $cmd." 1 0 0 ||\ return 1 return 0 } #------------------------------------------------------------------------------ # Function: action_MOVE # # Input: # $1 - Path 1 # $2 - Path 2 # $3 - Changelist Desc # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. #------------------------------------------------------------------------------ function action_MOVE { vvmsg "CALL: action_MOVE ($*)" declare path1="$1" declare path2="$2" declare changeDesc=${3:-default} declare changeFormFile=/tmp/bbi.changeFormFile.$$.$RANDOM declare submitLog=/tmp/bbi.submit.$$.$RANDOM.log declare -i exitCode declare cmd= declare targetDepot= declare targetDepotType= targetDepot="${path2#//}" targetDepot="${targetDepot%%/*}" targetDepotType=$($P4 -ztag -F %Type% depot -o $targetDepot) targetDepotDepth=$($P4 -ztag -F %StreamDepth% depot -o $targetDepot) targetDepotDepth=${targetDepotDepth##*/} msg "Moving to $path2 ($targetDepotType depot)." map_workspace_to_path "$ImportWS" "$targetDepotType" "$targetDepotDepth" "$path2" ||\ bail "Failed to map workspace "$ImportWS" to path [$path2] $targetDepotType depot." runCmd "$P4C -s sync -q" "Syncing workspace with updated view." 1 0 0 ||\ return 1 runCmd "$P4C -s edit $path1" "Editing prior to rename." 1 0 0 ||\ bail "Edit prior to rename failed." runCmd "$P4C -s move $path1 $path2" "Renaming." 1 0 0 ||\ bail "Rename failed." if [[ -n "$($P4C -ztag -F '%depotFile%' opened -m1)" ]]; then $P4C change -o | sed "s/<enter description here>/$changeDesc/g" |\ $PERL -e "while(<>){last if /^Jobs:/; print;}" > $changeFormFile if [[ $NO_OP -eq 0 ]]; then if [[ $NetParallelMax -gt 1 ]]; then msg "Submitting in parallel ..." cmd="$P4C -s submit --parallel=threads=$NetParallelMax" else msg "Submitting ..." cmd="$P4C -s submit" fi echo Running: $cmd > $submitLog $cmd -i < $changeFormFile > $submitLog 2>&1 exitCode=$? cat $submitLog [[ $exitCode -ne 0 ]] && return 1 GARBAGE+=" $changeFormFile" else msg "NO_OP: Would submit changelist with updates here." fi else warnmsg "MOVE to $path2 resulted in no changes." fi return 0 } #------------------------------------------------------------------------------ # Function: action_STREAM # # Create a stream spec, and configure the import workspace to use it. # # Globals Variables are uppercase-initiated, e.g. $ImportWS, while local # variables are lowercase-initiated, e.g. $baseline. # #------------------------------------------------------------------------------ function action_STREAM { vvmsg "CALL: action_STREAM ($*)" declare streamPath=$1 declare streamType=$2 declare streamParent=$3 declare streamDesc=${4:-default} declare streamOptions=${5:-default} declare streamOwner=$ImportUser declare sSpecFile=/tmp/bbi.sspec.$$.$RANDOM declare streamDepot= declare streamName= streamDepot=${streamPath#//} streamDepot=${streamDepot%/*} streamName=${streamPath##*/} if [[ -n "$($P4 -ztag -F '%Update%' stream -o $streamPath)" ]]; then msg "Skipping update of existing stream $streamPath." else msg "Creating $streamType stream $streamPath." # If the user has not defined stream options, use the current 'p4d' default # stream options for a stream of this type. if [[ $streamOptions == default ]]; then if [[ $streamType == mainline ]]; then streamOptions=$($P4 -ztag -F "%Options%" stream -t $streamType -o $streamPath 2>/dev/null) else streamOptions=$($P4 -ztag -F "%Options%" stream -t $streamType -P $streamParent -o $streamPath 2>/dev/null) fi fi [[ $streamDesc == default ]] && streamDesc="Created by $ImportUser." echo -e "Stream: $streamPath\n\nOwner: $ImportUser\n\nName: $streamName\n\nParent: $streamParent\n\nType: $streamType\n\nDescription:\n\t$streamDesc\n\nOptions: $streamOptions\n\nPaths:\n\tshare ...\n\n" > $sSpecFile vmsg "Generated stream spec:\n$(cat $sSpecFile)" if [[ $NO_OP -eq 0 ]]; then $P4 -s stream -i < $sSpecFile || return 1 else msg "NO_OP: Would generate stream $streamPath." fi fi map_workspace_to_path "$ImportWS" stream 1 "$streamPath" ||\ bail "Failed to map workspace "$ImportWS" to path [$streamPath] in stream depot." return 0 } #------------------------------------------------------------------------------ # Function: baseline_and_branch_import # # Input: None. Global variables are referenced. # # Environment Dependency: P4CONFIG must be defined. # # Globals Referenced: See load_actions() in bbi_load_and_verify.lib for a # list of globals referenced. This references the same values loaded in that # function. # # Additional Globals Referenced: # ImportUser # ImportWS # ImportWSRoot # # Return: # 0 - Import ran OK. # 1 - Errors detected. #------------------------------------------------------------------------------ function baseline_and_branch_import { vvmsg "CALL: baseline_and_branch_import ($*)" declare -a errors declare -i errorCount=0 declare -i i=0 msg "${H}\nStarting import at $(date).\n" prep_for_import ||\ bail "Failure preparing for import." i=1; while [[ $i -lt ${#ActionType[*]} ]]; do case ${ActionType[$i]} in (BRANCH_SPEC) msg "ACTION $i: ${ActionType[$i]}" action_BRANCH_SPEC "${ActionBranchSpecFile[$i]}" ||\ bail "Failed to load hand-crafted branch spec file ${ActionBranchSpecFile[$i]}" ;; (DEPOT_SPEC) msg "ACTION $i: ${ActionType[$i]}" action_DEPOT_SPEC "${ActionDepotSpecFile[$i]}" ||\ bail "Failed to load hand-crafted depot spec file ${ActionDepotSpecFile[$i]}" ;; (STREAM_SPEC) msg "ACTION $i: ${ActionType[$i]}" action_STREAM_SPEC "${ActionStreamSpecFile[$i]}" ||\ bail "Failed to load hand-crafted stream spec file ${ActionStreamSpecFile[$i]}" ;; (DEPOT) msg "ACTION $i: ${ActionType[$i]}" action_DEPOT "${ActionDepotName[$i]}" "${ActionDepotType[$i]}" \ "${ActionDesc[$i]}" ||\ bail "Failed to create ${ActionDepotType[$i]} depot //${ActionDepotName[$i]}" ;; (UPDATE) msg "ACTION $i: ${ActionType[$i]}" action_UPDATE "${ActionBaseline[$i]}" "${ActionPath1[$i]}" \ "${ActionDesc[$i]}" "${ActionUpdateOptions[$i]}" ||\ bail "Action UPDATE failed to apply baseline ${ActionBaseline[$i]}." ;; (POPULATE) msg "ACTION $i: ${ActionType[$i]}" action_POPULATE "${ActionPath1[$i]}" "${ActionPath2[$i]}" \ "${ActionDesc[$i]}" ||\ bail "Action POPULATE to ${ActionPath2[$i]} failed." ;; (COPY) msg "ACTION $i: ${ActionType[$i]}" action_COPY "${ActionPath1[$i]}" "${ActionPath2[$i]}" \ "${ActionDesc[$i]}" ||\ bail "Action COPY to ${ActionPath2[$i]} failed." ;; (MOVE) msg "ACTION $i: ${ActionType[$i]}" action_MOVE "${ActionPath1[$i]}" "${ActionPath2[$i]}" \ "${ActionDesc[$i]}" ||\ bail "Action MOVE to ${ActionPath2[$i]} failed." ;; (RECORD_MERGE) msg "ACTION $i: ${ActionType[$i]}" action_RECORD_MERGE "${ActionPath1[$i]}" "${ActionPath2[$i]}" \ "${ActionDesc[$i]}" ||\ bail "Action RECORD_MERGE to ${ActionPath2[$i]} failed." ;; (STREAM) msg "ACTION $i: ${ActionType[$i]}" msg "Creating ${ActionStreamType[$i]} stream ${ActionStreamPath[$i]}." action_STREAM "${ActionStreamPath[$i]}" "${ActionStreamType[$i]}" \ "${ActionStreamParent[$i]}" "${ActionStreamDesc[$i]}" \ "${ActionStreamOptions[$i]}" ||\ bail "Failed to create and bind workspace to stream ${ActionStreamPath[$i]}." ;; (*) errors[$errorCount]="Invalid action type detected at run time: [${ActionType[$i]}]." errorCount+=1 ;; esac if [[ $StepMode -eq 1 ]]; then echo -n "STEP MODE: ${ActionType[$i]} action completed - Press <Return> to continue...." read x </dev/tty fi i+=1 done if [[ $errorCount -eq 0 ]]; then return 0 else return 1 fi }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#58 | 19783 | C. Thomas Tyler |
Fixed bug in processing of DOS2UNIX option of UPDATE action. Now dos2unix run on files opened for add, edit, and move/add. Corrected message to account for DOS2uNIX option for UPDATE tag now applying to files opened add, edit, and move/add The message is now consistent with the logic in the script (which also now works as intended). |
||
#57 | 19649 | C. Thomas Tyler | Tweaked DOS2UNIX logic to apply to adds, edits, and move/adds. | ||
#56 | 19648 | C. Thomas Tyler | Picked up Kathy's rollback (but incremented version number anyway). | ||
#55 | 19644 | C. Thomas Tyler | Picked up Kathy's change to DOS2UNIX behavior. | ||
#54 | 19070 | C. Thomas Tyler |
Fixed UPDATE action for stream when StreamDepth>1. Made get_stream_subdir() and get_stream in bbi_paths.sh accept a depth parameters, and modified calls in bbi_acitons.sh to determine a value for the depth paramters and pass it in. Added unit test cases for StreamDepth>1. Added full integration test case to the test suite. |
||
#53 | 18861 | C. Thomas Tyler | Fixed bugs after a round of QA. | ||
#52 | 18860 | C. Thomas Tyler | Enhanced handling of non-brancing files. | ||
#51 | 18716 | C. Thomas Tyler |
Added logic to make a second attempt to execute failed staging area removals (using 'rm -rf'), but using 'sudo' on the second attempt. |
||
#50 | 18702 | C. Thomas Tyler |
Tweaked the JavaScript beautifier to preserve the original JavaScript unmodified if the beautifier tool fails to beautify it (i.e. returns a non-zero exist status). Consistent use of quotes for $tmpFile, which is reliably defined not to have spaces or funky characters in its name and doesn't need the clutter of quoting (which otherwise is often a best practice). |
||
#49 | 18699 | C. Thomas Tyler | Made warnings more consistent for different varieties of ASTYLE processing. | ||
#48 | 18698 | C. Thomas Tyler |
Tweaked to do the 'chmod -R +w .' just one time for the entire import workspace tree. |
||
#47 | 18697 | C. Thomas Tyler |
Added reporting of files by name which fail JavaScript beautification. Tweaked some 'find' commands to use $PWD rather than '.' to capture full file names for errors. |
||
#46 | 18661 | C. Thomas Tyler |
Robustness tweak: Followed best practice and defacto standard of ignoring comments and blank lines in the astyle.*.dirs files. |
||
#45 | 18654 | C. Thomas Tyler |
Added support for replacing files with '...' in the file name. Added test case for file with '...' in the name. Fixed test data causing COPY actions to appear to fail. Fixed test data causing ASTYLE to fail for Classic Perforce. |
||
#44 | 18649 | C. Thomas Tyler |
Fixed ASTYLE processing of 'include:' directives for scenario where we import at a level below the stream workspace root. Minor cosmetic tweak to DOS2UNIX processing. |
||
#43 | 18648 | C. Thomas Tyler | Another tweak for the MOVE action. | ||
#42 | 18647 | C. Thomas Tyler |
Fixed BUG in MOVE action when importing to 'complex' stream workspaces (those where we import below the stream root). |
||
#41 | 18646 | C. Thomas Tyler | Fixed bug in 'include' path for ASTYLE processing. | ||
#40 | 18644 | C. Thomas Tyler |
Added support for enhanced astyle dirs file format: Each line now has a prefix: C: Look for *.c, *.cpp, and *.h files in given dirs. JavaScript: Look for *.js files in given dirs. Java: Look for *.java files recursively in in given trees. include:<component_file> includes contents of another file. C/C++ and Java are formatted using astyle. JavaScript is formatted using beautify.sh. Added simulated beautify.sh script to support test suite update to test JavaScript beautification. |
||
#39 | 18503 | C. Thomas Tyler | Removed spurious text. | ||
#38 | 18457 | C. Thomas Tyler |
Added CLIENT_SPEC action. Added VERIFY option to UPDATE action. Fixed RENAME option, renamed RENAME to MOVE, and added RENAME as a synonym for MOVE. Shortened error messages by removing redundant 'Aborting' comment in bail() calls, as messages are already prefixed with 'FATAL:'. Enhanced auditing and fixed issues with parallel submits. Updated BBI Config File require version to 3.6.0. |
||
#37 | 18456 | C. Thomas Tyler | Fixed variable name typo. | ||
#36 | 18452 | C. Thomas Tyler |
Completed implementation of parallels submit. Enhanced auditability. |
||
#35 | 18451 | C. Thomas Tyler |
Performance enhancement: Now does parallel submits if net.parallel.max > 1. |
||
#34 | 18442 | C. Thomas Tyler | Tweaked! | ||
#33 | 18439 | C. Thomas Tyler | Tweaked ASTYLE processing. | ||
#32 | 18438 | C. Thomas Tyler |
Implemented 'Injection script' mechanism, to allow for running hand-crafted corrective action scripts to handle symlink refactoring conversions (e.g. symlink to a file replaced with a file). |
||
#31 | 18410 | C. Thomas Tyler |
Implemented 'CMD:' prefix for baseline definintions, and added sample config file to illustrate pulling from Git Hub. Updated BBIJunkFiles.txt to exclude import of .git foldres. Added test case and updatd test suite to call it. |
||
#30 | 18409 | C. Thomas Tyler |
Adjusted rsync command for processing tarfiles that apply to a subdirectory of a stream workspace root. |
||
#29 | 18408 | C. Thomas Tyler |
BBI Config File format updated to 3.5.1. RENAME action support has been re-added. |
||
#28 | 18407 | C. Thomas Tyler |
Added support for using branch specs for POPULATE, COPY, and RECORD_MERGE actions. Added support for custom description for POPULATE (which before just printed a message indicating custom messages were ignored). Adjusted test suite to test. |
||
#27 | 18402 | C. Thomas Tyler |
bbi.sh v3.5.1: Added support for BRANCH_SPEC, DEPOT_SPEC, and STREAM_SPEC actions, which allow imports to use hand-crafted spec files during imports. This allows the BBI import process to simulate the evolution of stream specs over time, e.g. to reflect reparenting, and to account for things like non-branching files and CBD workflows that use sophisticated, hand-crafted stream specs. The required BBI Config file version has been updated from 3.2 to 3.5. Test suite has been updated to test new functionality. |
||
#26 | 18394 | C. Thomas Tyler |
Implemented labeling feature. Added doc for label feature. Added preflight checks for malformed label tags. |
||
#25 | 18389 | C. Thomas Tyler |
Enhanced astyle processing to do recursive search for *.java files in specified directories while searching only in specified directories for *.(c|cpp|h) files. Added sample *.java file to the test suite for testing Java style. |
||
#24 | 18387 | C. Thomas Tyler |
Implemented the DOS2UNIX option for the UDPATE action. Updated test suite to apply DOS2UNIX. Documented DOS2UNIX in BBIConfigFileFormat.txt, and enhanced ASTYLE documentation as well. |
||
#23 | 18379 | C. Thomas Tyler |
Fixed bug in depot spec generation. Fixed a bug in the DEPOT action where the generated depot spec had a 'Type:' field with only a single newline rather than a double-newline. I suspect this will fix spurious failures reported by Adrian Waters where there was an error related to the StreamDepth field, which this script doesn't interact with. It's not clear why the failure was only spurious, but this should put an end to it once and for all. #review-18380 @adrian_waters |
||
#22 | 18376 | C. Thomas Tyler |
Just incremented version numbers for Adrian's changes. No functional changes. |
||
#21 | 18375 | adrian_waters |
Add 'Step Mode' (-S argument) so process pauses (for user input) between each configuration file action #review @ttyler |
||
#20 | 18219 | C. Thomas Tyler |
Fixed bug in RECORD_MERGE processing. After BBI creates the temporary workspace and maps it to a path on the server, it does a 'p4 flush' rather than 'p4 sync' prior to doing UPDATE, COPY, or RECORD_MERGE processing. That's a performance optimization; flush is a 1000x faster than a sync, since it only says it syncs files, without actually syncing them. For UPDATE and COPY actions, it's entirely appropriate to skip the actual sync, since UPDATE and COPY put the correct file content they want in place anyway. But for RECORD_MERGE, which needs to do a 'resolve' check, the fact that it did a 'flush' and not a real 'sync' mattered, since it really needs the workspace contents to be accurate before the resolve. That's where the tamper check saved the day. Perforce was thinking, "OK, these should match the target files exactly, with no change, since a 'resolve -ay' was done. And when it went to verify that, the tamper check failed. Once figured, the fix was simple: For the RECORD_MERGE action, it now does a real 'sync' rather than a 'flush'. |
||
#19 | 18177 | C. Thomas Tyler |
Added '-R' flag to attempt rename detection, with warnings about when it results in insanely long run times. |
||
#18 | 18174 | C. Thomas Tyler |
Added support for non-branching files (Streams only). If a *.nobranch file exists in the config directory when processing updates, the files specified in the *.nobranch are not added to version control unless the stream type is 'mainline.' The *.nobranchg file (e.g. FGS.nobranch) contains a list of non-branchign files, one per line, with a path relative to the root of a workspace). |
||
#17 | 18164 | C. Thomas Tyler |
Modified so that existing stream specs are not updated with the STREAM tag; only new ones are created. Added quotes around '-ztag -F' format field values. |
||
#16 | 18034 | C. Thomas Tyler | Added code for calling astyle on Java code. | ||
#15 | 16891 | C. Thomas Tyler |
Fixed a regression for importing into Classic Perforce introduced when making updates for Streams. |
||
#14 | 16889 | C. Thomas Tyler |
Non-zero rsync exit codes are now always treated as hard failures. This will create challenges for when exporting from ClearCase dynamic views, rsync copies from which tend to result in scary but (mostly?) harmless rsync errors. |
||
#13 | 16888 | C. Thomas Tyler | Fixed an issue with generated demo workspace, and removed ugly/excess tabs. | ||
#12 | 16881 | C. Thomas Tyler |
Fixed bug in processing of COPY rule. The fix was done by normalizing the variable name use for changelist descriptions is normalized to $changeDesc. It some cases it already was $changeDesc, in others it was just $desc. In most cases that was just a cosmetic difference, but in the COPY rule it was a bug. |
||
#11 | 16437 | C. Thomas Tyler |
Fixed issue with failing to return to the correct directory after ASTYLE processing is complete. |
||
#10 | 16436 | C. Thomas Tyler |
Fixed bug in logic finding the astyle tool, and enhanced auditability. |
||
#9 | 16423 | C. Thomas Tyler |
Added support for ASTYLE option for UPDATE entry in *.bbi.cfg files. Fixed bug chekcing for User P4CONFIG file; it was checking $P4CONFIG rather than $UserP4CONFIG. Update Copyright to new, simpler and smaller-chunk-of-text standard for some files. |
||
#8 | 15541 | C. Thomas Tyler |
Modified reconcile logic to do three-pass imports, effectively disable rename detection, speeding up big baseline reconciles by a few orders of magnitude. Tweaked client spec of generated demo workspace. |
||
#7 | 14023 | C. Thomas Tyler |
Optimized old-school methodology, using 'p4 add -f ...' rather than two find commands (one for files, one for symlinks) to feed 'p4 add'. |
||
#6 | 13984 | C. Thomas Tyler |
Experiment: Trying BBI w/o reconcile to workaound a strange performance issue. |
||
#5 | 13981 | C. Thomas Tyler | Experimental highly instrament 'p4 reconcile' command | ||
#4 | 13967 | C. Thomas Tyler | Memory usage optimizations and added '-m' to speed up 'p4 reconcile.' | ||
#3 | 13605 | C. Thomas Tyler |
bbi_actions.sh v1.1.7: Fixed regression in STREAM action introduced in 1.1.6. |
||
#2 | 13592 | C. Thomas Tyler |
bbi_actions.sh v1.1.6: * Fixed bug in RECORD_MERGE action. * Removed redundant code from STREAM action. |
||
#1 | 13590 | C. Thomas Tyler |
Changed naming convention to use standard '.sh'; using '.lib' confused some text editors. |
||
//guest/perforce_software/p4bbi/dev/lib/bbi_actions.lib | |||||
#13 | 12934 | C. Thomas Tyler |
Add ability to import subdirectories of a stream workspace root dir, allowing for smaller, more granular tar files. This is a partial implementation; it works for Streams but breaks Classic imports. TO DO: Fix this. Corrected rsync commands to use '--delete' option. This change introduces a new library file, bbi_paths.lib. Updated test suite accordingly. |
||
#12 | 12926 | C. Thomas Tyler |
Added support for BASELINE_STORAGE definition in the BBI Config file. The value can be reference a shell environment variable, added to env.sh. Updated BBI Config File required veresion to 3.2.0 Updated test suite accordingly. |
||
#11 | 12435 | C. Thomas Tyler | Changed import workspace SubmitOptions: field from leaveunchanged to revertunchanged to workaround an issue. | ||
#10 | 12374 | C. Thomas Tyler |
Increased required BBI config file from 3.0 to 3.1. The new 3.1 format requires that a NAME tag be defined, e.g. NAME=FGS. Updated BBIConfigFileFormat.txt accordingly. This new NAME tag is incorporated into the log filename, the name of the import workspace, and the workspace root directory. This enables parallel operation of multiple concurrent imports of unrelated modules into the same target Helix server. Added doc clarification that P4CONFIG file specified with '-P' must be an absolute path, and added error checking as well. Added a check to ensure the P4CONFIG file does not define a P4CLIENT value, with appropriate error messge if it does. Added -V flag to query version of bbi.sh as well as included bash library files. Made corresponding updates to the test suite, including removing P4CLIENT from the test P4CONFIG file, and updating FGS.*.bbi.cfg files to the new confgie file format. Minor cosmetic changes. |
||
#9 | 12351 | C. Thomas Tyler |
bbi_actions.lib v1.0.9: Added initialization of default depot (which may or may not ultimately be used). |
||
#8 | 11984 | C. Thomas Tyler |
Reworked general processing style to use much less RAM and avoid "Argument list too long" errors." |
||
#7 | 11959 | C. Thomas Tyler | Merge Down hot fix from main to dev. | ||
#6 | 11810 | C. Thomas Tyler |
Implemented RMTOP feature. Updated TO DO notes. |
||
#5 | 11808 | C. Thomas Tyler |
Addd root-relative style of tar file, not needing RMTOP. Added support for *.zip files. Added -J flag to bbi.sh to obliterate junk files in BBIJunkFiles.txt. Enahnced sample files and docs. |
||
#4 | 11800 | C. Thomas Tyler |
Added '-f' flag to 'p4 reconcile' to enable adding files with Perforce wildcards in filename (@, #, *, %). Note that it is not posible to add files with '...' in the name. It pains me to do this without requiring a corresponding '-f' flag in bbi.sh, to make the user explicitly aware that they're adding files with wildcards in the name. However, this is a migration tool, and when doing imports there is rarely a decision to make. Your legacy data is what it is, and if there are files that require '-f' to be added, so be it. |
||
#3 | 11797 | C. Thomas Tyler | Implemented remaining import actions. | ||
#2 | 11785 | C. Thomas Tyler |
Partially imported import actions. Enhanced BBI config file version check. Enhanced logging. |
||
#1 | 11784 | C. Thomas Tyler |
Refactored bash libriaries. Added bbi_actions.lib to hold the BBI functionality. Branched 3 bash library files from the SDP, removing the SDP dependency. Enhanced docs. |