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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
# R overlay -- overlay package, addition control (abc/base)
# -*- coding: utf-8 -*-
# Copyright (C) 2014 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.
"""overlay package, addition control (abstract/base objects)"""
import abc
from abc import abstractmethod, abstractproperty
try:
from abc import abstractclassmethod
except ImportError:
from abc import abstractmethod as abstractclassmethod
from abc import abstractmethod as abstractstaticmethod
else:
from abc import abstractstaticmethod
import itertools
# __metaclass__/metaclass= workaround
_AbstractObject = abc.ABCMeta ( str("AbstractObject"), ( object, ), {} )
def _gen_bits ( count ):
yield 0
for k in range(count):
yield 2**k
##assert k + 1 == count
yield ( 2**count ) - 1
# --- end of _gen_bits (...) ---
class AdditionControlResult ( object ):
# for package_info-level checks,
# addition control can "recommend" the following actions
# (restricted-inclusive-or; priority as listed in descending order,
# or, more formal, lower integer > 0 means higher priority (and 0 having
# the lowest priority))
#
# Note that any value v with bool(v)==False should be interpreted as
# keep-default-behavior.
# However, at addition-control-rule level, v==None means "rule does
# not care about package", whereas v==PKG_DEFAULT_BEHAVIOR means
# "force default behavior".
# Currently, there's no difference between None/bool(v)==False,
# as addition control is handled by package rules only.
#
#
# force-deny -- always deny the package
# deny-replace -- accept new packages only (**)
# force-replace -- always replace existing ebuilds (***)
# replace-only -- do not add new packages (**)
# revbump-on-collision -- forced revbump if an ebuild exists already
# default-behavior -- no addition control
#
# (**) in this context, "replace" includes revbump checks
# (***) does not trigger revbump logic
#
# force-deny should not be used in package rules,
# because it is inferior to the "do-not-process" action.
# (package_info objects have to be kept in memory only to get rejected
# in package_dir.add_package(), while "do-not-process" filters them out
# immediately)
# There are two use cases, though:
# * in package rules: collapsed branches
# (level1 sets force-deny, level2 resets it)
# * if the control result depends on the package being replaced
# (equal to deny-replace, but faster)
#
(
PKG_DEFAULT_BEHAVIOR,
PKG_FORCE_DENY,
PKG_DENY_REPLACE,
PKG_FORCE_REPLACE,
PKG_REPLACE_ONLY,
PKG_REVBUMP_ON_COLLISION,
PKG_ALL,
) = _gen_bits(5)
PKG_DESCRIPTION_MAP = {
PKG_FORCE_DENY : 'force-deny',
PKG_DENY_REPLACE : 'deny-replace',
PKG_FORCE_REPLACE : 'force-replace',
PKG_REPLACE_ONLY : 'replace-only',
PKG_REVBUMP_ON_COLLISION : 'revbump-on-collision',
PKG_DEFAULT_BEHAVIOR : 'default',
}
PKG_DESCRIPTION_REVMAP = { v: k for k,v in PKG_DESCRIPTION_MAP.items() }
@classmethod
def convert_str ( cls, s ):
desc_rmap = cls.PKG_DESCRIPTION_REVMAP
if not s:
raise ValueError ( "str must not be empty." )
bitmask = 0
for arg in filter ( None, s.strip().lower().split(",") ):
# ^ strip(),lower(),split() ...
print(arg)
try:
bitmask |= desc_rmap [arg]
except KeyError:
raise ValueError ( arg )
# -- end for
return bitmask
# --- end of convert_str (...) ---
@classmethod
def get_reversed_sort_key ( cls, k ):
return (-1) * ( k or cls.PKG_ALL )
# --- end of get_reversed_sort_key (...) ---
@classmethod
def get_sort_key ( cls, k ):
return ( k or cls.PKG_ALL )
# --- end of get_sort_key (...) ---
@classmethod
def get_effective_package_policy ( cls, pkg_policy ):
# hardcoded for now
if not pkg_policy:
return cls.PKG_DEFAULT_BEHAVIOR
elif (pkg_policy & ~cls.PKG_ALL):
raise ValueError("{:#x}: too low/high".format(pkg_policy))
elif pkg_policy & cls.PKG_FORCE_DENY:
return cls.PKG_FORCE_DENY
elif pkg_policy & cls.PKG_DENY_REPLACE:
if pkg_policy & cls.PKG_REPLACE_ONLY:
# deny-replace and replace-only => force-deny
return cls.PKG_FORCE_DENY
else:
return cls.PKG_DENY_REPLACE
elif pkg_policy & cls.PKG_FORCE_REPLACE:
return pkg_policy & (cls.PKG_FORCE_REPLACE|cls.PKG_REPLACE_ONLY)
elif pkg_policy & (cls.PKG_REPLACE_ONLY|cls.PKG_REVBUMP_ON_COLLISION):
return (
pkg_policy & (cls.PKG_REPLACE_ONLY|cls.PKG_REVBUMP_ON_COLLISION)
)
# -- end if
raise NotImplementedError("{:#x} unmatched".format(pkg_policy))
# --- end f get_effective_package_policy (...) ---
# --- end of AdditionControlResult ---
class AbstractAdditionControl ( _AbstractObject, AdditionControlResult ):
## @abstractmethod
## def get_sub_view ( self, key ):
## raise NotImplementedError()
@abstractmethod
def check_package (
self, category, package_dir, new_package, old_package_if_any
):
raise NotImplementedError()
|