* [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/overlay/pkgdir/manifest/, roverlay/tools/, roverlay/config/, ...
@ 2013-06-08 16:21 André Erdmann
2013-06-13 16:34 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
0 siblings, 1 reply; 2+ messages in thread
From: André Erdmann @ 2013-06-08 16:21 UTC (permalink / raw
To: gentoo-commits
commit: e10fad59fff1d89e49df904cbba61049184257e7
Author: André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Sat Jun 8 16:12:29 2013 +0000
Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Sat Jun 8 16:12:29 2013 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=e10fad59
additions dir / ebuild manifest creation
* additions dir, PatchView: support an arbitrary number of patches per file,
and use non-version-specific "default" patches
* additions dir, EbuildView: find ebuilds that could be imported
Ebuild manifest creation has been partially merged into
packagedir_ebuildmanifest / moved to roverlay.tools.ebuild[env].
Also added ebuild import support to packagedir_base (work in progress).
---
roverlay/config/const.py | 8 +-
roverlay/config/entrymap.py | 2 +-
roverlay/overlay/additionsdir.py | 114 ++++++++++++---
roverlay/overlay/category.py | 3 +-
roverlay/overlay/pkgdir/__init__.py | 3 +
roverlay/overlay/pkgdir/manifest/__init__.py | 49 -------
roverlay/overlay/pkgdir/manifest/env.py | 122 ----------------
.../overlay/pkgdir/manifest/manifest_ebuild.py | 111 ---------------
roverlay/overlay/pkgdir/packagedir_base.py | 156 +++++++++++++++++++--
.../overlay/pkgdir/packagedir_ebuildmanifest.py | 67 ++++++++-
roverlay/tools/ebuild.py | 55 ++++++++
roverlay/tools/ebuildenv.py | 135 ++++++++++++++++++
roverlay/tools/patch.py | 36 ++---
roverlay/tools/runcmd.py | 37 +++++
14 files changed, 550 insertions(+), 348 deletions(-)
diff --git a/roverlay/config/const.py b/roverlay/config/const.py
index b3e8dc4..19086f9 100644
--- a/roverlay/config/const.py
+++ b/roverlay/config/const.py
@@ -71,15 +71,15 @@ _CONSTANTS = dict (
TOOLS = dict (
EBUILD = dict (
- prog = "/usr/bin/ebuild",
- target = "manifest",
+ exe = "/usr/bin/ebuild",
),
PATCH = dict (
exe = "patch",
opts = (
'--no-backup-if-mismatch',
- '--reject-file=-'
- '--quiet', '--force',
+ '--reject-file=-',
+ '--verbose',
+ # '--quiet', # '--force',
)
),
),
diff --git a/roverlay/config/entrymap.py b/roverlay/config/entrymap.py
index c98bc68..4551435 100644
--- a/roverlay/config/entrymap.py
+++ b/roverlay/config/entrymap.py
@@ -254,7 +254,7 @@ CONFIG_ENTRY_MAP = dict (
),
# ebuild is used to create Manifest files
ebuild_prog = dict (
- path = [ 'TOOLS', 'ebuild_prog' ],
+ path = [ 'TOOLS', 'ebuild_exe' ],
value_type = 'fs_path',
description = "name of/path to the ebuild executable",
),
diff --git a/roverlay/overlay/additionsdir.py b/roverlay/overlay/additionsdir.py
index 7136bb5..f0a6be4 100644
--- a/roverlay/overlay/additionsdir.py
+++ b/roverlay/overlay/additionsdir.py
@@ -7,6 +7,9 @@
import os
import re
+EMPTY_TUPLE = ()
+
+
class AdditionsDir ( object ):
def __init__ ( self, fspath, name=None, parent=None ):
@@ -54,6 +57,9 @@ class _AdditionsDirView ( object ):
class _EbuildAdditionsView ( _AdditionsDirView ):
+ # with leading '-'
+ RE_PVR = '[-](?P<pvr>[0-9.]+([-]r[0-9]+)?)'
+
def __init__ ( self, additions_dir ):
super ( _EbuildAdditionsView, self ).__init__ (
additions_dir=additions_dir
@@ -62,37 +68,113 @@ class _EbuildAdditionsView ( _AdditionsDirView ):
self.prepare()
# --- end of __init__ (...) ---
- def _get_files_with_suffix ( self, suffix ):
- assert '.' not in self._additions_dir.name
+ def _fs_iter_regex ( self, regex ):
+ fre = re.compile ( regex )
- fre = re.compile (
- self._additions_dir.name + '[-](?P<pvr>[0-9.]+([-]r[0-9]+)?)'
- + suffix.replace ( '.', '[.]' )
- )
root = self._additions_dir.root
for fname in os.listdir ( root ):
fmatch = fre.match ( fname )
if fmatch:
- yield ( fmatch.group ( 'pvr' ), ( root + os.sep + fname ), fname )
- # --- end of _get_files_with_suffix (...) ---
+ yield ( fmatch, ( root + os.sep + fname ), fname )
+ # --- end of _fs_iter_regex (...) ---
+
+
+class EbuildView ( _EbuildAdditionsView ):
+
+ RE_EBUILD_SUFFIX = '[.]ebuild'
+
+ def has_ebuilds ( self ):
+ return bool ( getattr ( self, '_ebuilds', None ) )
+ # --- end of has_ebuilds (...) ---
+
+ def get_ebuilds ( self ):
+ return self._ebuilds
+ # --- end of get_ebuilds (...) ---
+
+ def __iter__ ( self ):
+ return iter ( self.get_ebuilds )
+ # --- end of __iter__ (...) ---
+
+ def _prepare ( self ):
+ if self._additions_dir.exists():
+ ebuilds = list()
+
+ for fmatch, fpath, fname in self._fs_iter_regex (
+ self._additions_dir.name + self.RE_PVR + self.RE_EBUILD_SUFFIX
+ ):
+ # deref symlinks
+ ebuilds.append (
+ fmatch.group ( 'pvr' ), os.path.abspath ( fpath ), fname
+ )
+ # --- end of _prepare (...) --
+
class PatchView ( _EbuildAdditionsView ):
+ RE_PATCH_SUFFIX = '(?P<patchno>[0-9]{4})?[.]patch'
+
def has_patches ( self ):
return bool ( getattr ( self, '_patches', None ) )
# --- end of has_patches (...) ---
- def get_patches ( self, pvr ):
- patch = self._patches.get ( pvr, None )
- return ( patch, ) if patch is not None else None
+ def get_patches ( self, pvr, fallback_to_default=True ):
+ patches = self._patches.get ( pvr, None )
+ if patches:
+ return patches
+ elif fallback_to_default:
+ return getattr ( self, '_default_patches', EMPTY_TUPLE )
+ else:
+ return EMPTY_TUPLE
# --- end of get_patches (...) ---
+ def get_default_patches ( self ):
+ return getattr ( self, '_default_patches', EMPTY_TUPLE )
+ # --- end of get_default_patches (...) ---
+
def prepare ( self ):
+ def patchno_sort ( iterable ):
+ return list (
+ v[1] for v in sorted ( iterable, key=lambda k: k[0] )
+ )
+ # --- end of patchno_sort (...) ---
+
if self._additions_dir.exists():
- # dict { pvr => patch_file }
- self._patches = {
- pvr: fpath
- for pvr, fpath, fname in self._get_files_with_suffix ( '.patch' )
- }
+ # dict { pvr => *(patch_no, patch_file) }
+ patches = dict()
+
+
+ # find version-specific patches
+ for fmatch, fpath, fname in self._fs_iter_regex (
+ self._additions_dir.name + self.RE_PVR + self.RE_PATCH_SUFFIX
+ ):
+ patchno = fmatch.group ( 'patchno' )
+ patchno = -1 if patchno is None else int ( patchno )
+ pvr = fmatch.group ( 'pvr' )
+ if pvr in patches:
+ patches [pvr].append ( ( patchno, fpath ) )
+ else:
+ patches [pvr] = [ ( patchno, fpath ) ]
+
+ # -- end for;
+
+ self._patches = { k: patchno_sort ( v ) for k, v in patches.items() }
+
+
+ # find default patches
+
+ default_patches = []
+
+ for fmatch, fpath, fname in self._fs_iter_regex (
+ self._additions_dir.name + self.RE_PATCH_SUFFIX
+ ):
+ patchno = fmatch.group ( 'patchno' )
+
+ default_patches.append (
+ ( ( -1 if patchno is None else int ( patchno ) ), fpath )
+ )
+ # -- end for;
+
+ if default_patches:
+ self._default_patches = patchno_sort ( default_patches )
# --- end of prepare (...) ---
diff --git a/roverlay/overlay/category.py b/roverlay/overlay/category.py
index 7ccd86e..0e33fc7 100644
--- a/roverlay/overlay/category.py
+++ b/roverlay/overlay/category.py
@@ -318,8 +318,9 @@ class Category ( object ):
additions_dir = additions_dir.get_obj_subdir ( package ),
**write_kwargs
)
+ # -- end if;
- self.remove_empty()
+ self.remove_empty()
# --- end of write (...) ---
def write_manifest ( self, **manifest_kw ):
diff --git a/roverlay/overlay/pkgdir/__init__.py b/roverlay/overlay/pkgdir/__init__.py
index cc4b79b..baf4eea 100644
--- a/roverlay/overlay/pkgdir/__init__.py
+++ b/roverlay/overlay/pkgdir/__init__.py
@@ -57,6 +57,9 @@ def _configure():
else:
_package_dir_class = _package_dir_module.PackageDirBase
+ if hasattr ( _package_dir_class, 'init_cls' ):
+ _package_dir_class.init_cls()
+
logging.getLogger ('pkgdir').debug (
'Using {!r} as manifest implementation.'.format ( mf_impl )
)
diff --git a/roverlay/overlay/pkgdir/manifest/__init__.py b/roverlay/overlay/pkgdir/manifest/__init__.py
deleted file mode 100644
index 795fd0b..0000000
--- a/roverlay/overlay/pkgdir/manifest/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# R overlay -- manifest package (__init__)
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012 André Erdmann <dywi@mailerd.de>
-# Distributed under the terms of the GNU General Public License;
-# either version 2 of the License, or (at your option) any later version.
-
-"""manifest package
-
-This package provides Manifest creation for ebuilds.
-This module has one function create_manifest() that creates an Manifest
-for ebuilds from a package directory.
-"""
-
-__all__ = [ 'create_manifest', ]
-import logging
-import threading
-
-from roverlay.overlay.pkgdir.manifest import manifest_ebuild
-
-_manifest_creation = manifest_ebuild.ExternalManifestCreation ( lazy_init=True )
-# ExternalManifestCreation does not support threads (-> multiprocesses)
-# for one directory/overlay
-_manifest_lock = threading.Lock()
-
-def create_manifest ( package_info_list, nofail=False ):
- """Creates a Manifest for package_info, using the <<best>> implementation
- available.
-
- current implementation: ExternalManifestCreation (using ebuild(1))
-
- arguments:
- * package_info --
- * nofail -- catch exceptions and return False
- """
- ret = False
- try:
- _manifest_lock.acquire()
- ret = _manifest_creation.create_for ( package_info_list )
- except Exception as e:
- logging.exception ( e )
- if nofail:
- ret = False
- else:
- raise
- finally:
- _manifest_lock.release()
-
- return ret
-# --- end of create_manifest (...) ---
diff --git a/roverlay/overlay/pkgdir/manifest/env.py b/roverlay/overlay/pkgdir/manifest/env.py
deleted file mode 100644
index e24ace8..0000000
--- a/roverlay/overlay/pkgdir/manifest/env.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# R overlay -- manifest package, manifest environment for subprocess.Popen
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012 André Erdmann <dywi@mailerd.de>
-# Distributed under the terms of the GNU General Public License;
-# either version 2 of the License, or (at your option) any later version.
-
-"""manifest environment for subprocess.Popen
-
-This module implements a minimal (filtered) environment based on os.environ
-for manifest creation implementations that use external programs, e.g.
-ebuild(1).
-"""
-
-__all__ = [ 'ManifestEnv', ]
-
-import os
-import copy
-import logging
-
-from roverlay import util
-
-class ManifestEnv ( object ):
- """per-repo environment container for Manifest creation using ebuild."""
-
- @classmethod
- def get_new ( cls ):
- return cls ( filter_env=True ).get_env (
- distdir="", portage_ro_distdirs=""
- )
- # --- end of get_new (...) ---
-
- def __init__ ( self, filter_env=True ):
- """Initializes a ManifestEnv.
-
- arguments:
- * filter_env -- if True: start with an empty env and copy vars
- from os.environ selectively
- else : start with os.environ as env
- """
- self.filter_env = filter_env
- self._manenv = dict()
- self.logger = logging.getLogger ( 'ManifestEnv' )
- self._common_env = None
- # --- end of __init__ (...) ---
-
- def get_env ( self, distdir, portage_ro_distdirs ):
- """Returns an env dict for repo_dir.
-
- arguments:
- * repo_dir --
- """
- env = self._get_common_manifest_env()
- env ['DISTDIR'] = distdir
- env ['PORTAGE_RO_DISTDIRS'] = portage_ro_distdirs
- return env
- # --- end of get_env (...) ---
-
- def _get_common_manifest_env ( self, noret=False ):
- """Creates an environment suitable for an
- "ebuild <ebuild> digest|manifest" call (or uses an already existing env).
- Returns a shallow copy of this env which can then be locally modified
- (setting DISTDIR, PORTAGE_RO_DISTDIRS).
-
- arguments:
- * noret -- do not return copied env if True
- """
-
- if self._common_env is None:
-
- if self.filter_env:
-
- # selectively import os.environ
- our_env = util.keepenv (
- ( 'PATH', '' ),
- 'LANG',
- 'PWD',
- 'EBUILD_DEFAULT_OPTS'
- )
- else:
- # copy os.environ
- our_env = dict ( os.environ )
-
- # -- common env part
-
- # set FEATURES
- # * digest -- needed? (works without it)
- # * assume-digests --
- # * unknown-features-warn -- should FEATURES ever change
- #
- # * noauto -- should prevent ebuild from adding additional actions,
- # it still tries to download source packages, which is just wrong
- # here 'cause it is expected that the R package file exists when
- # calling this function, so FETCHCOMMAND/RESUMECOMMAND will be set
- # to /bin/true if possible.
- #
- # * distlocks -- disabled if FETCHCOMMAND/RESUMECOMMAND set to no-op
- #
- our_env ['FEATURES'] = \
- "noauto digest assume-digests unknown-features-warn"
-
- # try to prevent src fetching
- fetch_nop = util.sysnop (
- nop_returns_success=True,
- format_str="{nop} \${{DISTDIR}} \${{FILE}} \${{URI}}"
- )
-
- if not fetch_nop is None:
- self.logger.debug (
- fetch_nop [0] + " disables/replaces FETCHCOMMAND,RESUMECOMMAND."
- )
- our_env ['FETCHCOMMAND'] = fetch_nop [1]
- our_env ['RESUMECOMMAND'] = fetch_nop [1]
- our_env ['FEATURES'] += " -distlocks"
-
-
- self._common_env = our_env
- # -- end if
- if noret:
- return None
- else:
- return copy.copy ( self._common_env )
- # --- end of _get_common_manifest_env (...) ---
diff --git a/roverlay/overlay/pkgdir/manifest/manifest_ebuild.py b/roverlay/overlay/pkgdir/manifest/manifest_ebuild.py
deleted file mode 100644
index 1004381..0000000
--- a/roverlay/overlay/pkgdir/manifest/manifest_ebuild.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# R overlay -- manifest package, manifest helpers (actual implementation)
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012 André Erdmann <dywi@mailerd.de>
-# Distributed under the terms of the GNU General Public License;
-# either version 2 of the License, or (at your option) any later version.
-
-"""manifest helpers (actual implementation)
-
-This module implements Manifest creation using ebuild(1).
-"""
-
-__all__ = [ 'ExternalManifestCreation', ]
-
-import os.path
-import copy
-import logging
-import subprocess
-
-
-import roverlay.overlay.pkgdir.distroot.static
-
-from roverlay import config, strutil
-
-from roverlay.overlay.pkgdir.manifest.env import ManifestEnv
-
-class ExternalManifestCreation ( object ):
- """This class implements Manifest creation using the low level ebuild
- interface, ebuild(1), which is called in a filtered environment.
- """
- # NOTE:
- # ebuild <ebuild> digest does not support multiprocesses for one overlay,
-
- def _doinit ( self ):
- """Initializes self's data, needs an initialized ConfigTree."""
- self.manifest_env = ManifestEnv.get_new()
- self.ebuild_tgt = config.get_or_fail ( 'TOOLS.EBUILD.target' )
- self.ebuild_prog = config.get_or_fail ( 'TOOLS.EBUILD.prog' )
-
- # set PORDIR_OVERLAY and DISTDIR
- self.manifest_env ['PORTDIR_OVERLAY'] = config.get_or_fail (
- 'OVERLAY.dir'
- )
- # self.distroot[.get_distdir(...)] replaces the __tmp__ directory
- self.distroot = (
- roverlay.overlay.pkgdir.distroot.static.get_configured ( static=True )
- )
-
- self._initialized = True
- # --- end of _doinit (...) ---
-
- def __init__ ( self, lazy_init=False ):
- self.logger = logging.getLogger ( 'ManifestCreation' )
- self._initialized = False
- if not lazy_init:
- self._doinit()
- # --- end of __init__ (...) ---
-
- def create_for ( self, package_info_list ):
- """See ManifestCreation.create_for.
- Calls ebuild, returns True on success else False.
-
- raises: *passes Exceptions from failed config lookups
- """
- if not self._initialized:
- self._doinit()
-
- # choosing one ebuild for calling "ebuild <ebuild>" is sufficient
- ebuild_file = package_info_list [0] ['ebuild_file']
-
- distdir = self.distroot.get_distdir ( package_info_list [0] ['name'] )
-
- #
- self.manifest_env ['DISTDIR'] = distdir.get_root()
-
- # add hardlinks to DISTROOT (replacing existing files/links)
- for p in package_info_list:
- # TODO: optimize this further?
- # -> "not has physical_only?"
- # (should be covered by "has package_file")
- distdir.add ( p ['package_file'], p ['package_src_destpath'] )
-
- ebuild_call = subprocess.Popen (
- (
- self.ebuild_prog,
- ebuild_file,
- self.ebuild_tgt
- ),
- stdin=None,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- env=self.manifest_env
- )
-
- output = ebuild_call.communicate()
-
- # log stderr
- for line in strutil.pipe_lines ( output [1], use_filter=True ):
- self.logger.warning ( line )
-
- if ebuild_call.returncode == 0:
- self.logger.debug ( "Manifest written." )
- return True
- else:
- self.logger.error (
- 'Couldn\'t create Manifest for {ebuild}! '
- 'Return code was {ret}.'.format (
- ebuild=ebuild_file, ret=ebuild_call.returncode
- )
- )
- return False
- # --- end of create_for (...) ---
diff --git a/roverlay/overlay/pkgdir/packagedir_base.py b/roverlay/overlay/pkgdir/packagedir_base.py
index 0e5ee81..e2f0f09 100644
--- a/roverlay/overlay/pkgdir/packagedir_base.py
+++ b/roverlay/overlay/pkgdir/packagedir_base.py
@@ -119,6 +119,7 @@ class PackageDirBase ( object ):
physical_only=True, pvr=pvr, ebuild_file=efile
)
self._packages [ p ['ebuild_verstr'] ] = p
+ return p
# --- end of _scan_add_package (...) ---
def add ( self, package_info, add_if_physical=False ):
@@ -364,7 +365,7 @@ class PackageDirBase ( object ):
for pvr in pvr_list:
self.purge_package ( pvr )
- assert not self.empty()
+ assert self.empty()
self.fs_cleanup()
# --- end of fs_destroy (...) ---
@@ -521,7 +522,7 @@ class PackageDirBase ( object ):
# write manifest (only if shared_fh is None)
if self._need_manifest and write_manifest:
- if not self.write_manifest():
+ if not self.write_manifest ( ignore_empty=True ):
success = False
# -- has_ebuilds?
@@ -533,6 +534,99 @@ class PackageDirBase ( object ):
return success
# --- end of write (...) ---
+ def import_extra_ebuilds ( self, overwrite, additions_dir ):
+ """Imports ebuilds from an additions dir into this package dir.
+
+ arguments:
+ * overwrite -- whether to overwrite existing ebuilds or not
+ * additions_dir -- additions dir for this package dir
+ """
+
+ def import_ebuild_efile ( pvr, efile_src, fname ):
+ """Imports an ebuild file into this package dir and registers it
+ in self._packages.
+
+ Returns the PackageInfo instance of the imported ebuild.
+
+ arguments:
+ * pvr --
+ * efile_src -- path to the (real, non-symlink) ebuild file
+ * fname -- name of the ebuild file
+ """
+ # this assertion is always true (see EbuildView)
+ assert fname == self.name + '-' + pvr + '.ebuild'
+
+ efile_dest = self.physical_location + os.sep + fname
+
+ ##efile_dest = (
+ ## self.physical_location + os.sep
+ ## + self.name + '-' + pvr + '.ebuild'
+ ##)
+
+ try:
+ # copy the ebuild file
+ shutil.copyfile ( efile_src, efile_dest )
+
+ # create PackageInfo and register it
+ p = PackageInfo (
+ imported=True, pvr=pvr, ebuild_file=efile
+ )
+ self._packages [ p ['ebuild_verstr'] ] = p
+
+
+ # manifest needs to be rewritten
+ self._need_manifest = True
+
+ # fetch SRC_URI?
+ # ebuild <ebuild> fetch?
+
+ # imported ebuilds cannot be used for generating metadata.xml
+ ##self._need_metadata = True
+
+ return p
+ except:
+ # this package dir is "broken" now,
+ # so a new manifest would be good...
+ #
+ # (the program stops when importing fails,
+ # so this is a theoretical case only)
+ #
+ self._need_manifest = True
+
+ if pvr in self._packages:
+ self.purge_package ( pvr )
+
+ if os.access ( efile_dest, os.F_OK ):
+ os.unlink ( efile_dest )
+
+ raise
+ # --- end of import_ebuild_efile (...) ---
+
+ eview = roverlay.overlay.additionsdir.EbuildView ( additions_dir )
+
+ if not self.physical_location:
+ raise Exception (
+ "import_extra_ebuilds() needs a non-virtual package dir!"
+ )
+ elif eview.has_ebuilds():
+ util.dodir ( self.physical_location, mkdir_p=True )
+
+ if not self._packages:
+ for pvr, efile, fname in eview.get_ebuilds():
+ import_ebuild_efile ( pvr, efile, fname )
+
+ elif overwrite:
+ for pvr, efile, fname in eview.get_ebuilds():
+ if pvr in self._packages:
+ self.purge_package ( pvr )
+ import_ebuild_efile ( pvr, efile, fname )
+
+ else:
+ for pvr, efile, fname in eview.get_ebuilds():
+ if pvr not in self._packages:
+ import_ebuild_efile ( pvr, efile, fname )
+ # --- end of import_extra_ebuilds (...) ---
+
def write_ebuilds ( self, overwrite, additions_dir, shared_fh=None ):
"""Writes all ebuilds.
@@ -571,25 +665,59 @@ class PackageDirBase ( object ):
return _success
# --- end of write_ebuild (...) ---
- def patch_ebuild ( efile, patches ):
+ def patch_ebuild ( efile, pvr, patches ):
+ """Applies zero or more patches to an ebuild (file).
+
+ Returns True on success (all patches applied cleanly,
+ where all >= 0), else False.
+
+ Removes the ebuild file if one or more patches failed.
+
+ arguments:
+ * efile -- path to the file that should be patched
+ * pvr -- ${PVR} of the ebuild (used for removing the ebuild)
+ * patches -- list of patch files to be applied, in order
+ """
if patches:
self.logger.info ( "Patching " + str ( efile ) )
self.logger.debug (
"Patches for {} (in that order): {}".format ( efile, patches )
)
- patch_ret = None
+ try:
+ patch_success = True
- for patch in patches:
- patch_ret = roverlay.tools.patch.dopatch (
- filepath=efile, patch=patch, logger=self.logger
- )
+ for patch in patches:
+ patch_ret = roverlay.tools.patch.dopatch (
+ filepath=efile, patch=patch, logger=self.logger
+ )
- if patch_ret != os.EX_OK:
- # TODO
- raise Exception ( patch )
+ if patch_ret != os.EX_OK:
+ self.logger.error (
+ "failed to apply patch {!r}!".format ( patch )
+ )
+ patch_success = False
+ break
- return True
+ except Exception as err:
+ # ^ which exceptions exactly?
+ self.logger.exception ( err )
+ patch_success = False
+ # -- end try;
+
+ if patch_success:
+ return True
+ else:
+ self.logger.error (
+ 'Removing ebuild {!r} due to errors '
+ 'while patching it.'.format ( efile )
+ )
+ # don't set need_manifest here (not required and
+ # write_manifest() would fail if no ebuild written)
+ #
+ ##self._need_manifest = True
+ self.purge_package ( pvr )
+ return False
else:
return True
# --- end of patch_ebuild (...) ---
@@ -614,7 +742,7 @@ class PackageDirBase ( object ):
patchview = roverlay.overlay.additionsdir.PatchView ( additions_dir )
haspatch = patchview.has_patches()
- for pvr, efile, p_info in ebuilds_to_write():
+ for pvr, efile, p_info in list ( ebuilds_to_write() ):
if not hasdir:
util.dodir ( self.physical_location, mkdir_p=True )
hasdir = True
@@ -623,7 +751,7 @@ class PackageDirBase ( object ):
write_ebuild ( efile, p_info ['ebuild'] )
) and (
not haspatch
- or patch_ebuild ( efile, patchview.get_patches ( pvr ) )
+ or patch_ebuild ( efile, pvr, patchview.get_patches ( pvr ) )
):
self._need_manifest = True
diff --git a/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py b/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py
index 1801a08..c9e3d84 100644
--- a/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py
+++ b/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py
@@ -6,17 +6,36 @@
__all__ = [ 'PackageDir', ]
-from roverlay.overlay.pkgdir import manifest
-from roverlay.overlay.pkgdir import packagedir_base
+import threading
+import roverlay.config
+import roverlay.tools.ebuild
+import roverlay.tools.ebuildenv
+import roverlay.overlay.pkgdir.packagedir_base
+import roverlay.overlay.pkgdir.distroot.static
-class PackageDir ( packagedir_base.PackageDirBase ):
+
+class PackageDir ( roverlay.overlay.pkgdir.packagedir_base.PackageDirBase ):
"""
PackageDir class that uses the ebuild executable for Manifest writing.
"""
-
+ #DISTROOT = None
+ #MANIFEST_ENV = None
+ MANIFEST_LOCK = threading.Lock()
MANIFEST_THREADSAFE = False
+ @classmethod
+ def init_cls ( cls ):
+ env = roverlay.tools.ebuildenv.ManifestEnv()
+ env.add_overlay_dir ( roverlay.config.get_or_fail ( 'OVERLAY.dir' ) )
+
+ cls.DISTROOT = (
+ roverlay.overlay.pkgdir.distroot.static.get_configured ( static=True )
+ )
+
+ cls.MANIFEST_ENV = env
+ # --- end of init_cls (...) ---
+
def _write_manifest ( self, pkgs_for_manifest ):
"""Generates and writes the Manifest file for this package.
@@ -24,6 +43,44 @@ class PackageDir ( packagedir_base.PackageDirBase ):
returns: success (True/False)
"""
+ try:
+ self.MANIFEST_LOCK.acquire()
+
+ # choosing one ebuild for calling "ebuild <ebuild>" is sufficient
+ ebuild_file = pkgs_for_manifest [0] ['ebuild_file']
+
+ distdir = self.DISTROOT.get_distdir ( pkgs_for_manifest [0] ['name'] )
+
+ # add hardlinks to DISTROOT (replacing existing files/links)
+ for p in pkgs_for_manifest:
+ # TODO: optimize this further?
+ # -> "not has physical_only?"
+ # (should be covered by "has package_file")
+ distdir.add ( p ['package_file'], p ['package_src_destpath'] )
+
+
+ if roverlay.tools.ebuild.doebuild_manifest (
+ ebuild_file, self.logger,
+ self.MANIFEST_ENV.get_env ( distdir.get_root() )
+ ):
+ self.logger.debug ( "Manifest written." )
+ ret = True
+
+ else:
+ self.logger.error (
+ 'Couldn\'t create Manifest for {ebuild}! '
+ 'Return code was {ret}.'.format (
+ ebuild=ebuild_file, ret=ebuild_call.returncode
+ )
+ )
+ ret = False
+
+ except Exception as err:
+ self.logger.exception ( err )
+ raise
+
+ finally:
+ self.MANIFEST_LOCK.release()
- return manifest.create_manifest ( pkgs_for_manifest, nofail=False )
+ return ret
# --- end of write_manifest (...) ---
diff --git a/roverlay/tools/ebuild.py b/roverlay/tools/ebuild.py
new file mode 100644
index 0000000..d9f4e9a
--- /dev/null
+++ b/roverlay/tools/ebuild.py
@@ -0,0 +1,55 @@
+# R overlay -- tools, run ebuild(1)
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+# NOTE:
+# this module has to be loaded after reading roverlay's config
+#
+
+import roverlay.tools.runcmd
+
+import roverlay.config
+import roverlay.util
+
+_EBUILD_CMDV = (
+ roverlay.config.get_or_fail ( 'TOOLS.EBUILD.exe' ),
+)
+
+def doebuild (
+ ebuild_file, command, logger, env=None, opts=(), return_success=True
+):
+ return roverlay.tools.runcmd.run_command (
+ cmdv = ( _EBUILD_CMDV + opts + ( ebuild_file, command ) ),
+ env = env,
+ logger = logger,
+ return_success = return_success
+ )
+# --- end of doebuild (...) ---
+
+def doebuild_manifest (
+ ebuild_file, logger, env=None, opts=(), return_success=True
+):
+ return doebuild (
+ ebuild_file = ebuild_file,
+ command = "manifest",
+ logger = logger,
+ env = env,
+ opts = opts,
+ return_success = return_success,
+ )
+# --- end of doebuild_manifest (...) ---
+
+def doebuild_fetch (
+ ebuild_file, logger, env=None, opts=(), return_success=True
+):
+ return doebuild (
+ ebuild_file = ebuild_file,
+ command = "fetch",
+ logger = logger,
+ env = env,
+ opts = ( '--skip-manifest', ) + opts,
+ return_success = return_success,
+ )
+# --- end of doebuild_fetch (...) ---
diff --git a/roverlay/tools/ebuildenv.py b/roverlay/tools/ebuildenv.py
new file mode 100644
index 0000000..40f6495
--- /dev/null
+++ b/roverlay/tools/ebuildenv.py
@@ -0,0 +1,135 @@
+# R overlay -- tools, env for ebuild.py
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+import os
+import copy
+import logging
+
+import roverlay.util
+
+class EbuildEnv ( object ):
+
+ def __init__ ( self, filter_env=True ):
+ """Initializes an EbuildEnv.
+
+ arguments:
+ * filter_env -- if True: start with an empty env and copy vars
+ from os.environ selectively
+ else : start with os.environ as env
+ """
+ self.filter_env = filter_env
+ self.logger = logging.getLogger ( 'ManifestEnv' )
+ self._common_env = None
+ # --- end of __init__ (...) ---
+
+ def add_info ( self, info, **kwargs ):
+ self._get_common_env ( True )
+ self._common_env.update ( info )
+ self._common_env.update ( kwargs )
+ # --- end of add_info (...) ---
+
+ def _get_env ( self, additional_info ):
+ env = self._get_common_env()
+ env.update ( additional_info )
+ return env
+ # --- end of get_env (...) ---
+
+ def get_distdir_env ( self, distdir ):
+ """Returns an onv dict for distdir.
+
+ arguments:
+ * distdir --
+ """
+ return self._get_env ( { 'DISTDIR': distdir } )
+ # --- end of get_distdir_env (...) ---
+
+ get_env = get_distdir_env
+
+ def add_overlay_dir ( self, overlay_dir ):
+ self._make_common_env()
+ self._common_env ['PORTDIR_OVERLAY'] = overlay_dir
+ # --- end of add_overlay_dir (...) ---
+
+ def _make_common_env ( self ):
+ if self.filter_env:
+
+ # selectively import os.environ
+ our_env = roverlay.util.keepenv (
+ ( 'PATH', '' ),
+ 'LANG',
+ 'PWD',
+ 'EBUILD_DEFAULT_OPTS'
+ )
+ else:
+ # copy os.environ
+ our_env = dict ( os.environ )
+
+ # -- common env part
+
+ # set FEATURES
+ # * digest -- needed? (works without it)
+ # * assume-digests --
+ # * unknown-features-warn -- should FEATURES ever change
+ #
+ # * noauto -- should prevent ebuild from adding additional actions,
+ # it still tries to download source packages, which is just wrong
+ # here 'cause it is expected that the R package file exists when
+ # calling this function, so FETCHCOMMAND/RESUMECOMMAND will be set
+ # to /bin/true if possible.
+ #
+ our_env ['FEATURES'] = \
+ "noauto digest assume-digests unknown-features-warn"
+
+ self._common_env = our_env
+ # --- end of _make_common_env (...) ---
+
+ def _get_common_env ( self ):
+ """Creates an environment suitable for an
+ "ebuild <ebuild> digest|manifest" call (or uses an already existing env).
+ Returns a shallow copy of this env which can then be locally modified
+ (setting DISTDIR, PORTAGE_RO_DISTDIRS).
+ """
+
+ if self._common_env is None:
+ self._make_common_env()
+
+ return copy.copy ( self._common_env )
+ # --- end of _get_common_env (...) ---
+
+# --- end of EbuildEnv ---
+
+class FetchEnv ( EbuildEnv ):
+ pass
+# --- end of FetchEnv ---
+
+
+class ManifestEnv ( EbuildEnv ):
+ """per-repo environment container for Manifest creation using ebuild."""
+
+ def _make_common_env ( self ):
+ super ( ManifestEnv, self )._make_common_env()
+
+ # set FETCHCOMMAND, RESUMECOMMAND and extend FEATURES:
+ # * distlocks -- disabled if FETCHCOMMAND/RESUMECOMMAND set to no-op
+ #
+
+ # try to prevent src fetching
+ fetch_nop = roverlay.util.sysnop (
+ nop_returns_success=True,
+ format_str="{nop} \${{DISTDIR}} \${{FILE}} \${{URI}}"
+ )
+
+ if not fetch_nop is None:
+ self.logger.debug (
+ fetch_nop [0] + " disables/replaces FETCHCOMMAND,RESUMECOMMAND."
+ )
+
+ self._common_env ['FETCHCOMMAND'] = fetch_nop [1]
+ self._common_env ['RESUMECOMMAND'] = fetch_nop [1]
+ self._common_env ['FEATURES'] += " -distlocks"
+ # --- end of _make_common_env (...) ---
+
+# --- end of ManifestEnv ---
diff --git a/roverlay/tools/patch.py b/roverlay/tools/patch.py
index 119ff80..ff48968 100644
--- a/roverlay/tools/patch.py
+++ b/roverlay/tools/patch.py
@@ -4,42 +4,28 @@
# Distributed under the terms of the GNU General Public License;
# either version 2 of the License, or (at your option) any later version.
-import subprocess
+# NOTE:
+# this module has to be loaded after reading roverlay's config
+#
+
+import roverlay.tools.runcmd
import roverlay.config
-import roverlay.strutil
import roverlay.util
_PATCHENV = roverlay.util.keepenv (
( 'PATH', '' ), 'LANG', 'LC_ALL', 'PWD', 'TMPDIR'
)
-# NOTE:
-# this module has to be loaded after reading roverlay's config
-#
-
-_PATCHOPTS = (
+_PATCH_CMDV = (
( roverlay.config.get_or_fail ( "TOOLS.PATCH.exe" ), )
+ roverlay.config.get_or_fail ( "TOOLS.PATCH.opts" )
)
def dopatch ( filepath, patch, logger ):
- print ( "RUN PATCH", filepath, patch )
- patch_call = subprocess.Popen (
- _PATCHOPTS + (
- filepath, patch
- ),
- stdin=None,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- env=_PATCHENV,
- )
-
- output = patch_call.communicate()
-
- # log stderr
- for line in roverlay.strutil.pipe_lines ( output [1], use_filter=True ):
- logger.warning ( line )
-
- return patch_call.returncode
+ return roverlay.tools.runcmd.run_command (
+ cmdv = ( _PATCH_CMDV + ( filepath, patch ) ),
+ env = _PATCHENV,
+ logger = logger
+ ).returncode
# --- end of dopatch (...) ---
diff --git a/roverlay/tools/runcmd.py b/roverlay/tools/runcmd.py
new file mode 100644
index 0000000..e6b4f19
--- /dev/null
+++ b/roverlay/tools/runcmd.py
@@ -0,0 +1,37 @@
+# R overlay -- tools, run a command
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+import os
+import subprocess
+
+import roverlay.strutil
+
+DEBUG_TO_CONSOLE = True
+
+def run_command ( cmdv, env, logger, return_success=False ):
+ if DEBUG_TO_CONSOLE:
+ cmd_call = subprocess.Popen ( cmdv, stdin=None, env=env )
+ else:
+ cmd_call = subprocess.Popen (
+ cmdv,
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env,
+ )
+
+ output = cmd_call.communicate()
+
+ # log stderr
+ if output [1]:
+ for line in roverlay.strutil.pipe_lines ( output [1], use_filter=True ):
+ logger.warning ( line )
+
+ if return_success:
+ return cmd_call.returncode == os.EX_OK
+ else:
+ return cmd_call
+# --- end of run_command (...) ---
^ permalink raw reply related [flat|nested] 2+ messages in thread
* [gentoo-commits] proj/R_overlay:master commit in: roverlay/overlay/pkgdir/manifest/, roverlay/tools/, roverlay/config/, ...
2013-06-08 16:21 [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/overlay/pkgdir/manifest/, roverlay/tools/, roverlay/config/, André Erdmann
@ 2013-06-13 16:34 ` André Erdmann
0 siblings, 0 replies; 2+ messages in thread
From: André Erdmann @ 2013-06-13 16:34 UTC (permalink / raw
To: gentoo-commits
commit: e10fad59fff1d89e49df904cbba61049184257e7
Author: André Erdmann <dywi <AT> mailerd <DOT> de>
AuthorDate: Sat Jun 8 16:12:29 2013 +0000
Commit: André Erdmann <dywi <AT> mailerd <DOT> de>
CommitDate: Sat Jun 8 16:12:29 2013 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=e10fad59
additions dir / ebuild manifest creation
* additions dir, PatchView: support an arbitrary number of patches per file,
and use non-version-specific "default" patches
* additions dir, EbuildView: find ebuilds that could be imported
Ebuild manifest creation has been partially merged into
packagedir_ebuildmanifest / moved to roverlay.tools.ebuild[env].
Also added ebuild import support to packagedir_base (work in progress).
---
roverlay/config/const.py | 8 +-
roverlay/config/entrymap.py | 2 +-
roverlay/overlay/additionsdir.py | 114 ++++++++++++---
roverlay/overlay/category.py | 3 +-
roverlay/overlay/pkgdir/__init__.py | 3 +
roverlay/overlay/pkgdir/manifest/__init__.py | 49 -------
roverlay/overlay/pkgdir/manifest/env.py | 122 ----------------
.../overlay/pkgdir/manifest/manifest_ebuild.py | 111 ---------------
roverlay/overlay/pkgdir/packagedir_base.py | 156 +++++++++++++++++++--
.../overlay/pkgdir/packagedir_ebuildmanifest.py | 67 ++++++++-
roverlay/tools/ebuild.py | 55 ++++++++
roverlay/tools/ebuildenv.py | 135 ++++++++++++++++++
roverlay/tools/patch.py | 36 ++---
roverlay/tools/runcmd.py | 37 +++++
14 files changed, 550 insertions(+), 348 deletions(-)
diff --git a/roverlay/config/const.py b/roverlay/config/const.py
index b3e8dc4..19086f9 100644
--- a/roverlay/config/const.py
+++ b/roverlay/config/const.py
@@ -71,15 +71,15 @@ _CONSTANTS = dict (
TOOLS = dict (
EBUILD = dict (
- prog = "/usr/bin/ebuild",
- target = "manifest",
+ exe = "/usr/bin/ebuild",
),
PATCH = dict (
exe = "patch",
opts = (
'--no-backup-if-mismatch',
- '--reject-file=-'
- '--quiet', '--force',
+ '--reject-file=-',
+ '--verbose',
+ # '--quiet', # '--force',
)
),
),
diff --git a/roverlay/config/entrymap.py b/roverlay/config/entrymap.py
index c98bc68..4551435 100644
--- a/roverlay/config/entrymap.py
+++ b/roverlay/config/entrymap.py
@@ -254,7 +254,7 @@ CONFIG_ENTRY_MAP = dict (
),
# ebuild is used to create Manifest files
ebuild_prog = dict (
- path = [ 'TOOLS', 'ebuild_prog' ],
+ path = [ 'TOOLS', 'ebuild_exe' ],
value_type = 'fs_path',
description = "name of/path to the ebuild executable",
),
diff --git a/roverlay/overlay/additionsdir.py b/roverlay/overlay/additionsdir.py
index 7136bb5..f0a6be4 100644
--- a/roverlay/overlay/additionsdir.py
+++ b/roverlay/overlay/additionsdir.py
@@ -7,6 +7,9 @@
import os
import re
+EMPTY_TUPLE = ()
+
+
class AdditionsDir ( object ):
def __init__ ( self, fspath, name=None, parent=None ):
@@ -54,6 +57,9 @@ class _AdditionsDirView ( object ):
class _EbuildAdditionsView ( _AdditionsDirView ):
+ # with leading '-'
+ RE_PVR = '[-](?P<pvr>[0-9.]+([-]r[0-9]+)?)'
+
def __init__ ( self, additions_dir ):
super ( _EbuildAdditionsView, self ).__init__ (
additions_dir=additions_dir
@@ -62,37 +68,113 @@ class _EbuildAdditionsView ( _AdditionsDirView ):
self.prepare()
# --- end of __init__ (...) ---
- def _get_files_with_suffix ( self, suffix ):
- assert '.' not in self._additions_dir.name
+ def _fs_iter_regex ( self, regex ):
+ fre = re.compile ( regex )
- fre = re.compile (
- self._additions_dir.name + '[-](?P<pvr>[0-9.]+([-]r[0-9]+)?)'
- + suffix.replace ( '.', '[.]' )
- )
root = self._additions_dir.root
for fname in os.listdir ( root ):
fmatch = fre.match ( fname )
if fmatch:
- yield ( fmatch.group ( 'pvr' ), ( root + os.sep + fname ), fname )
- # --- end of _get_files_with_suffix (...) ---
+ yield ( fmatch, ( root + os.sep + fname ), fname )
+ # --- end of _fs_iter_regex (...) ---
+
+
+class EbuildView ( _EbuildAdditionsView ):
+
+ RE_EBUILD_SUFFIX = '[.]ebuild'
+
+ def has_ebuilds ( self ):
+ return bool ( getattr ( self, '_ebuilds', None ) )
+ # --- end of has_ebuilds (...) ---
+
+ def get_ebuilds ( self ):
+ return self._ebuilds
+ # --- end of get_ebuilds (...) ---
+
+ def __iter__ ( self ):
+ return iter ( self.get_ebuilds )
+ # --- end of __iter__ (...) ---
+
+ def _prepare ( self ):
+ if self._additions_dir.exists():
+ ebuilds = list()
+
+ for fmatch, fpath, fname in self._fs_iter_regex (
+ self._additions_dir.name + self.RE_PVR + self.RE_EBUILD_SUFFIX
+ ):
+ # deref symlinks
+ ebuilds.append (
+ fmatch.group ( 'pvr' ), os.path.abspath ( fpath ), fname
+ )
+ # --- end of _prepare (...) --
+
class PatchView ( _EbuildAdditionsView ):
+ RE_PATCH_SUFFIX = '(?P<patchno>[0-9]{4})?[.]patch'
+
def has_patches ( self ):
return bool ( getattr ( self, '_patches', None ) )
# --- end of has_patches (...) ---
- def get_patches ( self, pvr ):
- patch = self._patches.get ( pvr, None )
- return ( patch, ) if patch is not None else None
+ def get_patches ( self, pvr, fallback_to_default=True ):
+ patches = self._patches.get ( pvr, None )
+ if patches:
+ return patches
+ elif fallback_to_default:
+ return getattr ( self, '_default_patches', EMPTY_TUPLE )
+ else:
+ return EMPTY_TUPLE
# --- end of get_patches (...) ---
+ def get_default_patches ( self ):
+ return getattr ( self, '_default_patches', EMPTY_TUPLE )
+ # --- end of get_default_patches (...) ---
+
def prepare ( self ):
+ def patchno_sort ( iterable ):
+ return list (
+ v[1] for v in sorted ( iterable, key=lambda k: k[0] )
+ )
+ # --- end of patchno_sort (...) ---
+
if self._additions_dir.exists():
- # dict { pvr => patch_file }
- self._patches = {
- pvr: fpath
- for pvr, fpath, fname in self._get_files_with_suffix ( '.patch' )
- }
+ # dict { pvr => *(patch_no, patch_file) }
+ patches = dict()
+
+
+ # find version-specific patches
+ for fmatch, fpath, fname in self._fs_iter_regex (
+ self._additions_dir.name + self.RE_PVR + self.RE_PATCH_SUFFIX
+ ):
+ patchno = fmatch.group ( 'patchno' )
+ patchno = -1 if patchno is None else int ( patchno )
+ pvr = fmatch.group ( 'pvr' )
+ if pvr in patches:
+ patches [pvr].append ( ( patchno, fpath ) )
+ else:
+ patches [pvr] = [ ( patchno, fpath ) ]
+
+ # -- end for;
+
+ self._patches = { k: patchno_sort ( v ) for k, v in patches.items() }
+
+
+ # find default patches
+
+ default_patches = []
+
+ for fmatch, fpath, fname in self._fs_iter_regex (
+ self._additions_dir.name + self.RE_PATCH_SUFFIX
+ ):
+ patchno = fmatch.group ( 'patchno' )
+
+ default_patches.append (
+ ( ( -1 if patchno is None else int ( patchno ) ), fpath )
+ )
+ # -- end for;
+
+ if default_patches:
+ self._default_patches = patchno_sort ( default_patches )
# --- end of prepare (...) ---
diff --git a/roverlay/overlay/category.py b/roverlay/overlay/category.py
index 7ccd86e..0e33fc7 100644
--- a/roverlay/overlay/category.py
+++ b/roverlay/overlay/category.py
@@ -318,8 +318,9 @@ class Category ( object ):
additions_dir = additions_dir.get_obj_subdir ( package ),
**write_kwargs
)
+ # -- end if;
- self.remove_empty()
+ self.remove_empty()
# --- end of write (...) ---
def write_manifest ( self, **manifest_kw ):
diff --git a/roverlay/overlay/pkgdir/__init__.py b/roverlay/overlay/pkgdir/__init__.py
index cc4b79b..baf4eea 100644
--- a/roverlay/overlay/pkgdir/__init__.py
+++ b/roverlay/overlay/pkgdir/__init__.py
@@ -57,6 +57,9 @@ def _configure():
else:
_package_dir_class = _package_dir_module.PackageDirBase
+ if hasattr ( _package_dir_class, 'init_cls' ):
+ _package_dir_class.init_cls()
+
logging.getLogger ('pkgdir').debug (
'Using {!r} as manifest implementation.'.format ( mf_impl )
)
diff --git a/roverlay/overlay/pkgdir/manifest/__init__.py b/roverlay/overlay/pkgdir/manifest/__init__.py
deleted file mode 100644
index 795fd0b..0000000
--- a/roverlay/overlay/pkgdir/manifest/__init__.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# R overlay -- manifest package (__init__)
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012 André Erdmann <dywi@mailerd.de>
-# Distributed under the terms of the GNU General Public License;
-# either version 2 of the License, or (at your option) any later version.
-
-"""manifest package
-
-This package provides Manifest creation for ebuilds.
-This module has one function create_manifest() that creates an Manifest
-for ebuilds from a package directory.
-"""
-
-__all__ = [ 'create_manifest', ]
-import logging
-import threading
-
-from roverlay.overlay.pkgdir.manifest import manifest_ebuild
-
-_manifest_creation = manifest_ebuild.ExternalManifestCreation ( lazy_init=True )
-# ExternalManifestCreation does not support threads (-> multiprocesses)
-# for one directory/overlay
-_manifest_lock = threading.Lock()
-
-def create_manifest ( package_info_list, nofail=False ):
- """Creates a Manifest for package_info, using the <<best>> implementation
- available.
-
- current implementation: ExternalManifestCreation (using ebuild(1))
-
- arguments:
- * package_info --
- * nofail -- catch exceptions and return False
- """
- ret = False
- try:
- _manifest_lock.acquire()
- ret = _manifest_creation.create_for ( package_info_list )
- except Exception as e:
- logging.exception ( e )
- if nofail:
- ret = False
- else:
- raise
- finally:
- _manifest_lock.release()
-
- return ret
-# --- end of create_manifest (...) ---
diff --git a/roverlay/overlay/pkgdir/manifest/env.py b/roverlay/overlay/pkgdir/manifest/env.py
deleted file mode 100644
index e24ace8..0000000
--- a/roverlay/overlay/pkgdir/manifest/env.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# R overlay -- manifest package, manifest environment for subprocess.Popen
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012 André Erdmann <dywi@mailerd.de>
-# Distributed under the terms of the GNU General Public License;
-# either version 2 of the License, or (at your option) any later version.
-
-"""manifest environment for subprocess.Popen
-
-This module implements a minimal (filtered) environment based on os.environ
-for manifest creation implementations that use external programs, e.g.
-ebuild(1).
-"""
-
-__all__ = [ 'ManifestEnv', ]
-
-import os
-import copy
-import logging
-
-from roverlay import util
-
-class ManifestEnv ( object ):
- """per-repo environment container for Manifest creation using ebuild."""
-
- @classmethod
- def get_new ( cls ):
- return cls ( filter_env=True ).get_env (
- distdir="", portage_ro_distdirs=""
- )
- # --- end of get_new (...) ---
-
- def __init__ ( self, filter_env=True ):
- """Initializes a ManifestEnv.
-
- arguments:
- * filter_env -- if True: start with an empty env and copy vars
- from os.environ selectively
- else : start with os.environ as env
- """
- self.filter_env = filter_env
- self._manenv = dict()
- self.logger = logging.getLogger ( 'ManifestEnv' )
- self._common_env = None
- # --- end of __init__ (...) ---
-
- def get_env ( self, distdir, portage_ro_distdirs ):
- """Returns an env dict for repo_dir.
-
- arguments:
- * repo_dir --
- """
- env = self._get_common_manifest_env()
- env ['DISTDIR'] = distdir
- env ['PORTAGE_RO_DISTDIRS'] = portage_ro_distdirs
- return env
- # --- end of get_env (...) ---
-
- def _get_common_manifest_env ( self, noret=False ):
- """Creates an environment suitable for an
- "ebuild <ebuild> digest|manifest" call (or uses an already existing env).
- Returns a shallow copy of this env which can then be locally modified
- (setting DISTDIR, PORTAGE_RO_DISTDIRS).
-
- arguments:
- * noret -- do not return copied env if True
- """
-
- if self._common_env is None:
-
- if self.filter_env:
-
- # selectively import os.environ
- our_env = util.keepenv (
- ( 'PATH', '' ),
- 'LANG',
- 'PWD',
- 'EBUILD_DEFAULT_OPTS'
- )
- else:
- # copy os.environ
- our_env = dict ( os.environ )
-
- # -- common env part
-
- # set FEATURES
- # * digest -- needed? (works without it)
- # * assume-digests --
- # * unknown-features-warn -- should FEATURES ever change
- #
- # * noauto -- should prevent ebuild from adding additional actions,
- # it still tries to download source packages, which is just wrong
- # here 'cause it is expected that the R package file exists when
- # calling this function, so FETCHCOMMAND/RESUMECOMMAND will be set
- # to /bin/true if possible.
- #
- # * distlocks -- disabled if FETCHCOMMAND/RESUMECOMMAND set to no-op
- #
- our_env ['FEATURES'] = \
- "noauto digest assume-digests unknown-features-warn"
-
- # try to prevent src fetching
- fetch_nop = util.sysnop (
- nop_returns_success=True,
- format_str="{nop} \${{DISTDIR}} \${{FILE}} \${{URI}}"
- )
-
- if not fetch_nop is None:
- self.logger.debug (
- fetch_nop [0] + " disables/replaces FETCHCOMMAND,RESUMECOMMAND."
- )
- our_env ['FETCHCOMMAND'] = fetch_nop [1]
- our_env ['RESUMECOMMAND'] = fetch_nop [1]
- our_env ['FEATURES'] += " -distlocks"
-
-
- self._common_env = our_env
- # -- end if
- if noret:
- return None
- else:
- return copy.copy ( self._common_env )
- # --- end of _get_common_manifest_env (...) ---
diff --git a/roverlay/overlay/pkgdir/manifest/manifest_ebuild.py b/roverlay/overlay/pkgdir/manifest/manifest_ebuild.py
deleted file mode 100644
index 1004381..0000000
--- a/roverlay/overlay/pkgdir/manifest/manifest_ebuild.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# R overlay -- manifest package, manifest helpers (actual implementation)
-# -*- coding: utf-8 -*-
-# Copyright (C) 2012 André Erdmann <dywi@mailerd.de>
-# Distributed under the terms of the GNU General Public License;
-# either version 2 of the License, or (at your option) any later version.
-
-"""manifest helpers (actual implementation)
-
-This module implements Manifest creation using ebuild(1).
-"""
-
-__all__ = [ 'ExternalManifestCreation', ]
-
-import os.path
-import copy
-import logging
-import subprocess
-
-
-import roverlay.overlay.pkgdir.distroot.static
-
-from roverlay import config, strutil
-
-from roverlay.overlay.pkgdir.manifest.env import ManifestEnv
-
-class ExternalManifestCreation ( object ):
- """This class implements Manifest creation using the low level ebuild
- interface, ebuild(1), which is called in a filtered environment.
- """
- # NOTE:
- # ebuild <ebuild> digest does not support multiprocesses for one overlay,
-
- def _doinit ( self ):
- """Initializes self's data, needs an initialized ConfigTree."""
- self.manifest_env = ManifestEnv.get_new()
- self.ebuild_tgt = config.get_or_fail ( 'TOOLS.EBUILD.target' )
- self.ebuild_prog = config.get_or_fail ( 'TOOLS.EBUILD.prog' )
-
- # set PORDIR_OVERLAY and DISTDIR
- self.manifest_env ['PORTDIR_OVERLAY'] = config.get_or_fail (
- 'OVERLAY.dir'
- )
- # self.distroot[.get_distdir(...)] replaces the __tmp__ directory
- self.distroot = (
- roverlay.overlay.pkgdir.distroot.static.get_configured ( static=True )
- )
-
- self._initialized = True
- # --- end of _doinit (...) ---
-
- def __init__ ( self, lazy_init=False ):
- self.logger = logging.getLogger ( 'ManifestCreation' )
- self._initialized = False
- if not lazy_init:
- self._doinit()
- # --- end of __init__ (...) ---
-
- def create_for ( self, package_info_list ):
- """See ManifestCreation.create_for.
- Calls ebuild, returns True on success else False.
-
- raises: *passes Exceptions from failed config lookups
- """
- if not self._initialized:
- self._doinit()
-
- # choosing one ebuild for calling "ebuild <ebuild>" is sufficient
- ebuild_file = package_info_list [0] ['ebuild_file']
-
- distdir = self.distroot.get_distdir ( package_info_list [0] ['name'] )
-
- #
- self.manifest_env ['DISTDIR'] = distdir.get_root()
-
- # add hardlinks to DISTROOT (replacing existing files/links)
- for p in package_info_list:
- # TODO: optimize this further?
- # -> "not has physical_only?"
- # (should be covered by "has package_file")
- distdir.add ( p ['package_file'], p ['package_src_destpath'] )
-
- ebuild_call = subprocess.Popen (
- (
- self.ebuild_prog,
- ebuild_file,
- self.ebuild_tgt
- ),
- stdin=None,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- env=self.manifest_env
- )
-
- output = ebuild_call.communicate()
-
- # log stderr
- for line in strutil.pipe_lines ( output [1], use_filter=True ):
- self.logger.warning ( line )
-
- if ebuild_call.returncode == 0:
- self.logger.debug ( "Manifest written." )
- return True
- else:
- self.logger.error (
- 'Couldn\'t create Manifest for {ebuild}! '
- 'Return code was {ret}.'.format (
- ebuild=ebuild_file, ret=ebuild_call.returncode
- )
- )
- return False
- # --- end of create_for (...) ---
diff --git a/roverlay/overlay/pkgdir/packagedir_base.py b/roverlay/overlay/pkgdir/packagedir_base.py
index 0e5ee81..e2f0f09 100644
--- a/roverlay/overlay/pkgdir/packagedir_base.py
+++ b/roverlay/overlay/pkgdir/packagedir_base.py
@@ -119,6 +119,7 @@ class PackageDirBase ( object ):
physical_only=True, pvr=pvr, ebuild_file=efile
)
self._packages [ p ['ebuild_verstr'] ] = p
+ return p
# --- end of _scan_add_package (...) ---
def add ( self, package_info, add_if_physical=False ):
@@ -364,7 +365,7 @@ class PackageDirBase ( object ):
for pvr in pvr_list:
self.purge_package ( pvr )
- assert not self.empty()
+ assert self.empty()
self.fs_cleanup()
# --- end of fs_destroy (...) ---
@@ -521,7 +522,7 @@ class PackageDirBase ( object ):
# write manifest (only if shared_fh is None)
if self._need_manifest and write_manifest:
- if not self.write_manifest():
+ if not self.write_manifest ( ignore_empty=True ):
success = False
# -- has_ebuilds?
@@ -533,6 +534,99 @@ class PackageDirBase ( object ):
return success
# --- end of write (...) ---
+ def import_extra_ebuilds ( self, overwrite, additions_dir ):
+ """Imports ebuilds from an additions dir into this package dir.
+
+ arguments:
+ * overwrite -- whether to overwrite existing ebuilds or not
+ * additions_dir -- additions dir for this package dir
+ """
+
+ def import_ebuild_efile ( pvr, efile_src, fname ):
+ """Imports an ebuild file into this package dir and registers it
+ in self._packages.
+
+ Returns the PackageInfo instance of the imported ebuild.
+
+ arguments:
+ * pvr --
+ * efile_src -- path to the (real, non-symlink) ebuild file
+ * fname -- name of the ebuild file
+ """
+ # this assertion is always true (see EbuildView)
+ assert fname == self.name + '-' + pvr + '.ebuild'
+
+ efile_dest = self.physical_location + os.sep + fname
+
+ ##efile_dest = (
+ ## self.physical_location + os.sep
+ ## + self.name + '-' + pvr + '.ebuild'
+ ##)
+
+ try:
+ # copy the ebuild file
+ shutil.copyfile ( efile_src, efile_dest )
+
+ # create PackageInfo and register it
+ p = PackageInfo (
+ imported=True, pvr=pvr, ebuild_file=efile
+ )
+ self._packages [ p ['ebuild_verstr'] ] = p
+
+
+ # manifest needs to be rewritten
+ self._need_manifest = True
+
+ # fetch SRC_URI?
+ # ebuild <ebuild> fetch?
+
+ # imported ebuilds cannot be used for generating metadata.xml
+ ##self._need_metadata = True
+
+ return p
+ except:
+ # this package dir is "broken" now,
+ # so a new manifest would be good...
+ #
+ # (the program stops when importing fails,
+ # so this is a theoretical case only)
+ #
+ self._need_manifest = True
+
+ if pvr in self._packages:
+ self.purge_package ( pvr )
+
+ if os.access ( efile_dest, os.F_OK ):
+ os.unlink ( efile_dest )
+
+ raise
+ # --- end of import_ebuild_efile (...) ---
+
+ eview = roverlay.overlay.additionsdir.EbuildView ( additions_dir )
+
+ if not self.physical_location:
+ raise Exception (
+ "import_extra_ebuilds() needs a non-virtual package dir!"
+ )
+ elif eview.has_ebuilds():
+ util.dodir ( self.physical_location, mkdir_p=True )
+
+ if not self._packages:
+ for pvr, efile, fname in eview.get_ebuilds():
+ import_ebuild_efile ( pvr, efile, fname )
+
+ elif overwrite:
+ for pvr, efile, fname in eview.get_ebuilds():
+ if pvr in self._packages:
+ self.purge_package ( pvr )
+ import_ebuild_efile ( pvr, efile, fname )
+
+ else:
+ for pvr, efile, fname in eview.get_ebuilds():
+ if pvr not in self._packages:
+ import_ebuild_efile ( pvr, efile, fname )
+ # --- end of import_extra_ebuilds (...) ---
+
def write_ebuilds ( self, overwrite, additions_dir, shared_fh=None ):
"""Writes all ebuilds.
@@ -571,25 +665,59 @@ class PackageDirBase ( object ):
return _success
# --- end of write_ebuild (...) ---
- def patch_ebuild ( efile, patches ):
+ def patch_ebuild ( efile, pvr, patches ):
+ """Applies zero or more patches to an ebuild (file).
+
+ Returns True on success (all patches applied cleanly,
+ where all >= 0), else False.
+
+ Removes the ebuild file if one or more patches failed.
+
+ arguments:
+ * efile -- path to the file that should be patched
+ * pvr -- ${PVR} of the ebuild (used for removing the ebuild)
+ * patches -- list of patch files to be applied, in order
+ """
if patches:
self.logger.info ( "Patching " + str ( efile ) )
self.logger.debug (
"Patches for {} (in that order): {}".format ( efile, patches )
)
- patch_ret = None
+ try:
+ patch_success = True
- for patch in patches:
- patch_ret = roverlay.tools.patch.dopatch (
- filepath=efile, patch=patch, logger=self.logger
- )
+ for patch in patches:
+ patch_ret = roverlay.tools.patch.dopatch (
+ filepath=efile, patch=patch, logger=self.logger
+ )
- if patch_ret != os.EX_OK:
- # TODO
- raise Exception ( patch )
+ if patch_ret != os.EX_OK:
+ self.logger.error (
+ "failed to apply patch {!r}!".format ( patch )
+ )
+ patch_success = False
+ break
- return True
+ except Exception as err:
+ # ^ which exceptions exactly?
+ self.logger.exception ( err )
+ patch_success = False
+ # -- end try;
+
+ if patch_success:
+ return True
+ else:
+ self.logger.error (
+ 'Removing ebuild {!r} due to errors '
+ 'while patching it.'.format ( efile )
+ )
+ # don't set need_manifest here (not required and
+ # write_manifest() would fail if no ebuild written)
+ #
+ ##self._need_manifest = True
+ self.purge_package ( pvr )
+ return False
else:
return True
# --- end of patch_ebuild (...) ---
@@ -614,7 +742,7 @@ class PackageDirBase ( object ):
patchview = roverlay.overlay.additionsdir.PatchView ( additions_dir )
haspatch = patchview.has_patches()
- for pvr, efile, p_info in ebuilds_to_write():
+ for pvr, efile, p_info in list ( ebuilds_to_write() ):
if not hasdir:
util.dodir ( self.physical_location, mkdir_p=True )
hasdir = True
@@ -623,7 +751,7 @@ class PackageDirBase ( object ):
write_ebuild ( efile, p_info ['ebuild'] )
) and (
not haspatch
- or patch_ebuild ( efile, patchview.get_patches ( pvr ) )
+ or patch_ebuild ( efile, pvr, patchview.get_patches ( pvr ) )
):
self._need_manifest = True
diff --git a/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py b/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py
index 1801a08..c9e3d84 100644
--- a/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py
+++ b/roverlay/overlay/pkgdir/packagedir_ebuildmanifest.py
@@ -6,17 +6,36 @@
__all__ = [ 'PackageDir', ]
-from roverlay.overlay.pkgdir import manifest
-from roverlay.overlay.pkgdir import packagedir_base
+import threading
+import roverlay.config
+import roverlay.tools.ebuild
+import roverlay.tools.ebuildenv
+import roverlay.overlay.pkgdir.packagedir_base
+import roverlay.overlay.pkgdir.distroot.static
-class PackageDir ( packagedir_base.PackageDirBase ):
+
+class PackageDir ( roverlay.overlay.pkgdir.packagedir_base.PackageDirBase ):
"""
PackageDir class that uses the ebuild executable for Manifest writing.
"""
-
+ #DISTROOT = None
+ #MANIFEST_ENV = None
+ MANIFEST_LOCK = threading.Lock()
MANIFEST_THREADSAFE = False
+ @classmethod
+ def init_cls ( cls ):
+ env = roverlay.tools.ebuildenv.ManifestEnv()
+ env.add_overlay_dir ( roverlay.config.get_or_fail ( 'OVERLAY.dir' ) )
+
+ cls.DISTROOT = (
+ roverlay.overlay.pkgdir.distroot.static.get_configured ( static=True )
+ )
+
+ cls.MANIFEST_ENV = env
+ # --- end of init_cls (...) ---
+
def _write_manifest ( self, pkgs_for_manifest ):
"""Generates and writes the Manifest file for this package.
@@ -24,6 +43,44 @@ class PackageDir ( packagedir_base.PackageDirBase ):
returns: success (True/False)
"""
+ try:
+ self.MANIFEST_LOCK.acquire()
+
+ # choosing one ebuild for calling "ebuild <ebuild>" is sufficient
+ ebuild_file = pkgs_for_manifest [0] ['ebuild_file']
+
+ distdir = self.DISTROOT.get_distdir ( pkgs_for_manifest [0] ['name'] )
+
+ # add hardlinks to DISTROOT (replacing existing files/links)
+ for p in pkgs_for_manifest:
+ # TODO: optimize this further?
+ # -> "not has physical_only?"
+ # (should be covered by "has package_file")
+ distdir.add ( p ['package_file'], p ['package_src_destpath'] )
+
+
+ if roverlay.tools.ebuild.doebuild_manifest (
+ ebuild_file, self.logger,
+ self.MANIFEST_ENV.get_env ( distdir.get_root() )
+ ):
+ self.logger.debug ( "Manifest written." )
+ ret = True
+
+ else:
+ self.logger.error (
+ 'Couldn\'t create Manifest for {ebuild}! '
+ 'Return code was {ret}.'.format (
+ ebuild=ebuild_file, ret=ebuild_call.returncode
+ )
+ )
+ ret = False
+
+ except Exception as err:
+ self.logger.exception ( err )
+ raise
+
+ finally:
+ self.MANIFEST_LOCK.release()
- return manifest.create_manifest ( pkgs_for_manifest, nofail=False )
+ return ret
# --- end of write_manifest (...) ---
diff --git a/roverlay/tools/ebuild.py b/roverlay/tools/ebuild.py
new file mode 100644
index 0000000..d9f4e9a
--- /dev/null
+++ b/roverlay/tools/ebuild.py
@@ -0,0 +1,55 @@
+# R overlay -- tools, run ebuild(1)
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+# NOTE:
+# this module has to be loaded after reading roverlay's config
+#
+
+import roverlay.tools.runcmd
+
+import roverlay.config
+import roverlay.util
+
+_EBUILD_CMDV = (
+ roverlay.config.get_or_fail ( 'TOOLS.EBUILD.exe' ),
+)
+
+def doebuild (
+ ebuild_file, command, logger, env=None, opts=(), return_success=True
+):
+ return roverlay.tools.runcmd.run_command (
+ cmdv = ( _EBUILD_CMDV + opts + ( ebuild_file, command ) ),
+ env = env,
+ logger = logger,
+ return_success = return_success
+ )
+# --- end of doebuild (...) ---
+
+def doebuild_manifest (
+ ebuild_file, logger, env=None, opts=(), return_success=True
+):
+ return doebuild (
+ ebuild_file = ebuild_file,
+ command = "manifest",
+ logger = logger,
+ env = env,
+ opts = opts,
+ return_success = return_success,
+ )
+# --- end of doebuild_manifest (...) ---
+
+def doebuild_fetch (
+ ebuild_file, logger, env=None, opts=(), return_success=True
+):
+ return doebuild (
+ ebuild_file = ebuild_file,
+ command = "fetch",
+ logger = logger,
+ env = env,
+ opts = ( '--skip-manifest', ) + opts,
+ return_success = return_success,
+ )
+# --- end of doebuild_fetch (...) ---
diff --git a/roverlay/tools/ebuildenv.py b/roverlay/tools/ebuildenv.py
new file mode 100644
index 0000000..40f6495
--- /dev/null
+++ b/roverlay/tools/ebuildenv.py
@@ -0,0 +1,135 @@
+# R overlay -- tools, env for ebuild.py
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+import os
+import copy
+import logging
+
+import roverlay.util
+
+class EbuildEnv ( object ):
+
+ def __init__ ( self, filter_env=True ):
+ """Initializes an EbuildEnv.
+
+ arguments:
+ * filter_env -- if True: start with an empty env and copy vars
+ from os.environ selectively
+ else : start with os.environ as env
+ """
+ self.filter_env = filter_env
+ self.logger = logging.getLogger ( 'ManifestEnv' )
+ self._common_env = None
+ # --- end of __init__ (...) ---
+
+ def add_info ( self, info, **kwargs ):
+ self._get_common_env ( True )
+ self._common_env.update ( info )
+ self._common_env.update ( kwargs )
+ # --- end of add_info (...) ---
+
+ def _get_env ( self, additional_info ):
+ env = self._get_common_env()
+ env.update ( additional_info )
+ return env
+ # --- end of get_env (...) ---
+
+ def get_distdir_env ( self, distdir ):
+ """Returns an onv dict for distdir.
+
+ arguments:
+ * distdir --
+ """
+ return self._get_env ( { 'DISTDIR': distdir } )
+ # --- end of get_distdir_env (...) ---
+
+ get_env = get_distdir_env
+
+ def add_overlay_dir ( self, overlay_dir ):
+ self._make_common_env()
+ self._common_env ['PORTDIR_OVERLAY'] = overlay_dir
+ # --- end of add_overlay_dir (...) ---
+
+ def _make_common_env ( self ):
+ if self.filter_env:
+
+ # selectively import os.environ
+ our_env = roverlay.util.keepenv (
+ ( 'PATH', '' ),
+ 'LANG',
+ 'PWD',
+ 'EBUILD_DEFAULT_OPTS'
+ )
+ else:
+ # copy os.environ
+ our_env = dict ( os.environ )
+
+ # -- common env part
+
+ # set FEATURES
+ # * digest -- needed? (works without it)
+ # * assume-digests --
+ # * unknown-features-warn -- should FEATURES ever change
+ #
+ # * noauto -- should prevent ebuild from adding additional actions,
+ # it still tries to download source packages, which is just wrong
+ # here 'cause it is expected that the R package file exists when
+ # calling this function, so FETCHCOMMAND/RESUMECOMMAND will be set
+ # to /bin/true if possible.
+ #
+ our_env ['FEATURES'] = \
+ "noauto digest assume-digests unknown-features-warn"
+
+ self._common_env = our_env
+ # --- end of _make_common_env (...) ---
+
+ def _get_common_env ( self ):
+ """Creates an environment suitable for an
+ "ebuild <ebuild> digest|manifest" call (or uses an already existing env).
+ Returns a shallow copy of this env which can then be locally modified
+ (setting DISTDIR, PORTAGE_RO_DISTDIRS).
+ """
+
+ if self._common_env is None:
+ self._make_common_env()
+
+ return copy.copy ( self._common_env )
+ # --- end of _get_common_env (...) ---
+
+# --- end of EbuildEnv ---
+
+class FetchEnv ( EbuildEnv ):
+ pass
+# --- end of FetchEnv ---
+
+
+class ManifestEnv ( EbuildEnv ):
+ """per-repo environment container for Manifest creation using ebuild."""
+
+ def _make_common_env ( self ):
+ super ( ManifestEnv, self )._make_common_env()
+
+ # set FETCHCOMMAND, RESUMECOMMAND and extend FEATURES:
+ # * distlocks -- disabled if FETCHCOMMAND/RESUMECOMMAND set to no-op
+ #
+
+ # try to prevent src fetching
+ fetch_nop = roverlay.util.sysnop (
+ nop_returns_success=True,
+ format_str="{nop} \${{DISTDIR}} \${{FILE}} \${{URI}}"
+ )
+
+ if not fetch_nop is None:
+ self.logger.debug (
+ fetch_nop [0] + " disables/replaces FETCHCOMMAND,RESUMECOMMAND."
+ )
+
+ self._common_env ['FETCHCOMMAND'] = fetch_nop [1]
+ self._common_env ['RESUMECOMMAND'] = fetch_nop [1]
+ self._common_env ['FEATURES'] += " -distlocks"
+ # --- end of _make_common_env (...) ---
+
+# --- end of ManifestEnv ---
diff --git a/roverlay/tools/patch.py b/roverlay/tools/patch.py
index 119ff80..ff48968 100644
--- a/roverlay/tools/patch.py
+++ b/roverlay/tools/patch.py
@@ -4,42 +4,28 @@
# Distributed under the terms of the GNU General Public License;
# either version 2 of the License, or (at your option) any later version.
-import subprocess
+# NOTE:
+# this module has to be loaded after reading roverlay's config
+#
+
+import roverlay.tools.runcmd
import roverlay.config
-import roverlay.strutil
import roverlay.util
_PATCHENV = roverlay.util.keepenv (
( 'PATH', '' ), 'LANG', 'LC_ALL', 'PWD', 'TMPDIR'
)
-# NOTE:
-# this module has to be loaded after reading roverlay's config
-#
-
-_PATCHOPTS = (
+_PATCH_CMDV = (
( roverlay.config.get_or_fail ( "TOOLS.PATCH.exe" ), )
+ roverlay.config.get_or_fail ( "TOOLS.PATCH.opts" )
)
def dopatch ( filepath, patch, logger ):
- print ( "RUN PATCH", filepath, patch )
- patch_call = subprocess.Popen (
- _PATCHOPTS + (
- filepath, patch
- ),
- stdin=None,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- env=_PATCHENV,
- )
-
- output = patch_call.communicate()
-
- # log stderr
- for line in roverlay.strutil.pipe_lines ( output [1], use_filter=True ):
- logger.warning ( line )
-
- return patch_call.returncode
+ return roverlay.tools.runcmd.run_command (
+ cmdv = ( _PATCH_CMDV + ( filepath, patch ) ),
+ env = _PATCHENV,
+ logger = logger
+ ).returncode
# --- end of dopatch (...) ---
diff --git a/roverlay/tools/runcmd.py b/roverlay/tools/runcmd.py
new file mode 100644
index 0000000..e6b4f19
--- /dev/null
+++ b/roverlay/tools/runcmd.py
@@ -0,0 +1,37 @@
+# R overlay -- tools, run a command
+# -*- coding: utf-8 -*-
+# Copyright (C) 2013 André Erdmann <dywi@mailerd.de>
+# Distributed under the terms of the GNU General Public License;
+# either version 2 of the License, or (at your option) any later version.
+
+import os
+import subprocess
+
+import roverlay.strutil
+
+DEBUG_TO_CONSOLE = True
+
+def run_command ( cmdv, env, logger, return_success=False ):
+ if DEBUG_TO_CONSOLE:
+ cmd_call = subprocess.Popen ( cmdv, stdin=None, env=env )
+ else:
+ cmd_call = subprocess.Popen (
+ cmdv,
+ stdin=None,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ env=env,
+ )
+
+ output = cmd_call.communicate()
+
+ # log stderr
+ if output [1]:
+ for line in roverlay.strutil.pipe_lines ( output [1], use_filter=True ):
+ logger.warning ( line )
+
+ if return_success:
+ return cmd_call.returncode == os.EX_OK
+ else:
+ return cmd_call
+# --- end of run_command (...) ---
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2013-06-13 16:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-08 16:21 [gentoo-commits] proj/R_overlay:gsoc13/next commit in: roverlay/overlay/pkgdir/manifest/, roverlay/tools/, roverlay/config/, André Erdmann
2013-06-13 16:34 ` [gentoo-commits] proj/R_overlay:master " André Erdmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox