Forked from gaahrdner/dynamic-puppet-environments.sh
Last active
December 14, 2015 22:08
-
-
Save darktim/5155879 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /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