commit: deb87a465306d05146d7eb55d27d7d89943725c0 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Sun Jun 24 21:42:52 2018 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Wed Jun 27 03:15:08 2018 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=deb87a46
{,PKG_}INSTALL_MASK: support trailing slash (bug 658322) 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 | 129 ++++++++++++++++++++++++++++ pym/portage/util/install_mask.py | 7 +- 2 files changed, 134 insertions(+), 2 deletions(-) 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 000000000..f651eb4b7 --- /dev/null +++ b/pym/portage/tests/util/test_install_mask.py @@ -0,0 +1,129 @@ +# 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, + ), + ) + ), + ( + '/foo*', + ( + ( + 'foo', + True, + ), + ( + 'foo/', + True, + ), + ( + 'foobar', + True, + ), + ( + 'foobar/', + True, + ), + ) + ), + ( + '/foo*/', + ( + ( + 'foo', + False, + ), + ( + 'foo/', + True, + ), + ( + 'foobar', + False, + ), + ( + 'foobar/', + 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 1667d883a..32627eb05 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: