Add @GNOME download source.
[openwrt.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         env_init
152         [ -z "$name" ] && usage
153         [ -f "$ENVDIR/.git/refs/heads/$name" ] || error "environment '$name' not found"
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         [ -f "$ENVDIR/.git/refs/heads/$name" ] || error "environment '$name' not found"
163
164         env_init
165         env_ask_sync
166         git checkout "$name"
167         env_link_config
168 }
169
170 env_rename() {
171         local NAME="${1##*/}"
172         env_init
173         git branch -m "$NAME"
174 }
175
176 env_new() {
177         local NAME="$1"
178         local branch
179         local from="master"
180
181         [ -z "$NAME" ] && usage
182         env_init 1
183         
184         branch="$(git branch | grep '^\* ' | awk '{print $2}')"
185         if [ -n "$branch" -a "$branch" != "master" ]; then
186                 env_ask_sync
187                 if ask_bool 0 "Do you want to clone the current environment?"; then
188                         from="$branch"
189                 fi
190                 rm -f "$BASEDIR/.config" "$BASEDIR/files"
191         fi
192         git checkout -b "$1" "$from"
193         if [ -f "$BASEDIR/.config" -o -d "$BASEDIR/files" ]; then
194                 if ask_bool 1 "Do you want to keep your current config and files?"; then
195                         [ -d "$BASEDIR/files" -a \! -L "$BASEDIR/files" ] && {
196                                 mv "$BASEDIR/files/"* "$ENVDIR/" 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