3 # Author: Kevin Wentworth
4 # Author: Chris Koeritz
6 # This contains a bunch of reusable functions that help out in managing websites.
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.
12 source "$FEISTY_MEOW_SCRIPTS/core/launch_feisty_meow.sh"
14 export SSM_LOG_FILE="$TMP/$(logname)-siteavenger-script.log"
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"
25 # load in at least the default version to get us moving.
26 source "$SITE_MANAGEMENT_CONFIG_FILE"
27 exit_on_error "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
29 # configure feisty revision control to ignore vendor folders.
30 export NO_CHECKIN_VENDOR=true
32 # tests that the main storage folder for apps exists.
33 function check_apps_root()
35 local appdir="$1"; shift
36 if [ ! -d "$appdir" ]; then
37 echo "$(date_stringer): Creating the apps directory: $appdir" >> "$SSM_LOG_FILE"
39 exit_on_error "Making apps directory when not already present"
43 #hmmm: extract to core somewhere...
44 # locates a parent directory of a certain name, if possible. returns success
45 # (as zero) if the directory was found, and failure if there was no parent
46 # named as requested. sets a global variable PARENT_DIR_FOUND to the full
47 # directory name that matched, including the name being sought (but omitting
48 # any deeper directories than that).
49 function find_named_parent_dir()
51 local dir_name_sought="$1"; shift
52 # clear any previous global result.
53 unset PARENT_DIR_FOUND
54 # check for degenerate case of parameter count.
55 if [ -z "$dir_name_sought" ]; then
57 find_named_parent_dir: requires a directory name parameter, which will be
58 sought out above the current directory. the return value indicates whether
59 the requested name was found or not.
63 # loop upwards in dir hierarchy to find the name.
65 local currdir="$(\pwd)"
66 if [ "$currdir" == "/" ]; then
67 # we climbed out of all subdirs. this is a failure case.
70 # get the base part of our name to check on success.
71 local base="$(basename "$currdir")"
72 if [ "$base" == "$dir_name_sought" ]; then
73 # yes, that is the right name. success case. save our result.
74 export PARENT_DIR_FOUND="$currdir"
80 # tries to find an appropriate config file for the application.
81 function locate_config_file()
83 local app_dirname="$1"; shift
85 local configfile="$THISDIR/config/${app_dirname}.app"
86 echo "$(date_stringer): config file guessed?: $configfile" >> "$SSM_LOG_FILE"
87 if [ ! -f "$configfile" ]; then
88 # this is not a good config file. we can't auto-guess the config.
89 echo -e "$(date_stringer):
90 There is no specific site configuration file in:
92 We will continue onward using the default and hope that this project follows
93 the standard pattern for cakephp projects." >> "$SSM_LOG_FILE"
94 # we'll pull in the default config file we set earlier; this will
95 # reinitialize some variables based on the app name.
97 # they gave us a valid config file. let's try using it.
98 export SITE_MANAGEMENT_CONFIG_FILE="$configfile"
101 # try to load the config.
102 source "$SITE_MANAGEMENT_CONFIG_FILE"
103 exit_on_error "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
108 # this function will seek out top-level directories in the target directory passed in.
109 # if there is only one directory, then it is returned (in the app_dirname variable).
110 # otherwise, the user is asked which directory to use.
111 # important: this sets a global variable app_dirname to the application's directory name.
112 function find_app_folder()
114 local appsdir="$1"; shift
116 # throw away any prior value so no confusion arises.
119 # count number of directories... if exactly one, then choose it.
120 numdirs=$(count_directories "$appsdir")
122 if [ $numdirs -eq 0 ]; then
124 echo "There are no directories in the application directory:"
126 echo "Please create a directory for the site storage, based on the application"
127 echo "name that you want to work on. Or you can just pass the directory name"
128 echo "on the command line, e.g.:"
129 echo " $(basename $0) turtle"
132 elif [ $numdirs -eq 1 ]; then
133 app_dirname="$(basename $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d) )"
134 exit_on_error "Guessing application folder"
136 # there's more than one folder in apps...
138 # if we can find an avenger5 directory above our current PWD, then that might tell us our name.
139 if find_named_parent_dir "avenger5"; then
140 # we can grab a name above the avenger5 location. let's try that.
141 app_dirname="$(basename "$(dirname $PARENT_DIR_FOUND)" )"
143 # well, we couldn't guess a directory based on our current location,
144 # so ask the user to choose.
145 # Reference: https://askubuntu.com/questions/1705/how-can-i-create-a-select-menu-in-a-shell-script
147 PS3='Please pick a folder for site initialization: '
148 options=( $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d -exec basename {} ';') "Quit")
149 select app_dirname in "${options[@]}"; do
151 "Quit") echo ; echo "Quitting from the script."; return 1; ;;
152 *) echo ; echo "You picked folder '$app_dirname'" ; break; ;;
155 if [ -z "$app_dirname" ]; then
156 echo "The folder was not provided. This script needs a directory name"
157 echo "within which to initialize the site."
163 test_app_folder "$appsdir" "$app_dirname"
164 exit_on_error "Testing application folder: $app_dirname"
166 echo "Application folder is: $app_dirname"
170 # ensures that the app directory name is valid and then loads the config
171 # for the app (either via a specific file or using the defaults).
172 function test_app_folder()
174 local appsdir="$1"; shift
175 local dir="$1"; shift
177 local combo="$appsdir/$dir"
179 if [ ! -d "$combo" ]; then
180 echo "$(date_stringer): Creating app directory: $combo" >> "$SSM_LOG_FILE"
182 exit_on_error "Making application directory when not already present"
185 locate_config_file "$dir"
188 # eases some permissions to enable apache to write log files and do other shopkeeping.
189 function fix_site_perms()
191 local app_dir="$1"; shift
193 local site_dir="$app_dir/$CHECKOUT_DIR_NAME"
195 if [ -f "$site_dir/bin/cake" ]; then
196 sudo chmod -R a+rx "$site_dir/bin/cake"
197 exit_on_error "Enabling execute bit on cake binary"
200 if [ -d "$site_dir/logs" ]; then
201 sudo chmod -R g+w "$site_dir/logs"
202 exit_on_error "Enabling group write on site's Logs directory"
205 if [ -d "$site_dir/tmp" ]; then
206 sudo chmod -R g+w "$site_dir/tmp"
207 exit_on_error "Enabling group write on site's tmp directory"
211 # tosses out any cached object data that originated from the database.
212 function clear_orm_cache()
214 local site_dir="$1"; shift
216 if [ -f "$site_dir/bin/cake" ]; then
217 # flush any cached objects from db.
218 "$site_dir/bin/cake" orm_cache clear
219 exit_on_error "Clearing ORM cache"
223 # updates the revision control repository passed in. this expects that the
224 # repo will live in a folder called "checkout_dirname" under the app path,
225 # which is the standard for our deployed sites.
226 # important: this also sets a global variable called site_store_path to the full
227 # path of the application.
228 function update_repo()
230 local full_app_dir="$1"; shift
231 local checkout_dirname="$1"; shift
232 local repo_root="$1"; shift
233 local repo_name="$1"; shift
235 echo "$(date_stringer): here are parms in update repo:" >> "$SSM_LOG_FILE"
236 echo "$(date_stringer): $(var full_app_dir checkout_dirname repo_root repo_name)" >> "$SSM_LOG_FILE"
238 # forget any prior value, since we are going to validate the path.
239 unset site_store_path
241 pushd "$full_app_dir" &>/dev/null
242 exit_on_error "Switching to our app dir '$full_app_dir'"
244 local complete_path="$full_app_dir/$checkout_dirname"
246 # see if the checkout directory exits. the repo_found variable is set to
247 # non-empty if we find it and it's a valid git repo.
249 if [ -d "$checkout_dirname" ]; then
250 # checkout directory exists, so let's check it.
251 pushd "$checkout_dirname" &>/dev/null
252 exit_on_error "Switching to our checkout directory: $checkout_dirname"
254 # ask for repository name (without .git).
255 if git rev-parse --git-dir > /dev/null 2>&1; then
256 # this is a valid git repo.
260 # we don't consider the state of having the dir exist but the repo be wrong as good.
261 if [ -z "$repo_found" ]; then
262 echo "There is a problem; this folder is not a valid repository:"
263 echo " $full_app_dir"
264 echo "This script cannot continue unless the git repository is valid."
270 if [ ! -z "$repo_found" ]; then
271 # a repository was found, so update the version here and leave.
272 echo "Repository $repo_name exists. Updating it."
274 exit_on_error "Recursive checkout on: $complete_path"
276 # clone the repo since it wasn't found.
277 echo "Cloning repository $repo_name now."
278 git clone "$repo_root/$repo_name.git" $checkout_dirname
279 exit_on_error "Git clone of repository: $repo_name"
282 #not doing this here since powerup uses this and has no sudo.
283 #fix_site_perms "$complete_path"
286 # construct the full path to where the app will actually live.
287 site_store_path="$complete_path"
292 # this function goes to the directory specified and makes it right with
293 # composer install. this is as opposed to composer update, which could
295 function composer_repuff()
297 local site_store_path="$1"; shift
299 pushd "$site_store_path" &>/dev/null
300 exit_on_error "Switching to our app dir '$site_store_path'"
302 echo "Updating site with composer..."
305 exit_on_error "Composer installation step on '$site_store_path'."
309 dir="$site_store_path/$CHECKOUT_DIR_NAME/vendor/siteavenger/avcore"
310 if [ -d "$dir" ]; then
311 echo "Running avcore database migrations..."
312 logfile="$TMP/problem-avcore_db_migration-$(date_stringer).log"
313 ./bin/cake migrations migrate -p Avcore &>"$logfile"
314 if [ $? -ne 0 ]; then
315 echo "** FAILED: Database migrations for avcore. Check log file in: $logfile"
316 # we keep going, because some sites aren't ready for this yet.
319 echo "Database for avcore migrated."
328 # this function creates the links needed to make the site function properly given our
329 # various dependencies and infrastructure.
330 function create_site_links()
332 local site_store_path="$1"; shift
333 local theme_name="$1"; shift
335 echo "Creating symbolic links for site assets..."
337 # jump into the site path so we can start making relative links.
338 pushd "$site_store_path" &>/dev/null
339 exit_on_error "Switching to our app dir '$site_store_path'"
341 pushd webroot &>/dev/null
343 # remove all symlinks that might plague us.
344 find . -maxdepth 1 -type l -exec rm -f {} ';'
345 exit_on_error "Cleaning out links in webroot"
347 # link in the avcore plugin.
348 make_safe_link "../vendor/siteavenger/avcore/webroot" avcore
350 # make the link for our theme as a lower-case version of the theme.
351 themelower=${theme_name,,}
352 make_safe_link "../plugins/$theme_name/webroot" "$themelower"
354 # link in any favicon files.
355 if [ -d "../plugins/$theme_name/favicon" ]; then
357 for fave in "../plugins/$theme_name/favicon"/*; do
358 make_safe_link "$fave" .
362 # get back out of webroot.
365 # hop up a level above where we had been.
368 # link 'public' to webroot.
369 if [ -L public ]; then
370 # public is a symlink.
372 exit_on_error "Removing public directory symlink"
373 elif [ -d public ]; then
374 # public is a folder with default files.
377 exit_on_error "Removing public directory and contents"
380 # create the main 'public' symlink
382 make_safe_link $CHECKOUT_DIR_NAME/webroot public
383 exit_on_error "Creating link to webroot called 'public'"
385 #hmmm: public/$themelower/im will be created automatically by system user with appropriate permissions
387 echo Created symbolic links.
393 # fetches composer to make sure it's up to date.
394 # (if powerup runs, composer install doesn't update git origin.)
395 function update_composer_repository()
397 local site_store_path="$1"; shift
399 pushd "$site_store_path" &>/dev/null
401 if git config remote.composer.url &>/dev/null; then
403 echo "Updated the composer repository."
405 echo "No composer repository was found for updating."
409 # fixes the ownership for a site avenger or php application.
410 # this almost certainly will require sudo capability, if there are any ownership problems
411 # that need to be resolved.
412 function fix_appdir_ownership()
414 local appsdir="$1"; shift
415 local dir="$1"; shift
417 local combo="$appsdir/$dir"
419 # go with the default user running the script.
421 if [ ! -z "$user_name" -a "$user_name" != "root" ]; then
422 echo "$(date_stringer): Chowning the app folder to be owned by: $user_name" >> "$SSM_LOG_FILE"
423 #hmmm: have to hope for now for standard group named after user
424 sudo chown -R "$user_name:$user_name" "$combo"
425 exit_on_error "Chowning $combo to be owned by $user_name"
427 echo "$(date_stringer): user name failed checks for chowning, was found as '$user_name'" >> "$SSM_LOG_FILE"
431 #probably not enough for path!
432 fix_site_perms "$combo"
435 # Jumps to an application directory given the app name. If no app name is
436 # given, it will show a menu to pick the app.
439 # check for parameters.
440 app_dirname="$1"; shift
442 check_apps_root "$BASE_APPLICATION_PATH"
444 # find proper webroot where the site will be initialized.
445 if [ -z "$app_dirname" ]; then
446 # no dir was passed, so guess it.
447 find_app_folder "$BASE_APPLICATION_PATH"
449 test_app_folder "$BASE_APPLICATION_PATH" "$app_dirname"
451 if [ $? -ne 0 ]; then
452 echo "Could not locate the application directory: ${app_dirname}"
456 # where we expect to find our checkout folder underneath.
457 full_app_dir="$BASE_APPLICATION_PATH/$app_dirname"
459 pushd $full_app_dir/$CHECKOUT_DIR_NAME
460 #redundant if pushd pwd