]> git.saurik.com Git - wxWidgets.git/blobdiff - wxPython/distrib/mac/buildpkg.py
move wxPython to new trunk
[wxWidgets.git] / wxPython / distrib / mac / buildpkg.py
diff --git a/wxPython/distrib/mac/buildpkg.py b/wxPython/distrib/mac/buildpkg.py
deleted file mode 100644 (file)
index a9c70c1..0000000
+++ /dev/null
@@ -1,484 +0,0 @@
-#!/usr/bin/env python
-
-"""buildpkg.py -- Build OS X packages for Apple's Installer.app.
-
-This is an experimental command-line tool for building packages to be
-installed with the Mac OS X Installer.app application. 
-
-It is much inspired by Apple's GUI tool called PackageMaker.app, that 
-seems to be part of the OS X developer tools installed in the folder 
-/Developer/Applications. But apparently there are other free tools to 
-do the same thing which are also named PackageMaker like Brian Hill's 
-one: 
-
-  http://personalpages.tds.net/~brian_hill/packagemaker.html
-
-Beware of the multi-package features of Installer.app (which are not 
-yet supported here) that can potentially screw-up your installation 
-and are discussed in these articles on Stepwise:
-
-  http://www.stepwise.com/Articles/Technical/Packages/InstallerWoes.html
-  http://www.stepwise.com/Articles/Technical/Packages/InstallerOnX.html
-
-Beside using the PackageMaker class directly, by importing it inside 
-another module, say, there are additional ways of using this module:
-the top-level buildPackage() function provides a shortcut to the same 
-feature and is also called when using this module from the command-
-line.
-
-    ****************************************************************
-    NOTE: For now you should be able to run this even on a non-OS X 
-          system and get something similar to a package, but without
-          the real archive (needs pax) and bom files (needs mkbom) 
-          inside! This is only for providing a chance for testing to 
-          folks without OS X.
-    ****************************************************************
-
-TODO:
-  - test pre-process and post-process scripts (Python ones?)
-  - handle multi-volume packages (?)
-  - integrate into distutils (?)
-
-Dinu C. Gherman, 
-gherman@europemail.com
-November 2001
-
-!! USE AT YOUR OWN RISK !!
-"""
-
-__version__ = 0.2
-__license__ = "FreeBSD"
-
-
-import os, sys, glob, fnmatch, shutil, string, copy, getopt
-from os.path import basename, dirname, join, islink, isdir, isfile
-
-Error = "buildpkg.Error"
-
-PKG_INFO_FIELDS = """\
-Title
-Version
-Description
-DefaultLocation
-DeleteWarning
-NeedsAuthorization
-DisableStop
-UseUserMask
-Application
-Relocatable
-Required
-InstallOnly
-RequiresReboot
-RootVolumeOnly
-LongFilenames
-LibrarySubdirectory
-AllowBackRev
-OverwritePermissions
-InstallFat\
-"""
-
-######################################################################
-# Helpers
-######################################################################
-
-# Convenience class, as suggested by /F.
-
-class GlobDirectoryWalker:
-    "A forward iterator that traverses files in a directory tree."
-
-    def __init__(self, directory, pattern="*"):
-        self.stack = [directory]
-        self.pattern = pattern
-        self.files = []
-        self.index = 0
-
-
-    def __getitem__(self, index):
-        while 1:
-            try:
-                file = self.files[self.index]
-                self.index = self.index + 1
-            except IndexError:
-                # pop next directory from stack
-                self.directory = self.stack.pop()
-                self.files = os.listdir(self.directory)
-                self.index = 0
-            else:
-                # got a filename
-                fullname = join(self.directory, file)
-                if isdir(fullname) and not islink(fullname):
-                    self.stack.append(fullname)
-                if fnmatch.fnmatch(file, self.pattern):
-                    return fullname
-
-
-######################################################################
-# The real thing
-######################################################################
-
-class PackageMaker:
-    """A class to generate packages for Mac OS X.
-
-    This is intended to create OS X packages (with extension .pkg)
-    containing archives of arbitrary files that the Installer.app 
-    will be able to handle.
-
-    As of now, PackageMaker instances need to be created with the 
-    title, version and description of the package to be built. 
-    The package is built after calling the instance method 
-    build(root, **options). It has the same name as the constructor's 
-    title argument plus a '.pkg' extension and is located in the same 
-    parent folder that contains the root folder.
-
-    E.g. this will create a package folder /my/space/distutils.pkg/:
-
-      pm = PackageMaker("distutils", "1.0.2", "Python distutils.")
-      pm.build("/my/space/distutils")
-    """
-
-    packageInfoDefaults = {
-        'Title': None,
-        'Version': None,
-        'Description': '',
-        'DefaultLocation': '/',
-        'DeleteWarning': '',
-        'NeedsAuthorization': 'NO',
-        'DisableStop': 'NO',
-        'UseUserMask': 'YES',
-        'Application': 'NO',
-        'Relocatable': 'YES',
-        'Required': 'NO',
-        'InstallOnly': 'NO',
-        'RequiresReboot': 'NO',
-        'RootVolumeOnly' : 'NO',
-        'InstallFat': 'NO',
-        'LongFilenames': 'YES',
-        'LibrarySubdirectory': 'Standard',
-        'AllowBackRev': 'YES',
-        'OverwritePermissions': 'NO',
-        }
-
-
-    def __init__(self, title, version, desc):
-        "Init. with mandatory title/version/description arguments."
-
-        info = {"Title": title, "Version": version, "Description": desc}
-        self.packageInfo = copy.deepcopy(self.packageInfoDefaults)
-        self.packageInfo.update(info)
-        
-        # variables set later
-        self.packageRootFolder = None
-        self.packageResourceFolder = None
-        self.sourceFolder = None
-        self.resourceFolder = None
-
-
-    def build(self, root, resources=None, **options):
-        """Create a package for some given root folder.
-
-        With no 'resources' argument set it is assumed to be the same 
-        as the root directory. Option items replace the default ones 
-        in the package info.
-        """
-
-        # set folder attributes
-        self.sourceFolder = root
-        if resources == None:
-            self.resourceFolder = root
-        else:
-            self.resourceFolder = resources
-
-        # replace default option settings with user ones if provided
-        fields = self. packageInfoDefaults.keys()
-        for k, v in options.items():
-            if k in fields:
-                self.packageInfo[k] = v
-            elif not k in ["OutputDir"]:
-                raise Error, "Unknown package option: %s" % k
-        
-        # Check where we should leave the output. Default is current directory
-        outputdir = options.get("OutputDir", os.getcwd())
-        packageName = self.packageInfo["Title"]
-        self.PackageRootFolder = os.path.join(outputdir, packageName + ".pkg")
-        # do what needs to be done
-        self._makeFolders()
-        self._addInfo()
-        self._addBom()
-        self._addArchive()
-        self._addResources()
-        self._addSizes()
-        self._addLoc()
-
-
-    def _makeFolders(self):
-        "Create package folder structure."
-
-        # Not sure if the package name should contain the version or not...
-        # packageName = "%s-%s" % (self.packageInfo["Title"], 
-        #                          self.packageInfo["Version"]) # ??
-
-        contFolder = join(self.PackageRootFolder, "Contents")
-        self.packageResourceFolder = join(contFolder, "Resources")
-        os.mkdir(self.PackageRootFolder)
-        os.mkdir(contFolder)
-        os.mkdir(self.packageResourceFolder)
-
-    def _addInfo(self):
-        "Write .info file containing installing options."
-
-        # Not sure if options in PKG_INFO_FIELDS are complete...
-
-        info = ""
-        for f in string.split(PKG_INFO_FIELDS, "\n"):
-            if self.packageInfo.has_key(f):
-                info = info + "%s %%(%s)s\n" % (f, f)
-        info = info % self.packageInfo
-        base = self.packageInfo["Title"] + ".info"
-        path = join(self.packageResourceFolder, base)
-        f = open(path, "w")
-        f.write(info)
-
-
-    def _addBom(self):
-        "Write .bom file containing 'Bill of Materials'."
-
-        # Currently ignores if the 'mkbom' tool is not available.
-
-        try:
-            base = self.packageInfo["Title"] + ".bom"
-            bomPath = join(self.packageResourceFolder, base)
-            cmd = "mkbom %s %s" % (self.sourceFolder, bomPath)
-            res = os.system(cmd)
-        except:
-            pass
-
-
-    def _addArchive(self):
-        "Write .pax.gz file, a compressed archive using pax/gzip."
-
-        # Currently ignores if the 'pax' tool is not available.
-
-        cwd = os.getcwd()
-
-        # create archive
-        os.chdir(self.sourceFolder)
-        base = basename(self.packageInfo["Title"]) + ".pax"
-        self.archPath = join(self.packageResourceFolder, base)
-        cmd = "pax -w -f %s %s" % (self.archPath, ".")
-        res = os.system(cmd)
-        
-        # compress archive
-        cmd = "gzip %s" % self.archPath
-        res = os.system(cmd)
-        os.chdir(cwd)
-
-
-    def _addResources(self):
-        "Add Welcome/ReadMe/License files, .lproj folders and scripts."
-
-        # Currently we just copy everything that matches the allowed 
-        # filenames. So, it's left to Installer.app to deal with the 
-        # same file available in multiple formats...
-
-        if not self.resourceFolder:
-            return
-
-        # find candidate resource files (txt html rtf rtfd/ or lproj/)
-        allFiles = []
-        for pat in string.split("*.txt *.html *.rtf *.rtfd *.lproj", " "):
-            pattern = join(self.resourceFolder, pat)
-            allFiles = allFiles + glob.glob(pattern)
-
-        # find pre-process and post-process scripts
-        # naming convention: packageName.{pre,post}_{upgrade,install}
-        # Alternatively the filenames can be {pre,post}_{upgrade,install}
-        # in which case we prepend the package name
-        packageName = self.packageInfo["Title"]
-        for pat in ("*upgrade", "*install", "*flight"):
-            pattern = join(self.resourceFolder, packageName + pat)
-            pattern2 = join(self.resourceFolder, pat)
-            allFiles = allFiles + glob.glob(pattern)
-            allFiles = allFiles + glob.glob(pattern2)
-
-        # check name patterns
-        files = []
-        for f in allFiles:
-            for s in ("Welcome", "License", "ReadMe"):
-                if string.find(basename(f), s) == 0:
-                    files.append((f, f))
-            if f[-6:] == ".lproj":
-                files.append((f, f))
-            elif basename(f) in ["pre_upgrade", "pre_install", "post_upgrade", "post_install"]:
-                files.append((f, packageName+"."+basename(f)))
-            elif basename(f) in ["preflight", "postflight"]:
-                files.append((f, f))
-            elif f[-8:] == "_upgrade":
-                files.append((f,f))
-            elif f[-8:] == "_install":
-                files.append((f,f))
-
-        # copy files
-        for src, dst in files:
-            src = basename(src)
-            dst = basename(dst)
-            f = join(self.resourceFolder, src)
-            if isfile(f):
-                shutil.copy(f, os.path.join(self.packageResourceFolder, dst))
-            elif isdir(f):
-                # special case for .rtfd and .lproj folders...
-                d = join(self.packageResourceFolder, dst)
-                os.mkdir(d)
-                files = GlobDirectoryWalker(f)
-                for file in files:
-                    shutil.copy(file, d)
-
-
-    def _addSizes(self):
-        "Write .sizes file with info about number and size of files."
-
-        # Not sure if this is correct, but 'installedSize' and 
-        # 'zippedSize' are now in Bytes. Maybe blocks are needed? 
-        # Well, Installer.app doesn't seem to care anyway, saying 
-        # the installation needs 100+ MB...
-
-        numFiles = 0
-        installedSize = 0
-        zippedSize = 0
-
-        files = GlobDirectoryWalker(self.sourceFolder)
-        for f in files:
-            numFiles = numFiles + 1
-            installedSize = installedSize + os.lstat(f)[6]
-
-        try:
-            zippedSize = os.stat(self.archPath+ ".gz")[6]
-        except OSError: # ignore error 
-            pass
-        base = self.packageInfo["Title"] + ".sizes"
-        f = open(join(self.packageResourceFolder, base), "w")
-        format = "NumFiles %d\nInstalledSize %d\nCompressedSize %d\n"
-        f.write(format % (numFiles, installedSize, zippedSize))
-
-    def _addLoc(self):
-        "Write .loc file."
-        base = self.packageInfo["Title"] + ".loc"
-        f = open(join(self.packageResourceFolder, base), "w")
-        f.write('/')
-
-# Shortcut function interface
-
-def buildPackage(*args, **options):
-    "A Shortcut function for building a package."
-    
-    o = options
-    title, version, desc = o["Title"], o["Version"], o["Description"]
-    pm = PackageMaker(title, version, desc)
-    apply(pm.build, list(args), options)
-
-
-######################################################################
-# Tests
-######################################################################
-
-def test0():
-    "Vanilla test for the distutils distribution."
-
-    pm = PackageMaker("distutils2", "1.0.2", "Python distutils package.")
-    pm.build("/Users/dinu/Desktop/distutils2")
-
-
-def test1():
-    "Test for the reportlab distribution with modified options."
-
-    pm = PackageMaker("reportlab", "1.10", 
-                      "ReportLab's Open Source PDF toolkit.")
-    pm.build(root="/Users/dinu/Desktop/reportlab", 
-             DefaultLocation="/Applications/ReportLab",
-             Relocatable="YES")
-
-def test2():
-    "Shortcut test for the reportlab distribution with modified options."
-
-    buildPackage(
-        "/Users/dinu/Desktop/reportlab", 
-        Title="reportlab", 
-        Version="1.10", 
-        Description="ReportLab's Open Source PDF toolkit.",
-        DefaultLocation="/Applications/ReportLab",
-        Relocatable="YES")
-
-
-######################################################################
-# Command-line interface
-######################################################################
-
-def printUsage():
-    "Print usage message."
-
-    format = "Usage: %s <opts1> [<opts2>] <root> [<resources>]"
-    print format % basename(sys.argv[0])
-    print
-    print "       with arguments:"
-    print "           (mandatory) root:         the package root folder"
-    print "           (optional)  resources:    the package resources folder"
-    print
-    print "       and options:"
-    print "           (mandatory) opts1:"
-    mandatoryKeys = string.split("Title Version Description", " ")
-    for k in mandatoryKeys:
-        print "               --%s" % k
-    print "           (optional) opts2: (with default values)"
-
-    pmDefaults = PackageMaker.packageInfoDefaults
-    optionalKeys = pmDefaults.keys()
-    for k in mandatoryKeys:
-        optionalKeys.remove(k)
-    optionalKeys.sort()
-    maxKeyLen = max(map(len, optionalKeys))
-    for k in optionalKeys:
-        format = "               --%%s:%s %%s"
-        format = format % (" " * (maxKeyLen-len(k)))
-        print format % (k, repr(pmDefaults[k]))
-
-
-def main():
-    "Command-line interface."
-
-    shortOpts = ""
-    keys = PackageMaker.packageInfoDefaults.keys()
-    longOpts = map(lambda k: k+"=", keys)
-
-    try:
-        opts, args = getopt.getopt(sys.argv[1:], shortOpts, longOpts)
-    except getopt.GetoptError, details:
-        print details
-        printUsage()
-        return
-
-    optsDict = {}
-    for k, v in opts:
-        optsDict[k[2:]] = v
-
-    ok = optsDict.keys()
-    if not (1 <= len(args) <= 2):
-        print "No argument given!"
-    elif not ("Title" in ok and \
-              "Version" in ok and \
-              "Description" in ok):
-        print "Missing mandatory option!"
-    else:
-        apply(buildPackage, args, optsDict)
-        return
-
-    printUsage()
-
-    # sample use:
-    # buildpkg.py --Title=distutils \
-    #             --Version=1.0.2 \
-    #             --Description="Python distutils package." \
-    #             /Users/dinu/Desktop/distutils
-
-
-if __name__ == "__main__":
-    main()