Add method to check if filesystem is case sensitive.
This commit is contained in:
parent
6916349697
commit
97bcd8a631
|
@ -546,6 +546,10 @@ bool DirAccess::get_include_hidden() const {
|
|||
return include_hidden;
|
||||
}
|
||||
|
||||
bool DirAccess::is_case_sensitive(const String &p_path) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void DirAccess::_bind_methods() {
|
||||
ClassDB::bind_static_method("DirAccess", D_METHOD("open", "path"), &DirAccess::_open);
|
||||
ClassDB::bind_static_method("DirAccess", D_METHOD("get_open_error"), &DirAccess::get_open_error);
|
||||
|
@ -583,6 +587,8 @@ void DirAccess::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
|
||||
ClassDB::bind_method(D_METHOD("get_include_hidden"), &DirAccess::get_include_hidden);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("is_case_sensitive", "path"), &DirAccess::is_case_sensitive);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_navigational"), "set_include_navigational", "get_include_navigational");
|
||||
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "include_hidden"), "set_include_hidden", "get_include_hidden");
|
||||
}
|
||||
|
|
|
@ -159,6 +159,8 @@ public:
|
|||
void set_include_hidden(bool p_enable);
|
||||
bool get_include_hidden() const;
|
||||
|
||||
virtual bool is_case_sensitive(const String &p_path) const;
|
||||
|
||||
DirAccess() {}
|
||||
virtual ~DirAccess() {}
|
||||
};
|
||||
|
|
|
@ -204,6 +204,14 @@
|
|||
Returns the available space on the current directory's disk, in bytes. Returns [code]0[/code] if the platform-specific method to query the available space fails.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_case_sensitive" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="path" type="String" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the file system or directory use case sensitive file names.
|
||||
[b]Note:[/b] This method is implemented on macOS and Windows. On other platforms, it always returns [code]true[/code].
|
||||
</description>
|
||||
</method>
|
||||
<method name="list_dir_begin">
|
||||
<return type="int" enum="Error" />
|
||||
<description>
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "dir_access_windows.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/os/memory.h"
|
||||
#include "core/string/print_string.h"
|
||||
|
||||
|
@ -40,6 +41,26 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
typedef struct _NT_IO_STATUS_BLOCK {
|
||||
union {
|
||||
LONG Status;
|
||||
PVOID Pointer;
|
||||
} DUMMY;
|
||||
ULONG_PTR Information;
|
||||
} NT_IO_STATUS_BLOCK;
|
||||
|
||||
typedef struct _NT_FILE_CASE_SENSITIVE_INFO {
|
||||
ULONG Flags;
|
||||
} NT_FILE_CASE_SENSITIVE_INFO;
|
||||
|
||||
typedef enum _NT_FILE_INFORMATION_CLASS {
|
||||
FileCaseSensitiveInformation = 71,
|
||||
} NT_FILE_INFORMATION_CLASS;
|
||||
|
||||
#define NT_FILE_CS_FLAG_CASE_SENSITIVE_DIR 0x00000001
|
||||
|
||||
extern "C" NTSYSAPI LONG NTAPI NtQueryInformationFile(HANDLE FileHandle, NT_IO_STATUS_BLOCK *IoStatusBlock, PVOID FileInformation, ULONG Length, NT_FILE_INFORMATION_CLASS FileInformationClass);
|
||||
|
||||
struct DirAccessWindowsPrivate {
|
||||
HANDLE h; // handle for FindFirstFile.
|
||||
WIN32_FIND_DATA f;
|
||||
|
@ -340,6 +361,33 @@ String DirAccessWindows::get_filesystem_type() const {
|
|||
ERR_FAIL_V("");
|
||||
}
|
||||
|
||||
bool DirAccessWindows::is_case_sensitive(const String &p_path) const {
|
||||
String f = p_path;
|
||||
if (!f.is_absolute_path()) {
|
||||
f = get_current_dir().path_join(f);
|
||||
}
|
||||
f = fix_path(f);
|
||||
|
||||
HANDLE h_file = ::CreateFileW((LPCWSTR)(f.utf16().get_data()), 0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
|
||||
if (h_file == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NT_IO_STATUS_BLOCK io_status_block;
|
||||
NT_FILE_CASE_SENSITIVE_INFO file_info;
|
||||
LONG out = NtQueryInformationFile(h_file, &io_status_block, &file_info, sizeof(NT_FILE_CASE_SENSITIVE_INFO), FileCaseSensitiveInformation);
|
||||
::CloseHandle(h_file);
|
||||
|
||||
if (out >= 0) {
|
||||
return file_info.Flags & NT_FILE_CS_FLAG_CASE_SENSITIVE_DIR;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
DirAccessWindows::DirAccessWindows() {
|
||||
p = memnew(DirAccessWindowsPrivate);
|
||||
p->h = INVALID_HANDLE_VALUE;
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
uint64_t get_space_left() override;
|
||||
|
||||
virtual String get_filesystem_type() const override;
|
||||
virtual bool is_case_sensitive(const String &p_path) const override;
|
||||
|
||||
DirAccessWindows();
|
||||
~DirAccessWindows();
|
||||
|
|
|
@ -1776,12 +1776,12 @@ void FileSystemDock::_rename_operation_confirm() {
|
|||
|
||||
// Present a more user friendly warning for name conflict.
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||
#if defined(WINDOWS_ENABLED)
|
||||
// Workaround case insensitivity on Windows.
|
||||
if ((da->file_exists(new_path) || da->dir_exists(new_path)) && new_path.to_lower() != old_path.to_lower()) {
|
||||
#else
|
||||
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
|
||||
#endif
|
||||
|
||||
bool new_exist = (da->file_exists(new_path) || da->dir_exists(new_path));
|
||||
if (!da->is_case_sensitive(new_path.get_base_dir())) {
|
||||
new_exist = new_exist && (new_path.to_lower() != old_path.to_lower());
|
||||
}
|
||||
if (new_exist) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
|
||||
s->set_text(col_index, old_name);
|
||||
return;
|
||||
|
|
|
@ -49,6 +49,7 @@ protected:
|
|||
virtual String get_drive(int p_drive) override;
|
||||
|
||||
virtual bool is_hidden(const String &p_name) override;
|
||||
virtual bool is_case_sensitive(const String &p_path) const override;
|
||||
};
|
||||
|
||||
#endif // UNIX ENABLED
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include "dir_access_macos.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
|
||||
#if defined(UNIX_ENABLED)
|
||||
|
||||
#include <errno.h>
|
||||
|
@ -78,4 +80,19 @@ bool DirAccessMacOS::is_hidden(const String &p_name) {
|
|||
return [hidden boolValue];
|
||||
}
|
||||
|
||||
bool DirAccessMacOS::is_case_sensitive(const String &p_path) const {
|
||||
String f = p_path;
|
||||
if (!f.is_absolute_path()) {
|
||||
f = get_current_dir().path_join(f);
|
||||
}
|
||||
f = fix_path(f);
|
||||
|
||||
NSURL *url = [NSURL fileURLWithPath:@(f.utf8().get_data())];
|
||||
NSNumber *cs = nil;
|
||||
if (![url getResourceValue:&cs forKey:NSURLVolumeSupportsCaseSensitiveNamesKey error:nil]) {
|
||||
return false;
|
||||
}
|
||||
return [cs boolValue];
|
||||
}
|
||||
|
||||
#endif // UNIX_ENABLED
|
||||
|
|
|
@ -419,6 +419,7 @@ def configure_msvc(env, vcvars_msvc_config):
|
|||
"dwmapi",
|
||||
"dwrite",
|
||||
"wbemuuid",
|
||||
"ntdll",
|
||||
]
|
||||
|
||||
if env.debug_features:
|
||||
|
@ -610,6 +611,7 @@ def configure_mingw(env):
|
|||
"dwmapi",
|
||||
"dwrite",
|
||||
"wbemuuid",
|
||||
"ntdll",
|
||||
]
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in New Issue