diff --git a/docs/user/config.adoc b/docs/user/config.adoc index 2bbb60e6d..0534ad027 100644 --- a/docs/user/config.adoc +++ b/docs/user/config.adoc @@ -42,7 +42,8 @@ There's no support for multiple config files or inheriting/overriding config fil "language": "Default", "permissionLevel": 2, "plugins": [], - "mcmetaSummaryOverrides": {} + "mcmetaSummaryOverrides": {}, + useFilePolling: false }, "format": { "blockStateBracketSpacing": { "inside": 0 }, diff --git a/packages/core/src/common/externals/NodeJsExternals.ts b/packages/core/src/common/externals/NodeJsExternals.ts index 8c69299be..a138775eb 100644 --- a/packages/core/src/common/externals/NodeJsExternals.ts +++ b/packages/core/src/common/externals/NodeJsExternals.ts @@ -117,8 +117,10 @@ export const NodeJsExternals: Externals = { unlink(location) { return fsp.unlink(toFsPathLike(location)) }, - watch(locations) { - return new ChokidarWatcherWrapper(chokidar.watch(locations.map(toPath))) + watch(locations, { usePolling = false } = {}) { + return new ChokidarWatcherWrapper( + chokidar.watch(locations.map(toPath), { usePolling }), + ) }, writeFile(location, data, options) { return fsp.writeFile(toFsPathLike(location), data, options) diff --git a/packages/core/src/common/externals/index.ts b/packages/core/src/common/externals/index.ts index f6dad7621..7a9b2fda1 100644 --- a/packages/core/src/common/externals/index.ts +++ b/packages/core/src/common/externals/index.ts @@ -71,7 +71,7 @@ export interface ExternalFileSystem { showFile(path: FsLocation): Promise stat(location: FsLocation): Promise<{ isDirectory(): boolean; isFile(): boolean }> unlink(location: FsLocation): Promise - watch(locations: FsLocation[]): FsWatcher + watch(locations: FsLocation[], options: { usePolling?: boolean }): FsWatcher /** * @param options `mode` - File mode bit mask (e.g. `0o775`). */ diff --git a/packages/core/src/service/Config.ts b/packages/core/src/service/Config.ts index a4613ffad..c93159bb5 100644 --- a/packages/core/src/service/Config.ts +++ b/packages/core/src/service/Config.ts @@ -115,6 +115,16 @@ export interface EnvConfig { > permissionLevel: 1 | 2 | 3 | 4 plugins: string[] + /** + * Makes the file-watcher use polling to watch for file changes. + * Comes at a performance cost for very large datapacks. + * + * On Windows, enabling this can fix file-lock issues when Spyglass is running. + * See: https://github.com/SpyglassMC/Spyglass/issues/1414 + * + * **You should only consider enabling this for Windows machines.** + */ + useFilePolling: boolean } export type LinterSeverity = 'hint' | 'information' | 'warning' | 'error' @@ -352,6 +362,7 @@ export const VanillaConfig: Config = { permissionLevel: 2, plugins: [], mcmetaSummaryOverrides: {}, + useFilePolling: false, }, format: { blockStateBracketSpacing: { inside: 0 }, diff --git a/packages/core/src/service/Project.ts b/packages/core/src/service/Project.ts index ecbf6f853..29e853ae0 100644 --- a/packages/core/src/service/Project.ts +++ b/packages/core/src/service/Project.ts @@ -511,7 +511,9 @@ export class Project implements ExternalEventEmitter { } this.#watchedFiles.clear() this.#watcherReady = false - this.#watcher = this.externals.fs.watch(this.projectRoots).once('ready', () => { + this.#watcher = this.externals.fs.watch(this.projectRoots, { + usePolling: this.config.env.useFilePolling, + }).once('ready', () => { this.#watcherReady = true resolve() }).on('add', (uri) => {