You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@gump.apache.org by le...@apache.org on 2005/11/12 12:54:04 UTC

svn commit: r332761 - in /gump/branches/Gump3: pygump/ pygump/python/ pygump/python/gump/ pygump/python/gump/engine/ pygump/python/gump/model/ webgump/ webgump/bin/

Author: leosimons
Date: Sat Nov 12 03:53:47 2005
New Revision: 332761

URL: http://svn.apache.org/viewcvs?rev=332761&view=rev
Log:
More work on GUMP-105 -- adding 'use last successful build' functionality. This is tricky stuff which will take quite a bit of munging to get right. But the basics *seem* to be holding up with this new code...

Added:
    gump/branches/Gump3/webgump/INSTALL.txt   (with props)
Modified:
    gump/branches/Gump3/pygump/   (props changed)
    gump/branches/Gump3/pygump/python/gump/config.py
    gump/branches/Gump3/pygump/python/gump/engine/algorithm.py
    gump/branches/Gump3/pygump/python/gump/engine/persistence.py
    gump/branches/Gump3/pygump/python/gump/model/util.py
    gump/branches/Gump3/pygump/python/main.py
    gump/branches/Gump3/webgump/bin/get-apache
    gump/branches/Gump3/webgump/bin/settings

Propchange: gump/branches/Gump3/pygump/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sat Nov 12 03:53:47 2005
@@ -1,2 +1,3 @@
 work
 *.pyc
+gumpshelf

Modified: gump/branches/Gump3/pygump/python/gump/config.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/config.py?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/config.py (original)
+++ gump/branches/Gump3/pygump/python/gump/config.py Sat Nov 12 03:53:47 2005
@@ -324,6 +324,24 @@
     return impl
 
 
+def get_persistence_helper(config):
+    """Provide a persistence helper."""
+    log = get_logger(config, "persister")
+    if config.enable_persistence:
+        log.info("""Enabling ***experimental*** persistence features!
+          Phooey...you're very on-the-edge at the moment!""")
+        import shelve
+        shelf = shelve.open(config.persistence_file)
+    
+        from gump.engine.persistence import ShelfBasedPersistenceHelper
+        helper = ShelfBasedPersistenceHelper(shelf, log)
+        return helper
+    else:
+        log.info("Not using persistence! (pass --enable-persistence to enable)")
+        from gump.engine.algorithm import NoopPersistenceHelper
+        return NoopPersistenceHelper()
+
+
 def get_plugin(config):
     """Provide a Plugin implementation."""
     from gump.engine.algorithm import DumbAlgorithm
@@ -331,11 +349,15 @@
     
     (pre_process_plugins, plugins, post_process_plugins) = get_plugins(config)
     error_handler = get_error_handler(config)
+    persistence_helper = get_persistence_helper(config)
     
     if getattr(config, "project_name", False):
-        mainalgorithm = MoreEfficientAlgorithm(plugins, error_handler, project_list=config.project_name)
+        mainalgorithm = MoreEfficientAlgorithm(plugins, error_handler,
+                                               persistence_helper=persistence_helper,
+                                               project_list=config.project_name)
     else:
-        mainalgorithm = MoreEfficientAlgorithm(plugins, error_handler)
+        mainalgorithm = MoreEfficientAlgorithm(plugins, error_handler,
+                                               persistence_helper=persistence_helper)
     
     return (DumbAlgorithm(pre_process_plugins, error_handler),
             mainalgorithm, #DumbAlgorithm(plugins, error_handler)

Modified: gump/branches/Gump3/pygump/python/gump/engine/algorithm.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/engine/algorithm.py?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/engine/algorithm.py (original)
+++ gump/branches/Gump3/pygump/python/gump/engine/algorithm.py Sat Nov 12 03:53:47 2005
@@ -39,6 +39,7 @@
 from gump.model import ModelObject, CvsModule, ExceptionInfo, Jar
 from gump.model.util import mark_failure, check_failure, mark_skip, check_skip
 from gump.model.util import mark_whether_module_was_updated
+from gump.model.util import mark_stale_prereq
 from gump.model.util import check_module_update_failure
 from gump.model.util import store_exception
 
@@ -164,13 +165,16 @@
                         "{{{finalization stage}}}", type, value, traceback)
 
 class NoopPersistenceHelper:
