Commit dfb24fa1 authored by Thomas Larrieu's avatar Thomas Larrieu

finished implementing cleanup feature. still have to implement testing for this.

parent f5d260a2
...@@ -228,157 +228,189 @@ class Recipe(object): ...@@ -228,157 +228,189 @@ class Recipe(object):
log.error('Command failed: %s: %s' % (e, cmd)) log.error('Command failed: %s: %s' % (e, cmd))
raise zc.buildout.UserError('System error') raise zc.buildout.UserError('System error')
def install(self): def clean(self, cleanup_list):
log = logging.getLogger(self.name) """
parts = [] Basically, this method does not do much, appart from removing
what it is told to, as a list passed in args
make_cmd = self.options.get('make-binary', 'make').strip() """
make_options = ' '.join(self.options.get('make-options', '').split()) import glob
make_targets = ' '.join(self.options.get('make-targets', 'install').split()) def build_working_iterator(cleanup_list):
configure_options = self.options.get('configure-options', '').split()
configure_cmd = self.options.get('configure-command', '').strip()
if not configure_cmd:
# Default to using basic configure script.
configure_cmd = './configure'
# Inject the --prefix parameter if not already present
if '--prefix' not in ' '.join(configure_options):
configure_options.insert(0, '--prefix=\"%s\"' % self.options['prefix'])
elif make_cmd == 'make' and make_targets == 'install':
make_targets += ' prefix=\"%s\"' % self.options['prefix']
patch_cmd = self.options.get('patch-binary', 'patch').strip()
patch_options = ' '.join(self.options.get('patch-options', '-p0').split())
patches = self.options.get('patches', '').split()
if self.environ:
for key in sorted(self.environ.keys()):
log.info('[ENV] %s = %s', key, self.environ[key])
# Download the source using hexagonit.recipe.download
if self.options['url']:
compile_dir = self.options['compile-directory']
if os.path.exists(compile_dir):
# leftovers from a previous failed attempt, removing it.
log.warning('Removing already existing directory %s' % compile_dir)
shutil.rmtree(compile_dir)
os.mkdir(compile_dir)
try:
opt = self.options.copy()
opt['destination'] = compile_dir
hexagonit.recipe.download.Recipe(
self.buildout, self.name, opt).install()
except:
shutil.rmtree(compile_dir)
raise
else:
log.info('Using local source directory: %s' % self.options['path'])
compile_dir = self.options['path']
current_dir = os.getcwd() current_dir = os.getcwd()
try: for pattern in cleanup_list:
os.mkdir(self.options['location']) # if current pattern contains wildcards, we search for all matching
except OSError as e: # files/directories
if e.errno == errno.EEXIST: if pattern.find('*') > -1 or pattern.find('?') > -1 or pattern.find('[') > -1:
pass g = glob.glob(pattern)
os.chdir(compile_dir) if g:
tmp_path = self.environ['TMP'] for x in g:
shutil.rmtree(tmp_path, True) yield x
os.mkdir(tmp_path) else:
raise IOError("Pattern " + pattern + " did not match anything")
try: elif os.path.exists(pattern):
try: if os.path.relpath(pattern).startswith('..'):
# We support packages that either extract contents to the $PWD raise IOError(current_dir + " does not contain " + pattern)
# or alternatively have a single directory.
contents = os.listdir(compile_dir)
if len(contents) == 1 and os.path.isdir(contents[0]):
# Single container
os.chdir(contents[0])
if patches:
log.info('Applying patches')
for patch in patches:
patch_filename, is_temp = self.download_file(patch)
self.run('%s %s < %s' % (patch_cmd, patch_options, patch_filename))
if is_temp:
os.remove(patch_filename)
if 'pre-configure-hook' in self.options and len(self.options['pre-configure-hook'].strip()) > 0:
log.info('Executing pre-configure-hook')
self.call_script(self.options['pre-configure-hook'])
pre_configure_cmd = self.options.get('pre-configure', '').strip() % self.options
if pre_configure_cmd != '':
log.info('Executing pre-configure')
self.run(pre_configure_cmd)
self.run(('%s %s' % (configure_cmd, ' '.join(configure_options))) % self.options)
if 'pre-make-hook' in self.options and len(self.options['pre-make-hook'].strip()) > 0:
log.info('Executing pre-make-hook')
self.call_script(self.options['pre-make-hook'])
pre_build_cmd = self.options.get('pre-build', '').strip() % self.options
if pre_build_cmd != '':
log.info('Executing pre-build')
self.run(pre_build_cmd)
self.run(('%s %s' % (make_cmd, make_options)) % self.options)
pre_install_cmd = self.options.get('pre-install', '').strip() % self.options
if pre_install_cmd != '':
log.info('Executing pre-install')
self.run(pre_install_cmd)
self.run(('%s %s %s' % (make_cmd, make_options, make_targets)) % self.options)
if 'post-make-hook' in self.options and len(self.options['post-make-hook'].strip()) > 0:
log.info('Executing post-make-hook')
self.call_script(self.options['post-make-hook'])
post_install_cmd = self.options.get('post-install', '').strip() % self.options
if post_install_cmd != '':
log.info('Executing post-install')
self.run(post_install_cmd)
if self.buildout_prefix != '' and os.path.exists(self.buildout_prefix):
log.info('Getting installed file lists')
parts.extend(self.get_installed_files(tmp_path))
except:
log.error('Compilation error. The package is left as is at %s where '
'you can inspect what went wrong' % os.getcwd())
raise
finally:
os.chdir(current_dir)
shutil.rmtree(tmp_path)
# Check promises
self.check_promises()
if self.options['url']:
if self.options.get('keep-compile-dir',
self.buildout['buildout'].get('keep-compile-dir', '')).lower() in ('true', 'yes', '1', 'on'):
# If we're keeping the compile directory around, add it to
# the parts so that it's also removed when this recipe is
# uninstalled.
parts.append(self.options['compile-directory'])
else: else:
shutil.rmtree(compile_dir) yield pattern
del self.options['compile-directory'] else:
raise IOError(pattern + " does not exist")
# As build_working_iterator is a generator and since we want to first
# check every file (raising exceptions when necessary) BEFORE removing
# anything from the file system, we enforce full lookup by build a tuple
# out of it
for x in tuple(build_working_iterator(cleanup_list)):
# This first condition is mandatory as we might have removed an entire
# tree during a previous iteration, possibly leading to a case where
# some items are still to be removed but do not exist anymore
if os.path.exists(x):
if os.path.isdir(x):
shutil.rmtree(x)
else:
os.remove(x)
logging.getLogger(self.name).info('%s has been successfully removed', x)
parts.append(self.options['location'])
# Cleanup state
cleanup_list = self.options.get('cleanup', '').split()
self.clean(cleanup_list) def install(self):
return parts log = logging.getLogger(self.name)
parts = []
make_cmd = self.options.get('make-binary', 'make').strip()
make_options = ' '.join(self.options.get('make-options', '').split())
make_targets = ' '.join(self.options.get('make-targets', 'install').split())
configure_options = self.options.get('configure-options', '').split()
configure_cmd = self.options.get('configure-command', '').strip()
if not configure_cmd:
# Default to using basic configure script.
configure_cmd = './configure'
# Inject the --prefix parameter if not already present
if '--prefix' not in ' '.join(configure_options):
configure_options.insert(0, '--prefix=\"%s\"' % self.options['prefix'])
elif make_cmd == 'make' and make_targets == 'install':
make_targets += ' prefix=\"%s\"' % self.options['prefix']
patch_cmd = self.options.get('patch-binary', 'patch').strip()
patch_options = ' '.join(self.options.get('patch-options', '-p0').split())
patches = self.options.get('patches', '').split()
if self.environ:
for key in sorted(self.environ.keys()):
log.info('[ENV] %s = %s', key, self.environ[key])
# Download the source using hexagonit.recipe.download
if self.options['url']:
compile_dir = self.options['compile-directory']
if os.path.exists(compile_dir):
# leftovers from a previous failed attempt, removing it.
log.warning('Removing already existing directory %s' % compile_dir)
shutil.rmtree(compile_dir)
os.mkdir(compile_dir)
try:
opt = self.options.copy()
opt['destination'] = compile_dir
hexagonit.recipe.download.Recipe(
self.buildout, self.name, opt).install()
except:
shutil.rmtree(compile_dir)
raise
else:
log.info('Using local source directory: %s' % self.options['path'])
compile_dir = self.options['path']
def clean(self, cleanup_list):
"""
Basically, this method does not do much, appart from removing
what it is told to, as a list passed in args
"""
current_dir = os.getcwd() current_dir = os.getcwd()
for i, directory in enumerate(cleanup_list): try:
print str(i) + "->" + directory os.mkdir(self.options['location'])
except OSError as e:
if e.errno == errno.EEXIST:
pass
os.chdir(compile_dir)
tmp_path = self.environ['TMP']
shutil.rmtree(tmp_path, True)
os.mkdir(tmp_path)
try:
try:
# We support packages that either extract contents to the $PWD
# or alternatively have a single directory.
contents = os.listdir(compile_dir)
if len(contents) == 1 and os.path.isdir(contents[0]):
# Single container
os.chdir(contents[0])
if patches:
log.info('Applying patches')
for patch in patches:
patch_filename, is_temp = self.download_file(patch)
self.run('%s %s < %s' % (patch_cmd, patch_options, patch_filename))
if is_temp:
os.remove(patch_filename)
if 'pre-configure-hook' in self.options and len(self.options['pre-configure-hook'].strip()) > 0:
log.info('Executing pre-configure-hook')
self.call_script(self.options['pre-configure-hook'])
pre_configure_cmd = self.options.get('pre-configure', '').strip() % self.options
if pre_configure_cmd != '':
log.info('Executing pre-configure')
self.run(pre_configure_cmd)
self.run(('%s %s' % (configure_cmd, ' '.join(configure_options))) % self.options)
if 'pre-make-hook' in self.options and len(self.options['pre-make-hook'].strip()) > 0:
log.info('Executing pre-make-hook')
self.call_script(self.options['pre-make-hook'])
pre_build_cmd = self.options.get('pre-build', '').strip() % self.options
if pre_build_cmd != '':
log.info('Executing pre-build')
self.run(pre_build_cmd)
self.run(('%s %s' % (make_cmd, make_options)) % self.options)
pre_install_cmd = self.options.get('pre-install', '').strip() % self.options
if pre_install_cmd != '':
log.info('Executing pre-install')
self.run(pre_install_cmd)
self.run(('%s %s %s' % (make_cmd, make_options, make_targets)) % self.options)
if 'post-make-hook' in self.options and len(self.options['post-make-hook'].strip()) > 0:
log.info('Executing post-make-hook')
self.call_script(self.options['post-make-hook'])
post_install_cmd = self.options.get('post-install', '').strip() % self.options
if post_install_cmd != '':
log.info('Executing post-install')
self.run(post_install_cmd)
if self.buildout_prefix != '' and os.path.exists(self.buildout_prefix):
log.info('Getting installed file lists')
parts.extend(self.get_installed_files(tmp_path))
except:
log.error('Compilation error. The package is left as is at %s where '
'you can inspect what went wrong' % os.getcwd())
raise
finally:
os.chdir(current_dir)
shutil.rmtree(tmp_path)
# Check promises
self.check_promises()
if self.options['url']:
if self.options.get('keep-compile-dir',
self.buildout['buildout'].get('keep-compile-dir', '')).lower() in ('true', 'yes', '1', 'on'):
# If we're keeping the compile directory around, add it to
# the parts so that it's also removed when this recipe is
# uninstalled.
parts.append(self.options['compile-directory'])
else:
shutil.rmtree(compile_dir)
del self.options['compile-directory']
parts.append(self.options['location'])
# Cleanup state
cleanup_list = self.options.get('cleanup', '').split()
self.clean(cleanup_list)
return parts
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment