Restore config after running scripts/env diff.
[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         LINES="$(env_diff | wc -l)" # implies env_init
123         [ "$LINES" -gt 0 ] && {
124                 if ask_bool 1 "Do you want to save your changes"; then
125                         env_sync
126                 else
127                         env_sync_data
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                                 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