From 568e6eec31f173b2e0c2a29ae4bb8693a0b41383 Mon Sep 17 00:00:00 2001 From: Ezekiel Warren Date: Fri, 13 Sep 2024 10:34:30 -0700 Subject: [PATCH] fix: long path workaround --- ecsact/cli/commands/build/recipe/BUILD.bazel | 1 + ecsact/cli/commands/build/recipe/cook.cc | 4 ++++ ecsact/cli/commands/recipe-bundle/BUILD.bazel | 1 + .../recipe-bundle/build_recipe_bundle.cc | 16 +++++++++++----- ecsact/cli/detail/BUILD.bazel | 7 +++++++ ecsact/cli/detail/long_path_workaround.cc | 17 +++++++++++++++++ ecsact/cli/detail/long_path_workaround.hh | 13 +++++++++++++ 7 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 ecsact/cli/detail/long_path_workaround.cc create mode 100644 ecsact/cli/detail/long_path_workaround.hh diff --git a/ecsact/cli/commands/build/recipe/BUILD.bazel b/ecsact/cli/commands/build/recipe/BUILD.bazel index d6a491b..66127da 100644 --- a/ecsact/cli/commands/build/recipe/BUILD.bazel +++ b/ecsact/cli/commands/build/recipe/BUILD.bazel @@ -48,6 +48,7 @@ cc_library( "//ecsact/cli/detail:download", "//ecsact/cli/detail:glob", "//ecsact/cli/detail:archive", + "//ecsact/cli/detail:long_path_workaround", "//ecsact/cli/commands/build:build_recipe", "//ecsact/cli/commands/build:cc_compiler_config", "//ecsact/cli/commands/build:cc_defines_gen", diff --git a/ecsact/cli/commands/build/recipe/cook.cc b/ecsact/cli/commands/build/recipe/cook.cc index 104e26c..ac299bf 100644 --- a/ecsact/cli/commands/build/recipe/cook.cc +++ b/ecsact/cli/commands/build/recipe/cook.cc @@ -24,6 +24,7 @@ #include "ecsact/cli/detail/download.hh" #include "ecsact/cli/detail/glob.hh" #include "ecsact/cli/detail/archive.hh" +#include "ecsact/cli/detail/long_path_workaround.hh" #ifndef ECSACT_CLI_USE_SDK_VERSION # include "tools/cpp/runfiles/runfiles.h" #endif @@ -34,6 +35,7 @@ using ecsact::cli::report_warning; using ecsact::cli::detail::download_file; using ecsact::cli::detail::expand_path_globs; using ecsact::cli::detail::integrity; +using ecsact::cli::detail::long_path_workaround; using ecsact::cli::detail::path_before_glob; using ecsact::cli::detail::path_matches_glob; using ecsact::cli::detail::path_strip_prefix; @@ -286,6 +288,8 @@ static auto handle_source( // src_path = (base_directory / src_path).lexically_normal(); } + src_path = long_path_workaround(src_path); + auto outdir = src.outdir // ? options.work_dir / *src.outdir : options.work_dir; diff --git a/ecsact/cli/commands/recipe-bundle/BUILD.bazel b/ecsact/cli/commands/recipe-bundle/BUILD.bazel index 6b4b21d..d81dcba 100644 --- a/ecsact/cli/commands/recipe-bundle/BUILD.bazel +++ b/ecsact/cli/commands/recipe-bundle/BUILD.bazel @@ -16,6 +16,7 @@ cc_library( "//ecsact/cli/commands/codegen", "//ecsact/cli/commands/build:build_recipe", "//ecsact/cli/detail:download", + "//ecsact/cli/detail:long_path_workaround", "//ecsact/cli:report", ], ) diff --git a/ecsact/cli/commands/recipe-bundle/build_recipe_bundle.cc b/ecsact/cli/commands/recipe-bundle/build_recipe_bundle.cc index 16ddd0e..2b36ebe 100644 --- a/ecsact/cli/commands/recipe-bundle/build_recipe_bundle.cc +++ b/ecsact/cli/commands/recipe-bundle/build_recipe_bundle.cc @@ -19,11 +19,13 @@ #include #include #include "xxhash.h" - #include "ecsact/cli/report.hh" #include "ecsact/cli/detail/download.hh" +#include "ecsact/cli/detail/long_path_workaround.hh" #include "ecsact/cli/commands/codegen/codegen_util.hh" +using ecsact::cli::detail::long_path_workaround; + using namespace std::string_literals; using namespace std::string_view_literals; namespace fs = std::filesystem; @@ -88,7 +90,7 @@ static auto is_valid_bundle_entry_path(std::string_view path) -> bool { static auto read_file(fs::path path) -> std::optional> { auto ec = std::error_code{}; - auto file_size = fs::file_size(path, ec); + auto file_size = fs::file_size(long_path_workaround(path), ec); if(ec) { ecsact::cli::report_error( "failed to read file size {}: {}", @@ -97,7 +99,7 @@ static auto read_file(fs::path path) -> std::optional> { ); return {}; } - auto file = std::ifstream{path, std::ios_base::binary}; + auto file = std::ifstream{long_path_workaround(path), std::ios_base::binary}; if(!file) { ecsact::cli::report_error( "failed to open file file for reading {}", @@ -119,7 +121,7 @@ static auto read_file(fs::path path) -> std::optional> { } static auto write_file(fs::path path, std::span data) -> bool { - if(path.has_parent_path()) { + if(path.has_parent_path() && !fs::exists(path.parent_path())) { auto ec = std::error_code{}; fs::create_directories(path.parent_path(), ec); if(ec) { @@ -131,7 +133,11 @@ static auto write_file(fs::path path, std::span data) -> bool { return false; } } - auto file = std::ofstream(path, std::ios_base::binary | std::ios_base::trunc); + + auto file = std::ofstream{ + long_path_workaround(path), + std::ios::binary | std::ios::trunc + }; if(!file) { ecsact::cli::report_error( "failed to open file {}: {}", diff --git a/ecsact/cli/detail/BUILD.bazel b/ecsact/cli/detail/BUILD.bazel index 1c248b2..6bdd390 100644 --- a/ecsact/cli/detail/BUILD.bazel +++ b/ecsact/cli/detail/BUILD.bazel @@ -74,3 +74,10 @@ cc_library( "@boost.process", ], ) + +cc_library( + name = "long_path_workaround", + copts = copts, + hdrs = ["long_path_workaround.hh"], + srcs = ["long_path_workaround.cc"], +) diff --git a/ecsact/cli/detail/long_path_workaround.cc b/ecsact/cli/detail/long_path_workaround.cc new file mode 100644 index 0000000..b241b34 --- /dev/null +++ b/ecsact/cli/detail/long_path_workaround.cc @@ -0,0 +1,17 @@ +#include "ecsact/cli/detail/long_path_workaround.hh" + +auto ecsact::cli::detail::long_path_workaround( // + std::filesystem::path p +) -> std::filesystem::path { +#if _WIN32 + auto win_path_str = "\\\\?\\" + std::filesystem::absolute(p).string(); + for(auto& c : win_path_str) { + if(c == '/') { + c = '\\'; + } + } + return win_path_str; +#else + return p; +#endif +} diff --git a/ecsact/cli/detail/long_path_workaround.hh b/ecsact/cli/detail/long_path_workaround.hh new file mode 100644 index 0000000..4cd67ef --- /dev/null +++ b/ecsact/cli/detail/long_path_workaround.hh @@ -0,0 +1,13 @@ +#pragma once + +#include + +namespace ecsact::cli::detail { + +/** + * The Ecsact CLI isn't built with long path awareness on Windows. This utility + * function returns an absolute //?/ prefixed path on Windows and on other + * platforms does nothing. + */ +auto long_path_workaround(std::filesystem::path p) -> std::filesystem::path; +} // namespace ecsact::cli::detail