Zac Medico
2018-06-24 22:02:07 UTC
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:
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
2.13.6