blob: 58905c2f60ef7005f58564beb50bd76f5b58aa30 [file] [log] [blame]
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from _emerge.AsynchronousLock import AsynchronousLock
import portage
from portage import os
from portage.exception import PortageException
from portage.util.SlotObject import SlotObject
class EbuildBuildDir(SlotObject):
__slots__ = ("scheduler", "settings",
"locked", "_catdir", "_lock_obj")
def __init__(self, **kwargs):
SlotObject.__init__(self, **kwargs)
self.locked = False
def lock(self):
"""
This raises an AlreadyLocked exception if lock() is called
while a lock is already held. In order to avoid this, call
unlock() or check whether the "locked" attribute is True
or False before calling lock().
"""
if self._lock_obj is not None:
raise self.AlreadyLocked((self._lock_obj,))
dir_path = self.settings.get('PORTAGE_BUILDDIR')
if not dir_path:
raise AssertionError('PORTAGE_BUILDDIR is unset')
catdir = os.path.dirname(dir_path)
self._catdir = catdir
try:
portage.util.ensure_dirs(os.path.dirname(catdir),
gid=portage.portage_gid,
mode=0o70, mask=0)
except PortageException:
if not os.path.isdir(os.path.dirname(catdir)):
raise
catdir_lock = AsynchronousLock(path=catdir, scheduler=self.scheduler)
catdir_lock.start()
catdir_lock.wait()
self._assert_lock(catdir_lock)
try:
try:
portage.util.ensure_dirs(catdir,
gid=portage.portage_gid,
mode=0o70, mask=0)
except PortageException:
if not os.path.isdir(catdir):
raise
builddir_lock = AsynchronousLock(path=dir_path,
scheduler=self.scheduler)
builddir_lock.start()
builddir_lock.wait()
self._assert_lock(builddir_lock)
self._lock_obj = builddir_lock
self.settings['PORTAGE_BUILDDIR_LOCKED'] = '1'
finally:
self.locked = self._lock_obj is not None
catdir_lock.unlock()
def _assert_lock(self, async_lock):
if async_lock.returncode != os.EX_OK:
# TODO: create a better way to propagate this error to the caller
raise AssertionError("AsynchronousLock failed with returncode %s" \
% (async_lock.returncode,))
def clean_log(self):
"""Discard existing log. The log will not be be discarded
in cases when it would not make sense, like when FEATURES=keepwork
is enabled."""
settings = self.settings
if 'keepwork' in settings.features:
return
log_file = settings.get('PORTAGE_LOG_FILE')
if log_file is not None and os.path.isfile(log_file):
try:
os.unlink(log_file)
except OSError:
pass
def unlock(self):
if self._lock_obj is None:
return
self._lock_obj.unlock()
self._lock_obj = None
self.locked = False
self.settings.pop('PORTAGE_BUILDDIR_LOCKED', None)
catdir_lock = AsynchronousLock(path=self._catdir, scheduler=self.scheduler)
catdir_lock.start()
if catdir_lock.wait() == os.EX_OK:
try:
os.rmdir(self._catdir)
except OSError:
pass
finally:
catdir_lock.unlock()
class AlreadyLocked(portage.exception.PortageException):
pass