-    def use_previous_build(self, arg):
+    def store_previous_builds(self, *args):
         pass
     
-    def has_previous_build(self, arg):
+    def use_previous_build(self, *args):
         pass
     
-    def stop_using_previous_build(self, arg):
+    def has_previous_build(self, *args):
+        return False
+    
+    def stop_using_previous_build(self, *args):
         pass
 
 DEFAULT_PROJECT_REGEX = ".*"
@@ -187,7 +191,10 @@
       - if a module fails to update, the projects it contains are not built
       - if there were no changes to the module since the previous run, the projects
         it contains are not built
-      - if a project fails to build, none of its dependees are built
+      - if a project fails to build
+        - if there is a "previous build"
+          - its dependees are flagged "failed prereq" and built against that
+        - otherwise none of its dependees are built
     
     If an element "fails", its "failed" property will be set to "True" and an
     array named "failure_cause" will be created pointing to the elements that
@@ -266,6 +273,7 @@
                 # if there is a "last successful build", we'll use that
                 if self.persistence_helper.has_previous_build(project):
                     self.persistence_helper.use_previous_build(relationship.dependency)
+                    mark_stale_prereq(project, relationship.dependency)
                 else:
                     # otherwise, we're doomed!
                     mark_failure(project, relationship)
@@ -287,6 +295,8 @@
     
     def _finalize(self, workspace):
         DumbAlgorithm._finalize(self, workspace)
-        self.persistence_helper.stop_using_previous_build(workspace)
+        for project in workspace.projects:
+            self.persistence_helper.stop_using_previous_build(project)
+        self.persistence_helper.store_previous_builds(workspace)
         self.project_model_list = []
         self.module_model_list = []

Modified: gump/branches/Gump3/pygump/python/gump/engine/persistence.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/engine/persistence.py?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/engine/persistence.py (original)
+++ gump/branches/Gump3/pygump/python/gump/engine/persistence.py Sat Nov 12 03:53:47 2005
@@ -14,134 +14,291 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-#    Information from previous projects can be stored using the store_previous_build()
-#    method. It can be used in place of the "current build" using use_previous_build()
-#    if has_previous_build() shows there actually was a build stored, and then everything
-#    can be restored to normal using stop_using_previous_build().
+"""Extreme gump model hacking wizardry which uses the python shelve module to keep 
+around the "last successful build". This is an experimental module only!
 
-from gump.model.util import get_project_directory
-import os
+Why no unit tests? No good reason. There really ought to be some. Since this code has
+*loads* of side effects, the unit test should actually be quite big. Secondly, since
+basically we're subverting all the 'cleanness' of our model there should be extensive
+integration testing. Oh well. Testing in isolation *should* be relatively feasible just
+by passing in a mock shelf.
+
+Basically what happens is that when the algorithm.py detects a dependency on a failed
+build, it will ask this helper to get it a "previous one". In order to make the rest of
+the gump system work kind-of transparently, that means we need to realistically store
+"everything" about a particular project build. "Everything" is potentially pretty much
+a snapshot of the entire harddrive of the system, the entire gump codebase itself, the
+load-up of that codebase in memory, etc. That's a bit too much.
+
+What we do save is a mungled, minimized, small snapshot of a part of the project and
+the stuff it refers to within the gump model. And then we make a snapshot of the project
+directory (eg all of the checkout including subdirectories, so that should include all
+build outputs too) which we save too.
+
+Then when we want to use a previous build, we get the mangled project definition from
+the shelf and force-feed it into the new gump tree. We update it to reference the new
+module (though we don't update the module to reference the new project), update it to
+have dependencies on the new projects (though the algorithm.py doesn't make sure that
+those have already been built, which can introduce subtle problems if the dependencies
+for a project changed, but little we can do about that), then update the project path
+to reference the snapshot of its files, and then finally we actually "replace" the
+"current" (failed) project with the "previous" one in the project tree.
+
+This replacement project definition stays in force for the rest of the run (though
+algorithm.py could change that behaviour) so that if many projects depend on this failed
+one, we don't have to go through the process of loading the project every time.
+
+Why not implemented as a plugin? Well, this module is one of the core bits of the
+algorithm.py functionality, and otherwise pretty much hacks into lots of bits in the
+gump system. While the parts of this plugin that don't interact with the algorithm.py
+code very closely could be split off, keeping it "out" as a special case hopefully keeps
+the program flow a little more understandable.
+
+Note that the file-copying code is not very efficient. Ideally we can do something using
+hard links, falling back to efficient rsync. What we're doing here is doubling disk space
+usage. When using SVN and doing a 'keep local copy checked out and duplicate before build'
+(which gump2 does but gump3 does not at the moment), that means we have 3 checkouts of the
+same stuff, which means 6 times the disk space, since SVN keeps around the .svn
+directories). Ouch!
+"""
 
