Re: [gentoo-portage-dev] [PATCH 2/2] pym/portage/util/locale.py: add a C module to check locale

2016-05-19 Thread Michał Górny
' : [
>+  'src/check_locale.c',
>+  ],
>+}
> 
> class x_build(build):
>   """ Build command with extra build_man call. """
>diff --git a/src/check_locale.c b/src/check_locale.c
>new file mode 100644
>index 000..9762ef2
>--- /dev/null
>+++ b/src/check_locale.c
>@@ -0,0 +1,144 @@
>+/* Copyright 2005-2015 Gentoo Foundation
>+ * Distributed under the terms of the GNU General Public License v2
>+ */
>+
>+#include 
>+#include 
>+#include 
>+
>+static PyObject * portage_c_check_locale(PyObject *, PyObject *);
>+
>+static PyMethodDef CheckLocaleMethods[] = {
>+  {"_c_check_locale", portage_c_check_locale, METH_NOARGS, "Check the
>system locale."},
>+  {NULL, NULL, 0, NULL}
>+};
>+
>+#if PY_MAJOR_VERSION >= 3
>+static struct PyModuleDef moduledef = {
>+  PyModuleDef_HEAD_INIT,
>+  "portage_c_check_locale",   /* 
>m_name */
>+  "Module for checking the system locale for portage",/* 
>m_doc */
>+  -1, /* 
>m_size */
>+  CheckLocaleMethods, /* 
>m_methods */
>+  NULL,   /* 
>m_reload */
>+  NULL,   /* 
>m_traverse */
>+  NULL,   /* 
>m_clear */
>+  NULL,   /* 
>m_free */
>+};
>+#endif
>+
>+static PyObject *LocaleError;
>+
>+PyMODINIT_FUNC
>+#if PY_MAJOR_VERSION >= 3
>+PyInit_portage_c_check_locale(void)
>+#else
>+initportage_c_check_locale(void)
>+#endif
>+{
>+  PyObject *m;
>+
>+#if PY_MAJOR_VERSION >= 3
>+  m = PyModule_Create(&moduledef);
>+#else
>+  m = Py_InitModule("portage_c_check_locale", CheckLocaleMethods);
>+#endif
>+
>+  if (m == NULL)
>+#if PY_MAJOR_VERSION >= 3
>+  return NULL;
>+#else
>+  return;
>+#endif
>+
>+  LocaleError = PyErr_NewException("locale.LocaleError", NULL, NULL);
>+  Py_INCREF(LocaleError);
>+  PyModule_AddObject(m, "LocaleError", LocaleError);
>+
>+#if PY_MAJOR_VERSION >= 3
>+  return m;
>+#else
>+  return;
>+#endif
>+}
>+
>+
>+static void
>+error_msg(char msg[], int c[], int rc[], int ac[])
>+{
>+  int i, p;
>+
>+  strcat(msg, "  ");
>+  p = strlen(msg);
>+  for (i = 'a'; i <= 'z'; i++)
>+  msg[p++] = c[i-'a'];
>+
>+  strcat(msg, " -> ");
>+  p = strlen(msg);
>+  for (i = 'a'; i <= 'z'; i++)
>+  msg[p++] = rc[i-'a'];
>+  strcat(msg, "\n");
>+
>+  strcat(msg, "  expected: ");
>+  p = strlen(msg);
>+  for (i = 'a'; i <= 'z'; i++)
>+  msg[p++] = ac[i-'a'];
>+  strcat(msg, "\n\n");
>+}
>+
>+
>+static PyObject *
>+portage_c_check_locale(PyObject *self, PyObject *args)
>+{
>+  int i, upper = 1, lower = 1;
>+  int lc[26], uc[26], rlc[26], ruc[26];
>+  char msg[1024];
>+
>+  memset(msg, 0, 1024);
>+
>+  for (i = 'a'; i <= 'z'; i++) {
>+  lc[i-'a'] = i;
>+  ruc[i-'a'] = toupper(i);
>+  }
>+
>+  for (i = 'A'; i <= 'Z'; i++) {
>+  uc[i-'A'] = i;
>+  rlc[i-'A'] = tolower(i);
>+  }
>+
>+  for (i = 'a'; i <= 'z'; i++)
>+      if(lc[i-'a'] != rlc[i-'a']) {
>+  lower = 0;
>+  break;
>+  }
>+
>+  for (i = 'A'; i <= 'Z'; i++)
>+  if(uc[i-'A'] != ruc[i-'A']) {
>+  upper = 0;
>+  break;
>+  }
>+
>+  if (lower == 0 || upper == 0) {
>+  strcpy(msg,
>+  "!!! WARNING: The LC_CTYPE variable is set to a locale 
>that
>specifies\n"
>+  "!!! transformation between lowercase and uppercase 
>ASCII
>characters that\n"
>+  "!!! is different than the one specified by POSIX 
>locale. This can
>break\n"
>+  "!!! ebuilds and cause issues in programs that rely on 
>the common
>character\n"
>+  "!!! conversion scheme.  Please consider enabling 
>another locale
>(such as\n"
>+  "!!! en_US.UTF-8) in /etc/locale.gen and setting it as 
>LC_CTYPE
>in\n"
>+  "!!! make.conf.\n\n"
>+  );
>+
>+  if (lower == 0)
>+  error_msg(msg, lc, ruc, uc);
>+
>+  if (upper == 0)
>+  error_msg(msg, uc, rlc, lc);
>+  }
>+
>+#if PY_MAJOR_VERSION >= 3
>+  return Py_BuildValue("iy", lower && upper, msg);
>+#else
>+  return Py_BuildValue("is", lower && upper, msg);
>+#endif
>+}


-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH 2/2] pym/portage/util/locale.py: add a C module to check locale

2016-05-20 Thread Michał Górny
On Fri, 20 May 2016 06:59:14 -0400
"Anthony G. Basile"  wrote:

> On 5/19/16 9:38 AM, Michał Górny wrote:
> > Dnia 19 maja 2016 14:43:38 CEST, "Anthony G. Basile" 
> >  napisał(a):  
> >> From: "Anthony G. Basile" 
> >>
> >> The current method to check for the system locale is to use python's
> >> ctypes.util.find_library() to construct a full library path to the
> >> system libc.so which is then passed to ctypes.CDLL().  However,
> >> this gets bogged down in implementation dependant details and
> >> fails with musl.
> >>
> >> We work around this design flaw in ctypes with a small python module
> >> written in C called 'portage_c_check_locale', and only fall back on
> >> the current ctypes-based check when this module is not available.
> >>
> >> This has been tested on glibc, uClibc and musl systems.
> >>
> >> X-Gentoo-bug: 571444
> >> X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=571444
> >> Signed-off-by: Anthony G. Basile   
> > 
> > To be honest, I don't like this. Do we really want to duplicate all this, 
> > including duplicating the complete messages? This really looks messy and 
> > unmaintainable.
> > 
> > The only reason libc functions were being used was to workaround the hacky 
> > built-in case conversion functions. And this is the only part where CDLL 
> > was really used.
> > 
> > So please change this to provide trivial wrappers around the C library 
> > functions, and use them alternatively to ones obtained using CDLL. With a 
> > single common code doing all the check logic and messaging.
> > 
> >   
> 
> ctypes is itself a problem and so hacky python built-ins were replaced
> by more hacky python.  CDLL shouldn't be used at all.  The other problem
> is that non utf-8 encodings cause problems much earlier in the portage
> codebase than the test for a sane environment, which is a bigger problem
> than this small issue.  No one checked what happens with python2.7 +
> portage + exotic locale.  Since I don't know where this might head in
> the future, I kinda like the standalone potential.  The only repeated
> code here is the message.  Nonetheless, I can reduce this to just two
> functions, and do something like the following.  I assume that's what
> you're suggesting:
> 
> try:
>   from portage_c_convert_case import _c_toupper, _c_tolower
>   libc_toupper = _c_toupper
>   libc_lolower = _c_tolower
> except ImportError:
>   libc_fn = find_library("c")
>   if libc_fn is None:
>   return None
>   libc = LoadLibrary(libc_fn)
>   if libc is None:
>   return None
>   libc_toupper = libc.toupper
>   libc_tolower = libc.tolower
> 
> 
> Incidentally, another approach, one that I use in bash is as follows.  I
> think it requires bash4, and I'm not sure how to pull this into python
> gracefully.
> 
> l="abcdefghijklmnopqrstuvwxyz"
> u="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
> ru=${l^^}
> rl=${u,,}
> [[ $l == $rl ]] && echo "lower case okay" || echo "lower case bad"
> [[ $u == $ru ]] && echo "upper case okay" || echo "upper case bad"

Exactly as pointed out above. You have to import tolower()
and toupper() from libc as Python case conversion functions don't give
the same results as 'pure' libc used by bash.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpfrBpVYAfyE.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH 1/2] portage.package.ebuild.config: Rename iuse_implicit -> iuse_effective

2016-05-20 Thread Michał Górny
Rename the iuse_implicit variable used in USE_EXPAND handling to
iuse_effective, since that is what is actually passed there. Correct
naming makes figuring out what the function does much easier.
---
 pym/portage/package/ebuild/config.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 45b7d08..5f19996 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -1278,13 +1278,13 @@ class config(object):
"""
 
def __init__(self, settings, unfiltered_use,
-   use, usemask, iuse_implicit,
+   use, usemask, iuse_effective,
use_expand_split, use_expand_dict):
self._settings = settings
self._unfiltered_use = unfiltered_use
self._use = use
self._usemask = usemask
-   self._iuse_implicit = iuse_implicit
+   self._iuse_effective = iuse_effective
self._use_expand_split = use_expand_split
self._use_expand_dict = use_expand_dict
 
@@ -1302,7 +1302,7 @@ class config(object):
if has_wildcard:
var_split = [ x for x in var_split if x != "*" ]
has_iuse = set()
-   for x in self._iuse_implicit:
+   for x in self._iuse_effective:
if x[:prefix_len] == prefix:
has_iuse.add(x[prefix_len:])
if has_wildcard:
-- 
2.8.2




[gentoo-portage-dev] [PATCH 2/2] ebuild.config: Fix filtering all USE_EXPAND variables in EAPI 5+

2016-05-20 Thread Michał Górny
Ensure that all USE_EXPAND variables are properly filtered and exported
in EAPI 5 and newer, as required by the PMS. This includes exporting
an empty value if no matching flag is provided in IUSE.

Bug: https://bugs.gentoo.org/show_bug.cgi?id=582140
---
 pym/portage/eapi.py  |  6 +-
 pym/portage/package/ebuild/config.py | 11 ---
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py
index 1709026..c4fb374 100644
--- a/pym/portage/eapi.py
+++ b/pym/portage/eapi.py
@@ -50,6 +50,9 @@ def eapi_exports_EBUILD_PHASE_FUNC(eapi):
 def eapi_exports_REPOSITORY(eapi):
return eapi in ("4-python", "5-progress")
 
+def eapi_exports_USE_EXPAND_variables(eapi):
+   return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
+
 def eapi_has_pkg_pretend(eapi):
return eapi not in ("0", "1", "2", "3")
 
@@ -101,7 +104,7 @@ def eapi_has_targetroot(eapi):
 
 _eapi_attrs = collections.namedtuple('_eapi_attrs',
'dots_in_PN dots_in_use_flags exports_EBUILD_PHASE_FUNC '
-   'feature_flag_test feature_flag_targetroot '
+   'exports_USE_EXPAND_variables feature_flag_test feature_flag_targetroot 
'
'hdepend iuse_defaults iuse_effective posixish_locale '
'repo_deps required_use required_use_at_most_one_of slot_operator 
slot_deps '
'src_uri_arrows strong_blocks use_deps use_dep_defaults')
@@ -128,6 +131,7 @@ def _get_eapi_attrs(eapi):
dots_in_PN = (eapi is None or eapi_allows_dots_in_PN(eapi)),
dots_in_use_flags = (eapi is None or 
eapi_allows_dots_in_use_flags(eapi)),
exports_EBUILD_PHASE_FUNC = (eapi is None or 
eapi_exports_EBUILD_PHASE_FUNC(eapi)),
+   exports_USE_EXPAND_variables = (eapi is None or 
eapi_exports_USE_EXPAND_variables(eapi)),
feature_flag_test = True,
feature_flag_targetroot = (eapi is not None and 
eapi_has_targetroot(eapi)),
hdepend = (eapi is not None and eapi_has_hdepend(eapi)),
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 5f19996..ee1fadb 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -1279,7 +1279,7 @@ class config(object):
 
def __init__(self, settings, unfiltered_use,
use, usemask, iuse_effective,
-   use_expand_split, use_expand_dict):
+   use_expand_split, use_expand_dict, 
eapi_exports_USE_EXPAND_variables):
self._settings = settings
self._unfiltered_use = unfiltered_use
self._use = use
@@ -1287,6 +1287,7 @@ class config(object):
self._iuse_effective = iuse_effective
self._use_expand_split = use_expand_split
self._use_expand_dict = use_expand_dict
+   self._eapi_exports_USE_EXPAND_variables = 
eapi_exports_USE_EXPAND_variables
 
def __getitem__(self, key):
prefix = key.lower() + '_'
@@ -1330,7 +1331,7 @@ class config(object):
filtered_var_split.append(x)
var_split = filtered_var_split
 
-   if var_split:
+   if var_split or self._eapi_exports_USE_EXPAND_variables:
value = ' '.join(var_split)
else:
# Don't export empty USE_EXPAND vars unless the 
user config
@@ -1725,9 +1726,13 @@ class config(object):
x in self.get('USE_EXPAND', '').split())
lazy_use_expand = self._lazy_use_expand(
self, unfiltered_use, use, self.usemask,
-   portage_iuse, use_expand_split, self._use_expand_dict)
+   portage_iuse, use_expand_split, self._use_expand_dict,
+   eapi_attrs.exports_USE_EXPAND_variables)
 
use_expand_iuses = {}
+   if eapi_attrs.exports_USE_EXPAND_variables:
+   for k in use_expand_split:
+   use_expand_iuses[k] = set()
for x in portage_iuse:
x_split = x.split('_')
if len(x_split) == 1:
-- 
2.8.2




Re: [gentoo-portage-dev] [PATCH] ebuild: Extend helper-in-global-scope ban to all EAPIs

2016-05-20 Thread Michał Górny
On Thu,  5 May 2016 23:10:43 +0200
Michał Górny  wrote:

> Make helper calls in global scope fatal in all supported EAPIs since
> this is the behavior required by PMS and all major offenders are fixed
> already.
> ---
>  bin/eapi.sh   |  4 
>  bin/ebuild.sh | 30 ++
>  2 files changed, 6 insertions(+), 28 deletions(-)

Merged now.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpfu5F4jC_jU.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH 2/2] ebuild.config: Fix filtering all USE_EXPAND variables in EAPI 5+

2016-05-20 Thread Michał Górny
On Sat, 21 May 2016 00:26:40 +0200
Michał Górny  wrote:

> Ensure that all USE_EXPAND variables are properly filtered and exported
> in EAPI 5 and newer, as required by the PMS. This includes exporting
> an empty value if no matching flag is provided in IUSE.
> 
> Bug: https://bugs.gentoo.org/show_bug.cgi?id=582140
> ---
>  pym/portage/eapi.py  |  6 +-
>  pym/portage/package/ebuild/config.py | 11 ---
>  2 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/pym/portage/eapi.py b/pym/portage/eapi.py
> index 1709026..c4fb374 100644
> --- a/pym/portage/eapi.py
> +++ b/pym/portage/eapi.py
> @@ -50,6 +50,9 @@ def eapi_exports_EBUILD_PHASE_FUNC(eapi):
>  def eapi_exports_REPOSITORY(eapi):
>   return eapi in ("4-python", "5-progress")
>  
> +def eapi_exports_USE_EXPAND_variables(eapi):
> + return eapi not in ("0", "1", "2", "3", "4", "4-python", "4-slot-abi")
> +
>  def eapi_has_pkg_pretend(eapi):
>   return eapi not in ("0", "1", "2", "3")
>  
> @@ -101,7 +104,7 @@ def eapi_has_targetroot(eapi):
>  
>  _eapi_attrs = collections.namedtuple('_eapi_attrs',
>   'dots_in_PN dots_in_use_flags exports_EBUILD_PHASE_FUNC '
> - 'feature_flag_test feature_flag_targetroot '
> + 'exports_USE_EXPAND_variables feature_flag_test feature_flag_targetroot 
> '
>   'hdepend iuse_defaults iuse_effective posixish_locale '
>   'repo_deps required_use required_use_at_most_one_of slot_operator 
> slot_deps '
>   'src_uri_arrows strong_blocks use_deps use_dep_defaults')
> @@ -128,6 +131,7 @@ def _get_eapi_attrs(eapi):
>   dots_in_PN = (eapi is None or eapi_allows_dots_in_PN(eapi)),
>   dots_in_use_flags = (eapi is None or 
> eapi_allows_dots_in_use_flags(eapi)),
>   exports_EBUILD_PHASE_FUNC = (eapi is None or 
> eapi_exports_EBUILD_PHASE_FUNC(eapi)),
> + exports_USE_EXPAND_variables = (eapi is None or 
> eapi_exports_USE_EXPAND_variables(eapi)),
>   feature_flag_test = True,
>   feature_flag_targetroot = (eapi is not None and 
> eapi_has_targetroot(eapi)),
>   hdepend = (eapi is not None and eapi_has_hdepend(eapi)),
> diff --git a/pym/portage/package/ebuild/config.py 
> b/pym/portage/package/ebuild/config.py
> index 5f19996..ee1fadb 100644
> --- a/pym/portage/package/ebuild/config.py
> +++ b/pym/portage/package/ebuild/config.py
> @@ -1279,7 +1279,7 @@ class config(object):
>  
>   def __init__(self, settings, unfiltered_use,
>   use, usemask, iuse_effective,
> - use_expand_split, use_expand_dict):
> + use_expand_split, use_expand_dict, 
> eapi_exports_USE_EXPAND_variables):
>   self._settings = settings
>   self._unfiltered_use = unfiltered_use
>   self._use = use
> @@ -1287,6 +1287,7 @@ class config(object):
>   self._iuse_effective = iuse_effective
>   self._use_expand_split = use_expand_split
>   self._use_expand_dict = use_expand_dict
> + self._eapi_exports_USE_EXPAND_variables = 
> eapi_exports_USE_EXPAND_variables
>  
>   def __getitem__(self, key):
>   prefix = key.lower() + '_'
> @@ -1330,7 +1331,7 @@ class config(object):
>   filtered_var_split.append(x)
>   var_split = filtered_var_split
>  
> - if var_split:
> + if var_split or self._eapi_exports_USE_EXPAND_variables:
>   value = ' '.join(var_split)
>   else:
>   # Don't export empty USE_EXPAND vars unless the 
> user config
> @@ -1725,9 +1726,13 @@ class config(object):
>   x in self.get('USE_EXPAND', '').split())
>   lazy_use_expand = self._lazy_use_expand(
>   self, unfiltered_use, use, self.usemask,
> - portage_iuse, use_expand_split, self._use_expand_dict)
> + portage_iuse, use_expand_split, self._use_expand_dict,
> + eapi_attrs.exports_USE_EXPAND_variables)
>  
>   use_expand_iuses = {}
> +     if eapi_attrs.exports_USE_EXPAND_variables:
> + for k in use_expand_split:
> + use_expand_iuses[k] = set()
>   for x in portage_iuse:
>   x_split = x.split('_')
>   if len(x_split) == 1:

After some thinking, I'll prepare another patch that applies the change
to all EAPIs. The behavior for earlier EAPIs is implementation-defined
by PMS and having it inconsistent will only confuse users.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpwxUpygWeHZ.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH v2 1/2] portage.package.ebuild.config: Rename iuse_implicit -> iuse_effective

2016-05-21 Thread Michał Górny
Rename the iuse_implicit variable used in USE_EXPAND handling to
iuse_effective, since that is what is actually passed there. Correct
naming makes figuring out what the function does much easier.
---
 pym/portage/package/ebuild/config.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 45b7d08..5f19996 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -1278,13 +1278,13 @@ class config(object):
"""
 
def __init__(self, settings, unfiltered_use,
-   use, usemask, iuse_implicit,
+   use, usemask, iuse_effective,
use_expand_split, use_expand_dict):
self._settings = settings
self._unfiltered_use = unfiltered_use
self._use = use
self._usemask = usemask
-   self._iuse_implicit = iuse_implicit
+   self._iuse_effective = iuse_effective
self._use_expand_split = use_expand_split
self._use_expand_dict = use_expand_dict
 
@@ -1302,7 +1302,7 @@ class config(object):
if has_wildcard:
var_split = [ x for x in var_split if x != "*" ]
has_iuse = set()
-   for x in self._iuse_implicit:
+   for x in self._iuse_effective:
if x[:prefix_len] == prefix:
has_iuse.add(x[prefix_len:])
if has_wildcard:
-- 
2.8.2




[gentoo-portage-dev] [PATCH v2 2/2] portage.package.ebuild.config: Always export filtered USE_EXPAND vars

2016-05-21 Thread Michał Górny
Ensure that all USE_EXPAND variables are always exported with filtered
USE flags inside, even if none of those flags are declared in IUSE.
This is the behavior required for EAPI 5+ by the PMS.

Since the behavior for earlier EAPIs is left undefined and having
different behavior would be confusing to users, apply it in earlier
EAPIs as well.
---
 bin/ebuild.sh|  6 
 pym/portage/package/ebuild/config.py | 55 ++--
 2 files changed, 3 insertions(+), 58 deletions(-)

diff --git a/bin/ebuild.sh b/bin/ebuild.sh
index 5b3146d..edf885f 100755
--- a/bin/ebuild.sh
+++ b/bin/ebuild.sh
@@ -690,12 +690,6 @@ if ! has "$EBUILD_PHASE" clean cleanrm ; then
fi
 fi
 
-# unset USE_EXPAND variables that contain only the special "*" token
-for x in ${USE_EXPAND} ; do
-   [ "${!x}" == "*" ] && unset ${x}
-done
-unset x
-
 if has nostrip ${FEATURES} ${RESTRICT} || has strip ${RESTRICT}
 then
export DEBUGBUILD=1
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 5f19996..d92f5f6 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -1330,47 +1330,7 @@ class config(object):
filtered_var_split.append(x)
var_split = filtered_var_split
 
-   if var_split:
-   value = ' '.join(var_split)
-   else:
-   # Don't export empty USE_EXPAND vars unless the 
user config
-   # exports them as empty.  This is required for 
vars such as
-   # LINGUAS, where unset and empty have different 
meanings.
-   # The special '*' token is understood by 
ebuild.sh, which
-   # will unset the variable so that things like 
LINGUAS work
-   # properly (see bug #459350).
-   if has_wildcard:
-   value = '*'
-   else:
-   if has_iuse:
-   already_set = False
-   # Skip the first 'env' 
configdict, in order to
-   # avoid infinite recursion 
here, since that dict's
-   # __getitem__ calls the current 
__getitem__.
-   for d in 
self._settings.lookuplist[1:]:
-   if key in d:
-   already_set = 
True
-   break
-
-   if not already_set:
-   for x in 
self._unfiltered_use:
-   if 
x[:prefix_len] == prefix:
-   
already_set = True
-   break
-
-   if already_set:
-   value = ''
-   else:
-   value = '*'
-   else:
-   # It's not in IUSE, so just 
allow the variable content
-   # to pass through if it is 
defined somewhere.  This
-   # allows packages that support 
LINGUAS but don't
-   # declare it in IUSE to use the 
variable outside of the
-   # USE_EXPAND context.
-   value = None
-
-   return value
+   return ' '.join(var_split)
 
def setcpv(self, mycpv, use_cache=None, mydb=None):
"""
@@ -1727,7 +1687,7 @@ class config(object):
self, unfiltered_use, use, self.usemask,
portage_iuse, use_expand_split, self._use_expand_dict)
 
-   use_expand_iuses = {}
+   use_expand_iuses = dict((k, set()) for k in use_expand_split)
for x in portage_iuse:
x_split = x.split('_')
if len(x_split) == 1:
@@ -1735,18 +1695,9 @@ class config(object):
for i in range(len(x_split) - 1):
k = '_'.join(x_split[:i+1])
if k in use_expand_split:
-

[gentoo-portage-dev] [PATCH 3/3] portage.dbapi.vartree: Support exclusions in INSTALL_MASK

2016-05-21 Thread Michał Górny
Allow INSTALL_MASK patterns to start with '-' to indicate that
a specific match is to be excluded from being masked. In this case,
the last matching pattern determines whether the file is actually
filtered out or kept.
---
 pym/portage/dbapi/vartree.py | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 8e5ac43..d02d850 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -3690,19 +3690,21 @@ class dblink(object):
def _is_install_masked(self, relative_path):
ret = False
for pattern in self.settings.install_mask:
+   # if pattern starts with -, possibly exclude this path
+   pat_res = not pattern.startswith('-')
+   if not pat_res:
+   pattern = pattern[1:]
# absolute path pattern
if pattern.startswith('/'):
# match either exact path or one of parent dirs
# the latter is done via matching pattern/*
if (fnmatch.fnmatch(relative_path, pattern[1:])
or 
fnmatch.fnmatch(relative_path, pattern[1:] + '/*')):
-   ret = True
-   break
+   ret = pat_res
# filename
else:
if 
fnmatch.fnmatch(os.path.basename(relative_path), pattern):
-   ret = True
-   break
+   ret = pat_res
return ret
 
def treewalk(self, srcroot, destroot, inforoot, myebuild, cleanup=0,
-- 
2.8.3




[gentoo-portage-dev] [PATCH 2/3] Move INSTALL_MASK handling into merging

2016-05-21 Thread Michał Górny
Introduce a new logic for INSTALL_MASK handling in merging code,
replacing the old code that removed matching files and directories
from imagedir in bash. The new code actually ignores matching files
on-the-fly while testing for file collisions and merging files.
The files are still written to CONTENTS, and output using "###" zing
to indicate being masked, yet are not actually merged to the filesystem.
---
 bin/misc-functions.sh|  17 --
 pym/portage/dbapi/vartree.py | 102 ++-
 pym/portage/package/ebuild/config.py |   2 +-
 3 files changed, 65 insertions(+), 56 deletions(-)

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index b42e1d6..4086981 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -300,23 +300,6 @@ install_mask() {
set -${shopts}
 }
 
-preinst_mask() {
-   if [ -z "${D}" ]; then
-eerror "${FUNCNAME}: D is unset"
-return 1
-   fi
-
-   if ! ___eapi_has_prefix_variables; then
-   local ED=${D}
-   fi
-
-   # Make sure $PWD is not ${D} so that we don't leave gmon.out files
-   # in there in case any tools were built with -pg in CFLAGS.
-   cd "${T}"
-
-   install_mask "${ED}" "${INSTALL_MASK}"
-}
-
 preinst_sfperms() {
if [ -z "${D}" ]; then
 eerror "${FUNCNAME}: D is unset"
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 6209a86..8e5ac43 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -2490,7 +2490,7 @@ class dblink(object):

(statobj.st_dev, statobj.st_ino),

[]).append(relative_path)
 
-   if is_owned:
+   if is_owned and not 
self._is_install_masked(relative_path[1:]):
show_unmerge("---", 
unmerge_desc["replaced"], file_type, obj)
continue
elif relative_path in cfgfiledict:
@@ -3687,6 +3687,24 @@ class dblink(object):
def _emerge_log(self, msg):
emergelog(False, msg)
 
+   def _is_install_masked(self, relative_path):
+   ret = False
+   for pattern in self.settings.install_mask:
+   # absolute path pattern
+   if pattern.startswith('/'):
+   # match either exact path or one of parent dirs
+   # the latter is done via matching pattern/*
+   if (fnmatch.fnmatch(relative_path, pattern[1:])
+   or 
fnmatch.fnmatch(relative_path, pattern[1:] + '/*')):
+   ret = True
+   break
+   # filename
+   else:
+   if 
fnmatch.fnmatch(os.path.basename(relative_path), pattern):
+   ret = True
+   break
+   return ret
+
def treewalk(self, srcroot, destroot, inforoot, myebuild, cleanup=0,
mydbapi=None, prev_mtimes=None, counter=None):
"""
@@ -3846,16 +3864,6 @@ class dblink(object):
max_dblnk = dblnk
self._installed_instance = max_dblnk
 
