You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ri...@apache.org on 2008/08/21 15:16:33 UTC

svn commit: r687742 - in /incubator/qpid/trunk/qpid/buildtools: ./ buildCreator/ buildCreator/build.config buildCreator/buildCreator.py buildCreator/qpid.build

Author: ritchiem
Date: Thu Aug 21 06:16:32 2008
New Revision: 687742

URL: http://svn.apache.org/viewvc?rev=687742&view=rev
Log:
QPID-1256 : Initial commit of build creator tool. Documentation to appear on Wiki. (http://cwiki.apache.org/confluence/display/qpid/Build+Creator)

Added:
    incubator/qpid/trunk/qpid/buildtools/
    incubator/qpid/trunk/qpid/buildtools/buildCreator/
    incubator/qpid/trunk/qpid/buildtools/buildCreator/build.config
    incubator/qpid/trunk/qpid/buildtools/buildCreator/buildCreator.py   (with props)
    incubator/qpid/trunk/qpid/buildtools/buildCreator/qpid.build

Added: incubator/qpid/trunk/qpid/buildtools/buildCreator/build.config
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/buildtools/buildCreator/build.config?rev=687742&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/buildtools/buildCreator/build.config (added)
+++ incubator/qpid/trunk/qpid/buildtools/buildCreator/build.config Thu Aug 21 06:16:32 2008
@@ -0,0 +1,37 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements.  See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership.  The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License.  You may obtain a copy of the License at
+ -
+ -   http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied.  See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<builder>
+    <environment>
+        <version>M4.0-beta</version>        
+    </environment>
+
+    <sources>
+        <source>
+            <name>qpid</name>
+            <type>svn</type>
+            <url>https://svn.eu.apache.org/repos/asf/incubator/qpid/trunk/qpid/</url>
+        </source>
+    </sources>
+    
+    <builds>
+        <include>qpid.build</include>
+    </builds>
+</builder>

Added: incubator/qpid/trunk/qpid/buildtools/buildCreator/buildCreator.py
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/buildtools/buildCreator/buildCreator.py?rev=687742&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/buildtools/buildCreator/buildCreator.py (added)
+++ incubator/qpid/trunk/qpid/buildtools/buildCreator/buildCreator.py Thu Aug 21 06:16:32 2008
@@ -0,0 +1,1317 @@
+#!/usr/bin/env python
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import os
+import re
+import datetime
+import urllib
+import sys
+import string
+
+from xml.dom import minidom
+from optparse import OptionParser
+
+if map(int, string.split(string.split(sys.version)[0], ".")) < [2, 4, 0]:
+    print ("subprocess is required for this tool and is not present in versions prior to 2.4.0")
+    try:
+        import subprocess
+    except ImportError:
+        print ("subprocess module not found please install it locally or upgrade your python version")
+        sys.exit(1)
+
+import subprocess
+from subprocess import Popen
+
+TOOL_NAME="buildCreator.py"
+
+#Default Build script
+DEFAULT_BUILD="build.config"
+
+# Path locations
+DEFAULT_ROOTDIR="builder"
+SOURCE_DIR="src"
+PATCH_DIR="patch"
+BUILD_DIR="build"
+RELEASE_DIR="release"
+
+# Command Binaries
+SVN='svn'
+SVN_BIN='/usr/bin/svn'
+HTTP='http'
+FTP='ftp'
+WGET_BIN='/usr/bin/wget'
+FILE='file'
+CP_BIN='/bin/cp'
+PATCH_BIN='/usr/bin/patch'
+FILE_BIN='/usr/bin/file'
+LS_BIN='/bin/ls'
+TAR_BIN='/bin/tar'
+BZIP2_BIN='/usr/bin/bzip2'
+UNZIP_BIN='/usr/bin/unzip'
+
+
+
+GZIP_DATA='gzip compressed data'
+BZIP2_DATA='bzip2 compressed data'
+ZIP_DATA='Zip archive data'
+TAR_DATA='POSIX tar archive'
+DIFF_FILE="'diff' output text"
+
+#Build Targets
+DISTCLEAN='distclean'
+CLEAN='clean'
+RETRIEVE='retrieve'
+PREPARE='prepare'
+PATCH='patch'
+SHOWBUILDS='showbuilds'
+BUILD='build'
+RELEASE='release'
+FULL='full'
+HELP='help'
+DEFAULT_TARGET=FULL
+
+# XML Elements toplevel
+BUILDER="builder"
+ENVIRONMENT="environment"
+SOURCES="sources"
+SOURCE="source"
+PATCHES="patches"
+PATCH="patch"
+BUILDS="builds"
+INCLUDE="include"
+DEPENDENCY='dependency'
+TARGETS='targets'
+SCRIPT='script'
+
+# XML Elements - Source/Patch elements
+NAME="name"
+TYPE="type"
+URL="url"
+REVISION="revision"
+ROOTDIR="root"
+VERSION="version"
+PREFIX='prefix'
+PATH='path'
+
+PATH_SEP=os.sep
+
+_source=None
+_target=DEFAULT_BUILD
+_rootDir = DEFAULT_ROOTDIR
+_log = True
+_verbose = False
+_debug = False
+_ignoreErrors = False
+                         
+_charIndex = 0
+_waitingChars = ['-', '/' , '|',  '\\']
+
+def showUsage():
+    print TOOL_NAME+" [-c|--configure <config file>] [-v| --verbose] [-q|--quiet] [-i|--ignore-errors] [<build target>] [options]"
+    print "Available Targets:"
+    print "     distclean [source] - Remove all or specified retrieved source"
+    print "     clean [source]     - Remove all or specified source build directory"
+    print "     retrieve [source]  - Retrieve all or specified source"
+    print "     prepare [source]   - Prepare all or specified source : i.e. extract archives"
+    print "     patch [source]     - Patch all or specified source"
+    print "     showbuilds         - List all builds"
+    print "     build [build]      - Perform the build scripts for all or specified build"
+    print "     release [build]    - Perform the release scripts for all or specified source"
+    print "     full               - Perfrom clean, retrieve, prepare,  patch, build, release for all builds (DEFAULT)"
+
+def main():
+    global _log, _verbose, _debug, _rootDir, _target, _source, _baseConfiguration, _ignoreErrors
+
+    # Load the
+    parser = OptionParser()
+    parser.add_option("-c", "--config", dest="config",
+                      action="store", default=DEFAULT_BUILD,
+                      help="set configuration file : default = " + DEFAULT_BUILD)
+
+    parser.add_option("-v", "--verbose", dest="verbose",
+                      action="store_true", default=False, help="enable verbose output")
+
+    parser.add_option("-d", "--debug", dest="debug",
+                      action="store_true", default=False, help="enable debug output")
+
+    parser.add_option("-q", "--quiet", dest="quiet",
+                      action="store_false", default=True, help="Enable quiet ouptut")
+
+    parser.add_option("-i", "--ignore-errors", dest="ignoreErrors",
+                      action="store_true", default=False, help="Ignore errors")
+
+
+    (options, args) = parser.parse_args()
+
+    _verbose = options.verbose
+    _debug = options.debug
+    _log = options.quiet
+    _ignoreErrors = options.ignoreErrors
+
+    log("Logging Enabled")
+    verbose("Verbose Output Enabled")
+    debug("Debug Enabled")
+
+    checkSystemRequirements()
+
+
+    if (len(args) > 2):
+        showUsage()
+        sys.exit(1)
+    else:
+        # NOTE : Would be good to be able to do builder.py clean build release
+        if (len(args) > 0 ):
+            # Override the default target
+            _target = checkTarget(args[0])
+            # limit the comand to just the specified source
+            if (len(args) > 1 ):
+                _source = args[1]
+            else:
+                _source = None
+        else:
+            _target = FULL
+
+
+    _baseConfiguration = loadBaseConfiguration(options.config)
+
+    debug ("Loading Environment")
+    prepareEnvironment(_baseConfiguration.getElementsByTagName(ENVIRONMENT)[0])
+
+    if _target == DISTCLEAN:
+        distclean()
+
+    if _target == CLEAN or _target == FULL:
+        clean()
+
+    if _target == RETRIEVE or _target == FULL:
+        try:
+            retrieve()
+        except KeyboardInterrupt:
+            log ("User Interrupted preparation")
+            sys.exit(0)
+
+    if _target == PREPARE or _target == FULL:
+        prepare()
+
+    if _target == PATCH or _target == FULL:
+        patch()
+
+    if _target == SHOWBUILDS:
+        showBuilds()
+
+    if _target == BUILD or _target == FULL:
+        build()
+
+    if _target == RELEASE or _target == FULL:
+        release()
+
+    log("Complete")
+
+def checkTarget(target):
+
+    if target == HELP:
+        showUsage()
+        sys.exit(0)                
+
+    if target == DISTCLEAN:
+        return DISTCLEAN
+
+    if target == CLEAN:
+        return CLEAN
+
+    if target == RETRIEVE:
+        return RETRIEVE
+
+    if target == PREPARE:
+        return PREPARE
+
+    if target == PATCH:
+        return PATCH
+
+    if target == SHOWBUILDS:
+        return SHOWBUILDS
+
+    if target == BUILD:
+        return BUILD
+
+    if target == RELEASE:
+        return RELEASE
+
+    if target == FULL:
+        return FULL
+
+    warn("Target: '"+target+"' not valid")
+    showUsage()
+    sys.exit(1)
+
+
+################################################################################
+#
+# Environment
+#
+################################################################################
+def prepareEnvironment(env):
+    global _rootDir
+
+    rootdir = env.getElementsByTagName(ROOTDIR)
+    if (rootdir.length > 0):
+        _rootDir = getValue(rootdir[0])
+    else:
+        verbose ("Using default build dir: "+DEFAULT_ROOTDIR)
+        _rootDir = DEFAULT_ROOTDIR
+
+    if _rootDir == "":
+        verbose (ROOTDIR+" value is empty. Please specify a value for "+ ROOTDIR)
+        doExit(0)
+
+    if (os.path.exists(_rootDir)):
+        verbose ("Using Existing root dir: "+_rootDir)
+    else:
+        mkdir(_rootDir)
+
+################################################################################
+#
+# Clean Methods
+#
+################################################################################
+def clean():
+    global _source
+    sources = getSourceList()
+
+    if len(sources) > 0:
+        log ("Removing built code...")
+        performed = False        
+        for source in sources:
+            if _source != None:
+                if getName(source) == _source:
+                    performed = True
+                    removeDir(source, BUILD_DIR)
+            else:
+                removeDir(source, BUILD_DIR)
+
+        if _source == None:
+            deleteDir(_rootDir + PATH_SEP + BUILD_DIR)
+
+    builds = getBuildList()
+    if len(builds) > 0:
+        log ("Removing built releases...")
+        for build in builds:
+            if _source != None:
+                if getName(build) == _source:
+                    performed = True
+                    removeDir(build, RELEASE_DIR)
+            else:
+                removeDir(build, RELEASE_DIR)
+        if _source == None:
+            deleteDir(_rootDir + PATH_SEP + RELEASE_DIR)
+
+    if _source != None:
+        if not performed:
+            fatal("No such source:" + _source);
+
+
+
+def distclean():
+    sources  = getSourceList()
+
+    if len(sources) > 0:
+        log ("Removing source...")
+        for source in sources:
+            if _source != None:
+                if getName(source) == _source:
+                    performed = True
+                    removeDir(source, SOURCE_DIR)
+            else:
+                removeDir(source, SOURCE_DIR)
+
+        if _source == None:
+            deleteDir(_rootDir + PATH_SEP + SOURCE_DIR)
+
+        log ("Removing built code...")
+        for source in sources:
+            if _source != None:
+                if getName(source) == _source:
+                    performed = True
+                    removeDir(source, BUILD_DIR)
+            else:
+                removeDir(source, BUILD_DIR)
+        if _source == None:
+            deleteDir(_rootDir + PATH_SEP + BUILD_DIR)
+
+    patches =getPatchList()
+    if len(patches) > 0:
+        log ("Removing patches...")
+        for patch in patches:
+            if _source != None:
+                if getName(patch) == _source:
+                    performed = True
+                    removeDir(patch, PATCH_DIR)
+            else:
+                removeDir(patch, PATCH_DIR)
+        if _source == None:
+            deleteDir(_rootDir + PATH_SEP + PATCH_DIR)
+
+
+    builds = getBuildList()
+    if len(builds) > 0:
+        log ("Removing built releases...")
+        for build in builds:
+            if _source != None:
+                if getName(build) == _source:
+                    performed = True
+                    removeDir(build, RELEASE_DIR)
+            else:
+                removeDir(build, RELEASE_DIR)
+        if _source == None:
+            deleteDir(_rootDir + PATH_SEP + RELEASE_DIR)
+
+
+    if _source == None:
+        deleteDir(_rootDir)
+
+    if _source != None:
+        if not performed:
+            fatal("No such source:" + _source);
+
+
+
+def removeDir(source, rootdir):
+    name = getName(source)
+    deleteDir(_rootDir + PATH_SEP + rootdir + PATH_SEP + name)
+
+################################################################################
+#
+# Retrieve Methods
+#
+################################################################################
+def retrieve():
+    global _source
+    sources  = getSourceList()
+
+    # Retreive Source
+    performed=False
+    if len(sources) > 0:
+        log ("Retrieving source...")
+
+        mkdir(_rootDir + PATH_SEP + SOURCE_DIR)
+
+        for source in sources:
+            if _source != None:
+                if getName(source) == _source:
+                    performed = True
+                    downloadSource(source, SOURCE_DIR)
+            else:
+                downloadSource(source, SOURCE_DIR)
+
+    # Retreive Patches
+    patches = getPatchList()
+    if len(patches) > 0:
+
+        log ("Retrieving patches...")
+
+        mkdir(_rootDir + PATH_SEP + PATCH_DIR)
+
+        for patch in patches:
+            if _source != None:
+                if getName(patch) == _source:
+                    performed = True
+                    downloadSource(patch, PATCH_DIR)
+            else:
+                downloadSource(patch, PATCH_DIR)
+
+    if _source != None:
+        if not performed:
+            fatal("No such patch:" + _source);
+
+
+################################################################################
+#
+# Prepare Methods
+#
+################################################################################
+
+def prepare():
+    verbose("Prepare")
+
+    mkdir(_rootDir + PATH_SEP + BUILD_DIR)
+
+    sources = getSourceList()
+    performed = False
+    if len(sources) > 0:
+        log ("Preparing source...")
+        for source in sources:
+            if _source != None:
+                if getName(source) == _source:
+                    log_no_newline("Preparing "+getName(source)+": ")
+                    performed = True
+                    postProcess(source, SOURCE_DIR)
+            else:
+                log_no_newline("Preparing "+getName(source)+": ")
+                postProcess(source, SOURCE_DIR)
+        if _source != None:
+            if not performed:
+                fatal("No such source:" + _source);
+
+    patches = getPatchList()
+    if len(patches) > 0:
+        log ("Preparing patches...")
+        for patch in patches:
+            if _source != None:
+                if getName(patch) == _source:
+                    performed = True
+                    log("Preparing "+getName(patch))
+                    postProcess(patch, PATCH_DIR)
+            else:
+                log("Preparing "+getName(patch))
+                postProcess(patch, PATCH_DIR)
+
+        if _source != None:
+            if not performed:
+                fatal("No such patch:" + _source);
+
+
+def postProcess(item, destination):
+    name = getName(item)
+    type = getValue(item.getElementsByTagName(TYPE)[0])
+
+    verbose("Post Processing:"+name)
+
+    targetdir = _rootDir + PATH_SEP + destination + PATH_SEP + name
+
+    builddir = _rootDir + PATH_SEP + BUILD_DIR + PATH_SEP + name
+
+
+    if type == SVN:
+       # Do we want to perform an export?
+
+       #extractcommand=SVN_BIN+" export "+ targetdir +" "+ builddir
+       # Use -v just now so we can show progress 
+       extractcommand=CP_BIN+" -rvf "+ targetdir +" "+ builddir
+
+       runCommand(extractcommand, False)
+
+    else:
+        if type == FILE or type == HTTP or type == FTP:
+
+            mkdir(builddir)
+
+            # Look at all the files and see if they need unpacks
+            for root, dirs, files in os.walk(targetdir, topdown=False):
+                for file in files:
+                    command = FILE_BIN+" "+root+PATH_SEP+file
+
+                    result = Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                                            stderr=subprocess.PIPE)
+                    line = result.stdout.readline()
+                    firstline=line
+                    while (line != "" ):
+                        # process nextline
+                        line=result.stdout.readline()
+
+                    result.wait()
+
+                    if result.returncode != 0:
+                        fatal("Download (" + name + ") contained unrecognized file type:"+ firstline)
+
+
+                    extractcommand=""
+
+                    if firstline.find(GZIP_DATA) != -1:
+                        extractcommand=TAR_BIN+" -vxzf "+root+PATH_SEP+file+" -C " + builddir
+
+                    if firstline.find(BZIP2_DATA) != -1:
+                        extractcommand=TAR_BIN+" -vxjf "+root+PATH_SEP+file+" -C " + builddir
+
+                    if firstline.find(ZIP_DATA) != -1:
+                       extractcommand=ZIP_BIN+" -v "+root+PATH_SEP+file+" -d "+ builddir
+
+                    if firstline.find(TAR_DATA) != -1:
+                       extractcommand=TAR_BIN+" -vxf "+root+PATH_SEP+file+" -C "+ builddir
+
+                    if firstline.find(DIFF_FILE) != -1:
+                       extractcommand=CP_BIN+" -r "+root+PATH_SEP+file+" "+ builddir
+
+
+
+                    if not extractcommand=="":
+                        log_no_newline("Extracting archive:" + file+": " )
+                        runCommand(extractcommand, False)
+                    else:
+                        fatal("Download (" + name + ") contained unsupported file type:"+ firstline)
+
+
+
+################################################################################
+#
+# Patch Methods
+#
+################################################################################
+def patch():
+
+    # Retreive Patches
+    patches= getPatchList()
+    if len(patches) > 0:
+        performed = False
+        for patch in patches:
+            if _source != None:
+                if getName(source) == _source:
+                    performed = True
+                    applyPatch(patch)
+            else:
+                applyPatch(patch)
+
+        if _source != None:
+            if not performed:
+                fatal("No such patch:" + _source);
+
+
+def applyPatch(patch):
+    global _rootDir
+
+    name = getName(patch)
+    type = getValue(patch.getElementsByTagName(TYPE)[0])
+    source = getValue(patch.getElementsByTagName(SOURCE)[0])
+    if (patch.getElementsByTagName(PREFIX).length > 0):
+        prefix = getValue(patch.getElementsByTagName(PREFIX)[0])
+    else:
+        prefix = None
+
+    if (patch.getElementsByTagName(PATH).length > 0):
+        path= getValue(patch.getElementsByTagName(PATH)[0])
+    else:
+        path = None
+
+
+    basecommand = PATCH_BIN
+
+    if prefix != None:
+        basecommand = basecommand + " -p "+prefix
+
+    basecommand = basecommand + " -d "+ _rootDir + PATH_SEP + BUILD_DIR + PATH_SEP + source + PATH_SEP
+
+    if path != None:
+        basecommand = basecommand + path
+
+    basecommand = basecommand + " < "
+
+    patchSource= _rootDir + PATH_SEP + PATCH_DIR + PATH_SEP + name
+
+    log("Patching " + source + ": ")
+    for root, dirs, files in os.walk(patchSource, topdown=False):
+        for patchName in files:
+                log("Applying patch:"+name)
+                runCommandShowError(basecommand + patchSource + PATH_SEP + patchName)
+
+
+################################################################################
+#
+# build Methods
+#
+################################################################################
+def showBuilds():
+    builds = getNamesfromBuildList(getBuildList())
+    if len(builds) > 0:
+        log("Available Builds:")
+        for build in builds:
+            log(" "+build)
+    else:
+        log("No builds available")
+
+#
+# Given a list of build elements extract the Name values and return as a list
+#
+def getNamesfromBuildList(list):
+    names=[]
+    for item in list:
+        name = getName(item)
+        if name != None:
+            names.append(name)
+    return names
+
+def build():
+    doBuildAction(BUILD)
+
+
+
+################################################################################
+#
+# Release Methods
+#
+################################################################################
+def release():
+    log ("Releasing...")
+    mkdir(_rootDir + PATH_SEP + RELEASE_DIR)
+
+    builds = getBuildList()
+
+    for build in builds:
+        if _source != None:
+            if getName(build) == _source:
+                mkdir(_rootDir + PATH_SEP + RELEASE_DIR + PATH_SEP + getName(build))
+        else:
+            mkdir(_rootDir + PATH_SEP + RELEASE_DIR + PATH_SEP + getName(build))
+                    
+    doBuildAction(RELEASE)
+
+
+
+################################################################################
+#
+# Build Helper Methods
+#
+################################################################################
+
+def doBuildAction(action):
+    config = _baseConfiguration
+
+    if len(getSourceList()) > 0:
+        log("Performing "+ action.title() +"...")
+
+        builds = getBuildList()
+
+        performed = False
+        for build in builds:
+            if _source != None:
+                if getName(build) == _source:
+                    performed = True
+                    performScript(build , action)
+            else:
+                performScript(build, action)
+
+        if _source != None:
+            if not performed:
+                fatal("No such build:" + _source);
+
+
+def performScript(build, scriptName):
+    name = getName(build)
+
+    checkDependencies(build)
+
+    verbose("Running "+scriptName+":"+name)
+
+    targets = build.getElementsByTagName(TARGETS)
+
+    if targets.length > 0:
+        target = targets[0].getElementsByTagName(scriptName)
+
+        if target.length > 1:
+            fatal("More than one build target specified")
+
+        if target.length == 0:
+            fatal("No build target specified")
+
+        script = getValue(target[0].getElementsByTagName(SCRIPT)[0])
+
+        script = peformSubstitutionsInScript(build, script)
+
+        runScript(script)
+
+    else:
+        fatal("Build "+name+" has no build targets")
+
+
+def checkDependencies(build):
+    name = getName(build)
+    dependencies = build.getElementsByTagName(DEPENDENCY)
+
+    if dependencies > 0:
+        for dependency in dependencies :
+            sources = dependency.getElementsByTagName(SOURCE)
+            if sources.length == 0:
+                fatal("No sources specified in dependency block for build:"+name)
+            else:
+                for source in sources:
+                    sourceDependency = getValue(source)
+                    if not (sourceDefined(sourceDependency)):
+                        fatal("Unable to build "+name+" as specifed dependency("+sourceDependency +") is not available")
+
+def sourceDefined(name):
+    for source in getSourceList():
+        sourcename = getValue(source.getElementsByTagName(NAME)[0])
+        if sourcename == name:
+            return True
+    return False
+
+
+def runScript(script):
+    (returncode, stdout, stderr) = runCommandWithOutput(script)
+
+    if returncode != 0:
+        for line in stdout:            
+                warn(line)
+        for line in stderr:            
+                warn(line)
+
+        warn("Script Failed")
+
+        doExit(1)
+        
+
+################################################################################
+#
+# XML Helper Methods
+#
+################################################################################
+
+def loadBaseConfiguration(config):
+    log ("Loading configuration:" + config)
+    full = minidom.parse(config)
+    return full.getElementsByTagName(BUILDER)[0]
+
+#
+# Assumes that we have a <node>text</node> element and returns the text value.
+#
+def getValue(node):
+    if node.childNodes.length > 0:
+        return node.childNodes[0].data
+    else:
+        return ""
+
+def getEnvironment():
+    env = _baseConfiguration.getElementsByTagName(ENVIRONMENT)
+    if env.length > 0:
+        return env[0]
+    else:
+        return None
+
+#
+# Returns the value of the NAME element contained in the specified item
+#
+def getName(item):
+    name = item.getElementsByTagName(NAME)
+    if name.length > 0:
+        return getValue(name[0])
+
+#
+# Return the list of sources in this build configuration
+# If no sources are available then this is logged as a fatal error.
+#
+def getSourceList():
+    config = _baseConfiguration
+    sourceCount = config.getElementsByTagName(SOURCES).length
+    if sourceCount > 0:
+        return config.getElementsByTagName(SOURCES)[0].getElementsByTagName(SOURCE)
+    else:
+        fatal("No source elements defined.")
+#
+# Return the list of patches in this build configuration
+#
+def getPatchList():
+    config = _baseConfiguration
+    patchCount = config.getElementsByTagName(PATCHES).length
+    if patchCount > 0:
+        return config.getElementsByTagName(PATCHES)[0].getElementsByTagName(PATCH)
+    else:
+        return []
+
+# Returns a list of build elements including any any included build files
+# Currently nested build elements are not supported so all builds must be specified via the <include> tag.
+#
+def getBuildList():
+    config = _baseConfiguration
+
+    builds = config.getElementsByTagName(BUILDS)
+    buildcount = builds.length
+
+    if buildcount > 0:
+        build = builds[0]
+        useInclude = build.getElementsByTagName(INCLUDE).length > 0
+
+        # If we are using includes then build a list of all the files we need to include
+        if useInclude:
+            return  getIncludeList(build)
+
+        else:
+           warn("Nested builds not currently supported")
+    else:
+        fatal("No Builds defined in config")        
+
+#
+# Look at all <include> values in the given element and return the list of inlcudes
+#
+def getIncludeList(build):
+    includelist=[]
+    for include in build.getElementsByTagName(INCLUDE):
+        for item in getIncludeValue(getValue(include)):
+            includelist.append(item)
+
+    return includelist
+
+#
+# Process in the given include value.
+# This is done by performing `ls <include>`
+# This means includes such as 'builds/*.config' will match multiple includes and return all entries
+#
+# Any error in performing the ls is printed and the tool exits (unless ignore errors)
+#
+def getIncludeValue(include):
+    debug("Loading Includes:"+include+" ")    
+
+    command = LS_BIN+" "+include
+    (returncode, stdout, stderr) = runCommandWithOutput(command)
+
+    if returncode == 0:
+        values=[]
+        for line in stdout:
+            include = loadIncludeFile(line)
+            if not include == None:
+                values.append(include)
+        return values
+    else:
+        for line in stderr:
+            warn(line)
+        doExit(1)
+
+#
+# Given a file name parse the XML. Any trailing '\n's that the ls command may have added are removed here.
+# The file is checked to ensure that it is a <builds> file
+# The first <build> element is returned.
+#
+#  TODO: Allow multiple builds per file.
+#
+def loadIncludeFile(file):
+     buildFile = minidom.parse(file.rstrip('\n'))
+
+     builds = buildFile.getElementsByTagName(BUILDS)
+
+     if builds.length != 1:
+        warn("Build Configuration does not contain any <"+BUILDS+"> definitions")
+     else:
+        buildElements = builds[0].getElementsByTagName(BUILD)
+        if not buildElements.length > 0:
+            warn("Build Configuration does not contain any <"+BUILD+"> definitions")
+        else:
+            if buildElements.length > 0:
+                build = buildElements[0]
+                # getElementsByTagName is recursive so this will pick up the sub element build
+                # Only use the first element
+                namecount = build.getElementsByTagName(NAME).length
+                if namecount > 0:
+                    return build
+                else:
+                    return None
+
+#
+# Given the build target and a script substitute $value entries in script for values in
+# the Environment
+# the Source entries <source><name>
+# the build <build><name>
+# the release location : _rootDir + PATH_SEP + RELEASE_DIR + PATH_SEP + buildName
+#
+def peformSubstitutionsInScript(build, script):
+    buildName = getName(build)
+    sources = getSourceList()
+
+    #Replace Build name
+    script = script.replace("$build", buildName)
+
+    #Replace release directory
+    releaseDir = _rootDir + PATH_SEP + RELEASE_DIR + PATH_SEP + buildName            
+    script = script.replace("$release", releaseDir)
+
+    # Replace Source varables
+    for source in sources:
+        sourceName = getName(source)
+
+        search = "$"+sourceName
+
+        sourcePath = source.getElementsByTagName(PATH)
+
+        replacement = _rootDir + PATH_SEP + BUILD_DIR + PATH_SEP + sourceName
+        if sourcePath.length > 0:
+            replacement = replacement + PATH_SEP + getValue(sourcePath[0])
+
+        script = script.replace(search,replacement)
+
+    # Take values from the environment script for replacement
+    env = getEnvironment()
+    if env != None:
+        for item in env.childNodes:
+            if item.nodeType == 1:
+
+                search = "$"+item.tagName
+                replace = item.childNodes[0].data
+
+                script = script.replace(search,replace)
+
+    # Validate we got them all
+    dollar =script.find("$")
+    if dollar != -1:
+        space = script.find(" ",dollar)
+        fatal("Unknown variable defined in script"+script[dollar:space])
+    
+    return script
+
+################################################################################
+#
+# Download Helper Methods
+#
+################################################################################
+
+#
+# Download the item specified in source to the given destintation
+#
+def downloadSource(source, destination):
+    name = getName(source)
+    type = getValue(source.getElementsByTagName(TYPE)[0])
+    url =  getValue(source.getElementsByTagName(URL)[0])
+    log ( "Retrieving "+ name + "("+ type +")")
+
+    targetdir=_rootDir + PATH_SEP + destination + PATH_SEP + name
+
+    command = ""
+
+    mkdir(targetdir)
+
+    if (os.listdir(targetdir)==[]):
+
+        # Setup command for a fresh checkout
+        if (type == SVN):
+            command = SVN_BIN+" co "+url+" "+targetdir
+            if (source.getElementsByTagName(REVISION).length > 0):
+                revision =  getValue(source.getElementsByTagName(REVISION)[0])
+                command = command+" -r"+revision
+        else:
+            if (type == HTTP):
+                command = WGET_BIN+" --no-directories -P "+targetdir+" "+url
+            else:
+                if (type == FILE):
+                    if url.startswith(HTTP):
+                        command = WGET_BIN+" -P "+targetdir+" "+url
+                    else:
+                        if url.startswith(FTP):
+                            command = WGET_BIN+" -P "+targetdir+" "+url
+                        else:
+                            command = CP_BIN+" "+url+" "+targetdir
+    else:
+        warn("Target directory(" + targetdir + ") is not empty please ensure contents are valid or run 'clean "+name+"'")
+
+    verbose("Executing:"+command)
+    log_no_newline("Retrieving "+source.nodeName+": ")
+
+    if (type == FILE):
+        runCommand(command, True)
+    else:
+        runCommand(command, False)
+
+################################################################################
+#
+# Command Helper Methods
+#
+################################################################################
+
+#
+# Run command and print out last 20 lines of data on error
+#
+def runCommandShowError(command):
+    last20 = runCommand(command, False)
+    if last20 != None:
+        lines=last20[0]
+        lines=lines + 1
+        current = 1
+        while current != lines:
+            log (last20[current])
+            current = current + 1
+        doExit(1)
+
+#
+# Runs the given command if showOutput is true then stdout/stderr is shown on screen
+# other wise the last 20 lines of output is gathered:
+#
+# As command runs progress is shown
+#
+# return array [0] = no of elements in array. Array is fixed size 21 elements but not all are used. FIXME: this is poor
+#
+# TODO: Current mechanism for limiting to 20 lines is poor, potential to replace usages of this
+#       method with runCommandWithOutput below
+#
+def runCommand(command, showOutput):
+    debug("Running Command:"+command)
+    try:
+        if showOutput:
+            # Process that shows the output
+            result = Popen(command, shell=True)
+        else:
+            # consume the output ourselves
+            result = Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+
+            index=0
+            last20=[""] * 21
+            line = result.stdout.readline()
+            while (line != "" ):
+                logWaiting()
+
+                #Record last 20 lines of output
+                index = index + 1
+                if index == 20:
+                    index = 1
+
+                last20[index]=line
+
+                # process nextline
+                line = result.stdout.readline()
+
+            #
+            # If we didn't get any standard or fill our buffers then fill the end of the buffer with any stderr
+            #
+            if index == 0 | index < 15 :
+                line = result.stderr.readline()
+
+                if index != 0:
+                    index = index + 1
+                    if line != "":
+                        last20[index]="STDERR"
+                reset = index
+                while (line != "" ):
+                    logWaiting()
+
+                    #Record last 20 lines of output
+                    index = index + 1
+                    if index == 20:
+                        index = reset
+
+                    last20[index]=line
+
+                    # process nextline
+                    line = result.stderr.readline()
+
+        result.wait()
+
+        if result.returncode == 0:
+            logWaitingDone()
+        else:
+            logWaitingFailed("Failed")
+            if not showOutput:
+                last20[0]=index
+                return last20
+
+        return None
+
+    except IOError:
+        logWaitingFailed ("Error running command.")
+        doExit(1)
+
+#
+# Runs the given command if showOutput is true then stdout/stderr is shown on screen
+# Stdout and stderr is gathered up and returned with error code.
+#
+# return (result.returncode, stdout, stderr)
+#
+# As command runs progress is shown
+#
+def runCommandWithOutput(command):
+
+    result = Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                                   stderr=subprocess.PIPE)
+
+
+    # Retrieve STDOUT
+    stdout=[]
+    line = result.stdout.readline()
+    while (line != "" ):
+        logWaiting()
+
+        stdout.append(line)
+
+        # process nextline
+        line = result.stdout.readline()
+
+    line = result.stderr.readline()
+
+    # Retrieve STDERR
+    stderr=[]
+    while (line != "" ):
+        stderr.append(line)
+
+        # process nextline
+        line = result.stderr.readline()
+
+    result.wait()
+
+    logWaitingClear()
+
+    return (result.returncode, stdout, stderr)
+
+
+################################################################################
+#
+# OS Helper Methods
+#
+################################################################################
+
+#
+# Check _ignoreErrors value and exit if false
+#
+def doExit(code):
+    if not _ignoreErrors:
+        sys.exit(code)
+
+#
+# Check that the required binaries are present for this tool.
+# Only checks the minimum set.
+# Logs warning if archive tools are missing
+#
+def checkSystemRequirements():
+    exists = checkExists(SVN_BIN)
+    exists = exists & checkExists(WGET_BIN)
+    exists = exists & checkExists(CP_BIN)
+    exists = exists & checkExists(PATCH_BIN)
+    exists = exists & checkExists(FILE_BIN)
+
+    if not checkExists(TAR_BIN):
+        warn("Unable to process tar files as tar binary does not exist:" + TAR_BIN)
+    if not checkExists(BZIP2_BIN):
+        warn("Unable to process bzip2 files as bzip2 binary does not exist:" + BZIP2_BIN)
+    if not checkExists(UNZIP_BIN):
+        warn("Unable to process zip files as unzip binary does not exist:" + UNZIP_BIN)
+
+    if not exists:
+        sys.exit(1)
+
+#
+# Helper that checks for files existence
+#
+def checkExists(command):
+    debug_no_newline("Checking for "+command+":")
+    command = LS_BIN+" "+command
+
+    result = Popen(command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE)
+    line = result.stdout.readline()
+
+    while (line != "" ):
+        # process nextline
+        line = result.stdout.readline()
+
+    result.wait()
+
+    if result.returncode == 0:
+        debug("OK")
+        return True
+    else:
+        debug("Missing")
+        warn("Missing dependancy:"+command)
+        return False
+
+
+# Delete everything reachable from the directory named in 'top',
+# assuming there are no symbolic links.
+#
+# If an attempt to delete '/' is  performed this is logged as a fatal error
+#
+def deleteDir(top):
+    if top == '/':
+        fatal("Exiting as attempt to delete '/' occured.")
+    else:
+        if (os.path.exists(top)):
+            log_no_newline("Removing:"+top+". ")
+            for root, dirs, files in os.walk(top, topdown=False):
+                logWaiting()
+                for name in files:
+                    os.remove(os.path.join(root, name))
+                for name in dirs:
+                    logWaiting()
+                    os.rmdir(os.path.join(root, name))
+
+            logWaiting()
+            os.rmdir(top)
+
+            logWaitingDone()
+
+def mkdir(dir):
+    if not os.path.exists(dir):
+        os.mkdir(dir)
+
+
+################################################################################
+#
+# Logging Helper Methods
+#
+################################################################################
+
+#
+# Provide a spinning -/|\
+#
+def logWaiting():
+    global _charIndex, _waitingChars
+
+    _charIndex = (_charIndex + 1) % len(_waitingChars)
+
+    log_no_newline('\b')
+    log_no_newline(_waitingChars[_charIndex])
+
+#
+# Clear the logWaiting symbol and end the line with ' Done'
+#
+def logWaitingDone():
+    log_no_newline('\b')
+    log(" Done")
+
+#
+# Clear the logWaiting symbol
+#
+def logWaitingClear():
+        log_no_newline('\b')
+
+#
+# Clear the logWaiting symbol and end line with messsage
+#
+def logWaitingFailed(message):
+    log_no_newline('\b')
+    log(" "+message)
+
+def debug(string):
+    if _debug:
+        log(string)
+
+def verbose(string):
+    if _verbose:
+        log(string)
+
+def log (string):
+    if _log:
+        print string
+
+def warn (string):
+    print string
+
+def fatal(string):
+    print string
+    doExit(1)
+
+def log_no_newline (string):
+    if _log:
+        sys.stdout.write(string)
+        sys.stdout.flush()
+
+def verbose_no_newline (string):
+    if _verbose:
+        sys.stdout.write(string)
+        sys.stdout.flush()
+
+def debug_no_newline (string):
+    if _debug:
+        sys.stdout.write(string)
+        sys.stdout.flush()
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file

