Reimplement shared features
1.use shared-part in [buildout] section to define shared path 2.shared option is True or Flase 3.a magic substitution @@LOCATION@@ is used to for dynamic path
Showing
1.use shared-part in [buildout] section to define shared path 2.shared option is True or Flase 3.a magic substitution @@LOCATION@@ is used to for dynamic path
... | @@ -29,7 +29,7 @@ class Recipe(object): | ... | @@ -29,7 +29,7 @@ class Recipe(object): |
self.options = options | self.options = options | ||
self.buildout = buildout | self.buildout = buildout | ||
self.name = name | self.name = name | ||
log = logging.getLogger(self.name) | |||
# Merge options if there is a matched platform section | # Merge options if there is a matched platform section | ||
platform_options = self.buildout.get( | platform_options = self.buildout.get( | ||
"%s:%s:%s" % (name, sys.platform, self.get_machine()), | "%s:%s:%s" % (name, sys.platform, self.get_machine()), | ||
... | @@ -40,12 +40,41 @@ class Recipe(object): | ... | @@ -40,12 +40,41 @@ class Recipe(object): |
self.original_options = options.copy() | self.original_options = options.copy() | ||
options.update(platform_options) | options.update(platform_options) | ||
options['share'] = options.get('share', '').strip() | shared = options.get('shared', '') | ||
options['default-location'] = os.path.join( | if shared: | ||
shared_part = buildout['buildout'].get('shared-part', None) | |||
if not shared_part: | |||
raise ValueError( | |||
" Set ${buildout:shared-part} for shared feature") | |||
shared = os.path.join(shared_part.strip().rstrip('/'), self.name) | |||
if not os.path.exists(shared): | |||
os.makedirs(shared) | |||
self._debug_signature_text = [] | |||
# compute hash from options | |||
m = md5() | |||
buildout_directory = buildout['buildout']['directory'] | |||
profile_base_location = options.get('_profile_base_location_', '') | |||
for k, v in sorted(options.items()): | |||
# Key not vary on profile base location | |||
if profile_base_location: | |||
v = v.replace(profile_base_location, '${:_profile_base_location_}') | |||
option_signature = ('%r: %r' % (k, v)).encode() | |||
log.debug("Updating hash with %s", option_signature) | |||
self._debug_signature_text.append(option_signature) | |||
# Or maybe warn and disable cache | |||
assert buildout_directory not in option_signature | |||
m.update(option_signature) | |||
shared = os.path.join(shared, m.hexdigest()) | |||
log.info('shared directory %s set for %s' % (shared, self.name)) | |||
options['shared'] = shared | |||
default_location = options['default-location'] = os.path.join( | |||
buildout['buildout']['parts-directory'], | buildout['buildout']['parts-directory'], | ||
self.name) | self.name) if shared == '' else shared | ||
share = options['share'] | options['location'] = options['default-location'] | ||
options['location'] = options['default-location'] if share == '' else share.rstrip('/') | |||
prefix = options.get('prefix', '').strip() | prefix = options.get('prefix', '').strip() | ||
if prefix == '': | if prefix == '': | ||
... | @@ -88,6 +117,11 @@ class Recipe(object): | ... | @@ -88,6 +117,11 @@ class Recipe(object): |
else: | else: | ||
options['compile-directory'] = options['path'] | options['compile-directory'] = options['path'] | ||
from copy import copy | |||
for k, v in copy(options.items()): | |||
Please
register
or
sign in
to reply
|
|||
if '@@LOCATION@@' in v: | |||
options[k] = v.replace('@@LOCATION@@', default_location) | |||
self.environ = {} | self.environ = {} | ||
self.original_environment = os.environ.copy() | self.original_environment = os.environ.copy() | ||
... | @@ -250,10 +284,10 @@ class Recipe(object): | ... | @@ -250,10 +284,10 @@ class Recipe(object): |
log = logging.getLogger(self.name) | log = logging.getLogger(self.name) | ||
parts = [] | parts = [] | ||
# In share mode, do nothing if package has been installed. | # In shared mode, do nothing if package has been installed. | ||
if (not self.options['share'] == ''): | if (not self.options['shared'] == ''): | ||
log.info('Checking whether package is installed at share path: %s' % self.options['share']) | log.info('Checking whether package is installed at shared path: %s' % self.options['shared']) | ||
if self.check_promises(log): | if os.path.exists(self.options['shared']): | ||
log.info('This shared package has been installed by other package') | log.info('This shared package has been installed by other package') | ||
return parts | return parts | ||
... | @@ -314,6 +348,13 @@ class Recipe(object): | ... | @@ -314,6 +348,13 @@ class Recipe(object): |
shutil.rmtree(tmp_path, True) | shutil.rmtree(tmp_path, True) | ||
os.mkdir(tmp_path) | os.mkdir(tmp_path) | ||
# Create a debug file with the signatures. | |||
if self.options['shared']: | |||
with open(os.path.join( | |||
self.options["shared"], | |||
".slapos.recipe.cmmi.signature"), 'w') as f: | |||
f.write('\n'.join(self._debug_signature_text)) | |||
try: | try: | ||
try: | try: | ||
# We support packages that either extract contents to the $PWD | # We support packages that either extract contents to the $PWD | ||
... | @@ -369,17 +410,22 @@ class Recipe(object): | ... | @@ -369,17 +410,22 @@ class Recipe(object): |
log.info('Executing post-install') | log.info('Executing post-install') | ||
self.run(post_install_cmd) | self.run(post_install_cmd) | ||
if (self.buildout_prefix != '' | if (self.buildout_prefix != '' | ||
and self.options['share'] == '' | and self.options['shared'] == '' | ||
and os.path.exists(self.buildout_prefix)): | and os.path.exists(self.buildout_prefix)): | ||
log.info('Getting installed file lists') | log.info('Getting installed file lists') | ||
parts.extend(self.get_installed_files(tmp_path)) | parts.extend(self.get_installed_files(tmp_path)) | ||
except: | except: | ||
log.error('Compilation error. The package is left as is at %s where ' | log.error('Compilation error. The package is left as is at %s where ' | ||
'you can inspect what went wrong' % os.getcwd()) | 'you can inspect what went wrong' % os.getcwd()) | ||
# Delete shared directory if not correctly installed | |||
if self.options.get('shared'): | |||
shutil.rmtree(self.options['shared']) | |||
raise | raise | ||
finally: | finally: | ||
os.chdir(current_dir) | os.chdir(current_dir) | ||
shutil.rmtree(tmp_path) | # If in shared mode and have error during installed, tmp_path was already deleted | ||
if os.path.isdir(tmp_path): | |||
shutil.rmtree(tmp_path) | |||
# Check promises | # Check promises | ||
self.check_promises(log) | self.check_promises(log) | ||
... | @@ -395,7 +441,7 @@ class Recipe(object): | ... | @@ -395,7 +441,7 @@ class Recipe(object): |
shutil.rmtree(compile_dir) | shutil.rmtree(compile_dir) | ||
del self.options['compile-directory'] | del self.options['compile-directory'] | ||
if self.options['share'] == '': | if self.options['shared'] == '': | ||
parts.append(self.options['default-location']) | parts.append(self.options['default-location']) | ||
self.fix_shebang(self.options['default-location']) | self.fix_shebang(self.options['default-location']) | ||
... | ... |