-   # Apply INSTALL_MASK before collision-protect, since it may
-   # be useful to avoid collisions in some scenarios.
-   # We cannot detect if this is needed or not here as 
INSTALL_MASK can be
-   # modified by bashrc files.
-   phase = MiscFunctionsProcess(background=False,
-   commands=["preinst_mask"], phase="preinst",
-   scheduler=self._scheduler, settings=self.settings)
-   phase.start()
-   phase.wait()
-
# We check for unicode encoding issues after src_install. 
However,
# the check must be repeated here for binary packages (it's
# inexpensive since we call os.walk() here anyway).
@@ -3927,6 +3935,10 @@ class dblink(object):
 
relative_path = fpath[srcroot_len:]
 
+   # filter on INSTALL_MASK
+   if 
self._is_install_masked(relative_path):
+   continue
+
if line_ending_re.search(relative_path) 
is not None:

paths_with_newlines.append(relative_path)
 
@@ -4642,6 +4654,7 @@ class dblink(object):
while mergelist:
 
  

[gentoo-portage-dev] [PATCH 1/3] portage.package.ebuild.config: Move FEATURES=no* handling there

2016-05-21 Thread Michał Górny
Move the code responsible for adding additional paths to INSTALL_MASK
into portage.package.ebuild.config.
---
 bin/misc-functions.sh| 13 -
 pym/portage/package/ebuild/config.py | 10 ++
 2 files changed, 10 insertions(+), 13 deletions(-)

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index 58755a1..b42e1d6 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -314,20 +314,7 @@ preinst_mask() {
# in there in case any tools were built with -pg in CFLAGS.
cd "${T}"
 
-   # remove man pages, info pages, docs if requested
-   local f
-   for f in man info doc; do
-   if has no${f} $FEATURES; then
-   INSTALL_MASK="${INSTALL_MASK} /usr/share/${f}"
-   fi
-   done
-
install_mask "${ED}" "${INSTALL_MASK}"
-
-   # remove share dir if unnessesary
-   if has nodoc $FEATURES || has noman $FEATURES || has noinfo $FEATURES; 
then
-   rmdir "${ED}usr/share" &> /dev/null
-   fi
 }
 
 preinst_sfperms() {
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 45b7d08..fcc7ce5 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -1773,6 +1773,16 @@ class config(object):
# setcpv triggers lazy instantiation of things like 
_use_manager.
_eapi_cache.clear()
 
+   # Prepare the final value of INSTALL_MASK
+   install_mask = self["INSTALL_MASK"].split()
+   if 'nodoc' in self.features:
+   install_mask.append("/usr/share/doc")
+   if 'noinfo' in self.features:
+   install_mask.append("/usr/share/info")
+   if 'noman' in self.features:
+   install_mask.append("/usr/share/man")
+   self["INSTALL_MASK"] = ' '.join(install_mask)
+
def _grab_pkg_env(self, penv, container, protected_keys=None):
if protected_keys is None:
protected_keys = ()
-- 
2.8.3




[gentoo-portage-dev] [PATCH 0/3] INSTALL_MASK redesign, part I

2016-05-21 Thread Michał Górny
Hello, everyone.

As part of new GLEP effort, I'm working on improving INSTALL_MASK
support in Portage to make it cleaner and more featureful. Here's
the first set of commits resulting from this.

The previous implementation of INSTALL_MASK was done purely in bash.
Long story short, Portage removed all files matching one of INSTALL_MASK
patterns from the installation image.

My implementation is done purely as a filter in Python. The ebuild
configuration bits now generate final list of INSTALL_MASK. It is
afterwards used in vartree bits to filter files while checking for
collisions, merging and unmerging appropriately.

The major differences/improvements are:

* The files are actually left in image directory. Not that it makes any
  real difference but it is a bit cleaner and more like real mask this
  way.

* The pre-install "removing" output has been replaced by listing files
  with "###" zing in merging output (which means "not installed due
  to INSTALL_MASK").

* All masked files are now listed in vdb CONTENTS. Therefore, tools
  like app-portage/install-mask can now figure out to which packages
  masks were applied and rebuild them on mask changes appropriately.

* Mask exclusions are supported now. Which means you can do e.g.:
  INSTALL_MASK="/usr/share/locale -/usr/share/locale/foo".

* The code is now whitespace-safe. While patterns specified
  in INSTALL_MASK directly still can not contain spaces, pattern groups
  will be able to use them.

In a few days, I'll try to provide a part II that would implement
the actual mask groups. However, I may need some help adding support
for the configuration files.

I'm not touching PKG_INSTALL_MASK for now since it's harder and outside
of the scope of what I'm trying to achieve.



Michał Górny (3):
  portage.package.ebuild.config: Move FEATURES=no* handling there
  Move INSTALL_MASK handling into merging
  portage.dbapi.vartree: Support exclusions in INSTALL_MASK

 bin/misc-functions.sh|  30 --
 pym/portage/dbapi/vartree.py | 104 ++-
 pym/portage/package/ebuild/config.py |  10 
 3 files changed, 76 insertions(+), 68 deletions(-)

-- 
2.8.3




Re: [gentoo-portage-dev] [PATCH 2/3] Move INSTALL_MASK handling into merging

2016-05-22 Thread Michał Górny
On Sun, 22 May 2016 08:56:03 +0200
Michał Górny  wrote:

> Introduce a new logic for INSTALL_MASK handling in merging code,
> replacing the old code that removed matching files and directories
> from imagedir in bash. The new code actually ignores matching files
> on-the-fly while testing for file collisions and merging files.
> The files are still written to CONTENTS, and output using "###" zing
> to indicate being masked, yet are not actually merged to the filesystem.
> ---
>  bin/misc-functions.sh|  17 --
>  pym/portage/dbapi/vartree.py | 102 
> ++-
>  pym/portage/package/ebuild/config.py |   2 +-
>  3 files changed, 65 insertions(+), 56 deletions(-)

This actually fails when INSTALL_MASK is not defined. I will be sending
another patch shortly.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpD5HZwPJTkM.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH v2] Move INSTALL_MASK handling into merging

2016-05-22 Thread Michał Górny
Introduce a new logic for INSTALL_MASK handling in merging code,
replacing the old code that removed matching files and directories
from imagedir in bash. The new code actually ignores matching files
on-the-fly while testing for file collisions and merging files.
The files are still written to CONTENTS, and output using "###" zing
to indicate being masked, yet are not actually merged to the filesystem.
---
 bin/misc-functions.sh|  17 --
 pym/portage/dbapi/vartree.py | 102 ++-
 pym/portage/package/ebuild/config.py |   4 +-
 3 files changed, 66 insertions(+), 57 deletions(-)

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index b42e1d6..4086981 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -300,23 +300,6 @@ install_mask() {
set -${shopts}
 }
 
-preinst_mask() {
-   if [ -z "${D}" ]; then
-eerror "${FUNCNAME}: D is unset"
-return 1
-   fi
-
-   if ! ___eapi_has_prefix_variables; then
-   local ED=${D}
-   fi
-
-   # Make sure $PWD is not ${D} so that we don't leave gmon.out files
-   # in there in case any tools were built with -pg in CFLAGS.
-   cd "${T}"
-
-   install_mask "${ED}" "${INSTALL_MASK}"
-}
-
 preinst_sfperms() {
if [ -z "${D}" ]; then
 eerror "${FUNCNAME}: D is unset"
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 6209a86..8e5ac43 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -2490,7 +2490,7 @@ class dblink(object):

(statobj.st_dev, statobj.st_ino),

[]).append(relative_path)
 
-   if is_owned:
+   if is_owned and not 
self._is_install_masked(relative_path[1:]):
show_unmerge("---", 
unmerge_desc["replaced"], file_type, obj)
continue
elif relative_path in cfgfiledict:
@@ -3687,6 +3687,24 @@ class dblink(object):
def _emerge_log(self, msg):
emergelog(False, msg)
 
+   def _is_install_masked(self, relative_path):
+   ret = False
+   for pattern in self.settings.install_mask:
+   # absolute path pattern
+   if pattern.startswith('/'):
+   # match either exact path or one of parent dirs
+   # the latter is done via matching pattern/*
+   if (fnmatch.fnmatch(relative_path, pattern[1:])
+   or 
fnmatch.fnmatch(relative_path, pattern[1:] + '/*')):
+   ret = True
+   break
+   # filename
+   else:
+   if 
fnmatch.fnmatch(os.path.basename(relative_path), pattern):
+   ret = True
+   break
+   return ret
+
def treewalk(self, srcroot, destroot, inforoot, myebuild, cleanup=0,
mydbapi=None, prev_mtimes=None, counter=None):
"""
@@ -3846,16 +3864,6 @@ class dblink(object):
max_dblnk = dblnk
self._installed_instance = max_dblnk
 
-   # Apply INSTALL_MASK before collision-protect, since it may
-   # be useful to avoid collisions in some scenarios.
-   # We cannot detect if this is needed or not here as 
INSTALL_MASK can be
-   # modified by bashrc files.
-   phase = MiscFunctionsProcess(background=False,
-   commands=["preinst_mask"], phase="preinst",
-   scheduler=self._scheduler, settings=self.settings)
-   phase.start()
-   phase.wait()
-
# We check for unicode encoding issues after src_install. 
However,
# the check must be repeated here for binary packages (it's
# inexpensive since we call os.walk() here anyway).
@@ -3927,6 +3935,10 @@ class dblink(object):
 
relative_path = fpath[srcroot_len:]
 
+   # filter on INSTALL_MASK
+   if 
self._is_install_masked(relative_path):
+   continue
+
if line_ending_re.search(relative_path) 
is not None:

paths_with_newlines.append(relative_path)
 
@@ -4642,6 +4654,7 @@ class dblink(object):
while mergelist:
 
  

[gentoo-portage-dev] [PATCH 1/2] portage.util.configparser: Provide common code to handle cp imports

2016-05-22 Thread Michał Górny
Provide a common code unit to handle portable *ConfigParser imports
for all supported Python versions.
---
 pym/portage/_sets/__init__.py  | 10 ++
 pym/portage/repository/config.py   |  9 +
 pym/portage/util/_desktop_entry.py |  7 ++-
 pym/portage/util/configparser.py   | 22 ++
 4 files changed, 27 insertions(+), 21 deletions(-)
 create mode 100644 pym/portage/util/configparser.py

diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py
index 3203521..ec42f7c 100644
--- a/pym/portage/_sets/__init__.py
+++ b/pym/portage/_sets/__init__.py
@@ -9,14 +9,6 @@ __all__ = ["SETPREFIX", "get_boolean", "SetConfigError",
 import io
 import logging
 import sys
-try:
-   from configparser import NoOptionError, ParsingError
-   if sys.hexversion >= 0x302:
-   from configparser import ConfigParser as SafeConfigParser
-   else:
-   from configparser import SafeConfigParser
-except ImportError:
-   from ConfigParser import SafeConfigParser, NoOptionError, ParsingError
 import portage
 from portage import os
 from portage import load_mod
@@ -29,6 +21,8 @@ from portage.const import _ENABLE_SET_CONFIG
 from portage.exception import PackageSetNotFound
 from portage.localization import _
 from portage.util import writemsg_level
+from portage.util.configparser import (SafeConfigParser,
+   NoOptionError, ParsingError)
 
 SETPREFIX = "@"
 
diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py
index 00319fe..9039886 100644
--- a/pym/portage/repository/config.py
+++ b/pym/portage/repository/config.py
@@ -9,14 +9,6 @@ import warnings
 import sys
 import re
 
-try:
-   from configparser import Error as ConfigParserError
-   if sys.hexversion >= 0x302:
-   from configparser import ConfigParser as SafeConfigParser
-   else:
-   from configparser import SafeConfigParser
-except ImportError:
-   from ConfigParser import SafeConfigParser, Error as ConfigParserError
 import portage
 from portage import eclass_cache, os
 from portage.const import (MANIFEST2_HASH_FUNCTIONS, MANIFEST2_REQUIRED_HASH,
@@ -25,6 +17,7 @@ from portage.eapi import 
eapi_allows_directories_on_profile_level_and_repository
 from portage.env.loaders import KeyValuePairFileLoader
 from portage.util import (normalize_path, read_corresponding_eapi_file, 
shlex_split,
stack_lists, writemsg, writemsg_level, _recursive_file_list)
+from portage.util.configparser import SafeConfigParser, ConfigParserError
 from portage.util._path import isdir_raise_eaccess
 from portage.util.path import first_existing
 from portage.localization import _
diff --git a/pym/portage/util/_desktop_entry.py 
b/pym/portage/util/_desktop_entry.py
index 0b49547..95a015e 100644
--- a/pym/portage/util/_desktop_entry.py
+++ b/pym/portage/util/_desktop_entry.py
@@ -6,14 +6,11 @@ import re
 import subprocess
 import sys
 
-try:
-   from configparser import Error as ConfigParserError, RawConfigParser
-except ImportError:
-   from ConfigParser import Error as ConfigParserError, RawConfigParser
-
 import portage
 from portage import _encodings, _unicode_encode, _unicode_decode
 from portage.util import writemsg
+from portage.util.configparser import ConfigParserError, RawConfigParser
+
 
 def parse_desktop_entry(path):
"""
diff --git a/pym/portage/util/configparser.py b/pym/portage/util/configparser.py
new file mode 100644
index 000..d305052
--- /dev/null
+++ b/pym/portage/util/configparser.py
@@ -0,0 +1,22 @@
+# Copyright 2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = ['ConfigParserError', 'NoOptionError', 'ParsingError',
+   'RawConfigParser', 'SafeConfigParser']
+
+# the following scary compatibility thing provides two classes:
+# - SafeConfigParser that provides safe interpolation for values,
+# - RawConfigParser that provides no interpolation for values.
+
+import sys
+
+try:
+   from configparser import (Error as ConfigParserError,
+   NoOptionError, ParsingError, RawConfigParser)
+   if sys.hexversion >= 0x302:
+   from configparser import ConfigParser as SafeConfigParser
+   else:
+   from configparser import SafeConfigParser
+except ImportError:
+   from ConfigParser import (Error as ConfigParserError,
+   NoOptionError, ParsingError, RawConfigParser, SafeConfigParser)
-- 
2.8.3




[gentoo-portage-dev] [PATCH 2/2] portage.util.configparser: Commonize portable config file reading routine

2016-05-22 Thread Michał Górny
---
 pym/portage/_sets/__init__.py  | 29 ++-
 pym/portage/repository/config.py   | 38 ++---
 pym/portage/util/_desktop_entry.py | 20 ++---
 pym/portage/util/configparser.py   | 57 +-
 4 files changed, 64 insertions(+), 80 deletions(-)

diff --git a/pym/portage/_sets/__init__.py b/pym/portage/_sets/__init__.py
index ec42f7c..6d69bda 100644
--- a/pym/portage/_sets/__init__.py
+++ b/pym/portage/_sets/__init__.py
@@ -22,7 +22,7 @@ from portage.exception import PackageSetNotFound
 from portage.localization import _
 from portage.util import writemsg_level
 from portage.util.configparser import (SafeConfigParser,
-   NoOptionError, ParsingError)
+   NoOptionError, ParsingError, read_configs)
 
 SETPREFIX = "@"
 
@@ -50,32 +50,7 @@ class SetConfig(object):
})
 
if _ENABLE_SET_CONFIG:
-   # use read_file/readfp in order to control decoding of 
unicode
-   try:
-   # Python >=3.2
-   read_file = self._parser.read_file
-   except AttributeError:
-   read_file = self._parser.readfp
-
-   for p in paths:
-   f = None
-   try:
-   f = io.open(_unicode_encode(p,
-   encoding=_encodings['fs'], 
errors='strict'),
-   mode='r', 
encoding=_encodings['repo.content'],
-   errors='replace')
-   except EnvironmentError:
-   pass
-   else:
-   try:
-   read_file(f)
-   except ParsingError as e:
-   writemsg_level(_unicode_decode(
-   _("!!! Error while 
reading sets config file: %s\n")
-   ) % e, 
level=logging.ERROR, noiselevel=-1)
-   finally:
-   if f is not None:
-   f.close()
+   read_configs(self._parser, paths)
else:
self._create_default_config()
 
diff --git a/pym/portage/repository/config.py b/pym/portage/repository/config.py
index 9039886..a23f4bd 100644
--- a/pym/portage/repository/config.py
+++ b/pym/portage/repository/config.py
@@ -17,7 +17,8 @@ from portage.eapi import 
eapi_allows_directories_on_profile_level_and_repository
 from portage.env.loaders import KeyValuePairFileLoader
 from portage.util import (normalize_path, read_corresponding_eapi_file, 
shlex_split,
stack_lists, writemsg, writemsg_level, _recursive_file_list)
-from portage.util.configparser import SafeConfigParser, ConfigParserError
+from portage.util.configparser import (SafeConfigParser, ConfigParserError,
+   read_configs)
 from portage.util._path import isdir_raise_eaccess
 from portage.util.path import first_existing
 from portage.localization import _
@@ -542,15 +543,6 @@ class RepoConfigLoader(object):
"""Parse files in paths to load config"""
parser = SafeConfigParser(defaults=default_opts)
 
-   # use read_file/readfp in order to control decoding of unicode
-   try:
-   # Python >=3.2
-   read_file = parser.read_file
-   source_kwarg = 'source'
-   except AttributeError:
-   read_file = parser.readfp
-   source_kwarg = 'filename'
-
recursive_paths = []
for p in paths:
if isinstance(p, basestring):
@@ -558,31 +550,7 @@ class RepoConfigLoader(object):
else:
recursive_paths.append(p)
 
-   for p in recursive_paths:
-   if isinstance(p, basestring):
-   f = None
-   try:
-   f = io.open(_unicode_encode(p,
-   encoding=_encodings['fs'], 
errors='strict'),
-   mode='r', 
encoding=_encodings['repo.content'],
-   errors='replace')
-   except EnvironmentError:
-   pass
-   else:
-   # The 'source' keyword argument is 
needed since otherwise
- 

Re: [gentoo-portage-dev] [PATCH 2/2] pym/portage/util/locale.py: add a C module to help check locale

2016-05-22 Thread Michał Górny
pers = {}
> +x_c_helpers = {
> + 'portage_c_convert_case' : [
> + 'src/portage_c_convert_case.c',
> + ],
> +}
>  
>  class x_build(build):
>   """ Build command with extra build_man call. """
> diff --git a/src/portage_c_convert_case.c b/src/portage_c_convert_case.c
> new file mode 100644
> index 000..f60b0c2
> --- /dev/null
> +++ b/src/portage_c_convert_case.c
> @@ -0,0 +1,94 @@
> +/* Copyright 2005-2016 Gentoo Foundation
> + * Distributed under the terms of the GNU General Public License v2
> + */
> +
> +#include 
> +#include 
> +
> +static PyObject * portage_c_tolower(PyObject *, PyObject *);
> +static PyObject * portage_c_toupper(PyObject *, PyObject *);
> +
> +static PyMethodDef ConvertCaseMethods[] = {
> + {"_c_tolower", portage_c_tolower, METH_VARARGS, "Convert to lower case 
> using system locale."},
> + {"_c_toupper", portage_c_toupper, METH_VARARGS, "Convert to upper case 
> using system locale."},
> + {NULL, NULL, 0, NULL}

You should include stdlib.h or stdio.h for NULL.

> +};
> +
> +#if PY_MAJOR_VERSION >= 3
> +static struct PyModuleDef moduledef = {
> + PyModuleDef_HEAD_INIT,
> + "portage_c_convert_case",   /* 
> m_name */
> + "Module for converting case using the system locale",   /* 
> m_doc */
> + -1, /* 
> m_size */
> + ConvertCaseMethods, /* 
> m_methods */
> + NULL,   /* 
> m_reload */
> + NULL,   /* 
> m_traverse */
> + NULL,   /* 
> m_clear */
> + NULL,   /* 
> m_free */
> +};
> +#endif
> +
> +static PyObject *ConvertCaseError;
> +
> +PyMODINIT_FUNC
> +#if PY_MAJOR_VERSION >= 3
> +PyInit_portage_c_convert_case(void)
> +#else
> +initportage_c_convert_case(void)
> +#endif
> +{
> + PyObject *m;
> +
> +#if PY_MAJOR_VERSION >= 3
> + m = PyModule_Create(&moduledef);
> +#else
> + m = Py_InitModule("portage_c_convert_case", ConvertCaseMethods);
> +#endif
> +
> + if (m == NULL)
> +#if PY_MAJOR_VERSION >= 3
> + return NULL;
> +#else
> + return;
> +#endif
> +
> + ConvertCaseError = 
> PyErr_NewException("portage_c_convert_case.ConvertCaseError", NULL, NULL);
> + Py_INCREF(ConvertCaseError);
> + PyModule_AddObject(m, "ConvertCaseError", ConvertCaseError);
> +
> +#if PY_MAJOR_VERSION >= 3
> + return m;
> +#else
> + return;
> +#endif
> +}

To be honest, I think we'd be happier having two big #ifdefs for init
funcs rather than one function with a lot of #ifdefs, and the common
ConvertCaseError part in a separate static function.

> +
> +
> +static PyObject *
> +portage_c_tolower(PyObject *self, PyObject *args)
> +{
> + int c;
> +
> + if (!PyArg_ParseTuple(args, "i", &c))
> + {
> + PyErr_SetString(ConvertCaseError, "_c_tolower: PyArg_ParseTuple 
> failed");

From PyArg_ParseTuple() [1]:

| on failure, it returns false and raises the appropriate exception.

So I don't think you need or should use a custom exception here.

[1]:https://docs.python.org/2/c-api/arg.html#c.PyArg_ParseTuple

> + return NULL;
> + }
> +
> + return Py_BuildValue("i", tolower(c));
> +}
> +
> +
> +static PyObject *
> +portage_c_toupper(PyObject *self, PyObject *args)
> +{
> + int c;
> +
> + if (!PyArg_ParseTuple(args, "i", &c))
> + {
> + PyErr_SetString(ConvertCaseError, "_c_toupper: PyArg_ParseTuple 
> failed");
> + return NULL;
> + }
> +
> + return Py_BuildValue("i", toupper(c));
> +}

Thanks a lot for your effort. This is really getting in shape.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgp9y04POWsEG.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH 2/2] pym/portage/util/locale.py: add a C module to help check locale

2016-05-23 Thread Michał Górny
On Mon, 23 May 2016 08:08:18 -0400
"Anthony G. Basile"  wrote:

> On 5/23/16 2:44 AM, Michał Górny wrote:
> > On Sun, 22 May 2016 13:04:40 -0400
> > "Anthony G. Basile"  wrote:
> >   
> >> From: "Anthony G. Basile" 
> >>
> >> The current method to check for a sane system locale is to use python's
> >> ctypes.util.find_library() to construct a full library path to the
> >> system libc.so and pass that path to ctypes.CDLL() so we can call
> >> toupper() and tolower() directly.  However, this gets bogged down in
> >> implementation details and fails with musl.
> >>
> >> We work around this design flaw in ctypes with a small python module
> >> written in C which provides thin wrappers to toupper() and tolower(),
> >> and only fall back on the current ctypes-based check when this module
> >> is not available.
> >>
> >> This has been tested on glibc, uClibc and musl systems.
> >>
> >> X-Gentoo-bug: 571444
> >> X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=571444
> >>
> >> Signed-off-by: Anthony G. Basile 
> >> ---
> >>  pym/portage/util/locale.py   | 32 ++-
> >>  setup.py |  6 ++-
> >>  src/portage_c_convert_case.c | 94 
> >> 
> >>  3 files changed, 121 insertions(+), 11 deletions(-)
> >>  create mode 100644 src/portage_c_convert_case.c
> >>
> >> diff --git a/pym/portage/util/locale.py b/pym/portage/util/locale.py
> >> index 2a15ea1..85ddd2b 100644
> >> --- a/pym/portage/util/locale.py
> >> +++ b/pym/portage/util/locale.py
> >> @@ -11,6 +11,7 @@ from __future__ import absolute_import, unicode_literals
> >>  import locale
> >>  import logging
> >>  import os
> >> +import sys
> >>  import textwrap
> >>  import traceback
> >>  
> >> @@ -34,18 +35,26 @@ def _check_locale(silent):
> >>"""
> >>The inner locale check function.
> >>"""
> >> -
> >> -  libc_fn = find_library("c")
> >> -  if libc_fn is None:
> >> -  return None
> >> -  libc = LoadLibrary(libc_fn)
> >> -  if libc is None:
> >> -  return None
> >> +  try:
> >> +  from portage_c_convert_case import _c_toupper, _c_tolower
> >> +  libc_tolower = _c_tolower
> >> +  libc_toupper = _c_toupper  
> > 
> > Now I'm being picky... but if you named the functions toupper()
> > and tolower(), you could actually import the whole module as 'libc'
> > and have less code!  
> 
> I see what you're saying, and its tempting because its elegant, but I'm
> afraid of a clash of names.  I've got a bad feeling this will get us
> into trouble later.
> 
> Let me play with this and see what happens.

I don't think this will be problematic since things like this happen
in Python all the time ;-). And after all, C function names can be
different than Python function names.

> > Also it would be nice to actually make the module more generic. There
> > are more places where we use CDLL, and all of them could eventually be
> > supported by the module (unshare() would be much better done in C, for
> > example).  
> 
> Yeah I get your point here.  Let me convince myself first.

I've got a killer argument: right now we hardcode constants from Linux
headers in the Python code!

Not that I'm asking you to actually add code for that as well. Just
rename the module to something more generic like portage.util.libc ;-).

> >> +  except ImportError:
> >> +  writemsg_level("!!! Unable to import 
> >> portage_c_convert_case\n!!!\n",
> >> +  level=logging.WARNING, noiselevel=-1)  
> > 
> > Do we really want to warn verbosely about this? I think it'd be
> > a pretty common case for people running the git checkout.  
> 
> This should stay.  Its good to know that the module is not being
> imported and silently falling back on the ctypes stuff.
> 
> 1) its only going to happen in the rare occasion that you're using
> something like a turkish locale and can't import the module.

Wrong. This happens before the check is done, so it will be output
every time Portage is started, also with good locale.

> 2) people who do a git checkout should add
> PYTHONPATH=build/lib.linux-x86_64-3.4 to their env to test the module.
> I can add something to testpath.  Users

