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