Skip to content
Browse files

added geocamUtilWeb submodule and bootstrap.py

  • Loading branch information...
1 parent dc94d42 commit 833a99e0f5366668a7ff263f211fbecc4ffcd4c4 @trey0 committed Mar 1, 2011
Showing with 269 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. +3 −0 .gitmodules
  3. +8 −0 manage.py
  4. +246 −0 management/bootstrap.py
  5. +10 −0 management/requirements.txt
  6. +1 −0 submodules/geocamUtilWeb
View
1 .gitignore
@@ -17,3 +17,4 @@ django.wsgi
apps/geocamTrack/media/avatars/cache/*.png
apps/geocamTrack/media/avatars/gravatars
apps/geocamTrack/media/avatars/*.png
+apps/geocamUtil
View
3 .gitmodules
@@ -0,0 +1,3 @@
+[submodule "submodules/geocamUtilWeb"]
+ path = submodules/geocamUtilWeb
+ url = git@github.com:geocam/geocamUtilWeb.git
View
8 manage.py
@@ -5,6 +5,14 @@
# All Rights Reserved.
# __END_LICENSE__
+import os
+import sys
+
+# try to bootstrap before hooking into django management stuff
+ret = os.spawnl(os.P_WAIT, sys.executable, sys.executable, '%s/management/bootstrap.py' % os.path.dirname(__file__), '-v')
+if ret != 0:
+ sys.exit(ret)
+
from django.core.management import execute_manager
try:
import settings # Assumed to be in the same directory.
View
246 management/bootstrap.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python
+# __BEGIN_LICENSE__
+# Copyright (C) 2008-2010 United States Government as represented by
+# the Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+# __END_LICENSE__
+
+"""
+This bootstrap script does the first stage of prep work for a Django
+site that consists of multiple apps pulled in from separate repos via
+git submodules. The script does just enough so that our subsequent
+Django management commands will work -- they need Django to be installed
+and minimally configured, and they need the apps to be present
+and linked into the right place relative to the PYTHONPATH.
+
+This script is intended to be generic across sites. Please don't put
+any site-specific customizations in here. If you need to modify it,
+please check your changes into
+geocamDjangoSiteSkeleton/skel/bin/bootstrap.py so other sites can
+benefit. Normally we would put code like this in geocamUtil, but the
+whole reason we need a bootstrap step is to make sure things like
+geocamUtil are available...
+"""
+
+import os
+import sys
+from glob import glob
+import logging
+from random import choice
+
+DEFAULT_SITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+SOURCEME_NAME = 'sourceme.sh'
+SETTINGS_NAME = 'settings.py'
+STATUS_PATH_TEMPLATE = 'build/management/bootstrap/%sStatus.txt'
+
+ACTIONS = (dict(name='gitInitSubmodules',
+ desc="init and update submodules",
+ confirm=True),
+ dict(name='linkSubmodules',
+ desc='link submodules into apps directory',
+ confirm=True),
+ dict(name='installDjango',
+ desc='install Django',
+ confirm=True,
+ needed='needDjango'),
+ dict(name='genSourceme',
+ needed='needSourceme'),
+ dict(name='genSettings',
+ needed='needSettings'),
+ )
+ACTION_DICT = dict([(a['name'], a) for a in ACTIONS])
+
+def getConfirmation(opts, actionStr):
+ if opts.yes:
+ sys.stdout.write(actionStr+'? [Y/n] ')
+ print 'y'
+ return True
+ else:
+ while 1:
+ sys.stdout.write(actionStr+'? [Y/n] ')
+ response = raw_input().strip().lower()
+ if not response:
+ return True
+ elif response == 'y':
+ return True
+ elif response == 'n':
+ return False
+
+def dosys(cmd, continueOnError=False):
+ if cmd.startswith('sudo'):
+ # force print before user gets password prompt
+ print 'running: ' + cmd
+ else:
+ logging.info('running: ' + cmd)
+ ret = os.system(cmd)
+ if ret != 0:
+ if continueOnError:
+ logging.warning('warning: command returned non-zero return value %d' % ret)
+ else:
+ logging.error('error: command returned non-zero return value %d' % ret)
+ sys.exit(1)
+
+def writeFileMakeDir(path, text):
+ dir = os.path.dirname(path)
+ if not os.path.exists(dir):
+ os.makedirs(dir)
+ f = file(path, 'w')
+ f.write(text+'\n')
+ f.close()
+
+def fillTemplate(inputFile, outputFile, context):
+ from django.template import Template, Context
+ from django.conf import settings
+ if not settings.configured:
+ settings.configure()
+ tmpl = Template(file(inputFile, 'r').read())
+ text = tmpl.render(Context(context))
+ file(outputFile, 'w').write(text)
+
+######################################################################
+# ACTION DEFINITIONS
+
+def gitInitSubmodules(opts):
+ dosys('git submodule init')
+ dosys('git submodule update')
+
+def linkSubmodules(opts):
+ # assumes each submodule app has a models dir or a models.py file
+ submoduleAppDirs = [os.path.dirname(d) for d in glob('submodules/*/*/models*')]
+ for src in submoduleAppDirs:
+ appName = os.path.basename(src)
+ relativeSrc = '../%s' % src
+ dst = 'apps/%s' % appName
+ if os.path.lexists(dst):
+ logging.debug(' %s -> %s skipped (already exists)' % (dst, relativeSrc))
+ else:
+ logging.debug(' %s -> %s' % (dst, relativeSrc))
+ os.symlink(relativeSrc, dst)
+
+def needDjango(opts):
+ try:
+ import django
+ except ImportError:
+ return True
+ return False
+
+def installDjango(opts):
+ needSudo = not os.environ.has_key('VIRTUALENV')
+ if needSudo:
+ sudoStr = 'sudo '
+ else:
+ sudoStr = ''
+ dosys('%spip install django' % sudoStr)
+
+def needSourceme(opts):
+ return not os.path.exists(SOURCEME_NAME)
+
+def genSourceme(opts):
+ logging.info('generating %s' % SOURCEME_NAME)
+
+ fillTemplate('management/templates/%s' % SOURCEME_NAME,
+ SOURCEME_NAME,
+ dict(virtualEnvDir=os.environ.get('VIRTUALENV', None),
+ parentDir=os.path.dirname(os.path.abspath(os.getcwd())),
+ appsDir=os.path.abspath('apps')
+ ))
+
+def needSettings(opts):
+ return not os.path.exists(SETTINGS_NAME)
+
+def genSettings(opts):
+ logging.info('generating %s' % SETTINGS_NAME)
+
+ secretKey = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])
+
+ fillTemplate('management/templates/%s' % SETTINGS_NAME,
+ SETTINGS_NAME,
+ dict(secretKey=secretKey))
+
+def needAction(opts, action):
+ statusFile = STATUS_PATH_TEMPLATE % action['name']
+ if os.path.exists(statusFile):
+ return file(statusFile, 'r').read().strip()
+ else:
+ return False
+
+######################################################################
+# TOP-LEVEL CODE
+
+def doAction(opts, action):
+ # check if we need to do the action
+ neededName = action.get('needed', None)
+ if neededName:
+ # special check function defined for this action
+ neededFunc = globals()[neededName]
+ actionIsNeeded = neededFunc(opts)
+ if not actionIsNeeded:
+ logging.info('skipping step %s, not needed' % action['name'])
+ return
+ else:
+ # standard check function
+ status = needAction(opts, action)
+ if status:
+ logging.info('skipping step %s, status is %s' % (action['name'], status))
+ return
+
+ # confirm with user
+ if action.has_key('confirm') and not getConfirmation(opts, action['desc']):
+ writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'UNWANTED')
+ return
+
+ # do the action
+ actionFunc = globals()[action['name']]
+ actionFunc(opts)
+
+ # mark completion (unless special check function is defined)
+ if not neededName:
+ writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'DONE')
+
+def doit(opts, args):
+ os.chdir(opts.siteDir)
+ if os.path.exists('build/management/bootstrap/bootstrapStatus.txt'):
+ sys.exit(0)
+ print 'bootstrapping...'
+
+ logging.basicConfig(level=(logging.WARNING - opts.verbose * 10),
+ format='%(message)s')
+
+ if args:
+ for arg in args:
+ if arg not in ACTION_DICT:
+ print >>sys.stderr, 'ERROR: there is no action %s' % arg
+ print >>sys.stderr, 'available actions are: %s' % (' '.join([a['name'] for a in ACTIONS]))
+ sys.exit(1)
+ actions = [ACTION_DICT[arg] for arg in args]
+ else:
+ actions = ACTIONS
+
+ logging.info('working in %s' % os.getcwd())
+ for action in ACTIONS:
+ doAction(opts, action)
+
+ # mark overall completion
+ writeFileMakeDir(STATUS_PATH_TEMPLATE % 'bootstrap', 'DONE')
+
+ print '\nnow "source sourceme.sh" before running manage.py again'
+ sys.exit(1)
+
+def main():
+ import optparse
+ parser = optparse.OptionParser('usage: %prog [action1 action2 ...]')
+ parser.add_option('-y', '--yes',
+ action='store_true', default=False,
+ help='Automatically answer yes to all confirmation questions')
+ parser.add_option('-s', '--siteDir',
+ default=DEFAULT_SITE_DIR,
+ help='Site directory to work in [%default]')
+ parser.add_option('-v', '--verbose',
+ action='count', default=0,
+ help='Increase verbosity, can specify multiple times')
+ opts, args = parser.parse_args()
+ doit(opts, args)
+
+if __name__ == '__main__':
+ main()
View
10 management/requirements.txt
@@ -0,0 +1,10 @@
+# This is a pip requirements file
+# http://pip.openplans.org/requirement-format.html
+
+# If you have the geocamUtil app, these requirements will be installed
+# when you run "manage.py installreqs". This default version just
+# installs the requirements of the apps within the site by including the
+# auto-generated appRequirements.txt file, but you can do whatever you
+# want.
+
+-r ../build/management/appRequirements.txt
1 submodules/geocamUtilWeb
@@ -0,0 +1 @@
+Subproject commit 469722506bae7be905ab24a0cde400a3aaf1d7e3

0 comments on commit 833a99e

Please sign in to comment.
Something went wrong with that request. Please try again.