-def has_previous_build(project):
-    """Determine if information from a previous build was stored for this project."""
-    return hasattr(project, "previous_build")
+from gump.model import Workspace, Repository, Module, Project, Jar, Path
+from gump.model.util import get_project_directory, check_failure, check_skip
+import os
+import shutil
+import copy
 
+GUMP_STORAGE_DIRNAME=".gump-persist"
 
-def store_previous_build(project):
-    import copy
+def copytree(source=None, target=None, excludes=[]):
+    """Naive non-performant copytree utility.
     
-    stored_project = copy.deepcopy(project) # TODO problem here!!!!
+    TODO: replace with something efficient (like rsync.py from gump2)."""
+    if os.path.exists(target):
+        shutil.rmtree(target)
+    shutil.copytree(source, target)
+    for x in excludes:
+        fullpath = os.path.join(target, x)
+        if os.path.exists(fullpath):
+            shutil.rmtree(fullpath)
+        
+class ShelfBasedPersistenceHelper:
+    def __init__(self, shelf, log):
+        self.shelf = shelf
+        self.log = log
+        
+    def store_previous_builds(self, workspace):
+        for project in workspace.projects.values():
+            if not check_failure(project) and not check_skip(project):
+                self.log.debug(
+"Project %s built okay, storing as the new 'last successful build'..." % project)
+                self.store_previous_build(project)
+    
+    def store_previous_build(self, project):
+        if getattr(project, "failed", False):
+            return
+
+        # check there's no problematic references...
+        for output in project.outputs:
+            if isinstance(output, Jar): # relative path is ok...
+                continue
+            if isinstance(output, Path): # relative path is ok...
+                continue
+            
+            # eg a Classdir is not allowed...
+            raise "Can't store this kind of output (%s)!" % output
+        
+        # okay we can shelve this...
+        self.log.debug("Storing previous build for %s..." % project)
+        storeable_project = self.extract_storeable_project(project)
+        
+        # save files...
+        self.store_previous_build_files(storeable_project)
+        
+        # now disconnect the rest of the model tree so we don't save it.
+        storeable_project.module = None
+        self.shelve_project(storeable_project)
+        
+    def extract_storeable_project(self, oldproject):
+        # create a project referencing private copies of most stuff
+        oldmodule = oldproject.module
+        oldrepository = oldmodule.repository
+        oldworkspace = oldrepository.workspace
+        
+        newworkspace = Workspace(oldworkspace.name, oldworkspace.workdir)
+        newrepository = Repository(oldworkspace, oldrepository.name,
+                                   oldrepository.title, oldrepository.home_page,
+                                   oldrepository.cvsweb, oldrepository.redistributable)
+        newmodule = Module(newrepository, oldmodule.name, oldmodule.url, oldmodule.description)
+        newproject = Project(newmodule, oldproject.name, oldproject.path, oldproject.homedir)
+        
+        # and now we built that tree, note we set the reference to the module to null,
+        # right before saving, circumverting all the checks in the model. So none of the
+        # above except newproject is actually stored! Heh.
+        # only right before saving....newproject.module = None
+        
+        # store only names of dependencies
+        newproject.shelf_dependencies = []
+        for relationship in oldproject.dependencies:
+            newproject.shelf_dependencies.append(relationship.dependency.name)
+        
+        for output in oldproject.outputs:
+            # these should not hold references to other parts of the tree...
+            newproject.add_output(output)
+        
+        dontadd = ["module", "name", "path", "homedir", "dependencies", "dependees", "outputs", \
+                   "commands", "shelf_dependencies"]
+        for x in [x for x in dir(oldproject) if not x in dontadd]:
+            att = getattr(oldproject, x)
+            if callable(att):
+                continue
+            setattr(newproject, x, att)
+        
+        return newproject
     
