Fix the python INSTALL_MASK implementation so that a trailing slash
matches a directory, for compatibility with the previous bash
implementation.

Fixes: 3416876c0ee7 ("{,PKG_}INSTALL_MASK: python implementation")
Bug: https://bugs.gentoo.org/658322
---
 pym/portage/tests/util/test_install_mask.py | 87 +++++++++++++++++++++++++++++
 pym/portage/util/install_mask.py            |  7 ++-
 2 files changed, 92 insertions(+), 2 deletions(-)
 create mode 100644 pym/portage/tests/util/test_install_mask.py

diff --git a/pym/portage/tests/util/test_install_mask.py 
b/pym/portage/tests/util/test_install_mask.py
new file mode 100644
index 0000000000..0badcf0165
--- /dev/null
+++ b/pym/portage/tests/util/test_install_mask.py
@@ -0,0 +1,87 @@
+# Copyright 2018 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from portage.tests import TestCase
+from portage.util.install_mask import InstallMask
+
+
+class InstallMaskTestCase(TestCase):
+
+       def testTrailingSlash(self):
+               """
+               Test that elements with a trailing slash match a directory
+               but not a regular file.
+               """
+               cases = (
+                       (
+                               '/foo/bar/ -/foo/bar/*.foo -*.baz',
+                               (
+                                       (
+                                               'foo/bar/baz',
+                                               True,
+                                       ),
+                                       (
+                                               'foo/bar/',
+                                               True,
+                                       ),
+                                       # /foo/bar/ does not match
+                                       (
+                                               'foo/bar',
+                                               False,
+                                       ),
+                                       # this is excluded
+                                       (
+                                               'foo/bar/baz.foo',
+                                               False,
+                                       ),
+                                       # this is excluded
+                                       (
+                                               'foo/bar/baz.baz',
+                                               False,
+                                       ),
+                                       (
+                                               'foo/bar/baz.bar',
+                                               True,
+                                       ),
+                               )
+                       ),
+                       (
+                               '/foo/bar -/foo/bar/*.foo -*.baz',
+                               (
+                                       (
+                                               'foo/bar/baz',
+                                               True,
+                                       ),
+                                       # /foo/bar matches both foo/bar/ and 
foo/bar
+                                       (
+                                               'foo/bar/',
+                                               True,
+                                       ),
+                                       (
+                                               'foo/bar',
+                                               True,
+                                       ),
+                                       # this is excluded
+                                       (
+                                               'foo/bar/baz.foo',
+                                               False,
+                                       ),
+                                       # this is excluded
+                                       (
+                                               'foo/bar/baz.baz',
+                                               False,
+                                       ),
+                                       (
+                                               'foo/bar/baz.bar',
+                                               True,
+                                       ),
+                               )
+                       ),
+               )
+
+               for install_mask_str, paths in cases:
+                       install_mask = InstallMask(install_mask_str)
+                       for path, expected in paths:
+                               self.assertEqual(install_mask.match(path), 
expected,
+                                       'unexpected match result for "{}" with 
path {}'.\
+                                       format(install_mask_str, path))
diff --git a/pym/portage/util/install_mask.py b/pym/portage/util/install_mask.py
index 1667d883a0..32627eb05b 100644
--- a/pym/portage/util/install_mask.py
+++ b/pym/portage/util/install_mask.py
@@ -41,10 +41,13 @@ class InstallMask(object):
                                pattern = pattern[1:]
                        # absolute path pattern
                        if pattern.startswith('/'):
+                               # handle trailing slash for explicit directory 
match
+                               if path.endswith('/'):
+                                       pattern = pattern.rstrip('/') + '/'
                                # match either exact path or one of parent dirs
                                # the latter is done via matching pattern/*
                                if (fnmatch.fnmatch(path, pattern[1:])
-                                               or fnmatch.fnmatch(path, 
pattern[1:] + '/*')):
+                                               or fnmatch.fnmatch(path, 
pattern[1:].rstrip('/') + '/*')):
                                        ret = is_inclusive
                        # filename
                        else:
@@ -118,7 +121,7 @@ def install_mask_dir(base_dir, install_mask, onerror=None):
                except IndexError:
                        break
 
-               if install_mask.match(dir_path[base_dir_len:]):
+               if install_mask.match(dir_path[base_dir_len:] + '/'):
                        try:
                                os.rmdir(dir_path)
                        except OSError:
-- 
2.13.6


Reply via email to