Skip to content

Commit f32aac6

Browse files
committed
Review improvements
1 parent 33d4cc4 commit f32aac6

File tree

7 files changed

+71
-57
lines changed

7 files changed

+71
-57
lines changed

CMakeLists.txt

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/examples/globbing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ description = "Globbing sources"
2020
[target.mylib]
2121
type = "static"
2222
alias = "mylib::mylib"
23-
sources = ["mylib/**.hpp", "mylib/**.cpp", "mylib/**.gen.cxx"]
23+
sources = ["mylib/**.hpp", "mylib/**.cpp"]
2424
include-directories = ["mylib/include"]
2525

2626
# Single-folder glob in example/src/

src/cmake_generator.cpp

Lines changed: 59 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -54,64 +54,85 @@ static std::string format(const char *format, const tsl::ordered_map<std::string
5454
return s;
5555
}
5656

57-
static std::vector<std::string> expand_cmake_path(const fs::path &name, const fs::path &toml_dir, bool is_root_project) {
58-
59-
auto const extract_suffix = [](const fs::path &base, const fs::path &full) {
60-
auto fullpath = full.string();
61-
auto base_len = base.string().length();
62-
return fullpath.substr(base_len + 1, fullpath.length() - base_len);
63-
};
64-
auto const extract_path_parts = [](const fs::path &file_path) -> std::pair<std::string, std::string> {
65-
const auto path_as_string = file_path.string();
66-
auto const dot_position = path_as_string.find('.');
67-
if (dot_position != std::string::npos) {
68-
return {path_as_string.substr(0, dot_position), path_as_string.substr(dot_position)};
57+
static std::vector<fs::path> expand_cmake_path(const fs::path &source_path, const fs::path &toml_dir, bool is_root_project) {
58+
auto is_subdir = [](fs::path p, const fs::path &root) {
59+
while (true) {
60+
if (p == root) {
61+
return true;
62+
}
63+
auto parent = p.parent_path();
64+
if (parent == p) {
65+
break;
66+
}
67+
p = parent;
6968
}
70-
return {path_as_string, {}};
69+
return false;
7170
};
72-
auto const path_parts = extract_path_parts(name.filename());
73-
auto const &stem = path_parts.first;
74-
auto const &extension = path_parts.second;
71+
if (!is_subdir(fs::absolute(toml_dir / source_path), toml_dir)) {
72+
throw std::runtime_error("Path traversal is not allowed: " + source_path.string());
73+
}
74+
75+
// Split the path at the first period (since fs::path::stem() and fs::path::extension() split at the last period)
76+
std::string stem, extension;
77+
auto filename = source_path.filename().string();
78+
auto dot_position = filename.find('.');
79+
if (dot_position != std::string::npos) {
80+
stem = filename.substr(0, dot_position);
81+
extension = filename.substr(dot_position);
82+
} else {
83+
stem = filename;
84+
}
7585

76-
if (is_root_project && stem == "**" && name == name.filename()) {
77-
throw std::runtime_error("Recursive globbing not allowed in project root: " + name.string());
86+
if (is_root_project && stem == "**" && !source_path.has_parent_path()) {
87+
throw std::runtime_error("Recursive globbing not allowed in project root: " + source_path.string());
7888
}
7989

80-
std::vector<std::string> temp;
90+
auto has_extension = [](const fs::path &file_path, const std::string &extension) {
91+
auto path = file_path.string();
92+
return path.rfind(extension) == path.length() - extension.length();
93+
};
94+
95+
std::vector<fs::path> paths;
8196
if (stem == "*") {
82-
for (const auto &f : fs::directory_iterator(toml_dir / name.parent_path(), fs::directory_options::follow_directory_symlink)) {
83-
if (!f.is_directory() && extract_path_parts(f.path().filename()).second == extension) {
84-
temp.push_back(extract_suffix(toml_dir, f));
97+
for (const auto &f : fs::directory_iterator(toml_dir / source_path.parent_path(), fs::directory_options::follow_directory_symlink)) {
98+
if (!f.is_directory() && has_extension(f.path(), extension)) {
99+
paths.push_back(fs::relative(f, toml_dir));
85100
}
86101
}
87102
} else if (stem == "**") {
88-
for (const auto &f : fs::recursive_directory_iterator(toml_dir / name.parent_path(), fs::directory_options::follow_directory_symlink)) {
89-
if (!f.is_directory() && extract_path_parts(f.path().filename()).second == extension) {
90-
temp.push_back(extract_suffix(toml_dir, f.path()));
103+
for (const auto &f :
104+
fs::recursive_directory_iterator(toml_dir / source_path.parent_path(), fs::directory_options::follow_directory_symlink)) {
105+
if (!f.is_directory() && has_extension(f.path(), extension)) {
106+
paths.push_back(fs::relative(f, toml_dir));
91107
}
92108
}
93109
} else {
94-
temp.push_back(name.string());
110+
paths.push_back(source_path);
95111
}
96-
// Normalize all paths to work with CMake (it needs a / on Windows as well)
97-
for (auto &path : temp) {
98-
std::replace(path.begin(), path.end(), '\\', '/');
99-
}
100-
// Sort paths alphabetically for consistent cross-OS generation
101-
std::sort(temp.begin(), temp.end());
102-
return temp;
112+
113+
return paths;
103114
}
104115

105116
static std::vector<std::string> expand_cmake_paths(const std::vector<std::string> &sources, const fs::path &toml_dir, bool is_root_project) {
106-
// TODO: add duplicate checking
107-
std::vector<std::string> result;
117+
std::vector<std::string> paths;
108118
for (const auto &src : sources) {
109119
auto expanded = expand_cmake_path(src, toml_dir, is_root_project);
110120
for (const auto &f : expanded) {
111-
result.push_back(f);
121+
paths.push_back(f.string());
112122
}
113123
}
114-
return result;
124+
125+
// Normalize all paths to work with CMake (it needs a / on Windows as well)
126+
for (auto &path : paths) {
127+
std::replace(path.begin(), path.end(), '\\', '/');
128+
}
129+
130+
// Sort paths alphabetically for consistent cross-OS generation
131+
std::sort(paths.begin(), paths.end());
132+
133+
// TODO: remove duplicates
134+
135+
return paths;
115136
}
116137

117138
static void create_file(const fs::path &path, const std::string &contents) {
@@ -681,7 +702,7 @@ void generate_cmake(const char *path, const parser::Project *parent_project) {
681702

682703
parser::Project project(parent_project, path, false);
683704

684-
for (auto const &lang : project.project_languages) {
705+
for (const auto &lang : project.project_languages) {
685706
if (known_languages.find(lang) == known_languages.end()) {
686707
if (project.project_allow_unknown_languages) {
687708
printf("[warning] Unknown language '%s' specified\n", lang.c_str());

tests/globbing/cmake.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description = "Globbing sources"
66
[target.mylib]
77
type = "static"
88
alias = "mylib::mylib"
9-
sources = ["mylib/**.hpp", "mylib/**.cpp", "mylib/**.gen.cxx"]
9+
sources = ["mylib/**.hpp", "mylib/**.cpp"]
1010
include-directories = ["mylib/include"]
1111

1212
# Single-folder glob in example/src/

tests/globbing/mylib/include/mylib/mylib.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@
44

55
namespace mylib {
66
std::string message();
7-
std::string message2();
8-
}
7+
} // namespace mylib

tests/globbing/mylib/src/mylib/mylib.cxx

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/globbing/mylib/src/mylib/mylib.gen.cxx

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)