Allow renaming project assets while preserving id #576
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Attempt to fix issues seen in When renaming a background it corrupts the project. #574 where renaming assets causes ids to be regenerated and any scenes/events referring to those ids would be broken.
What is the current behavior? (You can also link to an open issue here)
Asset file watching is handled in https://github.com/chrismaltby/gb-studio/blob/v2beta/src/lib/project/watchProject.js using the module chokidar which handles the complexities of cross platform file watching. In chokidar when a watched file is renamed it fires an unlink (delete) file event followed by an add file event with no way to determine that this was a single rename action (and it looks unlikely that this functionality will change Add a file "rename" event paulmillr/chokidar#303). This caused a rename to first delete the asset, then it will be readded, at which point it gets a new id and all previous references are broken.
What is the new behavior (if this is a feature change)?
Using fs.stat I am fetching the inode value for each asset which appears to stay the same after a rename, when a file is deleted I store the asset data in a lookup table by inode and when a new file is added I check if the inode matches a recently deleted one and if it does I reuse the previous id and any additional previous data that might be useful to keep (such as the music speed conversion flag). With this change renaming an asset has a small flash of the asset being deleted before it reappears again a second a later with the scene collisions and actors positions unchanged.
As the inode values also get written to disk in the GBSProj file it's also now possible to rename an asset while GB Studio is closed and it will fix the links when you next load the project.
Maybe, I've only tested this on Mac so far. I'm interested in seeing if this works correctly on Windows. I believe Windows uses 64-bit inode values so I'm using the bigint arg when calling stat
await stat(filename, { bigint: true });
and storing the value as a string (since JSON doesn't support 64-bit values), without testing I can't be sure this is working. I'll do plenty before merging this.Linux should be okay but also needs a lot of testing.