summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc-André Lemburg <mal@egenix.com>2002-04-17 20:30:10 (GMT)
committerMarc-André Lemburg <mal@egenix.com>2002-04-17 20:30:10 (GMT)
commit0538f1f2c7171ceb0940fd3865172ad164d2005e (patch)
tree31d7a834f2f7a0f001956b4a0655727d6c09e643
parentb02ea65f92f7e0c04689f469d436ba35dc2f631f (diff)
downloadcpython-0538f1f2c7171ceb0940fd3865172ad164d2005e.zip
cpython-0538f1f2c7171ceb0940fd3865172ad164d2005e.tar.gz
cpython-0538f1f2c7171ceb0940fd3865172ad164d2005e.tar.bz2
Patch #531901 by Mark W. Alexander: adds a new distutils packager
base class (in bdist_packager) and two subclasses which make use of this base class: bdist_pkgtool (for Solaris) and bdist_sdux (for HP-UX).
-rw-r--r--Lib/distutils/command/__init__.py5
-rw-r--r--Lib/distutils/command/bdist.py11
-rw-r--r--Lib/distutils/command/bdist_packager.py250
-rw-r--r--Lib/distutils/command/bdist_pkgtool.py412
-rw-r--r--Lib/distutils/command/bdist_sdux.py302
5 files changed, 976 insertions, 4 deletions
diff --git a/Lib/distutils/command/__init__.py b/Lib/distutils/command/__init__.py
index ef8e9ad..8143627 100644
--- a/Lib/distutils/command/__init__.py
+++ b/Lib/distutils/command/__init__.py
@@ -21,4 +21,9 @@ __all__ = ['build',
'bdist_dumb',
'bdist_rpm',
'bdist_wininst',
+ 'bdist_sdux',
+ 'bdist_pkgtool',
+ # Note:
+ # bdist_packager is not included because it only provides
+ # an abstract base class
]
diff --git a/Lib/distutils/command/bdist.py b/Lib/distutils/command/bdist.py
index 99f7d95..f61611e 100644
--- a/Lib/distutils/command/bdist.py
+++ b/Lib/distutils/command/bdist.py
@@ -52,7 +52,7 @@ class bdist (Command):
]
# The following commands do not take a format option from bdist
- no_format_option = ('bdist_rpm',)
+ no_format_option = ('bdist_rpm', 'bdist_sdux', 'bdist_pkgtool')
# This won't do in reality: will need to distinguish RPM-ish Linux,
# Debian-ish Linux, Solaris, FreeBSD, ..., Windows, Mac OS.
@@ -62,18 +62,21 @@ class bdist (Command):
# Establish the preferred order (for the --help-formats option).
format_commands = ['rpm', 'gztar', 'bztar', 'ztar', 'tar',
- 'wininst', 'zip']
+ 'wininst', 'zip', 'pkgtool', 'sdux']
# And the real information.
format_command = { 'rpm': ('bdist_rpm', "RPM distribution"),
- 'gztar': ('bdist_dumb', "gzip'ed tar file"),
+ 'zip': ('bdist_dumb', "ZIP file"), 'gztar': ('bdist_dumb', "gzip'ed tar file"),
'bztar': ('bdist_dumb', "bzip2'ed tar file"),
'ztar': ('bdist_dumb', "compressed tar file"),
'tar': ('bdist_dumb', "tar file"),
'wininst': ('bdist_wininst',
"Windows executable installer"),
'zip': ('bdist_dumb', "ZIP file"),
- }
+ 'pkgtool': ('bdist_pkgtool',
+ "Solaris pkgtool distribution"),
+ 'sdux': ('bdist_sdux', "HP-UX swinstall depot"),
+ }
def initialize_options (self):
diff --git a/Lib/distutils/command/bdist_packager.py b/Lib/distutils/command/bdist_packager.py
new file mode 100644
index 0000000..a812307
--- /dev/null
+++ b/Lib/distutils/command/bdist_packager.py
@@ -0,0 +1,250 @@
+"""distutils.command.bdist_ packager
+
+Modified from bdist_dumb by Mark W. Alexander <slash@dotnetslash.net>
+
+Implements the Distutils 'bdist_packager' abstract command
+to be subclassed by binary package creation commands."""
+
+
+__revision__ = "$Id: bdist_packager.py,v 0.1 2001/04/4 mwa"
+
+import os
+from distutils.core import Command
+from distutils.util import get_platform
+from distutils.dir_util import create_tree, remove_tree
+from distutils.file_util import write_file
+from distutils.errors import *
+import string, sys
+
+class bdist_packager (Command):
+
+ description = "abstract base for package manager specific bdist commands"
+
+# XXX update user_options
+ user_options = [
+ ('bdist-base=', None,
+ "base directory for creating built distributions"),
+ ('pkg-dir=', None,
+ "base directory for creating binary packages (defaults to \"binary\" under "),
+ ('dist-dir=', 'd',
+ "directory to put final RPM files in "
+ "(and .spec files if --spec-only)"),
+ ('category=', None,
+ "Software category (packager dependent format)"),
+ ('revision=', None,
+ "package revision number"),
+ # the following have moved into the distribution class
+ #('packager=', None,
+ #"Package maintainer"),
+ #('packager-mail=', None,
+ #"Package maintainer's email address"),
+ #('author=', None,
+ #"Package author"),
+ #('author-mail=', None,
+ #"Package author's email address"),
+ #('license=', None,
+ #"License code"),
+ #('licence=', None,
+ #"alias for license"),
+ ('icon=', None,
+ "Package icon"),
+ ('subpackages=', None,
+ "Comma seperated list of seperately packaged trees"),
+ ('preinstall=', None,
+ "preinstall script (Bourne shell code)"),
+ ('postinstall=', None,
+ "postinstall script (Bourne shell code)"),
+ ('preremove=', None,
+ "preremove script (Bourne shell code)"),
+ ('postremove=', None,
+ "postremove script (Bourne shell code)"),
+ ('requires=', None,
+ "capabilities required by this package"),
+ ('keep-temp', 'k',
+ "don't clean up RPM build directory"),
+ ('control-only', None,
+ "Generate package control files and stop"),
+ ('no-autorelocate', None,
+ "Inhibit automatic relocation to installed site-packages"),
+ ]
+
+ boolean_options = ['keep-temp', 'control-only', 'no_autorelocate']
+
+ def ensure_string_not_none (self,option,default=None):
+ val = getattr(self,option)
+ if val is not None:
+ return
+ Command.ensure_string(self,option,default)
+ val = getattr(self,option)
+ if val is None:
+ raise DistutilsOptionError, "'%s' must be provided" % option
+
+ def ensure_script (self,arg):
+ if not arg:
+ return
+ try:
+ self.ensure_string(arg, None)
+ except:
+ try:
+ self.ensure_filename(arg, None)
+ except:
+ raise RuntimeError, \
+ "cannot decipher script option (%s)" \
+ % arg
+
+ def write_script (self,path,attr,default=None):
+ """ write the script specified in attr to path. if attr is None,
+ write use default instead """
+ val = getattr(self,attr)
+ if not val:
+ if not default:
+ return
+ else:
+ setattr(self,attr,default)
+ val = default
+ if val!="":
+ self.announce('Creating %s script', attr)
+ self.execute(write_file,
+ (path, self.get_script(attr)),
+ "writing '%s'" % path)
+
+ def get_binary_name(self):
+ py_ver = sys.version[0:string.find(sys.version,' ')]
+ return self.name + '-' + self.version + '-' + \
+ self.revision + '-' + py_ver
+
+ def get_script (self,attr):
+ # accept a script as a string ("line\012line\012..."),
+ # a filename, or a list
+ # XXX We could probably get away with copy_file, but I'm
+ # guessing this will be more flexible later on....
+ val = getattr(self,attr)
+ ret=None
+ if val:
+ try:
+ os.stat(val)
+ # script is a file
+ ret=[]
+ f=open(val)
+ ret=string.split(f.read(),"\012");
+ f.close()
+ #return ret
+ except:
+ if type(val)==type(""):
+ # script is a string
+ ret = string.split(val,"\012")
+ elif type(val)==type([]):
+ # script is a list
+ ret = val
+ else:
+ raise RuntimeError, \
+ "cannot figure out what to do with 'request' option (%s)" \
+ % val
+ return ret
+
+
+ def initialize_options (self):
+ d = self.distribution
+ self.keep_temp = 0
+ self.control_only = 0
+ self.no_autorelocate = 0
+ self.pkg_dir = None
+ self.plat_name = None
+ self.icon = None
+ self.requires = None
+ self.subpackages = None
+ self.category = None
+ self.revision = None
+
+ # PEP 241 Metadata
+ self.name = None
+ self.version = None
+ #self.url = None
+ #self.author = None
+ #self.author_email = None
+ #self.maintainer = None
+ #self.maintainer_email = None
+ #self.description = None
+ #self.long_description = None
+ #self.licence = None
+ #self.platforms = None
+ #self.keywords = None
+ self.root_package = None
+
+ # package installation scripts
+ self.preinstall = None
+ self.postinstall = None
+ self.preremove = None
+ self.postremove = None
+ # initialize_options()
+
+
+ def finalize_options (self):
+
+ if self.pkg_dir is None:
+ bdist_base = self.get_finalized_command('bdist').bdist_base
+ self.pkg_dir = os.path.join(bdist_base, 'binary')
+
+ if not self.plat_name:
+ d = self.distribution
+ self.plat = d.get_platforms()
+ if self.distribution.has_ext_modules():
+ self.plat_name = [sys.platform,]
+ else:
+ self.plat_name = ["noarch",]
+
+ d = self.distribution
+ self.ensure_string_not_none('name', d.get_name())
+ self.ensure_string_not_none('version', d.get_version())
+ self.ensure_string('category')
+ self.ensure_string('revision',"1")
+ #self.ensure_string('url',d.get_url())
+ if type(self.distribution.packages) == type([]):
+ self.root_package=self.distribution.packages[0]
+ else:
+ self.root_package=self.name
+ self.ensure_string('root_package',self.root_package)
+ #self.ensure_string_list('keywords')
+ #self.ensure_string_not_none('author', d.get_author())
+ #self.ensure_string_not_none('author_email', d.get_author_email())
+ self.ensure_filename('icon')
+ #self.ensure_string_not_none('maintainer', d.get_maintainer())
+ #self.ensure_string_not_none('maintainer_email',
+ #d.get_maintainer_email())
+ #self.ensure_string_not_none('description', d.get_description())
+ #self.ensure_string_not_none('long_description', d.get_long_description())
+ #if self.long_description=='UNKNOWN':
+ #self.long_description=self.description
+ #self.ensure_string_not_none('license', d.get_license())
+ self.ensure_string_list('requires')
+ self.ensure_filename('preinstall')
+ self.ensure_filename('postinstall')
+ self.ensure_filename('preremove')
+ self.ensure_filename('postremove')
+
+ # finalize_options()
+
+
+ def run (self):
+
+ raise RuntimeError, \
+ "abstract method -- subclass %s must override" % self.__class__
+ self.run_command('build')
+
+ install = self.reinitialize_command('install', reinit_subcommands=1)
+ install.root = self.pkg_dir
+
+ self.announce("installing to %s" % self.pkg_dir)
+ self.run_command('install')
+
+ # And make an archive relative to the root of the
+ # pseudo-installation tree.
+ archive_basename = "%s.%s" % (self.distribution.get_fullname(),
+ self.plat_name)
+
+ if not self.keep_temp:
+ remove_tree(self.pkg_dir, self.verbose, self.dry_run)
+
+ # run()
+
+# class bdist_packager
diff --git a/Lib/distutils/command/bdist_pkgtool.py b/Lib/distutils/command/bdist_pkgtool.py
new file mode 100644
index 0000000..fc035eb
--- /dev/null
+++ b/Lib/distutils/command/bdist_pkgtool.py
@@ -0,0 +1,412 @@
+"""distutils.command.bdist_pkgtool
+
+
+Author: Mark W. Alexander <slash@dotnet.net>
+
+Implements the Distutils 'bdist_pkgtool' command (create Solaris pkgtool
+distributions)."""
+
+import os, string, sys, pwd, grp
+import glob
+from types import *
+from distutils.core import Command, DEBUG
+from distutils.util import get_platform
+from distutils.file_util import write_file
+from distutils.errors import *
+from distutils.command import bdist_packager
+from distutils import sysconfig
+import compileall
+from commands import getoutput
+
+__revision__ = "$Id: bdist_pkgtool.py,v 0.3 mwa "
+
+# default request script - Is also wrapped around user's request script
+# unless --no-autorelocate is requested. Finds the python site-packages
+# directory and prompts for verification
+DEFAULT_REQUEST="""#!/bin/sh
+######################################################################
+# Distutils internal package relocation support #
+######################################################################
+
+PRODUCT="__DISTUTILS_NAME__"
+
+trap `exit 3` 15
+/usr/bin/which python 2>&1 >/dev/null
+if [ $? -ne 0 ]; then
+ echo "The python interpretor needs to be on your path!"
+ echo
+ echo "If you have more than one, make sure the first one is where"
+ echo "you want this module installed:"
+ exit 1
+fi
+
+PY_DIR=`python -c "import sys;print '%s/lib/python%s' % (sys.exec_prefix,sys.version[0:3])" 2>/dev/null`
+PY_PKG_DIR=`python -c "import sys;print '%s/lib/python%s/site-packages' % (sys.exec_prefix,sys.version[0:3])" 2>/dev/null`
+
+echo ""
+if [ -z "${PY_DIR}" ]; then
+ echo "I can't seem to find the python distribution."
+ echo "I'm assuming the default path for site-packages"
+else
+ BASEDIR="${PY_PKG_DIR}"
+ cat <<EOF
+ Python found! The default path:
+
+ ${BASEDIR}
+
+ will install ${PRODUCT} such that all python users
+ can import it.
+
+ If you just want individual access, you can install into
+ any directory and add that directory to your \$PYTHONPATH
+EOF
+fi
+echo ""
+
+BASEDIR=`ckpath -d ${BASEDIR} -ay \
+ -p "Where should ${PRODUCT} be installed? [${BASEDIR}]"` || exit $?
+
+######################################################################
+# user supplied request script follows #
+######################################################################
+"""
+### request script
+
+# default postinstall compiles and changes ownership on the module directory
+# XXX The ownership change _should_ be handled by adjusting the prototype file
+DEFAULT_POSTINSTALL="""#!/bin/sh
+/usr/bin/test -d ${BASEDIR}/__DISTUTILS_NAME__
+if [ $? -eq 0 ]; then
+ python -c "import compileall;compileall.compile_dir(\\"${BASEDIR}/__DISTUTILS_NAME__\\")"
+ chown -R root:other ${BASEDIR}/__DISTUTILS_NAME__
+fi
+"""
+
+# default preremove deletes *.pyc and *.pyo from the module tree
+# This should leave the tree empty, so pkgtool will remove it.
+# If the user's scripts place anything else in there (e.g. config files),
+# pkgtool will leave the directory intact
+DEFAULT_PREREMOVE="""#!/bin/sh
+
+/usr/bin/which python 2>&1 >/dev/null
+if [ $? -ne 0 ]; then
+ echo "The python interpretor needs to be on your path!"
+ echo
+ echo "If you have more than one, make sure the first one is where"
+ echo "you want this module removed from"
+ exit 1
+fi
+
+/usr/bin/test -d ${BASEDIR}/__DISTUTILS_NAME__
+if [ $? -eq 0 ]; then
+ find ${BASEDIR}/__DISTUTILS_NAME__ -name "*.pyc" -exec rm {} \;
+ find ${BASEDIR}/__DISTUTILS_NAME__ -name "*.pyo" -exec rm {} \;
+fi
+"""
+
+# default postremove removes the module directory _IF_ no files are
+# there (Turns out this isn't needed if the preremove does it's job
+# Left for posterity
+DEFAULT_POSTREMOVE="""#!/bin/sh
+
+/usr/bin/test -d ${BASEDIR}/__DISTUTILS_NAME__
+if [ $? -eq 0 ]; then
+ if [ `find ${BASEDIR}/__DISTUTILS_NAME__ ! -type d | wc -l` -eq 0 ]; then
+ rm -rf ${BASEDIR}/__DISTUTILS_NAME__
+ fi
+fi
+"""
+
+class bdist_pkgtool (bdist_packager.bdist_packager):
+
+ description = "create an pkgtool (Solaris) package"
+
+ user_options = bdist_packager.bdist_packager.user_options + [
+ ('revision=', None,
+ "package revision number (PSTAMP)"),
+ ('pkg-abrev=', None,
+ "Abbreviation (9 characters or less) of the package name"),
+ ('compver=', None,
+ "file containing compatible versions of this package (man compver)"),
+ ('depend=', None,
+ "file containing dependencies for this package (man depend)"),
+ #('category=', None,
+ #"Software category"),
+ ('request=', None,
+ "request script (Bourne shell code)"),
+ ]
+
+ def initialize_options (self):
+ # XXX Check for pkgtools on path...
+ bdist_packager.bdist_packager.initialize_options(self)
+ self.compver = None
+ self.depend = None
+ self.vendor = None
+ self.classes = None
+ self.request = None
+ self.pkg_abrev = None
+ self.revision = None
+ # I'm not sure I should need to do this, but the setup.cfg
+ # settings weren't showing up....
+ options = self.distribution.get_option_dict('bdist_packager')
+ for key in options.keys():
+ setattr(self,key,options[key][1])
+
+ # initialize_options()
+
+
+ def finalize_options (self):
+ global DEFAULT_REQUEST, DEFAULT_POSTINSTALL
+ global DEFAULT_PREREMOVE, DEFAULT_POSTREMOVE
+ if self.pkg_dir is None:
+ dist_dir = self.get_finalized_command('bdist').dist_dir
+ self.pkg_dir = os.path.join(dist_dir, "pkgtool")
+
+ self.ensure_string('classes', None)
+ self.ensure_string('revision', "1")
+ self.ensure_script('request')
+ self.ensure_script('preinstall')
+ self.ensure_script('postinstall')
+ self.ensure_script('preremove')
+ self.ensure_script('postremove')
+ self.ensure_string('vendor', None)
+ if self.__dict__.has_key('author'):
+ if self.__dict__.has_key('author_email'):
+ self.ensure_string('vendor',
+ "%s <%s>" % (self.author,
+ self.author_email))
+ else:
+ self.ensure_string('vendor',
+ "%s" % (self.author))
+ self.ensure_string('category', "System,application")
+ self.ensure_script('compver')
+ self.ensure_script('depend')
+ bdist_packager.bdist_packager.finalize_options(self)
+ if self.pkg_abrev is None:
+ self.pkg_abrev=self.name
+ if len(self.pkg_abrev)>9:
+ raise DistutilsOptionError, \
+ "pkg-abrev (%s) must be less than 9 characters" % self.pkg_abrev
+ # Update default scripts with our metadata name
+ DEFAULT_REQUEST = string.replace(DEFAULT_REQUEST,
+ "__DISTUTILS_NAME__", self.root_package)
+ DEFAULT_POSTINSTALL = string.replace(DEFAULT_POSTINSTALL,
+ "__DISTUTILS_NAME__", self.root_package)
+ DEFAULT_PREREMOVE = string.replace(DEFAULT_PREREMOVE,
+ "__DISTUTILS_NAME__", self.root_package)
+ DEFAULT_POSTREMOVE = string.replace(DEFAULT_POSTREMOVE,
+ "__DISTUTILS_NAME__", self.root_package)
+
+ # finalize_options()
+
+
+ def make_package(self,root=None):
+ # make directories
+ self.mkpath(self.pkg_dir)
+ if root:
+ pkg_dir = self.pkg_dir+"/"+root
+ self.mkpath(pkg_dir)
+ else:
+ pkg_dir = self.pkg_dir
+
+ install = self.reinitialize_command('install', reinit_subcommands=1)
+ # build package
+ self.announce('Building package')
+ self.run_command('build')
+ self.announce('Creating pkginfo file')
+ path = os.path.join(pkg_dir, "pkginfo")
+ self.execute(write_file,
+ (path,
+ self._make_info_file()),
+ "writing '%s'" % path)
+ # request script handling
+ if self.request==None:
+ self.request = self._make_request_script()
+ if self.request!="":
+ path = os.path.join(pkg_dir, "request")
+ self.execute(write_file,
+ (path,
+ self.request),
+ "writing '%s'" % path)
+
+ # Create installation scripts, since compver & depend are
+ # user created files, they work just fine as scripts
+ self.write_script(os.path.join(pkg_dir, "postinstall"),
+ 'postinstall',DEFAULT_POSTINSTALL)
+ self.write_script(os.path.join(pkg_dir, "preinstall"),
+ 'preinstall',None)
+ self.write_script(os.path.join(pkg_dir, "preremove"),
+ 'preremove',DEFAULT_PREREMOVE)
+ self.write_script(os.path.join(pkg_dir, "postremove"),
+ 'postremove',None)
+ self.write_script(os.path.join(pkg_dir, "compver"),
+ 'compver',None)
+ self.write_script(os.path.join(pkg_dir, "depend"),
+ 'depend',None)
+
+ self.announce('Creating prototype file')
+ path = os.path.join(pkg_dir, "prototype")
+ self.execute(write_file,
+ (path,
+ self._make_prototype()),
+ "writing '%s'" % path)
+
+
+ if self.control_only: # stop if requested
+ return
+
+
+ self.announce('Creating package')
+ pkg_cmd = ['pkgmk', '-o', '-f']
+ pkg_cmd.append(path)
+ pkg_cmd.append('-b')
+ pkg_cmd.append(os.environ['PWD'])
+ self.spawn(pkg_cmd)
+ pkg_cmd = ['pkgtrans', '-s', '/var/spool/pkg']
+ path = os.path.join(os.environ['PWD'],pkg_dir,
+ self.get_binary_name() + ".pkg")
+ self.announce('Transferring package to ' + pkg_dir)
+ pkg_cmd.append(path)
+ pkg_cmd.append(self.pkg_abrev)
+ self.spawn(pkg_cmd)
+ os.system("rm -rf /var/spool/pkg/%s" % self.pkg_abrev)
+
+
+ def run (self):
+ if self.subpackages:
+ self.subpackages=string.split(self.subpackages,",")
+ for pkg in self.subpackages:
+ self.make_package(subpackage)
+ else:
+ self.make_package()
+ # run()
+
+
+ def _make_prototype(self):
+ proto_file = ["i pkginfo"]
+ if self.request:
+ proto_file.extend(['i request'])
+ if self.postinstall:
+ proto_file.extend(['i postinstall'])
+ if self.postremove:
+ proto_file.extend(['i postremove'])
+ if self.preinstall:
+ proto_file.extend(['i preinstall'])
+ if self.preremove:
+ proto_file.extend(['i preremove'])
+ if self.compver:
+ proto_file.extend(['i compver'])
+ if self.requires:
+ proto_file.extend(['i depend'])
+ proto_file.extend(['!default 644 root bin'])
+ build = self.get_finalized_command('build')
+
+ try:
+ self.distribution.packages[0]
+ file_list=string.split(
+ getoutput("pkgproto %s/%s=%s" % (build.build_lib,
+ self.distribution.packages[0],
+ self.distribution.packages[0])),"\012")
+ except:
+ file_list=string.split(
+ getoutput("pkgproto %s=" % (build.build_lib)),"\012")
+ ownership="%s %s" % (pwd.getpwuid(os.getuid())[0],
+ grp.getgrgid(os.getgid())[0])
+ for i in range(len(file_list)):
+ file_list[i] = string.replace(file_list[i],ownership,"root bin")
+ proto_file.extend(file_list)
+ return proto_file
+
+ def _make_request_script(self):
+ global DEFAULT_REQUEST
+ # A little different from other scripts, if we are to automatically
+ # relocate to the target site-packages, we have to wrap any provided
+ # script with the autorelocation script. If no script is provided,
+ # The request script will simply be the autorelocate script
+ if self.no_autorelocate==0:
+ request=string.split(DEFAULT_REQUEST,"\012")
+ else:
+ self.announce('Creating relocation request script')
+ if self.request:
+ users_request=self.get_script('request')
+ if users_request!=None and users_request!=[]:
+ if self.no_autorelocate==0 and users_request[0][0:2]=="#!":
+ users_request.remove(users_request[0])
+ for i in users_request:
+ request.append(i)
+
+ if self.no_autorelocate==0:
+ request.append("#############################################")
+ request.append("# finalize relocation support #")
+ request.append("#############################################")
+ request.append('echo "BASEDIR=\\"${BASEDIR}\\"" >>$1')
+ return request
+
+ def _make_info_file(self):
+ """Generate the text of a pkgtool info file and return it as a
+ list of strings (one per line).
+ """
+ # definitions and headers
+ # PKG must be alphanumeric, < 9 characters
+ info_file = [
+ 'PKG="%s"' % self.pkg_abrev,
+ 'NAME="%s"' % self.name,
+ 'VERSION="%s"' % self.version,
+ 'PSTAMP="%s"' % self.revision,
+ ]
+ info_file.extend(['VENDOR="%s (%s)"' % (self.distribution.maintainer, \
+ self.distribution.license) ])
+ info_file.extend(['EMAIL="%s"' % self.distribution.maintainer_email ])
+
+ p = self.distribution.get_platforms()
+ if p is None or p==['UNKNOWN']:
+ archs=getoutput('uname -p')
+ else:
+ archs=string.join(self.distribution.get_platforms(),',')
+ #else:
+ #print "Assuming a sparc architecure"
+ #archs='sparc'
+ info_file.extend(['ARCH="%s"' % archs ])
+
+ if self.distribution.get_url():
+ info_file.extend(['HOTLINE="%s"' % self.distribution.get_url() ])
+ if self.classes:
+ info_file.extend(['CLASSES="%s"' % self.classes ])
+ if self.category:
+ info_file.extend(['CATEGORY="%s"' % self.category ])
+ site=None
+ for i in sys.path:
+ if i[-13:]=="site-packages":
+ site=i
+ break
+ if site:
+ info_file.extend(['BASEDIR="%s"' % site ])
+
+ return info_file
+
+ # _make_info_file ()
+
+ def _format_changelog(self, changelog):
+ """Format the changelog correctly and convert it to a list of strings
+ """
+ if not changelog:
+ return changelog
+ new_changelog = []
+ for line in string.split(string.strip(changelog), '\n'):
+ line = string.strip(line)
+ if line[0] == '*':
+ new_changelog.extend(['', line])
+ elif line[0] == '-':
+ new_changelog.append(line)
+ else:
+ new_changelog.append(' ' + line)
+
+ # strip trailing newline inserted by first changelog entry
+ if not new_changelog[0]:
+ del new_changelog[0]
+
+ return new_changelog
+
+ # _format_changelog()
+
+# class bdist_rpm
diff --git a/Lib/distutils/command/bdist_sdux.py b/Lib/distutils/command/bdist_sdux.py
new file mode 100644
index 0000000..985a37a
--- /dev/null
+++ b/Lib/distutils/command/bdist_sdux.py
@@ -0,0 +1,302 @@
+"""distutils.command.bdist_pkgtool
+
+Implements the Distutils 'bdist_sdux' command to create HP-UX
+swinstall depot"""
+
+# Mark Alexander <slash@dotnetslash.net>
+
+__revision__ = "$Id: bdist_sdux.py,v 0.2 "
+import os, string
+import glob
+from types import *
+from distutils.core import Command, DEBUG
+from distutils.util import get_platform
+from distutils.file_util import write_file
+from distutils.errors import *
+from distutils.command import bdist_packager
+import sys
+from commands import getoutput
+
+DEFAULT_CHECKINSTALL="""#!/bin/sh
+/usr/bin/which python 2>&1 >/dev/null
+if [ $? -ne 0 ]; then
+ echo "ERROR: Python must be on your PATH" &>2
+ echo "ERROR: (You may need to link it to /usr/bin) " &>2
+ exit 1
+fi
+PY_DIR=`python -c "import sys;print '%s/lib/python%s' % (sys.exec_prefix,sys.version[0:3])" #2>/dev/null`
+PY_PKG_DIR=`python -c "import sys;print '%s/lib/python%s/site-packages' % (sys.exec_prefix,sys.version[0:3])" #2>/dev/null`
+PY_LIB_DIR=`dirname $PY_PKG_DIR`
+
+if [ "`dirname ${SW_LOCATION}`" = "__DISTUTILS_PKG_DIR__" ]; then
+ # swinstall to default location
+ if [ "${PY_PKG_DIR}" != "__DISTUTILS_PKG_DIR__" ]; then
+ echo "ERROR: " &>2
+ echo "ERROR: Python is not installed where this package expected!" &>2
+ echo "ERROR: You need to manually relocate this package to your python installation." &>2
+ echo "ERROR: " &>2
+ echo "ERROR: Re-run swinstall specifying the product name:location, e.g.:" &>2
+ echo "ERROR: " &>2
+ echo "ERROR: swinstall -s [source] __DISTUTILS_NAME__:${PY_PKG_DIR}/__DISTUTILS_DIRNAME__" &>2
+ echo "ERROR: " &>2
+ echo "ERROR: to relocate this package to match your python installation" &>2
+ echo "ERROR: " &>2
+ exit 1
+ fi
+else
+ if [ "`dirname ${SW_LOCATION}`" != "${PY_PKG_DIR}" -a "`dirname ${SWLOCATION}`" != "${PY_LIB_DIR}" ]; then
+ echo "WARNING: " &>2
+ echo "WARNING: Package is being installed outside the 'normal' python search path!" &>2
+ echo "WARNING: Add ${SW_LOCATION} to PYTHONPATH to use this package" &>2
+ echo "WARNING: " &>2
+ fi
+fi
+"""
+
+DEFAULT_POSTINSTALL="""#!/bin/sh
+/usr/bin/which python 2>&1 >/dev/null
+if [ $? -ne 0 ]; then
+ echo "ERROR: Python must be on your PATH" &>2
+ echo "ERROR: (You may need to link it to /usr/bin) " &>2
+ exit 1
+fi
+python -c "import compileall;compileall.compile_dir(\\"${SW_LOCATION}\\")"
+"""
+
+DEFAULT_PREREMOVE="""#!/bin/sh
+# remove compiled bytecode files
+find ${SW_LOCATION} -name "*.pyc" -exec rm {} \;
+find ${SW_LOCATION} -name "*.pyo" -exec rm {} \;
+"""
+
+DEFAULT_POSTREMOVE="""#!/bin/sh
+if [ `find ${SW_LOCATION} ! -type d | wc -l` -eq 0 ]; then
+ # remove if there's nothing but empty directories left
+ rm -rf ${SW_LOCATION}
+fi
+"""
+
+class bdist_sdux(bdist_packager.bdist_packager):
+
+ description = "create an HP swinstall depot"
+
+ user_options = bdist_packager.bdist_packager.user_options + [
+ #('revision=', None,
+ #"package revision number (PSTAMP)"),
+ ('keep-permissions', None,
+ "Don't reset permissions and ownership to root/bin"), # XXX
+ ('corequisites=', None,
+ "corequisites"), # XXX
+ ('prerequisites=', None,
+ "prerequisites"), # XXX
+ #('category=', None,
+ #"Software category"),
+ ('checkinstall=', None, # XXX ala request
+ "checkinstall script (Bourne shell code)"),
+ ('configure=', None, # XXX
+ "configure script (Bourne shell code)"),
+ ('unconfigure=', None, # XXX
+ "unconfigure script (Bourne shell code)"),
+ ('verify=', None, # XXX
+ "verify script (Bourne shell code)"),
+ ('unpreinstall=', None, # XXX
+ "unpreinstall script (Bourne shell code)"),
+ ('unpostinstall=', None, # XXX
+ "unpostinstall script (Bourne shell code)"),
+ ]
+
+ boolean_options = ['keep-permissions']
+
+ def initialize_options (self):
+ bdist_packager.bdist_packager.initialize_options(self)
+ self.corequisites = None
+ self.prerequesites = None
+ self.checkinstall = None
+ self.configure = None
+ self.unconfigure = None
+ self.verify = None
+ self.unpreinstall = None
+ self.unpostinstall = None
+ # More
+ self.copyright = None
+ self.readme = None
+ self.machine_type = None
+ self.os_name = None
+ self.os_release = None
+ self.directory = None
+ self.readme = None
+ self.copyright = None
+ self.architecture= None
+ self.keep_permissions= None
+ options = self.distribution.get_option_dict('bdist_packager')
+ for key in options.keys():
+ setattr(self,key,options[key][1])
+
+ # initialize_options()
+
+
+ def finalize_options (self):
+ global DEFAULT_CHECKINSTALL, DEFAULT_POSTINSTALL
+ global DEFAULT_PREREMOVE, DEFAULT_POSTREMOVE
+ if self.pkg_dir==None:
+ dist_dir = self.get_finalized_command('bdist').dist_dir
+ self.pkg_dir = os.path.join(dist_dir, "sdux")
+ self.ensure_script('corequisites')
+ self.ensure_script('prerequesites')
+ self.ensure_script('checkinstall')
+ self.ensure_script('configure')
+ self.ensure_script('unconfigure')
+ self.ensure_script('verify')
+ self.ensure_script('unpreinstall')
+ self.ensure_script('unpostinstall')
+ self.ensure_script('copyright')
+ self.ensure_script('readme')
+ self.ensure_string('machine_type','*')
+ if not self.__dict__.has_key('platforms'):
+ # This is probably HP, but if it's not, use sys.platform
+ if sys.platform[0:5] == "hp-ux":
+ self.platforms = "HP-UX"
+ else:
+ self.platforms = string.upper(sys.platform)
+ else:
+ # we can only handle one
+ self.platforms=string.join(self.platforms[0])
+ self.ensure_string('os_release','*')
+ self.ensure_string('directory','%s/lib/python%s/site-packages' % \
+ (sys.exec_prefix, sys.version[0:3]))
+ bdist_packager.bdist_packager.finalize_options(self)
+ DEFAULT_CHECKINSTALL = string.replace(DEFAULT_CHECKINSTALL,
+ "__DISTUTILS_NAME__", self.name)
+ DEFAULT_CHECKINSTALL = string.replace(DEFAULT_CHECKINSTALL,
+ "__DISTUTILS_DIRNAME__", self.root_package)
+ DEFAULT_CHECKINSTALL = string.replace(DEFAULT_CHECKINSTALL,
+ "__DISTUTILS_PKG_DIR__", self.directory)
+ DEFAULT_POSTINSTALL = string.replace(DEFAULT_POSTINSTALL,
+ "__DISTUTILS_DIRNAME__", self.root_package)
+ #DEFAULT_PREREMOVE = string.replace(DEFAULT_PREREMOVE,
+ #"__DISTUTILS_NAME__", self.root_package)
+ #DEFAULT_POSTREMOVE = string.replace(DEFAULT_POSTREMOVE,
+ #"__DISTUTILS_NAME__", self.root_package)
+ # finalize_options()
+
+ def run (self):
+ # make directories
+ self.mkpath(self.pkg_dir)
+ psf_path = os.path.join(self.pkg_dir,
+ "%s.psf" % self.get_binary_name())
+ # build package
+ self.announce('Building package')
+ self.run_command('build')
+ self.announce('Creating psf file')
+ self.execute(write_file,
+ (psf_path,
+ self._make_control_file()),
+ "writing '%s'" % psf_path)
+ if self.control_only: # stop if requested
+ return
+
+ self.announce('Creating package')
+ spawn_cmd = ['swpackage', '-s']
+ spawn_cmd.append(psf_path)
+ spawn_cmd.append('-x')
+ spawn_cmd.append('target_type=tape')
+ spawn_cmd.append('@')
+ spawn_cmd.append(self.pkg_dir+"/"+self.get_binary_name()+'.depot')
+ self.spawn(spawn_cmd)
+
+ # run()
+
+
+ def _make_control_file(self):
+ # Generate a psf file and return it as list of strings (one per line).
+ # definitions and headers
+ title = "%s %s" % (self.maintainer,self.maintainer_email)
+ title=title[0:80]
+ #top=self.distribution.packages[0]
+ psf_file = [
+ 'vendor', # Vendor information
+ ' tag %s' % "DISTUTILS",
+ ' title %s' % title,
+ ' description Distutils package maintainer (%s)' % self.license,
+ 'end', # end of vendor
+ 'product', # Product information
+ ' tag %s' % self.name,
+ ' title %s' % self.description,
+ ' description %s' % self.description,
+ ' revision %s' % self.version,
+ ' architecture %s' % self.platforms,
+ ' machine_type %s' % self.machine_type,
+ ' os_name %s' % self.platforms,
+ ' os_release %s' % self.os_release,
+ ' directory %s' % self.directory + "/" + self.root_package,
+ ]
+
+ self.write_script(os.path.join(self.pkg_dir, "checkinstall"),
+ 'checkinstall',DEFAULT_CHECKINSTALL)
+ psf_file.extend([' checkinstall %s/checkinstall' % self.pkg_dir])
+ self.write_script(os.path.join(self.pkg_dir, "postinstall"),
+ 'postinstall',DEFAULT_POSTINSTALL)
+ psf_file.extend([' postinstall %s/postinstall' % self.pkg_dir])
+ self.write_script(os.path.join(self.pkg_dir, "preremove"),
+ 'preremove',DEFAULT_PREREMOVE)
+ psf_file.extend([' preremove %s/preremove' % self.pkg_dir])
+ self.write_script(os.path.join(self.pkg_dir, "postremove"),
+ 'postremove',DEFAULT_POSTREMOVE)
+ psf_file.extend([' postremove %s/postremove' % self.pkg_dir])
+ if self.preinstall:
+ self.write_script(self.pkg_dir+"/preinstall", 'preinstall', None)
+ psf_file.extend([' preinstall %s/preinstall' % self.pkg_dir])
+ if self.configure:
+ self.write_script(self.pkg_dir+"/configure", 'configure', None)
+ psf_file.extend([' configure %s/configure' % self.pkg_dir])
+ if self.unconfigure:
+ self.write_script(self.pkg_dir+"/unconfigure", 'unconfigure', None)
+ psf_file.extend([' unconfigure %s/unconfigure' % self.pkg_dir])
+ if self.verify:
+ self.write_script(self.pkg_dir+"/verify", 'verify', None)
+ psf_file.extend([' verify %s/verify' % self.pkg_dir])
+ if self.unpreinstall:
+ self.write_script(self.pkg_dir+"/unpreinstall", 'unpreinstall', None)
+ psf_file.extend([' unpreinstall %s/unpreinstall' % self.pkg_dir])
+ if self.unpostinstall:
+ self.write_script(self.pkg_dir+"/unpostinstall", 'unpostinstall', None)
+ psf_file.extend([' unpostinstall %s/unpostinstall' % self.pkg_dir])
+ psf_file.extend([' is_locatable true'])
+ #if self.long_description:
+ #psf_file.extend([self.long_description])
+ if self.copyright:
+ # XX make a copyright file XXX
+ write_script('copyright')
+ psf_file.extend([' copyright <copyright'])
+ if self.readme:
+ # XX make a readme file XXX
+ write_script('readme')
+ psf_file.extend([' readme <readme'])
+
+ psf_file.extend([' fileset']) # start fileset
+ if self.distribution.ext_modules:
+ platlib=self.get_finalized_command('build').build_platlib
+ else:
+ platlib=self.get_finalized_command('build').build_lib
+ title = "%s installation files" % (self.name)
+ psf_file.extend([
+ ' tag %s' % 'FILES',
+ ' title %s' % "%s installation files" % (self.name),
+ ' revision %s' % self.version,
+ ' directory %s/%s=%s/%s' % (platlib,self.root_package,self.directory,self.root_package),
+ ])
+ if not self.keep_permissions:
+ psf_file.extend([' file_permissions -m 555 -o root -g bin'])
+ psf_file.extend([' file *'])
+ psf_file.extend([' end']) # end of fileset
+ psf_file.extend(['end']) # end of product
+
+# XXX add fileset information
+
+
+ return psf_file
+
+ # _make_control_file ()
+
+
+# class bdist_sdux