-    if getattr(project, "failed", False):
-        return
+    def store_previous_build_files(self, project):
+        currentpath = os.path.join(get_project_directory(project))
+        if os.path.exists(currentpath):
+            storage_path = os.path.join(currentpath, GUMP_STORAGE_DIRNAME)
+    
+            self.log.debug("Saving %s files into %s..." % (project, storage_path))
+            
+            copytree(source=currentpath, target=storage_path, excludes=[GUMP_STORAGE_DIRNAME])
+            
+            project.original_path = project.path
+            project.path = os.path.join(project.path, GUMP_STORAGE_DIRNAME)
+        else:
+            self.log.debug("Not saving %s files -- none exist!" % project)
     
-    for output in project.outputs:
-        if isinstance(output, Homedir):
-            store_previous_build_homedir(project, output)
-            continue
-        if isinstance(output, Jar):
-            store_previous_build_jar(project, output)
-            continue
+    def shelve_project(self, storeable_project):
+        self.shelf[str(storeable_project.name)] = storeable_project
+    
+    def load_previous_build(self, project):
+        project.previous_build = self.shelf[str(project.name)]
+        
+        # and include in the "new" tree
+        project.previous_build.module = project.module
+        ws = project.repository.module.workspace
         
-        raise "Can't store this kind of output (%s)!" % output
+        # and link up dependencies
+        for depname in project.previous_build.shelf_dependencies:
+            # note we create a situation here where an "old" project seems to depend
+            # on a "new" one. This can sort-of be detected by the dependee belonging
+            # to a different workspace, except we just changed that, above! So, lets
+            # flag this dependency as "one from the past", at least...
+            if ws.projects.has_key(depname):
+                project.previous_build.add_dependency(ws.projects[depname])
+                setattr(project.previous_build.dependencies[-1], "previous_build", True)
+            else:
+                self.log.warn(
+"Previous build %s depends on project %s, which no longer exists! We're going to try and ignore this..." % (
+    project.previous_build, depname))
 
-# TODO make module out of all this, make this configurable
-import shutil
-storage_dir = os.path.join("work", "previous_build_storage")
-if not os.path.exists(storage_dir):
-  os.makedirs(storage_dir)
-
-def store_previous_build_homedir(project, homedir):
-    homedir_path = os.path.join(get_project_directory(project), homedir.directory)
-    homedir_storage_path = os.path.join(storage_dir, homedir_path)
-    shutil.copytree(homedir_path, homedir_storage_path)
-
-def is_special_previous_build_attr(name):
-    return name == "delete_atts_when_stopping_to_use_previous_build" or \
-           name == "use_atts_when_stopping_to_use_previous_build" or \
-           name == "previous_build"
-
-def use_previous_build(project):
-    # if the "previous build" "failed" we'll not attempt to use it
-    if getattr(project.previous_build, "failed", False):
-        return
-    
-    if hasattr(project, "use_atts_when_stopping_to_use_previous_build"):
-        # use_previous_build() seemingly was already active on this build
-        return
-
-    # we'll replace all current members with the "old" members
-    import inspect
-    members = inspect.getmembers(project)
-    oldmembers = inspect.getmembers(project.previous_build)
-    
-    # remember...
-    project.use_atts_when_stopping_to_use_previous_build = members
-
-    # we'll delete all current members that weren't there before
-    temporarily_delete_attrs = []
-    for (newname, newvalue) in members:
-        found_in_old = False
+    def has_previous_build(self, project):
+        """Determine if information from a previous build was stored for this project."""
+        
+        currentpath = os.path.join(get_project_directory(project))
+        storage_path = os.path.join(currentpath, GUMP_STORAGE_DIRNAME)
+        
+        files_available = os.path.exists(storage_path)
+        shelved = self.shelf.has_key(project.name)
+        return files_available and shelved
+    
+    def is_special_previous_build_attr(self, name):
+        return name in ["delete_atts_when_stopping_to_use_previous_build",
+                        "use_atts_when_stopping_to_use_previous_build",
+                        "previous_build"]
+    
+    def use_previous_build(self, project):
+        # algorithm should check this!
+        assert self.has_previous_build(project)
+        
+        self.log.debug("Using previous build for %s" % project)
+        
+        # get stuff from the shelf
+        self.load_previous_build(project)
+
+        # if the "previous build" "failed" we'll not attempt to use it
+        # note that we'd be dealing with a silly algorithm -- we shouldn't be
+        # storing failed builds...
+        if getattr(project.previous_build, "failed", False):
+            return
+        
+        if hasattr(project, "use_atts_when_stopping_to_use_previous_build"):
+            # use_previous_build() seemingly was already active on this build
+            return
+    
+        # we'll replace all current members with the "old" members
+        import inspect
+        members = inspect.getmembers(project)
+        oldmembers = inspect.getmembers(project.previous_build)
+        
+        # remember...
+        project.use_atts_when_stopping_to_use_previous_build = members
+    
+        # we'll delete all current members that weren't there before
+        temporarily_delete_attrs = []
+        for (newname, newvalue) in members:
+            found_in_old = False
+            for (oldname, oldvalue) in oldmembers:
+                if oldname == newname:
+                    found_in_old = True
+                    break
+            
+            if not found_in_old and not is_special_previous_build_attr(attname):
+                delattr(project, attname)
+        
+        # we'll have to remove the members on the old project but not
+        # on the new one
+        temporarily_add_attrs = []
         for (oldname, oldvalue) in oldmembers:
