Merge pull request #142 from anthonyprintup/globbing-extension-fix

Fixed globbing when multiple extensions are present in the file name
main
Duncan Ogilvie 4 months ago committed by GitHub
commit 6c46664336
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

18
CMakeLists.txt generated

@ -58,12 +58,9 @@ generate_documentation()
# Target: cmkr # Target: cmkr
set(cmkr_SOURCES set(cmkr_SOURCES
"src/arguments.cpp" cmake.toml
"src/build.cpp" "cmake/cmkr.cmake"
"src/cmake_generator.cpp" "cmake/version.hpp.in"
"src/help.cpp"
"src/main.cpp"
"src/project_parser.cpp"
"include/arguments.hpp" "include/arguments.hpp"
"include/build.hpp" "include/build.hpp"
"include/cmake_generator.hpp" "include/cmake_generator.hpp"
@ -71,9 +68,12 @@ set(cmkr_SOURCES
"include/help.hpp" "include/help.hpp"
"include/literals.hpp" "include/literals.hpp"
"include/project_parser.hpp" "include/project_parser.hpp"
"cmake/cmkr.cmake" "src/arguments.cpp"
"cmake/version.hpp.in" "src/build.cpp"
cmake.toml "src/cmake_generator.cpp"
"src/help.cpp"
"src/main.cpp"
"src/project_parser.cpp"
) )
add_executable(cmkr) add_executable(cmkr)

@ -54,57 +54,85 @@ static std::string format(const char *format, const tsl::ordered_map<std::string
return s; return s;
} }
static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs::path &toml_dir, bool is_root_project) { static std::vector<fs::path> expand_cmake_path(const fs::path &source_path, const fs::path &toml_dir, bool is_root_project) {
std::vector<std::string> temp; auto is_subdir = [](fs::path p, const fs::path &root) {
while (true) {
auto extract_suffix = [](const fs::path &base, const fs::path &full) { if (p == root) {
auto fullpath = full.string(); return true;
auto base_len = base.string().length(); }
auto delet = fullpath.substr(base_len + 1, fullpath.length() - base_len); auto parent = p.parent_path();
return delet; if (parent == p) {
break;
}
p = parent;
}
return false;
}; };
if (!is_subdir(fs::absolute(toml_dir / source_path), toml_dir)) {
throw std::runtime_error("Path traversal is not allowed: " + source_path.string());
}
auto stem = name.filename().stem().string(); // Split the path at the first period (since fs::path::stem() and fs::path::extension() split at the last period)
auto ext = name.extension(); std::string stem, extension;
auto filename = source_path.filename().string();
auto dot_position = filename.find('.');
if (dot_position != std::string::npos) {
stem = filename.substr(0, dot_position);
extension = filename.substr(dot_position);
} else {
stem = filename;
}
if (is_root_project && stem == "**" && name == name.filename()) { if (is_root_project && stem == "**" && !source_path.has_parent_path()) {
throw std::runtime_error("Recursive globbing not allowed in project root: " + name.string()); throw std::runtime_error("Recursive globbing not allowed in project root: " + source_path.string());
} }
auto has_extension = [](const fs::path &file_path, const std::string &extension) {
auto path = file_path.string();
return path.rfind(extension) == path.length() - extension.length();
};
std::vector<fs::path> paths;
if (stem == "*") { if (stem == "*") {
for (const auto &f : fs::directory_iterator(toml_dir / name.parent_path(), fs::directory_options::follow_directory_symlink)) { for (const auto &f : fs::directory_iterator(toml_dir / source_path.parent_path(), fs::directory_options::follow_directory_symlink)) {
if (!f.is_directory() && f.path().extension() == ext) { if (!f.is_directory() && has_extension(f.path(), extension)) {
temp.push_back(extract_suffix(toml_dir, f)); paths.push_back(fs::relative(f, toml_dir));
} }
} }
} else if (stem == "**") { } else if (stem == "**") {
for (const auto &f : fs::recursive_directory_iterator(toml_dir / name.parent_path(), fs::directory_options::follow_directory_symlink)) { for (const auto &f :
if (!f.is_directory() && f.path().extension() == ext) { fs::recursive_directory_iterator(toml_dir / source_path.parent_path(), fs::directory_options::follow_directory_symlink)) {
temp.push_back(extract_suffix(toml_dir, f.path())); if (!f.is_directory() && has_extension(f.path(), extension)) {
paths.push_back(fs::relative(f, toml_dir));
} }
} }
} else { } else {
temp.push_back(name.string()); paths.push_back(source_path);
} }
// Normalize all paths to work with CMake (it needs a / on Windows as well)
for (auto &path : temp) { return paths;
std::replace(path.begin(), path.end(), '\\', '/');
}
// Sort paths alphabetically for consistent cross-OS generation
std::sort(temp.begin(), temp.end());
return temp;
} }
static std::vector<std::string> expand_cmake_paths(const std::vector<std::string> &sources, const fs::path &toml_dir, bool is_root_project) { static std::vector<std::string> expand_cmake_paths(const std::vector<std::string> &sources, const fs::path &toml_dir, bool is_root_project) {
// TODO: add duplicate checking std::vector<std::string> paths;
std::vector<std::string> result;
for (const auto &src : sources) { for (const auto &src : sources) {
auto expanded = expand_cmake_path(src, toml_dir, is_root_project); auto expanded = expand_cmake_path(src, toml_dir, is_root_project);
for (const auto &f : expanded) { for (const auto &f : expanded) {
result.push_back(f); paths.push_back(f.string());
} }
} }
return result;
// Normalize all paths to work with CMake (it needs a / on Windows as well)
for (auto &path : paths) {
std::replace(path.begin(), path.end(), '\\', '/');
}
// Sort paths alphabetically for consistent cross-OS generation
std::sort(paths.begin(), paths.end());
// TODO: remove duplicates
return paths;
} }
static void create_file(const fs::path &path, const std::string &contents) { static void create_file(const fs::path &path, const std::string &contents) {
@ -674,7 +702,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
parser::Project project(parent_project, path, false); parser::Project project(parent_project, path, false);
for (auto const &lang : project.project_languages) { for (const auto &lang : project.project_languages) {
if (known_languages.find(lang) == known_languages.end()) { if (known_languages.find(lang) == known_languages.end()) {
if (project.project_allow_unknown_languages) { if (project.project_allow_unknown_languages) {
printf("[warning] Unknown language '%s' specified\n", lang.c_str()); printf("[warning] Unknown language '%s' specified\n", lang.c_str());

@ -4,4 +4,4 @@
namespace mylib { namespace mylib {
std::string message(); std::string message();
} } // namespace mylib

Loading…
Cancel
Save