Skip to content

Commit

Permalink
fixed #12754 - avoid unnecessary lookups when specified library has a…
Browse files Browse the repository at this point in the history
…n absolute path
  • Loading branch information
firewave committed Jun 11, 2024
1 parent 20472f5 commit b53409b
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 21 deletions.
47 changes: 27 additions & 20 deletions lib/library.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,15 @@ Library::Error Library::load(const char exename[], const char path[], bool debug
return Error();
}

const bool is_abs_path = Path::isAbsolute(path);

std::string absolute_path;
// open file..
tinyxml2::XMLDocument doc;
if (debug)
std::cout << "looking for library '" + std::string(path) + "'" << std::endl;
tinyxml2::XMLError error = doc.LoadFile(path);
// TODO: do not ignore read errors
if (error == tinyxml2::XML_ERROR_FILE_READ_ERROR && Path::getFilenameExtension(path).empty())
{
// Reading file failed, try again...
Expand All @@ -110,27 +113,31 @@ Library::Error Library::load(const char exename[], const char path[], bool debug
absolute_path = Path::getAbsoluteFilePath(fullfilename);
}

std::list<std::string> cfgfolders;
#ifdef FILESDIR
cfgfolders.emplace_back(FILESDIR "/cfg");
#endif
if (exename) {
const std::string exepath(Path::fromNativeSeparators(Path::getPathFromFilename(Path::getCurrentExecutablePath(exename))));
cfgfolders.push_back(exepath + "cfg");
cfgfolders.push_back(exepath + "../cfg");
cfgfolders.push_back(exepath);
}
// only perform further lookups when the given path was not absolute
if (!is_abs_path && error == tinyxml2::XML_ERROR_FILE_NOT_FOUND)
{
std::list<std::string> cfgfolders;
#ifdef FILESDIR
cfgfolders.emplace_back(FILESDIR "/cfg");
#endif
if (exename) {
const std::string exepath(Path::fromNativeSeparators(Path::getPathFromFilename(Path::getCurrentExecutablePath(exename))));
cfgfolders.push_back(exepath + "cfg");
cfgfolders.push_back(exepath + "../cfg");
cfgfolders.push_back(exepath);
}

while (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND && !cfgfolders.empty()) {
const std::string cfgfolder(cfgfolders.back());
cfgfolders.pop_back();
const char *sep = (!cfgfolder.empty() && endsWith(cfgfolder,'/') ? "" : "/");
const std::string filename(cfgfolder + sep + fullfilename);
if (debug)
std::cout << "looking for library '" + std::string(filename) + "'" << std::endl;
error = doc.LoadFile(filename.c_str());
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
absolute_path = Path::getAbsoluteFilePath(filename);
while (error == tinyxml2::XML_ERROR_FILE_NOT_FOUND && !cfgfolders.empty()) {
const std::string cfgfolder(cfgfolders.back());
cfgfolders.pop_back();
const char *sep = (!cfgfolder.empty() && endsWith(cfgfolder,'/') ? "" : "/");
const std::string filename(cfgfolder + sep + fullfilename);
if (debug)
std::cout << "looking for library '" + std::string(filename) + "'" << std::endl;
error = doc.LoadFile(filename.c_str());
if (error != tinyxml2::XML_ERROR_FILE_NOT_FOUND)
absolute_path = Path::getAbsoluteFilePath(filename);
}
}
} else
absolute_path = Path::getAbsoluteFilePath(path);
Expand Down
46 changes: 45 additions & 1 deletion test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@


def __remove_std_lookup_log(l : list, exepath):
print(l)
l.remove("looking for library 'std.cfg'")
l.remove("looking for library '{}/std.cfg'".format(exepath))
l.remove("looking for library '{}/../cfg/std.cfg'".format(exepath))
Expand Down Expand Up @@ -1570,3 +1569,48 @@ def test_lib_lookup_notfound(tmpdir):
"library not found: 'none'",
"cppcheck: Failed to load library configuration file 'none'. File not found"
]


def test_lib_lookup_absolute(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
pass

cfg_file = os.path.join(tmpdir, 'test.cfg')
with open(cfg_file, 'wt') as f:
f.write('''
<?xml version="1.0"?>
<def format="2">
</def>
''')

exitcode, stdout, _, exe = cppcheck_ex(['--library={}'.format(cfg_file), '--debug-lookup', test_file])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 0, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
assert lines == [
"looking for library '{}'".format(cfg_file),
'Checking {} ...'.format(test_file)
]


def test_lib_lookup_absolute_notfound(tmpdir):
test_file = os.path.join(tmpdir, 'test.c')
with open(test_file, 'wt'):
pass

cfg_file = os.path.join(tmpdir, 'test.cfg')

exitcode, stdout, _, exe = cppcheck_ex(['--library={}'.format(cfg_file), '--debug-lookup', test_file])
exepath = os.path.dirname(exe)
if sys.platform == 'win32':
exepath = exepath.replace('\\', '/')
assert exitcode == 1, stdout
lines = __remove_std_lookup_log(stdout.splitlines(), exepath)
assert lines == [
"looking for library '{}'".format(cfg_file),
"library not found: '{}'".format(cfg_file),
"cppcheck: Failed to load library configuration file '{}'. File not found".format(cfg_file)
]

0 comments on commit b53409b

Please sign in to comment.