e08869596d3688e645b0380a46fba0b1e1e13e28
[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 }
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 branch="$(git branch | grep '^\* ' | awk '{print $2}')"
154 [ "$name" = "$branch" ] && error "cannot delete the currently selected environment"
155 git branch -D "$name"
156 }
157
158 env_switch() {
159 local name="${1##*/}"
160 [ -z "$name" ] && usage
161
162 env_init
163 env_ask_sync
164 git checkout "$name" || error "environment '$name' not found"
165 env_link_config
166 }
167
168 env_rename() {
169 local NAME="${1##*/}"
170 env_init
171 git branch -m "$NAME"
172 }
173
174 env_new() {
175 local NAME="$1"
176 local branch
177 local from="master"
178
179 [ -z "$NAME" ] && usage
180 env_init 1
181
182 branch="$(git branch | grep '^\* ' | awk '{print $2}')"
183 if [ -n "$branch" -a "$branch" != "master" ]; then
184 env_ask_sync
185 if ask_bool 0 "Do you want to clone the current environment?"; then
186 from="$branch"
187 fi
188 rm -f "$BASEDIR/.config" "$BASEDIR/files"
189 fi
190 git checkout -b "$1" "$from"
191 if [ -f "$BASEDIR/.config" -o -d "$BASEDIR/files" ]; then
192 if ask_bool 1 "Do you want to keep your current config and files?"; then
193 [ -d "$BASEDIR/files" -a \! -L "$BASEDIR/files" ] && {
194 mv "$BASEDIR/files/"* "$ENVDIR/" 2>/dev/null
195 rmdir "$BASEDIR/files"
196 }
197 env_sync
198 else
199 rm -rf "$BASEDIR/.config" "$BASEDIR/files"
200 fi
201 fi
202 env_link_config
203 }
204
205 COMMAND="$1"; shift
206 case "$COMMAND" in
207 help) usage 0;;
208 new) env_new "$@";;
209 list) env_list "$@";;
210 clear) env_clear "$@";;
211 switch) env_switch "$@";;
212 delete) env_delete "$@";;
213 rename) env_rename "$@";;
214 diff) env_diff "$@";;
215 save) env_save "$@";;
216 revert) env_revert "$@";;
217 *) usage;;
218 esac