[backfire] uhttpd: merge r28792
[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     env_link_config
107 }
108
109 env_save() {
110         env_init
111         env_sync
112         env_link_config
113 }
114
115 env_revert() {
116         env_init
117         env_do_reset
118         env_link_config
119 }
120
121 env_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
133 env_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
150 env_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
159 env_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
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                                 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
207 COMMAND="$1"; shift
208 case "$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;;
220 esac