Re: [gentoo-portage-dev] [PATCH 2/2] portage.util.configparser: Commonize portable config file reading routine

2016-05-23 Thread Michał Górny
On Sun, 22 May 2016 11:04:51 -0700
Zac Medico  wrote:

> On 05/22/2016 01:41 AM, Michał Górny wrote:
> > ---
> >  pym/portage/_sets/__init__.py  | 29 ++-
> >  pym/portage/repository/config.py   | 38 ++---
> >  pym/portage/util/_desktop_entry.py | 20 ++---
> >  pym/portage/util/configparser.py   | 57 
> > +-
> >  4 files changed, 64 insertions(+), 80 deletions(-)  
> 
> These patches look good. Note that the _native_kwargs function is not
> really needed anymore, because it was just a workaround for this issue
> which only affected python 2.6.4 and earlier:
> 
>http://bugs.python.org/issue4978

Pushed now, thanks.

I'll do a global _native_kwargs cleanup in a separate patch.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpXQJxBE7cZ3.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH] Remove unneeded native_kwargs wrapper

2016-05-24 Thread Michał Górny
Remove the native_kwargs wrapper and all uses of it. As pointed out by
Zac Medico, this was only needed for Python < 2.6.5, and we no longer
support those versions for quite some time.
---
 bin/portageq  |  2 +-
 pym/_emerge/MiscFunctionsProcess.py   |  3 +--
 pym/_emerge/actions.py|  2 +-
 pym/_emerge/depgraph.py   | 12 
 pym/_emerge/resolver/output.py|  3 +--
 pym/portage/__init__.py   |  9 -
 pym/portage/dbapi/porttree.py |  4 ++--
 pym/portage/dbapi/vartree.py  |  3 +--
 pym/portage/news.py   |  3 +--
 pym/portage/package/ebuild/doebuild.py|  6 +++---
 pym/portage/repository/config.py  |  2 +-
 pym/portage/sync/modules/cvs/cvs.py   |  4 ++--
 pym/portage/sync/modules/git/git.py   |  4 ++--
 pym/portage/sync/modules/rsync/rsync.py   |  4 ++--
 pym/portage/sync/modules/svn/svn.py   |  6 +++---
 pym/portage/sync/modules/webrsync/webrsync.py |  2 +-
 pym/portage/util/__init__.py  |  2 +-
 pym/portage/util/configparser.py  |  5 ++---
 repoman/pym/repoman/modules/scan/ebuild/checks.py |  2 +-
 19 files changed, 30 insertions(+), 48 deletions(-)

diff --git a/bin/portageq b/bin/portageq
index 832d004..d645635 100755
--- a/bin/portageq
+++ b/bin/portageq
@@ -1281,7 +1281,7 @@ def add_pquery_arguments(parser):
kwargs["help"] = opt_info["help"]
except KeyError:
pass
-   arg_group.add_argument(*pargs, 
**portage._native_kwargs(kwargs))
+   arg_group.add_argument(*pargs, **kwargs)
 
 
 def usage(argv):
diff --git a/pym/_emerge/MiscFunctionsProcess.py 
b/pym/_emerge/MiscFunctionsProcess.py
index b7f5892..99cf598 100644
--- a/pym/_emerge/MiscFunctionsProcess.py
+++ b/pym/_emerge/MiscFunctionsProcess.py
@@ -40,8 +40,7 @@ class MiscFunctionsProcess(AbstractEbuildProcess):
# think this is a real phase.
phase_backup = self.settings.pop("EBUILD_PHASE", None)
try:
-   return spawn(" ".join(args), self.settings,
-   **portage._native_kwargs(kwargs))
+   return spawn(" ".join(args), self.settings, **kwargs)
finally:
if phase_backup is not None:
self.settings["EBUILD_PHASE"] = phase_backup
diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
index 59626ad..2ca7902 100644
--- a/pym/_emerge/actions.py
+++ b/pym/_emerge/actions.py
@@ -2378,7 +2378,7 @@ def load_emerge_config(emerge_config=None, **kargs):
if v and v.strip():
kwargs[k] = v
emerge_config.trees = portage.create_trees(trees=emerge_config.trees,
-   **portage._native_kwargs(kwargs))
+   **kwargs)
 
for root_trees in emerge_config.trees.values():
settings = root_trees["vartree"].settings
diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index cfaafa3..f78f08d 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -4175,8 +4175,7 @@ class depgraph(object):
pargs, kwargs = item
kwargs = kwargs.copy()
kwargs['collect_use_changes'] = True
-   if not self._show_unsatisfied_dep(*pargs,
-   **portage._native_kwargs(kwargs)):
+   if not self._show_unsatisfied_dep(*pargs, 
**kwargs):
remaining_items.append(item)
if len(remaining_items) != 
len(self._dynamic_config._unsatisfied_deps_for_display):

