Root/scripts/env

1#!/usr/bin/env bash
2BASEDIR="$PWD"
3ENVDIR="$PWD/env"
4
5usage() {
6    cat <<EOF
7Usage: $0 [options] <command> [arguments]
8Commands:
9    help This help text
10    list List environments
11    clear Delete all environment and revert to flat config/files
12    new <name> Create a new environment
13    switch <name> Switch to a different environment
14    delete <name> Delete an environment
15    rename <newname> Rename the current environment
16    diff Show differences between current state and environment
17    save Save your changes to the environment
18    revert Revert your changes since last save
19
20Options:
21
22EOF
23    exit ${1:-1}
24}
25
26error() {
27    echo "$0: $*"
28    exit 1
29}
30
31ask_bool() {
32    local DEFAULT="$1"; shift
33    local def defstr val
34    case "$DEFAULT" in
35        1) def=0; defstr="Y/n";;
36        0) def=1; defstr="y/N";;
37        *) def=; defstr="y/n";;
38    esac
39    while [ -z "$val" ]; do
40        local VAL
41
42        echo -n "$* ($defstr): "
43        read VAL
44        case "$VAL" in
45            y*|Y*) val=0;;
46            n*|N*) val=1;;
47            *) val="$def";;
48        esac
49    done
50    return "$val"
51}
52
53env_init() {
54    local CREATE="$1"
55    if [ -z "$CREATE" ]; then
56        [ -d "$ENVDIR" ] || exit 0
57    fi
58    [ -x "$(which git 2>/dev/null)" ] || error "Git is not installed"
59    mkdir -p "$ENVDIR" || error "Failed to create the environment directory"
60    cd "$ENVDIR" || error "Failed to switch to the environment directory"
61    [ -d .git ] || {
62        git init &&
63        touch .config &&
64        mkdir files &&
65        git add . &&
66        git commit -q -m "Initial import"
67    } || {
68        rm -rf .git
69        error "Failed to initialize the environment directory"
70    }
71}
72
73env_sync_data() {
74    [ \! -L "$BASEDIR/.config" -a -f "$BASEDIR/.config" ] && mv "$BASEDIR/.config" "$ENVDIR"
75    git add .
76    git add -u
77}
78
79env_sync() {
80    local STR="$1"
81    env_sync_data
82    git commit -m "${STR:-Update} at $(date)"
83}
84
85env_link_config() {
86    rm -f "$BASEDIR/.config"
87    ln -s env/.config "$BASEDIR/.config"
88    mkdir -p "$ENVDIR/files"
89    [ -L "$BASEDIR/files" ] || ln -s env/files "$BASEDIR/files"
90}
91
92env_do_reset() {
93    git reset --hard HEAD
94    git clean -d -f
95}
96
97env_list() {
98    env_init
99    git branch | grep -vE '^. master$'
100}
101
102env_diff() {
103    env_init
104    env_sync_data
105    git diff --cached
106    env_link_config
107}
108
109env_save() {
110    env_init
111    env_sync
112    env_link_config
113}
114
115env_revert() {
116    env_init
117    env_do_reset
118    env_link_config
119}
120
121env_ask_sync() {
122    env_sync_data
123    LINES="$(env_diff | wc -l)" # implies env_init
124    [ "$LINES" -gt 0 ] && {
125        if ask_bool 1 "Do you want to save your changes"; then
126            env_sync
127        else
128            env_do_reset
129        fi
130    }
131}
132
133env_clear() {
134    env_init
135    [ -L "$BASEDIR/.config" ] && rm -f "$BASEDIR/.config"
136    [ -L "$BASEDIR/files" ] && rm -f "$BASEDIR/files"
137    [ -f "$ENVDIR/.config" ] || ( cd "$ENVDIR/files" && find | grep -vE '^\.$' > /dev/null )
138    env_sync_data
139    if ask_bool 1 "Do you want to keep your current config and files"; then
140        mkdir -p "$BASEDIR/files"
141        cp -a "$ENVDIR/files/*" "$BASEDIR/files" 2>/dev/null >/dev/null
142        cp "$ENVDIR/.config" "$BASEDIR/"
143    else
144        rm -rf "$BASEDIR/files" "$BASEDIR/.config"
145    fi
146    cd "$BASEDIR"
147    rm -rf "$ENVDIR"
148}
149
150env_delete() {
151    local name="${1##*/}"
152    env_init
153    [ -z "$name" ] && usage
154    branch="$(git branch | grep '^\* ' | awk '{print $2}')"
155    [ "$name" = "$branch" ] && error "cannot delete the currently selected environment"
156    git branch -D "$name"
157}
158
159env_switch() {
160    local name="${1##*/}"
161    [ -z "$name" ] && usage
162
163    env_init
164    env_ask_sync
165    git checkout "$name" || error "environment '$name' not found"
166    env_link_config
167}
168
169env_rename() {
170    local NAME="${1##*/}"
171    env_init
172    git branch -m "$NAME"
173}
174
175env_new() {
176    local NAME="$1"
177    local branch
178    local from="master"
179
180    [ -z "$NAME" ] && usage
181    env_init 1
182    
183    branch="$(git branch | grep '^\* ' | awk '{print $2}')"
184    if [ -n "$branch" -a "$branch" != "master" ]; then
185        env_ask_sync
186        if ask_bool 0 "Do you want to clone the current environment?"; then
187            from="$branch"
188        fi
189        rm -f "$BASEDIR/.config" "$BASEDIR/files"
190    fi
191    git checkout -b "$1" "$from"
192    if [ -f "$BASEDIR/.config" -o -d "$BASEDIR/files" ]; then
193        if ask_bool 1 "Do you want to keep your current config and files?"; then
194            [ -d "$BASEDIR/files" -a \! -L "$BASEDIR/files" ] && {
195                mkdir -p "$ENVDIR/files"
196                mv "$BASEDIR/files/*" "$ENVDIR/files/" 2>/dev/null
197                rmdir "$BASEDIR/files"
198            }
199            env_sync
200        else
201            rm -rf "$BASEDIR/.config" "$BASEDIR/files"
202        fi
203    fi
204    env_link_config
205}
206
207COMMAND="$1"; shift
208case "$COMMAND" in
209    help) usage 0;;
210    new) env_new "$@";;
211    list) env_list "$@";;
212    clear) env_clear "$@";;
213    switch) env_switch "$@";;
214    delete) env_delete "$@";;
215    rename) env_rename "$@";;
216    diff) env_diff "$@";;
217    save) env_save "$@";;
218    revert) env_revert "$@";;
219    *) usage;;
220esac
221

Archive Download this file



interactive