diff options
author | André Erdmann <dywi@mailerd.de> | 2012-06-19 20:16:01 +0200 |
---|---|---|
committer | André Erdmann <dywi@mailerd.de> | 2012-06-19 20:16:01 +0200 |
commit | 2afa2439d20402b7cb7af0ca12edd5bb0c269bdc (patch) | |
tree | 126fe6c1ab0725917d1681ed43cfa65e99859922 /roverlay | |
parent | overlay creation (diff) | |
download | R_overlay-2afa2439d20402b7cb7af0ca12edd5bb0c269bdc.tar.gz R_overlay-2afa2439d20402b7cb7af0ca12edd5bb0c269bdc.tar.bz2 R_overlay-2afa2439d20402b7cb7af0ca12edd5bb0c269bdc.zip |
roverlay, 2012-06-19
* added Manifest creation to the overlay module
* code moved/adjusted for R package -> overlay conversion
* removed unnecessary code in ebuild module
new file: roverlay/ebuild/__init__.py
renamed: roverlay/portage/ebuild.py -> roverlay/ebuild/construction.py
new file: roverlay/ebuild/creation.py
renamed: roverlay/portage/manifest.py -> roverlay/manifest/__init__.py
renamed: roverlay/portage/manifesthelpers.py -> roverlay/manifest/helpers.py
renamed: roverlay/portage/metadata/creation.py -> roverlay/metadata/__init__.py
renamed: roverlay/portage/metadata/abstractnodes.py -> roverlay/metadata/abstractnodes.py
renamed: roverlay/portage/metadata/nodes.py -> roverlay/metadata/nodes.py
renamed: roverlay/portage/overlay/root.py -> roverlay/overlay/__init__.py
renamed: roverlay/portage/overlay/category.py -> roverlay/overlay/category.py
renamed: roverlay/portage/overlay/package.py -> roverlay/overlay/package.py
renamed: roverlay/portage/packageinfo.py -> roverlay/packageinfo.py
deleted: roverlay/portage/__init__.py
deleted: roverlay/portage/ebuildcreator.py
deleted: roverlay/portage/ebuildjob.py
deleted: roverlay/portage/metadata/__init__.py
deleted: roverlay/portage/overlay/__init__.py
new file: roverlay/static/__init__.py
new file: roverlay/static/depres.py
Diffstat (limited to 'roverlay')
-rw-r--r-- | roverlay/ebuild/__init__.py | 38 | ||||
-rw-r--r-- | roverlay/ebuild/construction.py (renamed from roverlay/portage/ebuild.py) | 170 | ||||
-rw-r--r-- | roverlay/ebuild/creation.py | 203 | ||||
-rw-r--r-- | roverlay/manifest/__init__.py (renamed from roverlay/portage/manifest.py) | 7 | ||||
-rw-r--r-- | roverlay/manifest/helpers.py (renamed from roverlay/portage/manifesthelpers.py) | 0 | ||||
-rw-r--r-- | roverlay/metadata/__init__.py (renamed from roverlay/portage/metadata/creation.py) | 15 | ||||
-rw-r--r-- | roverlay/metadata/abstractnodes.py (renamed from roverlay/portage/metadata/abstractnodes.py) | 0 | ||||
-rw-r--r-- | roverlay/metadata/nodes.py (renamed from roverlay/portage/metadata/nodes.py) | 2 | ||||
-rw-r--r-- | roverlay/overlay/__init__.py (renamed from roverlay/portage/overlay/root.py) | 26 | ||||
-rw-r--r-- | roverlay/overlay/category.py (renamed from roverlay/portage/overlay/category.py) | 72 | ||||
-rw-r--r-- | roverlay/overlay/package.py (renamed from roverlay/portage/overlay/package.py) | 165 | ||||
-rw-r--r-- | roverlay/packageinfo.py (renamed from roverlay/portage/packageinfo.py) | 39 | ||||
-rw-r--r-- | roverlay/portage/__init__.py | 0 | ||||
-rw-r--r-- | roverlay/portage/ebuildcreator.py | 184 | ||||
-rw-r--r-- | roverlay/portage/ebuildjob.py | 333 | ||||
-rw-r--r-- | roverlay/portage/metadata/__init__.py | 0 | ||||
-rw-r--r-- | roverlay/portage/overlay/__init__.py | 0 | ||||
-rw-r--r-- | roverlay/static/__init__.py | 5 | ||||
-rw-r--r-- | roverlay/static/depres.py | 29 |
19 files changed, 510 insertions, 778 deletions
diff --git a/roverlay/ebuild/__init__.py b/roverlay/ebuild/__init__.py new file mode 100644 index 0000000..259a352 --- /dev/null +++ b/roverlay/ebuild/__init__.py @@ -0,0 +1,38 @@ +# R Overlay -- ebuild creation, ebuild class +# Copyright 2006-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +class Ebuild ( object ): + + def __init__ ( self, content, header=None ): + """Initializes an Ebuild that has text content and optionally a + header (text, too). + + arguments: + * content -- + * header -- + """ + self.content = content + self.header = header + # --- end of __init__ (...) --- + + def write ( self, fh, header=None ): + """Write the ebuild into a file-like object. + + arguments: + * fh -- file handle + """ + if not self.content: + raise Exception ( "ebuild is empty!" ) + + if header is None: + if not self.header is None: + fh.write ( self.header ) + fh.write ( '\n' ) + else: + fh.write ( header ) + fh.write ( '\n' ) + + fh.write ( self.content ) + fh.write ( '\n' ) + # --- end of write_fh (...) --- diff --git a/roverlay/portage/ebuild.py b/roverlay/ebuild/construction.py index a435f5c..ed5bca5 100644 --- a/roverlay/portage/ebuild.py +++ b/roverlay/ebuild/construction.py @@ -6,10 +6,13 @@ import copy import roverlay.config -from roverlay.util import shorten_str +from roverlay.util import shorten_str +from roverlay.ebuild import Ebuild -class Ebuild ( object ): +class EbuildConstruction ( object ): + """Class that helps to create Ebuild objects.""" + EBUILD_INDENT = roverlay.config.get ( 'EBUILD.indent', '\t' ) ADD_REMAP = { @@ -27,80 +30,37 @@ class Ebuild ( object ): } def __init__ ( self, logger ): - """Initializes an Ebuild. - This is an abstraction layer between the verified + calculated data - and the ebuild data, which can be written into a file / stdout / stdin. - Most functions here assume that everything is fine when it reaches them. + """Initializes an EbuildConstruction object. arguments: - * logger -- logger for this Ebuild + * logger -- """ - self.logger = logger - # elements in ebuild_data are either a str or a list of str - self._data = dict () - self._ebuild_lines = None - self._ebuild_name = None self.has_rsuggests = False + # elements in data are either a str or a list of str + self._data = dict () # --- end of __init__ (...) --- - def cleanup ( self ): - """Removes stored data if ebuild_lines have already been calculated. - This saves some memory but makes this Ebuild read-only. - """ - if self._ebuild_lines: - # determine the ebuild name first - self._ebuild_name = self.suggest_name() - del self._data - self._data = None - - # --- end of cleanup (...) --- - - def prepare ( self, force_update=False, cleanup_after=False ): - """Tells this Ebuild to create ebuild lines. - - arguments: - * force_update -- create ebuild lines if they exist; defaults to False - and ignored if this Ebuild has been cleaned up - * cleanup_after -- run cleanup() after successful creation - - Returns True if ebuild_lines have been created or if they exist and - an update has not been enforced. Else returns False. - """ - if self._ebuild_lines and not force_update: - return True - elif self._data: - self._ebuild_lines = self._make_ebuild_lines() - if self._ebuild_lines: - if cleanup_after: self.cleanup() - return True - elif self._ebuild_lines: - # self._data is None - return True - - return False - - # --- end of prepare (...) --- - - def has_ebuild ( self ): - """Returns True if this object has ebuild text lines else False.""" - return bool ( self._ebuild_lines ) - # --- end of has_ebuild (...) --- + def get_ebuild ( self ): + """Creates and returns an Ebuild.""" + lines = '\n'.join ( self._make_ebuild_lines() ) + return Ebuild ( lines, header=None ) + # --- end of get_ebuild (...) --- def add ( self, key, value, append=True ): - """Adds data to this Ebuild. + """Adds data. arguments: - * key -- identifier of the data (e.g. DEPEND). - May be remapped (e.g. merging 'Title' and 'Description') - or even refused here - * value -- + * key -- identifier of the data (e.g. DEPEND). + May be remapped (e.g. merging 'Title' and 'Description') + or even refused here. + * value -- * append -- whether to append values or overwrite existing ones, defaults to True. - raises: Exception when ebuild data are readonly + returns: None (implicit) """ if self._data is None: # -- todo @@ -125,96 +85,8 @@ class Ebuild ( object ): # --- end of add (...) --- - def write ( self, file_to_write ): - """Writes an ebuild file. - - arguments: - * file_to_write -- path to the file that should be written - """ - # prepare ebuild lines and open file handle after that - if self.prepare ( False, False ): - try: - fh = open ( file_to_write, 'w' ) - self.show ( fh ) - fh.close() - del fh - except IOError as err: - self.logger.exception ( err ) - raise - - else: - self.logger.warning ( - 'Cannot write ebuild - it\'s empty! ' - '(check with has_ebuild() before calling this method.)' - ) - - # --- end of write (...) --- - - def show ( self, file_handle ): - """Prints the ebuild content into a file_handle. - - arguments: - file_handle -- object that has a writelines ( list ) method, e.g. file. - - Returns True if writing was successful, else False. - """ - if self.prepare ( False, False ): - lines = [ line + "\n" for line in self._ebuild_lines ] - file_handle.writelines ( lines ) - del lines - return True - else: - return False - - # --- end of show (...) --- - - def suggest_dir_name ( self ): - """Suggests a direcory name for this Ebuild.""" - if self._data is None: - return self._ebuild_name.partition ( '-' ) [0] - elif 'pkg_name' in self._data: - return self._data ['pkg_name'] - else: - return self.suggest_name().partition ( '-' ) [0] - # --- end of suggest_dir_name (...) --- - - def suggest_name ( self, fallback_name='' ): - """Suggests a file name for the ebuild. This is calculated using - pkg_name/version/revision. Returns a fallback_name if this is not - possible. - - arguments: - fallback_name -- name to return if no suggestion available, - defaults to empty string - """ - - if self._ebuild_name: - return self._ebuild_name - elif not self._data is None and 'pkg_name' in self._data: - name_components = [ self._data ['pkg_name'] ] - - if 'pkg_version' in self._data: - name_components.append ( self._data ['pkg_version'] ) - else: - # default ver - name_components.append ( '1.0' ) - - if 'pkg_revision' in self._data: - rev = self._data ['pkg_revision'] - - # omit rev == 0 and invalid revisions - if isinstance ( rev, int ) and rev > 0: - name_components.append ( 'r%i' % rev ) - - return '-'.join ( name_components ) - - else: - return fallback_name - - # --- end of suggest_name (...) --- - def _make_ebuild_lines ( self ): - """Creates text lines for this Ebuild. + """Creates text lines for the Ebuild. It assumes that enough data to do this are available. Exceptions (KeyError, NameError, ...) are passed if that's not the case. """ diff --git a/roverlay/ebuild/creation.py b/roverlay/ebuild/creation.py new file mode 100644 index 0000000..eed54b2 --- /dev/null +++ b/roverlay/ebuild/creation.py @@ -0,0 +1,203 @@ +# R Overlay -- ebuild creation, "job" module +# Copyright 2006-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +import logging + +import roverlay.static.depres + +from roverlay.ebuild.construction import EbuildConstruction +from roverlay.rpackage.descriptionreader import DescriptionReader + +# move this to const / config +DEPENDENCY_FIELDS = { + 'R_SUGGESTS' : [ 'Suggests' ], + 'DEPENDS' : [ 'Depends', 'Imports' ], + 'RDEPENDS' : [ 'LinkingTo', 'SystemRequirements' ] +} + +LOGGER = logging.getLogger ( 'EbuildCreation' ) + +class EbuildCreation ( object ): + + def __init__ ( self, package_info, depres_channel_spawner=None ): + + self.logger = LOGGER.getChild ( package_info ['name'] ) + self.package_info = package_info + + if depres_channel_spawner is None: + self.request_resolver = roverlay.static.depres.get_ebuild_channel + else: + self.request_resolver = depres_channel_spawner + + # > 0 busy/working; 0 == done,success; < 0 done,fail + self.status = 1 + + self.package_info.set_readonly() + # --- end of __init__ (...) --- + + def done() : return self.status < 1 + def busy() : return self.status > 0 + def success() : return self.status == 0 + def fail() : return self.status < 0 + + + def _resolve_dependencies ( self, ebuilder ): + if self.request_resolver is None: + self.logger.warning ( + "Cannot resolve dependencies, no resolver available!" + ) + return True + + res = None + # -- end pre func block -- + + def init_channels(): + # collect dep strings and initialize resolver channels + desc = self.package_info ['desc_data'] + channels = dict() + + def get_resolver ( dependency_type ): + if dependency_type not in channels: + channels [dependency_type] = self.request_resolver ( + dependency_type, + self.logger + ) + return channels [dependency_type] + # --- end of get_resolver (...) --- + + dep_type = desc_field = None + + for dep_type in DEPENDENCY_FIELDS: + resolver = None + + for desc_field in DEPENDENCY_FIELDS [dep_type]: + if desc_field in desc: + if not resolver: + resolver = get_resolver ( dep_type ) + + if isinstance ( desc [desc_field], str ): + resolver.add_dependency ( desc [desc_field] ) + elif hasattr ( desc [desc_field], '__iter__' ): + resolver.add_dependencies ( desc [desc_field] ) + else: + logger.warning ( + "Cannot add dependency '%s'." % desc [desc_field] + ) + # -- if desc_field + # -- for desc_field + # -- for dep_type + return channels + # --- end of init_resolvers (...) --- + + def try_resolve(): + for r in res.values(): + if r.satisfy_request() is None: + return False + return True + # --- end of try_resolve (...) --- + + # TODO + # replace try_resolve with + # False in ( r.satisfy_request() for r in res.values() ) + # ? + res = init_channels() + if not res: return True + success = False + + + if try_resolve(): + for dep_type, resolver in res.items(): + deplist = list ( filter ( None, resolver.collect_dependencies() ) ) + + if deplist is None: + ## FIXME: false positive: "empty" channel + raise Exception ( + 'dep_resolver is broken: ' + 'lookup() returns None but satisfy_request() says ok.' + ) + elif hasattr ( deplist, '__iter__' ): + # add dependencies in no_append/override mode + self.logger.debug ( "adding %s to %s", deplist, dep_type ) + ebuilder.add ( dep_type, deplist, False ) + else: + raise Exception ( "dep_resolver is broken: iterable expected!" ) + # -- for dep_type,.. + + success = True + + # tell the dep resolver channels that we're done + for r in res.values(): r.close() + return success + # --- end of resolve_dependencies (...) --- + + def _make_ebuild ( self ): + desc = self.package_info ['desc_data'] + if desc is None: + self.logger ( + 'desc empty- cannot create an ebuild for this package.' + ) + return None + + ebuilder = EbuildConstruction ( self.logger ) + + have_desc = False + + if 'Title' in desc: + ebuilder.add ( 'DESCRIPTION', desc ['Title'] ) + have_desc = True + + if 'Description' in desc: + ebuilder.add ( + 'DESCRIPTION', + ( '// ' if have_description else '' ) + desc ['Description'] + ) + + + ebuilder.add ( 'SRC_URI', self.package_info ['package_url'] ) + + if self._resolve_dependencies(): + return ( ebuilder.get_ebuild(), ebuilder.has_rsuggests ) + + return None + # --- end of _make_ebuild (...) --- + + def run ( self ): + if self.status < 1: + raise Exception ( "Cannot run again." ) + + try: + if self.package_info.get ( 'desc_data', + fallback_value=None, do_fallback=True ) is None: + + logging.warning ( 'Reading description data now.' ) + reader = DescriptionReader ( + self.package_info, + logger=self.logger, + read_now=True + ) + self.package_info.set_writeable() + self.package_info.update ( + desc_data=reader.get_desc ( run_if_unset=False ) + ) + del reader + # -- if + + self.package_info.set_readonly() + + ebuild_info = self._make_ebuild() + if ebuild_info is None: + self.status = -1 + else: + self.package_info.set_writeable() + self.package_info.update ( + ebuild=ebuild_info [0], + suggests=ebuild_info [1] + ) + self.package_info.set_readonly() + self.status = 0 + except Exception as e: + # log this and set status to fail + self.status = -10 + self.logger.exception ( e ) + # --- end of run (...) --- diff --git a/roverlay/portage/manifest.py b/roverlay/manifest/__init__.py index 79e241c..b95a855 100644 --- a/roverlay/portage/manifest.py +++ b/roverlay/manifest/__init__.py @@ -1,14 +1,11 @@ # R Overlay -- Manifest creation for ebuilds # Copyright 2006-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 - - import logging -import roverlay.portage.manifesthelpers +from roverlay.manifest import helpers -_MANIFEST_IMPLEMENTATION = \ - roverlay.portage.manifesthelpers.ExternalManifestCreation +_MANIFEST_IMPLEMENTATION = helpers.ExternalManifestCreation def create_manifest ( package_info, nofail=False ): diff --git a/roverlay/portage/manifesthelpers.py b/roverlay/manifest/helpers.py index e7a54eb..e7a54eb 100644 --- a/roverlay/portage/manifesthelpers.py +++ b/roverlay/manifest/helpers.py diff --git a/roverlay/portage/metadata/creation.py b/roverlay/metadata/__init__.py index d2f133c..82821bb 100644 --- a/roverlay/portage/metadata/creation.py +++ b/roverlay/metadata/__init__.py @@ -4,26 +4,27 @@ import roverlay.config -from roverlay.portage.metadata import nodes +from roverlay.metadata import nodes class MetadataJob ( object ): """R package description data -> metadata.xml interface.""" - def __init__ ( self, package_info, logger ): + def __init__ ( self, logger ): """Initializes a MetadataJob. arguments: - * package_info -- reserved for future usage - * logger -- logger to use (this instance won't call getChild) + (((* package_info -- reserved for future usage))) + * logger -- parent logger to use """ - self.logger = logger + self.logger = logger.getChild ( 'metadata' ) self._metadata = nodes.MetadataRoot() # reserved for future usage ("dominant ebuilds": when ebuildjobs # share one metadata instance etc.) self.package_info = None + self.filename = 'metadata.xml' # --- end of __init__ (...) --- - def update ( self, desc_data, package_info ): + def update ( self, package_info ): """Updates the metadata using the given description data. It's expected that this method is called when Ebuild creation is done. @@ -34,7 +35,7 @@ class MetadataJob ( object ): returns: None (implicit) """ - pass + desc_data = package_info ['desc_data'] mref = self._metadata diff --git a/roverlay/portage/metadata/abstractnodes.py b/roverlay/metadata/abstractnodes.py index 50c9f56..50c9f56 100644 --- a/roverlay/portage/metadata/abstractnodes.py +++ b/roverlay/metadata/abstractnodes.py diff --git a/roverlay/portage/metadata/nodes.py b/roverlay/metadata/nodes.py index 36bf22d..f35f8da 100644 --- a/roverlay/portage/metadata/nodes.py +++ b/roverlay/metadata/nodes.py @@ -3,7 +3,7 @@ # Distributed under the terms of the GNU General Public License v2 # import abstract nodes -from roverlay.portage.metadata.abstractnodes import \ +from roverlay.metadata.abstractnodes import \ MetadataNode, MetadataNodeNamedAccess, MetadataLeaf diff --git a/roverlay/portage/overlay/root.py b/roverlay/overlay/__init__.py index 086cab4..081f0b8 100644 --- a/roverlay/portage/overlay/root.py +++ b/roverlay/overlay/__init__.py @@ -9,7 +9,7 @@ import os from roverlay import config, util -from roverlay.portage.overlay.category import Category +from roverlay.overlay.category import Category DEFAULT_USE_DESC = '\n'.join ( [ 'byte-compile - enable byte compiling', @@ -95,16 +95,6 @@ class Overlay ( object ): ) . add ( package_info ) # --- end of add (...) --- - def ls ( self ): - """Returns a set of ebuilds/metadata stored in this overlay.""" - return frozenset ( - ( os.path.join ( n, c.ls() ) for n, c in self._categories.items() ) - ) - # --- end of ls (...) --- - - def __str__ ( self ): return '\n'.join ( self.ls() ) - # --- end of __str__ --- - def show ( self, **show_kw ): """Presents the ebuilds/metadata stored in this overlay. @@ -167,6 +157,20 @@ class Overlay ( object ): cat.generate_metadata ( **metadata_kw ) # --- end of generate_metadata (...) --- + def generate_manifest ( self, **manifest_kw ): + """Generates Manifest files for all ebuilds in this overlay that exist + physically/in filesystem. + Manifest files are automatically created when calling write(). + + arguments: + * **manifest_kw -- see PackageDir.generate_manifest(...) + + returns: None (implicit) + """ + for cat in self._categories.values(): + cat.generate_manifest ( **manifest_kw ) + # --- end of generate_manifest (...) --- + def _write_profiles_dir ( self, only_active_categories=True ): """Creates and updates the profiles/ dir. diff --git a/roverlay/portage/overlay/category.py b/roverlay/overlay/category.py index ff497f7..768f296 100644 --- a/roverlay/portage/overlay/category.py +++ b/roverlay/overlay/category.py @@ -5,14 +5,20 @@ import threading import os.path - -from roverlay.portage.overlay.package import PackageDir +from roverlay.overlay.package import PackageDir import roverlay.util class Category ( object ): def __init__ ( self, name, logger, directory ): + """Initializes a overlay/portage category (such as 'app-text', 'sci-R'). + + arguments: + * name -- name of the category + * logger -- parent logger + * directory -- filesystem location + """ self.logger = logger.getChild ( name ) self.name = name self._lock = threading.RLock() @@ -21,25 +27,20 @@ class Category ( object ): # --- end of __init__ (...) --- def empty ( self ): + """Returns True if this category contains 0 ebuilds.""" return \ len ( self._subdirs ) == 0 or \ not False in ( d.empty() for d in self._subdirs ) # --- end of empty (...) --- - def set_fs_location ( self, directory ): - self._lock.acquire() - self.physical_location = directory - - if not directory is None: - for pkg_name, pkg in self._subdirs.items(): - pkg.set_fs_location ( - os.path.join ( directory, pkg_name ) - ) + def add ( self, package_info ): + """Adds a package to this category. - self._lock.release() - # --- end of set_fs_location (...) --- + arguments: + * package_info -- - def add ( self, package_info ): + returns: None (implicit) + """ # TODO make keys available pkg_name = package_info ['name'] @@ -58,28 +59,47 @@ class Category ( object ): # --- end of add (...) --- def generate_metadata ( self, **metadata_kw ): + """Generates metadata for all packages in this category. + Metadata are automatically generated when calling write(). + + arguments: + * **metadata_kw -- see PackageDir.generate_metadata(...) + + returns: None (implicit) + """ for package in self._subdirs.values(): package.generate_metadata ( **metadata_kw ) # --- end of generate_metadata (...) --- + def generate_manifest ( self, **manifest_kw ): + """Generates Manifest files for all packages in this category. + Manifest files are automatically created when calling write(). + + arguments: + * **manifest_kw -- see PackageDir.generate_manifest(...) + + returns: None (implicit) + """ + for package in self._subdirs.values(): + package.generate_manifest ( **manifest_kw ) + # --- end of generate_manifest (...) --- + def show ( self, **show_kw ): + """Prints this category (its ebuild and metadata files). + + returns: None (implicit) + """ for package in self._subdirs.values(): package.show ( **show_kw ) # --- end of show (...) --- - def write ( self ): + def write ( self, **write_kw ): + """Writes this category to its filesystem location. + + returns: None (implicit) + """ for package in self._subdirs.values(): if package.physical_location and not package.empty(): roverlay.util.dodir ( package.physical_location ) - package.write() - + package.write ( **write_kw ) # --- end of write (...) --- - - def ls ( self ): - return frozenset ( - ( os.path.join ( n, p.ls() ) for n, p in self._subdirs.items() ) - ) - - def __str__ ( self ): return '\n'.join ( self.ls() ) - - diff --git a/roverlay/portage/overlay/package.py b/roverlay/overlay/package.py index 9fc0112..d43ec1f 100644 --- a/roverlay/portage/overlay/package.py +++ b/roverlay/overlay/package.py @@ -6,17 +6,22 @@ import threading import os.path import sys -from roverlay.portage.metadata.creation import MetadataJob +from roverlay.metadata import MetadataJob SUPPRESS_EXCEPTIONS = True class PackageDir ( object ): - # TODO: do Manifest creation here - def __init__ ( self, name, logger, directory ): + """Initializes a PackageDir which contains ebuilds, metadata and + a Manifest file. + + arguments: + * name -- name of the directory (${PN} in ebuilds) + * logger -- parent logger + * directory -- filesystem location of this PackageDir + """ self.logger = logger.getChild ( name ) - # Lock or RLock? (TODO) self._lock = threading.RLock() self._packages = dict() self._metadata = None @@ -24,12 +29,12 @@ class PackageDir ( object ): # --- end of __init__ (...) --- def empty ( self ): + """Returns True if no ebuilds stored, else False.""" return len ( self._packages ) == 0 - - def set_fs_location ( self, directory ): - self.physical_location = directory + # --- end of empty (...) --- def _get_metadata_filepath ( self ): + """Returns the path to the metadata file.""" return os.path.join ( '??' if self.physical_location is None else self.physical_location, self._metadata.filename @@ -37,6 +42,11 @@ class PackageDir ( object ): # --- end of _get_metadata_filepath (...) --- def _get_ebuild_filepath ( self, pvr ): + """Returns the path to the ebuild file. + + arguments: + * pvr -- version number with the revision (${PVR} in ebuilds) + """ filename = "%s-%s.ebuild" % ( self.name, pvr ) return os.path.join ( '??' if self.physical_location is None else self.physical_location, @@ -45,6 +55,12 @@ class PackageDir ( object ): # --- end of _get_ebuild_filepath (...) --- def write ( self ): + """Writes this directory to its (existent!) filesystem location. + + returns: None (implicit) + + raises: !! TODO + """ if self.physical_location is None: raise Exception ( "cannot write - no directory assigned!" ) @@ -53,6 +69,7 @@ class PackageDir ( object ): # mkdir not required here, overlay.Category does this + # write ebuilds for ver, p_info in self._packages.items(): fh = None try: @@ -61,40 +78,51 @@ class PackageDir ( object ): fh = open ( efile, 'w' ) ebuild.write ( fh ) + if fh: fh.close() # adjust owner/perm? TODO # chmod 0644 or 0444 # chown 250.250 + # this marks the package as 'written to fs' + # TODO update PackageInfo + p_info ['ebuild_filepath'] = efile + self.logger.info ( "Wrote ebuild %s." % efile ) except IOError as e: + if fh: fh.close() self.logger.error ( "Couldn't write ebuild %s." % efile ) self.logger.exception ( e ) - finally: - if fh: fh.close() - fh = None - + # write metadata fh = None try: mfile = self._get_metadata_filepath() fh = open ( mfile, 'w' ) self._metadata.write ( fh ) + if fh: fh.close() except IOError as e: + if fh: fh.close() self.logger.error ( "Failed to write metadata at %s." % mfile ) self.logger.exception ( e ) - finally: - if fh: fh.close() - del fh - # !! TODO write Manifest here + self.generate_manifest() self._lock.release() # --- end of write (...) --- def show ( self, stream=sys.stderr ): + """Prints this dir (the ebuilds and the metadata) into a stream. + + arguments: + * stream -- stream to use, defaults to sys.stderr + + returns: None (implicit) + + raises: !! TODO + """ self._lock.acquire() self._regen_metadata() @@ -115,23 +143,44 @@ class PackageDir ( object ): self._lock.release() + # --- end of show (...) --- - def _latest_package ( self ): - """Returns the package info with the highest version number.""" + def _latest_package ( self, pkg_filter=None, use_lock=False ): + """Returns the package info with the highest version number. + + arguments: + * pkg_filter -- either None or a callable, + None: do not filter packages + else: ignore package if it does not pass the filter + * use_lock -- if True: hold lock while searching + """ first = True retver = None retpkg = None - for p in self._packages.values(): - newver = p ['version'] - if first or newver > retver: - retver = newver - retpkg = p - first = False + if use_lock: self._lock.acquire() + for p in self._packages.values(): + if pkg_filter is None or pkg_filter ( p ): + newver = p ['version'] + if first or newver > retver: + retver = newver + retpkg = p + first = False + + if use_lock: self._lock.release() return retpkg # --- end of _latest_package (...) --- def add ( self, package_info ): + """Adds a package to this PackageDir. + + arguments: + * package_info -- + + returns: success as bool + + raises: Exception when ebuild already exists. + """ # !! p info key TODO shortver = package_info ['ebuild_verstr'] @@ -160,25 +209,38 @@ class PackageDir ( object ): self._packages [shortver] = package_info self._lock.release() + return True # --- end of add (...) --- def _regen_metadata ( self ): + """Regenerates the metadata.""" self.generate_metadata ( skip_if_existent=True, - use_all_packages=True, + use_all_packages=False, use_old_metadata=False ) + # --- end of _regen_metadata (...) --- def generate_metadata ( self, skip_if_existent=False, use_all_packages=False, use_old_metadata=False ): + """Creates metadata for this package. + + arguments: + * skip_if_existent -- do not create if metadata already exist + * use_all_packages -- TODO + * use_old_metadata -- TODO + """ + if use_old_metadata or use_all_packages: + raise Exception ( "using >1 package for metadata.xml is TODO!" ) + if skip_if_existent and not self._metadata is None: return self._lock.acquire() - if not use_old_metadata or self._metadata is None: + if self._metadata is None or not use_old_metadata: del self._metadata self._metadata = MetadataJob ( self.logger ) @@ -188,32 +250,41 @@ class PackageDir ( object ): else: self._metadata.update ( _latest_package() ) - self._lock.release() + # --- end of generate_metadata (...) --- - def _flist ( self ): - files = list() - if not self._metadata is None: - files.append ( self._metadata.filename ) - - for ver in self._packages: - files.append ( "%s-%s.ebuild" % ( self.name, ver ) ) - - return files - # --- end of _flist (...) --- - - def ls ( self ): - return frozenset ( self._flist() ) - # --- end of ls (...) --- + def generate_manifest ( self ): + """Generates the Manifest file for this package. - def lslong ( self ): - return frozenset ( ( os.path.join ( - '??' if self.physical_location is None else self.physical_location, - f - ) for f in self._flist() ) ) - # --- end of lslong (...) --- + expects: called in self.write(), after writing metadata/ebuilds - def __str__ ( self ): return '\n'.join ( self.ls() ) + returns: None (implicit) + raises: !! TODO + * Exception if not physical + """ + if self.physical_location is None: + raise Exception ( "no directory assigned." ) + + # it should be sufficient to call create_manifest for one ebuild, + # choosing the latest one here that exists in self.physical_location. + # + # metadata.xml's full path cannot be used for manifest creation here + # 'cause DISTDIR would be unknown + # + pkg_info_for_manifest = _latest_package ( + pkg_filter=lambda pkg : not pkg ['ebuild_filepath'] is None, + use_lock=True + ) + if pkg_info_for_manifest is None: + # ? FIXME + raise Exception ( + "No ebuild written so far! I really don't know what do to!" + ) + else: + # TODO: manifest creation interface is single threaded, + # may want to 'fix' this later + manifest.create_manifest ( pkg_info_for_manifest, nofail=False ) + # --- end of generate_manifest (...) --- diff --git a/roverlay/portage/packageinfo.py b/roverlay/packageinfo.py index 7ac4940..7a77ca0 100644 --- a/roverlay/portage/packageinfo.py +++ b/roverlay/packageinfo.py @@ -12,10 +12,12 @@ from roverlay import config, util LOGGER = logging.getLogger ( 'PackageInfo' ) VIRTUAL_KEYS = dict ( - DISTDIR = frozenset ( [ 'distdir', 'pkg_distdir' ] ), - EBUILD_FILE = frozenset ( [ 'ebuild_file', 'efile' ] ), - HAS_SUGGESTS = frozenset ( [ 'has_suggests', 'has_rsuggests' ] ), - SRC_URI = frozenset ( [ 'src_uri', 'package_url', 'url' ] ), + DISTDIR = frozenset ( ( 'distdir', 'pkg_distdir' ) ), + # removing this key + #EBUILD_FILE = frozenset ( ( 'ebuild_file', 'efile' ) ), + HAS_SUGGESTS = frozenset ( ( 'has_suggests', 'has_rsuggests' ) ), + SRC_URI = frozenset ( ( 'src_uri', 'package_url', 'url' ) ), + ALWAYS_FALLBACK = frozenset ( ( 'ebuild_filepath' ) ), ) @@ -120,17 +122,9 @@ class PackageInfo ( object ): elif 'origin' in self._info: return util.get_distdir ( self._info ['origin'] ) - elif key_low in VIRTUAL_KEYS ['EBUILD_FILE']: - return os.path.join ( - config.get_or_fail ( [ 'OVERLAY', 'dir' ] ), - config.get_or_fail ( [ 'OVERLAY', 'category' ] ), - self ['ebuild_name'].partition ( '-' ) [0], - self ['ebuild_name'] + ".ebuild" - ) - elif key_low in VIRTUAL_KEYS ['HAS_SUGGESTS']: - if key_low in self._info: - return self._info [key_low] + if 'has_suggests' in self._info: + return self._info ['has_suggests'] else: return False @@ -151,7 +145,7 @@ class PackageInfo ( object ): elif key_low in self._info: return self._info [key_low] - elif do_fallback: + elif do_fallback or key_low in VIRTUAL_KEYS ['ALWAYS_FALLBACK']: return fallback_value else: raise KeyError ( key ) @@ -195,6 +189,16 @@ class PackageInfo ( object ): if 'ebuild' in info: self._use_ebuild ( info ['ebuild'] ) + if 'desc_data' in info + self ['desc_data'] = info ['desc_data'] + elif 'desc' in info: + self ['desc_data'] = info ['desc'] + + + if 'suggests' in info: + self ['has_suggests'] = info ['suggests'] + + self._update_lock.release() # --- end of update (**kw) --- @@ -239,7 +243,12 @@ class PackageInfo ( object ): arguments: * ebuild -- """ + self ['ebuild'] = ebuild + # set status to ready for overlay + + # this does no longer work FIXME self ['has_suggests'] = ebuild.has_rsuggests # todo move Ebuild funcs to here self ['ebuild_dir'] = ebuild.suggest_dir_name() self ['ebuild_name'] = ebuild.suggest_name() + # --- end of _use_ebuild (...) --- diff --git a/roverlay/portage/__init__.py b/roverlay/portage/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/roverlay/portage/__init__.py +++ /dev/null diff --git a/roverlay/portage/ebuildcreator.py b/roverlay/portage/ebuildcreator.py deleted file mode 100644 index aee45e1..0000000 --- a/roverlay/portage/ebuildcreator.py +++ /dev/null @@ -1,184 +0,0 @@ -# R Overlay -- ebuild creation, "master" module -# Copyright 2006-2012 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -import time -import logging -import threading - -try: - import queue -except ImportError: - # python2 - import Queue as queue - - -from roverlay import config -from roverlay.depres import depresolver -from roverlay.depres.channels import EbuildJobChannel -from roverlay.portage.ebuildjob import EbuildJob - -class EbuildCreator ( object ): - - NUMTHREADS = config.get ( 'EBUILD.jobcount', 0 ) - - def __init__ ( self ): - """Initializes an EbuildCreator. This is an Object that controls the - R package -> ebuild creation. It continuously creates EbuildJobs for - every R package added. - """ - self.ebuild_headers = dict () - self.depresolve_main = depresolver.DependencyResolver () - - self.ebuild_jobs = queue.Queue() - self.ebuild_jobs_done = list() - - self.runlock = threading.Lock() - self._threads = None - - self.logger = logging.getLogger ( 'EbuildCreator' ) - - # this topic to change FIXME/TODO - # metadata [<ebuild_name>] = MetadataJob instance - self.metadata = dict() - - # --- end of init (...) --- - - def add_package ( self, package_file ): - """Adds an R package to the EbuildCreator, which means that an EbuildJob - will be created for it. Returns the EbuildJob, which is also stored - in the job queue. - - arguments: - * package_file -- path R package file - """ - new_job = EbuildJob ( package_file, self.get_resolver_channel ) - - self.ebuild_jobs.put ( new_job ) - - return new_job - - # --- end of add_package (...) --- - - def get_resolver_channel ( self, name=None, logger=None ): - """Returns a communication channel to the dependency resolver. - - arguments: - readonly -- whether the channel is listen-only (no write methods) or not - defaults to True - """ - return self.depresolve_main.register_channel ( - EbuildJobChannel ( name=name, logger=logger ) - ) - - # --- end of get_resolver_channel (...) --- - - def close ( self ): - self.depresolve_main.close() - # --- end of close (...) --- - - def _thread_run_ebuilds ( self ): - - while not self.ebuild_jobs.empty(): - try: - job = self.ebuild_jobs.get_nowait() - except queue.Empty: - # queue is empty, done - return - - job.run() - self.ebuild_jobs_done.append ( job ) - - # --- end of _thread_run_ebuilds (...) --- - - def start ( self ): - """Tells all EbuildJobs to run.""" - - if not self.runlock.acquire ( False ): - # already running - return True - - start = time.time() - - jobcount = EbuildCreator.NUMTHREADS - - if jobcount < 1: - ( self.logger.warning if jobcount < 0 else self.logger.debug ) ( - "Running in sequential mode." - ) - self._thread_run_ebuilds() - else: - self.logger.warning ( - "Running in concurrent mode with %i jobs." % jobcount - ) - self._threads = [ - threading.Thread ( target = self._thread_run_ebuilds ) - for n in range ( jobcount ) - ] - - for t in self._threads: t.start() - for t in self._threads: t.join() - - del self._threads - self._threads = None - - - stop = time.time() - self.logger.info ( 'done after %f seconds' % ( stop - start ) ) - - # make metadata, topic to change... FIXME/TODO - for ejob in self.ebuild_jobs_done: - if ejob.get_ebuild() is None: continue - - edir = ejob.package_info ['ebuild_dir'] - if not edir in self.metadata: - self.metadata [edir] = ejob.feed_metadata ( create=True ) - else: - ejob.feed_metadata ( metadata=self.metadata [edir] ) - - self.runlock.release() - - # --- end of start (...) --- - - def collect_ebuilds ( self ): - """Returns all ebuilds. (They may not be ready / TODO)""" - ebuilds = [ job.get_ebuild() for job in self.ebuild_jobs_done ] - return filter ( None, ebuilds ) - - # --- end of collect_ebuilds (...) --- - - def get_ebuild_header ( self, ebuild_header_file=None ): - """Reads and returns the content of an ebuild header file. - This is a normal file that can be included in ebuilds. - Every header file will only be read on first access, its content will - be stored in a dict that is shared among all EbuildCreator instances. - - arguments: - * ebuild_header_file -- path to the header file; defaults to none which - means that nothing will be read and an empty list - is returned. - """ - - if ebuild_header_file is None: - # nothing to read - return [] - - elif ebuild_header_file in self.ebuild_headers: - # previously read - return self.ebuild_headers [ebuild_header_file] - - else: - # read file - try: - fh = open ( ebuild_header_file, 'r' ) - lines = fh.readlines() - fh.close() - self.ebuild_headers [ebuild_header_file] = lines - del fh - return lines - - except IOError as err: - # todo - raise - - # --- end of get_ebuild_header (...) --- diff --git a/roverlay/portage/ebuildjob.py b/roverlay/portage/ebuildjob.py deleted file mode 100644 index 6ad2738..0000000 --- a/roverlay/portage/ebuildjob.py +++ /dev/null @@ -1,333 +0,0 @@ -# R Overlay -- ebuild creation, "job" module -# Copyright 2006-2012 Gentoo Foundation -# Distributed under the terms of the GNU General Public License v2 - -import logging -import re - -from roverlay import config, util -from roverlay.portage.ebuild import Ebuild -from roverlay.portage.packageinfo import PackageInfo -from roverlay.portage.metadata.creation import MetadataJob -from roverlay.rpackage.descriptionreader import DescriptionReader - - -class EbuildJob ( object ): - LOGGER = logging.getLogger ( 'EbuildJob' ) - - DEFAULT_EBUILD_HEADER = config.get ( 'EBUILD.default_header' ) - - # move this to const / config - DEPENDENCY_FIELDS = { - 'R_SUGGESTS' : [ 'Suggests' ], - 'DEPENDS' : [ 'Depends', 'Imports' ], - 'RDEPENDS' : [ 'LinkingTo', 'SystemRequirements' ] - } - - STATUS_LIST = [ 'INIT', 'BUSY', 'WAIT_RESOLVE', 'SUCCESS', 'FAIL' ] - - # status 'jump' control - # FAIL is always allowed, S -> S has to be explicitly allowed - STATUS_BRANCHMAP = dict ( - INIT = [ 'BUSY' ], - BUSY = [ 'BUSY', 'WAIT_RESOLVE', 'SUCCESS' ], - WAIT_RESOLVE = [ 'BUSY' ], - SUCCESS = [], - FAIL = [], - ) - - def __init__ ( self, package_file, depres_channel_spawner=None ): - """Initializes an EbuildJob, which creates an ebuild for an R package. - - arguments: - * package_info -- R package file info - * dep_resolver -- dependency resolver - """ - - """Note: - it is intended to run this job as thread, that's why it has its own - dep resolver 'communication channel', status codes etc. - """ - - self.package_info = PackageInfo ( filepath=package_file ) - self.package_info.set_readonly() - - try: - self.logger = EbuildJob.LOGGER.getChild ( - self.package_info ['filename'] - ) - except KeyError: - self.logger = EbuildJob.LOGGER.getChild ( '__undef__' ) - - self.description_reader = DescriptionReader ( - self.package_info, logger=self.logger - ) - - self.ebuild = None - - # only allow a function (at least callable) for self.get_resolver - if hasattr ( depres_channel_spawner, '__call__' ): - self.request_resolver = depres_channel_spawner - # _depres contains (almost) dependency resolution data/.., including - # communication channels and should only be modified in run() - self._depres = dict () - else: - self.request_resolver = None - - self.status = 'INIT' - - # --- end of __init__ (...) --- - - def feed_metadata ( self, create=False, metadata=None ): - """Feeds metadata, either a existing MetadataJob instance or a new one. - - arguments: - * create -- if True: create new metadata, "function mode", - requires bool (metadata) == False - * metadata -- if not None: metadata to update, "method mode", - requires bool (create) == False - - returns: created metadata if in function mode (create is True) else - None (implicit) - - raises: Exception if (create <=> metadata) - """ - if not create and not metadata: - raise Exception ( "either create or metadata" ) - elif create and metadata: - raise Exception ( "either create or metadata" ) - elif create: - metadata = MetadataJob ( - self.package_info, - self.logger.getChild ( 'metadata' ) - ) - - - metadata.update ( - self.description_reader.get_desc ( run_if_unset=False ), - self.package_info - ) - - if create: return metadata - # --- end of feed_metadata (...) --- - - def get_resolver ( self, dependency_type ): - # comment TODO - if not dependency_type in self._depres: - self._depres [dependency_type] = \ - self.request_resolver ( dependency_type, self.logger ) - - return self._depres [dependency_type] - # --- end of get_resolver (...) --- - - def get_ebuild ( self ): - """Returns the Ebuild that is created by this object. Note that you should - check the status with status ( $TODO::EBUILD_READY ) before trying to use - the Ebuild. - ##fixme: it is (should be?) guaranteed that self.ebuild is None unless the Ebuild is successfully created## - """ - return self.ebuild - - # --- end of get_ebuild (...) --- - - def get_status ( self, expected_status=None ): - """Returns the current status of this job or a bool that indicates - whether to current status matches the expected one. - - arguments: - * expected_status -- if not None: check if this job's state - is expected_status - """ - if not expected_status is None: - return bool ( self.status == expected_status ) - else: - return self.status - - # --- end of get_status (...) --- - - def done_success ( self ): - """Returns True if this has been successfully finished.""" - return self.get_status ( 'SUCCESS' ) - - # --- end of done_success (...) --- - - def run ( self ): - """Tells this EbuildJob to run. - This means that it reads the package file, resolves dependencies - using its resolver and creates an Ebuild object that is ready - to be written into a file. - """ - - # TODO move hardcoded entries to config/const - - try: - # enforcing BRANCHMAP status control: set status or return - if not self._set_status ( 'BUSY', True ): return - - desc = self.description_reader.get_desc ( True ) - if desc is None: - self._set_status ( 'FAIL' ) - self.logger.info ( 'Cannot create an ebuild for this package.' ) - - - ebuild = Ebuild ( self.logger.getChild ( "Ebuild" ) ) - - ebuild.add ( 'pkg_name', self.package_info ['package_name'] ) - - # TODO move regex to config/const - ebuild.add ( - 'pkg_version', - re.sub ( '[-]{1,}', '.', self.package_info ['package_version'] ) - ) - ebuild.add ( 'PKG_FILE', self.package_info ['package_file'] ) - - - have_description = False - - if 'Title' in desc: - ebuild.add ( 'DESCRIPTION', desc ['Title'] ) - have_description = True - - if 'Description' in desc: - ebuild.add ( - 'DESCRIPTION', - ( '// ' if have_description else '' ) + desc ['Description'] - ) - - del have_description - - - ebuild.add ( 'SRC_URI', self.package_info ['package_url'] ) - - ## default ebuild header, could use some const here (eclass name,..) - # TODO use a single string as ebuild header instead of joining it - # for every ebuild - ebuild.add ( - 'ebuild_header', - EbuildJob.DEFAULT_EBUILD_HEADER, - False - ) - - if not self.request_resolver is None: - # dependency resolution is enabled - - dep_type = desc_field = None - - - for dep_type in EbuildJob.DEPENDENCY_FIELDS: - - resolver = None - - for desc_field in EbuildJob.DEPENDENCY_FIELDS [dep_type]: - - if desc_field in desc: - if not resolver: - resolver = self.get_resolver ( dep_type ) - - if isinstance ( desc [desc_field], list ): - resolver.add_dependencies ( desc [desc_field] ) - - else: - resolver.add_depency ( desc [desc_field] ) - - - # lazy depres: wait until done and stop if any resolver channel - # returns None (which implies failure) - # wait for depres and store results - resolved = True - - if not self._set_status ( 'WAIT_RESOLVE' ): return - - for resolver in self._depres.values(): - if resolver.satisfy_request() is None: - resolved = False - break - - if not self._set_status ( 'BUSY' ): return - - if not resolved: - # ebuild is not creatable, - # set status to FAIL and close dep resolvers - self.logger.info ( - "Failed to resolve dependencies for this package." - ) - for r in self._depres.values(): r.close () - self._set_status ( 'FAIL' ) - return - else: - # add deps to the ebuild - for dep_type, resolver in self._depres.items(): - # python3 requires list ( filter ( ... ) ) - deplist = list ( - filter ( None, resolver.collect_dependencies () ) - ) - - if deplist is None: - ## FIXME: false positive: "empty" channel - raise Exception ( - 'dep_resolver is broken: ' - 'lookup() returns None but satisfy_request() says ok.' - ) - - elif isinstance ( deplist, ( list, set ) ): - # add dependencies in no_append/override mode - self.logger.debug ( "adding %s to %s", deplist, dep_type ) - ebuild.add ( dep_type, deplist, False ) - - else: - raise Exception ( - "dep_resolver is broken: list or set expected!" - ) - # --- end for - - # tell the dep resolver channels that we're done - for r in self._depres.values(): r.close () - - # --- end dep resolution - - - ## finalize self.ebuild: forced text creation + make it readonly - if ebuild.prepare ( True, True ): - self.ebuild = ebuild - - # update package info - self.package_info.set_writeable() - self.package_info.update ( ebuild=ebuild ) - self.package_info.set_readonly() - - - - except Exception as e: - # any exception means failure - self._set_status ( 'FAIL' ) - self.logger.exception ( e ) - raise - - # --- end of run (...) --- - - def _set_status ( self, new_status, ignore_invalid=False ): - """Changes the status of this job. May refuse to do that - if invalid change requested (e.g. 'FAIL' -> 'SUCCESS'). - - arguments: - new_status -- - """ - - if new_status == 'FAIL': - # always allowed - self.logger.info ( "Entering status '%s'.", new_status ) - self.status = new_status - return True - - if new_status and new_status in EbuildJob.STATUS_LIST: - # check if jumping from self.status to new_status is allowed - if new_status in EbuildJob.STATUS_BRANCHMAP [self.status]: - self.logger.debug ( "Entering status '%s'.", new_status ) - self.status = new_status - return True - - # default return - self.logger.error ( "Cannot enter status '%s'.", new_status ) - return False - - # --- end of _set_status (...) --- diff --git a/roverlay/portage/metadata/__init__.py b/roverlay/portage/metadata/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/roverlay/portage/metadata/__init__.py +++ /dev/null diff --git a/roverlay/portage/overlay/__init__.py b/roverlay/portage/overlay/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/roverlay/portage/overlay/__init__.py +++ /dev/null diff --git a/roverlay/static/__init__.py b/roverlay/static/__init__.py new file mode 100644 index 0000000..13e7869 --- /dev/null +++ b/roverlay/static/__init__.py @@ -0,0 +1,5 @@ +# R Overlay -- not signleton but static access to certain objects +# Copyright 2006-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +# currently used for testing diff --git a/roverlay/static/depres.py b/roverlay/static/depres.py new file mode 100644 index 0000000..a351f51 --- /dev/null +++ b/roverlay/static/depres.py @@ -0,0 +1,29 @@ +# R Overlay -- dependency resolution, static resolver access +# Copyright 2006-2012 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 + +from roverlay.depres.channels import EbuildJobChannel +from roverlay.depres.depresolver import DependencyResolver + +_RESOLVER = None + +def resolver(): + """Returns the resolver.""" + global _RESOLVER + if _RESOLVER is None: + _RESOLVER = DependencyResolver() + return _RESOLVER +# --- end of resolver (...) --- + +def get_ebuild_channel ( name=None, logger=None ): + """Returns a communication channel to the dependency resolver. + + arguments: + name -- + logger -- + """ + return resolver().register_channel ( + EbuildJobChannel ( name=name, logger=logger ) + ) + +# --- end of get_resolver_channel (...) --- |