Gentoo Archives: gentoo-portage-dev

From: Zac Medico <zmedico@g.o>
To: gentoo-portage-dev@l.g.o
Cc: Zac Medico <zmedico@g.o>
Subject: [gentoo-portage-dev] [PATCH] {,PKG_}INSTALL_MASK: support trailing slash (bug 658322)
Date: Sun, 24 Jun 2018 22:04:17
Message-Id: 20180624220207.2027-1-zmedico@gentoo.org
1 Fix the python INSTALL_MASK implementation so that a trailing slash
2 matches a directory, for compatibility with the previous bash
3 implementation.
4
5 Fixes: 3416876c0ee7 ("{,PKG_}INSTALL_MASK: python implementation")
6 Bug: https://bugs.gentoo.org/658322
7 ---
8 pym/portage/tests/util/test_install_mask.py | 87 +++++++++++++++++++++++++++++
9 pym/portage/util/install_mask.py | 7 ++-
10 2 files changed, 92 insertions(+), 2 deletions(-)
11 create mode 100644 pym/portage/tests/util/test_install_mask.py
12
13 diff --git a/pym/portage/tests/util/test_install_mask.py b/pym/portage/tests/util/test_install_mask.py
14 new file mode 100644
15 index 0000000000..0badcf0165
16 --- /dev/null
17 +++ b/pym/portage/tests/util/test_install_mask.py
18 @@ -0,0 +1,87 @@
19 +# Copyright 2018 Gentoo Foundation
20 +# Distributed under the terms of the GNU General Public License v2
21 +
22 +from portage.tests import TestCase
23 +from portage.util.install_mask import InstallMask
24 +
25 +
26 +class InstallMaskTestCase(TestCase):
27 +
28 + def testTrailingSlash(self):
29 + """
30 + Test that elements with a trailing slash match a directory
31 + but not a regular file.
32 + """
33 + cases = (
34 + (
35 + '/foo/bar/ -/foo/bar/*.foo -*.baz',
36 + (
37 + (
38 + 'foo/bar/baz',
39 + True,
40 + ),
41 + (
42 + 'foo/bar/',
43 + True,
44 + ),
45 + # /foo/bar/ does not match
46 + (
47 + 'foo/bar',
48 + False,
49 + ),
50 + # this is excluded
51 + (
52 + 'foo/bar/baz.foo',
53 + False,
54 + ),
55 + # this is excluded
56 + (
57 + 'foo/bar/baz.baz',
58 + False,
59 + ),
60 + (
61 + 'foo/bar/baz.bar',
62 + True,
63 + ),
64 + )
65 + ),
66 + (
67 + '/foo/bar -/foo/bar/*.foo -*.baz',
68 + (
69 + (
70 + 'foo/bar/baz',
71 + True,
72 + ),
73 + # /foo/bar matches both foo/bar/ and foo/bar
74 + (
75 + 'foo/bar/',
76 + True,
77 + ),
78 + (
79 + 'foo/bar',
80 + True,
81 + ),
82 + # this is excluded
83 + (
84 + 'foo/bar/baz.foo',
85 + False,
86 + ),
87 + # this is excluded
88 + (
89 + 'foo/bar/baz.baz',
90 + False,
91 + ),
92 + (
93 + 'foo/bar/baz.bar',
94 + True,
95 + ),
96 + )
97 + ),
98 + )
99 +
100 + for install_mask_str, paths in cases:
101 + install_mask = InstallMask(install_mask_str)
102 + for path, expected in paths:
103 + self.assertEqual(install_mask.match(path), expected,
104 + 'unexpected match result for "{}" with path {}'.\
105 + format(install_mask_str, path))
106 diff --git a/pym/portage/util/install_mask.py b/pym/portage/util/install_mask.py
107 index 1667d883a0..32627eb05b 100644
108 --- a/pym/portage/util/install_mask.py
109 +++ b/pym/portage/util/install_mask.py
110 @@ -41,10 +41,13 @@ class InstallMask(object):
111 pattern = pattern[1:]
112 # absolute path pattern
113 if pattern.startswith('/'):
114 + # handle trailing slash for explicit directory match
115 + if path.endswith('/'):
116 + pattern = pattern.rstrip('/') + '/'
117 # match either exact path or one of parent dirs
118 # the latter is done via matching pattern/*
119 if (fnmatch.fnmatch(path, pattern[1:])
120 - or fnmatch.fnmatch(path, pattern[1:] + '/*')):
121 + or fnmatch.fnmatch(path, pattern[1:].rstrip('/') + '/*')):
122 ret = is_inclusive
123 # filename
124 else:
125 @@ -118,7 +121,7 @@ def install_mask_dir(base_dir, install_mask, onerror=None):
126 except IndexError:
127 break
128
129 - if install_mask.match(dir_path[base_dir_len:]):
130 + if install_mask.match(dir_path[base_dir_len:] + '/'):
131 try:
132 os.rmdir(dir_path)
133 except OSError:
134 --
135 2.13.6