summaryrefslogtreecommitdiffstats
path: root/pym/_emerge/EbuildBuildDir.py
blob: af3ce0792c5625bad44c078b8cbdb2c871ef6bc7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# Copyright 1999-2010 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2

from _emerge.AsynchronousLock import AsynchronousLock
from _emerge.SlotObject import SlotObject
import portage
from portage import os
import errno

class EbuildBuildDir(SlotObject):

	__slots__ = ("dir_path", "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.dir_path
		catdir = os.path.dirname(dir_path)
		self._catdir = catdir

		portage.util.ensure_dirs(os.path.dirname(catdir),
			gid=portage.portage_gid,
			mode=0o70, mask=0)
		catdir_lock = AsynchronousLock(path=catdir, scheduler=self.scheduler)
		catdir_lock.start()
		catdir_lock.wait()
		try:
			portage.util.ensure_dirs(catdir,
				gid=portage.portage_gid,
				mode=0o70, mask=0)
			builddir_lock = AsynchronousLock(path=dir_path,
				scheduler=self.scheduler)
			builddir_lock.start()
			builddir_lock.wait()
			self._lock_obj = builddir_lock.lock_obj
			self.settings['PORTAGE_BUILDIR_LOCKED'] = '1'
		finally:
			self.locked = self._lock_obj is not None
			catdir_lock.unlock()

	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

		portage.locks.unlockdir(self._lock_obj)
		self._lock_obj = None
		self.locked = False
		self.settings.pop('PORTAGE_BUILDIR_LOCKED', None)

		catdir = self._catdir
		catdir_lock = None
		try:
			catdir_lock = portage.locks.lockdir(catdir)
		finally:
			if catdir_lock:
				try:
					os.rmdir(catdir)
				except OSError as e:
					if e.errno not in (errno.ENOENT,
						errno.ENOTEMPTY, errno.EEXIST):
						raise
					del e
				portage.locks.unlockdir(catdir_lock)

	class AlreadyLocked(portage.exception.PortageException):
		pass