Files
GDevelop/newIDE/electron-app/app/LocalFilesystemWatcher.js
Florian Rival 0771088db7 Fix endless reloads of in-game editor on Windows due to autosave
Also fix ignored files watching on Windows
2025-12-02 16:42:07 +01:00

83 lines
2.5 KiB
JavaScript

// @flow
const fileWatcher = require('chokidar');
const path = require('path');
let subscriptionCancelers = {};
let newSubscriptionId = 1;
const getNewSubscriptionId = () => {
const id = newSubscriptionId++;
return id.toString();
};
const normalizePath = path => {
if (!path) return ''; // Safety check
return path.replace(/\\/g, '/');
};
const setupWatcher = (folderPath, fileWiseCallback, serializedOptions) => {
const options = JSON.parse(serializedOptions);
const newSubscriptionId = getNewSubscriptionId();
const watcher = fileWatcher
.watch(folderPath, {
ignored: candidatePath => {
// Normalize the path to avoid issues with different path separators (\ on Windows, / on other OSes).
// Even on Windows, "candidatePath" returned by chokidar is always using "/".
// So we normalize all paths (candidatePath and ignore paths) to avoid missing ignored files on Windows.
const normalizedCandidatePath = normalizePath(candidatePath);
if (
(options.ignore || []).some(ignore =>
normalizedCandidatePath.includes(normalizePath(ignore))
) ||
// Force ignore, for safety, any node_modules folder as they are too big and would crash the watcher on macOS.
// Note that this will ignore any folder whose name is prefixed by "node_modules".
normalizedCandidatePath.includes('/node_modules') ||
// Same for git repositories (and any file starting by ".git").
normalizedCandidatePath.includes('/.git')
) {
console.info(
`Local file watcher has ignored path "${normalizedCandidatePath}".`
);
return true;
}
return false;
},
ignoreInitial: true,
awaitWriteFinish: {
stabilityThreshold: 250,
pollInterval: 100,
},
})
.on(
'change',
// TODO: Is it safe to let it like that since the OS could for some reason
// do never-ending operations on the folder or its children, making the debounce
// never ending.
fileWiseCallback
)
.on('unlink', fileWiseCallback)
.on('add', fileWiseCallback);
subscriptionCancelers[newSubscriptionId] = () => watcher.unwatch(folderPath);
return newSubscriptionId;
};
const disableWatcher = id => {
const subscriptionCanceler = subscriptionCancelers[id];
if (!subscriptionCanceler) {
console.log('No watcher subscription to disable.');
return;
}
subscriptionCanceler();
delete subscriptionCancelers[id];
};
module.exports = {
setupWatcher,
disableWatcher,
};