diff options
author | Ignacio Etcheverry <ignalfonsore@gmail.com> | 2019-07-08 15:16:35 +0200 |
---|---|---|
committer | Ignacio Etcheverry <ignalfonsore@gmail.com> | 2019-07-08 18:07:15 +0200 |
commit | 5ed3d34cd914ecd6930651769a423cad2999ca64 (patch) | |
tree | 7f5f64af0c83b031c8d4484287e474eb4d6e33f0 /modules | |
parent | 2c83255013b45a558d967e190cf5ddfb03f09dd6 (diff) |
Fix --generate-mono-glue bug when directory doesn't exist
DirAccess::get_full_path(path) only works if the path exists. Implement our own abspath function.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/mono/editor/bindings_generator.cpp | 24 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 6 | ||||
-rw-r--r-- | modules/mono/utils/path_utils.cpp | 127 | ||||
-rw-r--r-- | modules/mono/utils/path_utils.h | 32 |
4 files changed, 128 insertions, 61 deletions
diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b7a85b6216..45037bf637 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -875,14 +875,14 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect da->make_dir("Core"); da->make_dir("ObjectType"); - String core_dir = path_join(p_proj_dir, "Core"); - String obj_type_dir = path_join(p_proj_dir, "ObjectType"); + String core_dir = path::join(p_proj_dir, "Core"); + String obj_type_dir = path::join(p_proj_dir, "ObjectType"); // Generate source file for global scope constants and enums { StringBuilder constants_source; _generate_global_constants(constants_source); - String output_file = path_join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs"); + String output_file = path::join(core_dir, BINDINGS_GLOBAL_SCOPE_CLASS "_constants.cs"); Error save_err = _save_file(output_file, constants_source); if (save_err != OK) return save_err; @@ -896,7 +896,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect if (itype.api_type == ClassDB::API_EDITOR) continue; - String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); + String output_file = path::join(obj_type_dir, itype.proxy_name + ".cs"); Error err = _generate_cs_type(itype, output_file); if (err == ERR_SKIP) @@ -917,7 +917,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect const String &file_name = E->key(); const GodotCsCompressedFile &file_data = E->value(); - String output_file = path_join(core_dir, file_name); + String output_file = path::join(core_dir, file_name); Vector<uint8_t> data; data.resize(file_data.uncompressed_size); @@ -971,7 +971,7 @@ Error BindingsGenerator::generate_cs_core_project(const String &p_proj_dir, Vect cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); - String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); + String internal_methods_file = path::join(core_dir, BINDINGS_CLASS_NATIVECALLS ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) @@ -996,8 +996,8 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve da->make_dir("Core"); da->make_dir("ObjectType"); - String core_dir = path_join(p_proj_dir, "Core"); - String obj_type_dir = path_join(p_proj_dir, "ObjectType"); + String core_dir = path::join(p_proj_dir, "Core"); + String obj_type_dir = path::join(p_proj_dir, "ObjectType"); for (OrderedHashMap<StringName, TypeInterface>::Element E = obj_types.front(); E; E = E.next()) { const TypeInterface &itype = E.get(); @@ -1005,7 +1005,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve if (itype.api_type != ClassDB::API_EDITOR) continue; - String output_file = path_join(obj_type_dir, itype.proxy_name + ".cs"); + String output_file = path::join(obj_type_dir, itype.proxy_name + ".cs"); Error err = _generate_cs_type(itype, output_file); if (err == ERR_SKIP) @@ -1051,7 +1051,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve cs_icalls_content.append(INDENT1 CLOSE_BLOCK CLOSE_BLOCK); - String internal_methods_file = path_join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs"); + String internal_methods_file = path::join(core_dir, BINDINGS_CLASS_NATIVECALLS_EDITOR ".cs"); Error err = _save_file(internal_methods_file, cs_icalls_content); if (err != OK) @@ -1064,7 +1064,7 @@ Error BindingsGenerator::generate_cs_editor_project(const String &p_proj_dir, Ve Error BindingsGenerator::generate_cs_api(const String &p_output_dir) { - String output_dir = DirAccess::get_full_path(p_output_dir, DirAccess::ACCESS_FILESYSTEM); + String output_dir = path::abspath(path::realpath(p_output_dir)); DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); @@ -1862,7 +1862,7 @@ Error BindingsGenerator::generate_glue(const String &p_output_dir) { output.append("\n#endif // MONO_GLUE_ENABLED\n"); - Error save_err = _save_file(path_join(p_output_dir, "mono_glue.gen.cpp"), output); + Error save_err = _save_file(path::join(p_output_dir, "mono_glue.gen.cpp"), output); if (save_err != OK) return save_err; diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 7ae991eeaa..5c63359d88 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -241,9 +241,9 @@ void GDMono::initialize() { locations.push_back("/usr/local/var/homebrew/linked/mono/"); for (int i = 0; i < locations.size(); i++) { - String hint_assembly_rootdir = path_join(locations[i], "lib"); - String hint_mscorlib_path = path_join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll"); - String hint_config_dir = path_join(locations[i], "etc"); + String hint_assembly_rootdir = path::join(locations[i], "lib"); + String hint_mscorlib_path = path::join(hint_assembly_rootdir, "mono", "4.5", "mscorlib.dll"); + String hint_config_dir = path::join(locations[i], "etc"); if (FileAccess::exists(hint_mscorlib_path) && DirAccess::exists(hint_config_dir)) { assembly_rootdir = hint_assembly_rootdir; diff --git a/modules/mono/utils/path_utils.cpp b/modules/mono/utils/path_utils.cpp index 6e431f51e7..20863b1afe 100644 --- a/modules/mono/utils/path_utils.cpp +++ b/modules/mono/utils/path_utils.cpp @@ -36,16 +36,21 @@ #include "core/project_settings.h" #ifdef WINDOWS_ENABLED +#include <windows.h> + #define ENV_PATH_SEP ";" #else -#define ENV_PATH_SEP ":" #include <limits.h> +#include <unistd.h> + +#define ENV_PATH_SEP ":" #endif #include <stdlib.h> -String path_which(const String &p_name) { +namespace path { +String find_executable(const String &p_name) { #ifdef WINDOWS_ENABLED Vector<String> exts = OS::get_singleton()->get_environment("PATHEXT").split(ENV_PATH_SEP, false); #endif @@ -55,7 +60,7 @@ String path_which(const String &p_name) { return String(); for (int i = 0; i < env_path.size(); i++) { - String p = path_join(env_path[i], p_name); + String p = path::join(env_path[i], p_name); #ifdef WINDOWS_ENABLED for (int j = 0; j < exts.size(); j++) { @@ -73,42 +78,96 @@ String path_which(const String &p_name) { return String(); } -void fix_path(const String &p_path, String &r_out) { - r_out = p_path.replace("\\", "/"); +String cwd() { +#ifdef WINDOWS_ENABLED + const DWORD expected_size = ::GetCurrentDirectoryW(0, NULL); + + String buffer; + buffer.resize((int)expected_size); + if (::GetCurrentDirectoryW(expected_size, buffer.ptrw()) == 0) + return "."; + + return buffer.simplify_path(); +#else + char buffer[PATH_MAX]; + if (::getcwd(buffer, sizeof(buffer)) == NULL) + return "."; + + String result; + if (result.parse_utf8(buffer)) + return "."; - while (true) { // in case of using 2 or more slash - String compare = r_out.replace("//", "/"); - if (r_out == compare) - break; - else - r_out = compare; + return result.simplify_path(); +#endif +} + +String abspath(const String &p_path) { + if (p_path.is_abs_path()) { + return p_path.simplify_path(); + } else { + return path::join(path::cwd(), p_path).simplify_path(); } } -bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path) { +String realpath(const String &p_path) { #ifdef WINDOWS_ENABLED - CharType ret[_MAX_PATH]; - if (::_wfullpath(ret, p_existing_path.c_str(), _MAX_PATH)) { - String abspath = String(ret).replace("\\", "/"); - int pos = abspath.find(":/"); - if (pos != -1) { - r_abs_path = abspath.substr(pos - 1, abspath.length()); - } else { - r_abs_path = abspath; - } - return true; - } -#else - char *resolved_path = ::realpath(p_existing_path.utf8().get_data(), NULL); - if (resolved_path) { - String retstr; - bool success = !retstr.parse_utf8(resolved_path); - ::free(resolved_path); - if (success) { - r_abs_path = retstr; - return true; - } + // Open file without read/write access + HANDLE hFile = ::CreateFileW(p_path.c_str(), 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return p_path; + + const DWORD expected_size = ::GetFinalPathNameByHandleW(hFile, NULL, 0, FILE_NAME_NORMALIZED); + + if (expected_size == 0) { + ::CloseHandle(hFile); + return p_path; } + + String buffer; + buffer.resize((int)expected_size); + ::GetFinalPathNameByHandleW(hFile, buffer.ptrw(), expected_size, FILE_NAME_NORMALIZED); + + ::CloseHandle(hFile); + return buffer.simplify_path(); +#elif UNIX_ENABLED + char *resolved_path = ::realpath(p_path.utf8().get_data(), NULL); + + if (!resolved_path) + return p_path; + + String result; + bool parse_ok = result.parse_utf8(resolved_path); + ::free(resolved_path); + + if (parse_ok) + return p_path; + + return result.simplify_path(); #endif - return false; } + +String join(const String &p_a, const String &p_b) { + if (p_a.empty()) + return p_b; + + const CharType a_last = p_a[p_a.length() - 1]; + if ((a_last == '/' || a_last == '\\') || + (p_b.size() > 0 && (p_b[0] == '/' || p_b[0] == '\\'))) { + return p_a + p_b; + } + + return p_a + "/" + p_b; +} + +String join(const String &p_a, const String &p_b, const String &p_c) { + return path::join(path::join(p_a, p_b), p_c); +} + +String join(const String &p_a, const String &p_b, const String &p_c, const String &p_d) { + return path::join(path::join(path::join(p_a, p_b), p_c), p_d); +} + +} // namespace path diff --git a/modules/mono/utils/path_utils.h b/modules/mono/utils/path_utils.h index 69edf4deb7..ca25bc09f7 100644 --- a/modules/mono/utils/path_utils.h +++ b/modules/mono/utils/path_utils.h @@ -31,24 +31,32 @@ #ifndef PATH_UTILS_H #define PATH_UTILS_H +#include "core/string_builder.h" #include "core/ustring.h" -_FORCE_INLINE_ String path_join(const String &e1, const String &e2) { - return e1.plus_file(e2); -} +namespace path { -_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3) { - return e1.plus_file(e2).plus_file(e3); -} +String join(const String &p_a, const String &p_b); +String join(const String &p_a, const String &p_b, const String &p_c); +String join(const String &p_a, const String &p_b, const String &p_c, const String &p_d); -_FORCE_INLINE_ String path_join(const String &e1, const String &e2, const String &e3, const String &e4) { - return e1.plus_file(e2).plus_file(e3).plus_file(e4); -} +String find_executable(const String &p_name); -String path_which(const String &p_name); +/// Returns a normalized absolute path to the current working directory +String cwd(); -void fix_path(const String &p_path, String &r_out); +/** + * Obtains a normalized absolute path to p_path. Symbolic links are + * not resolved. The path p_path might not exist in the file system. + */ +String abspath(const String &p_path); -bool rel_path_to_abs(const String &p_existing_path, String &r_abs_path); +/** + * Obtains a normalized path to p_path with symbolic links resolved. + * The resulting path might be either a relative or an absolute path. + */ +String realpath(const String &p_path); + +} // namespace path #endif // PATH_UTILS_H |