SVN-Revision: 12212master
parent
3a321fb110
commit
131ba6fed7
@ -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 |
Loading…
Reference in new issue