2013-01-22 01:35:31 +00:00
|
|
|
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
|
|
|
# All Rights Reserved.
|
|
|
|
#
|
|
|
|
# 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.
|
|
|
|
|
|
|
|
import argparse
|
2014-04-07 16:59:33 +00:00
|
|
|
import collections
|
2013-01-22 01:35:31 +00:00
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
|
|
|
|
|
|
|
|
def get_elements_dir():
|
2013-02-25 09:17:32 +00:00
|
|
|
if not os.environ.get('ELEMENTS_PATH'):
|
|
|
|
raise Exception("$ELEMENTS_PATH must be set.")
|
|
|
|
return os.environ['ELEMENTS_PATH']
|
2013-01-22 01:35:31 +00:00
|
|
|
|
|
|
|
|
2014-03-10 13:46:44 +00:00
|
|
|
def _get_set(element, fname, elements_dir=None):
|
2013-01-22 01:35:31 +00:00
|
|
|
if elements_dir is None:
|
|
|
|
elements_dir = get_elements_dir()
|
|
|
|
|
2013-02-25 09:17:32 +00:00
|
|
|
for path in elements_dir.split(':'):
|
2014-03-10 13:46:44 +00:00
|
|
|
element_deps_path = (os.path.join(path, element, fname))
|
2013-02-25 09:17:32 +00:00
|
|
|
try:
|
|
|
|
with open(element_deps_path) as element_deps:
|
|
|
|
return set([line.strip() for line in element_deps])
|
|
|
|
except IOError as e:
|
|
|
|
if os.path.exists(os.path.join(path, element)) and e.errno == 2:
|
|
|
|
return set()
|
|
|
|
if e.errno == 2:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
raise
|
|
|
|
|
2013-06-19 20:23:27 +00:00
|
|
|
sys.stderr.write("ERROR: Element '%s' not found in '%s'\n" %
|
|
|
|
(element, elements_dir))
|
2013-02-25 09:17:32 +00:00
|
|
|
exit(-1)
|
2013-01-22 01:35:31 +00:00
|
|
|
|
|
|
|
|
2014-03-10 13:46:44 +00:00
|
|
|
def provides(element, elements_dir=None):
|
|
|
|
"""Return the set of elements provided by the specified element.
|
|
|
|
|
|
|
|
:param element: name of a single element
|
|
|
|
:param elements_dir: the elements dir to read from. If not supplied,
|
|
|
|
inferred by calling get_elements_dir().
|
|
|
|
|
|
|
|
:return: a set just containing all elements that the specified element
|
|
|
|
provides.
|
|
|
|
"""
|
|
|
|
return _get_set(element, 'element-provides', elements_dir)
|
|
|
|
|
|
|
|
|
|
|
|
def dependencies(element, elements_dir=None):
|
|
|
|
"""Return the non-transitive set of dependencies for a single element.
|
|
|
|
|
|
|
|
:param element: name of a single element
|
|
|
|
:param elements_dir: the elements dir to read from. If not supplied,
|
|
|
|
inferred by calling get_elements_dir().
|
|
|
|
|
|
|
|
:return: a set just containing all elements that the specified element
|
|
|
|
depends on.
|
|
|
|
"""
|
|
|
|
return _get_set(element, 'element-deps', elements_dir)
|
|
|
|
|
|
|
|
|
2013-01-22 01:35:31 +00:00
|
|
|
def expand_dependencies(user_elements, elements_dir=None):
|
2013-07-27 02:32:01 +00:00
|
|
|
"""Expand user requested elements using element-deps files.
|
2013-01-22 01:35:31 +00:00
|
|
|
|
|
|
|
Arguments:
|
|
|
|
:param user_elements: iterable enumerating the elements a user requested
|
|
|
|
:param elements_dir: the elements dir to read from. Passed directly to
|
|
|
|
dependencies()
|
|
|
|
|
|
|
|
:return: a set containing user_elements and all dependent elements
|
|
|
|
including any transitive dependencies.
|
|
|
|
"""
|
|
|
|
final_elements = set(user_elements)
|
2014-04-07 16:59:33 +00:00
|
|
|
check_queue = collections.deque(user_elements)
|
2014-03-10 13:46:44 +00:00
|
|
|
provided = set()
|
2013-01-22 01:35:31 +00:00
|
|
|
|
|
|
|
while check_queue:
|
2014-04-07 16:59:33 +00:00
|
|
|
# bug #1303911 - run through the provided elements first to avoid
|
|
|
|
# adding unwanted dependencies and looking for virtual elements
|
|
|
|
element = check_queue.popleft()
|
2014-03-10 13:46:44 +00:00
|
|
|
if element in provided:
|
|
|
|
continue
|
2013-01-22 01:35:31 +00:00
|
|
|
deps = dependencies(element, elements_dir)
|
2014-03-10 13:46:44 +00:00
|
|
|
provided.update(provides(element, elements_dir))
|
|
|
|
check_queue.extend(deps - (final_elements | provided))
|
2013-01-22 01:35:31 +00:00
|
|
|
final_elements.update(deps)
|
|
|
|
|
2014-03-10 13:46:44 +00:00
|
|
|
conflicts = set(user_elements) & provided
|
|
|
|
if conflicts:
|
|
|
|
sys.stderr.write("ERROR: Following elements were explicitly required "
|
|
|
|
"but are provided by other included elements: %s\n" %
|
|
|
|
", ".join(conflicts))
|
|
|
|
exit(-1)
|
|
|
|
return final_elements - provided
|
2013-01-22 01:35:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
def main(argv):
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('elements', nargs='+',
|
|
|
|
help='elements to inspect')
|
|
|
|
parser.add_argument('--expand-dependencies', '-d', action='store_true',
|
|
|
|
default=False,
|
|
|
|
help='Print expanded dependencies of all args')
|
|
|
|
|
|
|
|
args = parser.parse_args(argv[1:])
|
|
|
|
|
|
|
|
if args.expand_dependencies:
|
|
|
|
print(' '.join(expand_dependencies(args.elements)))
|
|
|
|
return 0
|
|
|
|
|
|
|
|
sys.stderr.write("ERROR: please choose an option.\n")
|
|
|
|
return -1
|