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