self._dynamic_config._unsatisfied_deps_for_display = remaining_items
@@ -4327,8 +4326,7 @@ class depgraph(object):
not been scheduled for replacement.
"""
kwargs["trees"] = self._dynamic_config._graph_trees
-   return self._select_atoms_highest_available(*pargs,
-   **portage._native_kwargs(kwargs))
+   return self._select_atoms_highest_available(*pargs, **kwargs)
 
def _select_atoms_highest_available(self, root, depstring,
myuse=None, parent=None, strict=True, trees=None, 
priority=None):
@@ -8511,8 +8509,7 @@ class depgraph(object):
writemsg("\n", noiselevel=-1)
 
for pargs, kwargs in 
self._dynamic_config._unsatisfied_deps_for_display:
-   self._show_unsatisfied_dep(*pargs,
-   **portage._native

Re: [gentoo-portage-dev] [PATCH 3/3] pym/portage/util/locale.py: add a C module to help check locale

2016-05-28 Thread Michał Górny
> + PyObject *m;
> + m = PyModule_Create(&moduledef);
> + return m;
> +}
> +#else
> +initlibc(void)
> +{
> + Py_InitModule("libc", LibcMethods);
> +}
> +#endif
> +
> +
> +static PyObject *
> +_libc_tolower(PyObject *self, PyObject *args)
> +{
> + int c;
> +
> + if (!PyArg_ParseTuple(args, "i", &c))
> + return NULL;
> +
> + return Py_BuildValue("i", tolower(c));
> +}
> +
> +
> +static PyObject *
> +_libc_toupper(PyObject *self, PyObject *args)
> +{
> + int c;
> +
> + if (!PyArg_ParseTuple(args, "i", &c))
> + return NULL;
> +
> + return Py_BuildValue("i", toupper(c));
> +}

Aside from that, it look nice and shiny now. Thanks a lot!

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpMDaEA9fng0.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH 3/3] pym/portage/util/locale.py: add a C module to help check locale

2016-05-29 Thread Michał Górny
On Sun, 29 May 2016 02:37:50 -0400
"Anthony G. Basile"  wrote:

> On 5/29/16 2:30 AM, Michał Górny wrote:
> > On Fri, 27 May 2016 10:26:44 -0400
> > "Anthony G. Basile"  wrote:
> >   
> >> From: "Anthony G. Basile" 
> >>
> >> The current method to check for a sane system locale is to use python's
> >> ctypes.util.find_library() to construct a full library path to the
> >> system libc.so and pass that path to ctypes.CDLL() so we can call
> >> toupper() and tolower() directly.  However, this gets bogged down in
> >> implementation details and fails with musl.
> >>
> >> We work around this design flaw in ctypes with a small python module
> >> written in C which provides thin wrappers to toupper() and tolower(),
> >> and only fall back on the current ctypes-based check when this module
> >> is not available.
> >>
> >> This has been tested on glibc, uClibc and musl systems.
> >>
> >> X-Gentoo-bug: 571444
> >> X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=571444
> >>
> >> Signed-off-by: Anthony G. Basile 
> >> ---
> >>  pym/portage/util/locale.py | 16 ++-
> >>  setup.py   |  6 +++-
> >>  src/portage_util_libc.c| 70 
> >> ++
> >>  3 files changed, 84 insertions(+), 8 deletions(-)
> >>  create mode 100644 src/portage_util_libc.c
> >>
> >> diff --git a/pym/portage/util/locale.py b/pym/portage/util/locale.py
> >> index 093eb86..5b09945 100644
> >> --- a/pym/portage/util/locale.py
> >> +++ b/pym/portage/util/locale.py
> >> @@ -34,13 +34,15 @@ def _check_locale(silent):
> >>"""
> >>The inner locale check function.
> >>"""
> >> -
> >> -  libc_fn = find_library("c")
> >> -  if libc_fn is None:
> >> -  return None
> >> -  libc = LoadLibrary(libc_fn)
> >> -  if libc is None:
> >> -  return None
> >> +  try:
> >> +  from portage.util import libc
> >> +  except ImportError:
> >> +  libc_fn = find_library("c")
> >> +  if libc_fn is None:
> >> +  return None
> >> +  libc = LoadLibrary(libc_fn)
> >> +  if libc is None:
> >> +  return None
> >>  
> >>lc = list(range(ord('a'), ord('z')+1))
> >>uc = list(range(ord('A'), ord('Z')+1))
> >> diff --git a/setup.py b/setup.py
> >> index 25429bc..5ca8156 100755
> >> --- a/setup.py
> >> +++ b/setup.py
> >> @@ -47,7 +47,11 @@ x_scripts = {
> >>  # Dictionary custom modules written in C/C++ here.  The structure is
> >>  #   key   = module name
> >>  #   value = list of C/C++ source code, path relative to top source 
> >> directory
> >> -x_c_helpers = {}
> >> +x_c_helpers = {
> >> +  'portage.util.libc' : [
> >> +  'src/portage_util_libc.c',
> >> +  ],
> >> +}
> >>  
> >>  class x_build(build):
> >>""" Build command with extra build_man call. """
> >> diff --git a/src/portage_util_libc.c b/src/portage_util_libc.c
> >> new file mode 100644
> >> index 000..00b09c2
> >> --- /dev/null
> >> +++ b/src/portage_util_libc.c
> >> @@ -0,0 +1,70 @@
> >> +/* Copyright 2005-2016 Gentoo Foundation
> >> + * Distributed under the terms of the GNU General Public License v2
> >> + */
> >> +
> >> +#include 
> >> +#include 
> >> +#include 
> >> +
> >> +static PyObject * _libc_tolower(PyObject *, PyObject *);
> >> +static PyObject * _libc_toupper(PyObject *, PyObject *);
> >> +
> >> +static PyMethodDef LibcMethods[] = {
> >> +  {"tolower", _libc_tolower, METH_VARARGS, "Convert to lower case using 
> >> system locale."},
> >> +  {"toupper", _libc_toupper, METH_VARARGS, "Convert to upper case using 
> >> system locale."},
> >> +  {NULL, NULL, 0, NULL}
> >> +};
> >> +
> >> +#if PY_MAJOR_VERSION >= 3
> >> +static struct PyModuleDef moduledef = {
> >> +  PyModuleDef_HEAD_INIT,
> >> +  "libc", /* 
> >> m_name */
&

Re: [gentoo-portage-dev] [PATCH] Remove unneeded native_kwargs wrapper

2016-05-31 Thread Michał Górny
On Tue, 24 May 2016 11:08:44 +0200
Alexander Berntsen  wrote:

> -BEGIN PGP SIGNED MESSAGE-
> Hash: SHA512
> 
> Welp that took forever to read through... I didn't see anything wrong
> with it. So if tests pass and everything looks OK to you, go ahead and
> push it.

Merged now.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpWLd3EwKFeo.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH 4/3] portage.package.ebuild.config: Support path groups from install-mask.conf

2016-05-31 Thread Michał Górny
---
 .../package/ebuild/_config/InstallMaskManager.py   | 59 ++
 pym/portage/package/ebuild/config.py   | 34 -
 pym/portage/util/configparser.py   | 19 ++-
 3 files changed, 110 insertions(+), 2 deletions(-)
 create mode 100644 pym/portage/package/ebuild/_config/InstallMaskManager.py

diff --git a/pym/portage/package/ebuild/_config/InstallMaskManager.py 
b/pym/portage/package/ebuild/_config/InstallMaskManager.py
new file mode 100644
index 000..96cb539
--- /dev/null
+++ b/pym/portage/package/ebuild/_config/InstallMaskManager.py
@@ -0,0 +1,59 @@
+# Copyright 2010-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+__all__ = (
+   'InstallMaskManager',
+)
+
+import sys
+
+from portage import os
+from portage.localization import _
+from portage.util import writemsg
+from portage.util.configparser import (SafeConfigParser, ConfigParserError,
+   MultiValueConfigParserDict, read_configs)
+
+
+class InstallMaskManager(object):
+   def __init__(self, repositories, abs_user_config, user_config=True):
+   self._groups = {}
+
+   # read repository defined groups
+   self._read_config_from_repositories(repositories)
+
+   if user_config:
+   self._read_config(os.path.join(abs_user_config, 
'install-mask.conf'), True)
+
+   def _read_config_from_repositories(self, repositories):
+   for r in repositories.repos_with_profiles():
+   self._read_config(os.path.join(r.location, 'metadata', 
'install-mask.conf'))
+
+   def _read_config(self, path, is_user_config=False):
+   # use separate parsers to detect collisions properly
+   cfp_kwargs = {}
+   if sys.hexversion >= 0x0302:
+   cfp_kwargs['strict'] = False
+   parser = SafeConfigParser(dict_type=MultiValueConfigParserDict,
+   **cfp_kwargs)
+   try:
+   read_configs(parser, [path])
+   except ConfigParserError as e:
+   writemsg(
+   _("!!! Error while reading %s: %s\n") % (path, 
e),
+   noiselevel=-1)
+   return
+
+   for sname in parser.sections():
+   if not is_user_config and sname in self._groups:
+   writemsg(
+   _("!!! Error while reading %s: 
duplicate group %s found\n") % (path, sname),
+   noiselevel=-1)
+   continue
+   if not parser.has_option(sname, 'path'):
+   continue
+
+   paths = parser.get(sname, 'path').split('\n')
+   self._groups[sname] = paths
+
+   def expand_group(self, gname):
+   return self._groups[gname]
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 9d13703..dfbd7f2 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -60,6 +60,7 @@ from portage.package.ebuild._config.features_set import 
features_set
 from portage.package.ebuild._config.KeywordsManager import KeywordsManager
 from portage.package.ebuild._config.LicenseManager import LicenseManager
 from portage.package.ebuild._config.UseManager import UseManager
+from portage.package.ebuild._config.InstallMaskManager import 
InstallMaskManager
 from portage.package.ebuild._config.LocationsManager import LocationsManager
 from portage.package.ebuild._config.MaskManager import MaskManager
 from portage.package.ebuild._config.VirtualsManager import VirtualsManager
@@ -277,6 +278,7 @@ class config(object):
# force instantiation of lazy immutable objects when 
cloning, so
# that they're not instantiated more than once
self._keywords_manager_obj = clone._keywords_manager
+   self._install_mask_manager_obj = 
clone._install_mask_manager
self._mask_manager_obj = clone._mask_manager
 
# shared mutable attributes
@@ -329,6 +331,7 @@ class config(object):
else:
# lazily instantiated objects
self._keywords_manager_obj = None
+   self._install_mask_manager_obj = None
self._mask_manager_obj = None
self._virtuals_manager_obj = None
 
@@ -1032,6 +1035,15 @@ class config(object):
return self._keywords_manager_obj
 
@property
+   def _install_mask_manager(self):
+   if self._install_mask_manager_obj is None:
+   self._install_mask_manager_obj = InstallMaskManager(
+ 

Re: [gentoo-portage-dev] New meeting

2016-06-07 Thread Michał Górny
Dnia 3 czerwca 2016 19:06:38 CEST, Alexander Berntsen  
napisał(a):
>-BEGIN PGP SIGNED MESSAGE-
>Hash: SHA512
>
>It seems the three of us who've replied are all available 2016-06-07
>at 2pm UTC. That's 4pm for me. Check when it is in your timezone[0],
>and I'll see you then! And remember to update the agenda[1] with your
>items.

Could you add the topic of PMS compliance patches for me? Thanks to our very 
helpful www team, wiki is completely inaccessible to people who are not around 
a PC.

I'll be in travel during the meeting, and I'll hopefully join via phone unless 
I fall asleep too hard :-). In case the latter happens, short note the releases 
topic:

I'd really appreciate if we could:

1. Get at least patches 1-3 (preferably all 4) of my INSTALL_MASK improvements 
merged,

2. Do a release with them and the global-score use* ban (already in master),

3. Delay USE_EXPAND patches post release.

The global-scope use* uses are already fixed, so urgent release with the change 
will prevent people from reintroducing them.

The INSTALL_MASK enhancements would give people more tools for lingua 
filtering. Therefore, it would be good to have it early, and to mention them in 
the news item before LINGUAS are adjusted to adhere to the PMS.

>
>
>[0]
><http://whenisgood.net/ResultsPopup?event=portage&code=y8rwaw9&slot=146530800>
>[1]  <https://wiki.gentoo.org/wiki/Project:Portage/Meetings#Agenda>
>- -- 
>Alexander
>berna...@gentoo.org
>https://secure.plaimi.net/~alexander
>-BEGIN PGP SIGNATURE-
>Version: GnuPG v2
>
>iQIcBAEBCgAGBQJXUbkeAAoJENQqWdRUGk8BtC0QAJ9DBSBqya9vfWGUT7AVXYMV
>tAjdNXhs8jJ/ygCEX6MkRvYFqjRuHDIKlGKNpNR96HA7M9j6oxyjySN4ccxxtG7R
>T4dBSKPBrU7SEyOeTjtacgXqvbXBJQKrAsAEdJwyr8f5HPmys+Y1GsWqtOJT3N2a
>q8X6AZzKRft3XatXi0UahTUq4R2/Ln/RfelE0QQGjMEFCzxdj5nZBbyJdfroSlBK
>g9KkHX9QLfoCEbvI8Fe0dksWVmFV8ESwnDvkoNEb+A5ODSTBRvqkaOc3T3hLGEQM
>zGS/FT4de38A29ScGtbVWaM/VeDAfUj9hmu+tzSxzN1sNPHpRPn/dKDco71aFaIe
>gNLMhLmFyiJftThMV7bnGmuc6EvtLl72oM/Ca/4WI8ZDO4XqkuWIth1vdZKyq3wm
>3xI1Cwsow2Fjg0kN8e2nkKgZHw/3ulEZnvaC9QijkCjJpjxD013kHtd3xhndBmAi
>gJMtQf4MOtoluiq7wKVQMUQb6yty8jyWjiHrO9YUwwhXFodfZ10/aXwx3aK20e2U
>BgyVxpG+gxwkBJbuEQWIQbgvQHxyuwOlRvaE7KyRvsTLmrbMQjaf8ya7VX/Tzl6H
>EJxQpEIwqARgVMY6WluPRSAg6vqB1f/ozLntpjqCwInyHYO1y2AS2++VPLusoZkC
>Mtr9L1PTgtVfGWf2edy8
>=PUFC
>-END PGP SIGNATURE-


-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH 4/3] portage.package.ebuild.config: Support path groups from install-mask.conf

2016-06-10 Thread Michał Górny
On Tue, 31 May 2016 17:58:34 +0200
Michał Górny  wrote:

> ---
>  .../package/ebuild/_config/InstallMaskManager.py   | 59 
> ++
>  pym/portage/package/ebuild/config.py   | 34 -
>  pym/portage/util/configparser.py   | 19 ++-
>  3 files changed, 110 insertions(+), 2 deletions(-)
>  create mode 100644 pym/portage/package/ebuild/_config/InstallMaskManager.py

Please disregard this one. After discussion with ulm, the spec is
changing and I will be providing an updated patch later. However,
the remaining three still apply.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpbdoNQzqiWc.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH v2] Move INSTALL_MASK handling into merging

2016-06-12 Thread Michał Górny
Dnia 12 czerwca 2016 11:10:55 CEST, Zac Medico  napisał(a):
>On 05/22/2016 01:21 AM, Michał Górny wrote:
>> Introduce a new logic for INSTALL_MASK handling in merging code,
>> replacing the old code that removed matching files and directories
>> from imagedir in bash. The new code actually ignores matching files
>> on-the-fly while testing for file collisions and merging files.
>> The files are still written to CONTENTS, and output using "###" zing
>> to indicate being masked, yet are not actually merged to the
>filesystem.
>
>Since collision-protect relies on existing files in its collision test,
>install-masked files are no longer going to trigger collisions. Then,
>since the install-masked files are still written to CONTENTS, it's
>possible for the unmerge of one package to unmerge colliding files that
>belong to another package!
>
>There are a number of ways to solve this problem. For example, we could
>have the unmerge code ignore any files in CONTENTS that match the
>INSTALL_MASK value that was used at merge time.

Hmm, thinking about this more widely (i.e. actually thinking rather than 
mimicking the old behavior), I think it would be better to actually use the 
original file set for collision-protect. This will make it possible to detect 
collisions that would otherwise be hidden via INSTALL_MASK.

-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH 3/3] portage.dbapi.vartree: Support exclusions in INSTALL_MASK

2016-06-12 Thread Michał Górny
Dnia 12 czerwca 2016 11:20:36 CEST, Zac Medico  napisał(a):
>On 05/21/2016 11:56 PM, Michał Górny wrote:
>> Allow INSTALL_MASK patterns to start with '-' to indicate that
>> a specific match is to be excluded from being masked. In this case,
>> the last matching pattern determines whether the file is actually
>> filtered out or kept.
>> ---
>>  pym/portage/dbapi/vartree.py | 10 ++
>>  1 file changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/pym/portage/dbapi/vartree.py
>b/pym/portage/dbapi/vartree.py
>> index 8e5ac43..d02d850 100644
>> --- a/pym/portage/dbapi/vartree.py
>> +++ b/pym/portage/dbapi/vartree.py
>> @@ -3690,19 +3690,21 @@ class dblink(object):
>>  def _is_install_masked(self, relative_path):
>>  ret = False
>>  for pattern in self.settings.install_mask:
>> +# if pattern starts with -, possibly exclude this path
>> +pat_res = not pattern.startswith('-')
>> +if not pat_res:
>> +pattern = pattern[1:]
>>  # absolute path pattern
>>  if pattern.startswith('/'):
>>  # match either exact path or one of parent dirs
>>  # the latter is done via matching pattern/*
>>  if (fnmatch.fnmatch(relative_path, pattern[1:])
>>  or 
>> fnmatch.fnmatch(relative_path, pattern[1:] + '/*')):
>> -ret = True
>> -break
>> +ret = pat_res
>>  # filename
>>  else:
>>  if 
>> fnmatch.fnmatch(os.path.basename(relative_path), pattern):
>> -ret = True
>> -break
>> +ret = pat_res
>>  return ret
>>  
>>  def treewalk(self, srcroot, destroot, inforoot, myebuild,
>cleanup=0,
>> 
>
>In order to implement this with pre-compiled patterns, we can use a
>separate regular expression to represent all of the exclusions.

That won't work since exclusive and inclusive patterns can be stacked, and for 
this to work they are applied in order.

E.g. /usr/foo -/usr/foo/bar /usr/foo/bar/baz

Should remove all foo subdirectories except for bar, and also baz inside bar.


-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH 1/3] portage.package.ebuild.config: Move FEATURES=no* handling there

2016-06-12 Thread Michał Górny
Dnia 12 czerwca 2016 09:28:14 CEST, Zac Medico  napisał(a):
>On 06/12/2016 12:19 AM, Zac Medico wrote:
>> On 05/21/2016 11:56 PM, Michał Górny wrote:
>>> diff --git a/pym/portage/package/ebuild/config.py
>b/pym/portage/package/ebuild/config.py
>>> index 45b7d08..fcc7ce5 100644
>>> --- a/pym/portage/package/ebuild/config.py
>>> +++ b/pym/portage/package/ebuild/config.py
>>> @@ -1773,6 +1773,16 @@ class config(object):
>>> # setcpv triggers lazy instantiation of things like 
>>> _use_manager.
>>> _eapi_cache.clear()
>>>  
>>> +   # Prepare the final value of INSTALL_MASK
>>> +   install_mask = self["INSTALL_MASK"].split()
>>> +   if 'nodoc' in self.features:
>>> +   install_mask.append("/usr/share/doc")
>>> +   if 'noinfo' in self.features:
>>> +   install_mask.append("/usr/share/info")
>>> +   if 'noman' in self.features:
>>> +   install_mask.append("/usr/share/man")
>>> +   self["INSTALL_MASK"] = ' '.join(install_mask)
>>> +
>>> def _grab_pkg_env(self, penv, container, protected_keys=None):
>>> if protected_keys is None:
>>> protected_keys = ()
>>>
>> 
>> I'm concerned that these values can be appended more than once,
>causing
>> the variable to contain duplicate values, because setcpv only calls
>> reset when the has_changed variable is True. So, we only want to call
>> this code when has_changed is True. In fact, this code can go
>> immediately after the reset call here:
>> 
>>  if has_changed:
>>  self.reset(keeping_pkg=1)
>> 
>
>Actually, it's more tricky than that, because we need to account for
>both global FEATURES settings and package.env FEATURES settings, and my
>above statements do not account for the global settings.
>
>Also need to consider the case where these features are enabled
>globally, and then *disabled* via package.env!

Then maybe we should just ban them and tell people to use INSTALL_MASK directly 
instead. Their behavior is quite unclear anyway, considering later possible 
exclusions.


-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH 3/3] portage.dbapi.vartree: Support exclusions in INSTALL_MASK

2016-06-12 Thread Michał Górny
Dnia 12 czerwca 2016 11:43:35 CEST, Zac Medico  napisał(a):
>On 06/12/2016 02:31 AM, Michał Górny wrote:
>> Dnia 12 czerwca 2016 11:20:36 CEST, Zac Medico 
>napisał(a):
>>> On 05/21/2016 11:56 PM, Michał Górny wrote:
>>>> Allow INSTALL_MASK patterns to start with '-' to indicate that
>>>> a specific match is to be excluded from being masked. In this case,
>>>> the last matching pattern determines whether the file is actually
>>>> filtered out or kept.
>>>> ---
>>>>  pym/portage/dbapi/vartree.py | 10 ++
>>>>  1 file changed, 6 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/pym/portage/dbapi/vartree.py
>>> b/pym/portage/dbapi/vartree.py
>>>> index 8e5ac43..d02d850 100644
>>>> --- a/pym/portage/dbapi/vartree.py
>>>> +++ b/pym/portage/dbapi/vartree.py
>>>> @@ -3690,19 +3690,21 @@ class dblink(object):
>>>>def _is_install_masked(self, relative_path):
>>>>ret = False
>>>>for pattern in self.settings.install_mask:
>>>> +  # if pattern starts with -, possibly exclude this path
>>>> +  pat_res = not pattern.startswith('-')
>>>> +  if not pat_res:
>>>> +  pattern = pattern[1:]
>>>># absolute path pattern
>>>>if pattern.startswith('/'):
>>>># match either exact path or one of parent dirs
>>>># the latter is done via matching pattern/*
>>>>if (fnmatch.fnmatch(relative_path, pattern[1:])
>>>>or 
>>>> fnmatch.fnmatch(relative_path, pattern[1:] + '/*')):
>>>> -  ret = True
>>>> -  break
>>>> +  ret = pat_res
>>>># filename
>>>>else:
>>>>if 
>>>> fnmatch.fnmatch(os.path.basename(relative_path), pattern):
>>>> -  ret = True
>>>> -  break
>>>> +  ret = pat_res
>>>>return ret
>>>>  
>>>>def treewalk(self, srcroot, destroot, inforoot, myebuild,
>>> cleanup=0,
>>>>
>>>
>>> In order to implement this with pre-compiled patterns, we can use a
>>> separate regular expression to represent all of the exclusions.
>> 
>> That won't work since exclusive and inclusive patterns can be
>stacked, and for this to work they are applied in order.
>> 
>> E.g. /usr/foo -/usr/foo/bar /usr/foo/bar/baz
>> 
>> Should remove all foo subdirectories except for bar, and also baz
>inside bar.
>
>Hmm, I suppose there could be an optimized implementation to handle
>INSTALL_MASK settings where there are no such ordering constraints.

Is this really worth the effort? I'm using the patch for a while and I/O's the 
bottleneck, not CPU. If you really insist on optimizing this, i guess we could 
precompile all patterns separately.


-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH v2] Move INSTALL_MASK handling into merging

2016-06-12 Thread Michał Górny
Dnia 12 czerwca 2016 11:49:26 CEST, Zac Medico  napisał(a):
>On 06/12/2016 02:28 AM, Michał Górny wrote:
>> Dnia 12 czerwca 2016 11:10:55 CEST, Zac Medico 
>napisał(a):
>>> On 05/22/2016 01:21 AM, Michał Górny wrote:
>>>> Introduce a new logic for INSTALL_MASK handling in merging code,
>>>> replacing the old code that removed matching files and directories
>>>> from imagedir in bash. The new code actually ignores matching files
>>>> on-the-fly while testing for file collisions and merging files.
>>>> The files are still written to CONTENTS, and output using "###"
>zing
>>>> to indicate being masked, yet are not actually merged to the
>>> filesystem.
>>>
>>> Since collision-protect relies on existing files in its collision
>test,
>>> install-masked files are no longer going to trigger collisions.
>Then,
>>> since the install-masked files are still written to CONTENTS, it's
>>> possible for the unmerge of one package to unmerge colliding files
>that
>>> belong to another package!
>>>
>>> There are a number of ways to solve this problem. For example, we
>could
>>> have the unmerge code ignore any files in CONTENTS that match the
>>> INSTALL_MASK value that was used at merge time.
>> 
>> Hmm, thinking about this more widely (i.e. actually thinking rather
>than mimicking the old behavior), I think it would be better to
>actually use the original file set for collision-protect. This will
>make it possible to detect collisions that would otherwise be hidden
>via INSTALL_MASK.
>
>Even then, we have to carefully consider how the absence of installed
>files affects the collision test. It's safest for the unmerge code to
>be
>aware of the merge time INSTALL_MASK setting, and not try to unmerge
>the
>install-masked files.

But then it wouldn't unmerge the newly masked files as well. Getting this right 
will require a lot of effort, and we're less likely to screw something up if we 
keep it simple.


-- 
Best regards,
Michał Górny (by phone)



Re: [gentoo-portage-dev] [PATCH] ebuild: Extend helper-in-global-scope ban to all EAPIs

2016-06-26 Thread Michał Górny
On Sun, 26 Jun 2016 17:07:09 -0700
Zac Medico  wrote:

> On 05/20/2016 03:27 PM, Michał Górny wrote:
> > On Thu,  5 May 2016 23:10:43 +0200
> > Michał Górny  wrote:
> >   
> >> Make helper calls in global scope fatal in all supported EAPIs since
> >> this is the behavior required by PMS and all major offenders are fixed
> >> already.
> >> ---
> >>  bin/eapi.sh   |  4 
> >>  bin/ebuild.sh | 30 ++
> >>  2 files changed, 6 insertions(+), 28 deletions(-)  
> > 
> > Merged now.
> >   
> 
> Seems we might need to revert this patch:
> 
> https://forums.gentoo.org/viewtopic-t-1047248.html

If we revert it, people will stop caring for another year...

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpjRRa6t3u7q.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH] repoman: Make LIVEVCS.* checks fatal

2016-06-28 Thread Michał Górny
Make LIVEVCS.* checks fatal to prevent people from committing ebuilds
using live eclasses instead of package.masking them afterwards by QA.
---
 repoman/pym/repoman/qa_data.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/repoman/pym/repoman/qa_data.py b/repoman/pym/repoman/qa_data.py
index 48ab389..738368e 100644
--- a/repoman/pym/repoman/qa_data.py
+++ b/repoman/pym/repoman/qa_data.py
@@ -270,8 +270,6 @@ qawarnings = set((
"repo.eapi.deprecated",
"usage.obsolete",
"upstream.workaround",
-   "LIVEVCS.stable",
-   "LIVEVCS.unmasked",
"IUSE.rubydeprecated",
 ))
 
-- 
2.9.0




Re: [gentoo-portage-dev] [PATCH] repoman: Make LIVEVCS.* checks fatal

2016-06-30 Thread Michał Górny
On Tue, 28 Jun 2016 12:40:07 -0700
Zac Medico  wrote:

> On 06/28/2016 11:30 AM, Michał Górny wrote:
> > Make LIVEVCS.* checks fatal to prevent people from committing ebuilds
> > using live eclasses instead of package.masking them afterwards by QA.
> > ---
> >  repoman/pym/repoman/qa_data.py | 2 --
> >  1 file changed, 2 deletions(-)
> > 
> > diff --git a/repoman/pym/repoman/qa_data.py b/repoman/pym/repoman/qa_data.py
> > index 48ab389..738368e 100644
> > --- a/repoman/pym/repoman/qa_data.py
> > +++ b/repoman/pym/repoman/qa_data.py
> > @@ -270,8 +270,6 @@ qawarnings = set((
> > "repo.eapi.deprecated",
> > "usage.obsolete",
> > "upstream.workaround",
> > -   "LIVEVCS.stable",
> > -   "LIVEVCS.unmasked",
> > "IUSE.rubydeprecated",
> >  ))
> >  
> >   
> 
> Looks good.

Signed and pushed!

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpr98ZWnpyED.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] Leadership election

2016-10-11 Thread Michał Górny
On Tue, 11 Oct 2016 01:59:38 -0700
Zac Medico  wrote:

> On 10/11/2016 12:06 AM, Alexander Berntsen wrote:
> > Right, voting. I vote for... Brian? Yeah. Brian!
> >   
> 
> I vote for Brian too. Brian! :)

++Brian.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpoSx5652awM.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH] [sync] Increase the default git sync-depth to 10

2016-10-30 Thread Michał Górny
Increate the default git sync-depth from 1 to 10, to ensure that
gentoo-mirror git clones retain at least a single original signed
commit.
---
 pym/portage/sync/modules/git/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pym/portage/sync/modules/git/__init__.py 
b/pym/portage/sync/modules/git/__init__.py
index d5eb5c6..54070fc 100644
--- a/pym/portage/sync/modules/git/__init__.py
+++ b/pym/portage/sync/modules/git/__init__.py
@@ -18,7 +18,7 @@ class CheckGitConfig(CheckSyncConfig):
def check_depth(self):
d = self.repo.sync_depth
# default
-   self.repo.sync_depth = 1
+   self.repo.sync_depth = 10
 
if d is not None:
try:
-- 
2.10.2




[gentoo-portage-dev] [PATCH] [sync] Run `git update-index --refresh` when doing shallow pulls

2016-10-30 Thread Michał Górny
Run `git update-index --refresh` to force proper index recheck before
running `git reset --merge` on a shallow pull. This fixes syncing on
some filesystem configurations including overlayfs on squashfs.
---
 pym/portage/sync/modules/git/git.py | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/pym/portage/sync/modules/git/git.py 
b/pym/portage/sync/modules/git/git.py
index 3734b80..dc94ec9 100644
--- a/pym/portage/sync/modules/git/git.py
+++ b/pym/portage/sync/modules/git/git.py
@@ -89,7 +89,7 @@ class GitSync(NewBase):
else:
# Since the default merge strategy typically fails when
# the depth is not unlimited, use `git fetch` followed 
by
-   # `git reset --merge`.
+   # `git update-index --refresh`, then `git reset 
--merge`.
try:
remote_branch = portage._unicode_decode(

subprocess.check_output([self.bin_command, 'rev-parse',
@@ -116,12 +116,23 @@ class GitSync(NewBase):
**self.spawn_kwargs)
 
if exitcode == os.EX_OK and self.repo.sync_depth is not None:
-   reset_cmd = [self.bin_command, 'reset', '--merge', 
remote_branch]
-   if quiet:
-   reset_cmd.append('--quiet')
-   exitcode = subprocess.call(reset_cmd,
+   # update-index --refresh is needed on some filesystems
+   # (e.g. with overlayfs on squashfs)
+   update_index_cmd = [self.bin_command, 'update-index']
+   if quiet: # -q needs to go first
+   update_index_cmd.append('-q')
+   update_index_cmd.append('--refresh')
+
+   exitcode = subprocess.call(update_index_cmd,
cwd=portage._unicode_encode(self.repo.location))
 
+   if exitcode == os.EX_OK:
+   reset_cmd = [self.bin_command, 'reset', 
'--merge', remote_branch]
+   if quiet:
+   reset_cmd.append('--quiet')
+   exitcode = subprocess.call(reset_cmd,
+   
cwd=portage._unicode_encode(self.repo.location))
+
if exitcode != os.EX_OK:
msg = "!!! git pull error in %s" % self.repo.location
self.logger(self.xterm_titles, msg)
-- 
2.10.2




Re: [gentoo-portage-dev] [PATCH] [sync] Increase the default git sync-depth to 10

2016-10-30 Thread Michał Górny
On Sun, 30 Oct 2016 13:22:51 -0700
Zac Medico  wrote:

> On Sun, Oct 30, 2016 at 1:19 PM, Zac Medico  wrote:
> > On 10/30/2016 12:08 PM, Michał Górny wrote:  
> >> Increate the default git sync-depth from 1 to 10, to ensure that
> >> gentoo-mirror git clones retain at least a single original signed
> >> commit.  
> >
> > Why wouldn't the last commit always be signed?  
> 
> Oh, it could be a merge commit. Couldn't the original signed commit be
> much more than 10 commit behind though?

No, gentoo-mirror is only doing a single-level merge commit to combine
signed changes with cache. I'm using 10 as round safe default that
shouldn't take up too much space.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgp91imwmLMoU.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH] [sync] Run `git update-index --refresh` when doing shallow pulls

2016-10-30 Thread Michał Górny
On Sun, 30 Oct 2016 13:39:53 -0700
Zac Medico  wrote:

> On 10/30/2016 12:23 PM, Michał Górny wrote:
> > Run `git update-index --refresh` to force proper index recheck before
> > running `git reset --merge` on a shallow pull. This fixes syncing on
> > some filesystem configurations including overlayfs on squashfs.  
> 
> Maybe we should use --really-refresh in case the --assume-unchanged flag
> gets toggled on somehow (maybe via .git/config)?

I don't know. I think we can revisit it if it really becomes a problem
for anyone.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpVmnmuWjxmS.pgp
Description: OpenPGP digital signature


[gentoo-portage-dev] [PATCH] [sync] Increase the default git sync-depth to 10

2016-10-30 Thread Michał Górny
Increate the default git sync-depth from 1 to 10, to ensure that
gentoo-mirror git clones retain at least a single original signed
commit.
---
 man/portage.5| 10 --
 pym/portage/sync/modules/git/__init__.py |  2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/man/portage.5 b/man/portage.5
index 963f49d..c1e4d97 100644
--- a/man/portage.5
+++ b/man/portage.5
@@ -965,8 +965,14 @@ Specifies priority of given repository.
 Specifies CVS repository.
 .TP
 .B sync\-depth
-Specifies clone depth to use for DVCS repositories. Defaults to 1 (only
-the newest commit). If set to 0, the depth is unlimited.
+Specifies clone depth to use for DVCS repositories. Defaults to 10
+(commits deep). If set to 0, the depth is unlimited.
+.br
+The default depth of 10 was chosen as a compromise between space
+and bandwidth savings, and maintaining a history of recent commits.
+It is especially important for gentoo-mirror repositories where the most
+recent commits are automated and unsigned, and it is necessary to
+rewind the history to the newest signed commit for OpenPGP verification.
 .TP
 .B sync\-git\-clone\-extra\-opts
 Extra options to give to git when cloning repository (git clone).
diff --git a/pym/portage/sync/modules/git/__init__.py 
b/pym/portage/sync/modules/git/__init__.py
index d5eb5c6..54070fc 100644
--- a/pym/portage/sync/modules/git/__init__.py
+++ b/pym/portage/sync/modules/git/__init__.py
@@ -18,7 +18,7 @@ class CheckGitConfig(CheckSyncConfig):
def check_depth(self):
d = self.repo.sync_depth
# default
-   self.repo.sync_depth = 1
+   self.repo.sync_depth = 10
 
if d is not None:
try:
-- 
2.10.2




Re: [gentoo-portage-dev] [PATCH] [sync] Run `git update-index --refresh` when doing shallow pulls

2016-10-30 Thread Michał Górny
On Sun, 30 Oct 2016 13:53:05 -0700
Zac Medico  wrote:

> On 10/30/2016 01:44 PM, Michał Górny wrote:
> > On Sun, 30 Oct 2016 13:39:53 -0700
> > Zac Medico  wrote:
> >   
> >> On 10/30/2016 12:23 PM, Michał Górny wrote:  
> >>> Run `git update-index --refresh` to force proper index recheck before
> >>> running `git reset --merge` on a shallow pull. This fixes syncing on
> >>> some filesystem configurations including overlayfs on squashfs.
> >>
> >> Maybe we should use --really-refresh in case the --assume-unchanged flag
> >> gets toggled on somehow (maybe via .git/config)?  
> > 
> > I don't know. I think we can revisit it if it really becomes a problem
> > for anyone.  
> 
> OK, sounds good. The patch LGTM.

Pushed.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgp_3opTsGQ3Z.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH] [sync] Increase the default git sync-depth to 10

2016-10-30 Thread Michał Górny
On Sun, 30 Oct 2016 14:44:26 -0700
Zac Medico  wrote:

> On 10/30/2016 02:34 PM, Michał Górny wrote:
> > Increate the default git sync-depth from 1 to 10, to ensure that  
> 
> s/Increate/Increase/

Fixed.

> > gentoo-mirror git clones retain at least a single original signed
> > commit.
> > ---
> >  man/portage.5| 10 --
> >  pym/portage/sync/modules/git/__init__.py |  2 +-
> >  2 files changed, 9 insertions(+), 3 deletions(-)
> > 
> > diff --git a/man/portage.5 b/man/portage.5
> > index 963f49d..c1e4d97 100644
> > --- a/man/portage.5
> > +++ b/man/portage.5
> > @@ -965,8 +965,14 @@ Specifies priority of given repository.
> >  Specifies CVS repository.
> >  .TP
> >  .B sync\-depth
> > -Specifies clone depth to use for DVCS repositories. Defaults to 1 (only
> > -the newest commit). If set to 0, the depth is unlimited.
> > +Specifies clone depth to use for DVCS repositories. Defaults to 10
> > +(commits deep). If set to 0, the depth is unlimited.
> > +.br
> > +The default depth of 10 was chosen as a compromise between space
> > +and bandwidth savings, and maintaining a history of recent commits.
> > +It is especially important for gentoo-mirror repositories where the most
> > +recent commits are automated and unsigned, and it is necessary to
> > +rewind the history to the newest signed commit for OpenPGP verification.  
> 
> Shouldn't people feel uneasy about the last commit being unverifiable? I
> would think that that last commit should be signed with an
> infrastructure key.

I've even written a blog post [1] about that. Long story short,
trusting some random key used by automated process running on remote
server with no real security is insane. I've made a script that
verifies underlying repo commit instead, and diffs for metadata
changes.

[1]:https://blogs.gentoo.org/mgorny/2016/04/15/why-automated-gentoo-mirror-commits-are-not-signed-and-how-to-verify-them-2/

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpgqKE6ZVgvK.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] Re: [PATCH] [sync] Run `git update-index --refresh` when doing shallow pulls

2016-10-31 Thread Michał Górny
On Mon, 31 Oct 2016 07:16:24 + (UTC)
Martin Vaeth  wrote:

> Michał Górny  wrote:
> > +   if quiet: # -q needs to go first
> > +   update_index_cmd.append('-q')  
> 
> The options -q --unmerged (which are implicitly passed by "git status")
> are not only to suppress verbosity:
> The git-update-index man page has to say for these options:
> 
> : the default behavior is to error out. This option makes
> : git update-index continue anyway.
> 
> and if I understood the git source code correctly, without
> these options git will indeed break some loops early in the
> "error" case, i.e. it will perhaps not do a full update of
> the index in the "error" case.

It's a 'best effort' attempt at making git not error out
in the following merge. If it doesn't work, the merge will print
the error.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpWdkbJQrA03.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] portage-2.3.2 stable request?

2016-11-04 Thread Michał Górny
On Fri, 4 Nov 2016 13:19:39 -0700
Zac Medico  wrote:

> On 11/04/2016 01:14 PM, Brian Dolbec wrote:
> > On Thu, 3 Nov 2016 15:55:23 -0700
> > Zac Medico  wrote:
> >   
> >> In about a week, portage-2.3.2 will be eligible for a stable request.
> >>
> >> The only potential problem that I've noticed is the complaint about
> >> changes from bug 552814 causing issues for people using git sync with
> >> overlay filesystems, but setting sync-depth = 0 gives those users a
> >> workaround. There's also bug 597838, about the sync-depth setting
> >> being ineffective, but I only know of a couple of people that have
> >> been able to reproduce that.
> >>
> >> So, do we want to do a stable request portage-2.3.2 when the time
> >> comes?  
> > 
> > I'm not sure.  Do we -r1 it adding a patch or two and ask it be stabled?
> >   
> 
> There are just 4 commits since 2.3.2, and they all look good. Maybe we
> should just cut a 2.3.3 release and wait another 30 days (we also need
> to stabilize app-crypt/gkeys since it's needed by emerge-webrsync now).

Wouldn't it be better to have a really working version of gkeys before
it's stabilized? Like one that could be used without having to create
custom configuration files and/or run it as root?

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpVR3redBmlG.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH] sync: call git prune before shallow fetch (bug 599008)

2016-11-05 Thread Michał Górny
On Sat,  5 Nov 2016 13:43:15 -0700
Zac Medico  wrote:

> This is necessary in order to avoid "There are too many unreachable
> loose objects" warnings from automatic git gc calls.
> 
> X-Gentoo-Bug: 599008
> X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=599008
> ---
>  pym/portage/sync/modules/git/git.py | 6 ++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/pym/portage/sync/modules/git/git.py 
> b/pym/portage/sync/modules/git/git.py
> index f288733..c90cf88 100644
> --- a/pym/portage/sync/modules/git/git.py
> +++ b/pym/portage/sync/modules/git/git.py
> @@ -101,6 +101,12 @@ class GitSync(NewBase):
>   writemsg_level(msg + "\n", level=logging.ERROR, 
> noiselevel=-1)
>   return (e.returncode, False)
>  
> + # For shallow fetch, unreachable objects must be pruned
> + # manually, since otherwise automatic git gc calls will
> + # eventually warn about them (see bug 599008).
> + subprocess.call(['git', 'prune'],
> + cwd=portage._unicode_encode(self.repo.location))
> +
>   git_cmd_opts += " --depth %d" % self.repo.sync_depth
>   git_cmd = "%s fetch %s%s" % (self.bin_command,
>   remote_branch.partition('/')[0], git_cmd_opts)

Does it have a performance impact?

-- 
Best regards,
Michał Górny


pgpxPy9bIdGpf.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH] sync: call git prune before shallow fetch (bug 599008)

2016-11-05 Thread Michał Górny
On Sat, 5 Nov 2016 15:11:10 -0700
Zac Medico  wrote:

> On 11/05/2016 02:50 PM, Michał Górny wrote:
> > On Sat,  5 Nov 2016 13:43:15 -0700
> > Zac Medico  wrote:
> >   
> >> This is necessary in order to avoid "There are too many unreachable
> >> loose objects" warnings from automatic git gc calls.
> >>
> >> X-Gentoo-Bug: 599008
> >> X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=599008
> >> ---
> >>  pym/portage/sync/modules/git/git.py | 6 ++
> >>  1 file changed, 6 insertions(+)
> >>
> >> diff --git a/pym/portage/sync/modules/git/git.py 
> >> b/pym/portage/sync/modules/git/git.py
> >> index f288733..c90cf88 100644
> >> --- a/pym/portage/sync/modules/git/git.py
> >> +++ b/pym/portage/sync/modules/git/git.py
> >> @@ -101,6 +101,12 @@ class GitSync(NewBase):
> >>writemsg_level(msg + "\n", level=logging.ERROR, 
> >> noiselevel=-1)
> >>return (e.returncode, False)
> >>  
> >> +  # For shallow fetch, unreachable objects must be pruned
> >> +  # manually, since otherwise automatic git gc calls will
> >> +  # eventually warn about them (see bug 599008).
> >> +  subprocess.call(['git', 'prune'],
> >> +  cwd=portage._unicode_encode(self.repo.location))
> >> +
> >>git_cmd_opts += " --depth %d" % self.repo.sync_depth
> >>git_cmd = "%s fetch %s%s" % (self.bin_command,
> >>remote_branch.partition('/')[0], git_cmd_opts)  
> > 
> > Does it have a performance impact?  
> 
> Yes, it takes about 20 seconds on my laptop. I suppose we could make
> this an optional thing, so that those people can do it manually if they
> want.

So we have improvement from at most few seconds for normal 'git pull'
to around a minute for shallow pull?

-- 
Best regards,
Michał Górny


pgpLtvazW4Jsz.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH] sync: call git prune before shallow fetch (bug 599008)

2016-11-06 Thread Michał Górny
On Sat, 5 Nov 2016 15:56:20 -0700
Zac Medico  wrote:

> On 11/05/2016 03:22 PM, Michał Górny wrote:
> > On Sat, 5 Nov 2016 15:11:10 -0700
> > Zac Medico  wrote:
> >   
> >> On 11/05/2016 02:50 PM, Michał Górny wrote:  
> >>> On Sat,  5 Nov 2016 13:43:15 -0700
> >>> Zac Medico  wrote:
> >>> 
> >>>> This is necessary in order to avoid "There are too many unreachable
> >>>> loose objects" warnings from automatic git gc calls.
> >>>>
> >>>> X-Gentoo-Bug: 599008
> >>>> X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=599008
> >>>> ---
> >>>>  pym/portage/sync/modules/git/git.py | 6 ++
> >>>>  1 file changed, 6 insertions(+)
> >>>>
> >>>> diff --git a/pym/portage/sync/modules/git/git.py 
> >>>> b/pym/portage/sync/modules/git/git.py
> >>>> index f288733..c90cf88 100644
> >>>> --- a/pym/portage/sync/modules/git/git.py
> >>>> +++ b/pym/portage/sync/modules/git/git.py
> >>>> @@ -101,6 +101,12 @@ class GitSync(NewBase):
> >>>>  writemsg_level(msg + "\n", 
> >>>> level=logging.ERROR, noiselevel=-1)
> >>>>  return (e.returncode, False)
> >>>>  
> >>>> +# For shallow fetch, unreachable objects must 
> >>>> be pruned
> >>>> +# manually, since otherwise automatic git gc 
> >>>> calls will
> >>>> +# eventually warn about them (see bug 599008).
> >>>> +subprocess.call(['git', 'prune'],
> >>>> +
> >>>> cwd=portage._unicode_encode(self.repo.location))
> >>>> +
> >>>>  git_cmd_opts += " --depth %d" % 
> >>>> self.repo.sync_depth
> >>>>  git_cmd = "%s fetch %s%s" % (self.bin_command,
> >>>>  remote_branch.partition('/')[0], 
> >>>> git_cmd_opts)
> >>>
> >>> Does it have a performance impact?
> >>
> >> Yes, it takes about 20 seconds on my laptop. I suppose we could make
> >> this an optional thing, so that those people can do it manually if they
> >> want.  
> > 
> > So we have improvement from at most few seconds for normal 'git pull'
> > to around a minute for shallow pull?  
> 
> Well we've got a least 3 resources to consider:
> 
> 1) network bandwidth
> 2) disk usage
> 3) sync time
> 
> For me, sync time doesn't really matter that much, but I suppose it
> might for some people.

For a common user, network bandwidth is not a problem with git (except
maybe for the huge initial clone). Especially when syncing frequently,
the gain from subsequent --depth=1 is negligible. When syncing rarely,
you probably prefer snapshots anyway.

I doubt this could be of benefit even to dial-up users; that is,
that more time would be saved on fetching than lost on all the ops
needed to make things continue to work. The additional data won't
affect the data plan users much probably either.

Especially that Gentoo is all about fetching distfiles that are huge
compared to the git updates for the repository.

As for the disk usage, again, the difference should be negligible.
The major difference is done on initial fetch. Of course, regularly
pruning the repository will reduce its size. But then, pruning it will
non-shallow fetches would probably achieve a similar effect thanks to
delta compression.

That leaves the sync time. Which is becoming worse than rsync.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpxVXUiCYwdc.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH v2] parse_metadata_use: prefer first language found (bug 599060)

2016-11-06 Thread Michał Górny
On Sun,  6 Nov 2016 12:37:22 -0800
Zac Medico  wrote:

> Descriptions may exist for multiple languages, so ignore all except
> the first description found for a particular value of restrict, so
> that use.local.desc content is consistent.
> 
> X-Gentoo-Bug: 599060
> X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=599060
> ---
>  pym/portage/xml/metadata.py | 10 ++
>  1 file changed, 10 insertions(+)
> 
> [PATCH v2] fix to handle multiple values of restrict
> 
> diff --git a/pym/portage/xml/metadata.py b/pym/portage/xml/metadata.py
> index 4940bfb..1bc1c78 100644
> --- a/pym/portage/xml/metadata.py
> +++ b/pym/portage/xml/metadata.py
> @@ -455,6 +455,16 @@ def parse_metadata_use(xml_tree):
>   if pkg_flag is not None:
>   flag_restrict = flag.get("restrict")
>  
> + # Descriptions may exist for multiple 
> languages, so
> + # ignore all except the first description found 
> for a
> + # particular value of restrict (see bug 599060).
> + try:
> + uselist[pkg_flag][flag_restrict]
> + except KeyError:
> + pass
> + else:
> + continue
> +
>   # emulate the Element.itertext() method from 
> python-2.7
>   inner_text = []
>   stack = []

This really doesn't fix the bug at hand. We should always prefer
English descriptions, either through lang="en" or lang="".

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgplpQgZxt5pz.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] Vote to revert all changes related to shallow git fetch from bug 552814

2016-11-07 Thread Michał Górny
On Sun, 6 Nov 2016 11:26:06 -0800
Zac Medico  wrote:

> Given the performance issues introduced by `git update-index` and `git
> prune`, shallow fetch doesn't seem to be a practical default at this time.
> 
> In order to prepare a release that will be eligible for stabilization, I
> propose that we revert all of the changes related to bug 552814:
> 
> https://gitweb.gentoo.org/proj/portage.git/commit/?id=84413bb1dd9df322568ce25efc5b7854a43d03c7
> https://gitweb.gentoo.org/proj/portage.git/commit/?id=55aef9bf297ef8cbf29921acb454449d01313818
> https://gitweb.gentoo.org/proj/portage.git/commit/?id=f5d258656de3db54af06fbca9b8da5217d3802f4
> https://gitweb.gentoo.org/proj/portage.git/commit/?id=f77fcd6b0b4ebb49ca62f5767cd5c931127c3dbb
> https://gitweb.gentoo.org/proj/portage.git/commit/?id=d075422a8902617833ec945d94beb0bb334d44c9

Please do that. The sooner it is done, the less likely it is that users
have too many loose objects to not be able to clean up the mess
automatically during periodic 'git gc'.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>


pgpqTwH99fREO.pgp
Description: OpenPGP digital signature


Re: [gentoo-portage-dev] [PATCH] Run distcc-pump server throughout src_configure() to src_install()

2017-01-31 Thread Michał Górny
Dnia 2014-09-07, nie o godzinie 12:16 +0200, Michał Górny pisze:
> Start distcc-pump server in all phases throughout src_configure() to
> src_install() rather than in src_compile() alone. Since each of those
> phases may involve some compilations, we should try to take full
> advantage of distcc in all of them. Moreover, this silences distcc
> warnings about being unable to connect to the server when compiling.

Pushed.

-- 
Best regards,
Michał Górny



signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH] sys-apps/portage: add native-extensions USE flag (bug 571444)

2017-02-01 Thread Michał Górny
W dniu 01.02.2017, śro o godzinie 09∶06 -0800, użytkownik Zac Medico
napisał:
> The native-extensions USE flag will enable building of the
> libc bindings. This is not enabled by default because it does
> not support cross compilation.
> 
> X-Gentoo-bug: 571444
> X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=571444
> ---
>  sys-apps/portage/metadata.xml| 1 +
>  sys-apps/portage/portage-.ebuild | 7 ++-
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/sys-apps/portage/metadata.xml b/sys-
> apps/portage/metadata.xml
> index e032ea5..882d3ba 100644
> --- a/sys-apps/portage/metadata.xml
> +++ b/sys-apps/portage/metadata.xml
> @@ -12,6 +12,7 @@
>    
>  Build html API documentation with
> epydoc.
>  Use inter-process communication between portage
> and running ebuilds.
> +Build native extensions. Cross-
> compilation is not supported.
>  Preserve extended attributes (filesystem-
> stored metadata) when installing files. Usually only required for
> hardened systems.
>    
>  
> diff --git a/sys-apps/portage/portage-.ebuild b/sys-
> apps/portage/portage-.ebuild
> index 6a6f515..981db26 100644
> --- a/sys-apps/portage/portage-.ebuild
> +++ b/sys-apps/portage/portage-.ebuild
> @@ -19,7 +19,7 @@ HOMEPAGE="https://wiki.gentoo.org/wiki/Project:Porta
> ge"
>  LICENSE="GPL-2"
>  KEYWORDS=""
>  SLOT="0"
> -IUSE="build doc epydoc +ipc linguas_ru selinux xattr"
> +IUSE="build doc epydoc +ipc linguas_ru native-extensions selinux
> xattr"

Wouldn't it be better to enable it by default?

>  
>  DEPEND="!build? ( $(python_gen_impl_dep 'ssl(+)') )
>   >=app-arch/tar-1.27
> @@ -85,6 +85,11 @@ pkg_setup() {
>  python_prepare_all() {
>   distutils-r1_python_prepare_all
>  
> + if use native-extensions; then
> + printf "[build_ext]\nportage-ext-modules=true" >> \
> + setup.cfg || die
> + fi
> +
>   if ! use ipc ; then
>   einfo "Disabling ipc..."
>   sed -e "s:_enable_ipc_daemon =
> True:_enable_ipc_daemon = False:" \

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH] sys-apps/portage: add native-extensions USE flag (bug 571444)

2017-02-04 Thread Michał Górny
W dniu 01.02.2017, śro o godzinie 20∶46 -0500, użytkownik Michael
Orlitzky napisał:
> On 02/01/2017 04:03 PM, Michał Górny wrote:
> > >  SLOT="0"
> > > -IUSE="build doc epydoc +ipc linguas_ru selinux xattr"
> > > +IUSE="build doc epydoc +ipc linguas_ru native-extensions selinux
> > > xattr"
> > 
> > Wouldn't it be better to enable it by default?
> > 
> 
> Please don't enshrine personal preferences into IUSE defaults unless
> they're critical to the package.

You're saying nonsense. There is no reason for most of Gentoo users to
default to crippled Portage.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH 08/18] Add tentative support for EAPI6 eapply_user function

2017-02-10 Thread Michał Górny
W dniu 09.02.2017, czw o godzinie 14∶39 -0800, użytkownik Zac Medico
napisał:
> On 12/01/2014 01:28 PM, Michał Górny wrote:
> > Add support for the user patch applying function.
> > ---
> >  bin/eapi.sh  |  4 
> >  bin/phase-helpers.sh | 22 ++
> >  2 files changed, 26 insertions(+)
> > 
> > diff --git a/bin/eapi.sh b/bin/eapi.sh
> > index 8bb..6e78750 100644
> > --- a/bin/eapi.sh
> > +++ b/bin/eapi.sh
> > @@ -76,6 +76,10 @@ ___eapi_has_eapply() {
> > [[ ! ${1-${EAPI}} =~ 
> > ^(0|1|2|3|4|4-python|4-slot-abi|5|5-hdepend|5-progress)$ ]]
> >  }
> >  
> > +___eapi_has_eapply_user() {
> > +   [[ ! ${1-${EAPI}} =~ 
> > ^(0|1|2|3|4|4-python|4-slot-abi|5|5-hdepend|5-progress)$ ]]
> > +}
> > +
> >  ___eapi_has_master_repositories() {
> > [[ ${1-${EAPI}} =~ ^(5-progress)$ ]]
> >  }
> > diff --git a/bin/phase-helpers.sh b/bin/phase-helpers.sh
> > index e9fbbb4..f4b64ee 100644
> > --- a/bin/phase-helpers.sh
> > +++ b/bin/phase-helpers.sh
> > @@ -986,6 +986,28 @@ if ___eapi_has_eapply; then
> > }
> >  fi
> >  
> > +if ___eapi_has_eapply_user; then
> > +   eapply_user() {
> > +   local basedir=${PORTAGE_CONFIGROOT%/}/etc/portage/patches
> > +
> > +   local d applied
> > +   # possibilities:
> > +   # 1. ${CATEGORY}/${P}-${PR} (note: -r0 desired to avoid applying
> > +   #${P} twice)
> > +   # 2. ${CATEGORY}/${P}
> > +   # 3. ${CATEGORY}/${PN}
> > +   # all of the above may be optionally followed by a slot
> > +   for d in 
> > "${basedir}"/${CATEGORY}/{${P}-${PR},${P},${PN}}{,:${SLOT%/*}}; do
> > +   if [[ -d ${d} ]]; then
> > +   eapply "${d}"
> > +   applied=1
> 
> I think it should break out of the loop here, like epatch_user does.

As the comment above suggests, it was intentional that all directories
are used.

> It doesn't make sense to apply more-specific patches before
> less-specific patches, does it?

Maybe. It would probably be most reasonable to sort them all by
filename, and apply in that order. Also allowing patch with the same
filename to override/skip patch from less specific directory.

> Maybe we can just treat this as a bug fix? Is anyone relying on the
> multiple directory usage?

That sounds like a major behavior change for a 'fix'. I'm using multiple
directories though it's all pretty much a workaround solution, so I
guess it doesn't matter if we keep it stable.

> 
> > +   fi
> > +   done
> > +
> > +   [[ -n ${applied} ]] && ewarn "User patches applied."
> > +   }
> > +fi
> > +
> >  if ___eapi_has_master_repositories; then
> > master_repositories() {
> > local output repository=$1 retval
> > 
> 
> 

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCH 1/3] repoman: Sort deprecated eclasses

2017-02-22 Thread Michał Górny
---
 repoman/pym/repoman/modules/scan/ebuild/checks.py | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py 
b/repoman/pym/repoman/modules/scan/ebuild/checks.py
index 15e225156..286021524 100644
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ b/repoman/pym/repoman/modules/scan/ebuild/checks.py
@@ -416,19 +416,19 @@ class InheritDeprecated(LineCheck):
"base": False,
"bash-completion": "bash-completion-r1",
"boost-utils": False,
+   "clutter": "gnome2",
"distutils": "distutils-r1",
"games": False,
"gems": "ruby-fakegem",
-   "mono": "mono-env",
-   "python": "python-r1 / python-single-r1 / python-any-r1",
-   "ruby": "ruby-ng",
-   "x-modular": "xorg-2",
"gst-plugins-bad": "gstreamer",
"gst-plugins-base": "gstreamer",
"gst-plugins-good": "gstreamer",
"gst-plugins-ugly": "gstreamer",
"gst-plugins10": "gstreamer",
-   "clutter": "gnome2",
+   "mono": "mono-env",
+   "python": "python-r1 / python-single-r1 / python-any-r1",
+   "ruby": "ruby-ng",
+   "x-modular": "xorg-2",
}
 
_inherit_re = re.compile(r'^\s*inherit\s(.*)$')
-- 
2.11.1




[gentoo-portage-dev] [PATCH 3/3] repoman: Deprecate confutils.eclass

2017-02-22 Thread Michał Górny
---
 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py 
b/repoman/pym/repoman/modules/scan/ebuild/checks.py
index d091a92b7..06afad5f7 100644
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ b/repoman/pym/repoman/modules/scan/ebuild/checks.py
@@ -417,6 +417,7 @@ class InheritDeprecated(LineCheck):
"bash-completion": "bash-completion-r1",
"boost-utils": False,
"clutter": "gnome2",
+   "confutils": False,
"distutils": "distutils-r1",
"games": False,
"gems": "ruby-fakegem",
-- 
2.11.1




[gentoo-portage-dev] [PATCH 2/3] repoman: Deprecate gpe.eclass

2017-02-22 Thread Michał Górny
---
 repoman/pym/repoman/modules/scan/ebuild/checks.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/repoman/pym/repoman/modules/scan/ebuild/checks.py 
b/repoman/pym/repoman/modules/scan/ebuild/checks.py
index 286021524..d091a92b7 100644
--- a/repoman/pym/repoman/modules/scan/ebuild/checks.py
+++ b/repoman/pym/repoman/modules/scan/ebuild/checks.py
@@ -420,6 +420,7 @@ class InheritDeprecated(LineCheck):
"distutils": "distutils-r1",
"games": False,
"gems": "ruby-fakegem",
+   "gpe": False,
"gst-plugins-bad": "gstreamer",
"gst-plugins-base": "gstreamer",
"gst-plugins-good": "gstreamer",
-- 
2.11.1




Re: [gentoo-portage-dev] [PATCH 3/3] repoman: Deprecate confutils.eclass

2017-02-22 Thread Michał Górny
W dniu 22.02.2017, śro o godzinie 01∶15 -0800, użytkownik Zac Medico
napisał:
> This whole series looks good.

Pushed, thanks.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCH 2/3] checksum: Remove redundant internal fallbacks

2017-02-28 Thread Michał Górny
Remove the internal digest fallbacks since they have no real use
nowadays. The hashlib versions are preferred later in the logic anyway,
and they are available since Python 2.5.
---
 pym/portage/checksum.py | 19 ++-
 1 file changed, 2 insertions(+), 17 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 319252315..8b4d96e30 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -18,8 +18,8 @@ import tempfile
 # most preferred first. Please keep this in sync with logic below.
 # 
 #
-# MD5: python-fchksum, hashlib, mhash, hashlib/md5
-# SHA1: hashlib, mhash, hashlib/sha1
+# MD5: python-fchksum, hashlib, mhash
+# SHA1: hashlib, mhash
 # SHA256: hashlib, pycrypto, mhash
 # SHA512: hashlib, mhash
 # RMD160: hashlib, pycrypto, mhash
@@ -77,21 +77,6 @@ class _generate_hash_function(object):
 # Define hash functions, try to use the best module available. Later 
definitions
 # override earlier ones
 
-# Use the internal modules as last fallback
-try:
-   from hashlib import md5 as _new_md5
-except ImportError:
-   from md5 import new as _new_md5
-
-md5hash = _generate_hash_function("MD5", _new_md5, origin="internal")
-
-try:
-   from hashlib import sha1 as _new_sha1
-except ImportError:
-   from sha import new as _new_sha1
-
-sha1hash = _generate_hash_function("SHA1", _new_sha1, origin="internal")
-
 # Try to use mhash if available
 # mhash causes GIL presently, so it gets less priority than hashlib and
 # pycrypto. However, it might be the only accelerated implementation of
-- 
2.12.0




[gentoo-portage-dev] [PATCH 1/3] checksum: Add summary on top to help following the logic

2017-02-28 Thread Michał Górny
Add a summary of all supported digest algorithms on top of the file
along with the supported implementations and their order of preference.
This will help people follow the crazy logic below.
---
 pym/portage/checksum.py | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index cdf467003..319252315 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -1,5 +1,5 @@
 # checksum.py -- core Portage functionality
-# Copyright 1998-2014 Gentoo Foundation
+# Copyright 1998-2017 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 import portage
@@ -13,6 +13,19 @@ import stat
 import subprocess
 import tempfile
 
+
+# Summary of all available hashes and their implementations,
+# most preferred first. Please keep this in sync with logic below.
+# 
+#
+# MD5: python-fchksum, hashlib, mhash, hashlib/md5
+# SHA1: hashlib, mhash, hashlib/sha1
+# SHA256: hashlib, pycrypto, mhash
+# SHA512: hashlib, mhash
+# RMD160: hashlib, pycrypto, mhash
+# WHIRLPOOL: hashlib, mhash, bundled
+
+
 #dict of all available hash functions
 hashfunc_map = {}
 hashorigin_map = {}
-- 
2.12.0




[gentoo-portage-dev] [PATCHES] Little cleanup of checksum + BLAKE2*/SHA3

2017-02-28 Thread Michał Górny
Hi,

Here's a quick set of patches to the checksum module:

1) adds a summary table on top to ease the reading of the horrible code
   below,

2) removes dead fallbacks for md5/sha1 that apply only to py<2.5,

3) adds BLAKE2b/s and SHA3 hashes available in Python 3.6+.

Sadly, I wasn't able to find any other (fallback) Python provider
of the latter at the moment, so it will take a while before we can start
using it anywhere.

--
Best regards,
Michał Górny




[gentoo-portage-dev] [PATCH 3/3] checksum: Add blake2* and sha3 hashes from hashlib 3.6+

2017-02-28 Thread Michał Górny
Add initial support for using the new SHA3_256 and SHA3_512, as well
as competetive BLAKE2b and BLAKE2s hashes that are now provided
in hashlib module of Python 3.6.
---
 pym/portage/checksum.py | 14 +-
 pym/portage/const.py|  6 ++
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 8b4d96e30..a46b820af 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -24,6 +24,10 @@ import tempfile
 # SHA512: hashlib, mhash
 # RMD160: hashlib, pycrypto, mhash
 # WHIRLPOOL: hashlib, mhash, bundled
+# BLAKE2B (512): hashlib (3.6+)
+# BLAKE2S (512): hashlib (3.6+)
+# SHA3_256: hashlib (3.6+)
+# SHA3_512: hashlib (3.6+)
 
 
 #dict of all available hash functions
@@ -121,7 +125,15 @@ try:
sha1hash = _generate_hash_function("SHA1", hashlib.sha1, 
origin="hashlib")
sha256hash = _generate_hash_function("SHA256", hashlib.sha256, 
origin="hashlib")
sha512hash = _generate_hash_function("SHA512", hashlib.sha512, 
origin="hashlib")
-   for local_name, hash_name in (("rmd160", "ripemd160"), ("whirlpool", 
"whirlpool")):
+   for local_name, hash_name in (
+   ("rmd160", "ripemd160"),
+   ("whirlpool", "whirlpool"),
+   # available since Python 3.6
+   ("BLAKE2B", "blake2b"),
+   ("BLAKE2S", "blake2s"),
+   ("SHA3_256", "sha3_256"),
+   ("SHA3_512", "sha3_512"),
+   ):
try:
hashlib.new(hash_name)
except ValueError:
diff --git a/pym/portage/const.py b/pym/portage/const.py
index 179efce98..0cef2e8ae 100644
--- a/pym/portage/const.py
+++ b/pym/portage/const.py
@@ -224,9 +224,6 @@ MANIFEST1_REQUIRED_HASH  = "MD5"
 # - Set manifest-hashes in gentoo-x86/metadata/layout.conf as follows:
 # manifest-hashes = SHA512 WHIRLPOOL
 #
-# After SHA-3 is approved:
-# - Add new hashes to MANIFEST2_HASH_*.
-#
 # After SHA-3 is supported in stable portage:
 # - Set manifest-hashes in gentoo-x86/metadata/layout.conf as follows:
 # manifest-hashes = SHA3 SHA512 WHIRLPOOL
@@ -234,7 +231,8 @@ MANIFEST1_REQUIRED_HASH  = "MD5"
 # After layout.conf settings correspond to defaults in stable portage:
 # - Remove redundant settings from gentoo-x86/metadata/layout.conf.
 
-MANIFEST2_HASH_FUNCTIONS = ("SHA256", "SHA512", "WHIRLPOOL")
+MANIFEST2_HASH_FUNCTIONS = ("SHA256", "SHA512", "WHIRLPOOL",
+   "BLAKE2B", "BLAKE2S", "SHA3_256", "SHA3_512")
 MANIFEST2_HASH_DEFAULTS = frozenset(["SHA256", "SHA512", "WHIRLPOOL"])
 MANIFEST2_REQUIRED_HASH  = "SHA256"
 
-- 
2.12.0




Re: [gentoo-portage-dev] [PATCH 2/3] checksum: Remove redundant internal fallbacks

2017-02-28 Thread Michał Górny
W dniu 28.02.2017, wto o godzinie 10∶01 +0100, użytkownik Michał Górny
napisał:
> Remove the internal digest fallbacks since they have no real use
> nowadays. The hashlib versions are preferred later in the logic anyway,
> and they are available since Python 2.5.
> ---
>  pym/portage/checksum.py | 19 ++-
>  1 file changed, 2 insertions(+), 17 deletions(-)
> 
> diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
> index 319252315..8b4d96e30 100644
> --- a/pym/portage/checksum.py
> +++ b/pym/portage/checksum.py
> @@ -18,8 +18,8 @@ import tempfile
>  # most preferred first. Please keep this in sync with logic below.
>  # 
>  #
> -# MD5: python-fchksum, hashlib, mhash, hashlib/md5
> -# SHA1: hashlib, mhash, hashlib/sha1
> +# MD5: python-fchksum, hashlib, mhash
> +# SHA1: hashlib, mhash
>  # SHA256: hashlib, pycrypto, mhash
>  # SHA512: hashlib, mhash
>  # RMD160: hashlib, pycrypto, mhash
> @@ -77,21 +77,6 @@ class _generate_hash_function(object):
>  # Define hash functions, try to use the best module available. Later 
> definitions
>  # override earlier ones
>  
> -# Use the internal modules as last fallback
> -try:
> - from hashlib import md5 as _new_md5
> -except ImportError:
> - from md5 import new as _new_md5

Ok, I see it now that there's still some dead code in Portage
referencing the _new_md5 thingy directly. I'll look into fixing that.

> -
> -md5hash = _generate_hash_function("MD5", _new_md5, origin="internal")
> -
> -try:
> - from hashlib import sha1 as _new_sha1
> -except ImportError:
> - from sha import new as _new_sha1
> -
> -sha1hash = _generate_hash_function("SHA1", _new_sha1, origin="internal")
> -
>  # Try to use mhash if available
>  # mhash causes GIL presently, so it gets less priority than hashlib and
>  # pycrypto. However, it might be the only accelerated implementation of

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCHES] Fix md5 refs in vartree

2017-02-28 Thread Michał Górny
Hi,

Here's a prequel to my other patch set. It cleans up the use of MD5
in vartree.

Currently, MD5 is loaded from three different locations -- most of
merging code uses portage.checksum high-level functions, one bit uses
implementation detail of portage.checksum and one bit imports hashlib
directly.

I've replaced the use of portage.checksum implementation detail with
another use of hashlib, and removed the compatibility for Python < 2.5.
I think it's a reasonable temporary measure until someone on friend
terms with the code reworks it not to use MD5.

--
Best regards,
Michał Górny




[gentoo-portage-dev] [PATCH 1/2] vartree: Use hashlib lazy-import, kill py<2.5 compat

2017-02-28 Thread Michał Górny
---
 pym/portage/dbapi/vartree.py | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 5053801e6..2a612d162 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -1,4 +1,4 @@
-# Copyright 1998-2014 Gentoo Foundation
+# Copyright 1998-2017 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
 
 from __future__ import division, unicode_literals
@@ -9,6 +9,7 @@ __all__ = [
 
 import portage
 portage.proxy.lazyimport.lazyimport(globals(),
+   'hashlib:md5',
'portage.checksum:_perform_md5_merge@perform_md5',
'portage.data:portage_gid,portage_uid,secpass',
'portage.dbapi.dep_expand:dep_expand',
@@ -1118,11 +1119,7 @@ class vardbapi(dbapi):
packages that own it. This is used to optimize owner lookups
by narrowing the search down to a smaller number of packages.
"""
-   try:
-   from hashlib import md5 as _new_hash
-   except ImportError:
-   from md5 import new as _new_hash
-
+   _new_hash = md5
_hash_bits = 16
_hex_chars = _hash_bits // 4
 
