diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 583aaad3cdb..ac710e6992b 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -730,6 +730,7 @@ namespace ts { const nodeVersion = getNodeMajorVersion(); const isNode4OrLater = nodeVersion! >= 4; + const isLinuxOrMacOs = process.platform === "linux" || process.platform === "darwin"; const platform: string = _os.platform(); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); @@ -1029,6 +1030,12 @@ namespace ts { function fsWatch(fileOrDirectory: string, entryKind: FileSystemEntryKind.File | FileSystemEntryKind.Directory, callback: FsWatchCallback, recursive: boolean, fallbackPollingWatchFile: HostWatchFile, pollingInterval?: number): FileWatcher { let options: any; + const lastDirectoryPartWithDirectorySeparator = isLinuxOrMacOs ? + fileOrDirectory.substr(fileOrDirectory.lastIndexOf(directorySeparator)) : + undefined; + const lastDirectoryPart = isLinuxOrMacOs ? + lastDirectoryPartWithDirectorySeparator!.slice(directorySeparator.length) : + undefined; /** Watcher for the file system entry depending on whether it is missing or present */ let watcher = !fileSystemEntryExists(fileOrDirectory, entryKind) ? watchMissingFileSystemEntry() : @@ -1072,11 +1079,12 @@ namespace ts { } } try { - const presentWatcher = _fs.watch( fileOrDirectory, options, - callback + isLinuxOrMacOs ? + callbackChangingToMissingFileSystemEntry : + callback ); // Watch the missing file or directory or error presentWatcher.on("error", () => invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry)); @@ -1090,6 +1098,18 @@ namespace ts { } } + function callbackChangingToMissingFileSystemEntry(event: "rename" | "change", relativeName: string | undefined) { + // because relativeName is not guaranteed to be correct we need to check on each rename with few combinations + // Eg on ubuntoo while watchin app/node_modules the relativeName is "node_modules" which is neither relative nor full path + return event === "rename" && + (!relativeName || + relativeName === lastDirectoryPart || + relativeName.lastIndexOf(lastDirectoryPartWithDirectorySeparator!) === relativeName.length - lastDirectoryPartWithDirectorySeparator!.length) && + !fileSystemEntryExists(fileOrDirectory, entryKind) ? + invokeCallbackAndUpdateWatcher(watchMissingFileSystemEntry) : + callback(event, relativeName); + } + /** * Watch the file or directory using fs.watchFile since fs.watch threw exception * Eg. on linux the number of watches are limited and one could easily exhaust watches and the exception ENOSPC is thrown when creating watcher at that point