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 # tries to find an appropriate config file for the application.
44 function locate_config_file()
46 local app_dirname="$1"; shift
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:
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.
60 # they gave us a valid config file. let's try using it.
61 export SITE_MANAGEMENT_CONFIG_FILE="$configfile"
64 # try to load the config.
65 source "$SITE_MANAGEMENT_CONFIG_FILE"
66 exit_on_error "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
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()
77 local appsdir="$1"; shift
79 # throw away any prior value so no confusion arises.
82 # count number of directories... if exactly one, then choose it.
83 numdirs=$(count_directories "$appsdir")
85 if [ $numdirs -eq 0 ]; then
87 echo "There are no directories in the application directory:"
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"
95 elif [ $numdirs -eq 1 ]; then
96 app_dirname="$(basename $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d) )"
97 exit_on_error "Guessing application folder"
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
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
106 "Quit") echo ; echo "Quitting from the script."; return 1; ;;
107 *) echo ; echo "You picked folder '$app_dirname'" ; break; ;;
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."
117 test_app_folder "$appsdir" "$app_dirname"
118 exit_on_error "Testing application folder: $app_dirname"
120 echo "Application folder is: $app_dirname"
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()
128 local appsdir="$1"; shift
129 local dir="$1"; shift
131 local combo="$appsdir/$dir"
133 if [ ! -d "$combo" ]; then
134 echo "$(date_stringer): Creating app directory: $combo" >> "$SSM_LOG_FILE"
136 exit_on_error "Making application directory when not already present"
139 locate_config_file "$dir"
142 # eases some permissions to enable apache to write log files and do other shopkeeping.
143 function fix_site_perms()
145 local app_dir="$1"; shift
147 local site_dir="$app_dir/$CHECKOUT_DIR_NAME"
149 if [ -f "$site_dir/bin/cake" ]; then
150 sudo chmod -R a+rx "$site_dir/bin/cake"
151 exit_on_error "Enabling execute bit on cake binary"
154 if [ -d "$site_dir/logs" ]; then
155 sudo chmod -R g+w "$site_dir/logs"
156 exit_on_error "Enabling group write on site's Logs directory"
159 if [ -d "$site_dir/tmp" ]; then
160 sudo chmod -R g+w "$site_dir/tmp"
161 exit_on_error "Enabling group write on site's tmp directory"
165 # tosses out any cached object data that originated from the database.
166 function clear_orm_cache()
168 local site_dir="$1"; shift
170 if [ -f "$site_dir/bin/cake" ]; then
171 # flush any cached objects from db.
172 "$site_dir/bin/cake" orm_cache clear
173 exit_on_error "Clearing ORM cache"
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()
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
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"
192 # forget any prior value, since we are going to validate the path.
193 unset site_store_path
195 pushd "$full_app_dir" &>/dev/null
196 exit_on_error "Switching to our app dir '$full_app_dir'"
198 local complete_path="$full_app_dir/$checkout_dirname"
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.
203 if [ -d "$checkout_dirname" ]; then
204 # checkout directory exists, so let's check it.
205 pushd "$checkout_dirname" &>/dev/null
206 exit_on_error "Switching to our checkout directory: $checkout_dirname"
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.
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."
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."
228 exit_on_error "Recursive checkout on: $complete_path"
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 exit_on_error "Git clone of repository: $repo_name"
236 #not doing this here since powerup uses this and has no sudo.
237 #fix_site_perms "$complete_path"
240 # construct the full path to where the app will actually live.
241 site_store_path="$complete_path"
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
249 function composer_repuff()
251 local site_store_path="$1"; shift
253 pushd "$site_store_path" &>/dev/null
254 exit_on_error "Switching to our app dir '$site_store_path'"
256 echo "Updating site with composer..."
259 exit_on_error "Composer installation step on '$site_store_path'."
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.
273 echo "Database for avcore migrated."
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()
286 local site_store_path="$1"; shift
287 local theme_name="$1"; shift
289 echo "Creating symbolic links for site assets..."
291 # jump into the site path so we can start making relative links.
292 pushd "$site_store_path" &>/dev/null
293 exit_on_error "Switching to our app dir '$site_store_path'"
295 pushd webroot &>/dev/null
297 # remove all symlinks that might plague us.
298 find . -maxdepth 1 -type l -exec rm -f {} ';'
299 exit_on_error "Cleaning out links in webroot"
301 # link in the avcore plugin.
302 make_safe_link "../vendor/siteavenger/avcore/webroot" avcore
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"
308 # link in any favicon files.
309 if [ -d "../plugins/$theme_name/favicon" ]; then
311 for fave in "../plugins/$theme_name/favicon"/*; do
312 make_safe_link "$fave" .
316 # get back out of webroot.
319 # hop up a level above where we had been.
322 # link 'public' to webroot.
323 if [ -L public ]; then
324 # public is a symlink.
326 exit_on_error "Removing public directory symlink"
327 elif [ -d public ]; then
328 # public is a folder with default files.
331 exit_on_error "Removing public directory and contents"
334 # create the main 'public' symlink
336 make_safe_link $CHECKOUT_DIR_NAME/webroot public
337 exit_on_error "Creating link to webroot called 'public'"
339 #hmmm: public/$themelower/im will be created automatically by system user with appropriate permissions
341 echo Created symbolic links.
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()
351 local site_store_path="$1"; shift
353 pushd "$site_store_path" &>/dev/null
355 if git config remote.composer.url &>/dev/null; then
357 echo "Updated the composer repository."
359 echo "No composer repository was found for updating."
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()
368 local appsdir="$1"; shift
369 local dir="$1"; shift
371 local combo="$appsdir/$dir"
373 # go with the default user running the script.
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 exit_on_error "Chowning $combo to be owned by $user_name"
381 echo "$(date_stringer): user name failed checks for chowning, was found as '$user_name'" >> "$SSM_LOG_FILE"
385 #probably not enough for path!
386 fix_site_perms "$combo"
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.
393 # check for parameters.
394 app_dirname="$1"; shift
396 check_apps_root "$BASE_APPLICATION_PATH"
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"
403 test_app_folder "$BASE_APPLICATION_PATH" "$app_dirname"
405 if [ $? -ne 0 ]; then
406 echo "Could not locate the application directory: ${app_dirname}"
410 # where we expect to find our checkout folder underneath.
411 full_app_dir="$BASE_APPLICATION_PATH/$app_dirname"
413 pushd $full_app_dir/$CHECKOUT_DIR_NAME
414 #redundant if pushd pwd