-- 
2.12.0




[gentoo-portage-dev] [PATCH 2/2] vartree: Replace uses of internal portage.checksum._new_md5 var

2017-02-28 Thread Michał Górny
Use the public hashlib.md5 method that is required for other code in
the module already.
---
 pym/portage/dbapi/vartree.py | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 2a612d162..c421dc50b 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -4690,8 +4690,7 @@ class dblink(object):
os.unlink(mysrc)
os.symlink(myto, mysrc)
 
-   mymd5 = portage.checksum._new_md5(
-   _unicode_encode(myto)).hexdigest()
+   mymd5 = md5(_unicode_encode(myto)).hexdigest()
 
protected = False
if stat.S_ISLNK(mymode) or stat.S_ISREG(mymode):
@@ -4725,8 +4724,7 @@ class dblink(object):
# of the link target path 
string is used
# for cfgfiledict (symlinks are
# protected since bug #485598).
-   destmd5 = 
portage.checksum._new_md5(
-   
_unicode_encode(mydest_link)).hexdigest()
+   destmd5 = 
md5(_unicode_encode(mydest_link)).hexdigest()
 
elif stat.S_ISREG(mydmode):
destmd5 = perform_md5(mydest,
-- 
2.12.0




[gentoo-portage-dev] [PATCH 1/2] checksum: Fix overriding fallbacks on broken pycrypto

2017-02-28 Thread Michał Górny
The pycrypto override used the same variables as actual hash functions
before determining whether its functions are useful. As a result, if
pycrypto had a broken module and no hash function was generated,
the possible previous implementation was replaced by None.
---
 pym/portage/checksum.py | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index a46b820af..fc38417a7 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -105,14 +105,14 @@ except ImportError:
 # is broken somehow.
 try:
from Crypto.Hash import SHA256, RIPEMD
-   sha256hash = getattr(SHA256, 'new', None)
-   if sha256hash is not None:
+   sha256hash_ = getattr(SHA256, 'new', None)
+   if sha256hash_ is not None:
sha256hash = _generate_hash_function("SHA256",
-   sha256hash, origin="pycrypto")
-   rmd160hash = getattr(RIPEMD, 'new', None)
-   if rmd160hash is not None:
+   sha256hash_, origin="pycrypto")
+   rmd160hash_ = getattr(RIPEMD, 'new', None)
+   if rmd160hash_ is not None:
rmd160hash = _generate_hash_function("RMD160",
-   rmd160hash, origin="pycrypto")
+   rmd160hash_, origin="pycrypto")
 except ImportError:
pass
 
-- 
2.12.0




[gentoo-portage-dev] [PATCH 2/2] checksum: Add pycryptodome fallbacks for SHA3 and BLAKE2

2017-02-28 Thread Michał Górny
---
 pym/portage/checksum.py | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index fc38417a7..042a0a745 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -116,6 +116,28 @@ try:
 except ImportError:
pass
 
+try:
+   # added in pycryptodome
+   from Crypto.Hash import BLAKE2b, BLAKE2s, SHA3_256, SHA3_512
+   blake2bhash_ = getattr(BLAKE2b, 'new', None)
+   if blake2bhash_ is not None:
+   blake2bhash = _generate_hash_function("BLAKE2B",
+   blake2bhash_, origin="pycrypto")
+   blake2shash_ = getattr(BLAKE2s, 'new', None)
+   if blake2shash_ is not None:
+   blake2shash = _generate_hash_function("BLAKE2S",
+   blake2shash_, origin="pycrypto")
+   sha3_256hash_ = getattr(SHA3_256, 'new', None)
+   if sha3_256hash_ is not None:
+   sha3_256hash = _generate_hash_function("SHA3_256",
+   sha3_256hash_, origin="pycrypto")
+   sha3_512hash_ = getattr(SHA3_512, 'new', None)
+   if sha3_512hash_ is not None:
+   sha3_512hash = _generate_hash_function("SHA3_512",
+   sha3_512hash_, origin="pycrypto")
+except ImportError:
+   pass
+
 # Use hashlib from python-2.5 if available and prefer it over pycrypto and 
internal fallbacks.
 # Need special handling for RMD160/WHIRLPOOL as they may not always be 
provided by hashlib.
 try:
-- 
2.12.0




Re: [gentoo-portage-dev] [PATCHES] Fix md5 refs in vartree

2017-03-01 Thread Michał Górny
W dniu 28.02.2017, wto o godzinie 11∶03 -0800, użytkownik Zac Medico
napisał:
> On 02/28/2017 02:12 AM, Michał Górny wrote:
> > Hi,
> > 
> > Here's a prequel to my other patch set. It cleans up the use of MD5
> > in vartree.
> > 
> > Currently, MD5 is loaded from three different locations -- most of
> > merging code uses portage.checksum high-level functions, one bit uses
> > implementation detail of portage.checksum and one bit imports hashlib
> > directly.
> > 
> > I've replaced the use of portage.checksum implementation detail with
> > another use of hashlib, and removed the compatibility for Python < 2.5.
> > I think it's a reasonable temporary measure until someone on friend
> > terms with the code reworks it not to use MD5.
> > 
> > --
> > Best regards,
> > Michał Górny
> > 
> > 
> 
> Both series look good to me.

Thanks. Merged both yesterday.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH 1/2] checksum: Fix overriding fallbacks on broken pycrypto

