merge r17576 to 8.09
[openwrt/svn-archive/archive.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 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