Skip to content

Commit 5b21e25

Browse files
committed
Allow directories to be specified without trailing path separator
1 parent 6200cb8 commit 5b21e25

5 files changed

Lines changed: 27 additions & 39 deletions

File tree

lib/pathmatch.cpp

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,25 +84,21 @@ PathMatch::PathMatch(const std::vector<std::string> &paths, const std::string &b
8484
if (p.front() == '.')
8585
p = mBasepath + "/" + p;
8686

87-
p = Path::fromNativeSeparators(p);
87+
p = Path::fromNativeSeparators(Path::simplifyPath(p));
8888

89-
if (Path::isAbsolute(p)) {
90-
p = Path::simplifyPath(p);
89+
if (p.back() == '/')
90+
p.pop_back();
9191

92-
if (p.back() == '/')
93-
regex_string.append("^" + translate(p));
94-
else
95-
regex_string.append("^" + translate(p) + "$");
96-
} else {
97-
if (p.back() == '/')
98-
regex_string.append("/" + translate(p));
99-
else
100-
regex_string.append("/" + translate(p) + "$");
101-
}
92+
if (Path::isAbsolute(p))
93+
regex_string.push_back('^');
94+
else
95+
regex_string.push_back('/');
96+
97+
regex_string.append(translate(p) + "(/|$)");
10298
}
10399

104100
if (regex_string.empty())
105-
regex_string = "^$";
101+
return;
106102

107103
if (mode == Mode::icase)
108104
mRegex = std::regex(regex_string, std::regex_constants::extended | std::regex_constants::icase);

lib/pathmatch.h

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,32 +31,25 @@
3131

3232
/**
3333
* Path matching rules:
34+
* - All rules are simplified first (path separators vary by platform):
35+
* - '/./' => '/'
36+
* - '/dir/../' => '/'
37+
* - '//' => '/'
38+
* - Trailing slashes are removed
39+
* - Rules can contain globs:
40+
* - '**' matches any number of characters including path separators.
41+
* - '*' matches any number of characters except path separators.
42+
* - '?' matches any single character except path separators.
3443
* - If a rule looks like an absolute path (e.g. starts with '/', but varies by platform):
35-
* - The rule will be simplified (path separators vary by platform):
36-
* - '/./' => '/'
37-
* - '/dir/../' => '/'
38-
* - '//' => '/'
39-
* - If the rule ends with a path separator, match all files where the rule matches the start of the file's
40-
* simplified absolute path. Globs are allowed in the rule.
41-
* - Otherwise, match all files where the rule matches the file's simplified absolute path.
42-
* Globs are allowed in the rule.
44+
* - Match all files where the rule matches the start of the file's simplified absolute path up until a path
45+
* separator or the end of the pathname.
4346
* - If a rule starts with '.':
4447
* - The rule is interpreted as a path relative to `basepath` and then converted to an absolute path and
4548
* treated as such according to the above procedure. If the rule is relative to some other directory, it should
4649
* be modified to be relative to `basepath` first (this should be done with rules in project files, for example).
4750
* - Otherwise:
48-
* - No simplification is done to the rule.
49-
* - If the rule ends with a path separator:
50-
* - Match all files where the rule matches any part of the file's simplified absolute path, and the matching
51-
* part directly follows a path separator. Globs are allowed in the rule.
52-
* - Otherwise:
53-
* - Match all files where the rule matches the end of the file's simplified absolute path, and the matching
54-
* part directly follows a path separator. Globs are allowed in the rule.
55-
*
56-
* - Glob rules:
57-
* - '**' matches any number of characters including path separators.
58-
* - '*' matches any number of characters except path separators.
59-
* - '?' matches any single character except path separators.
51+
* - Match all files where the rule matches any part of the file's simplified absolute path up until a
52+
* path separator or the end of the pathname, and the matching part directly follows a path separator.
6053
**/
6154

6255
/**

test/cli/other_test.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2478,7 +2478,6 @@ def test_addon_suppr_cli_line(tmp_path):
24782478
__test_addon_suppr(tmp_path, ['--suppress=misra-c2012-2.3:*:3'])
24792479

24802480

2481-
@pytest.mark.xfail(strict=True) # #13437 - TODO: suppression needs to match the whole input path
24822481
def test_addon_suppr_cli_file_line(tmp_path):
24832482
__test_addon_suppr(tmp_path, ['--suppress=misra-c2012-2.3:test.c:3'])
24842483

test/testcmdlineparser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3345,7 +3345,7 @@ class TestCmdlineParser : public TestFixture {
33453345
const char * const argv[] = {"cppcheck", "-isrc\\file.cpp", "src/file.cpp"};
33463346
ASSERT(!fillSettingsFromArgs(argv));
33473347
ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
3348-
ASSERT_EQUALS("src/file.cpp", parser->getIgnoredPaths()[0]);
3348+
ASSERT_EQUALS("src\\file.cpp", parser->getIgnoredPaths()[0]);
33493349
ASSERT_EQUALS(1, parser->getPathNames().size());
33503350
ASSERT_EQUALS("src/file.cpp", parser->getPathNames()[0]);
33513351
ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str());
@@ -3367,7 +3367,7 @@ class TestCmdlineParser : public TestFixture {
33673367
const char * const argv[] = {"cppcheck", "-isrc\\", "src\\file.cpp"};
33683368
ASSERT(!fillSettingsFromArgs(argv));
33693369
ASSERT_EQUALS(1, parser->getIgnoredPaths().size());
3370-
ASSERT_EQUALS("src/", parser->getIgnoredPaths()[0]);
3370+
ASSERT_EQUALS("src\\", parser->getIgnoredPaths()[0]);
33713371
ASSERT_EQUALS(1, parser->getPathNames().size());
33723372
ASSERT_EQUALS("src/file.cpp", parser->getPathNames()[0]);
33733373
ASSERT_EQUALS("cppcheck: error: could not find or open any of the paths given.\ncppcheck: Maybe all paths were ignored?\n", logger->str());

test/testpathmatch.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class TestPathMatch : public TestFixture {
156156
}
157157

158158
void onemaskcwd() const {
159-
ASSERT(!srcMatcher.match("./src"));
159+
ASSERT(srcMatcher.match("./src"));
160160
}
161161

162162
void twomasklongerpath1() const {
@@ -229,9 +229,9 @@ class TestPathMatch : public TestFixture {
229229
PathMatch match({"test?.cpp"});
230230
ASSERT(match.match("test1.cpp"));
231231
ASSERT(match.match("src/test1.cpp"));
232+
ASSERT(match.match("test1.cpp/src"));
232233
ASSERT(!match.match("test1.c"));
233234
ASSERT(!match.match("test.cpp"));
234-
ASSERT(!match.match("test1.cpp/src"));
235235
}
236236

237237
void globstar1() const {

0 commit comments

Comments
 (0)