2017-03-01 Thread Michał Górny
W dniu 28.02.2017, wto o godzinie 23∶57 -0800, użytkownik Zac Medico
napisał:
> On 02/28/2017 11:34 PM, Michał Górny wrote:
> > The pycrypto override used the same variables as actual hash functions
> > before determining whether its functions are useful. As a result, if
> > pycrypto had a broken module and no hash function was generated,
> > the possible previous implementation was replaced by None.
> > ---
> >  pym/portage/checksum.py | 12 ++--
> >  1 file changed, 6 insertions(+), 6 deletions(-)
> > 
> > diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
> > index a46b820af..fc38417a7 100644
> > --- a/pym/portage/checksum.py
> > +++ b/pym/portage/checksum.py
> > @@ -105,14 +105,14 @@ except ImportError:
> >  # is broken somehow.
> >  try:
> > from Crypto.Hash import SHA256, RIPEMD
> > -   sha256hash = getattr(SHA256, 'new', None)
> > -   if sha256hash is not None:
> > +   sha256hash_ = getattr(SHA256, 'new', None)
> > +   if sha256hash_ is not None:
> > sha256hash = _generate_hash_function("SHA256",
> > -   sha256hash, origin="pycrypto")
> > -   rmd160hash = getattr(RIPEMD, 'new', None)
> > -   if rmd160hash is not None:
> > +   sha256hash_, origin="pycrypto")
> > +   rmd160hash_ = getattr(RIPEMD, 'new', None)
> > +   if rmd160hash_ is not None:
> > rmd160hash = _generate_hash_function("RMD160",
> > -   rmd160hash, origin="pycrypto")
> > +   rmd160hash_, origin="pycrypto")
> >  except ImportError:
> > pass
> >  
> > 
> 
> Looks good.

Thanks. Merged both patches.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH] movefile: support in-kernel file copying on Linux (bug 607868)

2017-03-02 Thread Michał Górny
copying. There is an implicit hole at the
> + * end of the file.
> + */
> +offset_hole = lseek(fd_in, offset_data, SEEK_HOLE);
> +if (offset_hole < 0) {
> +error = 1;
> +break;
> +}
> +
> +/* Revert SEEK_HOLE offset change, since we're going
> + * to copy the data that comes before the hole.
> + */
> +if (lseek(fd_in, offset_out, SEEK_SET) < 0) {
> +error = 1;
> +break;
> +}
> +
> +copyfunc_ret = copyfunc(fd_out,
> +fd_in,
> +&offset_out,
> +offset_hole - offset_data);
> +
> +if (copyfunc_ret < 0) {
> +if ((errno == EXDEV || errno == ENOSYS) &&
> +copyfunc == cfr_wrapper) {
> +/* Use sendfile instead of copy_file_range for
> + * cross-device copies, or when the copy_file_range
> + * syscall is not available (less than Linux 4.5).
> + */
> +copyfunc = sendfile;
> +copyfunc_ret = copyfunc(fd_out,
> +fd_in,
> +&offset_out,
> +offset_hole - offset_data);
> +
> +if (copyfunc_ret < 0) {

I think you still should have a proper fallback for sendfile() refusing
to do its job.

> +error = 1;
> +break;
> +}
> +}
> +else {
> +error = 1;
> +break;
> +        }
> +}
> +}
> +#else
> +/* Less than Linux 3.1 does not support SEEK_DATA or copy_file_range,
> + * so just use sendfile for in-kernel copy. This will fail for Linux
> + * versions from 2.6.0 to 2.6.32, because sendfile does not support
> + * writing to regular files. The caller should perform a runtime
> + * test to verify that this function works with the running kernel.
> + */
> +struct stat sb;
> +int stat_acquired;
> +
> +if (!PyArg_ParseTuple(args, "ii", &fd_in, &fd_out))
> +return NULL;
> +
> +eintr_retry = 1;
> +offset_out = 0;
> +stat_acquired = 0;
> +
> +while (eintr_retry) {
> +
> +error = 0;
> +
> +Py_BEGIN_ALLOW_THREADS
> +
> +if (!stat_acquired && fstat(fd_in, &sb) < 0) {
> +error = 1;
> +}
> +else {
> +stat_acquired = 1;
> +while (offset_out < sb.st_size) {
> +copyfunc_ret = sendfile(fd_out,
> +fd_in,
> +&offset_out,
> +sb.st_size - offset_out);
> +
> +if (copyfunc_ret < 0) {

Likewise, especially that old kernels may refuse file-to-file copy here.

> +error = 1;
> +break;
> +}
> +}
> +}
> +#endif
> +Py_END_ALLOW_THREADS
> +
> +if (!(error && errno == EINTR && PyErr_CheckSignals() == 0))
> +eintr_retry = 0;
> +}
> +
> +if (error)
> +return PyErr_SetFromErrno(PyExc_OSError);
> +
> +return Py_BuildValue("i", offset_out);
> +}

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH v2] movefile: support in-kernel file copying on Linux (bug 607868)

2017-03-03 Thread Michał Górny
 +if (errno == EINVAL && !offset_out) {
> +lseek_works = 0;
> +}
> +error = 1;
> +break;
> +}
> +
> +copyfunc_ret = copyfunc(fd_out,
> +fd_in,
> +&offset_out,
> +len);
> +
> +if (copyfunc_ret < 0) {
> +if ((errno == EXDEV || errno == ENOSYS) &&
> +copyfunc == cfr_wrapper) {
> +/* Use sendfile instead of copy_file_range for
> + * cross-device copies, or when the copy_file_range
> + * syscall is not available (less than Linux 4.5).
> + */
> +copyfunc = sendfile;
> +copyfunc_ret = copyfunc(fd_out,
> +fd_in,
> +&offset_out,
> +len);
> +
> +if (copyfunc_ret < 0) {
> +/* On Linux, if lseek succeeded above, then
> + * sendfile should have worked here too, so
> + * don't bother to fallback for EINVAL here.
> + */
> +error = 1;
> +break;
> +}
> +}
> +else {
> +error = 1;
> +break;
> +}
> +}
> +}
> +}
> +
> +/* Less than Linux 3.1 does not support SEEK_DATA or copy_file_range,
> + * so just use sendfile for in-kernel copy. This will fail for Linux
> + * versions from 2.6.0 to 2.6.32, because sendfile does not support
> + * writing to regular files.
> + */
> +if (sendfile_works && !lseek_works) {
> +error = 0;
> +
> +if (!stat_in_acquired && fstat(fd_in, &stat_in) < 0) {
> +error = 1;
> +}
> +else {
> +stat_in_acquired = 1;
> +while (offset_out < stat_in.st_size) {
> +copyfunc_ret = sendfile(fd_out,
> +fd_in,
> +&offset_out,
> +stat_in.st_size - offset_out);
> +
> +if (copyfunc_ret < 0) {
> +if (errno == EINVAL && !offset_out) {
> +sendfile_works = 0;
> +}
> +error = 1;
> +break;
> +}
> +}
> +}
> +}
> +
> +/* This implementation will work on any kernel. */
> +if (!sendfile_works) {
> +error = 0;
> +
> +if (!stat_out_acquired && fstat(fd_in, &stat_out) < 0) {
> +error = 1;
> +}
> +else {
> +stat_out_acquired = 1;
> +if (buf == NULL)
> +buf = malloc(stat_out.st_blksize);
> +if (buf == NULL) {
> +error = 1;
> +}
> +else {
> +while (1) {
> +/* Some bytes may still be buffered from the
> + * previous iteration of the outer loop.
> + */
> +if (!buf_bytes) {
> +buf_offset = 0;
> +buf_bytes = read(fd_in, buf, 
> stat_out.st_blksize);
> +
> +if (!buf_bytes) {
> +/* EOF */
> +break;
> +}
> +else if (buf_bytes < 0) {
> +error = 1;
> +break;
> +}
> +}
> +
> +copyfunc_ret = write(fd_out, buf + buf_offset, 
> buf_bytes);
> +if (copyfunc_ret < 0) {
> +error = 1;
> +break;
> +}
> +
> +buf_bytes -= copyfunc_ret;
> +buf_offset += copyfunc_ret;
> +}
> +}
> +}
> +}
> +
> +Py_END_ALLOW_THREADS
> +
> +if (!(error && errno == EINTR && PyErr_CheckSignals() == 0))
> +eintr_retry = 0;

To be honest, I can't do it but it'd be really a good idea if someone
could analyze all the code paths where the code above could give 'error
= 1' and ensure that:

a. there is no case when we error=1 and leave errno unmodified/unset
(i.e. can accidentally leave earlier EINTR there),

b. we can correctly recover from any EINTR, i.e. if EINTR causes some
function to be interrupted in the middle, our next iteration starts
safely.

> +}
> +
> +free(buf);

if (buf != NULL) ?

> +
> +if (error)
> +return PyErr_SetFromErrno(PyExc_OSError);
> +
> +return Py_BuildValue("i", offset_out);
> +}

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH] emerge: auto-enable --with-bdeps if --usepkg is not enabled (bug 598444)

2017-03-04 Thread Michał Górny
W dniu 04.03.2017, sob o godzinie 01∶34 -0800, użytkownik Zac Medico
napisał:
> It's useful to enable --with-bdeps by default so that @world updates
> will update all packages that are not eligible for removal by
> emerge --depclean. However, many users of binary packages do not want
> unnecessary build time dependencies installed, therefore do not
> auto-enable --with-bdeps for installation actions when the --usepkg
> option is enabled.
> 
> X-Gentoo-bug: 598444
> X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=598444
> ---
>  man/emerge.1 |  18 ++-
>  pym/_emerge/create_depgraph_params.py|   4 +
>  pym/_emerge/depgraph.py  |   4 +-
>  pym/portage/tests/resolver/ResolverPlayground.py |   5 +
>  pym/portage/tests/resolver/test_bdeps.py | 197 
> +++
>  5 files changed, 223 insertions(+), 5 deletions(-)
>  create mode 100644 pym/portage/tests/resolver/test_bdeps.py

Just to be clear, this will break stuff for people who have more than
one slot of LLVM enabled since different slots build-depend on colliding
packages.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


Re: [gentoo-portage-dev] [PATCH] emerge: auto-enable --with-bdeps if --usepkg is not enabled (bug 598444)

2017-03-04 Thread Michał Górny
W dniu 04.03.2017, sob o godzinie 02∶30 -0800, użytkownik Zac Medico
napisał:
> On 03/04/2017 01:59 AM, Michał Górny wrote:
> > W dniu 04.03.2017, sob o godzinie 01∶34 -0800, użytkownik Zac Medico
> > napisał:
> > > It's useful to enable --with-bdeps by default so that @world updates
> > > will update all packages that are not eligible for removal by
> > > emerge --depclean. However, many users of binary packages do not want
> > > unnecessary build time dependencies installed, therefore do not
> > > auto-enable --with-bdeps for installation actions when the --usepkg
> > > option is enabled.
> > > 
> > > X-Gentoo-bug: 598444
> > > X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=598444
> > > ---
> > >  man/emerge.1 |  18 ++-
> > >  pym/_emerge/create_depgraph_params.py|   4 +
> > >  pym/_emerge/depgraph.py  |   4 +-
> > >  pym/portage/tests/resolver/ResolverPlayground.py |   5 +
> > >  pym/portage/tests/resolver/test_bdeps.py | 197 
> > > +++
> > >  5 files changed, 223 insertions(+), 5 deletions(-)
> > >  create mode 100644 pym/portage/tests/resolver/test_bdeps.py
> > 
> > Just to be clear, this will break stuff for people who have more than
> > one slot of LLVM enabled since different slots build-depend on colliding
> > packages.
> 
> Hmm, that's unfortunate, because putting --with-bdeps=n in
> EMERGE_DEFAULT_OPTS is not good for --depclean. I'll have to think about
> a better way to handle this case. We've already got a bug open for this
> sort of situation here:
> 
> https://bugs.gentoo.org/show_bug.cgi?id=427938

Eventually I want to try to accept more lit versions for LLVM. However,
it kinda fails when LLVM upgrades gtest and lit is bound to a specific
output.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCHES] Checksums pt. 3 -- one more fallback for SHA3

2017-03-12 Thread Michał Górny
Hi,

Just a quick patchset fixing fallback doc and adding pysha3 support.
Next time, I'll probably replace the whole horrible fallback logic there
with something cleaner (and lazy).

--
Best regards,
Michał Górny




[gentoo-portage-dev] [PATCH 2/2] portage.checksum: Support pysha3 fallback for SHA3

2017-03-12 Thread Michał Górny
pysha3 provides a stand-alone FIPS-compliant SHA3 implementation that
can be used as a fallback for Python < 3.6.
---
 pym/portage/checksum.py | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index ac11d3f4b..3e61acdec 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -10,6 +10,7 @@ from portage import _encodings
 from portage import _unicode_decode, _unicode_encode
 import errno
 import stat
+import sys
 import subprocess
 import tempfile
 
@@ -26,8 +27,8 @@ import tempfile
 # WHIRLPOOL: hashlib, mhash, bundled
 # BLAKE2B (512): hashlib (3.6+), pycrypto
 # BLAKE2S (512): hashlib (3.6+), pycrypto
-# SHA3_256: hashlib (3.6+), pycrypto
-# SHA3_512: hashlib (3.6+), pycrypto
+# SHA3_256: hashlib (3.6+), pysha3, pycrypto
+# SHA3_512: hashlib (3.6+), pysha3, pycrypto
 
 
 #dict of all available hash functions
@@ -138,6 +139,15 @@ try:
 except ImportError:
pass
 
+# Support using pysha3 as fallback for python<3.6
+try:
+   import sha3
+
+   sha3_256hash = _generate_hash_function("SHA3_256", sha3.sha3_256, 
origin="pysha3")
+   sha3_512hash = _generate_hash_function("SHA3_512", sha3.sha3_512, 
origin="pysha3")
+except ImportError:
+   pass
+
 # Use hashlib from python-2.5 if available and prefer it over pycrypto and 
internal fallbacks.
 # Need special handling for RMD160/WHIRLPOOL as they may not always be 
provided by hashlib.
 try:
-- 
2.12.0




[gentoo-portage-dev] [PATCH 1/2] portage.checksum: Update fallback doc for SHA3/BLAKE2*

2017-03-12 Thread Michał Górny
---
 pym/portage/checksum.py | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 042a0a745..ac11d3f4b 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -24,10 +24,10 @@ import tempfile
 # SHA512: hashlib, mhash
 # RMD160: hashlib, pycrypto, mhash
 # WHIRLPOOL: hashlib, mhash, bundled
-# BLAKE2B (512): hashlib (3.6+)
-# BLAKE2S (512): hashlib (3.6+)
-# SHA3_256: hashlib (3.6+)
-# SHA3_512: hashlib (3.6+)
+# BLAKE2B (512): hashlib (3.6+), pycrypto
+# BLAKE2S (512): hashlib (3.6+), pycrypto
+# SHA3_256: hashlib (3.6+), pycrypto
+# SHA3_512: hashlib (3.6+), pycrypto
 
 
 #dict of all available hash functions
-- 
2.12.0




[gentoo-portage-dev] [PATCH 04/14] portage.checksum: Support getting byte string checksums

2017-03-12 Thread Michał Górny
Add a checksum_str() method to Portage hashes and a matching function to
make it possible to compute checksums of arbitrary bytestrings rather
than just files.
---
 pym/portage/checksum.py | 29 +
 1 file changed, 29 insertions(+)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 67d6a544f..9ba251f29 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -59,6 +59,18 @@ class _generate_hash_function(object):
hashfunc_map[hashtype] = self
hashorigin_map[hashtype] = origin
 
+   def checksum_str(self, data):
+   """
+   Obtain a checksum of a byte-string.
+
+   @param data: Data to hash
+   @type data: bytes
+   @return: The hash of the data (hex-digest)
+   """
+   checksum = self._hashobject()
+   checksum.update(data)
+   return checksum.hexdigest()
+
def checksum_file(self, filename):
"""
Run a checksum against a file.
@@ -461,3 +473,20 @@ def perform_multiple_checksums(filename, hashes=["MD5"], 
calc_prelink=0):
raise portage.exception.DigestException(x+" hash 
function not available (needs dev-python/pycrypto or >=dev-lang/python-2.5)")
rVal[x] = perform_checksum(filename, x, calc_prelink)[0]
return rVal
+
+
+def checksum_str(data, hashname="MD5"):
+   """
+   Run a specific checksum against a byte string.
+
+   @param filename: Data to checksum
+   @type filename: Bytes
+   @param hashname: The type of hash function to run
+   @type hashname: String
+   @rtype: String
+   @return: The hash (hex-digest) of the data
+   """
+   if hashname not in hashfunc_map:
+   raise portage.exception.DigestException(hashname + \
+   " hash function not available (needs 
dev-python/pycrypto)")
+   return hashfunc_map[hashname].checksum_str(data)
-- 
2.12.0




[gentoo-portage-dev] [PATCHES] portage.checksum hacking, pt. 4

2017-03-12 Thread Michał Górny
Hi,

Here's a huge batch of patches for portage.checksum and relevant stuff.
It's not a complete rewrite as I have originally planned, and it's still
not the code I'd like to see but functionally it has been improved a lot.

Notable changes:

1. Other modules no longer use hashfunc_map, now they use the public
functions instead.

2. A method to checksum byte strings (i.e. stuff in-memory) has been
added. For better compatibility, practically unused python-fchksum
support has been removed. [TODO: possibly port other uses of hashlib
in Portage?]

3. Tests for all hash functions have been added. This makes it possible
to verify that different implementations are working correctly. It is
especially important because some of the Keccak (SHA-3) implementations
are using pre-FIPS Keccak version. [TODO: make it possible to test
all available fallbacks, not only the used function]

4. Fallbacks have been reworked so that the relevant modules are loaded
only if a better implementation is not available already. Fallbacks for
functions that are guaranteed to be available in hashlib have been
removed.

5. Support using pygcrypt as provider of optimized hash function
fallbacks (for ripemd160, Whirlpool and SHA3).

6. Support for Streebog (GOST R 34.11-2012) hash algorithm, provided
either by pygcrypt or pure Python pygost module. [TODO: find a better
pure Python provider]

--
Best regards,
Michał Górny




[gentoo-portage-dev] [PATCH 02/14] portage.checksum: Remove python-fchksum support

2017-03-12 Thread Michał Górny
Remove the support for MD5 implementation from python-fchksum package.
The package is rarely installed, supports Python 2.7 only and the code
handles checksumming a whole file only.
---
 pym/portage/checksum.py | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 3e61acdec..9f88f7e65 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -19,7 +19,7 @@ import tempfile
 # most preferred first. Please keep this in sync with logic below.
 # 
 #
-# MD5: python-fchksum, hashlib, mhash
+# MD5: hashlib, mhash
 # SHA1: hashlib, mhash
 # SHA256: hashlib, pycrypto, mhash
 # SHA512: hashlib, mhash
@@ -186,15 +186,6 @@ if "WHIRLPOOL" not in hashfunc_map:
from portage.util.whirlpool import new as _new_whirlpool
whirlpoolhash = _generate_hash_function("WHIRLPOOL", _new_whirlpool, 
origin="bundled")
 
-# Use python-fchksum if available, prefer it over all other MD5 implementations
-try:
-   from fchksum import fmd5t as md5hash
-   hashfunc_map["MD5"] = md5hash
-   hashorigin_map["MD5"] = "python-fchksum"
-
-except ImportError:
-   pass
-
 # There is only one implementation for size
 def getsize(filename):
size = os.stat(filename).st_size
-- 
2.12.0




[gentoo-portage-dev] [PATCH 01/14] Use public API: hashfunc_map -> get_valid_checksum_keys()

2017-03-12 Thread Michał Górny
Use get_valid_checksum_keys() function instead of accessing hashfunc_map
directly throughout the Portage.
---
 pym/portage/_emirrordist/FetchTask.py |  2 +-
 pym/portage/dbapi/bintree.py  |  4 ++--
 pym/portage/eclass_cache.py   |  2 +-
 pym/portage/manifest.py   |  4 ++--
 pym/portage/package/ebuild/fetch.py   | 10 +-
 5 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/pym/portage/_emirrordist/FetchTask.py 
b/pym/portage/_emirrordist/FetchTask.py
index 64de67582..203b8c213 100644
--- a/pym/portage/_emirrordist/FetchTask.py
+++ b/pym/portage/_emirrordist/FetchTask.py
@@ -574,7 +574,7 @@ class FetchTask(CompositeTask):
else:
for hash_name in self.digests:
if hash_name != "size" and \
-   hash_name in 
portage.checksum.hashfunc_map:
+   hash_name in 
portage.checksum.get_valid_checksum_keys():
return hash_name
 
return None
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py
index ae9e7caa2..12c3d3e51 100644
--- a/pym/portage/dbapi/bintree.py
+++ b/pym/portage/dbapi/bintree.py
@@ -7,7 +7,7 @@ __all__ = ["bindbapi", "binarytree"]
 
 import portage
 portage.proxy.lazyimport.lazyimport(globals(),
-   'portage.checksum:hashfunc_map,perform_multiple_checksums,' + \
+   'portage.checksum:get_valid_checksum_keys,perform_multiple_checksums,' 
+ \
'verify_all,_apply_hash_filter,_hash_filter',
'portage.dbapi.dep_expand:dep_expand',
'portage.dep:dep_getkey,isjustname,isvalidatom,match_from_list',
@@ -1546,7 +1546,7 @@ class binarytree(object):
if metadata is None:
return digests
 
-   for k in hashfunc_map:
+   for k in get_valid_checksum_keys():
v = metadata.get(k)
if not v:
continue
diff --git a/pym/portage/eclass_cache.py b/pym/portage/eclass_cache.py
index 2988d25d6..d2d9e2710 100644
--- a/pym/portage/eclass_cache.py
+++ b/pym/portage/eclass_cache.py
@@ -48,7 +48,7 @@ class hashed_path(object):
# we don't care to allow .mD5 as an alias for .md5
raise AttributeError(attr)
hashname = attr.upper()
-   if hashname not in checksum.hashfunc_map:
+   if hashname not in checksum.get_valid_checksum_keys():
raise AttributeError(attr)
val = checksum.perform_checksum(self.location, hashname)[0]
setattr(self, attr, val)
diff --git a/pym/portage/manifest.py b/pym/portage/manifest.py
index 7278e21c1..28a77ba87 100644
--- a/pym/portage/manifest.py
+++ b/pym/portage/manifest.py
@@ -13,7 +13,7 @@ import warnings
 
 import portage
 portage.proxy.lazyimport.lazyimport(globals(),
-   'portage.checksum:hashfunc_map,perform_multiple_checksums,' + \
+   'portage.checksum:get_valid_checksum_keys,perform_multiple_checksums,' 
+ \
'verify_all,_apply_hash_filter,_filter_unaccelarated_hashes',
'portage.repository.config:_find_invalid_path_char',
'portage.util:write_atomic,writemsg_level',
@@ -154,7 +154,7 @@ class Manifest(object):
 

self.hashes.update(hashes.intersection(MANIFEST2_HASH_FUNCTIONS))
self.hashes.difference_update(hashname for hashname in \
-   list(self.hashes) if hashname not in hashfunc_map)
+   list(self.hashes) if hashname not in 
get_valid_checksum_keys())
self.hashes.add("size")
self.hashes.add(MANIFEST2_REQUIRED_HASH)
for t in MANIFEST2_IDENTIFIERS:
diff --git a/pym/portage/package/ebuild/fetch.py 
b/pym/portage/package/ebuild/fetch.py
index 8755b7522..5c4b74446 100644
--- a/pym/portage/package/ebuild/fetch.py
+++ b/pym/portage/package/ebuild/fetch.py
@@ -29,7 +29,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
 
 from portage import OrderedDict, os, selinux, shutil, _encodings, \
_shell_quote, _unicode_encode
-from portage.checksum import (hashfunc_map, perform_md5, verify_all,
+from portage.checksum import (get_valid_checksum_keys, perform_md5, verify_all,
_filter_unaccelarated_hashes, _hash_filter, _apply_hash_filter)
 from portage.const import BASH_BINARY, CUSTOM_MIRRORS_FILE, \
GLOBAL_CONFIG_PATH
@@ -551,6 +551,8 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
distdir_writable = can_fetch and not fetch_to_ro
failed_files = set()
restrict_fetch_msg = False
+   valid_hashes = frozenset(get_valid_checksum_keys())
+   valid_hashes.discard("size")
 
for myfile in filedict:
"""
@@ -564,11 +566,9 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0,
orig_digests = my

[gentoo-portage-dev] [PATCH 06/14] portage.checksum: Fix BLAKE2* fallbacks from pycryptodome

2017-03-12 Thread Michał Górny
Fix BLAKE2* fallback functions to explicitly provide digest length as
required by pycryptodome.
---
 pym/portage/checksum.py | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 9ba251f29..82e8bec00 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -132,14 +132,16 @@ except ImportError:
 try:
