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 --color | grep -vE '^. master$'
100}
101
102env_diff() {
103    env_init
104    env_sync_data
105    git diff --cached --color
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        shopt -s dotglob
142        cp -a "$ENVDIR/files/"* "$BASEDIR/files" 2>/dev/null >/dev/null
143        shopt -u dotglob
144        cp "$ENVDIR/.config" "$BASEDIR/"
145    else
146        rm -rf "$BASEDIR/files" "$BASEDIR/.config"
147    fi
148    cd "$BASEDIR"
149    rm -rf "$ENVDIR"
150}
151
152env_delete() {
153    local name="${1##*/}"
154    env_init
155    [ -z "$name" ] && usage
156    branch="$(git branch | grep '^\* ' | awk '{print $2}')"
157    [ "$name" = "$branch" ] && error "cannot delete the currently selected environment"
158    git branch -D "$name"
159}
160
161env_switch() {
162    local name="${1##*/}"
163    [ -z "$name" ] && usage
164
165    env_init
166    env_ask_sync
167    git checkout "$name" || error "environment '$name' not found"
168    env_link_config
169}
170
171env_rename() {
172    local NAME="${1##*/}"
173    env_init
174    git branch -m "$NAME"
175}
176
177env_new() {
178    local NAME="$1"
179    local branch
180    local from="master"
181
182    [ -z "$NAME" ] && usage
183    env_init 1
184    
185    branch="$(git branch | grep '^\* ' | awk '{print $2}')"
186    if [ -n "$branch" -a "$branch" != "master" ]; then
187        env_ask_sync
188        if ask_bool 0 "Do you want to clone the current environment?"; then
189            from="$branch"
190        fi
191        rm -f "$BASEDIR/.config" "$BASEDIR/files"
192    fi
193    git checkout -b "$1" "$from"
194    if [ -f "$BASEDIR/.config" -o -d "$BASEDIR/files" ]; then
195        if ask_bool 1 "Do you want to start your configuration repository with the current configuration?"; then
196            [ -d "$BASEDIR/files" -a \! -L "$BASEDIR/files" ] && {
197                mkdir -p "$ENVDIR/files"
198                shopt -s dotglob
199                mv "$BASEDIR/files/"* "$ENVDIR/files/" 2>/dev/null
200                shopt -u dotglob
201                rmdir "$BASEDIR/files"
202            }
203            env_sync
204        else
205            rm -rf "$BASEDIR/.config" "$BASEDIR/files"
206        fi
207    fi
208    env_link_config
209}
210
211COMMAND="$1"; shift
212case "$COMMAND" in
213    help) usage 0;;
214    new) env_new "$@";;
215    list) env_list "$@";;
216    clear) env_clear "$@";;
217    switch) env_switch "$@";;
218    delete) env_delete "$@";;
219    rename) env_rename "$@";;
220    diff) env_diff "$@";;
221    save) env_save "$@";;
222    revert) env_revert "$@";;
223    *) usage;;
224esac
225

Archive Download this file



interactive