#!/bin/bash #------------------------------------------------------------------------------ # snapclone.sh: This script clones a personal repo, using rsync to simulate # copying a pre-cloned DVCS repo template from a NetApp filer snapshot. # # It modifiers the local workspace in ways to "Make it your own," by: # - Changing the default user in .p4config # - Taking a local checkpoint and performing minor surgery on it to # correct the protections table for the current user. # - Modifying the generated .p4config to enable local journaling. # - Adjusting the RemoteUser: field of the 'origin' remote spec to the current # user. # set -u #------------------------------------------------------------------------------ function msg () { echo -e "$*"; } function cmd () { msg "Executing: $*"; $*; return $?; } function bail () { msg "Error: $1"; exit ${2:-1}; } function usage () { echo -e "Usage: For testing this script: ${0##*/} -p <proj> [-u <user>] [-F] Specify -F to to foricbly remote the user workspace if it exists. If you already have a copy of the template worksapce, run like this: ${0##*/} -d <repo_dir> [-f] Specify '-f' to do the optional fetch after the sync. This requires you to be logged in to the server to work. "; exit 1; } declare MasterWS= declare TemplateStorageBase=/netapp/p4/ws/templates declare TemplateStorage= declare Proj=Unset declare Passwd=Unset declare Port=Unset declare User=Unset declare TemplateSet=s1 declare TemplateName=${Proj}-${TemplateSet} declare RepoStorageBase=/netapp/p4/ws declare RepoStorage=Unset declare SpecFile= declare Version=1.2.0 declare -i DoFetch=0 declare -i Force=0 declare -i shiftArgs=0 set +u while [[ $# -gt 0 ]]; do case $1 in (-F) Force=1;; (-f) DoFetch=1;; (-u) User=$2; shiftArgs=1;; (-p) Proj=$2; shiftArgs=1;; (-d) RepoStorage=$2; shiftArgs=1;; (-P) Passwd=$2; shiftArgs=1;; (-h) usage -h;; (-man) usage -man;; (-V) show_versions; exit 1;; (-v1) export VERBOSITY=1;; (-v2) export VERBOSITY=2;; (-v3) export VERBOSITY=3;; (-v4) export VERBOSITY=4;; (-v5) export VERBOSITY=5;; (-L) export P4U_LOG=$2; shiftArgs=1;; (-si) SilentMode=1;; (-n) export NO_OP=1;; (-D) set -x;; # Debug; use 'set -x' mode. (*) bail "Usage Error: Unknown arg ($1)." ;; esac # Shift (modify $#) the appropriate number of times. shift; while [[ $shiftArgs -gt 0 ]]; do [[ $# -eq 0 ]] && bail "Usage Error: Bad argument count." shiftArgs=$shiftArgs-1 shift done done set -u #------------------------------------------------------------------------------ # Command Line Validation if [[ $RepoStorage == Unset ]]; then [[ $Proj == Unset ]] && bail "Usage Error: Specify either '-d <repo_dir>' or '-p <proj>')." fi #------------------------------------------------------------------------------ # Main Program. msg "Started ${0##*/} v$Version at $(date).\n" export P4ENVIRO=/dev/null/.p4enviro export P4CONFIG=.p4config [[ $User == Unset ]] && User=$(whoami) if [[ $RepoStorage == Unset ]]; then TemplateStorage=${TemplateStorageBase}/${Proj}-${TemplateSet} if [[ -d $TemplateStorage/.p4root ]]; then msg "Using template $TemplateStorage." else bail "Could not find a suitable template. Checked: $TemplateStorage" fi RepoStorage=${RepoStorageBase}/${User}/${Proj} if [[ -d $RepoStorage ]]; then if [[ $Force -eq 1 ]]; then /bin/rm -rf $RepoStorage || bail "Failed to remove existing repo dir: $RepoStorage." else bail "Repo already exists at $RepoStorage." fi fi mkdir -p $RepoStorage || bail "Failed to create repo storage dir: $RepoStorage." msg "Snap/Cloning from $TemplateStorage to $RepoStorage." rsync -a $TemplateStorage/ $RepoStorage || bail "Failed to snap/clone template repo." else [[ ! -d "$RepoStorage" ]] && bail "The dir specified with '-d <repo_dir>' does not exist." fi msg "Massaging data". cd $RepoStorage/.p4root || bail "Failed to cd to $RepoStorage/.p4root" p4d -r $RepoStorage/.p4root -k db.remote,db.protect,db.user -jd partial_ckp MasterWS=$(grep "@pv@ 7 @db.user@" partial_ckp|cut -d '@' -f 6) msg "Adjusting metadata to change owner from $MasterWS to $User." sed -e "s:@db.remote@ @origin@ @${MasterWS}@:@db.remote@ @origin@ @${User}@:g" \ -e "s:@db.protect@ 0 0 @${MasterWS}@:@db.protect@ 0 0 @${User}@:g" \ -e "s:@db.protect@ 1 0 @${MasterWS}@:@db.protect@ 1 0 @${User}@:g" \ -e "s:@db.protect@ 1 0 @${MasterWS}@:@db.protect@ 1 0 @${User}@:g" \ -e "s:@${MasterWS}@:@${User}@:g" \ partial_ckp > partial_ckp.mod # For safety, disable server vars so 'p4 init' doesn't go haywire on p4d. unset P4PORT P4ROOT P4JOURNAL P4LOG P4DEBUG P4AUDIT p4d -r $RepoStorage/.p4root -jr partial_ckp.mod grep -v P4USER= $RepoStorage/$P4CONFIG | grep -v P4PORT= > $RepoStorage/${P4CONFIG}.1 echo "P4PORT=rsh:/bin/sh -c \"umask 077 && exec p4d -i -J '\$configdir/.p4root/journal' -r '\$configdir/.p4root'\"" >> $RepoStorage/${P4CONFIG}.1 echo "P4USER=$User" >> $RepoStorage/${P4CONFIG}.1 mv -f $RepoStorage/${P4CONFIG}.1 $RepoStorage/${P4CONFIG} Port=$(p4 -ztag -F %Address% remote -o origin) if [[ $Port == ssl:* ]]; then export P4TRUST=$RepoStorage/.p4trust cmd p4 -p $Port trust -y fi msg "\nAdding User $User to 'origin' remote spec." SpecFile=$(mktemp) p4 remote -o origin > $SpecFile ||\ bail "Failed to write remote spec file to $SpecFile." echo "RemoteUser: $User" >> $SpecFile p4 remote -i < $SpecFile || bail "Failed to load remote spec file $SpecFile with these contents:\n$(cat $SpecFile)\n" msg "\nChanging workspace owner to $User." p4 client -o | grep -v '^Owner:' > $SpecFile ||\ bail "Failed to write client spec file to $SpecFile." echo "Owner: $User" >> $SpecFile p4 client -i < $SpecFile || bail "Failed to load client spec file $SpecFile with these contents:\n$(cat $SpecFile)\n" rm -f $SpecFile if [[ $Passwd != Unset ]]; then touch .p4passwd chmod 600 .p4passwd echo "$Passwd" > .p4passwd msg "P:[$(cat .p4passwd)]" msg "Logging in to master server." p4 login -r origin < .p4passwd rm -f .p4passwd fi if [[ $DoFetch -eq 1 ]]; then msg "\nFetching." p4 fetch else msg "\nTo update your workspace to the latest versions:\n p4 login -r origin # Skip this if are logged into the master server.\n p4 fetch\n" fi msg "\nDone. Enjoy your repo in: $RepoStorage" msg "That took $(($SECONDS/3600)) hours $(($SECONDS%3600/60)) minutes $(($SECONDS%60)) seconds.\n" exit 0
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#13 | 20216 | Perforce maintenance | Don't need db.domain. | ||
#12 | 20215 | Perforce maintenance | Removed redundant call to mktemp(). | ||
#11 | 20214 | Perforce maintenance |
snapclone.sh v1.1.8: * Changed old '-f' to '-F' * Added new '-f' (fetch); changed default behavior to not fetch. * Updated usage(). * Updated test suite accordingly. |
||
#10 | 20213 | Perforce maintenance | Changed TemplateOwner to MasterWS. | ||
#9 | 20212 | Perforce maintenance |
snapclone.sh v1.1.6: * Changed workspace Owner field to current user. |
||
#8 | 20128 | Perforce maintenance |
snapclone.sh v1.1.3: * Fixed compatibility with '-d' usage vs. '-p' usage. |
||
#7 | 20123 | C. Thomas Tyler |
snapclone.sh v1.1.2: * Added '-d' flag to start processing after external creation of snapshotted clone tree. * Misc code cleanup. |
||
#6 | 20118 | Perforce maintenance |
snapclone.sh v1.1.1: * Refined performance improvement, fixing issues. * Cleaned up excess .p4config.1 file generated. |
||
#5 | 20115 | C. Thomas Tyler |
snapclone.sh v1.1.0: * Performance enhancement, now checkpoints only tables that need transmogrification. |
||
#4 | 20114 | Perforce maintenance |
snapclone.sh v1.0.9: * Improved handling of remote spec file. * Added more error checking and handling. |
||
#3 | 20089 | Perforce maintenance | Adjusted storage location. | ||
#2 | 19957 | Perforce maintenance | Enhanced checkpoint surgery to make it more narrow. | ||
#1 | 19956 | Perforce maintenance | Refactored. | ||
//guest/tom_tyler/snapclone/main/flexclone.sh | |||||
#5 | 19955 | Perforce maintenance | Added notes. | ||
#4 | 19953 | Perforce maintenance |
flexclone.sh is taking shape. Added test script. |
||
#3 | 19952 | Perforce maintenance | Milestone PoC. | ||
#2 | 19951 | Perforce maintenance | wip. | ||
#1 | 19950 | Perforce maintenance | Added flexclone script, wip. |