Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-14 Thread Zac Medico
On 11/11/2014 01:14 AM, Alexander Berntsen wrote:
> On 11/11/14 01:17, Zac Medico wrote:
>> We could certainly express it in a way that doesn't involve any
>> mutating loop control variables, but ultimately that's going to
>> lead to more lines of code, and it will leave imperative
>> programmers wondering why we didn't choose a simpler and more
>> succinct approach.
> 
>> For example, we could create an class for iterating over the paths
>> from a given path down to the root directory. Then we could create
>> a function which selects the first element from that iterator that
>> exists. Once the class and function are implemented, their usage
>> would be very succinct:
> 
>> first_parent = first_existing(iter_parents(path))
> I would greatly prefer this. But I suppose I'm in a minority. v2 of
> the patch is fine by me.

Thanks. I eliminated one more backslash, and pushed it.

Now I'm thinking about splitting out a first_existing function so that I
can use it in portage.data._unprivileged_mode(), to determine if the
unprivileged root can be created. Maybe I'll do it with the iterator
approach that we've discussed, and we'll see what the consensus is.
-- 
Thanks,
Zac



Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-11 Thread Alexander Berntsen
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

On 11/11/14 01:17, Zac Medico wrote:
> We could certainly express it in a way that doesn't involve any
> mutating loop control variables, but ultimately that's going to
> lead to more lines of code, and it will leave imperative
> programmers wondering why we didn't choose a simpler and more
> succinct approach.
> 
> For example, we could create an class for iterating over the paths
> from a given path down to the root directory. Then we could create
> a function which selects the first element from that iterator that
> exists. Once the class and function are implemented, their usage
> would be very succinct:
> 
> first_parent = first_existing(iter_parents(path))
I would greatly prefer this. But I suppose I'm in a minority. v2 of
the patch is fine by me.

- -- 
Alexander
berna...@gentoo.org
https://secure.plaimi.net/~alexander
-BEGIN PGP SIGNATURE-
Version: GnuPG v2
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iF4EAREIAAYFAlRh04kACgkQRtClrXBQc7Wg7AD/WmncYIvR/f6OZ9W2mVfpgMmL
pZRD+68xWgWTdvatodYBAIX9VfX/0kINsmV9RhzumhLnHYE7LMz43nLy+yrekbxp
=H68V
-END PGP SIGNATURE-



Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-10 Thread Zac Medico
On 11/10/2014 12:32 PM, Alexander Berntsen wrote:
> On 10/11/14 19:21, Zac Medico wrote:
>> Well, you'll have to clarify what's so "terrible" about it. Note that I 
>> didn't
>> use os.path.isdir or similar because those functions hide all kinds of 
>> relevant
>> exceptions, such as EACCES.
> I wish there were a more declarative way of expressing this in Python.
> It's extremely imperative.

We could certainly express it in a way that doesn't involve any mutating
loop control variables, but ultimately that's going to lead to more
lines of code, and it will leave imperative programmers wondering why we
didn't choose a simpler and more succinct approach.

For example, we could create an class for iterating over the paths from
a given path down to the root directory. Then we could create a function
which selects the first element from that iterator that exists. Once the
class and function are implemented, their usage would be very succinct:

  first_parent = first_existing(iter_parents(path))
-- 
Thanks,
Zac



Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-10 Thread Alexander Berntsen
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

On 10/11/14 19:21, Zac Medico wrote:
> Well, you'll have to clarify what's so "terrible" about it. Note that I didn't
> use os.path.isdir or similar because those functions hide all kinds of 
> relevant
> exceptions, such as EACCES.
I wish there were a more declarative way of expressing this in Python.
It's extremely imperative.

> If it's the continue and break that upset you, we can do it like this:
> 
> found_dir = False
> while current_dir != os.sep and not found_dir:
>   try:
>   os.stat(current_dir)
>   found_dir  = True
>   except OSError:
>   if errno == errno.ENOENT:
>   current_dir = \
>   os.path.dirname(current_dir)
>   else:
>   found_dir  = True
That's a little better -- I'd prefer that. Thanks.
- -- 
Alexander
berna...@gentoo.org
https://secure.plaimi.net/~alexander
-BEGIN PGP SIGNATURE-
Version: GnuPG v2
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iF4EAREIAAYFAlRhIPkACgkQRtClrXBQc7WTpQD7BYE1+KdV8XG4h0JghIJ/dP4v
17isaVatmFdoSQdtwEsA/RXXK33wyWxR4yN0HDENtU5peRJPU/u/eRA/lobm31j9
=jLaK
-END PGP SIGNATURE-



Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-10 Thread Zac Medico
On 11/10/2014 03:09 AM, Alexander Berntsen wrote:
> On 10/11/14 00:24, Zac Medico wrote:
>> ir
>> +while current_dir != os.sep:
>> +try:
>> +st = 
>> os.stat(current_dir)
>> +except OSError as e:
>> +if errno == 
>> errno.ENOENT:
>> +current_dir = \
>> +
>> os.path.dirname(current_dir)
>> +continue
>> +break
> Can you think of a less terrible way of doing this in Python?

Well, you'll have to clarify what's so "terrible" about it. Note that I didn't
use os.path.isdir or similar because those functions hide all kinds of relevant
exceptions, such as EACCES.

If it's the continue and break that upset you, we can do it like this:

