1
2
3
4 __all__ = (
5 'LicenseManager',
6 )
7
8 from portage import os
9 from portage.dep import ExtendedAtomDict, use_reduce
10 from portage.exception import InvalidDependString
11 from portage.localization import _
12 from portage.util import grabdict, grabdict_package, writemsg
13 from portage.versions import cpv_getkey, _pkg_str
14
15 from portage.package.ebuild._config.helper import ordered_by_atom_specificity
16
17
19
20 - def __init__(self, license_group_locations, abs_user_config, user_config=True):
21
22 self._accept_license_str = None
23 self._accept_license = None
24 self._license_groups = {}
25 self._plicensedict = ExtendedAtomDict(dict)
26 self._undef_lic_groups = set()
27
28 if user_config:
29 license_group_locations = list(license_group_locations) + [abs_user_config]
30
31 self._read_license_groups(license_group_locations)
32
33 if user_config:
34 self._read_user_config(abs_user_config)
35
42
44 for loc in locations:
45 for k, v in grabdict(
46 os.path.join(loc, "license_groups")).items():
47 self._license_groups.setdefault(k, []).extend(v)
48
49 for k, v in self._license_groups.items():
50 self._license_groups[k] = frozenset(v)
51
53 ret = old
54 atom_license_map = self._plicensedict.get("*/*")
55 if atom_license_map is not None:
56 v = atom_license_map.pop("*/*", None)
57 if v is not None:
58 ret = " ".join(v)
59 if old:
60 ret = old + " " + ret
61 if not atom_license_map:
62
63 del self._plicensedict["*/*"]
64 return ret
65
67 """ Take a token from ACCEPT_LICENSE or package.license and expand it
68 if it's a group token (indicated by @) or just return it if it's not a
69 group. If a group is negated then negate all group elements."""
70 expanded_tokens = []
71 for x in tokens:
72 expanded_tokens.extend(self._expandLicenseToken(x, None))
73 return expanded_tokens
74
76 negate = False
77 rValue = []
78 if token.startswith("-"):
79 negate = True
80 license_name = token[1:]
81 else:
82 license_name = token
83 if not license_name.startswith("@"):
84 rValue.append(token)
85 return rValue
86 group_name = license_name[1:]
87 if traversed_groups is None:
88 traversed_groups = set()
89 license_group = self._license_groups.get(group_name)
90 if group_name in traversed_groups:
91 writemsg(_("Circular license group reference"
92 " detected in '%s'\n") % group_name, noiselevel=-1)
93 rValue.append("@"+group_name)
94 elif license_group:
95 traversed_groups.add(group_name)
96 for l in license_group:
97 if l.startswith("-"):
98 writemsg(_("Skipping invalid element %s"
99 " in license group '%s'\n") % (l, group_name),
100 noiselevel=-1)
101 else:
102 rValue.extend(self._expandLicenseToken(l, traversed_groups))
103 else:
104 if self._license_groups and \
105 group_name not in self._undef_lic_groups:
106 self._undef_lic_groups.add(group_name)
107 writemsg(_("Undefined license group '%s'\n") % group_name,
108 noiselevel=-1)
109 rValue.append("@"+group_name)
110 if negate:
111 rValue = ["-" + token for token in rValue]
112 return rValue
113
115 """
116 Get an ACCEPT_LICENSE list, accounting for package.license.
117 """
118 accept_license = self._accept_license
119 cp = cpv_getkey(cpv)
120 cpdict = self._plicensedict.get(cp)
121 if cpdict:
122 if not hasattr(cpv, slot):
123 cpv = _pkg_str(cpv, slot=slot, repo=repo)
124 plicence_list = ordered_by_atom_specificity(cpdict, cpv)
125 if plicence_list:
126 accept_license = list(self._accept_license)
127 for x in plicence_list:
128 accept_license.extend(x)
129 return accept_license
130
132 """
133 Generate a pruned version of ACCEPT_LICENSE, by intersection with
134 LICENSE. This is required since otherwise ACCEPT_LICENSE might be
135 too big (bigger than ARG_MAX), causing execve() calls to fail with
136 E2BIG errors as in bug #262647.
137 """
138 try:
139 licenses = set(use_reduce(lic, uselist=use, flat=True))
140 except InvalidDependString:
141 licenses = set()
142 licenses.discard('||')
143
144 accept_license = self._getPkgAcceptLicense(cpv, slot, repo)
145
146 if accept_license:
147 acceptable_licenses = set()
148 for x in accept_license:
149 if x == '*':
150 acceptable_licenses.update(licenses)
151 elif x == '-*':
152 acceptable_licenses.clear()
153 elif x[:1] == '-':
154 acceptable_licenses.discard(x[1:])
155 elif x in licenses:
156 acceptable_licenses.add(x)
157
158 licenses = acceptable_licenses
159 return ' '.join(sorted(licenses))
160
162 """
163 Take a LICENSE string and return a list of any licenses that the user
164 may need to accept for the given package. The returned list will not
165 contain any licenses that have already been accepted. This method
166 can throw an InvalidDependString exception.
167
168 @param cpv: The package name (for package.license support)
169 @type cpv: String
170 @param use: "USE" from the cpv's metadata
171 @type use: String
172 @param lic: "LICENSE" from the cpv's metadata
173 @type lic: String
174 @param slot: "SLOT" from the cpv's metadata
175 @type slot: String
176 @rtype: List
177 @return: A list of licenses that have not been accepted.
178 """
179
180 licenses = set(use_reduce(lic, matchall=1, flat=True))
181 licenses.discard('||')
182
183 acceptable_licenses = set()
184 for x in self._getPkgAcceptLicense(cpv, slot, repo):
185 if x == '*':
186 acceptable_licenses.update(licenses)
187 elif x == '-*':
188 acceptable_licenses.clear()
189 elif x[:1] == '-':
190 acceptable_licenses.discard(x[1:])
191 else:
192 acceptable_licenses.add(x)
193
194 license_str = lic
195 if "?" in license_str:
196 use = use.split()
197 else:
198 use = []
199
200 license_struct = use_reduce(license_str, uselist=use, opconvert=True)
201 return self._getMaskedLicenses(license_struct, acceptable_licenses)
202
204 if not license_struct:
205 return []
206 if license_struct[0] == "||":
207 ret = []
208 for element in license_struct[1:]:
209 if isinstance(element, list):
210 if element:
211 tmp = self._getMaskedLicenses(element, acceptable_licenses)
212 if not tmp:
213 return []
214 ret.extend(tmp)
215 else:
216 if element in acceptable_licenses:
217 return []
218 ret.append(element)
219
220
221 return ret
222
223 ret = []
224 for element in license_struct:
225 if isinstance(element, list):
226 if element:
227 ret.extend(self._getMaskedLicenses(element,
228 acceptable_licenses))
229 else:
230 if element not in acceptable_licenses:
231 ret.append(element)
232 return ret
233
235 if accept_license_str != self._accept_license_str:
236 self._accept_license_str = accept_license_str
237 self._accept_license = tuple(self.expandLicenseTokens(accept_license_str.split()))
238