Skip to content
Browse files

Code cleanup

Added the extra-copies and extra-dirs
  • Loading branch information...
1 parent 6c4d9db commit e77ad7857fc8ae60de413c533db6ac89fbff3c09 Alvaro Saurin committed Mar 25, 2013
Showing with 184 additions and 234 deletions.
  1. +17 −14 README.md
  2. +94 −32 as/recipe/frozenpkg/frozen.py
  3. +43 −63 as/recipe/frozenpkg/frozenrpm.py
  4. +2 −2 as/recipe/frozenpkg/frozentgz.py
  5. +14 −117 setup.py
  6. +6 −3 testing/Makefile
  7. +8 −3 testing/buildout.cfg
View
31 README.md
@@ -37,23 +37,28 @@ Options
pkg-deps
Package dependencies. It must be a space-separated list of RPM packages.
- install-prefix
+ pkg-prefix
The installation prefix. Default: /opt/pkg-name
+ pkg-pre-install
+ Shell commands to run before installing the RPM
+
+ pkg-post-install
+ Shell commands to run after installing the RPM
+
eggs
The list of eggs that must be copied to the RPM package.
scripts
The scripts that will be copied to the package. Tese scripts will have their paths relocated to the installation prefix.
+ extra-dirs
+ Any additional directories to create.
+
extra-copies
Any additional extra copies. They must be specified as "orig -> dest", where orig can be any valid glob expression, and dest must be a path relative to install-prefix.
- pkg-pre-install
- Shell commands to run before installing the RPM
- pkg-post-install
- Shell commands to run after installing the RPM
Example
@@ -68,23 +73,21 @@ Example
pkg-url = http://www.mycomp.com
pkg-license = GPL
pkg-deps = libevent
+ pkg-prefix = /opt/testapp
+ pkg-pre-install =
+ echo "Installing at ${buildout:pkg-prefix}"
- install-prefix = /opt/testapp
+ pkg-post-install =
+ echo "Installed at ${buildout:pkg-prefix}"
eggs = ${main:eggs}
- scripts =
- testapp
-
extra-copies =
/usr/local/lib/mylib.so -> lib/
/usr/local/lib/myextras*.so -> lib/
- pkg-pre-install =
- echo "Installing at ${buildout:pkg-prefix}"
+ extra-dirs =
+ logs
- pkg-post-install =
- echo "Installed at ${buildout:pkg-prefix}"
-
debug = yes
View
126 as/recipe/frozenpkg/frozen.py
@@ -6,6 +6,7 @@
import logging
import glob
import re
+import tempfile
import pkg_resources
import subprocess
@@ -43,10 +44,44 @@ def __init__ (self, buildout, name, options):
else:
self.debug = False
+ def install(self):
+ """
+ Create a RPM
+ """
+ self.rpmbuild_dir = os.path.abspath(tempfile.mkdtemp(suffix = '', prefix = 'rpmbuild-'))
+
+ self.pkg_name = self.options['pkg-name']
+ self.pkg_version = self.options.get('pkg-version', '0.1')
+ self.pkg_vendor = self.options.get('pkg-vendor', 'unknown')
+ self.pkg_packager = self.options.get('pkg-packager', 'unknown')
+ self.pkg_url = self.options.get('pkg-url', 'unknown')
+ self.pkg_license = self.options.get('pkg-license', 'unknown')
+ self.pkg_group = self.options.get('pkg-group', 'unknown')
+ self.pkg_autodeps = self.options.get('pkg-autodeps', 'no')
+ self.pkg_prefix = self.options.get('pkg-prefix', os.path.join('opt', self.pkg_name))
+
+ self.buildroot = os.path.abspath(os.path.join(self.rpmbuild_dir, "BUILDROOT", self.pkg_name))
+ self.virtualenv_dir = os.path.abspath(self.buildroot + self.pkg_prefix)
+
+ ## create the build directory
+ try:
+ if not os.path.exists(self.virtualenv_dir):
+ os.makedirs(self.virtualenv_dir)
+
+ self._create_venv()
+ except:
+ logger.critical('ERROR: could not create virtual environment at "%s".' % (self.virtualenv_dir))
+ raise
+
############################################################################
+ def _virtualenv_path(self, path):
+ """
+ Return a path inside the virtualenv
+ """
+ return os.path.normpath(os.path.abspath(self.virtualenv_dir + '/' + path))
- def _create_venv(self, root_dir):
+ def _create_venv(self):
"""
Create a virtualenv in a directory
"""
@@ -59,7 +94,7 @@ def _create_venv(self, root_dir):
'--distribute',
'--no-site-packages',
'--clear',
- root_dir,
+ self.virtualenv_dir,
]
logger.info('Creating virtualenv by launching "%s".' % (" ".join(virtualenv)))
@@ -73,11 +108,11 @@ def _create_venv(self, root_dir):
sys.exit(1)
- def _copy_eggs (self, root_dir):
+ def _copy_eggs (self):
"""
Copy all the required eggs to the virtualenv
"""
- bin_dir = os.path.join(root_dir, 'bin')
+ bin_dir = os.path.join(self.virtualenv_dir, 'bin')
easy_install = os.path.join(bin_dir, 'easy_install')
if not os.path.exists(easy_install):
logger.critical('could NOT find easy_install at %s' % easy_install )
@@ -130,10 +165,10 @@ def _copy_eggs (self, root_dir):
raise UserError(stdout)
- def _copy_outputs(self, root_dir):
+ def _copy_outputs(self):
"""
Copies the outputs from parts
- :param root_dir: the root directory where to copy things
+ :param self.virtualenv_dir: the root directory where to copy things
"""
logger.info('Copying outputs.')
buildout_dir = self.buildout['buildout']['directory']
@@ -142,7 +177,7 @@ def _copy_outputs(self, root_dir):
outputs = self.buildout[part]['output']
for output in outputs.splitlines():
rel_dir = os.path.relpath(output, buildout_dir)
- dest_dir = os.path.join(root_dir, os.path.dirname(rel_dir))
+ dest_dir = self._virtualenv_path(os.path.dirname(rel_dir))
logger.debug('... "%s" -> "%s"' % (rel_dir, dest_dir))
if not os.path.exists(dest_dir):
@@ -153,17 +188,14 @@ def _copy_outputs(self, root_dir):
pass
- def _copy_extra_files (self, root_dir, install_prefix):
+ def _copy_extra_files (self):
"""
Copy any extra files, from the 'extra' options in the buildout
- :param root_dir: the root directory where to copy things
+ :param self.virtualenv_dir: the root directory where to copy things
"""
- assert (root_dir != None and len(root_dir) > 0)
- assert (install_prefix != None and len(install_prefix) > 0)
-
- pythonpath = []
+ assert (self.virtualenv_dir != None and len(self.virtualenv_dir) > 0)
+ assert (self.pkg_prefix != None and len(self.pkg_prefix) > 0)
- buildroot = os.path.normpath(os.path.join(root_dir, install_prefix))
buildout_dir = self.buildout['buildout']['directory']
extra_copies = [
@@ -177,12 +209,12 @@ def _copy_extra_files (self, root_dir, install_prefix):
src, dest = [b.strip() for b in copy_line.split("->")]
except Exception, e:
print "ERROR: malformed copy specification", e
- return pythonpath
+ return
if not os.path.isabs(src):
src = os.path.join(buildout_dir, src)
- full_path_dest = os.path.normpath(os.path.join(buildroot, dest))
+ full_path_dest = os.path.normpath(self._virtualenv_path(dest))
for src_el in glob.glob(src):
logger.debug('... copying "%s".' % src_el)
try:
@@ -198,20 +230,46 @@ def _copy_extra_files (self, root_dir, install_prefix):
shutil.copy(src_el, full_path_dest)
except Exception, e:
- logger.debug('ERROR: when copying "%s" to "%s"' % (src_el, full_path_dest))
+ logger.critical('ERROR: when copying "%s" to "%s"' % (src_el, full_path_dest))
- return pythonpath
-
- def _prepare_venv(self, root_dir):
+ def _create_extra_dirs (self):
+ """
+ Create any extra dirs
+ :param self.virtualenv_dir: the root directory where to copy things
+ """
+ assert (self.virtualenv_dir != None and len(self.virtualenv_dir) > 0)
+
+ extra_dirs_str = self.options.get('extra-dirs', None)
+ if extra_dirs_str:
+ logger.info('Creating extras directories.')
+ for directory in [r.strip() for r in extra_dirs_str.split('\n') if r.strip()]:
+
+ full_path_dest = self._virtualenv_path(directory)
+ if not os.path.exists(full_path_dest):
+ try:
+ logger.debug('... creating "%s".' % full_path_dest)
+ os.makedirs(full_path_dest)
+ except Exception, e:
+ msg = 'ERROR: when creating "%s" to "%s"' % (full_path_dest, str(e))
+ logger.critical(msg)
+ raise Exception(msg)
+
+ elif not os.path.isdir(full_path_dest):
+ msg = 'ERROR: "%s" exists but is not a directory'
+ logger.critical(msg)
+ raise Exception(msg)
+
+
+ def _prepare_venv(self):
"""
Finish the virtualenv by making it relocatable and removing some extra things we do not need...
"""
virtualenv = [
'virtualenv',
'--relocatable',
- root_dir,
+ self.virtualenv_dir,
]
logger.info('Making virtualenv relocatable with "%s".' % (" ".join(virtualenv)))
@@ -221,32 +279,36 @@ def _prepare_venv(self, root_dir):
stdout, _ = job.communicate()
if job.returncode != 0:
- logger.critical('could not run virtualenv')
+ logger.critical('ERROR: could not run "virtualenv".')
sys.exit(1)
- local_dir = os.path.join(root_dir, "local")
- logger.debug('Removing "%s".' % local_dir)
- shutil.rmtree(local_dir)
+ local_dir = os.path.join(self.virtualenv_dir, "local")
+ if os.path.exists(local_dir):
+ logger.debug('Removing "%s".' % local_dir)
+ shutil.rmtree(local_dir)
- def _create_tar (self, root_dir, filename, compress = False):
+ def _create_tar (self, filename, compress = False):
"""
Create a tar file from the virtualenv
"""
- logger.info('Creating tar file.')
+ logger.info('Creating tar file from the virtualenv.')
import tarfile
with tarfile.open(filename, 'w' if not compress else 'w:gz', dereference = True) as t:
- for name in glob.glob(os.path.join(root_dir, '*')):
- rel_name = '/' + os.path.relpath(name, root_dir)
+ for name in glob.glob(os.path.join(self.buildroot, '*')):
+ rel_name = '/' + os.path.relpath(name, self.buildroot)
t.add(name, arcname = rel_name)
if compress:
- return os.path.join(filename + ".gz")
+ output = os.path.join(filename + ".gz")
else:
- return filename
+ output = filename
+ logger.debug('... output: %s.' % output)
+ return output
-################################################################################
+
+ ################################################################################
if __name__ == '__main__':
f = Frozen()
View
106 as/recipe/frozenpkg/frozenrpm.py
@@ -70,62 +70,32 @@
class FrozenRPM(Frozen):
-
- def _create_dirs(self, top_rpmbuild_dir):
- """
- Create all the top dirs
- """
- try:
- os.mkdir(os.path.abspath(os.path.join(top_rpmbuild_dir, "BUILDROOT")))
- os.mkdir(os.path.abspath(os.path.join(top_rpmbuild_dir, "RPMS")))
- os.mkdir(os.path.abspath(os.path.join(top_rpmbuild_dir, "SOURCES")))
- os.mkdir(os.path.abspath(os.path.join(top_rpmbuild_dir, "SPECS")))
- os.mkdir(os.path.abspath(os.path.join(top_rpmbuild_dir, "SRPMS")))
- except:
- logger.critical('could not create directoies in %s' % top_rpmbuild_dir)
- shutil.rmtree(top_rpmbuild_dir, ignore_errors = True)
- sys.exit(1)
-
def install (self):
"""
Create a RPM
"""
- additional_ops = []
-
- top_rpmbuild_dir = os.path.abspath(tempfile.mkdtemp(suffix = '', prefix = 'rpmbuild-'))
- self._create_dirs(top_rpmbuild_dir)
+ super(FrozenRPM, self).install()
- pkg_name = self.options['pkg-name']
- pkg_version = self.options.get('pkg-version', '0.1')
- pkg_vendor = self.options.get('pkg-vendor', 'unknown')
- pkg_packager = self.options.get('pkg-packager', 'unknown')
- pkg_url = self.options.get('pkg-url', 'unknown')
- pkg_license = self.options.get('pkg-license', 'unknown')
- pkg_group = self.options.get('pkg-group', 'unknown')
- pkg_autodeps = self.options.get('pkg-autodeps', 'no')
+ self._create_rpm_dirs()
+ additional_ops = []
if self.options.has_key('pkg-deps'):
additional_ops = additional_ops + ["Requires: " + self.options['pkg-deps']]
- self.install_prefix = self.options.get('install-prefix', os.path.join('opt', pkg_name))
-
- buildroot_topdir = os.path.abspath(os.path.join(top_rpmbuild_dir, "BUILDROOT", pkg_name))
- buildroot_projdir = os.path.abspath(buildroot_topdir + self.install_prefix)
-
# replace the variables in the "spec" template
rpmspec = RPM_SPEC_TEMPLATE
- rpmspec = rpmspec.replace("@TOP_DIR@", top_rpmbuild_dir)
- rpmspec = rpmspec.replace("@PKG_NAME@", pkg_name)
- rpmspec = rpmspec.replace("@PKG_VENDOR@", pkg_vendor)
- rpmspec = rpmspec.replace("@PKG_VERSION@", pkg_version)
- rpmspec = rpmspec.replace("@PKG_PACKAGER@", pkg_packager)
- rpmspec = rpmspec.replace("@PKG_URL@", pkg_url)
- rpmspec = rpmspec.replace("@PKG_LICENSE@", pkg_license)
- rpmspec = rpmspec.replace("@PKG_GROUP@", pkg_group)
- rpmspec = rpmspec.replace("@PKG_AUTODEPS@", pkg_autodeps)
- rpmspec = rpmspec.replace("@INSTALL_PREFIX@", self.install_prefix)
- rpmspec = rpmspec.replace("@BUILD_ROOT@", buildroot_topdir)
+ rpmspec = rpmspec.replace("@TOP_DIR@", self.rpmbuild_dir)
+ rpmspec = rpmspec.replace("@PKG_NAME@", self.pkg_name)
+ rpmspec = rpmspec.replace("@PKG_VENDOR@", self.pkg_vendor)
+ rpmspec = rpmspec.replace("@PKG_VERSION@", self.pkg_version)
+ rpmspec = rpmspec.replace("@PKG_PACKAGER@", self.pkg_packager)
+ rpmspec = rpmspec.replace("@PKG_URL@", self.pkg_url)
+ rpmspec = rpmspec.replace("@PKG_LICENSE@", self.pkg_license)
+ rpmspec = rpmspec.replace("@PKG_GROUP@", self.pkg_group)
+ rpmspec = rpmspec.replace("@PKG_AUTODEPS@", self.pkg_autodeps)
+ rpmspec = rpmspec.replace("@INSTALL_PREFIX@", self.pkg_prefix)
+ rpmspec = rpmspec.replace("@BUILD_ROOT@", self.buildroot)
rpmspec = rpmspec.replace("@ADDITIONAL_OPS@", "\n".join(additional_ops))
# determine if we must run any pre/post commands
@@ -140,16 +110,8 @@ def install (self):
rpmspec = rpmspec.replace("@SCRIPTS@", scripts)
- ## create the build directory
- try:
- os.makedirs(buildroot_projdir)
- self._create_venv(buildroot_projdir)
- except:
- logger.critical('Could not create virtual environment at %s' % (buildroot_projdir))
- raise
-
## save the spec file
- spec_filename = os.path.abspath(os.path.join(buildroot_topdir, pkg_name) + ".spec")
+ spec_filename = os.path.abspath(os.path.join(self.buildroot, self.pkg_name) + ".spec")
logger.debug('Using spec file %s' % (spec_filename))
spec_file = None
try:
@@ -162,23 +124,25 @@ def install (self):
if spec_file:
spec_file.close()
- self._copy_eggs(buildroot_projdir)
- self._copy_outputs(buildroot_projdir)
- self._prepare_venv(buildroot_projdir)
+ self._copy_eggs()
+ self._copy_outputs()
+ self._create_extra_dirs()
+ self._copy_extra_files()
+ self._prepare_venv()
# create a tar file at SOURCES/.
# we can pass a tar file to rpmbuild, so it is easier as we may need
# a "tar" anyway.
# the spec file should be inside the tar, at the top level...
- tar_filename = os.path.join(top_rpmbuild_dir, "SOURCES", pkg_name + ".tar")
- tar_filename = self._create_tar(buildroot_topdir, tar_filename)
+ tar_filename = os.path.join(self.rpmbuild_dir, "SOURCES", self.pkg_name + ".tar")
+ tar_filename = self._create_tar(tar_filename)
# launch rpmbuild
command = [
"rpmbuild",
- "--buildroot", buildroot_topdir,
+ "--buildroot", self.buildroot,
"--define",
- "_topdir %s" % top_rpmbuild_dir,
+ "_topdir %s" % self.rpmbuild_dir,
"-ta", tar_filename,
]
@@ -193,8 +157,8 @@ def install (self):
# now try to find the RPMs we have built
result_rpms = []
- for arch_dir in os.listdir(os.path.join(top_rpmbuild_dir, "RPMS")):
- full_arch_dir = os.path.abspath(os.path.join(top_rpmbuild_dir, "RPMS", arch_dir))
+ for arch_dir in os.listdir(os.path.join(self.rpmbuild_dir, "RPMS")):
+ full_arch_dir = os.path.abspath(os.path.join(self.rpmbuild_dir, "RPMS", arch_dir))
if os.path.isdir(full_arch_dir):
for rpm_file in os.listdir(full_arch_dir):
if fnmatch.fnmatch(rpm_file, "*.rpm"):
@@ -206,9 +170,25 @@ def install (self):
result_rpms = result_rpms + [rpm_file]
if not self.debug:
- shutil.rmtree(top_rpmbuild_dir)
+ shutil.rmtree(self.rpmbuild_dir)
return result_rpms
+
+ def _create_rpm_dirs(self):
+ """
+ Create all the top dirs
+ """
+ for p in ["BUILDROOT", "RPMS", "SOURCES", "SPECS", "SRPMS"]:
+ full_p = os.path.join(self.rpmbuild_dir, p)
+ if not os.path.exists(full_p):
+ try:
+ os.makedirs(full_p)
+ except:
+ logger.critical('ERROR: could not create directory "%s"' % full_p)
+ shutil.rmtree(self.rpmbuild_dir, ignore_errors = True)
+ raise
+
+
def update (self):
pass
View
4 as/recipe/frozenpkg/frozentgz.py
@@ -26,10 +26,10 @@ def install (self):
pkg_name = self.options['pkg-name']
pkg_version = self.options.get('pkg-version', '0.1')
- self.install_prefix = self.options.get('install-prefix', os.path.join('opt', pkg_name))
+ self.pkg_prefix = self.options.get('pkg-prefix', os.path.join('opt', pkg_name))
buildroot_topdir = os.path.abspath(top_tgzbuild_dir + "/PKG/" + pkg_name)
- buildroot_projdir = os.path.abspath(buildroot_topdir + "/" + self.install_prefix)
+ buildroot_projdir = os.path.abspath(buildroot_topdir + "/" + self.pkg_prefix)
buildroot_tgzs = os.path.abspath(top_tgzbuild_dir + "/TGZ")
# get the python binary, the version and the library
View
131 setup.py
@@ -7,117 +7,13 @@
__VERSION__ = '0.2.18'
-#def read(*rnames):
-# return open(os.path.join(os.path.dirname(__file__), *rnames), "r").read()
-
-
-long_description = """
-Introduction
-============
-
-This recipe enables you to freeze your buildout in a RPM, tgz's, etc.
-You can specify the package details, the installation prefix, and the eggs and
-scripts that must be copied to the package.
-
-Only RPM packing is currently implemented.
-
-This recipe is EXPERIMENTAL and quite unstable, so use at your own risk...
-
-.. contents::
-
-- PyPI page: http://pypi.python.org/pypi?:action=display&name=as.recipe.frozenpkg
-
-Options
-=======
-
-pkg-name
- Mandatory. The package name.
-
-pkg-version
- The package version.
-
-pkg-vendor
- The package vendor.
-
-pkg-packager
- The packager.
-
-pkg-url
- The package URL.
-
-pkg-license
- The license.
-
-pkg-deps
- Package dependencies. It must be a space-separated list of RPM packages.
-
-install-prefix
- The installation prefix. Default: /opt/pkg-name
-
-eggs
- The list of eggs that must be copied to the RPM package.
-
-scripts
- The scripts from the bin directory that will be copied to the package. These scripts will have their paths relocated to the installation prefix.
-
-extra-copies
- Any additional extra copies. They must be specified as "orig -> dest", where orig can be any valid glob expression, and dest must be a path relative to install-prefix.
-
-pkg-pre-install
- Shell commands to run before installing the RPM
-
-pkg-post-install
- Shell commands to run after installing the RPM
-
-
-Example
-=======
-
- [rpm]
- recipe = as.recipe.frozenpkg:rpm
- pkg-name = testapp
- pkg-version = 1.0
- pkg-vendor = The Vendor
- pkg-packager = My Company
- pkg-url = http://www.mycomp.com
- pkg-license = GPL
- pkg-deps = libevent
-
- install-prefix = /opt/testapp
-
- eggs = ${buildout:eggs}
-
- sys-python = /usr/lib/python2.6
-
- scripts =
- testapp
-
- extra-copies =
- /usr/local/lib/mylib.so -> lib/
- /usr/local/lib/myextras*.so -> lib/
- pkg-pre-install =
- echo "Installing at ${buildout:pkg-prefix}"
-
- pkg-post-install =
- echo "Installed at ${buildout:pkg-prefix}"
-
- debug = yes
-
-
-Known Bugs
-==========
-
-- You must comment out the prelink_undo_cmd at /etc/rpm/macros.prelink, or the RPM generated will fail to install.
-
-"""
-
setup(
- name = "as.recipe.frozenpkg",
- description = "ZC Buildout recipe for freezing buildouts in RPM's, tar.gz's, etc",
- long_description = long_description,
- version = __VERSION__,
+ name = "as.recipe.frozenpkg",
+ description = "ZC Buildout recipe for freezing buildouts in RPM's, tar.gz's, etc",
+ long_description = open('README.md', 'rt').read(),
+ version = __VERSION__,
# Get more strings from http://www.python.org/pypi?%3Aaction=list_classifiers
classifiers = [
@@ -128,11 +24,11 @@
'License :: OSI Approved :: GNU General Public License (GPL)',
],
- keywords = 'buildout recipe',
- author = 'Alvaro Saurin',
- author_email = 'name dot surname at gmail.com',
+ keywords = 'buildout recipe',
+ author = 'Alvaro Saurin',
+ author_email = 'name dot surname at gmail.com',
- packages = find_packages(exclude = ['ez_setup']),
+ packages = find_packages(exclude = ['ez_setup']),
namespace_packages = ['as',
'as.recipe'],
@@ -143,14 +39,15 @@
'virtualenv',
],
- license = 'GPL',
- zip_safe = False,
- entry_points = {
- 'zc.buildout': [
- 'default = as.recipe.frozenpkg:FrozenRPM',
+ license = 'GPL',
+ zip_safe = False,
+ entry_points = {
+ 'zc.buildout': [
+ 'default = as.recipe.frozenpkg.frozenrpm:FrozenRPM',
'rpm = as.recipe.frozenpkg.frozenrpm:FrozenRPM',
'tgz = as.recipe.frozenpkg.frozentgz:FrozenTgz'
]
},
)
+
View
9 testing/Makefile
@@ -9,8 +9,11 @@ bin/buildout:
build: bin/buildout
bin/buildout -v -v
-distclean:
- rm -rf bin build develop-eggs eggs parts temp
+
+clean:
+ rm -rf bin build parts temp
rm -rf *.tar.gz *.rpm *.egg-info
-clean: distclean
+distclean:
+ rm -rf eggs develop-eggs
+
View
11 testing/buildout.cfg
@@ -23,10 +23,15 @@ pkg-packager = Thes testing company
pkg-url = http://www.test.com
pkg-license = BSD
pkg-deps = glibc
-install-prefix = /opt/frozen_test_app
-python-version = 2.6
-sys-dir = /usr/lib/python2.6
+pkg-prefix = /opt/frozen_test_app
+
debug = yes
eggs = ${buildout:eggs}
frozen_test_app
+extra-copies =
+ buildout.cfg -> extra/data1/buildout.cfg
+ buildout.cfg -> extra/data2/
+extra-dirs =
+ extra/data1
+ extra/data3

0 comments on commit e77ad78

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