Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 3way merge fix and merge recipe tests #126

Merged
merged 7 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ bazel_dep(name = "boost.url", version = "1.83.0.bzl.2")
bazel_dep(name = "yaml-cpp", version = "0.8.0")
bazel_dep(name = "libarchive", version = "3.7.4.bcr.2")

bazel_dep(name = "googletest", version = "1.15.2", dev_dependency = True)
bazel_dep(name = "toolchains_llvm", version = "1.0.0", dev_dependency = True)
bazel_dep(name = "hedron_compile_commands", dev_dependency = True)

Expand Down
137 changes: 75 additions & 62 deletions ecsact/cli/commands/build/build_recipe.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,10 @@ static auto parse_sources( //
outdir = src["outdir"].as<std::string>();
}

if(!relative_to_cwd && !src_path.is_absolute()) {
src_path = recipe_path.parent_path() / src_path;
if(relative_to_cwd && !src_path.is_absolute()) {
src_path = (fs::current_path() / src_path).lexically_normal();
} else {
src_path = src_path.lexically_normal();
}

result.emplace_back(source_path{
Expand All @@ -252,10 +254,7 @@ static auto parse_sources( //
});
}
} else if(src.IsScalar()) {
auto path = fs::path{src.as<std::string>()};
if(!path.is_absolute()) {
path = recipe_path.parent_path() / path;
}
auto path = fs::path{src.as<std::string>()}.lexically_normal();
result.emplace_back(source_path{
.path = path,
.outdir = ".",
Expand All @@ -266,76 +265,90 @@ static auto parse_sources( //
return result;
}

auto ecsact::build_recipe::from_yaml_file( //
std::filesystem::path p
auto ecsact::build_recipe::build_recipe_from_yaml_node( //
YAML::Node doc,
fs::path p
) -> create_result {
auto file = std::ifstream{p};
try {
auto doc = YAML::LoadFile(p.string());

if(!doc.IsMap()) {
return build_recipe_parse_error::expected_map_top_level;
}
if(!doc.IsMap()) {
return ecsact::build_recipe_parse_error::expected_map_top_level;
}

auto exports = parse_exports(doc["exports"]);
if(auto err = get_if_error(exports)) {
return *err;
}
auto exports = parse_exports(doc["exports"]);
if(auto err = get_if_error(exports)) {
return *err;
}

auto imports = parse_imports(doc["imports"]);
if(auto err = get_if_error(imports)) {
return *err;
}
auto imports = parse_imports(doc["imports"]);
if(auto err = get_if_error(imports)) {
return *err;
}

auto sources = parse_sources(p, doc["sources"]);
if(auto err = get_if_error(sources)) {
return *err;
}
auto sources = parse_sources(p, doc["sources"]);
if(auto err = get_if_error(sources)) {
return *err;
}

auto system_libs = parse_system_libs(doc["system_libs"]);
if(auto err = get_if_error(system_libs)) {
return *err;
}
auto system_libs = parse_system_libs(doc["system_libs"]);
if(auto err = get_if_error(system_libs)) {
return *err;
}

auto recipe = build_recipe{};
if(doc["name"]) {
recipe._name = doc["name"].as<std::string>();
}
if(p.has_parent_path()) {
recipe._base_directory = p.parent_path().generic_string();
}
recipe._exports = get_value(exports);
recipe._imports = get_value(imports);
recipe._sources = get_value(sources);
recipe._system_libs = get_value(system_libs);
auto recipe = ecsact::build_recipe{};
if(doc["name"]) {
recipe._name = doc["name"].as<std::string>();
}
if(p.has_parent_path()) {
recipe._base_directory = p.parent_path().generic_string();
}
recipe._exports = get_value(exports);
recipe._imports = get_value(imports);
recipe._sources = get_value(sources);
recipe._system_libs = get_value(system_libs);

if(recipe._exports.empty()) {
return build_recipe_parse_error::missing_exports;
}
if(recipe._exports.empty()) {
return build_recipe_parse_error::missing_exports;
}

auto import_modules =
ecsact::cli::detail::get_ecsact_modules(recipe._imports);
auto export_modules =
ecsact::cli::detail::get_ecsact_modules(recipe._exports);
auto import_modules =
ecsact::cli::detail::get_ecsact_modules(recipe._imports);
auto export_modules =
ecsact::cli::detail::get_ecsact_modules(recipe._exports);

if(!import_modules.unknown_module_methods.empty()) {
return build_recipe_parse_error::unknown_import_method;
}
if(!import_modules.unknown_module_methods.empty()) {
return build_recipe_parse_error::unknown_import_method;
}

if(!export_modules.unknown_module_methods.empty()) {
return build_recipe_parse_error::unknown_export_method;
}
if(!export_modules.unknown_module_methods.empty()) {
return build_recipe_parse_error::unknown_export_method;
}

for(auto&& [imp_mod, _] : import_modules.module_methods) {
for(auto&& [exp_mod, _] : export_modules.module_methods) {
if(imp_mod == exp_mod) {
return build_recipe_parse_error::
conflicting_import_export_method_modules;
}
for(auto&& [imp_mod, _] : import_modules.module_methods) {
for(auto&& [exp_mod, _] : export_modules.module_methods) {
if(imp_mod == exp_mod) {
return build_recipe_parse_error::
conflicting_import_export_method_modules;
}
}
}

return recipe;
return recipe;
}

auto ecsact::build_recipe::from_yaml_string( //
const std::string& str,
fs::path p
) -> create_result {
auto doc = YAML::Load(str);
return build_recipe_from_yaml_node(doc, p);
}

auto ecsact::build_recipe::from_yaml_file( //
std::filesystem::path p
) -> create_result {
auto file = std::ifstream{p};
try {
auto doc = YAML::LoadFile(p.string());
return build_recipe_from_yaml_node(doc, p);
} catch(const YAML::BadFile& err) {
ecsact::cli::report_error("YAML PARSE: {}", err.what());
return build_recipe_parse_error::bad_file;
Expand Down
17 changes: 16 additions & 1 deletion ecsact/cli/commands/build/build_recipe.hh
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#pragma once

#include <string>
#include <unordered_map>
#include <variant>
#include <vector>
#include <span>
#include <filesystem>
#include <cstddef>
#include <optional>
#include <filesystem>

namespace YAML {
class Node;
}

namespace ecsact {

Expand All @@ -33,6 +38,11 @@ public:
std::filesystem::path p
) -> create_result;

static auto from_yaml_string( //
const std::string& str,
std::filesystem::path p
) -> create_result;

static auto merge( //
const build_recipe& a,
const build_recipe& b
Expand Down Expand Up @@ -84,6 +94,11 @@ private:

build_recipe();
build_recipe(const build_recipe&);

static auto build_recipe_from_yaml_node( //
YAML::Node doc,
std::filesystem::path p
) -> create_result;
};

struct build_recipe::create_result
Expand Down
30 changes: 20 additions & 10 deletions ecsact/cli/commands/build/recipe/cook.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ static auto write_file(fs::path path, std::span<std::byte> data) -> void {
}

static auto handle_source( //
fs::path base_directory,
ecsact::build_recipe::source_fetch src,
const ecsact::cli::cook_recipe_options& options
) -> int {
Expand Down Expand Up @@ -239,6 +240,7 @@ static auto handle_source( //
}

static auto handle_source( //
fs::path base_directory,
ecsact::build_recipe::source_codegen src,
const ecsact::cli::cook_recipe_options& options
) -> int {
Expand Down Expand Up @@ -275,55 +277,61 @@ static auto handle_source( //
}

static auto handle_source( //
fs::path base_directory,
ecsact::build_recipe::source_path src,
const ecsact::cli::cook_recipe_options& options
) -> int {
auto src_path = src.path;
if(!src_path.is_absolute()) {
src_path = (base_directory / src_path).lexically_normal();
}

auto outdir = src.outdir //
? options.work_dir / *src.outdir
: options.work_dir;

auto ec = std::error_code{};
fs::create_directories(outdir, ec);

auto before_glob = path_before_glob(src.path);
auto paths = expand_path_globs(src.path, ec);
auto before_glob = path_before_glob(src_path);
auto paths = expand_path_globs(src_path, ec);
if(ec) {
ecsact::cli::report_error(
"Failed to glob {}: {}",
src.path.generic_string(),
src_path.generic_string(),
ec.message()
);
return 1;
}

for(auto path : paths) {
if(!fs::exists(src.path)) {
if(!fs::exists(src_path)) {
ecsact::cli::report_error(
"Source file {} does not exist",
src.path.generic_string()
src_path.generic_string()
);
return 1;
}
auto rel_outdir = outdir;
if(auto stripped = path_strip_prefix(src.path, before_glob)) {
if(auto stripped = path_strip_prefix(src_path, before_glob)) {
rel_outdir = outdir / *stripped;
}

fs::create_directories(rel_outdir, ec);
fs::copy(src.path, rel_outdir, ec);
fs::copy(src_path, rel_outdir, ec);

if(ec) {
ecsact::cli::report_error(
"Failed to copy source {} to {}: {}",
src.path.generic_string(),
src_path.generic_string(),
rel_outdir.generic_string(),
ec.message()
);
return 1;
} else {
ecsact::cli::report_info(
"Copied source {} to {}",
src.path.generic_string(),
src_path.generic_string(),
rel_outdir.generic_string()
);
}
Expand Down Expand Up @@ -707,7 +715,9 @@ auto ecsact::cli::cook_recipe( //

for(auto& src : recipe.sources()) {
exit_code = std::visit(
[&](auto& src) { return handle_source(src, recipe_options); },
[&](auto& src) {
return handle_source(recipe.base_directory(), src, recipe_options);
},
src
);

Expand Down
13 changes: 13 additions & 0 deletions ecsact/cli/commands/build/test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("//bazel:copts.bzl", "copts")

cc_test(
name = "merge_recipe_test",
copts = copts,
srcs = ["merge_recipe_test.cc"],
deps = [
"@googletest//:gtest",
"@googletest//:gtest_main",
"//ecsact/cli/commands/build:build_recipe",
],
)
Loading