-
Notifications
You must be signed in to change notification settings - Fork 718
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Delete files not existent in project directory #6501
Conversation
…al layouts , duplicate files exist. When renaming scenes/extensions/external events/external layouts, duplicate files exist, one with the old name and one with the new name. When deleting this items, the respective files are also not removed from the project directory. This is due to the fact that when saving the project, only the existing files in the project editor are written and saved, and the old ones still remain, potentialy creating duplicates and confusion. Therefore, when saving, we can resolve this issue by deleting all files from the scenes/extensions/external events/external layouts directories, before writing the correct files.
Hi @DavidMLPalma, I feel like this strategy is a bit brutal. We already have issues with users saving their projects in the installation directory and losing their projects because of that (when GDevelop is updated). So I think it's better not to have another potential cause for losing files. May I suggest that you check if the directory name is in the list |
Hi @AlexandreSi , I totally get your point, and in fact by checking if the directory name is one of those present in the list may lead to a more secure solution. I will change it then. |
@@ -142,6 +168,12 @@ export const onSaveProject = ( | |||
}; | |||
|
|||
const projectPath = path.dirname(filePath); | |||
|
|||
deleteExistingFilesFromDirs(projectPath).catch(err => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you improve a bit the whole onSaveProject
function so that it's an async
function? (If you're not familiar with it, I can provide guidance).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I improve the deleteExistingFilesFromDirs
function so it's an async
functions as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I think it's okay to keep it synchronous
@@ -142,6 +168,12 @@ export const onSaveProject = ( | |||
}; | |||
|
|||
const projectPath = path.dirname(filePath); | |||
|
|||
deleteExistingFilesFromDirs(projectPath).catch(err => { | |||
console.error('Unable to delete files in the project:', err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think here we could gain clarity if you mention the context: Unable to clean project folder before saving project:
//Project file | ||
if (entries.length === 1) resolve(); | ||
|
||
//If multiFile enabled in settings and directories exist! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You do not actually check if multifile is enabled in the project's settings. You should use project.isFolderProject()
for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make it one step clearer by removing the indent, you could do this:
if (!project.isFolderProject()) return;
const entries = fs.readdirSync(projectPath);
...
Also, I'm not sure this comment is useful anymore, your code is quite clear.
newIDE/app/src/ProjectsStorage/LocalFileStorageProvider/LocalProjectWriter.js
Outdated
Show resolved
Hide resolved
filenames.forEach(file => { | ||
let result = dirPath.concat('\\', file); | ||
fs.unlink(result, err => { | ||
if (err) return reject(err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could add context here, such as:
throw new Error(`Unable to remove file ${file}: ${err.message}`
Or something like that
Hi @AlexandreSi , |
if (project.isFolderProject()) { | ||
//If multiFile enabled in settings and directories exist! | ||
entries.forEach(entry => { | ||
let dirPath = projectPath.concat('\\', entry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot to check how you handle paths: Using strings that you concat yourself won't work because Windows user \
separator while Linux and macOS user /
. So you should use path.join
instead. You can find other users of path in the codebase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Furthermore, you can use const
instead of let
since you never reassign the variable value
let dirPath = projectPath.concat('\\', entry); | ||
if ( | ||
fs.statSync(dirPath).isDirectory() && | ||
splittedProjectFolderNames.includes(entry) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use this condition as an early return as well:
if (splittedProjectFolderNames.includes(entry)) return;
let dirPath = projectPath.concat('\\', entry);
...
) { | ||
const filenames = fs.readdirSync(dirPath); | ||
filenames.forEach(file => { | ||
let result = dirPath.concat('\\', file); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could rename result
with a name that actually represents what it is: filePath
or fileToRemovePath
Hi @AlexandreSi , Once again, thanks for your help and consideration ! |
try { | ||
deleteExistingFilesFromDirs(project, projectPath); | ||
} catch (e) { | ||
return Promise.reject( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that deleting the existing files from the folders should fail silently.
You can use instead:
console.warn('Unable to clean project folder before saving project: ', error)
But stopping a save could mean preventing a user from saving if an error happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, since you made the change to an async function (thank you!), could you replace the return new Promise.reject
line 158 by a throw new Error('...')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done !
if (!splittedProjectFolderNames.includes(entry)) return; | ||
|
||
const dirPath = path.join(projectPath, entry); | ||
if (fs.statSync(dirPath).isDirectory()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also replace the added intent by an early return here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks for staying with me though I asked for a lot of changes. I hope our coding style is clearer to you today!
Fix #4120 : When renaming scenes/extensions/external events/external layouts, duplicate files exist, one with the old name and one with the new name. Similarly, when deleting this items, the respective files are also not removed from the project directory. This is due to the fact that when saving the project, only the existing files in the project editor are written and saved, and nothing more is done. There may still remain old files that should not be there, potentially creating duplicates and confusion. Therefore, when saving, we can resolve this issue by deleting all files from the scenes/extensions/external events/external layouts directories, before writing the correct files.