found_dir = False
while current_dir != os.sep and not found_dir:
try:
os.stat(current_dir)
found_dir  = True
except OSError:
if errno == errno.ENOENT:
current_dir = \
os.path.dirname(current_dir)
else:
found_dir  = True

-- 
Thanks,
Zac



Re: [gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-10 Thread Alexander Berntsen
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

On 10/11/14 00:24, Zac Medico wrote:
> ir
> + while current_dir != os.sep:
> + try:
> + st = 
> os.stat(current_dir)
> + except OSError as e:
> + if errno == 
> errno.ENOENT:
> + current_dir = \
> + 
> os.path.dirname(current_dir)
> + continue
> + break
Can you think of a less terrible way of doing this in Python?

(Serious question, not snark!)
- -- 
Alexander
berna...@gentoo.org
https://secure.plaimi.net/~alexander
-BEGIN PGP SIGNATURE-
Version: GnuPG v2
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iF4EAREIAAYFAlRgnQYACgkQRtClrXBQc7X7IgD+OlJhVIsqEoeQkrpJhQOTypoU
uxOsZKj57wGO93cGwjQA/i5XAcFiQZz0ljLuZfSaG7rCXU5JtoMN7TDpi1HvF88O
=U/sJ
-END PGP SIGNATURE-



[gentoo-portage-dev] [PATCH] unprivileged mode: generate PORTAGE_DEPCACHEDIR

2014-11-09 Thread Zac Medico
For unprivileged mode, if PORTAGE_DEPCACHEDIR is unset and the default
PORTAGE_DEPCACHEDIR setting does not refer to a writable directory
(or there are not sufficient permissions to create it), then
automatically make PORTAGE_DEPCACHEDIR relative to the current target
root (which should always be writable for unprivileged mode). Also, in
create_trees, propagate the automatically generated PORTAGE_DEPCACHEDIR
setting to the config instance that is instantiated for ROOT = "/".

The result is that unprivileged mode will get a writable
PORTAGE_DEPCACHEDIR by default, and the default can be overridden by
setting the PORTAGE_DEPCACHEDIR variable.

Fixes: 1364fcd89384 ("Support unprivileged mode for bug #433453.")
X-Gentoo-Bug: 433453
X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=433453
---
 pym/portage/__init__.py  |  3 +++
 pym/portage/package/ebuild/config.py | 37 ++--
 2 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index 66bfeb0..d8046f3 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -570,6 +570,7 @@ def create_trees(config_root=None, target_root=None, 
trees=None, env=None,
env=env, eprefix=eprefix)
settings.lock()
 
+   depcachedir = settings.get('PORTAGE_DEPCACHEDIR')
trees._target_eroot = settings['EROOT']
myroots = [(settings['EROOT'], settings)]
if settings["ROOT"] == "/" and settings["EPREFIX"] == const.EPREFIX:
@@ -587,6 +588,8 @@ def create_trees(config_root=None, target_root=None, 
trees=None, env=None,
v = settings.get(k)
if v is not None:
clean_env[k] = v
+   if depcachedir is not None:
+   clean_env['PORTAGE_DEPCACHEDIR'] = depcachedir
settings = config(config_root=None, target_root="/",
env=clean_env, eprefix=None)
settings.lock()
diff --git a/pym/portage/package/ebuild/config.py 
b/pym/portage/package/ebuild/config.py
index 2ceb122..1ce5175 100644
--- a/pym/portage/package/ebuild/config.py
+++ b/pym/portage/package/ebuild/config.py
@@ -8,6 +8,7 @@ __all__ = [
 ]
 
 import copy
+import errno
 from itertools import chain
 import grp
 import logging
@@ -826,16 +827,6 @@ class config(object):
if "USE_ORDER" not in self:
self.backupenv["USE_ORDER"] = 
"env:pkg:conf:defaults:pkginternal:repo:env.d"
 
-   self.depcachedir = DEPCACHE_PATH
-   if portage.const.EPREFIX:
-   self.depcachedir = 
os.path.join(portage.const.EPREFIX,
-   DEPCACHE_PATH.lstrip(os.sep))
-
-   if self.get("PORTAGE_DEPCACHEDIR", None):
-   self.depcachedir = self["PORTAGE_DEPCACHEDIR"]
-   self["PORTAGE_DEPCACHEDIR"] = self.depcachedir
-   self.backup_changes("PORTAGE_DEPCACHEDIR")
-
if "CBUILD" not in self and "CHOST" in self:
self["CBUILD"] = self["CHOST"]
self.backup_changes("CBUILD")
@@ -898,6 +889,32 @@ class config(object):
self[var] = default_val
self.backup_changes(var)
 
+   self.depcachedir = self.get("PORTAGE_DEPCACHEDIR")
+   if self.depcachedir is None:
+   self.depcachedir = os.path.join(os.sep,
+   portage.const.EPREFIX, 
DEPCACHE_PATH.lstrip(os.sep))
+   if unprivileged and target_root != os.sep:
+   # In unprivileged mode, automatically 
make
+   # depcachedir relative to target_root 
if the
+   # default depcachedir is not writable.
+   current_dir = self.depcachedir
+   while current_dir != os.sep:
+   try:
+   st = 
os.stat(current_dir)
+   except OSError as e:
+   if errno == 
errno.ENOENT:
+   current_dir = \
+   
os.path.dirname(current_dir)
+   continue
+   break
+
+   if not os.access(current_dir, os.W_OK):
+   self.depcachedir = 
os.path.join(er