Skip to content

Commit de11b88

Browse files
committed
fix: fixed ignite variable resolutions
1 parent 4e44877 commit de11b88

File tree

6 files changed

+142
-79
lines changed

6 files changed

+142
-79
lines changed

tools/ignite/Configuration.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,27 @@
2121
#include <fstream>
2222

2323
static YAML::Node merge(const YAML::Node& a, const YAML::Node& b) {
24-
if (a.IsNull()) return b;
24+
if (a.IsNull()) return YAML::Clone(b);
2525

2626
if (a.IsMap() && b.IsMap()) {
27-
YAML::Node merged = a;
27+
YAML::Node merged = YAML::Clone(a);
2828
for (auto const& i : b) {
2929
if (auto const key = i.first.as<std::string>(); a[key]) {
3030
merged[key] = merge(a[key], i.second);
3131
} else {
32-
merged[key] = i.second;
32+
merged[key] = YAML::Clone(i.second);
3333
}
3434
}
3535
return merged;
3636
}
3737

3838
if (a.IsSequence() && b.IsSequence()) {
39-
YAML::Node merged = a;
40-
for (const auto& elem : b) { merged.push_back(elem); }
39+
YAML::Node merged = YAML::Clone(a);
40+
for (const auto& elem : b) { merged.push_back(YAML::Clone(elem)); }
4141
return merged;
4242
}
4343

44-
if (a.IsScalar() && b.IsScalar()) { return a; }
44+
if (a.IsScalar() && b.IsScalar()) { return YAML::Clone(a); }
4545

4646
std::stringstream ss;
4747
ss << a;

tools/ignite/Executor.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@ Executor& Executor::start() {
3939

4040
close(pipe_fd[WRITE]);
4141

42-
if (path_)
43-
if (chdir(path_->c_str()) == -1)
44-
throw std::runtime_error("failed to switch path to " + *path_);
42+
if (path_) {
43+
if (chdir(path_->c_str()) == -1) {
44+
perror("chdir failed");
45+
_exit(EXIT_FAILURE);
46+
}
47+
}
4548
clearenv();
4649

4750
std::vector<const char*> args;
@@ -52,11 +55,10 @@ Executor& Executor::start() {
5255
for (auto const& c : environ_) env.emplace_back(c.c_str());
5356
env.push_back(nullptr);
5457

55-
if (execve(args_[0].c_str(), (char* const*)args.data(),
56-
(char* const*)env.data()) == -1) {
57-
perror("execution failed");
58-
}
59-
exit(EXIT_FAILURE);
58+
execve(args_[0].c_str(), (char* const*)args.data(),
59+
(char* const*)env.data());
60+
perror("execution failed");
61+
_exit(EXIT_FAILURE);
6062
}
6163
return *this;
6264
}

tools/ignite/Ignite.cpp

Lines changed: 77 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@ void Ignite::resolve(const std::vector<std::string>& id,
101101
}
102102
}
103103

104-
recipe->second.cache = hash(recipe->second);
105-
auto cached = std::filesystem::exists(cachefile(recipe->second));
104+
auto resolved_recipe = recipe->second;
105+
resolved_recipe.cache = hash(resolved_recipe);
106+
auto cached = std::filesystem::exists(cachefile(resolved_recipe));
106107

107108
for (auto depend : depends) {
108109
auto idx = std::find_if(output.begin(), output.end(),
@@ -128,13 +129,17 @@ void Ignite::resolve(const std::vector<std::string>& id,
128129
}
129130
}
130131
}
131-
output.emplace_back(i, recipe->second, cached);
132+
output.emplace_back(i, resolved_recipe, cached);
132133
};
133134

134135
for (auto const& i : id) { dfs(i); }
135136
}
136137

137138
std::string Ignite::hash(const Recipe& recipe) {
139+
if (auto it = hash_cache.find(recipe.id); it != hash_cache.end()) {
140+
return it->second;
141+
}
142+
138143
std::string hash_sum;
139144

140145
{
@@ -159,13 +164,16 @@ std::string Ignite::hash(const Recipe& recipe) {
159164
throw std::runtime_error("missing required element '" + i +
160165
" for " + recipe.id);
161166
}
162-
std::stringstream ss;
163-
ss << depend_recipe->second.config.node;
164-
picosha2::hash256_hex_string(ss.str() + hash_sum, hash_sum);
167+
// Recursively hash the dependency so transitive changes
168+
// propagate: if a dep-of-dep changes, this recipe's hash
169+
// changes too.
170+
auto dep_hash = hash(depend_recipe->second);
171+
picosha2::hash256_hex_string(dep_hash + hash_sum, hash_sum);
165172
}
166173
}
167174
}
168175

176+
hash_cache[recipe.id] = hash_sum;
169177
return hash_sum;
170178
}
171179

