1
0
Fork 0

Merge pull request #79342 from RedworkDE/localize-win-path

Fix `ProjectSettings::localize_path` for Windows paths
This commit is contained in:
Rémi Verschelde 2023-08-07 14:45:48 +02:00
commit 432405a3e1
No known key found for this signature in database
GPG Key ID: C3336907360768E1
3 changed files with 69 additions and 8 deletions

View File

@ -146,30 +146,30 @@ const PackedStringArray ProjectSettings::_trim_to_supported_features(const Packe
#endif // TOOLS_ENABLED #endif // TOOLS_ENABLED
String ProjectSettings::localize_path(const String &p_path) const { String ProjectSettings::localize_path(const String &p_path) const {
if (resource_path.is_empty() || (p_path.is_absolute_path() && !p_path.begins_with(resource_path))) { String path = p_path.simplify_path();
return p_path.simplify_path();
if (resource_path.is_empty() || (path.is_absolute_path() && !path.begins_with(resource_path))) {
return path;
} }
// Check if we have a special path (like res://) or a protocol identifier. // Check if we have a special path (like res://) or a protocol identifier.
int p = p_path.find("://"); int p = path.find("://");
bool found = false; bool found = false;
if (p > 0) { if (p > 0) {
found = true; found = true;
for (int i = 0; i < p; i++) { for (int i = 0; i < p; i++) {
if (!is_ascii_alphanumeric_char(p_path[i])) { if (!is_ascii_alphanumeric_char(path[i])) {
found = false; found = false;
break; break;
} }
} }
} }
if (found) { if (found) {
return p_path.simplify_path(); return path;
} }
Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
String path = p_path.replace("\\", "/").simplify_path();
if (dir->change_dir(path) == OK) { if (dir->change_dir(path) == OK) {
String cwd = dir->get_current_dir(); String cwd = dir->get_current_dir();
cwd = cwd.replace("\\", "/"); cwd = cwd.replace("\\", "/");
@ -187,7 +187,7 @@ String ProjectSettings::localize_path(const String &p_path) const {
cwd = cwd.path_join(""); cwd = cwd.path_join("");
if (!cwd.begins_with(res_path)) { if (!cwd.begins_with(res_path)) {
return p_path; return path;
} }
return cwd.replace_first(res_path, "res://"); return cwd.replace_first(res_path, "res://");

View File

@ -43,6 +43,7 @@ class TypedArray;
class ProjectSettings : public Object { class ProjectSettings : public Object {
GDCLASS(ProjectSettings, Object); GDCLASS(ProjectSettings, Object);
_THREAD_SAFE_CLASS_ _THREAD_SAFE_CLASS_
friend class TestProjectSettingsInternalsAccessor;
public: public:
typedef HashMap<String, Variant> CustomMap; typedef HashMap<String, Variant> CustomMap;

View File

@ -32,9 +32,17 @@
#define TEST_PROJECT_SETTINGS_H #define TEST_PROJECT_SETTINGS_H
#include "core/config/project_settings.h" #include "core/config/project_settings.h"
#include "core/io/dir_access.h"
#include "core/variant/variant.h" #include "core/variant/variant.h"
#include "tests/test_macros.h" #include "tests/test_macros.h"
class TestProjectSettingsInternalsAccessor {
public:
static String &resource_path() {
return ProjectSettings::get_singleton()->resource_path;
};
};
namespace TestProjectSettings { namespace TestProjectSettings {
TEST_CASE("[ProjectSettings] Get existing setting") { TEST_CASE("[ProjectSettings] Get existing setting") {
@ -97,6 +105,58 @@ TEST_CASE("[ProjectSettings] Set value should be returned when retrieved") {
CHECK(ProjectSettings::get_singleton()->has_setting("my_custom_setting")); CHECK(ProjectSettings::get_singleton()->has_setting("my_custom_setting"));
} }
TEST_CASE("[ProjectSettings] localize_path") {
String old_resource_path = TestProjectSettingsInternalsAccessor::resource_path();
TestProjectSettingsInternalsAccessor::resource_path() = DirAccess::create(DirAccess::ACCESS_FILESYSTEM)->get_current_dir();
String root_path = ProjectSettings::get_singleton()->get_resource_path();
#ifdef WINDOWS_ENABLED
String root_path_win = ProjectSettings::get_singleton()->get_resource_path().replace("/", "\\");
#endif
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("filename"), "res://filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("path/filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("path/something/../filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("path/./filename"), "res://path/filename");
#ifdef WINDOWS_ENABLED
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("path\\filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("path\\something\\..\\filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("path\\.\\filename"), "res://path/filename");
#endif
// FIXME?: These checks pass, but that doesn't seems correct
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("../filename"), "res://filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("../path/filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("..\\path\\filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("/testroot/filename"), "/testroot/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("/testroot/path/filename"), "/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("/testroot/path/something/../filename"), "/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("/testroot/path/./filename"), "/testroot/path/filename");
#ifdef WINDOWS_ENABLED
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:/testroot/filename"), "C:/testroot/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:/testroot/path/filename"), "C:/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:/testroot/path/something/../filename"), "C:/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:/testroot/path/./filename"), "C:/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:\\testroot\\filename"), "C:/testroot/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:\\testroot\\path\\filename"), "C:/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:\\testroot\\path\\something\\..\\filename"), "C:/testroot/path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path("C:\\testroot\\path\\.\\filename"), "C:/testroot/path/filename");
#endif
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path + "/filename"), "res://filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path + "/path/filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path + "/path/something/../filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path + "/path/./filename"), "res://path/filename");
#ifdef WINDOWS_ENABLED
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path_win + "\\filename"), "res://filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path_win + "\\path\\filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path_win + "\\path\\something\\..\\filename"), "res://path/filename");
CHECK_EQ(ProjectSettings::get_singleton()->localize_path(root_path_win + "\\path\\.\\filename"), "res://path/filename");
#endif
TestProjectSettingsInternalsAccessor::resource_path() = old_resource_path;
}
} // namespace TestProjectSettings } // namespace TestProjectSettings
#endif // TEST_PROJECT_SETTINGS_H #endif // TEST_PROJECT_SETTINGS_H