# added in pycryptodome
from Crypto.Hash import BLAKE2b, BLAKE2s, SHA3_256, SHA3_512
+   import functools
+
blake2bhash_ = getattr(BLAKE2b, 'new', None)
if blake2bhash_ is not None:
blake2bhash = _generate_hash_function("BLAKE2B",
-   blake2bhash_, origin="pycrypto")
+   functools.partial(blake2bhash_, digest_bytes=64), 
origin="pycrypto")
blake2shash_ = getattr(BLAKE2s, 'new', None)
if blake2shash_ is not None:
blake2shash = _generate_hash_function("BLAKE2S",
-   blake2shash_, origin="pycrypto")
+   functools.partial(blake2shash_, digest_bytes=32), 
origin="pycrypto")
sha3_256hash_ = getattr(SHA3_256, 'new', None)
if sha3_256hash_ is not None:
sha3_256hash = _generate_hash_function("SHA3_256",
-- 
2.12.0




[gentoo-portage-dev] [PATCH 03/14] portage.checksum: create explicit checksum_file() method

2017-03-12 Thread Michał Górny
Make the file checksum generation code use an explicit checksum_file()
method rather than implicit __call__. This should be more readable,
and make it cleanly possible to add more methods.
---
 pym/portage/checksum.py | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 9f88f7e65..67d6a544f 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -59,7 +59,7 @@ class _generate_hash_function(object):
hashfunc_map[hashtype] = self
hashorigin_map[hashtype] = origin
 
-   def __call__(self, filename):
+   def checksum_file(self, filename):
"""
Run a checksum against a file.

@@ -186,11 +186,14 @@ if "WHIRLPOOL" not in hashfunc_map:
from portage.util.whirlpool import new as _new_whirlpool
whirlpoolhash = _generate_hash_function("WHIRLPOOL", _new_whirlpool, 
origin="bundled")
 
+
 # There is only one implementation for size
-def getsize(filename):
-   size = os.stat(filename).st_size
-   return (size, size)
-hashfunc_map["size"] = getsize
+class SizeHash(object):
+   def checksum_file(self, filename):
+   size = os.stat(filename).st_size
+   return (size, size)
+
+hashfunc_map["size"] = SizeHash()
 
 # end actual hash functions
 
@@ -420,7 +423,7 @@ def perform_checksum(filename, hashname="MD5", 
calc_prelink=0):
if hashname not in hashfunc_map:
raise 
portage.exception.DigestException(hashname + \
" hash function not available (needs 
dev-python/pycrypto)")
-   myhash, mysize = hashfunc_map[hashname](myfilename)
+   myhash, mysize = 
hashfunc_map[hashname].checksum_file(myfilename)
except (OSError, IOError) as e:
if e.errno in (errno.ENOENT, errno.ESTALE):
raise portage.exception.FileNotFound(myfilename)
-- 
2.12.0




[gentoo-portage-dev] [PATCH 07/14] portage.checksum: Remove fallbacks for algorithms guaranteed since py2.7

2017-03-12 Thread Michał Górny
The MD5, SHA1 and SHA2 algorithms are guaranteed to be available in
hashlib for Python 2.7 and newer, making the fallbacks to other
implementations meaningless. Remove them to simplify the code.
---
 pym/portage/checksum.py | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 82e8bec00..7812791ad 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -19,10 +19,10 @@ import tempfile
 # most preferred first. Please keep this in sync with logic below.
 # 
 #
-# MD5: hashlib, mhash
-# SHA1: hashlib, mhash
-# SHA256: hashlib, pycrypto, mhash
-# SHA512: hashlib, mhash
+# MD5: hashlib
+# SHA1: hashlib
+# SHA256: hashlib
+# SHA512: hashlib
 # RMD160: hashlib, pycrypto, mhash
 # WHIRLPOOL: hashlib, mhash, bundled
 # BLAKE2B (512): hashlib (3.6+), pycrypto
@@ -100,10 +100,6 @@ class _generate_hash_function(object):
 # WHIRLPOOL available.
 try:
import mhash, functools
-   md5hash = _generate_hash_function("MD5", functools.partial(mhash.MHASH, 
mhash.MHASH_MD5), origin="mhash")
-   sha1hash = _generate_hash_function("SHA1", 
functools.partial(mhash.MHASH, mhash.MHASH_SHA1), origin="mhash")
-   sha256hash = _generate_hash_function("SHA256", 
functools.partial(mhash.MHASH, mhash.MHASH_SHA256), origin="mhash")
-   sha512hash = _generate_hash_function("SHA512", 
functools.partial(mhash.MHASH, mhash.MHASH_SHA512), origin="mhash")
for local_name, hash_name in (("rmd160", "ripemd160"), ("whirlpool", 
"whirlpool")):
if hasattr(mhash, 'MHASH_%s' % local_name.upper()):
globals()['%shash' % local_name] = \
@@ -117,11 +113,7 @@ except ImportError:
 # Check for 'new' attributes, since they can be missing if the module
 # is broken somehow.
 try:
-   from Crypto.Hash import SHA256, RIPEMD
-   sha256hash_ = getattr(SHA256, 'new', None)
-   if sha256hash_ is not None:
-   sha256hash = _generate_hash_function("SHA256",
-   sha256hash_, origin="pycrypto")
+   from Crypto.Hash import RIPEMD
rmd160hash_ = getattr(RIPEMD, 'new', None)
if rmd160hash_ is not None:
rmd160hash = _generate_hash_function("RMD160",
-- 
2.12.0




[gentoo-portage-dev] [PATCH 08/14] portage.checksum: Remove exception handling for missing hashlib

2017-03-12 Thread Michał Górny
Remove the try-except block for potential ImportError of hashlib.
The hashlib module should be available in all supported Python versions,
and we do not really test or support the case when it is not available.
---
 pym/portage/checksum.py | 55 ++---
 1 file changed, 25 insertions(+), 30 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 7812791ad..68ed44fa9 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -9,6 +9,8 @@ from portage import os
 from portage import _encodings
 from portage import _unicode_decode, _unicode_encode
 import errno
+import functools
+import hashlib
 import stat
 import sys
 import subprocess
@@ -99,7 +101,7 @@ class _generate_hash_function(object):
 # pycrypto. However, it might be the only accelerated implementation of
 # WHIRLPOOL available.
 try:
-   import mhash, functools
+   import mhash
for local_name, hash_name in (("rmd160", "ripemd160"), ("whirlpool", 
"whirlpool")):
if hasattr(mhash, 'MHASH_%s' % local_name.upper()):
globals()['%shash' % local_name] = \
@@ -124,7 +126,6 @@ except ImportError:
 try:
# added in pycryptodome
from Crypto.Hash import BLAKE2b, BLAKE2s, SHA3_256, SHA3_512
-   import functools
 
blake2bhash_ = getattr(BLAKE2b, 'new', None)
if blake2bhash_ is not None:
@@ -156,34 +157,28 @@ except ImportError:
 
 # Use hashlib from python-2.5 if available and prefer it over pycrypto and 
internal fallbacks.
 # Need special handling for RMD160/WHIRLPOOL as they may not always be 
provided by hashlib.
-try:
-   import hashlib, functools
-   
-   md5hash = _generate_hash_function("MD5", hashlib.md5, origin="hashlib")
-   sha1hash = _generate_hash_function("SHA1", hashlib.sha1, 
origin="hashlib")
-   sha256hash = _generate_hash_function("SHA256", hashlib.sha256, 
origin="hashlib")
-   sha512hash = _generate_hash_function("SHA512", hashlib.sha512, 
origin="hashlib")
-   for local_name, hash_name in (
-   ("rmd160", "ripemd160"),
-   ("whirlpool", "whirlpool"),
-   # available since Python 3.6
-   ("BLAKE2B", "blake2b"),
-   ("BLAKE2S", "blake2s"),
-   ("SHA3_256", "sha3_256"),
-   ("SHA3_512", "sha3_512"),
-   ):
-   try:
-   hashlib.new(hash_name)
-   except ValueError:
-   pass
-   else:
-   globals()['%shash' % local_name] = \
-   _generate_hash_function(local_name.upper(), \
-   functools.partial(hashlib.new, hash_name), \
-   origin='hashlib')
-
-except ImportError:
-   pass
+md5hash = _generate_hash_function("MD5", hashlib.md5, origin="hashlib")
+sha1hash = _generate_hash_function("SHA1", hashlib.sha1, origin="hashlib")
+sha256hash = _generate_hash_function("SHA256", hashlib.sha256, 
origin="hashlib")
+sha512hash = _generate_hash_function("SHA512", hashlib.sha512, 
origin="hashlib")
+for local_name, hash_name in (
+   ("rmd160", "ripemd160"),
+   ("whirlpool", "whirlpool"),
+   # available since Python 3.6
+   ("BLAKE2B", "blake2b"),
+   ("BLAKE2S", "blake2s"),
+   ("SHA3_256", "sha3_256"),
+   ("SHA3_512", "sha3_512"),
+   ):
+   try:
+   hashlib.new(hash_name)
+   except ValueError:
+   pass
+   else:
+   globals()['%shash' % local_name] = \
+   _generate_hash_function(local_name.upper(), \
+   functools.partial(hashlib.new, hash_name), \
+   origin='hashlib')
 
 _whirlpool_unaccelerated = False
 if "WHIRLPOOL" not in hashfunc_map:
-- 
2.12.0




[gentoo-portage-dev] [PATCH 05/14] tests: Add minimal safety checks for checksums

2017-03-12 Thread Michał Górny
---
 pym/portage/tests/util/test_checksum.py | 88 +
 1 file changed, 88 insertions(+)
 create mode 100644 pym/portage/tests/util/test_checksum.py

diff --git a/pym/portage/tests/util/test_checksum.py 
b/pym/portage/tests/util/test_checksum.py
new file mode 100644
index 0..72b8cef3f
--- /dev/null
+++ b/pym/portage/tests/util/test_checksum.py
@@ -0,0 +1,88 @@
+# Copyright 2011-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+
+from portage.checksum import checksum_str
+from portage.exception import DigestException
+
+class ChecksumTestCase(TestCase):
+   text = b'Some test string used to check if the hash works'
+
+   def test_md5(self):
+   self.assertEqual(checksum_str(b'', 'MD5'),
+   'd41d8cd98f00b204e9800998ecf8427e')
+   self.assertEqual(checksum_str(self.text, 'MD5'),
+   '094c3bf4732f59b39d577e9726f1e934')
+
+   def test_sha1(self):
+   self.assertEqual(checksum_str(b'', 'SHA1'),
+   'da39a3ee5e6b4b0d3255bfef95601890afd80709')
+   self.assertEqual(checksum_str(self.text, 'SHA1'),
+   '5c572017d4e4d49e4aa03a2eda12dbb54a1e2e4f')
+
+   def test_sha256(self):
+   self.assertEqual(checksum_str(b'', 'SHA256'),
+   
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855')
+   self.assertEqual(checksum_str(self.text, 'SHA256'),
+   
'e3d4a1135181fe156d61455615bb6296198e8ca5b2f20ddeb85cb4cd27f62320')
+
+   def test_sha512(self):
+   self.assertEqual(checksum_str(b'', 'SHA512'),
+   
'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e')
+   self.assertEqual(checksum_str(self.text, 'SHA512'),
+   
'c8eaa902d48a2c82c2185a92f1c8bab8115c63c8d7a9966a8e8e81b07abcb9762f4707a6b27075e9d720277ba9fec072a59840d6355dd2ee64681d8f39a50856')
+
+   def test_rmd160(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'RMD160'),
+   
'9c1185a5c5e9fc54612808977ee8f548b2258d31')
+   self.assertEqual(checksum_str(self.text, 'RMD160'),
+   
'fc453174f63fc011d6f64abd2c45fb6a53c8239b')
+   except DigestException:
+   self.skipTest('RMD160 implementation not available')
+
+   def test_whirlpool(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'WHIRLPOOL'),
+   
'19fa61d75522a4669b44e39c1d2e1726c530232130d407f89afee0964997f7a73e83be698b288febcf88e3e03c4f0757ea8964e59b63d93708b138cc42a66eb3')
+   self.assertEqual(checksum_str(self.text, 'WHIRLPOOL'),
+   
'8f556a079b87057f19e0880eed6d833e40c916f4b133196f6842281a2517873074d399832470c11ee251696b4844a10197714a069ba3e3415c8a4eced8f91b48')
+   except DigestException:
+   self.skipTest('WHIRLPOOL implementation not available')
+
+   def test_blake2b(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'BLAKE2B'),
+   
'786a02f742015903c6c6fd852552d272912f4740e15847618a86e217f71f5419d25e1031afee585313896444934eb04b903a685b1448b755d56f701afe9be2ce')
+   self.assertEqual(checksum_str(self.text, 'BLAKE2B'),
+   
'84cb3c88838c7147bc9797c6525f812adcdcb40137f9c075963e3a3ed1fe06aaeeb4d2bb5589bad286864dc1aa834cfc4d66b8d7e4d4a246d91d45ce3a6eee43')
+   except DigestException:
+   self.skipTest('BLAKE2B implementation not available')
+
+   def test_blake2s(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'BLAKE2S'),
+   
'69217a3079908094e11121d042354a7c1f55b6482ca1a51e1b250dfd1ed0eef9')
+   self.assertEqual(checksum_str(self.text, 'BLAKE2S'),
+   
'823ab2429f27690450efe888b0404d092fe2ee72a9bd63d5342c251b4dbb373d')
+   except DigestException:
+   self.skipTest('BLAKE2S implementation not available')
+
+   def test_sha3_256(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'SHA3_256'),
+   
'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a')
+   self.assertEqual(checksum_str(self.text, 'SHA3_256'),
+   
'932fc0498ebb865406f9b6606280939283aa8a148562e39fd095a5d22bdec5c6')
+  

[gentoo-portage-dev] [PATCH 09/14] portage.checksum: Stop exposing global hash variables

2017-03-12 Thread Michał Górny
Stop exposing global variables such as 'md5hash'. Those are not used
anywhere anymore, exposing them makes the code more complex and makes it
easy to accidentally fail to set them properly (this happened already
for SHA3). Instead, rely on them being inserted into hashfunc_map.
---
 pym/portage/checksum.py | 42 --
 1 file changed, 20 insertions(+), 22 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 68ed44fa9..659012cdc 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -102,11 +102,10 @@ class _generate_hash_function(object):
 # WHIRLPOOL available.
 try:
import mhash
-   for local_name, hash_name in (("rmd160", "ripemd160"), ("whirlpool", 
"whirlpool")):
-   if hasattr(mhash, 'MHASH_%s' % local_name.upper()):
-   globals()['%shash' % local_name] = \
-   _generate_hash_function(local_name.upper(), \
-   functools.partial(mhash.MHASH, getattr(mhash, 
'MHASH_%s' % hash_name.upper())), \
+   for local_name, hash_name in (("RMD160", "RIPEMD160"), ("WHIRLPOOL", 
"WHIRLPOOL")):
+   if hasattr(mhash, 'MHASH_%s' % hash_name):
+   _generate_hash_function(local_name,
+   functools.partial(mhash.MHASH, getattr(mhash, 
'MHASH_%s' % hash_name)),
origin='mhash')
 except ImportError:
pass
@@ -118,7 +117,7 @@ try:
from Crypto.Hash import RIPEMD
rmd160hash_ = getattr(RIPEMD, 'new', None)
if rmd160hash_ is not None:
-   rmd160hash = _generate_hash_function("RMD160",
+   _generate_hash_function("RMD160",
rmd160hash_, origin="pycrypto")
 except ImportError:
pass
@@ -129,19 +128,19 @@ try:
 
blake2bhash_ = getattr(BLAKE2b, 'new', None)
if blake2bhash_ is not None:
-   blake2bhash = _generate_hash_function("BLAKE2B",
+   _generate_hash_function("BLAKE2B",
functools.partial(blake2bhash_, digest_bytes=64), 
origin="pycrypto")
blake2shash_ = getattr(BLAKE2s, 'new', None)
if blake2shash_ is not None:
-   blake2shash = _generate_hash_function("BLAKE2S",
+   _generate_hash_function("BLAKE2S",
functools.partial(blake2shash_, digest_bytes=32), 
origin="pycrypto")
sha3_256hash_ = getattr(SHA3_256, 'new', None)
if sha3_256hash_ is not None:
-   sha3_256hash = _generate_hash_function("SHA3_256",
+   _generate_hash_function("SHA3_256",
sha3_256hash_, origin="pycrypto")
sha3_512hash_ = getattr(SHA3_512, 'new', None)
if sha3_512hash_ is not None:
-   sha3_512hash = _generate_hash_function("SHA3_512",
+   _generate_hash_function("SHA3_512",
sha3_512hash_, origin="pycrypto")
 except ImportError:
pass
@@ -150,20 +149,20 @@ except ImportError:
 try:
import sha3
 
-   sha3_256hash = _generate_hash_function("SHA3_256", sha3.sha3_256, 
origin="pysha3")
-   sha3_512hash = _generate_hash_function("SHA3_512", sha3.sha3_512, 
origin="pysha3")
+   _generate_hash_function("SHA3_256", sha3.sha3_256, origin="pysha3")
+   _generate_hash_function("SHA3_512", sha3.sha3_512, origin="pysha3")
 except ImportError:
pass
 
 # Use hashlib from python-2.5 if available and prefer it over pycrypto and 
internal fallbacks.
 # Need special handling for RMD160/WHIRLPOOL as they may not always be 
provided by hashlib.
-md5hash = _generate_hash_function("MD5", hashlib.md5, origin="hashlib")
-sha1hash = _generate_hash_function("SHA1", hashlib.sha1, origin="hashlib")
-sha256hash = _generate_hash_function("SHA256", hashlib.sha256, 
origin="hashlib")
-sha512hash = _generate_hash_function("SHA512", hashlib.sha512, 
origin="hashlib")
+_generate_hash_function("MD5", hashlib.md5, origin="hashlib")
+_generate_hash_function("SHA1", hashlib.sha1, origin="hashlib")
+_generate_hash_function("SHA256", hashlib.sha256, origin="hashlib")
+_generate_hash_function("SHA512", hashlib.sha512, origin="hashlib")
 for local_name, hash_name in (
-   ("rmd160", "ripemd160"),
-   ("whirlpool", "whirlpool"),
+   ("RMD160", "ripemd160"),
+   ("WHIRLPOOL", "whirlpool"),
# available since Python 3.6
("BLAKE2B", "blake2b"),
("BLAKE2S", "blake2s"),
@@ -175,9 +174,8 @@ for local_name, hash_name in (
except ValueError:
pass
else:
-   globals()['%shash' % local_name] = \
-   _generate_hash_function(local_name.upper(), \
-   functools.partial(hashlib.new, hash_name), \
+   _generate_hash_function(local_name,
+   functools.partial(hashlib.new

[gentoo-portage-dev] [PATCH 11/14] portage.checksum: Support pygcrypt as optimized fallback

2017-03-12 Thread Michał Górny
pygcrypt uses libgcrypt which provides support for ripemd160, whirlpool,
SHA3, plus some algorithms not provided by any other library.
---
 pym/portage/checksum.py | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 2c482f5e7..92b41b133 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -135,6 +135,44 @@ if "SHA3_256" not in hashfunc_map or "SHA3_512" not in 
hashfunc_map:
pass
 
 
+# Support pygcrypt as fallback using optimized routines from libgcrypt
+# (GnuPG).
+gcrypt_algos = frozenset(('RMD160', 'WHIRLPOOL', 'SHA3_256', 'SHA3_512'))
+if gcrypt_algos.difference(hashfunc_map):
+   try:
+   import binascii
+   import pygcrypt.hashcontext
+
+   class GCryptHashWrapper(object):
+   def __init__(self, algo):
+   self._obj = 
pygcrypt.hashcontext.HashContext(algo=algo)
+
+   def update(self, data):
+   self._obj.write(data)
+
+   def hexdigest(self):
+   return 
binascii.b2a_hex(self._obj.read()).decode()
+
+   name_mapping = {
+   'RMD160': 'ripemd160',
+   'WHIRLPOOL': 'whirlpool',
+   'SHA3_256': 'sha3-256',
+   'SHA3_512': 'sha3-512',
+   }
+
+   for local_name, gcry_name in name_mapping.items():
+   try:
+   pygcrypt.hashcontext.HashContext(algo=gcry_name)
+   except Exception: # yes, it throws Exception...
+   pass
+   else:
+   _generate_hash_function(local_name,
+   
functools.partial(GCryptHashWrapper, gcry_name),
+   origin="pygcrypt")
+   except ImportError:
+   pass
+
+
 # Use pycrypto when available, prefer it over the internal fallbacks
 # Check for 'new' attributes, since they can be missing if the module
 # is broken somehow.
-- 
2.12.0




[gentoo-portage-dev] [PATCH 12/14] Support STREEBOG{256,512} hash function (from pygcrypt), #597736

2017-03-12 Thread Michał Górny
---
 pym/portage/checksum.py |  5 -
 pym/portage/const.py|  3 ++-
 pym/portage/tests/util/test_checksum.py | 18 ++
 3 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 92b41b133..3ee100c3f 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -137,7 +137,8 @@ if "SHA3_256" not in hashfunc_map or "SHA3_512" not in 
hashfunc_map:
 
 # Support pygcrypt as fallback using optimized routines from libgcrypt
 # (GnuPG).
-gcrypt_algos = frozenset(('RMD160', 'WHIRLPOOL', 'SHA3_256', 'SHA3_512'))
+gcrypt_algos = frozenset(('RMD160', 'WHIRLPOOL', 'SHA3_256', 'SHA3_512',
+   'STREEBOG256', 'STREEBOG512'))
 if gcrypt_algos.difference(hashfunc_map):
try:
import binascii
@@ -158,6 +159,8 @@ if gcrypt_algos.difference(hashfunc_map):
'WHIRLPOOL': 'whirlpool',
'SHA3_256': 'sha3-256',
'SHA3_512': 'sha3-512',
+   'STREEBOG256': 'stribog256',
+   'STREEBOG512': 'stribog512',
}
 
for local_name, gcry_name in name_mapping.items():
diff --git a/pym/portage/const.py b/pym/portage/const.py
index 0cef2e8ae..7e415ba9c 100644
--- a/pym/portage/const.py
+++ b/pym/portage/const.py
@@ -232,7 +232,8 @@ MANIFEST1_REQUIRED_HASH  = "MD5"
 # - Remove redundant settings from gentoo-x86/metadata/layout.conf.
 
 MANIFEST2_HASH_FUNCTIONS = ("SHA256", "SHA512", "WHIRLPOOL",
-   "BLAKE2B", "BLAKE2S", "SHA3_256", "SHA3_512")
+   "BLAKE2B", "BLAKE2S", "SHA3_256", "SHA3_512",
+   "STREEBOG256", "STREEBOG512")
 MANIFEST2_HASH_DEFAULTS = frozenset(["SHA256", "SHA512", "WHIRLPOOL"])
 MANIFEST2_REQUIRED_HASH  = "SHA256"
 
diff --git a/pym/portage/tests/util/test_checksum.py 
b/pym/portage/tests/util/test_checksum.py
index 72b8cef3f..01ac8f9d0 100644
--- a/pym/portage/tests/util/test_checksum.py
+++ b/pym/portage/tests/util/test_checksum.py
@@ -86,3 +86,21 @@ class ChecksumTestCase(TestCase):

'6634c004dc31822fa65c2f1e2e3bbf0cfa35085653cca1ca9ca42f8f3f13c908405e0b665918146181c9fc9a9d793fc05429d669c35a55517820dfaa071425ca')
except DigestException:
self.skipTest('SHA3_512 implementation not available')
+
+   def test_streebog256(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'STREEBOG256'),
+   
'3f539a213e97c802cc229d474c6aa32a825a360b2a933a949fd925208d9ce1bb')
+   self.assertEqual(checksum_str(self.text, 'STREEBOG256'),
+   
'4992f1239c46f15b89e7b83ded4d83fb5966da3692788a4a1a6d118f78c08444')
+   except DigestException:
+   self.skipTest('STREEBOG256 implementation not 
available')
+
+   def test_streebog512(self):
+   try:
+   self.assertEqual(checksum_str(b'', 'STREEBOG512'),
+   
'8e945da209aa869f0455928529bcae4679e9873ab707b55315f56ceb98bef0a7362f715528356ee83cda5f2aac4c6ad2ba3a715c1bcd81cb8e9f90bf4c1c1a8a')
+   self.assertEqual(checksum_str(self.text, 'STREEBOG512'),
+   
'330f5c26437f4e22c0163c72b12e93b8c27202f0750627355bdee43a0e0b253c90fbf0a27adbe5414019ff01ed84b7b240a1da1cbe10fae3adffc39c2d87a51f')
+   except DigestException:
+   self.skipTest('STREEBOG512 implementation not 
available')
-- 
2.12.0




[gentoo-portage-dev] [PATCH 14/14] travis: Install additional (pure Python) crypto providers if necessary

2017-03-12 Thread Michał Górny
Install pysha3 to provide the SHA3 routines on Python < 3.6, and install
pygost to provide a Streebog implementation.
---
 .travis.yml | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index 7fe3c06aa..196e3520a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,14 @@ python:
 - pypy
 
 # command to install dependencies
-install: "pip install lxml"
+install:
+- pip install lxml
+# python3.6+ has sha3 built-in, for older versions install pysha3
+# (except for pypy where pysha3 is broken)
+- "[[ ${TRAVIS_PYTHON_VERSION} == 3.[6789] || ${TRAVIS_PYTHON_VERSION} == 
pypy ]] || pip install pysha3"
+# always install pygost for Streebog
+# (except for py3.3 which it does not support)
+- "[[ ${TRAVIS_PYTHON_VERSION} == 3.3 ]] || pip install pygost"
 
 script:
 - printf "[build_ext]\nportage-ext-modules=true" >> setup.cfg
-- 
2.12.0




[gentoo-portage-dev] [PATCH 10/14] portage.checksum: Reorder to avoid loading redundant impls

2017-03-12 Thread Michał Górny
Reorder the checksum implementations to start with the most preferred
implementation, and try fallbacks only if the most preferred
implementation is not available. Most importantly, this means that
Portage will no longer attempt to load all hash libraries in the system,
especially when it can satisfy its requirements with hashlib.
---
 pym/portage/checksum.py | 145 +---
 1 file changed, 87 insertions(+), 58 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 659012cdc..2c482f5e7 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -93,66 +93,11 @@ class _generate_hash_function(object):
 
return (checksum.hexdigest(), size)
 
-# Define hash functions, try to use the best module available. Later 
definitions
-# override earlier ones
 
-# Try to use mhash if available
-# mhash causes GIL presently, so it gets less priority than hashlib and
-# pycrypto. However, it might be the only accelerated implementation of
-# WHIRLPOOL available.
-try:
-   import mhash
-   for local_name, hash_name in (("RMD160", "RIPEMD160"), ("WHIRLPOOL", 
"WHIRLPOOL")):
-   if hasattr(mhash, 'MHASH_%s' % hash_name):
-   _generate_hash_function(local_name,
-   functools.partial(mhash.MHASH, getattr(mhash, 
'MHASH_%s' % hash_name)),
-   origin='mhash')
-except ImportError:
-   pass
-
-# Use pycrypto when available, prefer it over the internal fallbacks
-# Check for 'new' attributes, since they can be missing if the module
-# is broken somehow.
-try:
-   from Crypto.Hash import RIPEMD
-   rmd160hash_ = getattr(RIPEMD, 'new', None)
-   if rmd160hash_ is not None:
-   _generate_hash_function("RMD160",
-   rmd160hash_, origin="pycrypto")
-except ImportError:
-   pass
-
-try:
-   # added in pycryptodome
-   from Crypto.Hash import BLAKE2b, BLAKE2s, SHA3_256, SHA3_512
-
-   blake2bhash_ = getattr(BLAKE2b, 'new', None)
-   if blake2bhash_ is not None:
-   _generate_hash_function("BLAKE2B",
-   functools.partial(blake2bhash_, digest_bytes=64), 
origin="pycrypto")
-   blake2shash_ = getattr(BLAKE2s, 'new', None)
-   if blake2shash_ is not None:
-   _generate_hash_function("BLAKE2S",
-   functools.partial(blake2shash_, digest_bytes=32), 
origin="pycrypto")
-   sha3_256hash_ = getattr(SHA3_256, 'new', None)
-   if sha3_256hash_ is not None:
-   _generate_hash_function("SHA3_256",
-   sha3_256hash_, origin="pycrypto")
-   sha3_512hash_ = getattr(SHA3_512, 'new', None)
-   if sha3_512hash_ is not None:
-   _generate_hash_function("SHA3_512",
-   sha3_512hash_, origin="pycrypto")
-except ImportError:
-   pass
-
-# Support using pysha3 as fallback for python<3.6
-try:
-   import sha3
+# Define hash functions, try to use the best module available. Preferred
+# modules should go first, latter ones should check if the hashes aren't
+# already defined.
 
-   _generate_hash_function("SHA3_256", sha3.sha3_256, origin="pysha3")
-   _generate_hash_function("SHA3_512", sha3.sha3_512, origin="pysha3")
-except ImportError:
-   pass
 
 # Use hashlib from python-2.5 if available and prefer it over pycrypto and 
internal fallbacks.
 # Need special handling for RMD160/WHIRLPOOL as they may not always be 
provided by hashlib.
@@ -178,6 +123,89 @@ for local_name, hash_name in (
functools.partial(hashlib.new, hash_name),
origin='hashlib')
 
+
+# Support using pysha3 as fallback for python<3.6
+if "SHA3_256" not in hashfunc_map or "SHA3_512" not in hashfunc_map:
+   try:
+   import sha3
+
+   _generate_hash_function("SHA3_256", sha3.sha3_256, 
origin="pysha3")
+   _generate_hash_function("SHA3_512", sha3.sha3_512, 
origin="pysha3")
+   except ImportError:
+   pass
+
+
+# Use pycrypto when available, prefer it over the internal fallbacks
+# Check for 'new' attributes, since they can be missing if the module
+# is broken somehow.
+if 'RMD160' not in hashfunc_map:
+   try:
+   from Crypto.Hash import RIPEMD
+   rmd160hash_ = getattr(RIPEMD, 'new', None)
+   if rmd160hash_ is not None:
+   _generate_hash_function("RMD160",
+   rmd160hash_, origin="pycrypto")
+   except ImportError:
+   pass
+
+# The following hashes were added in pycryptodome (pycrypto fork)
+if 'BLAKE2B' not in hashfunc_map:
+   try:
+   from Crypto.Hash import BLAKE2b
+   blake2bhash_ = getattr(BLAKE2b, 'new', None)
+   if blake2bhash_ is not None:
+   _generate_hash_function("BLAKE2B",
+   

[gentoo-portage-dev] [PATCH 13/14] portage.checksum: Support pygost as fallback Streebog provider

2017-03-12 Thread Michał Górny
Support the pure Python implementation of Streebog in pygost as
a fallback algorithm. The code is horrible (it stores all the data
in memory before hashing), so it is really intended as last fallback.
---
 pym/portage/checksum.py | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index 3ee100c3f..df896533f 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -247,6 +247,21 @@ if 'RMD160' not in hashfunc_map or 'WHIRLPOOL' not in 
hashfunc_map:
pass
 
 
+# Support pygost as fallback streebog provider
+# It's mostly provided as a reference implementation; it's pure Python,
+# slow and reads all data to memory (i.e. doesn't hash on update()...)
+if 'STREEBOG256' not in hashfunc_map or 'STREEBOG512' not in hashfunc_map:
+   try:
+   import pygost.gost34112012
+
+   _generate_hash_function("STREEBOG256",
+   functools.partial(pygost.gost34112012.GOST34112012, 
digest_size=32), origin="pygost")
+   _generate_hash_function("STREEBOG512",
+   functools.partial(pygost.gost34112012.GOST34112012, 
digest_size=64), origin="pygost")
+   except ImportError:
+   pass
+
+
 _whirlpool_unaccelerated = False
 if "WHIRLPOOL" not in hashfunc_map:
# Bundled WHIRLPOOL implementation
-- 
2.12.0




Re: [gentoo-portage-dev] [PATCH 01/14] Use public API: hashfunc_map -> get_valid_checksum_keys()

2017-03-12 Thread Michał Górny
W dniu 12.03.2017, nie o godzinie 13∶36 -0700, użytkownik Zac Medico
napisał:
> On Sun, Mar 12, 2017 at 11:59 AM, Michał Górny  wrote:
> > Use get_valid_checksum_keys() function instead of accessing hashfunc_map
> > directly throughout the Portage.
> > ---
> >  pym/portage/_emirrordist/FetchTask.py |  2 +-
> >  pym/portage/dbapi/bintree.py  |  4 ++--
> >  pym/portage/eclass_cache.py   |  2 +-
> >  pym/portage/manifest.py   |  4 ++--
> >  pym/portage/package/ebuild/fetch.py   | 10 +-
> >  5 files changed, 11 insertions(+), 11 deletions(-)
> > 
> > diff --git a/pym/portage/_emirrordist/FetchTask.py 
> > b/pym/portage/_emirrordist/FetchTask.py
> > index 64de67582..203b8c213 100644
> > --- a/pym/portage/_emirrordist/FetchTask.py
> > +++ b/pym/portage/_emirrordist/FetchTask.py
> > @@ -574,7 +574,7 @@ class FetchTask(CompositeTask):
> > else:
> > for hash_name in self.digests:
> > if hash_name != "size" and \
> > -   hash_name in 
> > portage.checksum.hashfunc_map:
> > +   hash_name in 
> > portage.checksum.get_valid_checksum_keys():
> 
> The get_valid_checksum_keys function creates a list for each call, so
> this is a lot less efficient that dict hash table lookup that it was
> before.

Does it really matter though? AFAICS this is just a matter of optimizing
the function, e.g. putting the keys in a frozenset.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCH] portage.checksum: Store supported hash types in a frozenset

2017-03-13 Thread Michał Górny
Copy the list of supported hash types (hashfunc_map dict) into
a frozenset to support efficient access in the public API.
---
 pym/portage/checksum.py | 25 ++---
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/pym/portage/checksum.py b/pym/portage/checksum.py
index df896533f..ff132751b 100644
--- a/pym/portage/checksum.py
+++ b/pym/portage/checksum.py
@@ -278,6 +278,9 @@ class SizeHash(object):
 
 hashfunc_map["size"] = SizeHash()
 
+# cache all supported hash methods in a frozenset
+hashfunc_keys = frozenset(hashfunc_map)
+
 # end actual hash functions
 
 
@@ -312,15 +315,15 @@ def _perform_md5_merge(x, **kwargs):
 
 def perform_all(x, calc_prelink=0):
mydict = {}
-   for k in hashfunc_map:
+   for k in hashfunc_keys:
mydict[k] = perform_checksum(x, k, calc_prelink)[0]
return mydict
 
 def get_valid_checksum_keys():
-   return list(hashfunc_map)
+   return hashfunc_keys
 
 def get_hash_origin(hashtype):
-   if hashtype not in hashfunc_map:
+   if hashtype not in hashfunc_keys:
raise KeyError(hashtype)
return hashorigin_map.get(hashtype, "unknown")
 
@@ -334,7 +337,7 @@ def _filter_unaccelarated_hashes(digests):
due to minimization of dependencies.
"""
if _whirlpool_unaccelerated and "WHIRLPOOL" in digests:
-   verifiable_hash_types = set(digests).intersection(hashfunc_map)
+   verifiable_hash_types = set(digests).intersection(hashfunc_keys)
verifiable_hash_types.discard("size")
if len(verifiable_hash_types) > 1:
digests = dict(digests)
@@ -383,7 +386,7 @@ def _apply_hash_filter(digests, hash_filter):
@type hash_filter: callable
"""
 
-   verifiable_hash_types = set(digests).intersection(hashfunc_map)
+   verifiable_hash_types = set(digests).intersection(hashfunc_keys)
verifiable_hash_types.discard("size")
modified = False
if len(verifiable_hash_types) > 1:
@@ -430,10 +433,10 @@ def verify_all(filename, mydict, calc_prelink=0, 
strict=0):
raise portage.exception.FileNotFound(filename)
return False, (str(e), None, None)
 
-   verifiable_hash_types = set(mydict).intersection(hashfunc_map)
+   verifiable_hash_types = set(mydict).intersection(hashfunc_keys)
verifiable_hash_types.discard("size")
if not verifiable_hash_types:
-   expected = set(hashfunc_map)
+   expected = set(hashfunc_keys)
expected.discard("size")
expected = list(expected)
expected.sort()
@@ -448,7 +451,7 @@ def verify_all(filename, mydict, calc_prelink=0, strict=0):
for x in sorted(mydict):
if   x == "size":
continue
-   elif x in hashfunc_map:
+   elif x in hashfunc_keys:
myhash = perform_checksum(filename, x, 
calc_prelink=calc_prelink)[0]
if mydict[x] != myhash:
if strict:
@@ -504,7 +507,7 @@ def perform_checksum(filename, hashname="MD5", 
calc_prelink=0):
# This happens during uninstallation of prelink.
prelink_capable = False
try:
-   if hashname not in hashfunc_map:
+   if hashname not in hashfunc_keys:
raise 
portage.exception.DigestException(hashname + \
" hash function not available (needs 
dev-python/pycrypto)")
myhash, mysize = 
hashfunc_map[hashname].checksum_file(myfilename)
@@ -541,7 +544,7 @@ def perform_multiple_checksums(filename, hashes=["MD5"], 
calc_prelink=0):
"""
rVal = {}
for x in hashes:
-   if x not in hashfunc_map:
+   if x not in hashfunc_keys:
raise portage.exception.DigestException(x+" hash 
function not available (needs dev-python/pycrypto or >=dev-lang/python-2.5)")
rVal[x] = perform_checksum(filename, x, calc_prelink)[0]
return rVal
@@ -558,7 +561,7 @@ def checksum_str(data, hashname="MD5"):
@rtype: String
@return: The hash (hex-digest) of the data
"""
-   if hashname not in hashfunc_map:
+   if hashname not in hashfunc_keys:
raise portage.exception.DigestException(hashname + \
" hash function not available (needs 
dev-python/pycrypto)")
return hashfunc_map[hashname].checksum_str(data)
-- 
2.12.0




Re: [gentoo-portage-dev] [PATCHES] portage.checksum hacking, pt. 4

2017-03-13 Thread Michał Górny
W dniu 12.03.2017, nie o godzinie 21∶31 -0700, użytkownik Zac Medico
napisał:
> On Sun, Mar 12, 2017 at 11:59 AM, Michał Górny  wrote:
> > Hi,
> > 
> > Here's a huge batch of patches for portage.checksum and relevant stuff.
> > It's not a complete rewrite as I have originally planned, and it's still
> > not the code I'd like to see but functionally it has been improved a lot.
> 
> The series looks good to me, except we should change the
> get_valid_checksum_keys function to return a frozenset.

Thanks a lot, all merged now.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCH] portage.package.ebuild: Use a fake FILESDIR to catch invalid accesses

2017-03-16 Thread Michał Górny
Use a model of fake FILESDIR path to ensure that invalid accesses to
FILESDIR will result in failures rather than being silently allowed by
Portage. This mostly involves accesses in the global scope and pkg_*
phases, although the current model does not cover the latter completely
(i.e. does not guarantee that the directory is removed post src_*).

This model aims to follow PMS wording quite precisely. The value of
FILESDIR is meant to be stable throughout the build process, and it is
reliably set to a temporary directory path. However, since the path is
not guaranteed to be present outside src_*, the directory symlink is not
actually created before src_* phases.

== Review notes ==
This is the final version that actually works ;-). I did a full egencache
run with it and the only packages that fail are eblit users (all of them
have bugs open with deadline 1 week from now). There might be a few more
silly failures, so I'll test it for a while, and ask Toralf to possibly
do some tinderboxing.

---
 man/ebuild.5 |  6 +++---
 pym/_emerge/EbuildPhase.py   |  4 +++-
 pym/portage/package/ebuild/config.py |  3 ---
 pym/portage/package/ebuild/doebuild.py   |  6 +-
 pym/portage/package/ebuild/prepare_build_dirs.py | 13 +
 5 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/man/ebuild.5 b/man/ebuild.5
index 72b8b6905..e4c866cd2 100644
--- a/man/ebuild.5
+++ b/man/ebuild.5
@@ -411,9 +411,9 @@ not be defined. It is autogenerated from the \fBSRC_URI\fR 
variable.
 .B WORKDIR\fR = \fI"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/work"
 Contains the path to the package build root.  Do not modify this variable.
 .TP
-.B FILESDIR\fR = \fI"${repository_location}/${CATEGORY}/${PN}/files"
-Contains the path to the 'files' subdirectory in the package specific
-location in given repository.  Do not modify this variable.
+.B FILESDIR\fR = \fI"${PORTAGE_TMPDIR}/${CATEGORY}/${PF}/files"
+Contains the path to the directory in which package-specific auxiliary
+files are located.  Do not modify this variable.
 .TP
 .B EBUILD_PHASE
 Contains the abreviated name of the phase function that is
diff --git a/pym/_emerge/EbuildPhase.py b/pym/_emerge/EbuildPhase.py
index fc185fcfd..504c812ea 100644
--- a/pym/_emerge/EbuildPhase.py
+++ b/pym/_emerge/EbuildPhase.py
@@ -11,7 +11,8 @@ from _emerge.BinpkgEnvExtractor import BinpkgEnvExtractor
 from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
 from _emerge.EbuildProcess import EbuildProcess
 from _emerge.CompositeTask import CompositeTask
-from portage.package.ebuild.prepare_build_dirs import _prepare_workdir
+from portage.package.ebuild.prepare_build_dirs import (_prepare_workdir,
+   _prepare_fake_filesdir)
 from portage.util import writemsg
 
 try:
@@ -229,6 +230,7 @@ class EbuildPhase(CompositeTask):
# ownership since tar can change that too.
os.utime(settings["WORKDIR"], None)
_prepare_workdir(settings)
+   _prepare_fake_filesdir(settings)
elif self.phase == "install":
out = io.StringIO()
_post_src_install_write_metadata(settings)
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index ef29afeab..f8043dbf5 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -2784,9 +2784,6 @@ class config(object):
mydict.pop("EPREFIX", None)
mydict.pop("EROOT", None)
 
-   if phase == 'depend':
-   mydict.pop('FILESDIR', None)
-
if phase not in ("pretend", "setup", "preinst", "postinst") or \
not eapi_exports_replace_vars(eapi):
mydict.pop("REPLACING_VERSIONS", None)
diff --git a/pym/portage/package/ebuild/doebuild.py 
b/pym/portage/package/ebuild/doebuild.py
index 4baae17b1..2f80a28ee 100644
--- a/pym/portage/package/ebuild/doebuild.py
+++ b/pym/portage/package/ebuild/doebuild.py
@@ -31,6 +31,7 @@ portage.proxy.lazyimport.lazyimport(globals(),
'portage.package.ebuild.digestcheck:digestcheck',
'portage.package.ebuild.digestgen:digestgen',
'portage.package.ebuild.fetch:fetch',
+   'portage.package.ebuild.prepare_build_dirs:_prepare_fake_filesdir',
'portage.package.ebuild._ipc.QueryCommand:QueryCommand',
'portage.dep._slot_operator:evaluate_slot_operator_equal_deps',
'portage.package.ebuild._spawn_nofetch:spawn_nofetch',
@@ -164,6 +165,9 @@ def _doebuild_spawn(phase, settings, actionmap=None, 
**kwargs):
os.path.basename(EBUILD_SH_BINARY))),
ebuild_sh_arg)
 
+   if phase == 'unpack':
+   _prepare_fake_filesdir(settings)
+
settings['EBUILD_PHASE'] = phase
try:
return

Re: [gentoo-portage-dev] [PATCH] portage.package.ebuild: Use a fake FILESDIR to catch invalid accesses

2017-03-16 Thread Michał Górny
On czw, 2017-03-16 at 21:29 +0100, Ulrich Mueller wrote:
> > > > > > On Thu, 16 Mar 2017, Michał Górny wrote:
> > +   mysettings["FILESDIR"] = os.path.join(settings["PORTAGE_BUILDDIR"], 
> > "files")
> 
> I believe that this contradicts current PMS 11.1, which defines
> FILESDIR as follows: "The full path to the package's files directory,
> used for small support files or patches. See section 4.3."
> 
> So maybe you should first propose a clarification of the PMS wording?

I think that 'full' in this context means 'absolute'. I don't think this
really requires us to use the 'original' path. But sure, I'll submit
a patch in a few minutes.

-- 
Best regards,
Michał Górny


signature.asc
Description: This is a digitally signed message part


[gentoo-portage-dev] [PATCH v2] portage.package.ebuild: Use a fake FILESDIR to catch invalid accesses

2017-03-18 Thread Michał Górny
Use a model of fake FILESDIR path to ensure that invalid accesses to
FILESDIR will result in failures rather than being silently allowed by
Portage. This mostly involves accesses in the global scope and pkg_*
phases, although the current model does not cover the latter completely
(i.e. does not guarantee that the directory is removed post src_*).

This model aims to follow PMS wording quite precisely. The value of
FILESDIR is meant to be stable throughout the build process, and it is
reliably set to a temporary directory path. However, since the path is
not guaranteed to be present outside src_*, the directory symlink is not
actually created before src_* phases.
---
 man/ebuild.5 |  6 +++---
 pym/_emerge/EbuildPhase.py   |  6 +-
 pym/portage/package/ebuild/config.py |  3 ---
 pym/portage/package/ebuild/doebuild.py   |  2 +-
 pym/portage/package/ebuild/prepare_build_dirs.py | 13 +
 5 files changed, 22 insertions(+), 8 deletions(-)

// CHANGED IN v2:
// - fixed FILESDIR to be created before unpack, not after
// - removed dupe logic

diff --git a/man/ebuild.5 b/man/ebuild.5
index 72b8b6905..e4c866cd2 100644
--- a/man/ebuild.5
+++ b/man/ebuild.5
@@ -411,9 +411,9 @@ not be defined. It is autogenerated from the \fBSRC_URI\fR 
variable.
 .B WORKDIR\fR = \fI"${PORTAGE_TMPDIR}/portage/${CATEGORY}/${PF}/work"
 Contains the path to the package build root.  Do not modify this variable.
 .TP
-.B FILESDIR\fR = \fI"${repository_location}/${CATEGORY}/${PN}/files"
-Contains the path to the 'files' subdirectory in the package specific
-location in given repository.  Do not modify this variable.
+.B FILESDIR\fR = \fI"${PORTAGE_TMPDIR}/${CATEGORY}/${PF}/files"
+Contains the path to the directory in which package-specific auxiliary
+files are located.  Do not modify this variable.
 .TP
 .B EBUILD_PHASE
 Contains the abreviated name of the phase function that is
diff --git a/pym/_emerge/EbuildPhase.py b/pym/_emerge/EbuildPhase.py
index fc185fcfd..4b5cbf8fa 100644
--- a/pym/_emerge/EbuildPhase.py
+++ b/pym/_emerge/EbuildPhase.py
@@ -11,7 +11,8 @@ from _emerge.BinpkgEnvExtractor import BinpkgEnvExtractor
 from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
 from _emerge.EbuildProcess import EbuildProcess
 from _emerge.CompositeTask import CompositeTask
-from portage.package.ebuild.prepare_build_dirs import _prepare_workdir
+from portage.package.ebuild.prepare_build_dirs import (_prepare_workdir,
+   _prepare_fake_filesdir)
 from portage.util import writemsg
 
 try:
@@ -129,6 +130,9 @@ class EbuildPhase(CompositeTask):
# If the environment.bz2 doesn't exist, then ebuild.sh 
will
# source the ebuild as a fallback.
 
+   if self.phase == "unpack":
+   _prepare_fake_filesdir(self.settings)
+
self._start_lock()
 
def _env_extractor_exit(self, env_extractor):
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index ef29afeab..f8043dbf5 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -2784,9 +2784,6 @@ class config(object):
mydict.pop("EPREFIX", None)
mydict.pop("EROOT", None)
 
-   if phase == 'depend':
-   mydict.pop('FILESDIR', None)
-
if phase not in ("pretend", "setup", "preinst", "postinst") or \
not eapi_exports_replace_vars(eapi):
mydict.pop("REPLACING_VERSIONS", None)
diff --git a/pym/portage/package/ebuild/doebuild.py 
b/pym/portage/package/ebuild/doebuild.py
index 4baae17b1..e7db54bcf 100644
--- a/pym/portage/package/ebuild/doebuild.py
+++ b/pym/portage/package/ebuild/doebuild.py
@@ -337,7 +337,6 @@ def doebuild_environment(myebuild, mydo, myroot=None, 
settings=None,
mysettings["EBUILD"]   = ebuild_path
mysettings["O"]= pkg_dir
mysettings.configdict["pkg"]["CATEGORY"] = cat
-   mysettings["FILESDIR"] = pkg_dir+"/files"
mysettings["PF"]   = mypv
 
if hasattr(mydbapi, 'repositories'):
@@ -390,6 +389,7 @@ def doebuild_environment(myebuild, mydo, myroot=None, 
settings=None,
mysettings["WORKDIR"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], 
"work")
mysettings["D"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "image") 
+ os.sep
mysettings["T"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "temp")
+   mysettings["FILESDIR"] = os.path.join(settings["PORTAGE_BUILDDIR"], 
"files")
 
# Prefix forward compatability
eprefix_lstrip = mysettings["EPREFIX"].lstrip(os.sep)
diff --git a/pym/portage/package/ebuild/prepare_build_dirs.py 
b/pym/portage/package/ebuild/prepare_build_dirs.py
index 7e5249b66..e3ae318bd 100644
--- a/pym/portage/package/ebuild/prepare_build_dirs.py
+++ b/pym/portage/packag

[gentoo-portage-dev] [PATCHES] Restrict DISTDIR to src_unpack and further

2017-03-18 Thread Michał Górny
Hi,

Here's a not-so-quick batch of patches that adjust DISTDIR shadow dir
handling to be alike the new handling of FILESDIR (and needs to be
applied on top of that).

The idea is that DISTDIR has a consistent value throughout all
the phases (as required by the PMS) and references the shadow directory.
The directory itself is not created until src_unpack, so mistaken
accesses in earlier phases are caught early. The accesses in pkg_pre/post
phases are not caught yet.

As usual, this patch can be applied after reasonable set of blockers
in ::gentoo is resolved.

--
Best regards,
Michał Górny




[gentoo-portage-dev] [PATCH 4/4] _emerge.Ebuild*: delay creating DISTDIR shadow until src_unpack

2017-03-18 Thread Michał Górny
---
 pym/_emerge/EbuildExecuter.py | 4 
 pym/_emerge/EbuildPhase.py| 4 +++-
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/pym/_emerge/EbuildExecuter.py b/pym/_emerge/EbuildExecuter.py
index 7a454c3e6..81257aa9e 100644
--- a/pym/_emerge/EbuildExecuter.py
+++ b/pym/_emerge/EbuildExecuter.py
@@ -8,7 +8,6 @@ import portage
 from portage import os
 from portage.eapi import eapi_has_src_prepare_and_src_configure, \
eapi_exports_replace_vars
-from portage.package.ebuild.prepare_build_dirs import _prepare_fake_distdir
 
 class EbuildExecuter(CompositeTask):
 
@@ -25,9 +24,6 @@ class EbuildExecuter(CompositeTask):
cleanup = 0
portage.prepare_build_dirs(pkg.root, settings, cleanup)
 
-   alist = settings.configdict["pkg"].get("A", "").split()
-   _prepare_fake_distdir(settings, alist)
-
if eapi_exports_replace_vars(settings['EAPI']):
vardb = pkg.root_config.trees['vartree'].dbapi
settings["REPLACING_VERSIONS"] = " ".join(
diff --git a/pym/_emerge/EbuildPhase.py b/pym/_emerge/EbuildPhase.py
index 4b5cbf8fa..535b64a9c 100644
--- a/pym/_emerge/EbuildPhase.py
+++ b/pym/_emerge/EbuildPhase.py
@@ -12,7 +12,7 @@ from _emerge.MiscFunctionsProcess import MiscFunctionsProcess
 from _emerge.EbuildProcess import EbuildProcess
 from _emerge.CompositeTask import CompositeTask
 from portage.package.ebuild.prepare_build_dirs import (_prepare_workdir,
-   _prepare_fake_filesdir)
+   _prepare_fake_distdir, _prepare_fake_filesdir)
 from portage.util import writemsg
 
 try:
@@ -131,6 +131,8 @@ class EbuildPhase(CompositeTask):
# source the ebuild as a fallback.
 
if self.phase == "unpack":
+   alist = self.settings.configdict["pkg"].get("A", 
"").split()
+   _prepare_fake_distdir(self.settings, alist)
_prepare_fake_filesdir(self.settings)
 
self._start_lock()
-- 
2.12.0




[gentoo-portage-dev] [PATCH 3/4] portage.package.ebuild.doebuild: Override DISTDIR unconditionally, #612972

2017-03-18 Thread Michał Górny
Ensure that DISTDIR is always defined to the path to the shadow
directory. This ensures that PMS rules for consistent value are
followed, and that no global scope calls should be able to access
the distfile directory. This also ensures that global-scope assignments
(e.g. in PATCHES) do not work around the shadow directory.
---
 pym/portage/package/ebuild/doebuild.py   | 9 +
 pym/portage/package/ebuild/prepare_build_dirs.py | 6 ++
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/pym/portage/package/ebuild/doebuild.py 
b/pym/portage/package/ebuild/doebuild.py
index 15e4abb48..8efc08334 100644
--- a/pym/portage/package/ebuild/doebuild.py
+++ b/pym/portage/package/ebuild/doebuild.py
@@ -348,7 +348,8 @@ def doebuild_environment(myebuild, mydo, myroot=None, 
settings=None,
 
mysettings["PORTDIR"] = os.path.realpath(mysettings["PORTDIR"])
mysettings.pop("PORTDIR_OVERLAY", None)
-   mysettings["DISTDIR"] = os.path.realpath(mysettings["DISTDIR"])
+   if "PORTAGE_ACTUAL_DISTDIR" not in mysettings:
+   mysettings["PORTAGE_ACTUAL_DISTDIR"] = 
os.path.realpath(mysettings["DISTDIR"])
mysettings["RPMDIR"]  = os.path.realpath(mysettings["RPMDIR"])
 
mysettings["ECLASSDIR"]   = mysettings["PORTDIR"]+"/eclass"
@@ -390,6 +391,7 @@ def doebuild_environment(myebuild, mydo, myroot=None, 
settings=None,
mysettings["WORKDIR"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], 
"work")
mysettings["D"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "image") 
+ os.sep
mysettings["T"] = os.path.join(mysettings["PORTAGE_BUILDDIR"], "temp")
+   mysettings["DISTDIR"] = os.path.join(settings["PORTAGE_BUILDDIR"], 
"distdir")
mysettings["FILESDIR"] = os.path.join(settings["PORTAGE_BUILDDIR"], 
"files")
 
# Prefix forward compatability
@@ -1207,9 +1209,8 @@ def doebuild(myebuild, mydo, _unused=DeprecationWarning, 
settings=None, debug=0,
mysettings.pop("REPLACING_VERSIONS", None)
 
# Make sure that DISTDIR is restored to it's normal value 
before we return!
-   if "PORTAGE_ACTUAL_DISTDIR" in mysettings:
-   mysettings["DISTDIR"] = 
mysettings["PORTAGE_ACTUAL_DISTDIR"]
-   del mysettings["PORTAGE_ACTUAL_DISTDIR"]
+   mysettings["DISTDIR"] = mysettings["PORTAGE_ACTUAL_DISTDIR"]
+   del mysettings["PORTAGE_ACTUAL_DISTDIR"]
 
if logfile and not returnpid:
try:
diff --git a/pym/portage/package/ebuild/prepare_build_dirs.py 
b/pym/portage/package/ebuild/prepare_build_dirs.py
index 0fa43ba59..6528d550e 100644
--- a/pym/portage/package/ebuild/prepare_build_dirs.py
+++ b/pym/portage/package/ebuild/prepare_build_dirs.py
@@ -411,10 +411,8 @@ def _prepare_fake_filesdir(settings):
os.symlink(real_filesdir, symlink_path)
 
 def _prepare_fake_distdir(settings, alist):
-   orig_distdir = settings["DISTDIR"]
-   settings["PORTAGE_ACTUAL_DISTDIR"] = orig_distdir
-   edpath = settings["DISTDIR"] = \
-   os.path.join(settings["PORTAGE_BUILDDIR"], "distdir")
+   orig_distdir = settings["PORTAGE_ACTUAL_DISTDIR"]
+   edpath = settings["DISTDIR"]
portage.util.ensure_dirs(edpath, gid=portage_gid, mode=0o755)
 
# Remove any unexpected files or directories.
-- 
2.12.0




  1   2   3   4   5   6   7   8   9   10   >