diff options
Diffstat (limited to 'scripts/env')
| -rwxr-xr-x | scripts/env | 219 | 
1 files changed, 219 insertions, 0 deletions
diff --git a/scripts/env b/scripts/env new file mode 100755 index 000000000..d783e20ef --- /dev/null +++ b/scripts/env @@ -0,0 +1,219 @@ +#!/usr/bin/env bash +BASEDIR="$PWD" +ENVDIR="$PWD/env" + +usage() { +	cat <<EOF +Usage: $0 [options] <command> [arguments] +Commands: +	help              This help text +	list              List environments +	clear             Delete all environment and revert to flat config/files +	new <name>        Create a new environment +	switch <name>     Switch to a different environment +	delete <name>     Delete an environment +	rename <newname>  Rename the current environment +	diff              Show differences between current state and environment +	save              Save your changes to the environment +	revert            Revert your changes since last save + +Options: + +EOF +	exit ${1:-1} +} + +error() { +	echo "$0: $*" +	exit 1 +} + +ask_bool() { +	local DEFAULT="$1"; shift +	local def defstr val +	case "$DEFAULT" in +		1) def=0; defstr="Y/n";; +		0) def=1; defstr="y/N";; +		*) def=;  defstr="y/n";; +	esac +	while [ -z "$val" ]; do +		local VAL + +		echo -n "$* ($defstr): " +		read VAL +		case "$VAL" in +			y*|Y*) val=0;; +			n*|N*) val=1;; +			*) val="$def";; +		esac +	done +	return "$val" +} + +env_init() { +	local CREATE="$1" +	if [ -z "$CREATE" ]; then +		[ -d "$ENVDIR" ] || exit 0 +	fi +	[ -x "$(which git 2>/dev/null)" ] || error "Git is not installed" +	mkdir -p "$ENVDIR" || error "Failed to create the environment directory" +	cd "$ENVDIR" || error "Failed to switch to the environment directory" +	[ -d .git ] || {  +		git init && +		touch .config && +		mkdir files && +		git-add . &&  +		git-commit -q -m "Initial import" +	} || { +		rm -rf .git +		error "Failed to initialize the environment directory" +	} +} + +env_sync_data() { +	[ \! -L "$BASEDIR/.config" -a -f "$BASEDIR/.config" ] && mv "$BASEDIR/.config" "$ENVDIR" +	git-add . +	git-add -u +} + +env_sync() { +	local STR="$1" +	env_sync_data +	git-commit -m "${STR:-Update} at $(date)" +} + +env_link_config() { +	rm -f "$BASEDIR/.config" +	ln -s env/.config "$BASEDIR/.config" +	mkdir -p "$ENVDIR/files" +	[ -L "$BASEDIR/files" ] || ln -s env/files "$BASEDIR/files" +} + +env_do_reset() { +	git-reset --hard HEAD +	git-clean -d -f +} + +env_list() { +	env_init +	git-branch | grep -vE '^. master$' +} + +env_diff() { +	env_init +	env_sync_data +	git-diff --cached +} + +env_save() { +	env_init +	env_sync +	env_link_config +} + +env_revert() { +	env_init +	env_do_reset +	env_link_config +} + +env_ask_sync() { +	LINES="$(env_diff | wc -l)" # implies env_init +	[ "$LINES" -gt 0 ] && { +		if ask_bool 1 "Do you want to save your changes"; then +			env_sync +		else +			env_sync_data +			env_do_reset +		fi +	} +} + +env_clear() { +	env_init +	[ -L "$BASEDIR/.config" ] && rm -f "$BASEDIR/.config" +	[ -L "$BASEDIR/files" ] && rm -f "$BASEDIR/files" +	[ -f "$ENVDIR/.config" ] || ( cd "$ENVDIR/files" && find | grep -vE '^\.$' > /dev/null ) +	env_sync_data +	if ask_bool 1 "Do you want to keep your current config and files"; then +		mkdir -p "$BASEDIR/files" +		cp -a "$ENVDIR/files/*" "$BASEDIR/files" 2>/dev/null >/dev/null +		cp "$ENVDIR/.config" "$BASEDIR/" +	else +		rm -rf "$BASEDIR/files" "$BASEDIR/.config" +	fi +	cd "$BASEDIR" +	rm -rf "$ENVDIR" +} + +env_delete() { +	local name="${1##*/}" +	[ -z "$name" ] && usage +	[ -f "$envdir/.git/refs/heads/$name" ] || error "environment '$name' not found" +	branch="$(git-branch | grep '^\* ' | awk '{print $2}')" +	[ "$name" = "branch" ] && error "cannot delete the currently selected environment" +	git-branch -D "$name" +} + +env_switch() { +	local name="${1##*/}" +	[ -z "$name" ] && usage +	[ -f "$envdir/.git/refs/heads/$name" ] || error "environment '$name' not found" + +	env_init +	env_ask_sync +	git-checkout "$NAME" +	env_link_config +} + +env_rename() { +	local NAME="${1##*/}" +	env_init +	git-branch -m "$NAME" +} + +env_new() { +	local NAME="$1" +	local branch +	local from="master" + +	[ -z "$NAME" ] && usage +	env_init 1 +	 +	branch="$(git-branch | grep '^\* ' | awk '{print $2}')" +	if [ -n "$branch" -a "$branch" != "master" ]; then +		env_ask_sync +		if ask_bool 0 "Do you want to clone the current environment?"; then +			from="$branch" +		fi +		rm -f "$BASEDIR/.config" "$BASEDIR/files" +	fi +	git-checkout -b "$1" "$from" +	if [ -f "$BASEDIR/.config" -o -d "$BASEDIR/files" ]; then +		if ask_bool 1 "Do you want to keep your current config and files?"; then +			[ -d "$BASEDIR/files" -a \! -L "$BASEDIR/files" ] && { +				mv "$BASEDIR/files/"* "$ENVDIR/" 2>/dev/null +				rmdir "$BASEDIR/files" +			} +			env_sync +		else +			rm -rf "$BASEDIR/.config" "$BASEDIR/files" +		fi +	fi +	env_link_config +} + +COMMAND="$1"; shift +case "$COMMAND" in +	help) usage 0;; +	new) env_new "$@";; +	list) env_list "$@";; +	clear) env_clear "$@";; +	switch) env_switch "$@";; +	delete) env_delete "$@";; +	rename) env_rename "$@";; +	diff) env_diff "$@";; +	save) env_save "$@";; +	revert) env_revert "$@";; +	*) usage;; +esac  | 
