| Index: recipe_engine/package.py
|
| diff --git a/recipe_engine/package.py b/recipe_engine/package.py
|
| index 34b8727fac93ff63be81814436c7824dbc59baa5..69a2f6d232453d742b1cf93d429af7ea5d4f20bf 100644
|
| --- a/recipe_engine/package.py
|
| +++ b/recipe_engine/package.py
|
| @@ -10,6 +10,7 @@ import functools
|
| import itertools
|
| import logging
|
| import os
|
| +import re
|
| import subprocess
|
| import sys
|
| import tempfile
|
| @@ -355,18 +356,28 @@ class Package(object):
|
|
|
| This is accessed by loader.py through RecipeDeps.get_package.
|
| """
|
| - def __init__(self, name, repo_spec, deps, recipes_dir):
|
| + def __init__(self, name, repo_spec, deps, repo_root, relative_recipes_dir):
|
| self.name = name
|
| self.repo_spec = repo_spec
|
| self.deps = deps
|
| - self.recipes_dir = recipes_dir
|
| + self.relative_recipes_dir = relative_recipes_dir
|
| + self._repo_root = repo_root
|
| +
|
| + @property
|
| + def recipes_dir(self):
|
| + """Returns the root of the recipes area (the part containing recipes/ and
|
| + recipe_modules/
|
| + """
|
| + return os.path.join(self._repo_root, self.relative_recipes_dir)
|
|
|
| @property
|
| def recipe_dirs(self):
|
| + """Returns a collection of directories containing recipes."""
|
| return [os.path.join(self.recipes_dir, 'recipes')]
|
|
|
| @property
|
| def module_dirs(self):
|
| + """Returns a collection of directories containing recipe modules."""
|
| return [os.path.join(self.recipes_dir, 'recipe_modules')]
|
|
|
| def find_dep(self, dep_name):
|
| @@ -386,6 +397,43 @@ class Package(object):
|
| if _is_recipe_module_dir(subpath):
|
| yield subpath
|
|
|
| + def all_files(self, context, seen=None):
|
| + """Returns a generator listing all file paths this package needs to run."""
|
| + if seen is None:
|
| + seen = set()
|
| + if self in seen:
|
| + return
|
| + seen.add(self)
|
| +
|
| + EXCLUDE = re.compile('\.pyc$') # pycs are not portable
|
| +
|
| + dirs = list(self.recipe_dirs) + list(self.module_dirs)
|
| + recipes_extra = os.path.join(self.recipes_dir, 'recipes.extra')
|
| + if os.path.exists(recipes_extra):
|
| + yield recipes_extra
|
| + with open(recipes_extra, 'r') as fh:
|
| + for fname in itertools.imap(self._normalize_extra_line, fh.readlines()):
|
| + f = os.path.join(self.recipes_dir, fname)
|
| + if os.path.isdir(f):
|
| + dirs.append(f)
|
| + else:
|
| + yield f
|
| +
|
| + yield self.repo_spec.proto_file(context).path
|
| + yield os.path.join(self.recipes_dir, 'recipes.py')
|
| + for basedir in dirs:
|
| + for root, dirs, files in os.walk(basedir):
|
| + for fname in files:
|
| + if not EXCLUDE.search(fname):
|
| + yield os.path.join(root, fname)
|
| +
|
| + for dep in self.deps.values():
|
| + for f in dep.all_files(context, seen):
|
| + yield f
|
| +
|
| + def _normalize_extra_line(self, line):
|
| + return re.sub(r'#.*', '', line).replace('/', os.sep).strip()
|
| +
|
|
|
| class PackageSpec(object):
|
| API_VERSION = 1
|
| @@ -553,6 +601,7 @@ class PackageDeps(object):
|
| self._context = context
|
| self._packages = {}
|
| self._overrides = overrides or {}
|
| + self._root_package = None
|
|
|
| @classmethod
|
| def create(cls, repo_root, proto_file, allow_fetch=False, overrides=None):
|
| @@ -573,7 +622,8 @@ class PackageDeps(object):
|
| for project_id, path in overrides.iteritems()}
|
| package_deps = cls(context, overrides=overrides)
|
|
|
| - package_deps._create_package(RootRepoSpec(proto_file), allow_fetch)
|
| + package_deps._root_package = package_deps._create_package(
|
| + RootRepoSpec(proto_file), allow_fetch)
|
| return package_deps
|
|
|
| def _create_package(self, repo_spec, allow_fetch):
|
| @@ -610,8 +660,8 @@ class PackageDeps(object):
|
|
|
| package = Package(
|
| project_id, repo_spec, deps,
|
| - os.path.join(repo_spec.repo_root(self._context),
|
| - package_spec.recipes_path))
|
| + repo_root=repo_spec.repo_root(self._context),
|
| + relative_recipes_dir=package_spec.recipes_path)
|
|
|
| self._packages[project_id] = package
|
| return package
|
| @@ -622,6 +672,11 @@ class PackageDeps(object):
|
| return self._packages[package_id]
|
|
|
| @property
|
| + def root_package(self):
|
| + """Returns the Package at the front of the dependency graph."""
|
| + return self._root_package
|
| +
|
| + @property
|
| def packages(self):
|
| for p in self._packages.values():
|
| yield p
|
|
|