-            if oldname == newname:
-                found_in_old = True
-                break
+            found_in_new = False
+            for (newname, newvalue) in newmembers:
+                if newname == oldname:
+                    found_in_new = True
+                    break
+            
+            if not found_in_new and not is_special_previous_build_attr(attname):
+                temporarily_add_attrs += oldname
         
-        if not found_in_old and not is_special_previous_build_attr(attname):
-            delattr(project, attname)
+        # the "failed" member is a special case since we set it below
+        if not hasattr(project, "failed"):
+            temporarily_add_attrs += "failed"
+        
+        # remember...
+        project.delete_atts_when_stopping_to_use_previous_build = temporarily_add_attrs
     
-    # we'll have to remove the members on the old project but not
-    # on the new one
-    temporarily_add_attrs = []
-    for (oldname, oldvalue) in oldmembers:
-        found_in_new = False
-        for (newname, newvalue) in newmembers:
-            if newname == oldname:
-                found_in_new = True
-                break
-        
-        if not found_in_new and not is_special_previous_build_attr(attname):
-            temporarily_add_attrs += oldname
-    
-    # the "failed" member is a special case since we set it below
-    if not hasattr(project, "failed"):
-        temporarily_add_attrs += "failed"
-    
-    # remember...
-    project.delete_atts_when_stopping_to_use_previous_build = temporarily_add_attrs
-
-    # move all old project members to the new one
-    for (name, value) in oldmembers:
-        if is_special_previous_build_attr(name):
-            continue
-        setattr(project, name, value)
-        
-    # unmark failure as a sanity check (we checked for it above)
-    project.failed = False
-    
-    
-def stop_using_previous_build(project):
-    if not hasattr(project, "use_atts_when_stopping_to_use_previous_build"):
-        # use_previous_build() seemingly wasn't active on this build
-        return
-    
-    # these were the temporary ones
-    attlist = project.delete_atts_when_stopping_to_use_previous_build
-    for attname in attlist:
-        if is_special_previous_build_attr(name):
-            # safety. This won't happen if use_previous_build() is used
-            continue
-        delattr(project, attname)
-    
-    # these were the actual values
-    for (name,value) in project.use_atts_when_stopping_to_use_previous_build:
-        if is_special_previous_build_attr(name):
-            # safety. This won't happen if use_previous_build() is used
-            continue
-        setattr(project, name, value)
-    
-    # get rid of the remembered stuff
-    if hasattr(project, "delete_atts_when_stopping_to_use_previous_build"):
-        del project.delete_atts_when_stopping_to_use_previous_build
-    if hasattr(project, "use_atts_when_stopping_to_use_previous_build"):
-        del project.use_atts_when_stopping_to_use_previous_build
+        # move all old project members to the new one
+        for (name, value) in oldmembers:
+            if is_special_previous_build_attr(name):
+                continue
+            setattr(project, name, value)
+            
+        # unmark failure as a sanity check (we checked for it above)
+        project.failed = False
+        
+    def stop_using_previous_build(self, project):
+        if not hasattr(project, "use_atts_when_stopping_to_use_previous_build"):
+            # use_previous_build() seemingly wasn't active on this build
+            return
+        
+        # these were the temporary ones
+        attlist = project.delete_atts_when_stopping_to_use_previous_build
+        for attname in attlist:
+            if is_special_previous_build_attr(name):
+                # safety. This won't happen if use_previous_build() is used
+                continue
+            delattr(project, attname)
+        
+        # these were the actual values
+        for (name,value) in project.use_atts_when_stopping_to_use_previous_build:
+            if is_special_previous_build_attr(name):
+                # safety. This won't happen if use_previous_build() is used
+                continue
+            setattr(project, name, value)
+        
+        # get rid of the remembered stuff
+        if hasattr(project, "delete_atts_when_stopping_to_use_previous_build"):
+            del project.delete_atts_when_stopping_to_use_previous_build
+        if hasattr(project, "use_atts_when_stopping_to_use_previous_build"):
+            del project.use_atts_when_stopping_to_use_previous_build

