1 |
commit: cb20d3f95bd20b528a14126b3d1c545c4ddb1704 |
2 |
Author: Michael Haubenwallner <haubi <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon May 28 16:40:04 2018 +0000 |
4 |
Commit: Michael Haubenwallner <haubi <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon May 28 16:43:59 2018 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/proj/prefix.git/commit/?id=cb20d3f9 |
7 |
|
8 |
sys-apps/portage: bump ebuildshell+prefix-chaining patches |
9 |
|
10 |
Package-Manager: Portage-2.3.24, Repoman-2.3.6 |
11 |
|
12 |
.../portage/files/portage-2.3.40-ebuildshell.patch | 354 ++++++++ |
13 |
.../files/portage-2.3.40-prefix-chaining.patch | 921 +++++++++++++++++++++ |
14 |
sys-apps/portage/portage-2.3.40.1.ebuild | 5 +- |
15 |
3 files changed, 1277 insertions(+), 3 deletions(-) |
16 |
|
17 |
diff --git a/sys-apps/portage/files/portage-2.3.40-ebuildshell.patch b/sys-apps/portage/files/portage-2.3.40-ebuildshell.patch |
18 |
new file mode 100644 |
19 |
index 0000000000..167ed3824e |
20 |
--- /dev/null |
21 |
+++ b/sys-apps/portage/files/portage-2.3.40-ebuildshell.patch |
22 |
@@ -0,0 +1,354 @@ |
23 |
+From 9075d30d24af87f69d23ae129dc75e1305cd3aa8 Mon Sep 17 00:00:00 2001 |
24 |
+From: Michael Haubenwallner <michael.haubenwallner@×××××××.at> |
25 |
+Date: Wed, 6 Nov 2013 12:40:05 +0100 |
26 |
+Subject: [PATCH 1/2] Add ebuildshell feature, bug#155161. |
27 |
+ |
28 |
+--- |
29 |
+ bin/ebuild.sh | 146 ++++++++++++++++++++++++++++++++++- |
30 |
+ bin/filter-bash-environment.py | 55 +++++++++---- |
31 |
+ bin/save-ebuild-env.sh | 2 +- |
32 |
+ man/make.conf.5 | 6 ++ |
33 |
+ pym/_emerge/AbstractEbuildProcess.py | 1 + |
34 |
+ pym/portage/const.py | 1 + |
35 |
+ 6 files changed, 194 insertions(+), 17 deletions(-) |
36 |
+ |
37 |
+diff --git a/bin/ebuild.sh b/bin/ebuild.sh |
38 |
+index f76a48d8e..51ba95cb1 100755 |
39 |
+--- a/bin/ebuild.sh |
40 |
++++ b/bin/ebuild.sh |
41 |
+@@ -121,7 +121,7 @@ __qa_source() { |
42 |
+ __qa_call() { |
43 |
+ local shopts=$(shopt) OLDIFS="$IFS" |
44 |
+ local retval |
45 |
+- "$@" |
46 |
++ __call-ebuildshell "$@" |
47 |
+ retval=$? |
48 |
+ set +e |
49 |
+ [[ $shopts != $(shopt) ]] && |
50 |
+@@ -547,6 +547,150 @@ if [[ -n ${QA_INTERCEPTORS} ]] ; then |
51 |
+ unset BIN_PATH BIN BODY FUNC_SRC |
52 |
+ fi |
53 |
+ |
54 |
++__call-ebuildshell() { |
55 |
++ if ! has ebuildshell ${FEATURES}; then |
56 |
++ "$@" |
57 |
++ return $? |
58 |
++ fi |
59 |
++ local __ebuildshell_args=( "$@" ) |
60 |
++ # These are the variables I have seen 'bash -i' maintaining the values for: |
61 |
++ local __ebuildshell_bash_i_vars="__ebuildshell_.* |
62 |
++ _ BASH_ARGC BASH_ARGV BASH_COMMAND BASH_LINENO BASH_SOURCE |
63 |
++ BASH_VERSINFO BASH_SUBSHELL BASHOPTS BASHPID COMP_WORDBREAKS |
64 |
++ DIRSTACK EUID FUNCNAME GROUPS HISTCMD HISTFILE LINENO PIPESTATUS |
65 |
++ PPID PS1 PS2 PS3 PS4 PWD RANDOM SECONDS SHELLOPTS UID" |
66 |
++ # Allow recursive ebuildshell, for use in multibuild.eclass and similar: |
67 |
++ local __ebuildshell_pid=${BASHPID:-$(__bashpid)} |
68 |
++ local __ebuildshell_tmpf="${T}/ebuildshell.${__ebuildshell_pid}" |
69 |
++ rm -f "${__ebuildshell_tmpf}."{ebuild,return}-{env,rovars} |
70 |
++ ( |
71 |
++ cat <<-EOE |
72 |
++ # local variables of functions using recursive ebuildshell are |
73 |
++ # visible to the EXIT trap of that recursive ebuildshell. To |
74 |
++ # keep them local, we have to filter them from that recursive |
75 |
++ # ebuildshell's return-env. As 'declare -p' is unable to tell |
76 |
++ # local-ity of variables, we abuse the trace attribute for local |
77 |
++ # variables to filter them from the return-env. So we need the |
78 |
++ # local alias active before declaring any functions. |
79 |
++ # On a sidehand, this allows for copy&paste of function body |
80 |
++ # lines including the local keyword. |
81 |
++ alias local='declare -t' |
82 |
++ shopt -s expand_aliases |
83 |
++ EOE |
84 |
++ ( |
85 |
++ declare -p |
86 |
++ declare -fp |
87 |
++ shopt -p |
88 |
++ [[ ${BASH_VERSINFO[0]} == 3 ]] && export |
89 |
++ ) | |
90 |
++ ( |
91 |
++ # we need everything but the bash vars after 'env -i' |
92 |
++ 2>"${__ebuildshell_tmpf}.ebuild-rovars" \ |
93 |
++ "${PORTAGE_PYTHON:-/tools/haubi/gentoo/s01en24/usr/bin/python}" \ |
94 |
++ "${PORTAGE_BIN_PATH}"/filter-bash-environment.py \ |
95 |
++ --report-readonly-variables \ |
96 |
++ --preserve-readonly-attribute \ |
97 |
++ "${__ebuildshell_bash_i_vars}" \ |
98 |
++ || die "filter-bash-environment.py failed" |
99 |
++ ) |
100 |
++ # 'declare -g' is available since bash-4.2, |
101 |
++ # https://bugs.gentoo.org/show_bug.cgi?id=155161#c35 |
102 |
++ if (( ${BASH_VERSINFO[0]} > 4 )) || |
103 |
++ (( ${BASH_VERSINFO[0]} == 4 && ${BASH_VERSINFO[1]} >= 2 )) |
104 |
++ then |
105 |
++ __ebuildshell_bash42_true= |
106 |
++ __ebuildshell_bash42_false='#bash-4.2#' |
107 |
++ else |
108 |
++ __ebuildshell_bash42_true='#bash-4.2#' |
109 |
++ __ebuildshell_bash42_false= |
110 |
++ fi |
111 |
++ # The already readonly variables, without bash maintained ones: |
112 |
++ __ebuildshell_ro_ebuild_vars=$(<"${__ebuildshell_tmpf}.ebuild-rovars") |
113 |
++ cat <<-EOE |
114 |
++ # properly quote the function arguments |
115 |
++ $(declare -p __ebuildshell_args) |
116 |
++ set -- "\${__ebuildshell_args[@]}" |
117 |
++ unset __ebuildshell_args |
118 |
++ # be informative about what to do |
119 |
++ PS1="EBUILD ${PN} $1 \$ " |
120 |
++ type $1 |
121 |
++ ${__ebuildshell_bash42_false}echo 'warning: preserving variables across phases requires bash-4.2' |
122 |
++ echo "WANTED: \$@" |
123 |
++ echo "or use: \"\\\$@\"" |
124 |
++ # use bash history, but not the 'user's real one |
125 |
++ HISTFILE=~/.bash_history |
126 |
++ # but do not use history-expansion with '!', |
127 |
++ # for copy&paste of function body lines containing: ! |
128 |
++ set +H |
129 |
++ # this is a debugging shell already |
130 |
++ shopt -u extdebug |
131 |
++ trap - DEBUG |
132 |
++ # at exit, dump the current environment |
133 |
++ trap " |
134 |
++ unalias local |
135 |
++ unset -f __call-ebuildshell |
136 |
++ rm -f '${__ebuildshell_tmpf}.return-'* |
137 |
++ ( |
138 |
++ ( |
139 |
++ # declare -p does not tell the -g flag, |
140 |
++ # so we add it by aliasing declare. |
141 |
++ ${__ebuildshell_bash42_true}echo \"alias declare='declare -g'\" |
142 |
++ declare -p |
143 |
++ ${__ebuildshell_bash42_true}echo \"unalias declare\" |
144 |
++ declare -fp |
145 |
++ shopt -p | grep -v '\\(expand_aliases\\|extdebug\\)$' |
146 |
++ $([[ ${BASH_VERSINFO[0]} == 3 ]] && echo export) |
147 |
++ ) | |
148 |
++ ( |
149 |
++ # We may have more readonly variables now, yet we |
150 |
++ # need to filter variables that were readonly before. |
151 |
++ # And filter local variables by their trace attribute. |
152 |
++ 2>'${__ebuildshell_tmpf}.return-rovars' \\ |
153 |
++ '${PORTAGE_PYTHON:-/tools/haubi/gentoo/s01en24/usr/bin/python}' \\ |
154 |
++ '${PORTAGE_BIN_PATH}'/filter-bash-environment.py \\ |
155 |
++ --report-readonly-variables \\ |
156 |
++ --preserve-readonly-attribute \\ |
157 |
++ --filter-traced-variables \\ |
158 |
++ '${__ebuildshell_bash_i_vars} \ |
159 |
++ ${__ebuildshell_ro_ebuild_vars}' \\ |
160 |
++ || die 'filter-bash-environment.py failed' |
161 |
++ ) |
162 |
++ ) > '${__ebuildshell_tmpf}.return-env' |
163 |
++ " EXIT |
164 |
++ # can do some cleanup right now |
165 |
++ rm -f '${__ebuildshell_tmpf}.ebuild-'* |
166 |
++ EOE |
167 |
++ ) > "${__ebuildshell_tmpf}.ebuild-env" |
168 |
++ |
169 |
++ # pre-fill the history with "$@" |
170 |
++ echo '"$@"' >> ~/.bash_history |
171 |
++ chown ${PORTAGE_USER:-portage}:${PORTAGE_GROUP:-portage} ~/.bash_history &>/dev/null |
172 |
++ |
173 |
++ env -i ${BASH} --rcfile "${__ebuildshell_tmpf}.ebuild-env" -i |
174 |
++ |
175 |
++ # The environment- and exit-status handling after leaving the ebuildshell |
176 |
++ # prompt is expected to be identical as without the ebuildshell prompt. |
177 |
++ local __ebuildshell_status=$? |
178 |
++ |
179 |
++ # We might be in a recursive ebuildshell, but do not want |
180 |
++ # any aliases being active while sourcing the return-env. |
181 |
++ local __ebuildshell_orig_aliases=$(alias) |
182 |
++ unalias -a |
183 |
++ source "${__ebuildshell_tmpf}.return-env" |
184 |
++ unalias -a |
185 |
++ eval "${__ebuildshell_orig_aliases}" |
186 |
++ |
187 |
++ # Portage has a whitelist of readonly variables: If an ebuild defines |
188 |
++ # additional readonly variables, their readonly attribute is removed |
189 |
++ # across ebuild phases. If we ever want to preserve the readonly |
190 |
++ # attribute of additional ebuild-defined variables across phases, |
191 |
++ # when returning from the ebuildshell their names are in |
192 |
++ # "${__ebuildshell_tmpf}.return-rovars" |
193 |
++ rm -f "${__ebuildshell_tmpf}."{ebuild,return}-{env,rovars} |
194 |
++ |
195 |
++ return ${__ebuildshell_status} |
196 |
++} |
197 |
++ |
198 |
+ # Subshell/helper die support (must export for the die helper). |
199 |
+ export EBUILD_MASTER_PID=${BASHPID:-$(__bashpid)} |
200 |
+ trap 'exit 1' SIGTERM |
201 |
+diff --git a/bin/filter-bash-environment.py b/bin/filter-bash-environment.py |
202 |
+index 06cac7214..5590dbfc4 100755 |
203 |
+--- a/bin/filter-bash-environment.py |
204 |
++++ b/bin/filter-bash-environment.py |
205 |
+@@ -12,7 +12,8 @@ func_end_re = re.compile(br'^\}$') |
206 |
+ |
207 |
+ var_assign_re = re.compile(br'(^|^declare\s+-\S+\s+|^declare\s+|^export\s+)([^=\s]+)=("|\')?.*$') |
208 |
+ close_quote_re = re.compile(br'(\\"|"|\')\s*$') |
209 |
+-readonly_re = re.compile(br'^declare\s+-(\S*)r(\S*)\s+') |
210 |
++readonly_re = re.compile(br'^declare\s+-(\S*)r(\S*)\s+([^=\s]+)') |
211 |
++trace_re = re.compile(br'^declare\s+-\S*t\S*\s+') |
212 |
+ # declare without assignment |
213 |
+ var_declare_re = re.compile(br'^declare(\s+-\S+)?\s+([^=\s]+)\s*$') |
214 |
+ |
215 |
+@@ -27,7 +28,7 @@ def have_end_quote(quote, line): |
216 |
+ return close_quote_match is not None and \ |
217 |
+ close_quote_match.group(1) == quote |
218 |
+ |
219 |
+-def filter_declare_readonly_opt(line): |
220 |
++def filter_declare_readonly_opt(line, options): |
221 |
+ readonly_match = readonly_re.match(line) |
222 |
+ if readonly_match is not None: |
223 |
+ declare_opts = b'' |
224 |
+@@ -35,14 +36,19 @@ def filter_declare_readonly_opt(line): |
225 |
+ group = readonly_match.group(i) |
226 |
+ if group is not None: |
227 |
+ declare_opts += group |
228 |
++ var = readonly_match.group(3) |
229 |
++ if '--report-readonly-variables' in options: |
230 |
++ getattr(sys.stderr, 'buffer', sys.stderr).write(var + b'\n') |
231 |
++ if '--preserve-readonly-attribute' in options: |
232 |
++ declare_opts += b'r' |
233 |
+ if declare_opts: |
234 |
+ line = b'declare -' + declare_opts + \ |
235 |
+- b' ' + line[readonly_match.end():] |
236 |
++ b' ' + var + line[readonly_match.end():] |
237 |
+ else: |
238 |
+- line = b'declare ' + line[readonly_match.end():] |
239 |
++ line = b'declare ' + var + line[readonly_match.end():] |
240 |
+ return line |
241 |
+ |
242 |
+-def filter_bash_environment(pattern, file_in, file_out): |
243 |
++def filter_bash_environment(pattern, file_in, file_out, options): |
244 |
+ # Filter out any instances of the \1 character from variable values |
245 |
+ # since this character multiplies each time that the environment |
246 |
+ # is saved (strange bash behavior). This can eventually result in |
247 |
+@@ -66,6 +72,8 @@ def filter_bash_environment(pattern, file_in, file_out): |
248 |
+ quote = var_assign_match.group(3) |
249 |
+ filter_this = pattern.match(var_assign_match.group(2)) \ |
250 |
+ is not None |
251 |
++ if not filter_this and '--filter-traced-variables' in options: |
252 |
++ filter_this = trace_re.match(line) is not None |
253 |
+ # Exclude the start quote when searching for the end quote, |
254 |
+ # to ensure that the start quote is not misidentified as the |
255 |
+ # end quote (happens if there is a newline immediately after |
256 |
+@@ -75,7 +83,7 @@ def filter_bash_environment(pattern, file_in, file_out): |
257 |
+ multi_line_quote = quote |
258 |
+ multi_line_quote_filter = filter_this |
259 |
+ if not filter_this: |
260 |
+- line = filter_declare_readonly_opt(line) |
261 |
++ line = filter_declare_readonly_opt(line, options) |
262 |
+ file_out.write(line.replace(b"\1", b"")) |
263 |
+ continue |
264 |
+ else: |
265 |
+@@ -84,8 +92,10 @@ def filter_bash_environment(pattern, file_in, file_out): |
266 |
+ # declare without assignment |
267 |
+ filter_this = pattern.match(declare_match.group(2)) \ |
268 |
+ is not None |
269 |
++ if not filter_this and '--filter-traced-variables' in options: |
270 |
++ filter_this = trace_re.match(line) is not None |
271 |
+ if not filter_this: |
272 |
+- line = filter_declare_readonly_opt(line) |
273 |
++ line = filter_declare_readonly_opt(line, options) |
274 |
+ file_out.write(line) |
275 |
+ continue |
276 |
+ |
277 |
+@@ -122,13 +132,28 @@ if __name__ == "__main__": |
278 |
+ "while leaving bash function definitions and here-documents " + \ |
279 |
+ "intact. The PATTERN is a space separated list of variable names" + \ |
280 |
+ " and it supports python regular expression syntax." |
281 |
+- usage = "usage: %s PATTERN" % os.path.basename(sys.argv[0]) |
282 |
+- args = sys.argv[1:] |
283 |
+- |
284 |
+- if '-h' in args or '--help' in args: |
285 |
+- sys.stdout.write(usage + "\n") |
286 |
+- sys.stdout.flush() |
287 |
+- sys.exit(os.EX_OK) |
288 |
++ usage = "usage: %s [-h|<options>] PATTERN" % os.path.basename(sys.argv[0]) |
289 |
++ args = [] |
290 |
++ known_options = { |
291 |
++ '--report-readonly-variables': |
292 |
++ "Write names of readonly variables to stderr.", |
293 |
++ '--preserve-readonly-attribute': |
294 |
++ "Preserve the '-r' flag in 'declare -r'.", |
295 |
++ '--filter-traced-variables': |
296 |
++ "Filter out variables declared with '-t' attribute." |
297 |
++ } |
298 |
++ options = {} |
299 |
++ for arg in sys.argv[1:]: |
300 |
++ if arg in known_options.keys(): |
301 |
++ options[arg] = True |
302 |
++ continue |
303 |
++ if '-h' == arg or '--help' == arg: |
304 |
++ sys.stdout.write(usage + "\n\nKnown <options>:\n\n") |
305 |
++ for option, descr in known_options.items(): |
306 |
++ sys.stdout.write(" " + option + "\t" + descr + "\n") |
307 |
++ sys.stdout.flush() |
308 |
++ sys.exit(os.EX_OK) |
309 |
++ args.append(arg) |
310 |
+ |
311 |
+ if len(args) != 1: |
312 |
+ sys.stderr.write(usage + "\n") |
313 |
+@@ -151,5 +176,5 @@ if __name__ == "__main__": |
314 |
+ |
315 |
+ var_pattern = b'^(' + b'|'.join(var_pattern) + b')$' |
316 |
+ filter_bash_environment( |
317 |
+- re.compile(var_pattern), file_in, file_out) |
318 |
++ re.compile(var_pattern), file_in, file_out, options) |
319 |
+ file_out.flush() |
320 |
+diff --git a/bin/save-ebuild-env.sh b/bin/save-ebuild-env.sh |
321 |
+index bb17382d4..af35a3327 100755 |
322 |
+--- a/bin/save-ebuild-env.sh |
323 |
++++ b/bin/save-ebuild-env.sh |
324 |
+@@ -53,7 +53,7 @@ __save_ebuild_env() { |
325 |
+ einfo einfon ewarn eerror ebegin __eend eend KV_major \ |
326 |
+ KV_minor KV_micro KV_to_int get_KV has \ |
327 |
+ __has_phase_defined_up_to \ |
328 |
+- hasv hasq __qa_source __qa_call \ |
329 |
++ hasv hasq __qa_source __qa_call __call-ebuildshell \ |
330 |
+ addread addwrite adddeny addpredict __sb_append_var \ |
331 |
+ use usev useq has_version portageq \ |
332 |
+ best_version use_with use_enable register_die_hook \ |
333 |
+diff --git a/man/make.conf.5 b/man/make.conf.5 |
334 |
+index b0c1aa4f2..568f350a0 100644 |
335 |
+--- a/man/make.conf.5 |
336 |
++++ b/man/make.conf.5 |
337 |
+@@ -408,6 +408,12 @@ exist). Also see the related \fIunmerge\-backup\fR feature. |
338 |
+ Use locks to ensure that unsandboxed ebuild phases never execute |
339 |
+ concurrently. Also see \fIparallel\-install\fR. |
340 |
+ .TP |
341 |
++.B ebuildshell |
342 |
++Drop into an interactive shell for each phase function, meant for |
343 |
++debugging. Because the shell would normally be used to execute the |
344 |
++phase function, commands like src_unpack or epatch are available in the |
345 |
++interactive shell. Use `die` to terminate the merge. |
346 |
++.TP |
347 |
+ .B fail\-clean |
348 |
+ Clean up temporary files after a build failure. This is particularly useful |
349 |
+ if you have \fBPORTAGE_TMPDIR\fR on tmpfs. If this feature is enabled, you |
350 |
+diff --git a/pym/_emerge/AbstractEbuildProcess.py b/pym/_emerge/AbstractEbuildProcess.py |
351 |
+index 370cac529..a521596e5 100644 |
352 |
+--- a/pym/_emerge/AbstractEbuildProcess.py |
353 |
++++ b/pym/_emerge/AbstractEbuildProcess.py |
354 |
+@@ -181,6 +181,7 @@ class AbstractEbuildProcess(SpawnProcess): |
355 |
+ self.fd_pipes = {} |
356 |
+ null_fd = None |
357 |
+ if 0 not in self.fd_pipes and \ |
358 |
++ "ebuildshell" not in self.settings.features and \ |
359 |
+ self.phase not in self._phases_interactive_whitelist and \ |
360 |
+ "interactive" not in self.settings.get("PROPERTIES", "").split(): |
361 |
+ null_fd = os.open('/dev/null', os.O_RDONLY) |
362 |
+diff --git a/pym/portage/const.py b/pym/portage/const.py |
363 |
+index 3c23c85ed..d9c57f300 100644 |
364 |
+--- a/pym/portage/const.py |
365 |
++++ b/pym/portage/const.py |
366 |
+@@ -161,6 +161,7 @@ SUPPORTED_FEATURES = frozenset([ |
367 |
+ "distlocks", |
368 |
+ "downgrade-backup", |
369 |
+ "ebuild-locks", |
370 |
++ "ebuildshell", |
371 |
+ "fail-clean", |
372 |
+ "fakeroot", |
373 |
+ "fixlafiles", |
374 |
+-- |
375 |
+2.16.1 |
376 |
+ |
377 |
|
378 |
diff --git a/sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch b/sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch |
379 |
new file mode 100644 |
380 |
index 0000000000..8e0864990d |
381 |
--- /dev/null |
382 |
+++ b/sys-apps/portage/files/portage-2.3.40-prefix-chaining.patch |
383 |
@@ -0,0 +1,921 @@ |
384 |
+From 9c991762d6becb779925d59289eb0324f269ad18 Mon Sep 17 00:00:00 2001 |
385 |
+From: Michael Haubenwallner <haubi@g.o> |
386 |
+Date: Thu, 23 Mar 2017 13:52:32 +0100 |
387 |
+Subject: [PATCH 2/2] add prefix-chaining support |
388 |
+ |
389 |
+--- |
390 |
+ bin/install-qa-check.d/05prefix | 30 ++++++- |
391 |
+ bin/phase-helpers.sh | 24 ++++++ |
392 |
+ pym/_emerge/actions.py | 6 +- |
393 |
+ pym/_emerge/depgraph.py | 53 +++++++----- |
394 |
+ pym/_emerge/resolver/output.py | 40 ++++++++- |
395 |
+ pym/portage/_sets/__init__.py | 5 ++ |
396 |
+ pym/portage/const.py | 6 ++ |
397 |
+ pym/portage/dbapi/vartree.py | 34 ++++++-- |
398 |
+ pym/portage/dep/dep_check.py | 99 +++++++++++++++++++++- |
399 |
+ .../package/ebuild/_config/LocationsManager.py | 3 + |
400 |
+ pym/portage/package/ebuild/config.py | 62 ++++++++++++++ |
401 |
+ pym/portage/package/ebuild/doebuild.py | 24 +++++- |
402 |
+ pym/portage/package/ebuild/fetch.py | 4 + |
403 |
+ pym/portage/sync/controller.py | 27 +++--- |
404 |
+ pym/portage/util/_dyn_libs/LinkageMapELF.py | 4 +- |
405 |
+ 15 files changed, 373 insertions(+), 48 deletions(-) |
406 |
+ |
407 |
+diff --git a/bin/install-qa-check.d/05prefix b/bin/install-qa-check.d/05prefix |
408 |
+index 32561e263..0c1147367 100644 |
409 |
+--- a/bin/install-qa-check.d/05prefix |
410 |
++++ b/bin/install-qa-check.d/05prefix |
411 |
+@@ -79,16 +79,42 @@ install_qa_check_prefix() { |
412 |
+ # unprefixed shebang, is the script directly in $PATH or an init |
413 |
+ # script? |
414 |
+ if [[ ":${PATH}:${EPREFIX}/etc/init.d:" == *":${fp}:"* ]] ; then |
415 |
+- if [[ -e ${EROOT}${line[0]} || -e ${ED}${line[0]} ]] ; then |
416 |
++ all_epfs="$PORTAGE_READONLY_EPREFIXES:$EPREFIX:$EROOT:$ED" |
417 |
++ save_IFS=$IFS |
418 |
++ IFS=: |
419 |
++ epfs=( $all_epfs ) |
420 |
++ IFS=$save_IFS |
421 |
++ |
422 |
++ found= |
423 |
++ for x in "${epfs[@]}"; do |
424 |
++ [[ -z "${x}" ]] && continue |
425 |
++ check="${x}${line[0]}" |
426 |
++ |
427 |
++ # might already contain a prefix |
428 |
++ if [[ "${line[0]}" == "${x}"* ]]; then |
429 |
++ check="${line[0]}" |
430 |
++ fi |
431 |
++ |
432 |
++ if [[ -e ${check} ]]; then |
433 |
++ found="${check}" |
434 |
++ fi |
435 |
++ done |
436 |
++ |
437 |
++ if [[ -n ${found} ]] ; then |
438 |
+ # is it unprefixed, but we can just fix it because a |
439 |
+ # prefixed variant exists |
440 |
+ eqawarn "prefixing shebang of ${fn#${D}}" |
441 |
++ |
442 |
++ if [[ ${found} == "${ED}"* || ${found} == "${EROOT}"* ]]; then |
443 |
++ found="${EPREFIX}${line[0]}" |
444 |
++ fi |
445 |
++ |
446 |
+ # statement is made idempotent on purpose, because |
447 |
+ # symlinks may point to the same target, and hence the |
448 |
+ # same real file may be sedded multiple times since we |
449 |
+ # read the shebangs in one go upfront for performance |
450 |
+ # reasons |
451 |
+- sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${EPREFIX}"${line[0]}':' "${rf}" |
452 |
++ sed -i -e '1s:^#! \?'"${line[0]}"':#!'"${found}"':' "${rf}" |
453 |
+ continue |
454 |
+ else |
455 |
+ # this is definitely wrong: script in $PATH and invalid shebang |
456 |
+diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh |
457 |
+index 75d92b407..c32533fb3 100644 |
458 |
+--- a/bin/phase-helpers.sh |
459 |
++++ b/bin/phase-helpers.sh |
460 |
+@@ -934,6 +934,10 @@ ___best_version_and_has_version_common() { |
461 |
+ fi |
462 |
+ "${cmd[@]}" |
463 |
+ local retval=$? |
464 |
++ if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then |
465 |
++ ${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' '${FUNCNAME[1]}' '${READONLY_EPREFIX%:*}' '${atom}'" |
466 |
++ retval=$? |
467 |
++ fi |
468 |
+ case "${retval}" in |
469 |
+ 0|1) |
470 |
+ return ${retval} |
471 |
+@@ -1194,6 +1198,10 @@ if ___eapi_has_master_repositories; then |
472 |
+ output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" master_repositories "${EROOT}" "${repository}") |
473 |
+ fi |
474 |
+ retval=$? |
475 |
++ if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then |
476 |
++ output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' master_repositories '${READONLY_EPREFIX%:*}' '${repository}'") |
477 |
++ retval=$? |
478 |
++ fi |
479 |
+ [[ -n ${output} ]] && echo "${output}" |
480 |
+ case "${retval}" in |
481 |
+ 0|1) |
482 |
+@@ -1225,6 +1233,10 @@ if ___eapi_has_repository_path; then |
483 |
+ output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" get_repo_path "${EROOT}" "${repository}") |
484 |
+ fi |
485 |
+ retval=$? |
486 |
++ if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then |
487 |
++ output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' get_repo_path '${READONLY_EPREFIX%:*}' '${repository}'") |
488 |
++ retval=$? |
489 |
++ fi |
490 |
+ [[ -n ${output} ]] && echo "${output}" |
491 |
+ case "${retval}" in |
492 |
+ 0|1) |
493 |
+@@ -1255,6 +1267,10 @@ if ___eapi_has_available_eclasses; then |
494 |
+ output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" available_eclasses "${EROOT}" "${repository}") |
495 |
+ fi |
496 |
+ retval=$? |
497 |
++ if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then |
498 |
++ output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' available_eclasses '${READONLY_EPREFIX%:*}' '${repository}'") |
499 |
++ retval=$? |
500 |
++ fi |
501 |
+ [[ -n ${output} ]] && echo "${output}" |
502 |
+ case "${retval}" in |
503 |
+ 0|1) |
504 |
+@@ -1285,6 +1301,10 @@ if ___eapi_has_eclass_path; then |
505 |
+ else |
506 |
+ output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" eclass_path "${EROOT}" "${repository}" "${eclass}") |
507 |
+ fi |
508 |
++ if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then |
509 |
++ output=$(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' eclass_path '${READONLY_EPREFIX%:*}' '${repository}' '${eclass}'") |
510 |
++ retval=$? |
511 |
++ fi |
512 |
+ retval=$? |
513 |
+ [[ -n ${output} ]] && echo "${output}" |
514 |
+ case "${retval}" in |
515 |
+@@ -1316,6 +1336,10 @@ if ___eapi_has_license_path; then |
516 |
+ else |
517 |
+ output=$("${PORTAGE_BIN_PATH}/ebuild-helpers/portageq" license_path "${EROOT}" "${repository}" "${license}") |
518 |
+ fi |
519 |
++ if [[ ${retval} -eq 1 && -n ${READONLY_EPREFIX} ]]; then |
520 |
++ output=(${SHELL} -c "EPREFIX='${READONLY_EPREFIX%:*}' EPYTHON= '${PORTAGE_BIN_PATH}/ebuild-helpers/portageq' license_path '${READONLY_EPREFIX%:*}' '${repository}' '${license}'") |
521 |
++ retval=$? |
522 |
++ fi |
523 |
+ retval=$? |
524 |
+ [[ -n ${output} ]] && echo "${output}" |
525 |
+ case "${retval}" in |
526 |
+diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py |
527 |
+index 432fc57e3..764462fc5 100644 |
528 |
+--- a/pym/_emerge/actions.py |
529 |
++++ b/pym/_emerge/actions.py |
530 |
+@@ -39,7 +39,7 @@ from portage import os |
531 |
+ from portage import shutil |
532 |
+ from portage import eapi_is_supported, _encodings, _unicode_decode |
533 |
+ from portage.cache.cache_errors import CacheError |
534 |
+-from portage.const import EPREFIX |
535 |
++from portage.const import EPREFIX, BPREFIX |
536 |
+ from portage.const import GLOBAL_CONFIG_PATH, VCS_DIRS, _DEPCLEAN_LIB_CHECK_DEFAULT |
537 |
+ from portage.const import SUPPORTED_BINPKG_FORMATS, TIMESTAMP_FORMAT |
538 |
+ from portage.dbapi.dep_expand import dep_expand |
539 |
+@@ -65,6 +65,7 @@ from portage.util.SlotObject import SlotObject |
540 |
+ from portage.util._async.run_main_scheduler import run_main_scheduler |
541 |
+ from portage.util._async.SchedulerInterface import SchedulerInterface |
542 |
+ from portage.util._eventloop.global_event_loop import global_event_loop |
543 |
++from portage.util._path import exists_raise_eaccess |
544 |
+ from portage._global_updates import _global_updates |
545 |
+ from portage.sync.old_tree_timestamp import old_tree_timestamp_warn |
546 |
+ from portage.localization import _ |
547 |
+@@ -2672,6 +2673,9 @@ def missing_sets_warning(root_config, missing_sets): |
548 |
+ if portage.const.EPREFIX: |
549 |
+ global_config_path = os.path.join(portage.const.EPREFIX, |
550 |
+ portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
551 |
++ if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX: |
552 |
++ global_config_path = os.path.join(portage.const.BPREFIX, |
553 |
++ portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
554 |
+ msg.append(" This usually means that '%s'" % \ |
555 |
+ (os.path.join(global_config_path, "sets/portage.conf"),)) |
556 |
+ msg.append(" is missing or corrupt.") |
557 |
+diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py |
558 |
+index f7bac69f9..a6eb0d3d4 100644 |
559 |
+--- a/pym/_emerge/depgraph.py |
560 |
++++ b/pym/_emerge/depgraph.py |
561 |
+@@ -3355,19 +3355,19 @@ class depgraph(object): |
562 |
+ # _dep_disjunctive_stack first, so that choices for build-time |
563 |
+ # deps influence choices for run-time deps (bug 639346). |
564 |
+ deps = ( |
565 |
+- (myroot, edepend["RDEPEND"], |
566 |
++ (myroot, "RDEPEND", |
567 |
+ self._priority(runtime=True)), |
568 |
+- (myroot, edepend["PDEPEND"], |
569 |
++ (myroot, "PDEPEND", |
570 |
+ self._priority(runtime_post=True)), |
571 |
+- (depend_root, edepend["DEPEND"], |
572 |
++ (depend_root, "DEPEND", |
573 |
+ self._priority(buildtime=True, |
574 |
+ optional=(pkg.built or ignore_depend_deps), |
575 |
+ ignored=ignore_depend_deps)), |
576 |
+- (self._frozen_config._running_root.root, edepend["HDEPEND"], |
577 |
++ (self._frozen_config._running_root.root, "HDEPEND", |
578 |
+ self._priority(buildtime=True, |
579 |
+ optional=(pkg.built or ignore_hdepend_deps), |
580 |
+ ignored=ignore_hdepend_deps)), |
581 |
+- (self._frozen_config._running_root.root, edepend["BDEPEND"], |
582 |
++ (self._frozen_config._running_root.root, "BDEPEND", |
583 |
+ self._priority(buildtime=True, |
584 |
+ optional=(pkg.built or ignore_bdepend_deps), |
585 |
+ ignored=ignore_bdepend_deps)), |
586 |
+@@ -3375,7 +3375,8 @@ class depgraph(object): |
587 |
+ |
588 |
+ debug = "--debug" in self._frozen_config.myopts |
589 |
+ |
590 |
+- for dep_root, dep_string, dep_priority in deps: |
591 |
++ for dep_root, dep_type, dep_priority in deps: |
592 |
++ dep_string = edepend[dep_type] |
593 |
+ if not dep_string: |
594 |
+ continue |
595 |
+ if debug: |
596 |
+@@ -3413,7 +3414,7 @@ class depgraph(object): |
597 |
+ |
598 |
+ try: |
599 |
+ dep_string = list(self._queue_disjunctive_deps( |
600 |
+- pkg, dep_root, dep_priority, dep_string)) |
601 |
++ pkg, dep_root, dep_priority, dep_string, dep_type)) |
602 |
+ except portage.exception.InvalidDependString as e: |
603 |
+ if pkg.installed: |
604 |
+ self._dynamic_config._masked_installed.add(pkg) |
605 |
+@@ -3428,14 +3429,14 @@ class depgraph(object): |
606 |
+ |
607 |
+ if not self._add_pkg_dep_string( |
608 |
+ pkg, dep_root, dep_priority, dep_string, |
609 |
+- allow_unsatisfied): |
610 |
++ allow_unsatisfied, dep_type): |
611 |
+ return 0 |
612 |
+ |
613 |
+ self._dynamic_config._traversed_pkg_deps.add(pkg) |
614 |
+ return 1 |
615 |
+ |
616 |
+ def _add_pkg_dep_string(self, pkg, dep_root, dep_priority, dep_string, |
617 |
+- allow_unsatisfied): |
618 |
++ allow_unsatisfied, dep_type=None): |
619 |
+ _autounmask_backup = self._dynamic_config._autounmask |
620 |
+ if dep_priority.optional or dep_priority.ignored: |
621 |
+ # Temporarily disable autounmask for deps that |
622 |
+@@ -3444,7 +3445,7 @@ class depgraph(object): |
623 |
+ try: |
624 |
+ return self._wrapped_add_pkg_dep_string( |
625 |
+ pkg, dep_root, dep_priority, dep_string, |
626 |
+- allow_unsatisfied) |
627 |
++ allow_unsatisfied, dep_type) |
628 |
+ finally: |
629 |
+ self._dynamic_config._autounmask = _autounmask_backup |
630 |
+ |
631 |
+@@ -3480,7 +3481,7 @@ class depgraph(object): |
632 |
+ not slot_operator_rebuild |
633 |
+ |
634 |
+ def _wrapped_add_pkg_dep_string(self, pkg, dep_root, dep_priority, |
635 |
+- dep_string, allow_unsatisfied): |
636 |
++ dep_string, allow_unsatisfied, dep_type=None): |
637 |
+ if isinstance(pkg.depth, int): |
638 |
+ depth = pkg.depth + 1 |
639 |
+ else: |
640 |
+@@ -3504,7 +3505,7 @@ class depgraph(object): |
641 |
+ try: |
642 |
+ selected_atoms = self._select_atoms(dep_root, |
643 |
+ dep_string, myuse=self._pkg_use_enabled(pkg), parent=pkg, |
644 |
+- strict=strict, priority=dep_priority) |
645 |
++ strict=strict, priority=dep_priority, dep_type=dep_type) |
646 |
+ except portage.exception.InvalidDependString: |
647 |
+ if pkg.installed: |
648 |
+ self._dynamic_config._masked_installed.add(pkg) |
649 |
+@@ -3811,7 +3812,7 @@ class depgraph(object): |
650 |
+ child_pkgs.sort() |
651 |
+ yield (atom, child_pkgs[-1]) |
652 |
+ |
653 |
+- def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct): |
654 |
++ def _queue_disjunctive_deps(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None): |
655 |
+ """ |
656 |
+ Queue disjunctive (virtual and ||) deps in self._dynamic_config._dep_disjunctive_stack. |
657 |
+ Yields non-disjunctive deps. Raises InvalidDependString when |
658 |
+@@ -3820,33 +3821,33 @@ class depgraph(object): |
659 |
+ for x in dep_struct: |
660 |
+ if isinstance(x, list): |
661 |
+ if x and x[0] == "||": |
662 |
+- self._queue_disjunction(pkg, dep_root, dep_priority, [x]) |
663 |
++ self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type) |
664 |
+ else: |
665 |
+ for y in self._queue_disjunctive_deps( |
666 |
+- pkg, dep_root, dep_priority, x): |
667 |
++ pkg, dep_root, dep_priority, x, dep_type): |
668 |
+ yield y |
669 |
+ else: |
670 |
+ # Note: Eventually this will check for PROPERTIES=virtual |
671 |
+ # or whatever other metadata gets implemented for this |
672 |
+ # purpose. |
673 |
+ if x.cp.startswith('virtual/'): |
674 |
+- self._queue_disjunction(pkg, dep_root, dep_priority, [x]) |
675 |
++ self._queue_disjunction(pkg, dep_root, dep_priority, [x], dep_type) |
676 |
+ else: |
677 |
+ yield x |
678 |
+ |
679 |
+- def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct): |
680 |
++ def _queue_disjunction(self, pkg, dep_root, dep_priority, dep_struct, dep_type=None): |
681 |
+ self._dynamic_config._dep_disjunctive_stack.append( |
682 |
+- (pkg, dep_root, dep_priority, dep_struct)) |
683 |
++ (pkg, dep_root, dep_priority, dep_struct, dep_type)) |
684 |
+ |
685 |
+ def _pop_disjunction(self, allow_unsatisfied): |
686 |
+ """ |
687 |
+ Pop one disjunctive dep from self._dynamic_config._dep_disjunctive_stack, and use it to |
688 |
+ populate self._dynamic_config._dep_stack. |
689 |
+ """ |
690 |
+- pkg, dep_root, dep_priority, dep_struct = \ |
691 |
++ pkg, dep_root, dep_priority, dep_struct, dep_type = \ |
692 |
+ self._dynamic_config._dep_disjunctive_stack.pop() |
693 |
+ if not self._add_pkg_dep_string( |
694 |
+- pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied): |
695 |
++ pkg, dep_root, dep_priority, dep_struct, allow_unsatisfied, dep_type): |
696 |
+ return 0 |
697 |
+ return 1 |
698 |
+ |
699 |
+@@ -4699,7 +4700,7 @@ class depgraph(object): |
700 |
+ return self._select_atoms_highest_available(*pargs, **kwargs) |
701 |
+ |
702 |
+ def _select_atoms_highest_available(self, root, depstring, |
703 |
+- myuse=None, parent=None, strict=True, trees=None, priority=None): |
704 |
++ myuse=None, parent=None, strict=True, trees=None, priority=None, dep_type=None): |
705 |
+ """This will raise InvalidDependString if necessary. If trees is |
706 |
+ None then self._dynamic_config._filtered_trees is used.""" |
707 |
+ |
708 |
+@@ -4722,6 +4723,13 @@ class depgraph(object): |
709 |
+ pkgsettings = self._frozen_config.pkgsettings[root] |
710 |
+ if trees is None: |
711 |
+ trees = self._dynamic_config._filtered_trees |
712 |
++ |
713 |
++ # this one is needed to guarantee good readonly root |
714 |
++ # resolution display in the merge list. required since |
715 |
++ # parent (below) can be None |
716 |
++ trees[root]["disp_parent"] = parent |
717 |
++ |
718 |
++ |
719 |
+ mytrees = trees[root] |
720 |
+ atom_graph = digraph() |
721 |
+ if True: |
722 |
+@@ -4753,7 +4761,7 @@ class depgraph(object): |
723 |
+ |
724 |
+ mycheck = portage.dep_check(depstring, None, |
725 |
+ pkgsettings, myuse=myuse, |
726 |
+- myroot=root, trees=trees) |
727 |
++ myroot=root, trees=trees, dep_type=dep_type) |
728 |
+ finally: |
729 |
+ # restore state |
730 |
+ self._dynamic_config._autounmask = _autounmask_backup |
731 |
+@@ -4829,6 +4837,7 @@ class depgraph(object): |
732 |
+ continue |
733 |
+ node_stack.append((child_node, node, child_atom)) |
734 |
+ |
735 |
++ trees[root].pop("disp_parent") |
736 |
+ return selected_atoms |
737 |
+ |
738 |
+ def _expand_virt_from_graph(self, root, atom): |
739 |
+diff --git a/pym/_emerge/resolver/output.py b/pym/_emerge/resolver/output.py |
740 |
+index 24340576c..4a1741f3a 100644 |
741 |
+--- a/pym/_emerge/resolver/output.py |
742 |
++++ b/pym/_emerge/resolver/output.py |
743 |
+@@ -22,11 +22,12 @@ from portage.localization import localized_size |
744 |
+ from portage.package.ebuild.config import _get_feature_flags |
745 |
+ from portage.package.ebuild._spawn_nofetch import spawn_nofetch |
746 |
+ from portage.output import ( blue, colorize, create_color_func, |
747 |
+- darkblue, darkgreen, green, nc_len, teal) |
748 |
++ darkblue, darkgreen, green, nc_len, teal, yellow, turquoise) |
749 |
+ bad = create_color_func("BAD") |
750 |
+ from portage._sets.base import InternalPackageSet |
751 |
+ from portage.util import writemsg_stdout |
752 |
+ from portage.versions import best, cpv_getversion |
753 |
++from portage.dep.dep_check import ro_selected |
754 |
+ |
755 |
+ from _emerge.Blocker import Blocker |
756 |
+ from _emerge.create_world_atom import create_world_atom |
757 |
+@@ -563,6 +564,42 @@ class Display(object): |
758 |
+ writemsg_stdout("%s\n" % (pkg,), noiselevel=-1) |
759 |
+ return |
760 |
+ |
761 |
++ def print_readonly_prefix(self): |
762 |
++ """Performs the actual output printing for the readonly prefix |
763 |
++ information stuff |
764 |
++ """ |
765 |
++ out = sys.stdout |
766 |
++ |
767 |
++ # print readonly selected packages |
768 |
++ if len(ro_selected) > 0: |
769 |
++ out.write("\n%s\n\n" % (darkgreen("Packages resolved from readonly installations:"))) |
770 |
++ |
771 |
++ ro_mismatch_warning = False |
772 |
++ ro_dupcheck = [] |
773 |
++ for x in ro_selected: |
774 |
++ tmp_type = x["type"].replace("END","") |
775 |
++ while len(tmp_type) < 4: |
776 |
++ tmp_type += " " |
777 |
++ if x["parent"] and str(x["atom"]) not in ro_dupcheck: |
778 |
++ out.write("[%s %s] %s %s %s (%s by %s)" % (teal("readonly"), |
779 |
++ green(tmp_type), green(str(x["matches"][0])), yellow("from"), |
780 |
++ blue(x["ro_root"]), turquoise(str(x["atom"])), green(x["parent"].cpv))) |
781 |
++ |
782 |
++ ro_dupcheck.append(str(x["atom"])) |
783 |
++ |
784 |
++ if x["host_mismatch"]: |
785 |
++ ro_mismatch_warning = True |
786 |
++ out.write(" %s\n" % (red("**"))) |
787 |
++ else: |
788 |
++ out.write("\n") |
789 |
++ |
790 |
++ if ro_mismatch_warning: |
791 |
++ out.write("\n%s:" % (red("**"))) |
792 |
++ out.write(yellow(" WARNING: packages marked with ** have been resolved as a\n")) |
793 |
++ out.write(yellow(" runtime dependency, but the CHOST variable for the parent\n")) |
794 |
++ out.write(yellow(" and dependency package don't match. This could cause link\n")) |
795 |
++ out.write(yellow(" errors. It is recommended to use RDEPEND READONLY_EPREFIX's\n")) |
796 |
++ out.write(yellow(" only with matching CHOST portage instances.\n")) |
797 |
+ |
798 |
+ def print_verbose(self, show_repos): |
799 |
+ """Prints the verbose output to std_out |
800 |
+@@ -913,6 +950,7 @@ class Display(object): |
801 |
+ show_repos = self.quiet_repo_display and repoadd_set and repoadd_set != set(["0"]) |
802 |
+ |
803 |
+ # now finally print out the messages |
804 |
++ self.print_readonly_prefix() |
805 |
+ self.print_messages(show_repos) |
806 |
+ self.print_blockers() |
807 |
+ if self.conf.verbosity == 3: |
808 |
+diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py |
809 |
+index 2c9bf9715..6a2784207 100644 |
810 |
+--- a/pym/portage/_sets/__init__.py |
811 |
++++ b/pym/portage/_sets/__init__.py |
812 |
+@@ -21,6 +21,7 @@ from portage.const import _ENABLE_SET_CONFIG |
813 |
+ from portage.exception import PackageSetNotFound |
814 |
+ from portage.localization import _ |
815 |
+ from portage.util import writemsg_level |
816 |
++from portage.util._path import exists_raise_eaccess |
817 |
+ from portage.util.configparser import (SafeConfigParser, |
818 |
+ NoOptionError, ParsingError, read_configs) |
819 |
+ |
820 |
+@@ -281,6 +282,10 @@ def load_default_config(settings, trees): |
821 |
+ if portage.const.EPREFIX: |
822 |
+ global_config_path = os.path.join(portage.const.EPREFIX, |
823 |
+ GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
824 |
++ if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX: |
825 |
++ global_config_path = os.path.join(portage.const.BPREFIX, |
826 |
++ GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
827 |
++ |
828 |
+ vcs_dirs = [_unicode_encode(x, encoding=_encodings['fs']) for x in VCS_DIRS] |
829 |
+ def _getfiles(): |
830 |
+ for path, dirs, files in os.walk(os.path.join(global_config_path, "sets")): |
831 |
+diff --git a/pym/portage/const.py b/pym/portage/const.py |
832 |
+index d9c57f300..a3d927c3b 100644 |
833 |
+--- a/pym/portage/const.py |
834 |
++++ b/pym/portage/const.py |
835 |
+@@ -190,6 +190,7 @@ SUPPORTED_FEATURES = frozenset([ |
836 |
+ "notitles", |
837 |
+ "parallel-fetch", |
838 |
+ "parallel-install", |
839 |
++ "prefix-chaining", |
840 |
+ "prelink-checksums", |
841 |
+ "preserve-libs", |
842 |
+ "protect-owned", |
843 |
+@@ -241,6 +242,11 @@ MANIFEST2_IDENTIFIERS = ("AUX", "MISC", "DIST", "EBUILD") |
844 |
+ #EPREFIX = "" |
845 |
+ # END PREFIX LOCAL |
846 |
+ |
847 |
++BPREFIX = EPREFIX |
848 |
++ |
849 |
++# --prefix commandline arg always rules, ends up in os.environ["EPREFIX"] |
850 |
++if "EPREFIX" in os.environ: |
851 |
++ os.environ["PORTAGE_OVERRIDE_EPREFIX"] = os.environ["EPREFIX"] |
852 |
+ # pick up EPREFIX from the environment if set |
853 |
+ if "PORTAGE_OVERRIDE_EPREFIX" in os.environ: |
854 |
+ EPREFIX = os.environ["PORTAGE_OVERRIDE_EPREFIX"] |
855 |
+diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py |
856 |
+index 77a72b5b1..f20c6763e 100644 |
857 |
+--- a/pym/portage/dbapi/vartree.py |
858 |
++++ b/pym/portage/dbapi/vartree.py |
859 |
+@@ -196,8 +196,19 @@ class vardbapi(dbapi): |
860 |
+ self._counter_path = os.path.join(self._eroot, |
861 |
+ CACHE_PATH, "counter") |
862 |
+ |
863 |
+- self._plib_registry = PreservedLibsRegistry(settings["ROOT"], |
864 |
+- os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry")) |
865 |
++ plibreg_path = os.path.join(self._eroot, PRIVATE_PATH, "preserved_libs_registry") |
866 |
++ |
867 |
++ if vartree: |
868 |
++ self._kill_eprefix = vartree._kill_eprefix |
869 |
++ else: |
870 |
++ self._kill_eprefix = False |
871 |
++ |
872 |
++ if self._kill_eprefix: |
873 |
++ self._aux_cache_filename = self._aux_cache_filename.replace(EPREFIX, "") |
874 |
++ self._counter_path = self._counter_path.replace(EPREFIX, "") |
875 |
++ plibreg_path = plibreg_path.replace(EPREFIX, "") |
876 |
++ |
877 |
++ self._plib_registry = PreservedLibsRegistry(settings["ROOT"], plibreg_path) |
878 |
+ self._linkmap = LinkageMap(self) |
879 |
+ chost = self.settings.get('CHOST') |
880 |
+ if not chost: |
881 |
+@@ -238,6 +249,9 @@ class vardbapi(dbapi): |
882 |
+ # This is an optimized hotspot, so don't use unicode-wrapped |
883 |
+ # os module and don't use os.path.join(). |
884 |
+ rValue = self._eroot + VDB_PATH + _os.sep + mykey |
885 |
++ if self._kill_eprefix: |
886 |
++ rValue = rValue.replace(EPREFIX, "") |
887 |
++ |
888 |
+ if filename is not None: |
889 |
+ # If filename is always relative, we can do just |
890 |
+ # rValue += _os.sep + filename |
891 |
+@@ -502,6 +516,9 @@ class vardbapi(dbapi): |
892 |
+ returnme = [] |
893 |
+ basepath = os.path.join(self._eroot, VDB_PATH) + os.path.sep |
894 |
+ |
895 |
++ if self._kill_eprefix: |
896 |
++ basepath = os.path.join(self.root, basepath.replace(EPREFIX, "")) |
897 |
++ |
898 |
+ if use_cache: |
899 |
+ from portage import listdir |
900 |
+ else: |
901 |
+@@ -598,11 +615,17 @@ class vardbapi(dbapi): |
902 |
+ del self.matchcache[mycat] |
903 |
+ return list(self._iter_match(mydep, |
904 |
+ self.cp_list(mydep.cp, use_cache=use_cache))) |
905 |
++ |
906 |
++ _tmp_path = os.path.join(self._eroot, VDB_PATH, mycat) |
907 |
++ |
908 |
++ if self._kill_eprefix: |
909 |
++ _tmp_path = _tmp_path.replace(EPREFIX, "") |
910 |
++ |
911 |
+ try: |
912 |
+ if sys.hexversion >= 0x3030000: |
913 |
+- curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime_ns |
914 |
++ curmtime = os.stat(_tmp_path).st_mtime_ns |
915 |
+ else: |
916 |
+- curmtime = os.stat(os.path.join(self._eroot, VDB_PATH, mycat)).st_mtime |
917 |
++ curmtime = os.stat(_tmp_path).st_mtime |
918 |
+ except (IOError, OSError): |
919 |
+ curmtime=0 |
920 |
+ |
921 |
+@@ -1450,7 +1473,7 @@ class vardbapi(dbapi): |
922 |
+ class vartree(object): |
923 |
+ "this tree will scan a var/db/pkg database located at root (passed to init)" |
924 |
+ def __init__(self, root=None, virtual=DeprecationWarning, categories=None, |
925 |
+- settings=None): |
926 |
++ settings=None, kill_eprefix=None): |
927 |
+ |
928 |
+ if settings is None: |
929 |
+ settings = portage.settings |
930 |
+@@ -1468,6 +1491,7 @@ class vartree(object): |
931 |
+ " constructor is unused", |
932 |
+ DeprecationWarning, stacklevel=2) |
933 |
+ |
934 |
++ self._kill_eprefix = kill_eprefix |
935 |
+ self.settings = settings |
936 |
+ self.dbapi = vardbapi(settings=settings, vartree=self) |
937 |
+ self.populated = 1 |
938 |
+diff --git a/pym/portage/dep/dep_check.py b/pym/portage/dep/dep_check.py |
939 |
+index 2896e2389..c700a3651 100644 |
940 |
+--- a/pym/portage/dep/dep_check.py |
941 |
++++ b/pym/portage/dep/dep_check.py |
942 |
+@@ -298,6 +298,95 @@ class _dep_choice(SlotObject): |
943 |
+ __slots__ = ('atoms', 'slot_map', 'cp_map', 'all_available', |
944 |
+ 'all_installed_slots', 'new_slot_count') |
945 |
+ |
946 |
++ro_trees={} |
947 |
++ro_vartrees={} |
948 |
++ro_selected=[] |
949 |
++ |
950 |
++def dep_match_readonly_roots(settings, atom, dep_type, parent=None): |
951 |
++ if len(ro_trees) < len(settings.readonly_prefixes): |
952 |
++ # MDUFT: create additional vartrees for every readonly root here. |
953 |
++ # the ro_vartrees instances are created below as they are needed to |
954 |
++ # avoid reading vartrees of portage instances which aren't required |
955 |
++ # while resolving this dependencies. |
956 |
++ for type in ("DEPEND","RDEPEND", "PDEPEND"): |
957 |
++ ro_trees[type] = [] |
958 |
++ |
959 |
++ for ro_root, ro_dep_types in settings.readonly_prefixes.items(): |
960 |
++ if type in ro_dep_types: |
961 |
++ ro_trees[type].append(ro_root) |
962 |
++ |
963 |
++ if len(ro_trees) == 0: |
964 |
++ return [] |
965 |
++ |
966 |
++ matches = [] |
967 |
++ |
968 |
++ for ro_root in ro_trees[dep_type]: |
969 |
++ if not ro_root in ro_vartrees: |
970 |
++ # target_root=ro_root ok? or should it be the real target_root? |
971 |
++ _tmp_settings = portage.config(config_root=ro_root, target_root=ro_root, |
972 |
++ config_incrementals=portage.const.INCREMENTALS) |
973 |
++ |
974 |
++ ro_vartrees[ro_root] = portage.vartree(root=ro_root, |
975 |
++ categories=_tmp_settings.categories, |
976 |
++ settings=_tmp_settings, kill_eprefix=True) |
977 |
++ |
978 |
++ ro_matches = ro_vartrees[ro_root].dbapi.match(atom) |
979 |
++ |
980 |
++ if ro_matches: |
981 |
++ ro_host_mismatch = False |
982 |
++ if dep_type is "RDEPEND": |
983 |
++ # we need to assure binary compatability, so it needs to be |
984 |
++ # the same CHOST! But how? for now i cannot do anything... |
985 |
++ if parent and parent.metadata["CHOST"] != ro_vartrees[ro_root].settings.get("CHOST", ""): |
986 |
++ # provocate a big fat warning in the list of external packages. |
987 |
++ ro_host_mismatch = True |
988 |
++ pass |
989 |
++ |
990 |
++ matches.append({ "ro_root": ro_root, "atom": atom, "matches": ro_matches, |
991 |
++ "type": dep_type, "parent": parent, "host_mismatch": ro_host_mismatch }) |
992 |
++ |
993 |
++ return matches |
994 |
++ |
995 |
++def dep_wordreduce_readonly(reduced, unreduced, settings, dep_type, parent): |
996 |
++ for mypos, token in enumerate(unreduced): |
997 |
++ # recurse if it's a list. |
998 |
++ if isinstance(reduced[mypos], list): |
999 |
++ reduced[mypos] = dep_wordreduce_readonly(reduced[mypos], |
1000 |
++ unreduced[mypos], settings, dep_type, parent) |
1001 |
++ |
1002 |
++ # do nothing if it's satisfied already. |
1003 |
++ elif not reduced[mypos]: |
1004 |
++ ro_matches = dep_match_readonly_roots(settings, unreduced[mypos], dep_type, parent) |
1005 |
++ |
1006 |
++ if ro_matches: |
1007 |
++ # TODO: select a match if there are more than one? |
1008 |
++ # for now, the first match is taken... |
1009 |
++ ro_selected.append(ro_matches[0]) |
1010 |
++ reduced[mypos] = True |
1011 |
++ |
1012 |
++ return reduced |
1013 |
++ |
1014 |
++# this may be better placed somewhere else, but i put it here for now, to |
1015 |
++# keep all functions in the patch on one big heap. |
1016 |
++def readonly_pathmatch_any(settings, path): |
1017 |
++ path = path.lstrip('/') |
1018 |
++ # first try locally, and match that if it exists. |
1019 |
++ if os.path.exists(os.path.join(EPREFIX,path)): |
1020 |
++ return os.path.join(EPREFIX,path) |
1021 |
++ |
1022 |
++ # after that try all readonly roots where DEPEND is allowed. this makes |
1023 |
++ # sure that executing binaries is possible from there. |
1024 |
++ for ro_root, ro_deps in settings.readonly_roots.items(): |
1025 |
++ if "DEPEND" in ro_deps: |
1026 |
++ print(" --- checking %s --- " % (os.path.join(ro_root,path))) |
1027 |
++ if os.path.exists(os.path.join(ro_root,path)): |
1028 |
++ return os.path.join(ro_root,path) |
1029 |
++ break |
1030 |
++ |
1031 |
++ # as a fallback make the string the same as it was originally. |
1032 |
++ # even though this path doesn't exist. |
1033 |
++ return os.path.join(EPREFIX,path) |
1034 |
++ |
1035 |
+ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None, |
1036 |
+ minimize_slots=False): |
1037 |
+ """ |
1038 |
+@@ -725,7 +814,7 @@ def dep_zapdeps(unreduced, reduced, myroot, use_binaries=0, trees=None, |
1039 |
+ assert(False) # This point should not be reachable |
1040 |
+ |
1041 |
+ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None, |
1042 |
+- use_cache=1, use_binaries=0, myroot=None, trees=None): |
1043 |
++ use_cache=1, use_binaries=0, myroot=None, trees=None, dep_type=None): |
1044 |
+ """ |
1045 |
+ Takes a depend string, parses it, and selects atoms. |
1046 |
+ The myroot parameter is unused (use mysettings['EROOT'] instead). |
1047 |
+@@ -829,6 +918,14 @@ def dep_check(depstring, mydbapi, mysettings, use="yes", mode=None, myuse=None, |
1048 |
+ writemsg("mysplit: %s\n" % (mysplit), 1) |
1049 |
+ writemsg("mysplit2: %s\n" % (mysplit2), 1) |
1050 |
+ |
1051 |
++ if dep_type is not None: |
1052 |
++ mysplit2=dep_wordreduce_readonly(unreduced=mysplit[:], |
1053 |
++ reduced=mysplit2, settings=mysettings, |
1054 |
++ dep_type=dep_type, parent=trees[myroot].get("disp_parent")) |
1055 |
++ |
1056 |
++ writemsg("\n", 1) |
1057 |
++ writemsg("mysplit2 after readonly reduce: %s\n" % (mysplit2), 1) |
1058 |
++ |
1059 |
+ selected_atoms = dep_zapdeps(mysplit, mysplit2, myroot, |
1060 |
+ use_binaries=use_binaries, trees=trees, minimize_slots=dnf) |
1061 |
+ |
1062 |
+diff --git a/pym/portage/package/ebuild/_config/LocationsManager.py b/pym/portage/package/ebuild/_config/LocationsManager.py |
1063 |
+index f7d7209ff..e37e5b1a9 100644 |
1064 |
+--- a/pym/portage/package/ebuild/_config/LocationsManager.py |
1065 |
++++ b/pym/portage/package/ebuild/_config/LocationsManager.py |
1066 |
+@@ -326,6 +326,9 @@ class LocationsManager(object): |
1067 |
+ if portage.const.EPREFIX: |
1068 |
+ self.global_config_path = os.path.join(portage.const.EPREFIX, |
1069 |
+ GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
1070 |
++ if not exists_raise_eaccess(self.global_config_path) and portage.const.BPREFIX: |
1071 |
++ self.global_config_path = os.path.join(portage.const.BPREFIX, |
1072 |
++ GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
1073 |
+ |
1074 |
+ def set_port_dirs(self, portdir, portdir_overlay): |
1075 |
+ self.portdir = portdir |
1076 |
+diff --git a/pym/portage/package/ebuild/config.py b/pym/portage/package/ebuild/config.py |
1077 |
+index 059aa83ce..3bf6049e8 100644 |
1078 |
+--- a/pym/portage/package/ebuild/config.py |
1079 |
++++ b/pym/portage/package/ebuild/config.py |
1080 |
+@@ -309,6 +309,7 @@ class config(object): |
1081 |
+ self.features = features_set(self) |
1082 |
+ self.features._features = copy.deepcopy(clone.features._features) |
1083 |
+ self._features_overrides = copy.deepcopy(clone._features_overrides) |
1084 |
++ self.readonly_prefixes = copy.deepcopy(clone.readonly_prefixes) |
1085 |
+ |
1086 |
+ #Strictly speaking _license_manager is not immutable. Users need to ensure that |
1087 |
+ #extract_global_changes() is called right after __init__ (if at all). |
1088 |
+@@ -969,6 +970,63 @@ class config(object): |
1089 |
+ |
1090 |
+ self._validate_commands() |
1091 |
+ |
1092 |
++ # expand READONLY_EPREFIX to a list of all readonly portage instances |
1093 |
++ # all the way down to the last one. beware that ATM a deeper instance |
1094 |
++ # in the chain can provide more than the toplevel! this means that |
1095 |
++ # if you only inherit DEPENDS from one instance, that instance may |
1096 |
++ # inherit RDEPENDs from another one, making the top-level instance |
1097 |
++ # inherit RDEPENDs from there too - even if the intermediate prefix |
1098 |
++ # does not do this. |
1099 |
++ self.readonly_prefixes = {} |
1100 |
++ ro_cfg_root = config_root |
1101 |
++ ro_widest_depset = set(['DEPEND', 'RDEPEND', 'PDEPEND']) |
1102 |
++ |
1103 |
++ while ro_cfg_root: |
1104 |
++ ro_make_conf_paths = [ |
1105 |
++ os.path.join(ro_cfg_root, 'etc', 'make.conf'), |
1106 |
++ os.path.join(ro_cfg_root, MAKE_CONF_FILE) |
1107 |
++ ] |
1108 |
++ try: |
1109 |
++ if os.path.samefile(*ro_make_conf_paths): |
1110 |
++ ro_make_conf_paths.pop() |
1111 |
++ except OSError: |
1112 |
++ pass |
1113 |
++ |
1114 |
++ ro_cfg_root = None |
1115 |
++ for ro_make_conf in ro_make_conf_paths: |
1116 |
++ if not os.path.exists(ro_make_conf): |
1117 |
++ continue |
1118 |
++ |
1119 |
++ ro_cfg = getconfig(ro_make_conf, tolerant=True, allow_sourcing=True) |
1120 |
++ if not "READONLY_EPREFIX" in ro_cfg: |
1121 |
++ continue |
1122 |
++ |
1123 |
++ if not ro_cfg["READONLY_EPREFIX"].find(":"): |
1124 |
++ raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s" % (ro_make_conf)) |
1125 |
++ |
1126 |
++ if ro_cfg_root is not None: |
1127 |
++ raise portage.exception.InvalidReadonlyERoot("ERROR: duplicate READONLY_EPREFIX in %s and %s" % tuple(ro_make_conf_paths)) |
1128 |
++ |
1129 |
++ (ro_cfg_root,ro_cfg_root_deps) = ro_cfg["READONLY_EPREFIX"].rsplit(":",1) |
1130 |
++ |
1131 |
++ if not os.path.exists(ro_cfg_root): |
1132 |
++ raise portage.exception.InvalidReadonlyERoot("ERROR: malformed READONLY_EPREFIX in %s: %s does not exist!" % (ro_make_conf, ro_cfg_root)) |
1133 |
++ |
1134 |
++ if os.path.samefile(ro_cfg_root, config_root): |
1135 |
++ raise portage.exception.InvalidReadonlyERoot("ERROR: cannot add this instance (%s) as READONLY_EPREFIX in %s." % (ro_cfg_root, ro_make_conf)) |
1136 |
++ |
1137 |
++ if ro_cfg_root in self.readonly_prefixes: |
1138 |
++ raise portage.exception.InvalidReadonlyERoot("ERROR: circular READONLY_EPREFIX's in %s. %s already checked for %s" % (ro_make_conf, ro_cfg_root, self.readonly_prefixes[ro_cfg_root])) |
1139 |
++ |
1140 |
++ # intersect the widest depset with the current one to strip down |
1141 |
++ # the allowed dependency resolution to not be wider than the |
1142 |
++ # next higher one. this way we can prevent for a given prefix |
1143 |
++ # to resolve RDEPENDs from a prefix with a different CHOST that |
1144 |
++ # is a few levels deeper in the chain. |
1145 |
++ ro_widest_depset = set(ro_cfg_root_deps.split(",")) & ro_widest_depset |
1146 |
++ self.readonly_prefixes[ro_cfg_root] = ro_widest_depset |
1147 |
++ pass |
1148 |
++ |
1149 |
+ for k in self._case_insensitive_vars: |
1150 |
+ if k in self: |
1151 |
+ self[k] = self[k].lower() |
1152 |
+@@ -2771,6 +2829,10 @@ class config(object): |
1153 |
+ if not (src_phase and eapi_attrs.broot): |
1154 |
+ mydict.pop("BROOT", None) |
1155 |
+ |
1156 |
++ # populate with PORTAGE_READONLY_EPREFIXES |
1157 |
++ if self.readonly_prefixes and len(self.readonly_prefixes) > 0: |
1158 |
++ mydict["PORTAGE_READONLY_EPREFIXES"] = ':'.join(self.readonly_prefixes) |
1159 |
++ |
1160 |
+ # Prefix variables are supported beginning with EAPI 3, or when |
1161 |
+ # force-prefix is in FEATURES, since older EAPIs would otherwise be |
1162 |
+ # useless with prefix configurations. This brings compatibility with |
1163 |
+diff --git a/pym/portage/package/ebuild/doebuild.py b/pym/portage/package/ebuild/doebuild.py |
1164 |
+index f8b784d6b..a6548a43b 100644 |
1165 |
+--- a/pym/portage/package/ebuild/doebuild.py |
1166 |
++++ b/pym/portage/package/ebuild/doebuild.py |
1167 |
+@@ -52,6 +52,7 @@ from portage import bsd_chflags, \ |
1168 |
+ unmerge, _encodings, _os_merge, \ |
1169 |
+ _shell_quote, _unicode_decode, _unicode_encode |
1170 |
+ from portage.const import EBUILD_SH_ENV_FILE, EBUILD_SH_ENV_DIR, \ |
1171 |
++ GLOBAL_CONFIG_PATH, \ |
1172 |
+ EBUILD_SH_BINARY, INVALID_ENV_FILE, MISC_SH_BINARY, PORTAGE_PYM_PACKAGES, EPREFIX, MACOSSANDBOX_PROFILE |
1173 |
+ from portage.data import portage_gid, portage_uid, secpass, \ |
1174 |
+ uid, userpriv_groups |
1175 |
+@@ -73,6 +74,7 @@ from portage.package.ebuild.prepare_build_dirs import prepare_build_dirs |
1176 |
+ from portage.process import find_binary |
1177 |
+ from portage.util import ( apply_recursive_permissions, |
1178 |
+ apply_secpass_permissions, |
1179 |
++ getconfig, |
1180 |
+ noiselimit, |
1181 |
+ shlex_split, |
1182 |
+ varexpand, |
1183 |
+@@ -80,6 +82,7 @@ from portage.util import ( apply_recursive_permissions, |
1184 |
+ writemsg_stdout, |
1185 |
+ write_atomic |
1186 |
+ ) |
1187 |
++from portage.util._path import exists_raise_eaccess |
1188 |
+ from portage.util.cpuinfo import get_cpu_count |
1189 |
+ from portage.util.lafilefixer import rewrite_lafile |
1190 |
+ from portage.util.compression_probe import _compressors |
1191 |
+@@ -243,8 +246,27 @@ def _doebuild_path(settings, eapi=None): |
1192 |
+ |
1193 |
+ for x in portage_bin_path: |
1194 |
+ path.append(os.path.join(x, "ebuild-helpers")) |
1195 |
++ |
1196 |
++ # PREFIX CHAINING: append default path for all prefixes involved |
1197 |
++ pfxs = [ eprefix ] |
1198 |
++ pfxs.extend(settings.readonly_prefixes) |
1199 |
++ for prefix in pfxs: |
1200 |
++ global_config_path = os.path.join(prefix, GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
1201 |
++ make_globals_path = os.path.join(global_config_path, "make.globals") |
1202 |
++ if exists_raise_eaccess(make_globals_path): |
1203 |
++ expand_map = { "EPREFIX": prefix } |
1204 |
++ pxcfg = getconfig(make_globals_path, True, expand_map) |
1205 |
++ pxdefp = [x for x in pxcfg.get("DEFAULT_PATH", "").split(":") if x] |
1206 |
++ for x in pxdefp: |
1207 |
++ if x.startswith(prefix) and not x in path: |
1208 |
++ path.append(x) |
1209 |
++ else: |
1210 |
++ pxdefs = [prefix + "/usr/sbin", prefix + "/usr/bin", prefix + "/sbin", prefix + "/bin"] |
1211 |
++ path.extend(pxdefs) |
1212 |
++ # END PREFIX CHAINING |
1213 |
++ |
1214 |
+ path.extend(prerootpath) |
1215 |
+- path.extend(defaultpath) |
1216 |
++ # path.extend(defaultpath) # PREFIX CHAINING appends the default path for involved prefixes above |
1217 |
+ path.extend(rootpath) |
1218 |
+ path.extend(extrapath) |
1219 |
+ # END PREFIX LOCAL |
1220 |
+diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py |
1221 |
+index 265d0c9fc..2ec6ff472 100644 |
1222 |
+--- a/pym/portage/package/ebuild/fetch.py |
1223 |
++++ b/pym/portage/package/ebuild/fetch.py |
1224 |
+@@ -43,6 +43,7 @@ from portage.output import colorize, EOutput |
1225 |
+ from portage.util import apply_recursive_permissions, \ |
1226 |
+ apply_secpass_permissions, ensure_dirs, grabdict, shlex_split, \ |
1227 |
+ varexpand, writemsg, writemsg_level, writemsg_stdout |
1228 |
++from portage.util._path import exists_raise_eaccess |
1229 |
+ from portage.process import spawn |
1230 |
+ |
1231 |
+ _userpriv_spawn_kwargs = ( |
1232 |
+@@ -874,6 +875,9 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, |
1233 |
+ global_config_path = GLOBAL_CONFIG_PATH |
1234 |
+ if portage.const.EPREFIX: |
1235 |
+ global_config_path = os.path.join(portage.const.EPREFIX, |
1236 |
++ GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
1237 |
++ if not exists_raise_eaccess(global_config_path) and portage.const.BPREFIX: |
1238 |
++ global_config_path = os.path.join(portage.const.BPREFIX, |
1239 |
+ GLOBAL_CONFIG_PATH.lstrip(os.sep)) |
1240 |
+ |
1241 |
+ missing_file_param = False |
1242 |
+diff --git a/pym/portage/sync/controller.py b/pym/portage/sync/controller.py |
1243 |
+index 3bccf6f74..cacd63797 100644 |
1244 |
+--- a/pym/portage/sync/controller.py |
1245 |
++++ b/pym/portage/sync/controller.py |
1246 |
+@@ -94,19 +94,20 @@ class SyncManager(object): |
1247 |
+ self.module_controller = portage.sync.module_controller |
1248 |
+ self.module_names = self.module_controller.module_names |
1249 |
+ self.hooks = {} |
1250 |
+- for _dir in ["repo.postsync.d", "postsync.d"]: |
1251 |
+- postsync_dir = os.path.join(self.settings["PORTAGE_CONFIGROOT"], |
1252 |
+- portage.USER_CONFIG_PATH, _dir) |
1253 |
+- hooks = OrderedDict() |
1254 |
+- for filepath in util._recursive_file_list(postsync_dir): |
1255 |
+- name = filepath.split(postsync_dir)[1].lstrip(os.sep) |
1256 |
+- if os.access(filepath, os.X_OK): |
1257 |
+- hooks[filepath] = name |
1258 |
+- else: |
1259 |
+- writemsg_level(" %s %s hook: '%s' is not executable\n" |
1260 |
+- % (warn("*"), _dir, _unicode_decode(name),), |
1261 |
+- level=logging.WARN, noiselevel=2) |
1262 |
+- self.hooks[_dir] = hooks |
1263 |
++ for _confroot in [self.settings["PORTAGE_CONFIGROOT"], portage.const.BPREFIX]: |
1264 |
++ for _dir in ["repo.postsync.d", "postsync.d"]: |
1265 |
++ postsync_dir = os.path.join(_confroot, |
1266 |
++ portage.USER_CONFIG_PATH, _dir) |
1267 |
++ hooks = OrderedDict() |
1268 |
++ for filepath in util._recursive_file_list(postsync_dir): |
1269 |
++ name = filepath.split(postsync_dir)[1].lstrip(os.sep) |
1270 |
++ if os.access(filepath, os.X_OK): |
1271 |
++ hooks[filepath] = name |
1272 |
++ else: |
1273 |
++ writemsg_level(" %s %s hook: '%s' is not executable\n" |
1274 |
++ % (warn("*"), _dir, _unicode_decode(name),), |
1275 |
++ level=logging.WARN, noiselevel=2) |
1276 |
++ self.hooks[_dir] = hooks |
1277 |
+ |
1278 |
+ def __getattr__(self, name): |
1279 |
+ if name == 'async': |
1280 |
+diff --git a/pym/portage/util/_dyn_libs/LinkageMapELF.py b/pym/portage/util/_dyn_libs/LinkageMapELF.py |
1281 |
+index a063621c1..968fbd339 100644 |
1282 |
+--- a/pym/portage/util/_dyn_libs/LinkageMapELF.py |
1283 |
++++ b/pym/portage/util/_dyn_libs/LinkageMapELF.py |
1284 |
+@@ -12,7 +12,7 @@ from portage import _os_merge |
1285 |
+ from portage import _unicode_decode |
1286 |
+ from portage import _unicode_encode |
1287 |
+ from portage.cache.mappings import slot_dict_class |
1288 |
+-from portage.const import EPREFIX |
1289 |
++from portage.const import BPREFIX |
1290 |
+ from portage.dep.soname.multilib_category import compute_multilib_category |
1291 |
+ from portage.exception import CommandNotFound, InvalidData |
1292 |
+ from portage.localization import _ |
1293 |
+@@ -268,7 +268,7 @@ class LinkageMapELF(object): |
1294 |
+ continue |
1295 |
+ plibs.update((x, cpv) for x in items) |
1296 |
+ if plibs: |
1297 |
+- args = [os.path.join(EPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"] |
1298 |
++ args = [os.path.join(BPREFIX or "/", "usr/bin/scanelf"), "-qF", "%a;%F;%S;%r;%n"] |
1299 |
+ args.extend(os.path.join(root, x.lstrip("." + os.sep)) \ |
1300 |
+ for x in plibs) |
1301 |
+ try: |
1302 |
+-- |
1303 |
+2.16.1 |
1304 |
+ |
1305 |
|
1306 |
diff --git a/sys-apps/portage/portage-2.3.40.1.ebuild b/sys-apps/portage/portage-2.3.40.1.ebuild |
1307 |
index bf7393b3ac..0bea1d9f01 100644 |
1308 |
--- a/sys-apps/portage/portage-2.3.40.1.ebuild |
1309 |
+++ b/sys-apps/portage/portage-2.3.40.1.ebuild |
1310 |
@@ -91,10 +91,9 @@ pkg_setup() { |
1311 |
python_prepare_all() { |
1312 |
distutils-r1_python_prepare_all |
1313 |
|
1314 |
- # fails to apply |
1315 |
- #epatch "${FILESDIR}"/${PN}-2.3.10-ebuildshell.patch # 155161 |
1316 |
+ epatch "${FILESDIR}"/${PN}-2.3.40-ebuildshell.patch # 155161 |
1317 |
use prefix-chaining && |
1318 |
- epatch "${FILESDIR}"/${PN}-2.3.18-prefix-chaining.patch |
1319 |
+ epatch "${FILESDIR}"/${PN}-2.3.40-prefix-chaining.patch |
1320 |
|
1321 |
if use native-extensions; then |
1322 |
printf "[build_ext]\nportage-ext-modules=true\n" >> \ |