#!/bin/bash
# swap_source.sh <StreamPath>
#
# Sets /opt/perforce/dev/sdp or /opt/perforce/dev/bin to pull from a
# different stream, e.g.:
#
#   ./swap_source.sh p4-sdp/dev_rebrand
#   ./swap_source.sh p4-sdp/dev
#   ./swap_source.sh p4-sdp/main
#   ./swap_source.sh test-install_sdp/dev
#   ./swap_source.sh test-install_sdp/main
#
# This is also how the initial clone is done on a fresh machine -- there's
# no separate bootstrap step. The first time a given StreamPath is used on a
# machine, this does a fresh 'p4 clone -r' using a matching remote spec
# (StreamPath with '/' replaced by '_', e.g. p4-sdp_dev_rebrand). On later
# calls, if the target directory was previously parked by this script for a
# different source, that source is parked in turn and the requested one is
# moved back into place -- no re-clone needed.
#
# Read-only access (P4USER=ftp) is used for a fresh clone unless
# P4_SWAP_USER is set in the environment, e.g. for read/write access:
#   P4_SWAP_USER=yourP4user ./swap_source.sh p4-sdp/dev_rebrand

set -u

ThisScript=${0##*/}

function msg () { echo -e "$*"; }
function bail () { echo -e "\\nError: ${1:-Unknown Error}\\n"; exit 1; }

# Mirrors the DEV_HOME logic in dev_env.sh.
if [[ "$HOSTNAME" == p4c-bos-01.p4demo.com ]]; then
   DevHome=/opt/perforce/.dev
else
   DevHome=/opt/perforce/dev
fi

P4Port=public.perforce.com:1666
P4CloneUser=${P4_SWAP_USER:-ftp}

StreamPath="${1:-}"
[[ -n "$StreamPath" ]] || bail "Usage: $ThisScript <StreamPath>, e.g. $ThisScript p4-sdp/dev_rebrand"

case "$StreamPath" in
   p4-sdp/*)           Target=sdp ;;
   test-install_sdp/*) Target=bin ;;
   *) bail "Unrecognized stream path '$StreamPath'; expected p4-sdp/<stream> or test-install_sdp/<stream>." ;;
esac

RemoteSpec="${StreamPath//\//_}"
ActiveDir="$DevHome/$Target"
MarkerFile="$ActiveDir/.current-source"

if [[ -e "$ActiveDir" && ! -d "$ActiveDir" ]]; then
   bail "$ActiveDir exists and is not a directory."
fi

CurrentSuffix=
[[ -f "$MarkerFile" ]] && CurrentSuffix="$(cat "$MarkerFile")"

if [[ "$CurrentSuffix" == "$RemoteSpec" ]]; then
   msg "$Target is already sourced from $StreamPath. Nothing to do."
   exit 0
fi

ParkedTargetDir="${ActiveDir}.${RemoteSpec}"

if [[ -d "$ActiveDir" ]]; then
   if [[ -z "$CurrentSuffix" ]]; then
      bail "$ActiveDir exists but has no $MarkerFile identifying its source; refusing to move it aside blindly. Investigate manually."
   fi
   ParkedCurrentDir="${ActiveDir}.${CurrentSuffix}"
   [[ -e "$ParkedCurrentDir" ]] && bail "Cannot park $ActiveDir at $ParkedCurrentDir; that path already exists."
   msg "Parking current $Target checkout ($CurrentSuffix) at $ParkedCurrentDir ..."
   mv "$ActiveDir" "$ParkedCurrentDir" || bail "mv \"$ActiveDir\" \"$ParkedCurrentDir\" failed."
fi

if [[ -d "$ParkedTargetDir" ]]; then
   msg "Restoring previously-parked $Target checkout for $StreamPath from $ParkedTargetDir ..."
   mv "$ParkedTargetDir" "$ActiveDir" || bail "mv \"$ParkedTargetDir\" \"$ActiveDir\" failed."
else
   msg "No prior checkout found for $StreamPath; cloning fresh via remote spec $RemoteSpec (as $P4CloneUser) ..."
   mkdir -p "$ActiveDir" || bail "mkdir -p \"$ActiveDir\" failed."
   (
      cd "$ActiveDir" || exit 1
      export P4CONFIG=.p4config.local
      p4 -u "$P4CloneUser" clone -p "$P4Port" -r "$RemoteSpec" || exit 1
      # The cloned repo ships its own .p4ignore, which collides with the
      # DVCS-generated default of the same name; force a sync to let the
      # real one land.
      p4 sync -f .p4ignore || exit 1
      if [[ "$Target" == bin ]]; then
         # test-install_sdp ships its own tracked .p4ignore.local, a more
         # comprehensive ignore list (p4/p4d binaries, logs, test_sdp.*.cfg,
         # and .current-source itself) curated for exactly this kind of
         # clone -- just point P4IGNORE at it.
         sed -i -E -e "s/^P4IGNORE=.*/P4IGNORE=.p4ignore.local/" .p4config.local || exit 1
      else
         # p4-sdp has no such file, and we shouldn't be adding our own
         # tooling-specific patterns to the SDP's real .p4ignore -- so chain
         # a local-only one onto it instead (P4IGNORE supports a ';'-
         # separated list) just to cover our own .current-source marker.
         printf '%s\n' .current-source .p4ignore.local > .p4ignore.local || exit 1
         sed -i -E -e "s/^P4IGNORE=.*/&;.p4ignore.local/" .p4config.local || exit 1
      fi
      echo "$RemoteSpec" > .current-source
   ) || bail "Fresh clone/setup of $StreamPath failed."
fi

msg "$Target is now sourced from $StreamPath."
