fix a small typo
[openwrt-10.03/.git] / scripts / env
1 #!/usr/bin/env bash
2 BASEDIR="$PWD"
3 ENVDIR="$PWD/env"
4
5 usage() {
6         cat <<EOF
7 Usage: $0 [options] <command> [arguments]
8 Commands:
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
20 Options:
21
22 EOF
23         exit ${1:-1}
24 }
25
26 error() {
27         echo "$0: $*"
28         exit 1
29 }
30
31 ask_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
53 env_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
73 env_sync_data() {
74         [ \! -L "$BASEDIR/.config" -a -f "$BASEDIR/.config" ] && mv "$BASEDIR/.config" "$ENVDIR"
75         git-add .
76         git-add -u
77 }
78
79 env_sync() {
80         local STR="$1"
81         env_sync_data
82         git-commit -m "${STR:-Update} at $(date)"
83 }
84
85 env_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
92 env_do_reset() {
93         git-reset --hard HEAD
94         git-clean -d -f
95 }
96
97 env_list() {
98         env_init
99         git-branch | grep -vE '^. master$'
100 }
101
102 env_diff() {
103         env_init
104         env_sync_data
105         git-diff --cached
106 }
107
108 env_save() {
109         env_init
110         env_sync
111         env_link_config
112 }
113
114 env_revert() {
115         env_init
116         env_do_reset
117         env_link_config
118 }
119
120 env_ask_sync() {
121         LINES="$(env_diff | wc -l)" # implies env_init
122         [ "$LINES" -gt 0 ] && {
123                 if ask_bool 1 "Do you want to save your changes"; then
124                         env_sync
125                 else
126                         env_sync_data
127                         env_do_reset
128                 fi
129         }
130 }
131
132 env_clear() {
133         env_init
134         [ -L "$BASEDIR/.config" ] && rm -f "$BASEDIR/.config"
135         [ -L "$BASEDIR/files" ] && rm -f "$BASEDIR/files"
136         [ -f "$ENVDIR/.config" ] || ( cd "$ENVDIR/files" && find | grep -vE '^\.$' > /dev/null )
137         env_sync_data
138         if ask_bool 1 "Do you want to keep your current config and files"; then
139                 mkdir -p "$BASEDIR/files"
140                 cp -a "$ENVDIR/files/*" "$BASEDIR/files" 2>/dev/null >/dev/null
141                 cp "$ENVDIR/.config" "$BASEDIR/"
142         else
143                 rm -rf "$BASEDIR/files" "$BASEDIR/.config"
144         fi
145         cd "$BASEDIR"
146         rm -rf "$ENVDIR"
147 }
148
149 env_delete() {
150         local name="${1##*/}"
151         [ -z "$name" ] && usage
152         [ -f "$envdir/.git/refs/heads/$name" ] || error "environment '$name' not found"
153         branch="$(git-branch | grep '^\* ' | awk '{print $2}')"
154         [ "$name" = "branch" ] && error "cannot delete the currently selected environment"
155         git-branch -D "$name"
156 }
157
158 env_switch() {
159         local name="${1##*/}"
160         [ -z "$name" ] && usage
161         [ -f "$ENVDIR/.git/refs/heads/$name" ] || error "environment '$name' not found"
162
163         env_init
164         env_ask_sync
165         git-checkout "$NAME"
166         env_link_config
167 }
168
169 env_rename() {
170         local NAME="${1##*/}"
171         env_init
172         git-branch -m "$NAME"
173 }
174
175 env_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                                 mv "$BASEDIR/files/"* "$ENVDIR/" 2>/dev/null
196                                 rmdir "$BASEDIR/files"
197                         }
198                         env_sync
199                 else
200                         rm -rf "$BASEDIR/.config" "$BASEDIR/files"
201                 fi
202         fi
203         env_link_config
204 }
205
206 COMMAND="$1"; shift
207 case "$COMMAND" in
208         help) usage 0;;
209         new) env_new "$@";;
210         list) env_list "$@";;
211         clear) env_clear "$@";;
212         switch) env_switch "$@";;
213         delete) env_delete "$@";;
214         rename) env_rename "$@";;
215         diff) env_diff "$@";;
216         save) env_save "$@";;
217         revert) env_revert "$@";;
218         *) usage;;
219 esac