@@ -177,9 +185,9 @@ void Ignite::build(const Recipe& recipe) {
177185
if (access(i.path().c_str(), W_OK) != 0) {
178186
std::error_code code;
179187
std::filesystem::permissions(i.path(),
180-
std::filesystem::perms::group_all |
181-
std::filesystem::perms::owner_all |
182-
std::filesystem::perms::group_all,
188+
std::filesystem::perms::owner_all |
189+
std::filesystem::perms::group_all |
190+
std::filesystem::perms::others_all,
183191
code);
184192
}
185193
}
@@ -190,8 +198,9 @@ void Ignite::build(const Recipe& recipe) {
190198
.arg("-r")
191199
.arg("-f")
192200
.arg(container.host_root)
193-
.execute();
201+
.run();
194202
});
203+
std::filesystem::create_directories(cache_path / "logs");
195204
std::ofstream logger(cache_path / "logs" /
196205
(recipe.package_name(recipe.element_id) + ".log"));
197206
container.logger = &logger;
@@ -315,7 +324,7 @@ Container Ignite::setup_container(
315324

316325
for (auto const& [path, info, cached] : states) {
317326
auto installation_path = std::filesystem::path("install-root") /
318-
recipe.package_name();
327+
recipe.package_name(recipe.element_id);
319328
installation_path = recipe.config.get<std::string>(
320329
recipe.name() + "-include-path",
321330
recipe.config.get<std::string>(
@@ -352,7 +361,7 @@ void Ignite::integrate(Container& container, const Recipe& recipe,
352361
if (root.empty()) {
353362
extractor.arg("--exclude=./etc/hosts")
354363
.arg("--exclude=./etc/hostname")
355-
.arg("--exclude=./etc/resolve.conf")
364+
.arg("--exclude=./etc/resolv.conf")
356365
.arg("--exclude=./proc")
357366
.arg("--exclude=./run")
358367
.arg("--exclude=./sys")
@@ -402,7 +411,7 @@ void Ignite::integrate(Container& container, const Recipe& recipe,
402411
.arg(cache_file_path)
403412
.arg("--exclude=./etc/hosts")
404413
.arg("--exclude=./etc/hostname")
405-
.arg("--exclude=./etc/resolve.conf")
414+
.arg("--exclude=./etc/resolv.conf")
406415
.arg("--exclude=./proc")
407416
.arg("--exclude=./run")
408417
.arg("--exclude=./sys")
@@ -435,7 +444,7 @@ void extract(const std::filesystem::path& filepath,
435444
}
436445

437446
int status = Executor(exe)
438-
.arg("-xvPf")
447+
.arg("-xvf")
439448
.arg(filepath)
440449
.arg("-C")
441450
.arg(output_path)
@@ -503,7 +512,7 @@ std::optional<std::filesystem::path> Ignite::prepare_sources(
503512
extract(filepath,
504513
build_root / (subdir ? *subdir : std::filesystem::path("")),
505514
files_list);
506-
if (!subdir) {
515+
if (!subdir && !files_list.empty()) {
507516
std::string dir = files_list.front();
508517
auto idx = dir.find('/');
509518
if (idx != std::string::npos) { dir = dir.substr(0, idx); }
@@ -562,16 +571,21 @@ void Ignite::compile_source(const Recipe& build_info, Container* container,
562571
}
563572

564573
if (build_info.config.get<std::string>("build-type", "") == "import") {
565-
auto source = resolved_build_root /
566-
build_info.config.get<std::string>("source", "");
567-
auto target = resolved_install_root /
568-
build_info.config.get<std::string>("target", "");
569-
std::filesystem::create_directories(target);
574+
auto source = extra_variables["build-root"] /
575+
std::filesystem::path(
576+
build_info.config.get<std::string>("source", ""));
577+
auto target = extra_variables["install-root"] /
578+
std::filesystem::path(
579+
build_info.config.get<std::string>("target", ""));
580+
std::filesystem::create_directories(
581+
resolved_install_root /
582+
build_info.config.get<std::string>("target", ""));
570583
Executor("/bin/cp")
571584
.arg("-rap")
572585
.arg(source / ".")
573586
.arg("-t")
574587
.arg(target)
588+
.container(container)
575589
.execute();
576590
} else {
577591
auto script = build_info.config.get<std::string>("script", "");
@@ -584,7 +598,6 @@ void Ignite::compile_source(const Recipe& build_info, Container* container,
584598
script = build_info.resolve(script, config, extra_variables);
585599

586600
std::cout << "Exec(script)" << std::endl;
587-
std::cout << "Exec(pre-script)" << std::endl;
588601

589602
if (script.length() > 500) {
590603
auto script_path = resolved_build_root / "pkgupd_exec_script.sh";
@@ -633,15 +646,28 @@ void Ignite::compile_source(const Recipe& build_info, Container* container,
633646

634647
void Ignite::strip(const Recipe& build_info, Container* container,
635648
const std::filesystem::path& install_root) {
649+
std::vector<std::string> mime_to_strip;
650+
if (config.node["strip-mimetype"]) {
651+
for (auto const& i : config.node["strip-mimetype"]) {
652+
mime_to_strip.emplace_back(i.as<std::string>());
653+
}
654+
}
655+
if (build_info.config.node["strip-mimetype"]) {
656+
for (auto const& i : build_info.config.node["strip-mimetype"]) {
657+
mime_to_strip.emplace_back(i.as<std::string>());
658+
}
659+
}
660+
636661
for (auto const& iter :
637662
std::filesystem::recursive_directory_iterator(install_root)) {
638663
if (!iter.is_regular_file()) continue;
639664
// if file is executable and writable or
640665
// if file ends with .so and .a
641-
// TODO check if it cover all cases
642666
if (((iter.path().has_extension() &&
643667
(iter.path().extension() == ".so" ||
644-
iter.path().extension() == ".a")) ||
668+
iter.path().extension() == ".a" ||
669+
iter.path().filename().string().find(".so.") !=
670+
std::string::npos)) ||
645671
(access(iter.path().c_str(), X_OK) == 0)) &&
646672
access(iter.path().c_str(), W_OK) == 0) {
647673
auto [status, mime_type] = Executor("/bin/file")
@@ -656,19 +682,6 @@ void Ignite::strip(const Recipe& build_info, Container* container,
656682
continue;
657683
}
658684

659-
std::vector<std::string> mime_to_strip;
660-
if (config.node["strip-mimetype"]) {
661-
for (auto const& i : config.node["strip-mimetype"]) {
662-
mime_to_strip.emplace_back(i.as<std::string>());
663-
}
664-
}
665-
666-
if (build_info.config.node["strip-mimetype"]) {
667-
for (auto const& i : build_info.config.node["strip-mimetype"]) {
668-
mime_to_strip.emplace_back(i.as<std::string>());
669-
}
670-
}
671-
672685
if (std::find(mime_to_strip.begin(), mime_to_strip.end(),
673686
mime_type) == mime_to_strip.end()) {
674687
continue;
@@ -684,13 +697,15 @@ void Ignite::strip(const Recipe& build_info, Container* container,
684697
.silent()
685698
.execute();
686699

700+
auto fname = iter.path().filename().string();
687701
std::string strip_args = "--strip-all";
688-
if (iter.path().has_extension()) {
689-
if (iter.path().extension() == ".a") {
690-
strip_args = "--strip-debug";
691-
} else {
692-
strip_args = "--strip-unneeded";
693-
}
702+
if (iter.path().has_extension() &&
703+
iter.path().extension() == ".a") {
704+
strip_args = "--strip-debug";
705+
} else if ((iter.path().has_extension() &&
706+
iter.path().extension() == ".so") ||
707+
fname.find(".so.") != std::string::npos) {
708+
strip_args = "--strip-unneeded";
694709
}
695710

696711
// Strip out the debugging symbols
@@ -765,19 +780,33 @@ void Ignite::pack(const Recipe& build_info, Container* container,
765780
}
766781
}
767782

783+
// Collect paths first; modifying the tree during recursive_directory_iterator
784+
// is undefined behavior.
785+
std::vector<std::filesystem::path> dirs_to_clean;
786+
std::vector<std::filesystem::path> files_to_remove;
787+
std::vector<std::filesystem::path> dbg_to_move;
788+
bool clean_empty_dirs = build_info.config.get<bool>("clean-empty-dir", true);
789+
768790
for (auto const& i : std::filesystem::recursive_directory_iterator(
769791
install_root_package)) {
770792
if (i.is_directory()) {
771-
if (i.path().empty() &&
772-
build_info.config.get<bool>("clean-empty-dir", true)) {
773-
std::filesystem::remove(i.path());
774-
}
793+
if (clean_empty_dirs) { dirs_to_clean.push_back(i.path()); }
775794
} else if (!keep_files.empty() && keep_file(i.path().filename())) {
776795
continue;
777796
} else if (i.path().has_extension() && i.path().extension() == ".la") {
778-
std::filesystem::remove(i.path());
797+
files_to_remove.push_back(i.path());
779798
} else if (i.path().has_extension() && i.path().extension() == ".dbg") {
780-
move_file(i.path(), install_root_dbg);
799+
dbg_to_move.push_back(i.path());
800+
}
801+
}
802+
803+
for (auto const& p : files_to_remove) { std::filesystem::remove(p); }
804+
for (auto const& p : dbg_to_move) { move_file(p, install_root_dbg); }
805+
// Reverse so children are removed before parents, allowing cascading cleanup.
806+
std::reverse(dirs_to_clean.begin(), dirs_to_clean.end());
807+
for (auto const& p : dirs_to_clean) {
808+
if (std::filesystem::exists(p) && std::filesystem::is_empty(p)) {
809+
std::filesystem::remove(p);
781810
}
782811
}
783812

tools/ignite/Ignite.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Ignite {
3636
std::filesystem::path project_path, cache_path;
3737

3838
std::map<std::string, Compiler> compilers;
39+
std::map<std::string, std::string> hash_cache;
3940

4041
public:
4142
Configuration& config;

0 commit comments

Comments
 (0)