using THISDIR instead of WORKDIR
[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 THISDIR, 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 export SSM_LOG_FILE="$TMP/$(logname)-siteavenger-script.log"
15
16 # get our configuration loaded, if we know the config file.
17 # if there is none, we will use our default version.
18 export SITE_MANAGEMENT_CONFIG_FILE
19 if [ -z "$SITE_MANAGEMENT_CONFIG_FILE" ]; then
20   SITE_MANAGEMENT_CONFIG_FILE="$THISDIR/config/default.app"
21   echo "$(date_stringer): Site management config file was not set.  Using default:" >> "$SSM_LOG_FILE"
22   echo "$(date_stringer):   $SITE_MANAGEMENT_CONFIG_FILE" >> "$SSM_LOG_FILE"
23 fi
24
25 # load in at least the default version to get us moving.
26 source "$SITE_MANAGEMENT_CONFIG_FILE"
27 test_or_die "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
28
29 # configure feisty revision control to ignore vendor folders.
30 export NO_CHECKIN_VENDOR=true
31
32 # tests that the main storage folder for apps exists.
33 function check_apps_root()
34 {
35   local appdir="$1"; shift
36   if [ ! -d "$appdir" ]; then
37     echo "$(date_stringer): Creating the apps directory: $appdir" >> "$SSM_LOG_FILE"
38     mkdir "$appdir"
39     test_or_die "Making apps directory when not already present"
40   fi
41 }
42
43 # tries to find an appropriate config file for the application.
44 function locate_config_file()
45 {
46   local app_dirname="$1"; shift
47
48   local configfile="$THISDIR/config/${app_dirname}.app"
49   echo "$(date_stringer): config file guessed?: $configfile" >> "$SSM_LOG_FILE"
50   if [ ! -f "$configfile" ]; then
51     # this is not a good config file.  we can't auto-guess the config.
52     echo -e "$(date_stringer): 
53 There is no specific site configuration file in:
54   $configfile
55 We will continue onward using the default and hope that this project follows
56 the standard pattern for cakephp projects." >> "$SSM_LOG_FILE"
57     # we'll pull in the default config file we set earlier; this will
58     # reinitialize some variables based on the app name.
59   else
60     # they gave us a valid config file.  let's try using it.
61     export SITE_MANAGEMENT_CONFIG_FILE="$configfile"
62   fi
63
64   # try to load the config.
65   source "$SITE_MANAGEMENT_CONFIG_FILE"
66   test_or_die "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
67
68   return 0
69 }
70
71 # this function will seek out top-level directories in the target directory passed in.
72 # if there is only one directory, then it is returned (in the app_dirname variable).
73 # otherwise, the user is asked which directory to use.
74 # important: this sets a global variable app_dirname to the application's directory name.
75 function find_app_folder()
76 {
77   local appsdir="$1"; shift
78
79   # throw away any prior value so no confusion arises.
80   unset app_dirname
81   
82   # count number of directories...  if exactly one, then choose it.
83   numdirs=$(count_directories "$appsdir")
84
85   if [ $numdirs -eq 0 ]; then
86     sep
87     echo "There are no directories in the application directory:"
88     echo "  $appsdir"
89     echo "Please create a directory for the site storage, based on the application"
90     echo "name that you want to work on.  Or you can just pass the directory name"
91     echo "on the command line, e.g.:"
92     echo "  $(basename $0) turtle"
93     sep
94     exit 1
95   elif [ $numdirs -eq 1 ]; then
96     app_dirname="$(basename $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d) )"
97     test_or_die "Guessing application folder"
98   else
99     # if more than one folder, force user to choose.
100     # Reference: https://askubuntu.com/questions/1705/how-can-i-create-a-select-menu-in-a-shell-script
101     holdps3="$PS3"
102     PS3='Please pick a folder for site initialization: '
103     options=( $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d -exec basename {} ';') "Quit")
104     select app_dirname in "${options[@]}"; do
105       case $app_dirname in
106         "Quit") echo ; echo "Quitting from the script."; return 1; ;;
107         *) echo ; echo "You picked folder '$app_dirname'" ; break; ;;
108       esac
109     done
110     if [ -z "$app_dirname" ]; then
111       echo "The folder was not provided.  This script needs a directory name"
112       echo "within which to initialize the site."
113       return 1
114     fi
115     PS3="$holdps3"
116   fi
117   test_app_folder "$appsdir" "$app_dirname"
118   test_or_die "Testing application folder: $app_dirname"
119
120   echo "Application folder is: $app_dirname"
121   return 0
122 }
123
124 # ensures that the app directory name is valid and then loads the config
125 # for the app (either via a specific file or using the defaults).
126 function test_app_folder()
127 {
128   local appsdir="$1"; shift
129   local dir="$1"; shift
130
131   local combo="$appsdir/$dir"
132
133   if [ ! -d "$combo" ]; then
134     echo "$(date_stringer): Creating app directory: $combo" >> "$SSM_LOG_FILE"
135     mkdir "$combo"
136     test_or_die "Making application directory when not already present"
137   fi
138
139   locate_config_file "$dir"
140 }
141
142 # eases some permissions to enable apache to write log files and do other shopkeeping.
143 function fix_site_perms()
144 {
145   local app_dir="$1"; shift
146
147   local site_dir="$app_dir/$CHECKOUT_DIR_NAME"
148
149   if [ -f "$site_dir/bin/cake" ]; then
150     sudo chmod -R a+rx "$site_dir/bin/cake"
151     test_or_die "Enabling execute bit on cake binary"
152   fi
153
154   if [ -d "$site_dir/logs" ]; then
155     sudo chmod -R g+w "$site_dir/logs"
156     test_or_die "Enabling group write on site's Logs directory"
157   fi
158
159   if [ -d "$site_dir/tmp" ]; then
160     sudo chmod -R g+w "$site_dir/tmp"
161     test_or_die "Enabling group write on site's tmp directory"
162   fi
163 }
164
165 # tosses out any cached object data that originated from the database.
166 function clear_orm_cache()
167 {
168   local site_dir="$1"; shift
169
170   if [ -f "$site_dir/bin/cake" ]; then
171     # flush any cached objects from db.
172     "$site_dir/bin/cake" orm_cache clear
173     test_or_die "Clearing ORM cache"
174   fi
175 }
176
177 # updates the revision control repository passed in.  this expects that the
178 # repo will live in a folder called "checkout_dirname" under the app path,
179 # which is the standard for our deployed sites.
180 # important: this also sets a global variable called site_store_path to the full
181 # path of the application.
182 function update_repo()
183 {
184   local full_app_dir="$1"; shift
185   local checkout_dirname="$1"; shift
186   local repo_root="$1"; shift
187   local repo_name="$1"; shift
188
189 echo "$(date_stringer): here are parms in update repo:" >> "$SSM_LOG_FILE"
190 echo "$(date_stringer): $(var full_app_dir checkout_dirname repo_root repo_name)" >> "$SSM_LOG_FILE"
191
192   # forget any prior value, since we are going to validate the path.
193   unset site_store_path
194
195   pushd "$full_app_dir" &>/dev/null
196   test_or_die "Switching to our app dir '$full_app_dir'"
197
198   local complete_path="$full_app_dir/$checkout_dirname"
199
200   # see if the checkout directory exits.  the repo_found variable is set to
201   # non-empty if we find it and it's a valid git repo.
202   repo_found=
203   if [ -d "$checkout_dirname" ]; then
204     # checkout directory exists, so let's check it.
205     pushd "$checkout_dirname" &>/dev/null
206     test_or_die "Switching to our checkout directory: $checkout_dirname"
207
208     # ask for repository name (without .git).
209     if git rev-parse --git-dir > /dev/null 2>&1; then
210       # this is a valid git repo.
211       repo_found=yes
212     fi
213  
214     # we don't consider the state of having the dir exist but the repo be wrong as good.
215     if [ -z "$repo_found" ]; then
216       echo "There is a problem; this folder is not a valid repository:"
217       echo "  $full_app_dir"
218       echo "This script cannot continue unless the git repository is valid."
219       exit 1
220     fi
221     popd &>/dev/null
222   fi
223
224   if [ ! -z "$repo_found" ]; then
225     # a repository was found, so update the version here and leave.
226     echo "Repository $repo_name exists.  Updating it."
227     rgetem
228     test_or_die "Recursive checkout on: $complete_path"
229   else
230     # clone the repo since it wasn't found.
231     echo "Cloning repository $repo_name now."
232     git clone "$repo_root/$repo_name.git" $checkout_dirname
233     test_or_die "Git clone of repository: $repo_name"
234   fi
235
236 #not doing this here since powerup uses this and has no sudo.
237   #fix_site_perms "$complete_path"
238
239 #unused?
240   # construct the full path to where the app will actually live.
241   site_store_path="$complete_path"
242
243   popd &>/dev/null
244 }
245
246 # this function goes to the directory specified and makes it right with
247 # composer install.  this is as opposed to composer update, which could
248 # change the state. 
249 function composer_repuff()
250 {
251   local site_store_path="$1"; shift
252
253   pushd "$site_store_path" &>/dev/null
254   test_or_die "Switching to our app dir '$site_store_path'"
255
256   echo "Updating site with composer..."
257
258   composer -n install
259   test_or_die "Composer installation step on '$site_store_path'."
260   echo "Site updated."
261
262 #hmmm: argh global
263   dir="$site_store_path/$CHECKOUT_DIR_NAME/vendor/siteavenger/avcore"
264   if [ -d "$dir" ]; then
265     echo "Running avcore database migrations..."
266     logfile="$TMP/problem-avcore_db_migration-$(date_stringer).log"
267     ./bin/cake migrations migrate -p Avcore &>"$logfile"
268     if [ $? -ne 0 ]; then
269       echo "** FAILED: Database migrations for avcore.  Check log file in: $logfile"
270       # we keep going, because some sites aren't ready for this yet.
271     else
272       \rm "$logfile"
273       echo "Database for avcore migrated."
274     fi
275   fi
276
277   clear_orm_cache
278
279   popd &>/dev/null
280 }
281
282 # this function creates the links needed to make the site function properly given our
283 # various dependencies and infrastructure.
284 function create_site_links()
285 {
286   local site_store_path="$1"; shift
287   local theme_name="$1"; shift
288
289   echo "Creating symbolic links for site assets..."
290
291   # jump into the site path so we can start making relative links.
292   pushd "$site_store_path" &>/dev/null
293   test_or_die "Switching to our app dir '$site_store_path'"
294
295   pushd webroot &>/dev/null
296
297   # remove all symlinks that might plague us.
298   find . -maxdepth 1 -type l -exec rm -f {} ';'
299   test_or_die "Cleaning out links in webroot"
300
301   # link in the avcore plugin.
302   make_safe_link "../vendor/siteavenger/avcore/webroot" avcore
303
304   # make the link for our theme as a lower-case version of the theme.
305   themelower=${theme_name,,}
306   make_safe_link "../plugins/$theme_name/webroot" "$themelower"
307
308   # link in any favicon files.
309   if [ -d "../plugins/$theme_name/favicon" ]; then
310     local fave
311     for fave in "../plugins/$theme_name/favicon"/*; do
312       make_safe_link "$fave" .
313     done
314   fi
315
316   # get back out of webroot.
317   popd &>/dev/null
318
319   # hop up a level above where we had been.
320   pushd .. &>/dev/null
321
322   # link 'public' to webroot.
323   if [ -L public ]; then
324     # public is a symlink.
325     \rm public
326     test_or_die "Removing public directory symlink"
327   elif [ -d public ]; then
328     # public is a folder with default files.
329 #hmmm: is that safe?
330     \rm -rf public
331     test_or_die "Removing public directory and contents"
332   fi
333
334   # create the main 'public' symlink
335 #hmmm: argh global
336   make_safe_link $CHECKOUT_DIR_NAME/webroot public
337   test_or_die "Creating link to webroot called 'public'"
338
339 #hmmm: public/$themelower/im will be created automatically by system user with appropriate permissions
340
341   echo Created symbolic links.
342
343   popd &>/dev/null
344   popd &>/dev/null
345 }
346
347 # fetches composer to make sure it's up to date.
348 # (if powerup runs, composer install doesn't update git origin.)
349 function update_composer_repository()
350 {
351   local site_store_path="$1"; shift
352
353   pushd "$site_store_path" &>/dev/null
354
355   if git config remote.composer.url &>/dev/null; then
356     git pull composer
357     echo "Updated the composer repository."
358   else
359     echo "No composer repository was found for updating."
360   fi
361 }
362
363 # fixes the ownership for a site avenger or php application.
364 # this almost certainly will require sudo capability, if there are any ownership problems
365 # that need to be resolved.
366 function fix_appdir_ownership()
367 {
368   local appsdir="$1"; shift
369   local dir="$1"; shift
370
371   local combo="$appsdir/$dir"
372
373   # go with the default user running the script.
374   user_name="$USER"
375   if [ ! -z "$user_name" -a "$user_name" != "root" ]; then
376     echo "$(date_stringer): Chowning the app folder to be owned by: $user_name" >> "$SSM_LOG_FILE"
377 #hmmm: have to hope for now for standard group named after user 
378     sudo chown -R "$user_name:$user_name" "$combo"
379     test_or_die "Chowning $combo to be owned by $user_name"
380   else
381     echo "$(date_stringer): user name failed checks for chowning, was found as '$user_name'" >> "$SSM_LOG_FILE"
382   fi
383
384   # 
385 #probably not enough for path!
386   fix_site_perms "$combo"
387 }
388
389 # Jumps to an application directory given the app name.  If no app name is
390 # given, it will show a menu to pick the app.
391 function switch_to()
392 {
393   # check for parameters.
394   app_dirname="$1"; shift
395
396   check_apps_root "$BASE_APPLICATION_PATH"
397
398   # find proper webroot where the site will be initialized.
399   if [ -z "$app_dirname" ]; then
400     # no dir was passed, so guess it.
401     find_app_folder "$BASE_APPLICATION_PATH"
402   else
403     test_app_folder "$BASE_APPLICATION_PATH" "$app_dirname"
404   fi
405   if [ $? -ne 0 ]; then
406     echo "Could not locate the application directory: ${app_dirname}"
407     return 1
408   fi
409
410   # where we expect to find our checkout folder underneath.
411   full_app_dir="$BASE_APPLICATION_PATH/$app_dirname"
412
413   pushd $full_app_dir/$CHECKOUT_DIR_NAME
414 #redundant if pushd  pwd
415 }
416