From 716ca530e1c4515d8683c9d5be3d56b301758b66 Mon Sep 17 00:00:00 2001 From: James <> Date: Wed, 4 Nov 2015 11:49:21 +0000 Subject: trunk-47381 --- scripts/env | 226 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100755 scripts/env (limited to 'scripts/env') diff --git a/scripts/env b/scripts/env new file mode 100755 index 0000000..63e26eb --- /dev/null +++ b/scripts/env @@ -0,0 +1,226 @@ +#!/usr/bin/env bash +BASEDIR="$PWD" +ENVDIR="$PWD/env" +export GREP_OPTIONS= + +usage() { + cat < [arguments] +Commands: + help This help text + list List environments + clear Delete all environment and revert to flat config/files + new Create a new environment + switch Switch to a different environment + delete Delete an environment + rename Rename the current environment + diff Show differences between current state and environment + save [message] Save your changes to the environment, optionally using + the given commit message + 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 --color | grep -vE '^. master$' +} + +env_diff() { + env_init + env_sync_data + git diff --cached --color + env_link_config +} + +env_save() { + env_init + env_sync "$@" + env_link_config +} + +env_revert() { + env_init + env_do_reset + env_link_config +} + +env_ask_sync() { + env_sync_data + 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_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" + shopt -s dotglob + cp -a "$ENVDIR/files/"* "$BASEDIR/files" 2>/dev/null >/dev/null + shopt -u dotglob + cp "$ENVDIR/.config" "$BASEDIR/" + else + rm -rf "$BASEDIR/files" "$BASEDIR/.config" + fi + cd "$BASEDIR" + rm -rf "$ENVDIR" +} + +env_delete() { + local name="${1##*/}" + env_init + [ -z "$name" ] && usage + 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 + + env_init + env_ask_sync + git checkout "$name" || error "environment '$name' not found" + 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 start your configuration repository with the current configuration?"; then + [ -d "$BASEDIR/files" -a \! -L "$BASEDIR/files" ] && { + mkdir -p "$ENVDIR/files" + shopt -s dotglob + mv "$BASEDIR/files/"* "$ENVDIR/files/" 2>/dev/null + shopt -u dotglob + 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 -- cgit v1.2.3