Propchange: incubator/qpid/trunk/qpid/buildtools/buildCreator/buildCreator.py
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/qpid/trunk/qpid/buildtools/buildCreator/qpid.build
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/buildtools/buildCreator/qpid.build?rev=687742&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/buildtools/buildCreator/qpid.build (added)
+++ incubator/qpid/trunk/qpid/buildtools/buildCreator/qpid.build Thu Aug 21 06:16:32 2008
@@ -0,0 +1,55 @@
+<!--
+ -
+ - Licensed to the Apache Software Foundation (ASF) under one
+ - or more contributor license agreements.  See the NOTICE file
+ - distributed with this work for additional information
+ - regarding copyright ownership.  The ASF licenses this file
+ - to you under the Apache License, Version 2.0 (the
+ - "License"); you may not use this file except in compliance
+ - with the License.  You may obtain a copy of the License at
+ -
+ -   http://www.apache.org/licenses/LICENSE-2.0
+ -
+ - Unless required by applicable law or agreed to in writing,
+ - software distributed under the License is distributed on an
+ - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ - KIND, either express or implied.  See the License for the
+ - specific language governing permissions and limitations
+ - under the License.
+ -
+ -->
+<builds>
+    <build>
+        <name>qpid-build</name>
+        
+        <dependency>
+            <source>qpid</source>
+        </dependency>
+
+        <targets>
+            <build>
+                <script><![CDATA[
+                
+pushd $qpid/java
+ant -Dproject.version=$version build
+
+]]>
+                </script>
+            </build>
+
+            <release>
+                <script><![CDATA[
+# Create build package
+mkdir -p $release/$build-$version
+cp -r $qpid/java/build/* $release/$build-$version
+
+# Build release artifact
+cd $release
+tar cvzf $build-$version.tgz $build-$version
+]]>
+                </script>
+            </release>
+        </targets>
+
+    </build>
+</builds>