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 WORKDIR, 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 # get our configuration loaded, if we know the config file.
15 # if there is none, we will use our default version.
16 export SITE_MANAGEMENT_CONFIG_FILE
17 if [ -z "$SITE_MANAGEMENT_CONFIG_FILE" ]; then
18 SITE_MANAGEMENT_CONFIG_FILE="$WORKDIR/config/default.app"
19 echo "Site management config file was not set. Using default:"
20 echo " $SITE_MANAGEMENT_CONFIG_FILE"
23 # load in at least the default version to get us moving.
24 source "$SITE_MANAGEMENT_CONFIG_FILE"
25 test_or_die "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
27 # configure feisty revision control to ignore vendor folders.
28 export NO_CHECKIN_VENDOR=true
30 # tests that the main storage folder for apps exists.
31 function check_apps_root()
33 local appdir="$1"; shift
34 if [ ! -d "$appdir" ]; then
35 echo "Creating the apps directory: $appdir"
37 test_or_die "Making apps directory when not already present"
41 # tries to find an appropriate config file for the application.
42 function locate_config_file()
44 local app_dirname="$1"; shift
46 local configfile="$WORKDIR/config/${app_dirname}.app"
47 echo "config file?: $configfile"
48 if [ ! -f "$configfile" ]; then
49 # this is not a good config file. we can't auto-guess the config.
51 There is no specific site configuration file in:
53 We will continue onward using the default and hope that this project follows
54 the standard pattern for cakephp projects."
55 # we'll pull in the default config file we set earlier; this will
56 # reinitialize some variables based on the app name.
58 # they gave us a valid config file. let's try using it.
59 export SITE_MANAGEMENT_CONFIG_FILE="$configfile"
62 # try to load the config.
63 source "$SITE_MANAGEMENT_CONFIG_FILE"
64 test_or_die "loading site management configuration from: $SITE_MANAGEMENT_CONFIG_FILE"
69 # this function will seek out top-level directories in the target directory passed in.
70 # if there is only one directory, then it is returned (in the app_dirname variable).
71 # otherwise, the user is asked which directory to use.
72 # important: this sets a global variable app_dirname to the application's directory name.
73 function find_app_folder()
75 local appsdir="$1"; shift
77 # throw away any prior value so no confusion arises.
80 # count number of directories... if exactly one, then choose it.
81 numdirs=$(count_directories "$appsdir")
83 if [ $numdirs -eq 0 ]; then
85 echo "There are no directories in the application directory:"
87 echo "Please create a directory for the site storage, based on the application"
88 echo "name that you want to work on. Or you can just pass the directory name"
89 echo "on the command line, e.g.:"
90 echo " $(basename $0) turtle"
93 elif [ $numdirs -eq 1 ]; then
94 app_dirname="$(basename $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d) )"
95 test_or_die "Guessing application folder"
97 # if more than one folder, force user to choose.
98 # Reference: https://askubuntu.com/questions/1705/how-can-i-create-a-select-menu-in-a-shell-script
100 PS3='Please pick a folder for site initialization: '
101 options=( $(find "$appsdir" -mindepth 1 -maxdepth 1 -type d -exec basename {} ';') "Quit")
102 select app_dirname in "${options[@]}"; do
104 "Quit") echo ; echo "Quitting from the script."; return 1; ;;
105 *) echo ; echo "You picked folder '$app_dirname'" ; break; ;;
108 if [ -z "$app_dirname" ]; then
109 echo "The folder was not provided. This script needs a directory name"
110 echo "within which to initialize the site."
115 test_app_folder "$appsdir" "$app_dirname"
116 test_or_die "Testing application folder: $app_dirname"
118 echo "Application folder is: $app_dirname"
122 # ensures that the app directory name is valid and then loads the config
123 # for the app (either via a specific file or using the defaults).
124 function test_app_folder()
126 local appsdir="$1"; shift
127 local dir="$1"; shift
129 local combo="$appsdir/$dir"
131 if [ ! -d "$combo" ]; then
132 echo "Creating app directory: $combo"
134 test_or_die "Making application directory when not already present"
137 locate_config_file "$dir"
140 # eases some permissions to enable apache to write log files and do other shopkeeping.
141 function fix_site_perms()
143 local app_dir="$1"; shift
145 local site_dir="$app_dir/$CHECKOUT_DIR_NAME"
147 if [ -f "$site_dir/bin/cake" ]; then
148 sudo chmod -R a+rx "$site_dir/bin/cake"
149 test_or_die "Enabling execute bit on cake binary"
152 if [ -d "$site_dir/logs" ]; then
153 sudo chmod -R g+w "$site_dir/logs"
154 test_or_die "Enabling group write on site's Logs directory"
157 if [ -d "$site_dir/tmp" ]; then
158 sudo chmod -R g+w "$site_dir/tmp"
159 test_or_die "Enabling group write on site's tmp directory"
163 # tosses out any cached object data that originated from the database.
164 function clear_orm_cache()
166 local site_dir="$1"; shift
168 if [ -f "$site_dir/bin/cake" ]; then
169 # flush any cached objects from db.
170 "$site_dir/bin/cake" orm_cache clear
171 test_or_die "Clearing ORM cache"
175 # updates the revision control repository passed in. this expects that the
176 # repo will live in a folder called "checkout_dirname" under the app path,
177 # which is the standard for our deployed sites.
178 # important: this also sets a global variable called site_store_path to the full
179 # path of the application.
180 function update_repo()
182 local full_app_dir="$1"; shift
183 local checkout_dirname="$1"; shift
184 local repo_root="$1"; shift
185 local repo_name="$1"; shift
187 echo here are parms in update repo:
188 var full_app_dir checkout_dirname repo_root repo_name
190 # forget any prior value, since we are going to validate the path.
191 unset site_store_path
193 pushd "$full_app_dir" &>/dev/null
194 test_or_die "Switching to our app dir '$full_app_dir'"
196 local complete_path="$full_app_dir/$checkout_dirname"
198 # see if the checkout directory exits. the repo_found variable is set to
199 # non-empty if we find it and it's a valid git repo.
201 if [ -d "$checkout_dirname" ]; then
202 # checkout directory exists, so let's check it.
203 pushd "$checkout_dirname" &>/dev/null
204 test_or_die "Switching to our checkout directory: $checkout_dirname"
206 # ask for repository name (without .git).
207 if git rev-parse --git-dir > /dev/null 2>&1; then
208 # this is a valid git repo.
212 # we don't consider the state of having the dir exist but the repo be wrong as good.
213 if [ -z "$repo_found" ]; then
214 echo "There is a problem; this folder is not a valid repository:"
215 echo " $full_app_dir"
216 echo "This script cannot continue unless the git repository is valid."
222 if [ ! -z "$repo_found" ]; then
223 # a repository was found, so update the version here and leave.
224 echo "Repository $repo_name exists. Updating it."
226 test_or_die "Recursive checkout on: $complete_path"
228 # clone the repo since it wasn't found.
229 echo "Cloning repository $repo_name now."
230 git clone "$repo_root/$repo_name.git" $checkout_dirname
231 test_or_die "Git clone of repository: $repo_name"
234 #not doing this here since powerup uses this and has no sudo.
235 #fix_site_perms "$complete_path"
238 # construct the full path to where the app will actually live.
239 site_store_path="$complete_path"
244 # this function goes to the directory specified and makes it right with
245 # composer install. this is as opposed to composer update, which could
247 function composer_repuff()
249 local site_store_path="$1"; shift
251 pushd "$site_store_path" &>/dev/null
252 test_or_die "Switching to our app dir '$site_store_path'"
254 echo "Updating site with composer..."
257 test_or_die "Composer installation step on '$site_store_path'."
261 dir="$site_store_path/$CHECKOUT_DIR_NAME/vendor/siteavenger/avcore"
262 if [ -d "$dir" ]; then
263 echo "Running avcore database migrations..."
264 logfile="$TMP/problem-avcore_db_migration-$(date_stringer).log"
265 ./bin/cake migrations migrate -p Avcore &>"$logfile"
266 if [ $? -ne 0 ]; then
267 echo "** FAILED: Database migrations for avcore. Check log file in: $logfile"
268 # we keep going, because some sites aren't ready for this yet.
271 echo "Database for avcore migrated."
280 # this function creates the links needed to make the site function properly given our
281 # various dependencies and infrastructure.
282 function create_site_links()
284 local site_store_path="$1"; shift
285 local theme_name="$1"; shift
287 echo "Creating symbolic links for site assets..."
289 # jump into the site path so we can start making relative links.
290 pushd "$site_store_path" &>/dev/null
291 test_or_die "Switching to our app dir '$site_store_path'"
293 pushd webroot &>/dev/null
295 # remove all symlinks that might plague us.
296 find . -maxdepth 1 -type l -exec rm -f {} ';'
297 test_or_die "Cleaning out links in webroot"
299 # link in the avcore plugin.
300 make_safe_link "../vendor/siteavenger/avcore/webroot" avcore
302 # make the link for our theme as a lower-case version of the theme.
303 themelower=${theme_name,,}
304 make_safe_link "../plugins/$theme_name/webroot" "$themelower"
306 # link in any favicon files.
307 if [ -d "../plugins/$theme_name/favicon" ]; then
309 for fave in "../plugins/$theme_name/favicon"/*; do
310 make_safe_link "$fave" .
314 # get back out of webroot.
317 # hop up a level above where we had been.
320 # link 'public' to webroot.
321 if [ -L public ]; then
322 # public is a symlink.
324 test_or_die "Removing public directory symlink"
325 elif [ -d public ]; then
326 # public is a folder with default files.
329 test_or_die "Removing public directory and contents"
332 # create the main 'public' symlink
334 make_safe_link $CHECKOUT_DIR_NAME/webroot public
335 test_or_die "Creating link to webroot called 'public'"
337 #hmmm: public/$themelower/im will be created automatically by system user with appropriate permissions
339 echo Created symbolic links.
345 # fetches composer to make sure it's up to date.
346 # (if powerup runs, composer install doesn't update git origin.)
347 function update_composer_repository()
349 local site_store_path="$1"; shift
351 pushd "$site_store_path" &>/dev/null
353 if git config remote.composer.url &>/dev/null; then
355 echo "Updated the composer repository."
357 echo "No composer repository was found for updating."
361 # fixes the ownership for a site avenger or php application.
362 # this almost certainly will require sudo capability, if there are any ownership problems
363 # that need to be resolved.
364 function fix_appdir_ownership()
366 local appsdir="$1"; shift
367 local dir="$1"; shift
369 local combo="$appsdir/$dir"
371 # go with the default user running the script.
373 if [ ! -z "$user_name" -a "$user_name" != "root" ]; then
374 echo "Chowning the app folder to be owned by: $user_name"
375 #hmmm: have to hope for now for standard group named after user
376 sudo chown -R "$user_name:$user_name" "$combo"
377 test_or_die "Chowning $combo to be owned by $user_name"
379 echo "user name failed checks for chowning, was found as '$user_name'"
383 #probably not enough for path!
384 fix_site_perms "$combo"
387 # Jumps to an application directory given the app name. If no app name is
388 # given, it will show a menu to pick the app.
391 # check for parameters.
392 app_dirname="$1"; shift
394 check_apps_root "$BASE_APPLICATION_PATH"
396 # find proper webroot where the site will be initialized.
397 if [ -z "$app_dirname" ]; then
398 # no dir was passed, so guess it.
399 find_app_folder "$BASE_APPLICATION_PATH"
401 test_app_folder "$BASE_APPLICATION_PATH" "$app_dirname"
403 if [ $? -ne 0 ]; then
404 echo "Could not locate that application directory"
408 # where we expect to find our checkout folder underneath.
409 full_app_dir="$BASE_APPLICATION_PATH/$app_dirname"
411 cd $full_app_dir/$CHECKOUT_DIR_NAME