aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Erdmann <dywi@mailerd.de>2013-02-05 21:48:45 +0100
committerAndré Erdmann <dywi@mailerd.de>2013-02-05 21:53:10 +0100
commitea138f2357586d89b72301558e2f595ce5fba812 (patch)
treeb49d0a97fcd6f46d9e29957d25563c88956b5d64
parentpackagedir_portagemanifest: fix indent typo (diff)
downloadR_overlay-ea138f2357586d89b72301558e2f595ce5fba812.tar.gz
R_overlay-ea138f2357586d89b72301558e2f595ce5fba812.tar.bz2
R_overlay-ea138f2357586d89b72301558e2f595ce5fba812.zip
overlay/pkgdir/symlink/distroot: HardlinkDistroot
added HardlinkDistroot, a distroot class that manages package files in a flat hardlink structure (one dir for all links). This will be used as replacement for the __tmp__ dir in pkgdir_ebuildmanifest.
-rw-r--r--roverlay/overlay/pkgdir/symlink/distroot.py195
1 files changed, 143 insertions, 52 deletions
diff --git a/roverlay/overlay/pkgdir/symlink/distroot.py b/roverlay/overlay/pkgdir/symlink/distroot.py
index 7345d98..269be94 100644
--- a/roverlay/overlay/pkgdir/symlink/distroot.py
+++ b/roverlay/overlay/pkgdir/symlink/distroot.py
@@ -4,7 +4,10 @@
# Distributed under the terms of the GNU General Public License;
# either version 2 of the License, or (at your option) any later version.
-__all__ = [ 'SymlinkDistroot', 'ThreadsafeSymlinkDistroot' ]
+__all__ = [
+ 'SymlinkDistroot', 'ThreadsafeSymlinkDistroot', 'HardlinkDistroot',
+ 'LinkDistrootBase',
+]
import os
import atexit
@@ -17,26 +20,14 @@ import roverlay.config
import roverlay.overlay.pkgdir.symlink.distdir
-class _SymlinkDistrootBase ( object ):
+class LinkDistrootBase ( object ):
+ """Base class for sym-/hardlink distroots."""
_instance_lock = threading.Lock()
- __instance = None
@classmethod
def get_configured ( cls ):
- """Returns the static SymlinkDistroot instance."""
- if cls.__instance is None:
- with cls._instance_lock:
- if cls.__instance is None:
- cls.__instance = cls (
- root = roverlay.config.get (
- 'OVERLAY.SYMLINK_DISTROOT.root', ""
- ),
- is_tmpdir = roverlay.config.get_or_fail (
- 'OVERLAY.SYMLINK_DISTROOT.tmp'
- ),
- )
- return cls.__instance
+ raise NotImplementedError()
# --- end of get_configured (...) ---
def __repr__ ( self ):
@@ -50,7 +41,7 @@ class _SymlinkDistrootBase ( object ):
# --- end of __str__ (...) ---
def __init__ ( self, root, is_tmpdir ):
- """Initializes a _SymlinkDistrootBase instance.
+ """Initializes a LinkDistrootBase instance.
arguments:
* root -- root directory where per-package SymlinkDistdirs will
@@ -65,7 +56,7 @@ class _SymlinkDistrootBase ( object ):
Raises: ConfigError if root is not set and is_tmpdir evaluates to False.
"""
- super ( _SymlinkDistrootBase, self ).__init__()
+ super ( LinkDistrootBase, self ).__init__()
self._root = root
self._is_tmpdir = bool ( is_tmpdir )
@@ -116,10 +107,135 @@ class _SymlinkDistrootBase ( object ):
# --- end of get (...) ---
def _prepare ( self ):
+ """Prepares the distroot.
+ Called for both temporary and persistent distroots.
+ """
+ pass
+ # --- end of _prepare (...) ---
+
+ def get ( self, package_name ):
+ """Returns a distdir object for the given package.
+
+ arguments:
+ * package_name
+
+ Has to be implemented by derived classes.
+
+ Note: the returned object can also be this object ("self")
+ """
+ raise NotImplementedError()
+ # --- end of get (...) ---
+
+# --- end of LinkDistrootBase ---
+
+class HardlinkDistroot ( LinkDistrootBase ):
+ """A directory that combines distroot and distdir functionality and
+ manages distfiles using hardlinks.
+
+ => flat structure (single dir that contains links to all package files)
+ """
+
+ __instance = None
+
+ @classmethod
+ def get_configured ( cls ):
+ """Returns the static SymlinkDistroot instance.
+
+ Relevant config keys:
+ * OVERLAY.HARDLINK_DISTROOT.root
+ """
+ if cls.__instance is None:
+ with cls._instance_lock:
+ if cls.__instance is None:
+ cls.__instance = cls (
+ root = roverlay.config.get (
+ 'OVERLAY.HARDLINK_DISTROOT.root', ""
+ ),
+ )
+ return cls.__instance
+ # --- end of get_configured (...) ---
+
+ def __init__ ( self, root ):
+ # is_tmpdir does not seem to be useful for this class
+ super ( HardlinkDistroot ).__init__ (
+ root = root,
+ is_tmpdir = False
+ )
+ # --- end of __init__ (...) ---
+
+ def get ( self, package_name ):
+ # compat function
+ return self
+ # --- end of get (...) ---
+
+ def add ( self, fpath, fname=None ):
+ """Adds a hardlink to a file to this dir.
+
+ Replaces existing files/hardlinks.
+
+ arguments:
+ * fpath -- path to the file for which a symlink will be created
+ * fname -- name of the symlink, defaults to os.path.basename ( fpath )
+ """
+ hardlink = self.root + os.sep + ( fname or os.path.basename ( fpath ) )
+
+ # assume that the hardlink already exists
+ try:
+ os.unlink ( hardlink )
+ except OSError as oserr:
+ if oserr.errno == 2:
+ pass
+ else:
+ raise
+
+ os.link ( fpath, hardlink )
+ # --- end of add (...) ---
+
+# --- end of HardlinkDistroot ---
+
+class SymlinkDistroot ( LinkDistrootBase ):
+ """A symlink distroot that uses a dict to remember
+ per-package SymlinkDistdirs.
+ """
+
+ __instance = None
+
+ @classmethod
+ def get_configured ( cls ):
+ """Returns the static SymlinkDistroot instance.
+
+ Relevant config keys:
+ * OVERLAY.SYMLINK_DISTROOT.root
+ * OVERLAY.SYMLINK_DISTROOT.tmp
+ """
+ if cls.__instance is None:
+ with cls._instance_lock:
+ if cls.__instance is None:
+ cls.__instance = cls (
+ root = roverlay.config.get (
+ 'OVERLAY.SYMLINK_DISTROOT.root', ""
+ ),
+ is_tmpdir = roverlay.config.get_or_fail (
+ 'OVERLAY.SYMLINK_DISTROOT.tmp'
+ ),
+ )
+ return cls.__instance
+ # --- end of get_configured (...) ---
+
+ # _not_ threadsafe, but get() is expected to be called
+ # within a (per-package_name) threadsafe context
+
+ def __init__ ( self, *args, **kwargs ):
+ """see LinkDistrootBase.__init__()"""
+ super ( SymlinkDistroot, self ).__init__ ( *args, **kwargs )
+ self._subdirs = dict()
+ # --- end of __init__ (...) ---
+
+ def _prepare ( self ):
"""Prepares the SymlinkDistroot. Called for both temporary and
persistent distroots.
- The default actions is to remove broken symlinks.
+ The default action is to remove broken symlinks.
"""
if not self._is_tmpdir:
self.remove_broken_symlinks ( unsafe_assumptions=True )
@@ -129,11 +245,13 @@ class _SymlinkDistrootBase ( object ):
"""Returns a SymlinkDistdir for the given package.
arguments:
- * package_name
-
- Has to be implemented by derived classes.
+ * package_name --
"""
- raise NotImplementedError()
+ try:
+ return self._subdirs [package_name]
+ except KeyError:
+ self._subdirs [package_name] = self._get ( package_name )
+ return self._subdirs [package_name]
# --- end of get (...) ---
def remove_broken_symlinks ( self, unsafe_assumptions=False ):
@@ -180,35 +298,6 @@ class _SymlinkDistrootBase ( object ):
# --- end of remove_broken_symlinks (...) ---
-# --- end of _SymlinkDistrootBase ---
-
-class SymlinkDistroot ( _SymlinkDistrootBase ):
- """A symlink distroot that uses a dict to remember
- per-package SymlinkDistdirs.
- """
-
- # _not_ threadsafe, but get() is expected to be called
- # within a (per-package_name) threadsafe context
-
- def __init__ ( self, *args, **kwargs ):
- """see _SymlinkDistrootBase.__init__()"""
- super ( SymlinkDistroot, self ).__init__ ( *args, **kwargs )
- self._subdirs = dict()
- # --- end of __init__ (...) ---
-
- def get ( self, package_name ):
- """Returns a SymlinkDistdir for the given package.
-
- arguments:
- * package_name --
- """
- try:
- return self._subdirs [package_name]
- except KeyError:
- self._subdirs [package_name] = self._get ( package_name )
- return self._subdirs [package_name]
- # --- end of get (...) ---
-
# --- end of SymlinkDistroot ---
class ThreadsafeSymlinkDistroot ( SymlinkDistroot ):
@@ -216,6 +305,8 @@ class ThreadsafeSymlinkDistroot ( SymlinkDistroot ):
# will be removed if SymlinkDistroot is sufficient.
+ __instance = None
+
def __init__ ( self, *args, **kwargs ):
super ( ThreadsafeSymlinkDistroot, self ).__init__ ( *args, **kwargs )
self._lock = threading.Lock()