cef784e5f7b50fca582a8f7c63950f50d29c2c18
[feisty_meow.git] / scripts / site_avenger / shared_site_mgr.sh
1 #!/bin/bash
2
3 # Author: Kevin Wentworth
4 # Author: Chris Koeritz
5
6 # This contains a bunch of reusable functions that help out in managing websites.
7
8 # This script is sourced, and relies on the value of WORKDIR, which should
9 # point at the directory where the site management scripts are stored,
10 # especially this one.
11
12 source "$FEISTY_MEOW_SCRIPTS/core/launch_feisty_meow.sh"
13
14 # get our configuration loaded.
15 export SITE_MANAGEMENT_CONFIG_FILE
16 if [ -z "$SITE_MANAGEMENT_CONFIG_FILE" ]; then
17   SITE_MANAGEMENT_CONFIG_FILE="$WORKDIR/config/default-site_avenger.config"
18 fi
19 source "$SITE_MANAGEMENT_CONFIG_FILE"
20 test_or_die "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
21
22 # configure feisty revision control to ignore vendor folders.
23 export NO_CHECKIN_VENDOR=true
24
25 # tests that the main storage folder for apps exists.
26 function check_application_dir()
27 {
28   local appdir="$1"; shift
29   if [ ! -d "$appdir" ]; then
30     echo "Creating the apps directory: $appdir"
31     mkdir "$appdir"
32     test_or_die "Making apps directory when not already present"
33   fi
34 }
35
36 # this function will seek out top-level directories in the target directory passed in.
37 # if there is only one directory, then it is returned (in the app_dirname variable).
38 # otherwise, the user is asked which directory to use.
39 # important: this sets a global variable app_dirname to the application's directory name.
40 function find_app_folder()
41 {
42   local appsdir="$1"; shift
43
44   # throw away any prior value so no confusion arises.
45   unset app_dirname
46   
47   # count number of directories...  if exactly one, then choose it.
48   numdirs=$(count_directories "$appsdir")
49
50   if [ $numdirs -eq 0 ]; then
51     sep
52     echo "There are no directories in the application directory:"
53     echo "  $appsdir"
54     echo "Please create a directory for the site storage, based on the application"
55     echo "name that you want to work on.  Or you can just pass the directory name"
56     echo "on the command line, e.g.:"
57     echo "  $(basename $0) turtle"
58     sep
59     exit 1
60   elif [ $numdirs -eq 1 ]; then
61     app_dirname="$(basename $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d) )"
62     test_or_die "Guessing application folder"
63   else
64     # if more than one folder, force user to choose.
65     # Reference: https://askubuntu.com/questions/1705/how-can-i-create-a-select-menu-in-a-shell-script
66     holdps3="$PS3"
67     PS3='Please pick a folder for site initialization: '
68     options=( $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d -exec basename {} ';') "Quit")
69     select app_dirname in "${options[@]}"; do
70       case $app_dirname in
71         "Quit") echo ; echo "Quitting from the script."; exit 1; ;;
72         *) echo ; echo "You picked folder '$app_dirname'" ; break; ;;
73       esac
74     done
75     if [ -z "$app_dirname" ]; then
76       echo "The folder was not provided.  This script needs a directory name"
77       echo "within which to initialize the site."
78       exit 1
79     fi
80     PS3="$holdps3"
81   fi
82   test_app_folder "$appsdir" "$app_dirname"
83   test_or_die "Testing application folder: $app_dirname"
84
85   echo "Application folder is: $app_dirname"
86 }
87
88 # ensures that the app directory name is valid.
89 function test_app_folder()
90 {
91   local appsdir="$1"; shift
92   local dir="$1"; shift
93
94   local combo="$appsdir/$dir"
95
96   if [ ! -d "$combo" ]; then
97     echo "Creating app directory: $combo"
98     mkdir "$combo"
99     test_or_die "Making application directory when not already present"
100   fi
101 }
102
103 # eases some permissions to enable apache to write log files and do other shopkeeping.
104 function fix_site_perms()
105 {
106   local site_dir="$1"; shift
107
108   if [ -f "$site_dir/bin/cake" ]; then
109     chmod -R a+rx "$site_dir/bin/cake"
110     test_or_die "Enabling execute bit on cake binary"
111   fi
112
113   if [ -d "$site_dir/logs" ]; then
114     chmod -R g+w "$site_dir/logs"
115     test_or_die "Enabling group write on site's Logs directory"
116   fi
117
118   if [ -d "$site_dir/tmp" ]; then
119     chmod -R g+w "$site_dir/tmp"
120     test_or_die "Enabling group write on site's tmp directory"
121   fi
122 }
123
124 # tosses out any cached object data that originated from the database.
125 function clear_orm_cache()
126 {
127   local site_dir="$1"; shift
128
129   if [ -f "$site_dir/bin/cake" ]; then
130     # flush any cached objects from db.
131     "$site_dir/bin/cake" orm_cache clear
132     test_or_die "Clearing ORM cache"
133   fi
134 }
135
136 # updates the revision control repository passed in.  this expects that the
137 # repo will live in a folder called "checkout_dirname" under the app path,
138 # which is the standard for our deployed sites.
139 # important: this also sets a global variable called site_store_path to the full
140 # path of the application.
141 function update_repo()
142 {
143   local full_app_dir="$1"; shift
144   local checkout_dirname="$1"; shift
145   local repo_root="$1"; shift
146   local repo_name="$1"; shift
147
148   # forget any prior value, since we are going to validate the path.
149   unset site_store_path
150
151   pushd "$full_app_dir" &>/dev/null
152   test_or_die "Switching to our app dir '$full_app_dir'"
153
154   local complete_path="$full_app_dir/$checkout_dirname"
155
156   # see if the checkout directory exits.  the repo_found variable is set to
157   # non-empty if we find it and it's a valid git repo.
158   repo_found=
159   if [ -d "$checkout_dirname" ]; then
160     # checkout directory exists, so let's check it.
161     pushd "$checkout_dirname" &>/dev/null
162     test_or_die "Switching to our checkout directory: $checkout_dirname"
163
164     # ask for repository name (without .git).
165     if git rev-parse --git-dir > /dev/null 2>&1; then
166       # this is a valid git repo.
167       repo_found=yes
168     fi
169  
170     # we don't consider the state of having the dir exist but the repo be wrong as good.
171     if [ -z "$repo_found" ]; then
172       echo "There is a problem; this folder is not a valid repository:"
173       echo "  $full_app_dir"
174       echo "This script cannot continue unless the git repository is valid."
175       exit 1
176     fi
177     popd &>/dev/null
178   fi
179
180   if [ ! -z "$repo_found" ]; then
181     # a repository was found, so update the version here and leave.
182     echo "Repository $repo_name exists.  Updating it."
183     rgetem
184     test_or_die "Recursive checkout on: $complete_path"
185   else
186     # clone the repo since it wasn't found.
187     echo "Cloning repository $repo_name now."
188     git clone "$repo_root/$repo_name.git" $checkout_dirname
189     test_or_die "Git clone of repository: $repo_name"
190   fi
191
192   fix_site_perms "$complete_path"
193
194   # construct the full path to where the app will actually live.
195   site_store_path="$complete_path"
196
197   popd &>/dev/null
198 }
199
200 # this function goes to the directory specified and makes it right with
201 # composer install.  this is as opposed to composer update, which could
202 # change the state. 
203 function composer_repuff()
204 {
205   local site_store_path="$1"; shift
206
207   pushd "$site_store_path" &>/dev/null
208   test_or_die "Switching to our app dir '$site_store_path'"
209
210   echo "Updating site with composer..."
211
212   composer -n install
213   test_or_die "Composer installation step on '$site_store_path'."
214   echo "Site updated."
215
216 #hmmm: argh global
217   dir="$site_store_path/$CHECKOUT_DIR_NAME/vendor/siteavenger/avcore"
218   if [ -d "$dir" ]; then
219     echo "Running avcore database migrations..."
220     logfile="$TMP/problem-avcore_db_migration-$(date_stringer).log"
221     ./bin/cake migrations migrate -p Avcore &>"$logfile"
222     if [ $? -ne 0 ]; then
223       echo "** FAILED: Database migrations for avcore.  Check log file in: $logfile"
224       # we keep going, because some sites aren't ready for this yet.
225     else
226       \rm "$logfile"
227       echo "Database for avcore migrated."
228     fi
229   fi
230
231   clear_orm_cache
232
233   popd &>/dev/null
234 }
235
236 # this function creates the links needed to make the site function properly given our
237 # various dependencies and infrastructure.
238 function create_site_links()
239 {
240   local site_store_path="$1"; shift
241   local theme_name="$1"; shift
242
243   echo "Creating symbolic links for site assets..."
244
245   # jump into the site path so we can start making relative links.
246   pushd "$site_store_path" &>/dev/null
247   test_or_die "Switching to our app dir '$site_store_path'"
248
249   pushd webroot &>/dev/null
250
251   # remove all symlinks that might plague us.
252   find . -maxdepth 1 -type l -exec rm -f {} ';'
253   test_or_die "Cleaning out links in webroot"
254
255   # link in the avcore plugin.
256   make_safe_link "../vendor/siteavenger/avcore/webroot" avcore
257
258   # make the link for our theme as a lower-case version of the theme.
259   themelower=${theme_name,,}
260   make_safe_link "../plugins/$theme_name/webroot" "$themelower"
261
262   # link in any favicon files.
263   if [ -d "../plugins/$theme_name/favicon" ]; then
264     local fave
265     for fave in "../plugins/$theme_name/favicon"/*; do
266       make_safe_link "$fave" .
267     done
268   fi
269
270   # get back out of webroot.
271   popd &>/dev/null
272
273   # hop up a level above where we had been.
274   pushd .. &>/dev/null
275
276   # link 'public' to webroot.
277   if [ -L public ]; then
278     # public is a symlink.
279     \rm public
280     test_or_die "Removing public directory symlink"
281   elif [ -d public ]; then
282     # public is a folder with default files.
283 #hmmm: is that safe?
284     \rm -rf public
285     test_or_die "Removing public directory and contents"
286   fi
287
288   # create the main 'public' symlink
289 #hmmm: argh global
290   make_safe_link $CHECKOUT_DIR_NAME/webroot public
291   test_or_die "Creating link to webroot called 'public'"
292
293 #hmmm: public/$themelower/im will be created automatically by system user with appropriate permissions
294
295   echo Created symbolic links.
296
297   popd &>/dev/null
298   popd &>/dev/null
299 }
300
301 # fetches composer to make sure it's up to date.
302 # (if powerup runs, composer install doesn't update git origin.)
303 function update_composer_repository()
304 {
305   local site_store_path="$1"; shift
306
307   pushd "$site_store_path" &>/dev/null
308
309   if git config remote.composer.url &>/dev/null; then
310     git pull composer
311     echo "Updated the composer repository."
312   else
313     echo "No composer repository was found for updating."
314   fi
315 }
316
317