Skip to content

Commit 77e4529

Browse files
authored
fixed #12754 - avoid unnecessary lookups when specified library has an absolute path (#6513)
1 parent 43b4b70 commit 77e4529

2 files changed

Lines changed: 72 additions & 21 deletions

File tree

lib/library.cpp

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,15 @@ Library::Error Library::load(const char exename[], const char path[], bool debug
8787
return Error();
8888
}
8989

90+
const bool is_abs_path = Path::isAbsolute(path);
91+
9092
std::string absolute_path;
9193
// open file..
9294
tinyxml2::XMLDocument doc;
9395
if (debug)
9496
std::cout << "looking for library '" + std::string(path) + "'" << std::endl;
9597
tinyxml2::XMLError error = doc.LoadFile(path);
98+
// TODO: do not ignore read errors
9699
if (error == tinyxml2::XML_ERROR_FILE_READ_ERROR && Path::getFilenameExtension(path).empty())
97100
{
98101
// Reading file failed, try again...
@@ -110,27 +113,31 @@ Library::Error Library::load(const char exename[], const char path[], bool debug
110113
absolute_path = Path::getAbsoluteFilePath(fullfilename);
111114
}
112115

113-
std::list<std::string> cfgfolders;
114-
#ifdef FILESDIR
115-
cfgfolders.emplace_back(FILESDIR "/cfg");
116-
#endif
117-
if (exename) {
118-
const std::string exepath(Path::fromNativeSeparators(Path::getPathFromFilename(Path::getCurrentExecutablePath(exename))));
119-
cfgfolders.push_back(exepath + "cfg");
120-
cfgfolders.push_back(exepath + "../cfg");
121-
cfgfolders.push_back(exepath);
122-
}
116+
// only perform further lookups when the given path was not absolute
117+
if (!is_abs_path && error == tinyxml2::XML_ERROR_FILE_NOT_FOUND)
118+
{
119+
std::list<std::string> cfgfolders;
120+
#ifdef FILESDIR
121+
cfgfolders.emplace_back(FILESDIR "/cfg");
122+
#endif
123+
if (exename) {
124+
const std::string exepath(Path::fromNativeSeparators(Path::getPathFromFilename(Path::getCurrentExecutablePath(exename))));
125+
cfgfolders.push_back(exepath + "cfg");
126+
cfgfolders.push_back(exepath + "../cfg");
127+
cfgfolders.push_back(exepath);
128+
}
123129

124-
while (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND && !cfgfolders.empty()) {
125-
const std::string cfgfolder(cfgfolders.back());
126-
cfgfolders.pop_back();
127-
const char *sep = (!cfgfolder.empty() && endsWith(cfgfolder,'/') ? "" : "/");
128-
const std::string filename(cfgfolder + sep + fullfilename);
129-
if (debug)
130-
std::cout << "looking for library '" + std::string(filename) + "'" << std::endl;
131-
error = doc.LoadFile(filename.c_str());
132-
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
133-
absolute_path = Path::getAbsoluteFilePath(filename);
130+
while (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND && !cfgfolders.empty()) {
131+
const std::string cfgfolder(cfgfolders.back());
132+
cfgfolders.pop_back();
133+
const char *sep = (!cfgfolder.empty() && endsWith(cfgfolder,'/') ? "" : "/");
134+
const std::string filename(cfgfolder + sep + fullfilename);
135+
if (debug)
136+
std::cout << "looking for library '" + std::string(filename) + "'" << std::endl;
137+
error = doc.LoadFile(filename.c_str());
138+
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
139+
absolute_path = Path::getAbsoluteFilePath(filename);
140+
}
134141
}
135142
} else
136143
absolute_path = Path::getAbsoluteFilePath(path);

test/cli/other_test.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111

1212
def __remove_std_lookup_log(l : list, exepath):
13-
print(l)
1413
l.remove("looking for library 'std.cfg'")
1514
l.remove("looking for library '{}/std.cfg'".format(exepath))
1615
l.remove("looking for library '{}/../cfg/std.cfg'".format(exepath))
@@ -1570,3 +1569,48 @@ def test_lib_lookup_notfound(tmpdir):
15701569
"library not found: 'none'",
15711570
"cppcheck: Failed to load library configuration file 'none'. File not found"
15721571
]
1572+
1573+
1574+
def test_lib_lookup_absolute(tmpdir):
1575+
test_file = os.path.join(tmpdir, 'test.c')
1576+
with open(test_file, 'wt'):
1577+
pass
1578+
1579+
cfg_file = os.path.join(tmpdir, 'test.cfg')
1580+
with open(cfg_file, 'wt') as f:
1581+
f.write('''
1582+
<?xml version="1.0"?>
1583+
<def format="2">
1584+
</def>
1585+
''')
1586+
1587+
exitcode, stdout, _, exe = cppcheck_ex(['--library={}'.format(cfg_file), '--debug-lookup', test_file])
1588+
exepath = os.path.dirname(exe)
1589+
if sys.platform == 'win32':
1590+
exepath = exepath.replace('\\', '/')
1591+
assert exitcode == 0, stdout
1592+
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
1593+
assert lines == [
1594+
"looking for library '{}'".format(cfg_file),
1595+
'Checking {} ...'.format(test_file)
1596+
]
1597+
1598+
1599+
def test_lib_lookup_absolute_notfound(tmpdir):
1600+
test_file = os.path.join(tmpdir, 'test.c')
1601+
with open(test_file, 'wt'):
1602+
pass
1603+
1604+
cfg_file = os.path.join(tmpdir, 'test.cfg')
1605+
1606+
exitcode, stdout, _, exe = cppcheck_ex(['--library={}'.format(cfg_file), '--debug-lookup', test_file])
1607+
exepath = os.path.dirname(exe)
1608+
if sys.platform == 'win32':
1609+
exepath = exepath.replace('\\', '/')
1610+
assert exitcode == 1, stdout
1611+
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
1612+
assert lines == [
1613+
"looking for library '{}'".format(cfg_file),
1614+
"library not found: '{}'".format(cfg_file),
1615+
"cppcheck: Failed to load library configuration file '{}'. File not found".format(cfg_file)
1616+
]

0 commit comments

Comments
 (0)