#!/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."
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #3 | 33164 | Claude (AI Agent by Anthropic) |
Correct the previous ignore-handling fix (change 33162/33163): test-install_sdp already ships a tracked, comprehensive .p4ignore.local (p4/p4d, logs, test_sdp.*.cfg, etc.) that the bin/ clone was always meant to activate via the P4IGNORE rename -- my earlier "fix" wrongly assumed it was a fresh local-only file and clobbered it, and unnecessarily duplicated its patterns into the plain .p4ignore (reverted here). The only real gap was that .current-source (this project's own new marker filename) was never in that list -- added now. swap_source.sh updated to match: bin/ goes back to the simple P4IGNORE=.p4ignore.local rename (the tracked file now covers .current-source too); sdp/ (p4-sdp, which has no such pre-existing file, and shouldn't have our tooling-specific patterns added to the SDP's own real .p4ignore) keeps the new local-only chained-.p4ignore.local approach from change 33162. Agent: Claude Code, Model: Claude Sonnet 5 (claude-sonnet-5), operating as bot_Claude_Anthropic. |
||
| #2 | 33162 | Claude (AI Agent by Anthropic) |
Fix swap_source.sh: p4 status was flagging the .current-source marker file (and, for sdp, the new .p4ignore.local itself) as untracked, which broke test_preflight.sh/uat -- caught during the first real bootstrap run on the r9x86_64 canary. Fix: chain a local-only .p4ignore.local onto P4IGNORE via P4's semicolon-list syntax (excluding both .current-source and itself) rather than bin's previous approach of replacing P4IGNORE outright, which had been silently discarding the repo's own real .p4ignore patterns. Unifies bin/sdp handling (both now sync -f .p4ignore + chain .p4ignore.local). Agent: Claude Code, Model: Claude Sonnet 5 (claude-sonnet-5), operating as bot_Claude_Anthropic. |
||
| #1 | 33158 | Claude (AI Agent by Anthropic) |
Task 1.2: SDP Installer Test Suite source-swapping capability. Adds swap_source.sh (park/restore or fresh-clone via p4-sdp_*/test-install_sdp_* remote specs) and bootstrap_test_machine.sh (self-contained, curl-bootstrappable machine-join script, SDP Bash Coding Standard style with documented deviations, ShellCheck-clean). Fixes dev_env.sh's hardcoded P4USER/P4PORT, and init_root_dirs_for_local_installs.sh's stale r25.1 P4D default and a real bin.aarch64 URL bug (404; should be bin.linux26aarch64). Restructures InstallSDP-TestServerSetup.md around the new bootstrap script and adds a "Qualifying a New Platform" section. Agent: Claude Code, Model: Claude Sonnet 5 (claude-sonnet-5), operating as bot_Claude_Anthropic. |