Skip to content

Instantly share code, notes, and snippets.

@darktim
Forked from gaahrdner/dynamic-puppet-environments.sh
Last active December 14, 2015 22:08
Show Gist options
  • Save darktim/5155879 to your computer and use it in GitHub Desktop.
Save darktim/5155879 to your computer and use it in GitHub Desktop.
#! /bin/bash
# This script takes two arguments:
# * the repository URL for your puppet modules
# * the destination directory to check out all the branches into
#
# It then checks out all possible branches so you can have dynamic environments
#
# It would probably work better if we just checkout master instead of multiple
# cloning operations, but we'll leave that for version 2
# locking to prevent running twice
lockfile="/tmp/$(basename $0).lock"
if ( set -o noclobber; echo "locked $$" > "$lockfile") 2> /dev/null; then
trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
echo "Locking succeeded, created $lockfile with pid $$" >&2
else
echo "Lock failed, lockfile $lockfile exists - exit" >&2
exit 1
fi
# Conjunction function
function die {
log $*
exit 2
}
function log {
echo "$(date) $*"
}
function contains {
local e
for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
function usage_and_exit {
echo "Usage: dynamic-puppet-environments -r REPO_URL -p path [-f] [-d]
-r: the git url of the repository you would like to clone
-p: the path you want all branches to be checked out into
-f: forcibly overwrite and delete all the things
-d: delete branches that do not exist in the repository
-b: an existing branch name you want mapped to the directory production"
exit 2
}
[[ $1 ]] || usage_and_exit
GIT=$(command -v git) || die "Git not installed, so, yeah, this will never work."
PWD=$(pwd)
force=false
delete=false
production=false
while getopts "r:p:fdb:" OPTION
do
case $OPTION in
r) repo=$OPTARG;;
p) path=$OPTARG;;
f) force=true;;
d) delete=true;;
b) branch=$OPTARG ; production=true;;
?) usage_and_exit;;
esac
done
# mandatory arguments
[[ $repo ]] || die "Repository required, specify with -r"
[[ $path ]] || die "Path required, specify with -p"
# validations
$GIT ls-remote $repo &> /dev/null || die "Not a valid git repository."
# get all of our branches
declare -a Branch=($($GIT ls-remote -h $repo | cut -f2 | cut -d '/' -f 3))
declare -a Existing=($(find "$path" -maxdepth 1 -mindepth 1 -type d -printf "%f\n"))
log "We have ${#Branch[@]} branch(es) in our remote repository and ${#Existing[@]} branch(es) on our local disk"
# what to do when we force
if $force ; then
log "force flag set"
mkdir -p $path
log "forcibly creating directory ${path}"
fi
[[ -d $path ]] || die "Specified directory does not exist, consider using -f to force creation"
# mapping a branch to production? we got that
if $production ; then
log "production flag set"
if contains "production" "${Branch[@]}" && [[ $branch = "production" ]] ; then
log "production branch specified as 'production', ignoring"
else
if $force ; then
log "removing the production branch from our list of branches"
Branch=($(echo ${Branch[@]/production/}))
else
die "A branch named production already exists, use -f to ignore this branch"
fi
fi
fi
# get all the current branches in the specified path
if $delete ; then
log "Delete flag set, removing any branches which don't exist in the repository"
for e in "${Existing[@]}" ; do
if contains "$e" "${Branch[@]}" ; then
log "$repo has the branch $e, leaving it alone"
else
log "$repo does not contain the branch $e..."
if [[ ! -d "$e/.git" ]] ; then
log "and $e is not a git repository..."
if $force ; then
log "...but the force flag is set, deleting $e"
rm -rf "$path/$e"
else
log "...but the force flag is NOT set, leaving directory $e alone"
fi
fi
fi
done
else
log "Delete flag not set, local branch directories will remain on disk"
fi
# map each branch to a directory with the same name
for b in "${Branch[@]}" ; do
p="$path/$b"
if [[ -d $p ]] ; then
log "$p already exists..."
if [[ ! -d "$p/.git" ]] ; then
log "...but is not a git repository..."
if $force ; then
log "...and force flag is set, deleting $p and cloning branch $b"
rm -rf $p
$GIT clone -q $repo -b $b $p
else
die "...bailing out since we don't know what's in $p"
fi
else
# we should probably test if the existing git repo is the one we actually want
log "...pulling latest files from origin $b"
cd $p && $GIT reset --hard -q && $GIT pull -q origin $b && cd $PWD
fi
else
mkdir -p $p
log "Cloning branch $b from $repo into $p"
$GIT clone -q $repo -b $b $p
fi
if [[ $production && $b = $branch ]] ; then
if [[ ! -d "$path/production" ]] ; then
log "cloning $b into $path/production"
$GIT clone -q $repo -b $b "$path/production"
else
log "$path/production already exists..."
log "...pulling latest files from origin $b"
cd "$path/production" && $GIT reset --hard -q && $GIT pull -q origin $b && cd $PWD
fi
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment