Mercurial > hg
comparison mercurial/match.py @ 43949:8b1a9ba375e5
match: make sure `root` argument is always an absolute path (API)
The `root` argument should already be an absolute path, but we had
tests that passed a relative path. This patch fixes up the tests and
adds an assertion.
This assumes that `os.path.isabs('/repo')` will be `True` on all
platforms we care to run tests on. Augie tested for me that it does
work on Windows, so that's good enough for me.
Differential Revision: https://phab.mercurial-scm.org/D7649
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Fri, 13 Dec 2019 11:21:31 -0800 |
parents | 7eb701e355bd |
children | 5685ce2ea3bf |
comparison
equal
deleted
inserted
replaced
43948:9595b6a9f0d5 | 43949:8b1a9ba375e5 |
---|---|
181 'subinclude:<path>' - a file of patterns to match against files under | 181 'subinclude:<path>' - a file of patterns to match against files under |
182 the same directory | 182 the same directory |
183 '<something>' - a pattern of the specified default type | 183 '<something>' - a pattern of the specified default type |
184 | 184 |
185 Usually a patternmatcher is returned: | 185 Usually a patternmatcher is returned: |
186 >>> match(b'foo', b'.', [b're:.*\.c$', b'path:foo/a', b'*.py']) | 186 >>> match(b'/foo', b'.', [b're:.*\.c$', b'path:foo/a', b'*.py']) |
187 <patternmatcher patterns='.*\\.c$|foo/a(?:/|$)|[^/]*\\.py$'> | 187 <patternmatcher patterns='.*\\.c$|foo/a(?:/|$)|[^/]*\\.py$'> |
188 | 188 |
189 Combining 'patterns' with 'include' (resp. 'exclude') gives an | 189 Combining 'patterns' with 'include' (resp. 'exclude') gives an |
190 intersectionmatcher (resp. a differencematcher): | 190 intersectionmatcher (resp. a differencematcher): |
191 >>> type(match(b'foo', b'.', [b're:.*\.c$'], include=[b'path:lib'])) | 191 >>> type(match(b'/foo', b'.', [b're:.*\.c$'], include=[b'path:lib'])) |
192 <class 'mercurial.match.intersectionmatcher'> | 192 <class 'mercurial.match.intersectionmatcher'> |
193 >>> type(match(b'foo', b'.', [b're:.*\.c$'], exclude=[b'path:build'])) | 193 >>> type(match(b'/foo', b'.', [b're:.*\.c$'], exclude=[b'path:build'])) |
194 <class 'mercurial.match.differencematcher'> | 194 <class 'mercurial.match.differencematcher'> |
195 | 195 |
196 Notice that, if 'patterns' is empty, an alwaysmatcher is returned: | 196 Notice that, if 'patterns' is empty, an alwaysmatcher is returned: |
197 >>> match(b'foo', b'.', []) | 197 >>> match(b'/foo', b'.', []) |
198 <alwaysmatcher> | 198 <alwaysmatcher> |
199 | 199 |
200 The 'default' argument determines which kind of pattern is assumed if a | 200 The 'default' argument determines which kind of pattern is assumed if a |
201 pattern has no prefix: | 201 pattern has no prefix: |
202 >>> match(b'foo', b'.', [b'.*\.c$'], default=b're') | 202 >>> match(b'/foo', b'.', [b'.*\.c$'], default=b're') |
203 <patternmatcher patterns='.*\\.c$'> | 203 <patternmatcher patterns='.*\\.c$'> |
204 >>> match(b'foo', b'.', [b'main.py'], default=b'relpath') | 204 >>> match(b'/foo', b'.', [b'main.py'], default=b'relpath') |
205 <patternmatcher patterns='main\\.py(?:/|$)'> | 205 <patternmatcher patterns='main\\.py(?:/|$)'> |
206 >>> match(b'foo', b'.', [b'main.py'], default=b're') | 206 >>> match(b'/foo', b'.', [b'main.py'], default=b're') |
207 <patternmatcher patterns='main.py'> | 207 <patternmatcher patterns='main.py'> |
208 | 208 |
209 The primary use of matchers is to check whether a value (usually a file | 209 The primary use of matchers is to check whether a value (usually a file |
210 name) matches againset one of the patterns given at initialization. There | 210 name) matches againset one of the patterns given at initialization. There |
211 are two ways of doing this check. | 211 are two ways of doing this check. |
212 | 212 |
213 >>> m = match(b'foo', b'', [b're:.*\.c$', b'relpath:a']) | 213 >>> m = match(b'/foo', b'', [b're:.*\.c$', b'relpath:a']) |
214 | 214 |
215 1. Calling the matcher with a file name returns True if any pattern | 215 1. Calling the matcher with a file name returns True if any pattern |
216 matches that file name: | 216 matches that file name: |
217 >>> m(b'a') | 217 >>> m(b'a') |
218 True | 218 True |
226 >>> m.exact(b'a') | 226 >>> m.exact(b'a') |
227 True | 227 True |
228 >>> m.exact(b'main.c') | 228 >>> m.exact(b'main.c') |
229 False | 229 False |
230 """ | 230 """ |
231 assert os.path.isabs(root) | |
231 normalize = _donormalize | 232 normalize = _donormalize |
232 if icasefs: | 233 if icasefs: |
233 dirstate = ctx.repo().dirstate | 234 dirstate = ctx.repo().dirstate |
234 dsnormalize = dirstate.normalize | 235 dsnormalize = dirstate.normalize |
235 | 236 |
938 """Adapt a matcher to work on a subdirectory only. | 939 """Adapt a matcher to work on a subdirectory only. |
939 | 940 |
940 The paths are remapped to remove/insert the path as needed: | 941 The paths are remapped to remove/insert the path as needed: |
941 | 942 |
942 >>> from . import pycompat | 943 >>> from . import pycompat |
943 >>> m1 = match(b'root', b'', [b'a.txt', b'sub/b.txt']) | 944 >>> m1 = match(b'/root', b'', [b'a.txt', b'sub/b.txt']) |
944 >>> m2 = subdirmatcher(b'sub', m1) | 945 >>> m2 = subdirmatcher(b'sub', m1) |
945 >>> m2(b'a.txt') | 946 >>> m2(b'a.txt') |
946 False | 947 False |
947 >>> m2(b'b.txt') | 948 >>> m2(b'b.txt') |
948 True | 949 True |
1022 The matcher's non-matching-attributes (bad, traversedir) are ignored. | 1023 The matcher's non-matching-attributes (bad, traversedir) are ignored. |
1023 | 1024 |
1024 The prefix path should usually be the relative path from the root of | 1025 The prefix path should usually be the relative path from the root of |
1025 this matcher to the root of the wrapped matcher. | 1026 this matcher to the root of the wrapped matcher. |
1026 | 1027 |
1027 >>> m1 = match(util.localpath(b'root/d/e'), b'f', [b'../a.txt', b'b.txt']) | 1028 >>> m1 = match(util.localpath(b'/root/d/e'), b'f', [b'../a.txt', b'b.txt'], auditor=lambda name: None) |
1028 >>> m2 = prefixdirmatcher(b'd/e', m1) | 1029 >>> m2 = prefixdirmatcher(b'd/e', m1) |
1029 >>> m2(b'a.txt') | 1030 >>> m2(b'a.txt') |
1030 False | 1031 False |
1031 >>> m2(b'd/e/a.txt') | 1032 >>> m2(b'd/e/a.txt') |
1032 True | 1033 True |