aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Erdmann <dywi@mailerd.de>2012-06-19 20:16:01 +0200
committerAndré Erdmann <dywi@mailerd.de>2012-06-19 20:16:01 +0200
commit2afa2439d20402b7cb7af0ca12edd5bb0c269bdc (patch)
tree126fe6c1ab0725917d1681ed43cfa65e99859922 /roverlay
parentoverlay creation (diff)
downloadR_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__.py38
-rw-r--r--roverlay/ebuild/construction.py (renamed from roverlay/portage/ebuild.py)170
-rw-r--r--roverlay/ebuild/creation.py203
-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__.py0
-rw-r--r--roverlay/portage/ebuildcreator.py184
-rw-r--r--roverlay/portage/ebuildjob.py333
-rw-r--r--roverlay/portage/metadata/__init__.py0
-rw-r--r--roverlay/portage/overlay/__init__.py0
-rw-r--r--roverlay/static/__init__.py5
-rw-r--r--roverlay/static/depres.py29
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 (...) ---