diff options
author | André Erdmann <dywi@mailerd.de> | 2013-02-05 21:48:45 +0100 |
---|---|---|
committer | André Erdmann <dywi@mailerd.de> | 2013-02-05 21:53:10 +0100 |
commit | ea138f2357586d89b72301558e2f595ce5fba812 (patch) | |
tree | b49d0a97fcd6f46d9e29957d25563c88956b5d64 | |
parent | packagedir_portagemanifest: fix indent typo (diff) | |
download | R_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.py | 195 |
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() |