Modified: gump/branches/Gump3/pygump/python/gump/model/util.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/gump/model/util.py?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/gump/model/util.py (original)
+++ gump/branches/Gump3/pygump/python/gump/model/util.py Sat Nov 12 03:53:47 2005
@@ -64,6 +64,14 @@
         model_element.failure_cause = []
     model_element.failure_cause.append(cause)
 
+def mark_stale_prereq(model_element, stale_prereq):
+    """Mark a project with "stale prereq"."""
+    assert isinstance(model_element, Project)
+    model_element.has_stale_prereqs = True
+    if not hasattr(model_element, "stale_prereqs"):
+        model_element.stale_prereqs = []
+    model_element.stale_prereqs.append(stale_prereq)
+
 def check_failure(model_element):
     """Determine whether a model element has "failed"."""
     assert isinstance(model_element, ModelObject)

Modified: gump/branches/Gump3/pygump/python/main.py
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/pygump/python/main.py?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/pygump/python/main.py (original)
+++ gump/branches/Gump3/pygump/python/main.py Sat Nov 12 03:53:47 2005
@@ -58,7 +58,7 @@
 def get_parser(_homedir=None, _hostname=None, _projects=None, _workdir=None,
                _logdir=None, _workspace=None, _databaseserver="localhost",
                _databaseport=3306, _databasename="gump", _databaseuser="gump",
-               _databasepassword=None):
+               _databasepassword=None, _persistencefile="gumpshelf"):
     """Pygump uses the optparse package to provide the CLI.
     
     To add new options to pygump, change this method and document the changes
@@ -156,6 +156,16 @@
                       dest="database_password",
                       default=_databasepassword,
                       help="password gump will use to connect to the database")
+    parser.add_option("--persistencefile",
+                      action="store",
+                      dest="persistence_file",
+                      default=_persistencefile,
+                      help="DBM file gump will use for persistence support")
+    parser.add_option("--enable-persistence",
+                      action="store_true",
+                      dest="enable_persistence",
+                      default=False, # Default to NOT. At least during initial development...
+                      help="enable ***experimental*** persistence support")
     parser.add_option("--color",
                       action="store_true",
                       dest="enable_colors",

Added: gump/branches/Gump3/webgump/INSTALL.txt
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/INSTALL.txt?rev=332761&view=auto
==============================================================================
--- gump/branches/Gump3/webgump/INSTALL.txt (added)
+++ gump/branches/Gump3/webgump/INSTALL.txt Sat Nov 12 03:53:47 2005
@@ -0,0 +1,17 @@
+In order to run webgump, you need to get and install
+
+  * Apache2
+  * mod_python
+
+into its directory tree. The following command might work
+if you're on unix:
+
+  cd $GUMP_HOME
+  ./gump webgump get-apache
+
+but its not really tested all that well, so be prepared to
+read the script
+
+  webgump/bin/get-apache
+
+and execute the equivalent steps manually. Good luck!

Propchange: gump/branches/Gump3/webgump/INSTALL.txt
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: gump/branches/Gump3/webgump/bin/get-apache
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/get-apache?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/webgump/bin/get-apache (original)
+++ gump/branches/Gump3/webgump/bin/get-apache Sat Nov 12 03:53:47 2005
@@ -1,16 +1,22 @@
 #!/bin/bash
 # simple script to setup apache
 
-# Where are we?
-if [[ -z "$GUMP_HOME" ]]; then
-  echo "ERROR: \$GUMP_HOME not set!"
+function bail {
+  echo "ERROR:" "$@"
   exit 1
-fi
+}
+
+function warn {
+  echo "ERROR:" "$@"
+}
+
+# Where are we?
+[[ -z "$GUMP_HOME" ]] && bail "\$GUMP_HOME not set!"
 
 ###
 ### Settings
 ###
-APACHE_VERSION=2.0.53
+APACHE_VERSION=2.0.54
 APACHE_INSTALL=$GUMP_HOME/webgump/lib/apache2-install
 
 ###
@@ -20,23 +26,23 @@
   mkdir $APACHE_INSTALL
   cd $APACHE_INSTALL
   if [[ ! -d "$APACHE_INSTALL/httpd-$APACHE_VERSION" ]]; then
-    wget http://apache.surfnet.nl/httpd/httpd-$APACHE_VERSION.tar.gz
-    tar zxf httpd-$APACHE_VERSION.tar.gz
+    wget http://apache.surfnet.nl/httpd/httpd-$APACHE_VERSION.tar.gz || bail "Downloading httpd-$APACHE_VERSION failed! maybe there is a new version? Change APACHE_VERSION in webgump/bin/get-apache as appropriate"
+    tar zxf httpd-$APACHE_VERSION.tar.gz || bail "Corrupt tarball?"
   fi
-  cd $APACHE_INSTALL/httpd-$APACHE_VERSION
-  ./configure --prefix=$APACHE_INSTALL/current --enable-mods-shared=most
-  make
-  make install
+  cd $APACHE_INSTALL/httpd-$APACHE_VERSION || bail
+  ./configure --prefix=$APACHE_INSTALL/current --enable-mods-shared=most || bail "Apache config failed!"
+  make || bail "Apache build failed!"
+  make install || bail "Apache build failed!"
 else
-  echo "WARNING appears apache is already installed at"
-  echo "WARNING   $APACHE_INSTALL/current"
-  echo "WARNING We won't attempt re-install"
+  warn "It appears apache is already installed at"
+  warn "   $APACHE_INSTALL/current"
+  warn "We won't attempt re-install"
 fi
 
 ###
 ### Install mod_python
 ###
-$GUMP_HOME/webgump/bin/get-mod-python
+$GUMP_HOME/webgump/bin/get-mod-python || bail "mod_python download failed!"
 
 ###
 ### Use our own config

Modified: gump/branches/Gump3/webgump/bin/settings
URL: http://svn.apache.org/viewcvs/gump/branches/Gump3/webgump/bin/settings?rev=332761&r1=332760&r2=332761&view=diff
==============================================================================
--- gump/branches/Gump3/webgump/bin/settings (original)
+++ gump/branches/Gump3/webgump/bin/settings Sat Nov 12 03:53:47 2005
@@ -2,6 +2,19 @@
   echo "ERROR: \$GUMP_HOME is not set!"
   exit 1
 fi
+
 APACHECTL=$GUMP_HOME/webgump/lib/apache2-install/current/bin/apachectl
+if [[ ! -f "$APACHECTL" ]]; then
+  echo "ERROR: Apache HTTPD not properly installed, see webgump/INSTALL.txt!"
+  exit 1
+fi
 APACHECMD=$GUMP_HOME/webgump/lib/apache2-install/current/bin/httpd
+if [[ ! -f "$APACHECMD" ]]; then
+  echo "ERROR: Apache HTTPD not properly installed, see webgump/INSTALL.txt!"
+  exit 1
+fi
 APACHECONF=$GUMP_HOME/webgump/conf/`hostname -s`.conf
+if [[ ! -f "$APACHECONF" ]]; then
+  echo "ERROR: You need to create the apache config file $APACHECONF, see webgump/INSTALL.txt!"
+  exit 1
+fi