diskimage-builder/diskimage_builder/element_dependencies.py

230 lines
7.6 KiB
Python
Raw Normal View History

# Copyright 2013 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
import argparse
import collections
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
import errno
import logging
import os
import sys
import yaml
import diskimage_builder.logging_config
logger = logging.getLogger(__name__)
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
class Element(object):
"""An element"""
def __init__(self, name, path):
"""A new element
:param name: The element name
:param path: Full path to element. element-deps and
element-provides files will be parsed
"""
self.name = name
self.path = path
self.provides = set()
self.depends = set()
# read the provides & depends files for this element into a
# set; if the element has them.
provides = os.path.join(path, 'element-provides')
depends = os.path.join(path, 'element-deps')
try:
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
with open(provides) as p:
self.provides = set([line.strip() for line in p])
except IOError as e:
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
if e.errno == errno.ENOENT:
pass
else:
raise
try:
with open(depends) as d:
self.depends = set([line.strip() for line in d])
except IOError as e:
if e.errno == errno.ENOENT:
pass
else:
raise
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
logger.debug("New element : %s", str(self))
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
def __str__(self):
return '%s p:<%s> d:<%s>' % (self.name,
','.join(self.provides),
','.join(self.depends))
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
def get_elements_dir():
if not os.environ.get('ELEMENTS_PATH'):
raise Exception("$ELEMENTS_PATH must be set.")
return os.environ['ELEMENTS_PATH']
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
def expand_dependencies(user_elements, all_elements):
"""Expand user requested elements using element-deps files.
Arguments:
:param user_elements: iterable enumerating the elements a user requested
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
:param all_elements: Element object dictionary from find_all_elements
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
:return: a set containing the names of user_elements and all
dependent elements including any transitive dependencies.
"""
final_elements = set(user_elements)
check_queue = collections.deque(user_elements)
provided = set()
provided_by = collections.defaultdict(list)
while check_queue:
# bug #1303911 - run through the provided elements first to avoid
# adding unwanted dependencies and looking for virtual elements
element = check_queue.popleft()
if element in provided:
continue
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
elif element not in all_elements:
logger.error("Element '%s' not found", element)
sys.exit(1)
element_obj = all_elements[element]
element_deps = element_obj.depends
element_provides = element_obj.provides
# save which elements provide another element for potential
# error message
for provide in element_provides:
provided_by[provide].append(element)
provided.update(element_provides)
check_queue.extend(element_deps - (final_elements | provided))
final_elements.update(element_deps)
if "operating-system" not in provided:
logger.error(
"Please include an operating system element.")
sys.exit(-1)
conflicts = set(user_elements) & provided
if conflicts:
logger.error(
"The following elements are already provided by another element")
for element in conflicts:
logger.error("%s : already provided by %s" %
(element, provided_by[element]))
sys.exit(-1)
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
return final_elements - provided
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
def find_all_elements(paths=None):
"""Build a dictionary Element() objects
Walk ELEMENTS_PATH and find all elements. Make an Element object
for each element we wish to consider. Note we process overrides
such that elements specified earlier in the ELEMENTS_PATH override
those seen later.
:param paths: A list of paths to find elements in. If None will
use ELEMENTS_PATH
:return: a dictionary of all elements
"""
all_elements = {}
# note we process the later entries *first*, so that earlier
# entries will override later ones. i.e. with
# ELEMENTS_PATH=path1:path2:path3
# we want the elements in "path1" to override "path3"
if not paths:
paths = reversed(get_elements_dir().split(':'))
for path in paths:
if not os.path.isdir(path):
logger.error("ELEMENT_PATH entry '%s' is not a directory", path)
sys.exit(1)
# In words : make a list of directories in "path". Since an
# element is a directory, this is our list of elements.
elements = [os.path.realpath(os.path.join(path, f))
for f in os.listdir(path)
if os.path.isdir(os.path.join(path, f))]
for element in elements:
# the element name is the last part of the full path in
# element (these are all directories, we know that from
# above)
name = os.path.basename(element)
new_element = Element(name, element)
if name in all_elements:
logger.warning("Element <%s> overrides <%s>",
new_element.path, all_elements[name].path)
all_elements[name] = new_element
return all_elements
def main():
diskimage_builder.logging_config.setup()
parser = argparse.ArgumentParser()
parser.add_argument('elements', nargs='+',
help='display dependencies of the given elements')
parser.add_argument('--env', '-e', action='store_true',
default=False,
help=('Output eval-able bash strings for '
'IMAGE_ELEMENT variables'))
args = parser.parse_args(sys.argv[1:])
Making element overriding explicit This is a re-factor of element_dependencies to achieve two things -- centralising override policy and storing path names. Firstly we want to make the override policy for elements completely explicit. Currently, elements that wish to copy parts of other elements walk ELEMENTS_PATH themselves and look for elements in IMAGE_ELEMENT. How they handle duplicate elements can differ, leading to inconsistent behaviour. We introduce logic in element-info to find elements in each of the directories in ELEMENT_PATHS in *reverse* order -- that is to say, earlier entries in the paths will overwrite later ones. For example ELEMENT_PATHS=foo:bar:baz will mean that "foo/element" will override "baz/element", since "foo" is first. This should be sane to anyone familiar with $PATH. Documentation is clarified around this point and a test-case is added. The second thing is that we want to keep the complete path of the elements we have chosen. We want the aforementioned elements that walk the element list to use these canonical paths to pickup files; this way they don't need to make local decisions about element overrides, but can simply iterate a list and copy/merge files if they exist. A follow-on change (I7092e1845942f249175933d67ab121188f3511fd) will expose this data in a separate variable that can be parsed by elements (a further follow-on I0a64b45e9f2cfa28e84b2859d76b065a6c4590f0 modifies the elements to use this information). Thus this does not change the status-quo -- elements that are walking ELEMENTS_PATH themselves and can/will continue doing that. Change-Id: I2a29861c67de2d25c595cb35d850e92807d26ac6
2016-06-28 05:41:50 +00:00
all_elements = find_all_elements()
elements = expand_dependencies(args.elements, all_elements)
if args.env:
# first the "legacy" environment variable that just lists the
# elements
print("export IMAGE_ELEMENT='%s'" % ' '.join(elements))
# Then YAML
output = {}
for element in elements:
output[element] = all_elements[element].path
print("export IMAGE_ELEMENT_YAML='%s'" % yaml.safe_dump(output))
# Then bash array. Unfortunately, bash can't export array
# variables. So we take a compromise and produce an exported
# function that outputs the string to re-create the array.
# You can then simply do
# eval declare -A element_array=$(get_image_element_array)
# and you have it.
output = ""
for element in elements:
output += '[%s]=%s ' % (element, all_elements[element].path)
print("function get_image_element_array {\n"
" echo \"%s\"\n"
"};\n"
"export -f get_image_element_array;" % output)
else:
print(' '.join(elements))
return 0
if __name__ == "__main__":
main()