Skip to content

Conversation

@TML233
Copy link
Contributor

@TML233 TML233 commented Oct 26, 2024

closes godotengine/godot-proposals#11032
closes godotengine/godot-proposals#6307

This PR is a refactor of the Godot FileAccess system. It adds FileSystem and FileSystemProtocol to manage file path prefixes.

FileAccess access type and create_funcs are removed now. Different FileAccess types only deals with their targeted file source now, which means different platform's OS FileAccess now only handles paths that are in the os filesystem. They don't need to handle res:// user:// anymore, in fact, they don't even know about other protocols now. Platforms now implement their own OS protocol and OS FileAccess and register the os protocol to the FileSystem.

Current-file-unrelated methods like file_exists(path) and get_modified_time(path) are also moved to FileSystemProtocol. The original implementation instantiates a FileAccess, calls the method and immediately throws it away. This change can theoretically improve the performance with simple file operations.

By pre-defining some FileSystemProtocols that remaps paths, users can easily register a protocol prefix that remaps file paths.

Next, I'll move current-directory-unrelated methods to FileSystemProtocol. Making calls to those absolute directory methods will become cheaper. DirAccess can also just become a simple wrapper of FileSystemProtocols.

Issues

(Fixed) gdscript://

Solution

As far as I can tell, gdscript://object_id.gd represents a gdscript instance in memory.
To prevent stepping in old code, gdscript protocol is reserved. It fails all accesses silently.

Descripton

Introduced by #71197
This is the reason that GDScript test fails. It expects hardcoded console output. During the test, GDScript system requires a resource load for the file path prefixed gdscript://, which would silently fail and return false in the old FileAccess implementation. But in FileSystem, an error message of Unknown filesystem protocol gdscript generates, thus failing the test.
I don't think muting the error message is a good approach, if anyone adds a gdscript protocol, GDScript system would break because of this.

non-OS DirAccess change_dir to aboslute OS paths

DirAccess.make_dir_recursive_absolute("user://test")

# Get the aboslute OS path for user://test
# might be `%APPDATA%\Godot\app_userdata\GameName\test` on Windows
# or `~/.local/share/godot/app_userdata/GameName/test` on Linux
var absolute_path = ProjectSettings.globalize_path("user://test")


var dir = DirAccess.open("user://")

# This won't work as expected, DirAccess forbids you switch to directories outside user://
dir.change_dir("/any/other/path/on/disk")

# But this works, even if the given absolute path is not a path with user:// prefix
dir.change_dir(absolute_path)

# Current path is now user://test
print(dir.get_current_path())

This is caused by how change_dir handles protocol prefixes. It converts current path and target path to OS absolute paths, does the CWD changing to verify the path, and finally strip the specific protocol's root path from the aboslute path and add the protocol prefix.

It doesn't seem to be a by-design behavior for a DirAccess which handles prefixed paths to successfully change into an aboslute OS path. This seems to only be a weird edge case caused by the original implementation.

This won't work anymore after this PR, because every protocol handler are only given the path under that prefix now. You can only change_dir to a relative path or an absolute path with that prefix now.

Todo

  • Add FileSystem & FileSystemProtocol
  • Move current-file-unrelated methods of FileAccess to FileSystemProtocol
  • Move current-directory-unrelated methods of DirAccess to FileSystemProtocol
  • Write documents

Move hard-coded protocols to FileSystemProtocol

os:// and pipe:// are implemented and registered by different OS platforms.

  • res://
  • user://
  • uid://

Platform supports

Create FileSystemProtocolOS and FileSystemProtocolPipe.
Cleanup FileAccessPlatform and FileAccessPlatformPipe.
Add OS_Platform::initialize_filesystem().
Remove previous FileAccess::make_default calls from OS_Platform::initialize()

  • Windows
  • Linux
  • Android
  • MacOS (For DirAccess)

Future Tasks

  • Add FileAccessProtocolRemap
  • Expose FileSystemProtocol to GDVirtual

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a FileSystemProtocol to handle the path prefixes instead of doing it hard-coded in FileAccess Implement custom resource path support

2 participants