1 |
commit: deb87a465306d05146d7eb55d27d7d89943725c0 |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jun 24 21:42:52 2018 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Wed Jun 27 03:15:08 2018 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=deb87a46 |
7 |
|
8 |
{,PKG_}INSTALL_MASK: support trailing slash (bug 658322) |
9 |
|
10 |
Fix the python INSTALL_MASK implementation so that a trailing slash |
11 |
matches a directory, for compatibility with the previous bash |
12 |
implementation. |
13 |
|
14 |
Fixes: 3416876c0ee7 ("{,PKG_}INSTALL_MASK: python implementation") |
15 |
Bug: https://bugs.gentoo.org/658322 |
16 |
|
17 |
pym/portage/tests/util/test_install_mask.py | 129 ++++++++++++++++++++++++++++ |
18 |
pym/portage/util/install_mask.py | 7 +- |
19 |
2 files changed, 134 insertions(+), 2 deletions(-) |
20 |
|
21 |
diff --git a/pym/portage/tests/util/test_install_mask.py b/pym/portage/tests/util/test_install_mask.py |
22 |
new file mode 100644 |
23 |
index 000000000..f651eb4b7 |
24 |
--- /dev/null |
25 |
+++ b/pym/portage/tests/util/test_install_mask.py |
26 |
@@ -0,0 +1,129 @@ |
27 |
+# Copyright 2018 Gentoo Foundation |
28 |
+# Distributed under the terms of the GNU General Public License v2 |
29 |
+ |
30 |
+from portage.tests import TestCase |
31 |
+from portage.util.install_mask import InstallMask |
32 |
+ |
33 |
+ |
34 |
+class InstallMaskTestCase(TestCase): |
35 |
+ |
36 |
+ def testTrailingSlash(self): |
37 |
+ """ |
38 |
+ Test that elements with a trailing slash match a directory |
39 |
+ but not a regular file. |
40 |
+ """ |
41 |
+ cases = ( |
42 |
+ ( |
43 |
+ '/foo/bar/ -/foo/bar/*.foo -*.baz', |
44 |
+ ( |
45 |
+ ( |
46 |
+ 'foo/bar/baz', |
47 |
+ True, |
48 |
+ ), |
49 |
+ ( |
50 |
+ 'foo/bar/', |
51 |
+ True, |
52 |
+ ), |
53 |
+ # /foo/bar/ does not match |
54 |
+ ( |
55 |
+ 'foo/bar', |
56 |
+ False, |
57 |
+ ), |
58 |
+ # this is excluded |
59 |
+ ( |
60 |
+ 'foo/bar/baz.foo', |
61 |
+ False, |
62 |
+ ), |
63 |
+ # this is excluded |
64 |
+ ( |
65 |
+ 'foo/bar/baz.baz', |
66 |
+ False, |
67 |
+ ), |
68 |
+ ( |
69 |
+ 'foo/bar/baz.bar', |
70 |
+ True, |
71 |
+ ), |
72 |
+ ) |
73 |
+ ), |
74 |
+ ( |
75 |
+ '/foo/bar -/foo/bar/*.foo -*.baz', |
76 |
+ ( |
77 |
+ ( |
78 |
+ 'foo/bar/baz', |
79 |
+ True, |
80 |
+ ), |
81 |
+ # /foo/bar matches both foo/bar/ and foo/bar |
82 |
+ ( |
83 |
+ 'foo/bar/', |
84 |
+ True, |
85 |
+ ), |
86 |
+ ( |
87 |
+ 'foo/bar', |
88 |
+ True, |
89 |
+ ), |
90 |
+ # this is excluded |
91 |
+ ( |
92 |
+ 'foo/bar/baz.foo', |
93 |
+ False, |
94 |
+ ), |
95 |
+ # this is excluded |
96 |
+ ( |
97 |
+ 'foo/bar/baz.baz', |
98 |
+ False, |
99 |
+ ), |
100 |
+ ( |
101 |
+ 'foo/bar/baz.bar', |
102 |
+ True, |
103 |
+ ), |
104 |
+ ) |
105 |
+ ), |
106 |
+ ( |
107 |
+ '/foo*', |
108 |
+ ( |
109 |
+ ( |
110 |
+ 'foo', |
111 |
+ True, |
112 |
+ ), |
113 |
+ ( |
114 |
+ 'foo/', |
115 |
+ True, |
116 |
+ ), |
117 |
+ ( |
118 |
+ 'foobar', |
119 |
+ True, |
120 |
+ ), |
121 |
+ ( |
122 |
+ 'foobar/', |
123 |
+ True, |
124 |
+ ), |
125 |
+ ) |
126 |
+ ), |
127 |
+ ( |
128 |
+ '/foo*/', |
129 |
+ ( |
130 |
+ ( |
131 |
+ 'foo', |
132 |
+ False, |
133 |
+ ), |
134 |
+ ( |
135 |
+ 'foo/', |
136 |
+ True, |
137 |
+ ), |
138 |
+ ( |
139 |
+ 'foobar', |
140 |
+ False, |
141 |
+ ), |
142 |
+ ( |
143 |
+ 'foobar/', |
144 |
+ True, |
145 |
+ ), |
146 |
+ ) |
147 |
+ ), |
148 |
+ ) |
149 |
+ |
150 |
+ for install_mask_str, paths in cases: |
151 |
+ install_mask = InstallMask(install_mask_str) |
152 |
+ for path, expected in paths: |
153 |
+ self.assertEqual(install_mask.match(path), expected, |
154 |
+ 'unexpected match result for "{}" with path {}'.\ |
155 |
+ format(install_mask_str, path)) |
156 |
|
157 |
diff --git a/pym/portage/util/install_mask.py b/pym/portage/util/install_mask.py |
158 |
index 1667d883a..32627eb05 100644 |
159 |
--- a/pym/portage/util/install_mask.py |
160 |
+++ b/pym/portage/util/install_mask.py |
161 |
@@ -41,10 +41,13 @@ class InstallMask(object): |
162 |
pattern = pattern[1:] |
163 |
# absolute path pattern |
164 |
if pattern.startswith('/'): |
165 |
+ # handle trailing slash for explicit directory match |
166 |
+ if path.endswith('/'): |
167 |
+ pattern = pattern.rstrip('/') + '/' |
168 |
# match either exact path or one of parent dirs |
169 |
# the latter is done via matching pattern/* |
170 |
if (fnmatch.fnmatch(path, pattern[1:]) |
171 |
- or fnmatch.fnmatch(path, pattern[1:] + '/*')): |
172 |
+ or fnmatch.fnmatch(path, pattern[1:].rstrip('/') + '/*')): |
173 |
ret = is_inclusive |
174 |
# filename |
175 |
else: |
176 |
@@ -118,7 +121,7 @@ def install_mask_dir(base_dir, install_mask, onerror=None): |
177 |
except IndexError: |
178 |
break |
179 |
|
180 |
- if install_mask.match(dir_path[base_dir_len:]): |
181 |
+ if install_mask.match(dir_path[base_dir_len:] + '/'): |
182 |
try: |
183 |
os.rmdir(dir_path) |
184 |
except OSError: |