diff -Nru node-chokidar-3.4.3/debian/changelog node-chokidar-3.5.3/debian/changelog --- node-chokidar-3.4.3/debian/changelog 2020-11-12 10:20:35.000000000 +0000 +++ node-chokidar-3.5.3/debian/changelog 2022-05-12 04:31:58.000000000 +0000 @@ -1,3 +1,28 @@ +node-chokidar (3.5.3-2) unstable; urgency=medium + + * Team upload + * Disable more tests (Closes: #1010864) + + -- Yadd Thu, 12 May 2022 06:31:58 +0200 + +node-chokidar (3.5.3-1) unstable; urgency=medium + + * Team upload + + [ lintian-brush ] + * Set upstream metadata fields: Bug-Submit. + * Remove obsolete fields Contact, Name from debian/upstream/metadata + (already present in machine-readable debian/copyright). + + [ Yadd ] + * Add ctype=nodejs to component(s) + * Fix GitHub tags regex + * Update standards version to 4.6.0, no changes needed. + * New upstream version 3.5.3 + * Refresh patches + + -- Yadd Sat, 12 Mar 2022 13:12:36 +0100 + node-chokidar (3.4.3-3) unstable; urgency=medium * Team upload diff -Nru node-chokidar-3.4.3/debian/control node-chokidar-3.5.3/debian/control --- node-chokidar-3.4.3/debian/control 2020-10-27 19:23:01.000000000 +0000 +++ node-chokidar-3.5.3/debian/control 2022-03-12 12:13:34.000000000 +0000 @@ -4,26 +4,27 @@ Section: javascript Testsuite: autopkgtest-pkg-nodejs Priority: optional -Build-Depends: debhelper-compat (= 13), - nodejs , - dh-sequence-nodejs, - mocha (>= 4) , - chai , - node-sinon (>= 7) , - node-rimraf (>= 2.4.3) , - node-sinon-chai , - node-setimmediate , - node-is-glob , - node-is-binary-path , - node-anymatch (>= 3.0.3+~2.0.7-2~) , - node-normalize-path , - node-readdirp (>= 3.3.0) , - node-async-each , - node-braces , - node-path-is-absolute , - node-glob-parent , - node-inherits -Standards-Version: 4.5.0 +Build-Depends: + chai + , debhelper-compat (= 13) + , dh-sequence-nodejs + , mocha + , node-anymatch (>= 3.0.3+~2.0.7-2~) + , node-async-each + , node-braces + , node-glob-parent + , node-inherits + , node-is-binary-path + , node-is-glob + , node-normalize-path + , node-path-is-absolute + , node-readdirp (>= 3.3.0) + , node-rimraf + , node-setimmediate + , node-sinon (>= 7) + , node-sinon-chai + , nodejs +Standards-Version: 4.6.0 Vcs-Browser: https://salsa.debian.org/js-team/node-chokidar Vcs-Git: https://salsa.debian.org/js-team/node-chokidar.git Homepage: https://github.com/paulmillr/chokidar @@ -31,18 +32,19 @@ Package: node-chokidar Architecture: all -Depends: ${misc:Depends}, - nodejs, - node-is-glob, - node-is-binary-path, - node-anymatch (>= 3.0.3+~2.0.7-2), - node-normalize-path, - node-readdirp (>= 3.3.0), - node-async-each, - node-braces, - node-path-is-absolute, - node-glob-parent, - node-inherits +Depends: + ${misc:Depends} + , node-anymatch (>= 3.0.3+~2.0.7-2) + , node-async-each + , node-braces + , node-glob-parent + , node-inherits + , node-is-binary-path + , node-is-glob + , node-normalize-path + , node-path-is-absolute + , node-readdirp (>= 3.3.0) + , nodejs Description: wrapper around watch / watchFile / fsevents Chokidar does still rely on the Node.js core fs module, but when using fs.watch and fs.watchFile for watching, it normalizes the events it receives, diff -Nru node-chokidar-3.4.3/debian/patches/disable-some-tests.diff node-chokidar-3.5.3/debian/patches/disable-some-tests.diff --- node-chokidar-3.4.3/debian/patches/disable-some-tests.diff 2020-10-28 20:20:25.000000000 +0000 +++ node-chokidar-3.5.3/debian/patches/disable-some-tests.diff 2022-05-12 04:13:18.000000000 +0000 @@ -1,8 +1,8 @@ Description: disable one test -Author: Xavier Guimard +Author: Yadd Bug-Debian: https://bugs.debian.org/973207 Forwarded: no -Last-Update: 2020-10-27 +Last-Update: 2022-05-12 --- a/test.js +++ b/test.js @@ -174,7 +174,7 @@ it('should emit `addDir` event when directory was added', async () => { const testDir = getFixturePath('subdir'); const spy = await aspy(watcher, 'addDir'); -@@ -1044,30 +890,6 @@ +@@ -1046,30 +892,6 @@ await waitFor([spy.withArgs(EV_UNLINK_DIR)]); spy.should.have.been.calledWith(EV_UNLINK_DIR, deepDir); }); @@ -205,7 +205,7 @@ }); describe('watch symlinks', () => { if (isWindows) return true; -@@ -1207,23 +1029,6 @@ +@@ -1226,23 +1048,6 @@ await waitFor([spy.withArgs(EV_CHANGE)]); spy.should.have.been.calledWith(EV_CHANGE, watchedPath); }); @@ -229,7 +229,7 @@ it('should emit ready event even when broken symlinks are encountered', async () => { const targetDir = getFixturePath('subdir/nonexistent'); await fs_mkdir(targetDir); -@@ -1984,31 +1789,6 @@ +@@ -2197,31 +2002,6 @@ })(); }); }); @@ -261,3 +261,12 @@ it('should not prevent the process from exiting', async () => { const scriptFile = getFixturePath('script.js'); const scriptContent = ` +@@ -2289,8 +2069,5 @@ + describe('fsevents (native extension)', runTests.bind(this, {useFsEvents: true})); + } + } +- if(!isIBMi) { +- describe('fs.watch (non-polling)', runTests.bind(this, {usePolling: false, useFsEvents: false})); +- } + describe('fs.watchFile (polling)', runTests.bind(this, {usePolling: true, interval: 10})); + }); diff -Nru node-chokidar-3.4.3/debian/patches/series node-chokidar-3.5.3/debian/patches/series --- node-chokidar-3.4.3/debian/patches/series 2020-11-12 10:19:04.000000000 +0000 +++ node-chokidar-3.5.3/debian/patches/series 2022-05-12 04:13:30.000000000 +0000 @@ -1,2 +1 @@ disable-some-tests.diff -workaround-upstream-test-failure.diff diff -Nru node-chokidar-3.4.3/debian/patches/workaround-upstream-test-failure.diff node-chokidar-3.5.3/debian/patches/workaround-upstream-test-failure.diff --- node-chokidar-3.4.3/debian/patches/workaround-upstream-test-failure.diff 2020-11-12 10:19:40.000000000 +0000 +++ node-chokidar-3.5.3/debian/patches/workaround-upstream-test-failure.diff 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -Description: disable one test that fails even with a `npm install` -Author: Xavier Guimard -Forwarded: no -Last-Update: 2020-11-12 - ---- a/test.js -+++ b/test.js -@@ -954,12 +954,6 @@ - await waitFor([spy.withArgs(EV_CHANGE)]); - spy.should.have.been.calledWith(EV_CHANGE, testFile); - }); -- it('should not recurse indefinitely on circular symlinks', async () => { -- await fs_symlink(currentDir, getFixturePath('subdir/circular')); -- const watcher = chokidar_watch(); -- await waitForWatcher(watcher); -- // return true; -- }); - it('should recognize changes following symlinked dirs', async () => { - const linkedFilePath = sysPath.join(linkedDir, 'change.txt'); - const watcher = chokidar_watch(linkedDir, options); diff -Nru node-chokidar-3.4.3/debian/upstream/metadata node-chokidar-3.5.3/debian/upstream/metadata --- node-chokidar-3.4.3/debian/upstream/metadata 2020-10-27 19:22:51.000000000 +0000 +++ node-chokidar-3.5.3/debian/upstream/metadata 2022-03-12 11:58:39.000000000 +0000 @@ -1,7 +1,6 @@ --- Archive: GitHub Bug-Database: https://github.com/paulmillr/chokidar/issues -Contact: https://github.com/paulmillr/chokidar/issues -Name: chokidar +Bug-Submit: https://github.com/paulmillr/chokidar/issues/new Repository: https://github.com/paulmillr/chokidar.git Repository-Browse: https://github.com/paulmillr/chokidar diff -Nru node-chokidar-3.4.3/debian/watch node-chokidar-3.5.3/debian/watch --- node-chokidar-3.4.3/debian/watch 2020-10-27 19:22:51.000000000 +0000 +++ node-chokidar-3.5.3/debian/watch 2022-03-12 12:13:30.000000000 +0000 @@ -2,8 +2,8 @@ opts=\ dversionmangle=s/\+(debian|dfsg|ds|deb)(\.\d+)?$//,\ filenamemangle=s/.*\/v?([\d\.-]+)\.tar\.gz/chokidar-$1.tar.gz/ \ - https://github.com/paulmillr/chokidar/tags .*/archive/v?([\d\.]+).tar.gz debian + https://github.com/paulmillr/chokidar/tags .*/archive/.*/v?([\d\.]+).tar.gz debian -opts="searchmode=plain,pgpmode=none,component=upath" \ +opts="searchmode=plain,pgpmode=none,ctype=nodejs,component=upath" \ https://registry.npmjs.org/upath \ https://registry.npmjs.org/upath/-/upath-(1.[\d\.]*)@ARCHIVE_EXT@ ignore diff -Nru node-chokidar-3.4.3/.eslintrc node-chokidar-3.5.3/.eslintrc --- node-chokidar-3.4.3/.eslintrc 1970-01-01 00:00:00.000000000 +0000 +++ node-chokidar-3.5.3/.eslintrc 2022-01-18 07:42:14.000000000 +0000 @@ -0,0 +1,50 @@ +{ + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 9, + "sourceType": "script" + }, + "env": { + "node": true, + "es6": true + }, + "rules": { + "array-callback-return": "error", + "no-empty": [ + "error", + { + "allowEmptyCatch": true + } + ], + "no-lonely-if": "error", + "no-var": "error", + "object-shorthand": "error", + "prefer-arrow-callback": [ + "error", + { + "allowNamedFunctions": true + } + ], + "prefer-const": [ + "error", + { + "ignoreReadBeforeAssign": true + } + ], + "prefer-destructuring": [ + "error", + { + "object": true, + "array": false + } + ], + "prefer-spread": "error", + "prefer-template": "error", + "radix": "error", + "strict": "error", + "quotes": [ + "error", + "single" + ] + } +} \ No newline at end of file diff -Nru node-chokidar-3.4.3/.github/dependabot.yml node-chokidar-3.5.3/.github/dependabot.yml --- node-chokidar-3.4.3/.github/dependabot.yml 1970-01-01 00:00:00.000000000 +0000 +++ node-chokidar-3.5.3/.github/dependabot.yml 2022-01-18 07:42:14.000000000 +0000 @@ -0,0 +1,13 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + time: "11:00" + open-pull-requests-limit: 10 + ignore: + - dependency-name: dtslint + - dependency-name: mocha + - dependency-name: "@types/node" + - dependency-name: sinon diff -Nru node-chokidar-3.4.3/.github/full_changelog.md node-chokidar-3.5.3/.github/full_changelog.md --- node-chokidar-3.4.3/.github/full_changelog.md 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/.github/full_changelog.md 2022-01-18 07:42:14.000000000 +0000 @@ -1,3 +1,10 @@ +### Chokidar 3.5.1 (Jan 15, 2021) +- Fixes for symbolic links + +### Chokidar 3.5.0 (Jan 6, 2021) +- Support for ARM Macs with Apple Silicon. +- Fixes missing removal of symlinks when the target path was deleted (#1042) + ### Chokidar 3.4.3 (Oct 13, 2020) * Circular symlinks that point to some parent directory are no longer watched. This prevents infinite loops. diff -Nru node-chokidar-3.4.3/.github/funding.yml node-chokidar-3.5.3/.github/funding.yml --- node-chokidar-3.4.3/.github/funding.yml 1970-01-01 00:00:00.000000000 +0000 +++ node-chokidar-3.5.3/.github/funding.yml 2022-01-18 07:42:14.000000000 +0000 @@ -0,0 +1 @@ +custom: https://paulmillr.com/funding/ \ No newline at end of file diff -Nru node-chokidar-3.4.3/.github/workflows/lint.yml node-chokidar-3.5.3/.github/workflows/lint.yml --- node-chokidar-3.4.3/.github/workflows/lint.yml 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/.github/workflows/lint.yml 2022-01-18 07:42:14.000000000 +0000 @@ -21,3 +21,6 @@ - name: Run lint run: npm run lint + + - name: Run dtslint + run: npm run dtslint diff -Nru node-chokidar-3.4.3/index.js node-chokidar-3.5.3/index.js --- node-chokidar-3.4.3/index.js 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/index.js 2022-01-18 07:42:14.000000000 +0000 @@ -48,7 +48,8 @@ EMPTY_FN, isWindows, - isMacos + isMacos, + isIBMi } = require('./lib/constants'); const stat = promisify(fs.stat); @@ -330,6 +331,11 @@ opts.usePolling = isMacos; } + // Always default to polling on IBM i because fs.watch() is not available on IBM i. + if(isIBMi) { + opts.usePolling = true; + } + // Global override (useful for end-developers that need to force polling for all // instances of chokidar, regardless of usage/dependency depth) const envPoll = process.env.CHOKIDAR_USEPOLLING; @@ -864,6 +870,15 @@ const wasTracked = parent.has(item); parent.remove(item); + // Fixes issue #1042 -> Relative paths were detected and added as symlinks + // (https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L612), + // but never removed from the map in case the path was deleted. + // This leads to an incorrect state if the path was recreated: + // https://github.com/paulmillr/chokidar/blob/e1753ddbc9571bdc33b4a4af172d52cb6e611c10/lib/nodefs-handler.js#L553 + if (this._symlinkPaths.has(fullPath)) { + this._symlinkPaths.delete(fullPath); + } + // If we wait for this file to be fully written, cancel the wait. let relPath = path; if (this.options.cwd) relPath = sysPath.relative(this.options.cwd, path); diff -Nru node-chokidar-3.4.3/lib/constants.js node-chokidar-3.5.3/lib/constants.js --- node-chokidar-3.4.3/lib/constants.js 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/lib/constants.js 2022-01-18 07:42:14.000000000 +0000 @@ -2,6 +2,7 @@ const {sep} = require('path'); const {platform} = process; +const os = require('os'); exports.EV_ALL = 'all'; exports.EV_READY = 'ready'; @@ -61,3 +62,4 @@ exports.isWindows = platform === 'win32'; exports.isMacos = platform === 'darwin'; exports.isLinux = platform === 'linux'; +exports.isIBMi = os.type() === 'OS400'; diff -Nru node-chokidar-3.4.3/lib/fsevents-handler.js node-chokidar-3.5.3/lib/fsevents-handler.js --- node-chokidar-3.4.3/lib/fsevents-handler.js 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/lib/fsevents-handler.js 2022-01-18 07:42:14.000000000 +0000 @@ -104,7 +104,8 @@ * @returns {Function} closer */ function setFSEventsListener(path, realPath, listener, rawEmitter) { - let watchPath = sysPath.extname(path) ? sysPath.dirname(path) : path; + let watchPath = sysPath.extname(realPath) ? sysPath.dirname(realPath) : realPath; + const parentPath = sysPath.dirname(watchPath); let cont = FSEventsWatchers.get(watchPath); @@ -299,8 +300,7 @@ * @returns {Function} closer for the watcher instance */ _watchWithFsEvents(watchPath, realPath, transform, globFilter) { - if (this.fsw.closed) return; - if (this.fsw._isIgnored(watchPath)) return; + if (this.fsw.closed || this.fsw._isIgnored(watchPath)) return; const opts = this.fsw.options; const watchCallback = async (fullPath, flags, info) => { if (this.fsw.closed) return; diff -Nru node-chokidar-3.4.3/lib/nodefs-handler.js node-chokidar-3.5.3/lib/nodefs-handler.js --- node-chokidar-3.4.3/lib/nodefs-handler.js 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/lib/nodefs-handler.js 2022-01-18 07:42:14.000000000 +0000 @@ -421,7 +421,15 @@ if (!this.fsw.options.followSymlinks) { // watch symlink directly (don't follow) and detect changes this.fsw._incrReadyCount(); - const linkPath = await fsrealpath(path); + + let linkPath; + try { + linkPath = await fsrealpath(path); + } catch (e) { + this.fsw._emitReady(); + return true; + } + if (this.fsw.closed) return; if (dir.has(item)) { if (this.fsw._symlinkPaths.get(full) !== linkPath) { @@ -603,13 +611,14 @@ const follow = this.fsw.options.followSymlinks && !path.includes(STAR) && !path.includes(BRACE_START); let closer; if (stats.isDirectory()) { + const absPath = sysPath.resolve(path); const targetPath = follow ? await fsrealpath(path) : path; if (this.fsw.closed) return; closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath); if (this.fsw.closed) return; // preserve this symlink's target path - if (path !== targetPath && targetPath !== undefined) { - this.fsw._symlinkPaths.set(targetPath, true); + if (absPath !== targetPath && targetPath !== undefined) { + this.fsw._symlinkPaths.set(absPath, targetPath); } } else if (stats.isSymbolicLink()) { const targetPath = follow ? await fsrealpath(path) : path; diff -Nru node-chokidar-3.4.3/package.json node-chokidar-3.5.3/package.json --- node-chokidar-3.4.3/package.json 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/package.json 2022-01-18 07:42:14.000000000 +0000 @@ -1,7 +1,7 @@ { "name": "chokidar", - "description": "A neat wrapper around node.js fs.watch / fs.watchFile / fsevents.", - "version": "3.4.3", + "description": "Minimal and efficient cross-platform file watching library", + "version": "3.5.3", "homepage": "https://github.com/paulmillr/chokidar", "author": "Paul Miller (https://paulmillr.com)", "contributors": [ @@ -13,20 +13,20 @@ }, "main": "index.js", "dependencies": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "glob-parent": "~5.1.0", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" + "readdirp": "~3.6.0" }, "optionalDependencies": { - "fsevents": "~2.1.2" + "fsevents": "~2.3.2" }, "devDependencies": { "@types/node": "^14", - "chai": "^4.2", + "chai": "^4.3", "dtslint": "^3.3.0", "eslint": "^7.0.0", "mocha": "^7.0.0", @@ -34,6 +34,7 @@ "rimraf": "^3.0.0", "sinon": "^9.0.1", "sinon-chai": "^3.3.0", + "typescript": "~4.4.3", "upath": "^1.2.0" }, "files": [ @@ -52,7 +53,7 @@ "scripts": { "dtslint": "dtslint types", "lint": "eslint --report-unused-disable-directives --ignore-path .gitignore .", - "mocha": "mocha --exit --timeout 60000", + "mocha": "mocha --exit --timeout 90000", "test": "npm run lint && npm run mocha" }, "keywords": [ @@ -65,56 +66,6 @@ "fsevents" ], "types": "./types/index.d.ts", - "eslintConfig": { - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 9, - "sourceType": "script" - }, - "env": { - "node": true, - "es6": true - }, - "rules": { - "array-callback-return": "error", - "no-empty": [ - "error", - { - "allowEmptyCatch": true - } - ], - "no-lonely-if": "error", - "no-var": "error", - "object-shorthand": "error", - "prefer-arrow-callback": [ - "error", - { - "allowNamedFunctions": true - } - ], - "prefer-const": [ - "error", - { - "ignoreReadBeforeAssign": true - } - ], - "prefer-destructuring": [ - "error", - { - "object": true, - "array": false - } - ], - "prefer-spread": "error", - "prefer-template": "error", - "radix": "error", - "strict": "error", - "quotes": [ - "error", - "single" - ] - } - }, "nyc": { "include": [ "index.js", @@ -124,5 +75,11 @@ "html", "text" ] - } + }, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] } diff -Nru node-chokidar-3.4.3/README.md node-chokidar-3.5.3/README.md --- node-chokidar-3.4.3/README.md 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/README.md 2022-01-18 07:42:14.000000000 +0000 @@ -1,11 +1,9 @@ # Chokidar [![Weekly downloads](https://img.shields.io/npm/dw/chokidar.svg)](https://github.com/paulmillr/chokidar) [![Yearly downloads](https://img.shields.io/npm/dy/chokidar.svg)](https://github.com/paulmillr/chokidar) -> A neat wrapper around Node.js fs.watch / fs.watchFile / FSEvents. +> Minimal and efficient cross-platform file watching library [![NPM](https://nodei.co/npm/chokidar.png)](https://www.npmjs.com/package/chokidar) -Version 3 is out! Check out our blog post about it: [Chokidar 3: How to save 32TB of traffic every week](https://paulmillr.com/posts/chokidar-3-save-32tb-of-traffic/) - ## Why? Node.js `fs.watch`: @@ -15,6 +13,7 @@ * Often reports events twice. * Emits most changes as `rename`. * Does not provide an easy way to recursively watch file trees. +* Does not support recursive watching on Linux. Node.js `fs.watchFile`: @@ -35,6 +34,8 @@ and [many others](https://www.npmjs.com/browse/depended/chokidar). It has proven itself in production environments. +Version 3 is out! Check out our blog post about it: [Chokidar 3: How to save 32TB of traffic every week](https://paulmillr.com/posts/chokidar-3-save-32tb-of-traffic/) + ## How? Chokidar does still rely on the Node.js core `fs` module, but when using @@ -46,7 +47,7 @@ implementations like `kqueue` available on most \*nix platforms. Chokidar still does have to do some work to normalize the events received that way as well. -On other platforms, the `fs.watch`-based implementation is the default, which +On most other platforms, the `fs.watch`-based implementation is the default, which avoids polling and keeps CPU usage down. Be advised that chokidar will initiate watchers recursively for everything within scope of the paths that have been specified, so be judicious about not wasting system resources by watching much @@ -74,7 +75,7 @@ ## API ```javascript -// Example of a more typical implementation structure: +// Example of a more typical implementation structure // Initialize watcher. const watcher = chokidar.watch('file, dir, glob, or array', { @@ -254,8 +255,8 @@ Additionally `all` is available which gets emitted with the underlying event name and path for every event other than `ready`, `raw`, and `error`. `raw` is internal, use it carefully. * `.unwatch(path / paths)`: Stop watching files, directories, or glob patterns. -Takes an array of strings or just one string. Use with `await` to ensure bugs don't happen. -* `.close()`: **async** Removes all listeners from watched files. Asynchronous, returns Promise. +Takes an array of strings or just one string. +* `.close()`: **async** Removes all listeners from watched files. Asynchronous, returns Promise. Use with `await` to ensure bugs don't happen. * `.getWatched()`: Returns an object representing all the paths on the file system being watched by this `FSWatcher` instance. The object's keys are all the directories (using absolute paths unless the `cwd` option was used), and the @@ -264,7 +265,7 @@ ## CLI If you need a CLI interface for your file watching, check out -[chokidar-cli](https://github.com/kimmobrunfeldt/chokidar-cli), allowing you to +[chokidar-cli](https://github.com/open-cli-tools/chokidar-cli), allowing you to execute a command on each change, or get a stdio stream of change events. ## Install Troubleshooting @@ -286,7 +287,8 @@ ## Changelog For more detailed changelog, see [`full_changelog.md`](.github/full_changelog.md). -- **v3.4 (Apr 26, 2020):** Support for directory-based symlinks. Macos file replacement fixes. +- **v3.5 (Jan 6, 2021):** Support for ARM Macs with Apple Silicon. Fixes for deleted symlinks. +- **v3.4 (Apr 26, 2020):** Support for directory-based symlinks. Fixes for macos file replacement. - **v3.3 (Nov 2, 2019):** `FSWatcher#close()` method became async. That fixes IO race conditions related to close method. - **v3.2 (Oct 1, 2019):** Improve Linux RAM usage by 50%. Race condition fixes. Windows glob fixes. Improve stability by using tight range of dependency versions. - **v3.1 (Sep 16, 2019):** dotfiles are no longer filtered out by default. Use `ignored` option if needed. Improve initial Linux scan time by 50%. diff -Nru node-chokidar-3.4.3/test.js node-chokidar-3.5.3/test.js --- node-chokidar-3.4.3/test.js 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/test.js 2022-01-18 07:42:14.000000000 +0000 @@ -12,7 +12,7 @@ const sinonChai = require('sinon-chai'); const upath = require('upath'); -const {isWindows, isMacos, EV_ALL, EV_READY, EV_ADD, EV_CHANGE, EV_ADD_DIR, EV_UNLINK, EV_UNLINK_DIR, EV_RAW, EV_ERROR} +const {isWindows, isMacos, isIBMi, EV_ALL, EV_READY, EV_ADD, EV_CHANGE, EV_ADD_DIR, EV_UNLINK, EV_UNLINK_DIR, EV_RAW, EV_ERROR} = require('./lib/constants'); const chokidar = require('.'); @@ -519,9 +519,10 @@ await delay(); await fs_rmdir(testPath); - await delay(); + await delay(300); await write(testPath, 'file content'); + await delay(300); await waitFor([unlinkSpy]); unlinkSpy.should.have.been.calledWith(testPath); await waitFor([addSpy]); @@ -610,12 +611,13 @@ await delay(); await write(safePath, dateNow()); await fs_rename(safePath, testPath); - await delay(100); + await delay(300); await write(safePath, dateNow()); await fs_rename(safePath, testPath); - await delay(100); + await delay(300); await write(safePath, dateNow()); await fs_rename(safePath, testPath); + await delay(300); await waitFor([spy]); spy.withArgs(EV_CHANGE, testPath).should.have.been.calledThrice; }); @@ -1134,9 +1136,11 @@ }); it('should not recurse indefinitely on circular symlinks', async () => { await fs_symlink(currentDir, getFixturePath('subdir/circular')); - const watcher = chokidar_watch(); - await waitForWatcher(watcher); - // return true; + return new Promise((resolve, reject) => { + const watcher = chokidar_watch(); + watcher.on(EV_ERROR, resolve()); + watcher.on(EV_READY, reject('The watcher becomes ready, although he watches a circular symlink.')); + }) }); it('should recognize changes following symlinked dirs', async () => { const linkedFilePath = sysPath.join(linkedDir, 'change.txt'); @@ -1168,19 +1172,34 @@ spy.should.have.been.calledWith(EV_ADD, linkedDir); spy.should.have.been.calledOnce; }); + it('should survive ENOENT for missing symlinks when followSymlinks:false', async () => { + options.followSymlinks = false; + const targetDir = getFixturePath('subdir/nonexistent'); + await fs_mkdir(targetDir); + await fs_symlink(targetDir, getFixturePath('subdir/broken')); + await fs_rmdir(targetDir); + + const watcher = chokidar_watch(getFixturePath('subdir'), options); + const spy = await aspy(watcher, EV_ALL); + + spy.should.have.been.calledTwice; + spy.should.have.been.calledWith(EV_ADD_DIR, getFixturePath('subdir')); + spy.should.have.been.calledWith(EV_ADD, getFixturePath('subdir/add.txt')); + }); it('should watch symlinks within a watched dir as files when followSymlinks:false', async () => { options.followSymlinks = false; // Create symlink in linkPath const linkPath = getFixturePath('link'); fs.symlinkSync(getFixturePath('subdir'), linkPath); const spy = await aspy(chokidar_watch(), EV_ALL); - await delay(); + await delay(300); setTimeout(() => { fs.writeFileSync(getFixturePath('subdir/add.txt'), dateNow()); fs.unlinkSync(linkPath); fs.symlinkSync(getFixturePath('subdir/add.txt'), linkPath); }, options.usePolling ? 1200 : 300); + await delay(300); await waitFor([spy.withArgs(EV_CHANGE, linkPath)]); spy.should.not.have.been.calledWith(EV_ADD_DIR, linkPath); spy.should.not.have.been.calledWith(EV_ADD, getFixturePath('link/add.txt')); @@ -1963,74 +1982,6 @@ if (!macosFswatch) spy.should.have.been.calledOnce; }); }); - describe('close', () => { - it('should ignore further events on close', async () => { - return new Promise((resolve) => { - const spy = sinon.spy(); - const watcher = chokidar_watch(currentDir, options); - watcher.once(EV_ADD, () => { - watcher.once(EV_ADD, async () => { - await watcher.on(EV_ADD, spy).close(); - await delay(900); - await write(getFixturePath('add.txt'), dateNow()); - spy.should.not.have.been.called; - resolve(); - }); - }); - (async () => { - await waitForWatcher(watcher); - await write(getFixturePath('add.txt'), 'hello'); - await fs_unlink(getFixturePath('add.txt')); - })(); - }); - }); - it('should not ignore further events on close with existing watchers', async () => { - return new Promise((resolve) => { - const watcher1 = chokidar_watch(currentDir); - const watcher2 = chokidar_watch(currentDir); - // The EV_ADD event should be called on the second watcher even if the first watcher is closed - watcher2.on(EV_ADD, () => { - watcher2.on(EV_ADD, (path) => { - if (path.endsWith('add.txt')) { - resolve(); - } - }) - }); - (async () => { - await waitForWatcher(watcher1); - await waitForWatcher(watcher2); - // Watcher 1 is closed to ensure events only happen on watcher 2 - await watcher1.close(); - // Write a new file into the fixtures to test the EV_ADD event - await write(getFixturePath('add.txt'), 'hello'); - // Ensures EV_ADD is called. Immediately removing the file causes it to be skipped - await delay(200); - await fs_unlink(getFixturePath('add.txt')); - })() - }) - }); - it('should not prevent the process from exiting', async () => { - const scriptFile = getFixturePath('script.js'); - const scriptContent = ` - const chokidar = require("${__dirname.replace(/\\/g, '\\\\')}"); - const watcher = chokidar.watch("${scriptFile.replace(/\\/g, '\\\\')}"); - watcher.on("ready", () => { - watcher.close(); - process.stdout.write("closed"); - });`; - await write(scriptFile, scriptContent); - const obj = await exec(`node ${scriptFile}`); - const {stdout} = obj; - expect(stdout.toString()).to.equal('closed'); - }); - it('should always return the same promise', async () => { - const watcher = chokidar_watch(currentDir, options); - const closePromise = watcher.close(); - expect(closePromise).to.be.a('promise'); - expect(watcher.close()).to.be.equal(closePromise); - await closePromise; - }); - }); describe('env variable option override', () => { beforeEach(() => { // Do not spin up @@ -2044,7 +1995,6 @@ it('should make options.usePolling `true` when CHOKIDAR_USEPOLLING is set to true', async () => { options.usePolling = false; process.env.CHOKIDAR_USEPOLLING = 'true'; - const watcher = chokidar_watch(currentDir, options); await waitForWatcher(watcher); watcher.options.usePolling.should.be.true; @@ -2102,6 +2052,198 @@ }); } }); + describe('reproduction of bug in issue #1040', () => { + it('should detect change on symlink folders when consolidateThreshhold is reach', async () => { + const id = subdirId.toString(); + + const fixturesPathRel = sysPath.join(FIXTURES_PATH_REL, id, 'test-case-1040'); + const linkPath = sysPath.join(fixturesPathRel, 'symlinkFolder'); + await fs_mkdir(sysPath.resolve(linkPath), { recursive: true }); + + // Init chokidar + const watcher = chokidar.watch([]); + const events = []; + + // Add more than 10 folders to cap consolidateThreshhold + for (let i = 0 ; i < 20 ; i += 1) { + const folderPath = sysPath.join(fixturesPathRel, 'packages', `folder${i}`); + await fs_mkdir(sysPath.resolve(folderPath), { recursive: true }); + const filePath = sysPath.join(folderPath, `file${i}.js`); + await write(sysPath.resolve(filePath), 'file content'); + const symlinkPath = sysPath.join(linkPath, `folder${i}`); + await fs_symlink(sysPath.resolve(folderPath), symlinkPath); + watcher.add(sysPath.resolve(sysPath.join(symlinkPath, `file${i}.js`))); + } + + // Wait to be sure that we have no other event than the update file + await delay(300); + watcher.on('change', (event, path) => + events.push(`[change] ${event}: ${path}`) + ); + + // Update a random generated file to fire an event + const randomFilePath = sysPath.join(fixturesPathRel, 'packages', 'folder17', 'file17.js'); + await write(sysPath.resolve(randomFilePath), 'file content changer zeri ezhriez'); + + // Wait chokidar watch + await delay(300); + + expect(events.length).to.equal(1); + }) + }); + describe('reproduction of bug in issue #1024', () => { + it('should detect changes to folders, even if they were deleted before', async () => { + const id = subdirId.toString(); + const relativeWatcherDir = sysPath.join(FIXTURES_PATH_REL, id, 'test'); + const watcher = chokidar.watch(relativeWatcherDir, { + persistent: true, + }); + try { + const events = []; + watcher.on('all', (event, path) => + events.push(`[ALL] ${event}: ${path}`) + ); + const testSubDir = sysPath.join(relativeWatcherDir, 'dir'); + const testSubDirFile = sysPath.join(relativeWatcherDir, 'dir', 'file'); + + // Command sequence from https://github.com/paulmillr/chokidar/issues/1042. + await delay(); + await fs_mkdir(relativeWatcherDir); + await fs_mkdir(testSubDir); + // The following delay is essential otherwise the call of mkdir and rmdir will be equalize + await delay(300); + await fs_rmdir(testSubDir); + // The following delay is essential otherwise the call of rmdir and mkdir will be equalize + await delay(300); + await fs_mkdir(testSubDir); + await delay(300); + await write(testSubDirFile, ''); + await delay(300); + + chai.assert.deepStrictEqual(events, [ + `[ALL] addDir: ${sysPath.join('test-fixtures', id, 'test')}`, + `[ALL] addDir: ${sysPath.join('test-fixtures', id, 'test', 'dir')}`, + `[ALL] unlinkDir: ${sysPath.join('test-fixtures', id, 'test', 'dir')}`, + `[ALL] addDir: ${sysPath.join('test-fixtures', id, 'test', 'dir')}`, + `[ALL] add: ${sysPath.join('test-fixtures', id, 'test', 'dir', 'file')}`, + ]); + } finally { + watcher.close(); + } + }); + + it('should detect changes to symlink folders, even if they were deleted before', async () => { + const id = subdirId.toString(); + const relativeWatcherDir = sysPath.join(FIXTURES_PATH_REL, id, 'test'); + const linkedRelativeWatcherDir = sysPath.join(FIXTURES_PATH_REL, id, 'test-link'); + await fs_symlink(sysPath.resolve(relativeWatcherDir), linkedRelativeWatcherDir); + const watcher = chokidar.watch(linkedRelativeWatcherDir, { + persistent: true, + }); + try { + const events = []; + watcher.on('all', (event, path) => + events.push(`[ALL] ${event}: ${path}`) + ); + const testSubDir = sysPath.join(relativeWatcherDir, 'dir'); + const testSubDirFile = sysPath.join(relativeWatcherDir, 'dir', 'file'); + + // Command sequence from https://github.com/paulmillr/chokidar/issues/1042. + await delay(); + await fs_mkdir(relativeWatcherDir); + await fs_mkdir(testSubDir); + // The following delay is essential otherwise the call of mkdir and rmdir will be equalize + await delay(300); + await fs_rmdir(testSubDir); + // The following delay is essential otherwise the call of rmdir and mkdir will be equalize + await delay(300); + await fs_mkdir(testSubDir); + await write(testSubDirFile, ''); + await delay(300); + + chai.assert.deepStrictEqual(events, [ + `[ALL] addDir: ${sysPath.join('test-fixtures', id, 'test-link')}`, + `[ALL] addDir: ${sysPath.join('test-fixtures', id, 'test-link', 'dir')}`, + `[ALL] unlinkDir: ${sysPath.join('test-fixtures', id, 'test-link', 'dir')}`, + `[ALL] addDir: ${sysPath.join('test-fixtures', id, 'test-link', 'dir')}`, + `[ALL] add: ${sysPath.join('test-fixtures', id, 'test-link', 'dir', 'file')}`, + ]); + } finally { + watcher.close(); + } + }); + }); + + describe('close', () => { + it('should ignore further events on close', async () => { + return new Promise((resolve) => { + const spy = sinon.spy(); + const watcher = chokidar_watch(currentDir, options); + watcher.once(EV_ADD, () => { + watcher.once(EV_ADD, async () => { + await watcher.on(EV_ADD, spy).close(); + await delay(900); + await write(getFixturePath('add.txt'), dateNow()); + spy.should.not.have.been.called; + resolve(); + }); + }); + (async () => { + await waitForWatcher(watcher); + await delay(300); + await write(getFixturePath('add.txt'), 'hello'); + await delay(300); + await fs_unlink(getFixturePath('add.txt')); + })(); + }); + }); + it('should not ignore further events on close with existing watchers', async () => { + return new Promise((resolve) => { + const watcher1 = chokidar_watch(currentDir); + const watcher2 = chokidar_watch(currentDir); + // The EV_ADD event should be called on the second watcher even if the first watcher is closed + watcher2.on(EV_ADD, () => { + watcher2.on(EV_ADD, (path) => { + if (path.endsWith('add.txt')) { + resolve(); + } + }) + }); + (async () => { + await waitForWatcher(watcher1); + await waitForWatcher(watcher2); + // Watcher 1 is closed to ensure events only happen on watcher 2 + await watcher1.close(); + // Write a new file into the fixtures to test the EV_ADD event + await write(getFixturePath('add.txt'), 'hello'); + // Ensures EV_ADD is called. Immediately removing the file causes it to be skipped + await delay(200); + await fs_unlink(getFixturePath('add.txt')); + })() + }) + }); + it('should not prevent the process from exiting', async () => { + const scriptFile = getFixturePath('script.js'); + const scriptContent = ` + const chokidar = require("${__dirname.replace(/\\/g, '\\\\')}"); + const watcher = chokidar.watch("${scriptFile.replace(/\\/g, '\\\\')}"); + watcher.on("ready", () => { + watcher.close(); + process.stdout.write("closed"); + });`; + await write(scriptFile, scriptContent); + const obj = await exec(`node ${scriptFile}`); + const {stdout} = obj; + expect(stdout.toString()).to.equal('closed'); + }); + it('should always return the same promise', async () => { + const watcher = chokidar_watch(currentDir, options); + const closePromise = watcher.close(); + expect(closePromise).to.be.a('promise'); + expect(watcher.close()).to.be.equal(closePromise); + await closePromise; + }); + }); }; describe('chokidar', () => { @@ -2147,6 +2289,8 @@ describe('fsevents (native extension)', runTests.bind(this, {useFsEvents: true})); } } - describe('fs.watch (non-polling)', runTests.bind(this, {usePolling: false, useFsEvents: false})); + if(!isIBMi) { + describe('fs.watch (non-polling)', runTests.bind(this, {usePolling: false, useFsEvents: false})); + } describe('fs.watchFile (polling)', runTests.bind(this, {usePolling: true, interval: 10})); }); diff -Nru node-chokidar-3.4.3/types/index.d.ts node-chokidar-3.5.3/types/index.d.ts --- node-chokidar-3.4.3/types/index.d.ts 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/types/index.d.ts 2022-01-18 07:42:14.000000000 +0000 @@ -4,6 +4,7 @@ import * as fs from "fs"; import { EventEmitter } from "events"; +import { Matcher } from 'anymatch'; export class FSWatcher extends EventEmitter implements fs.FSWatcher { options: WatchOptions; @@ -17,13 +18,13 @@ * Add files, directories, or glob patterns for tracking. Takes an array of strings or just one * string. */ - add(paths: string | ReadonlyArray): void; + add(paths: string | ReadonlyArray): this; /** * Stop watching files, directories, or glob patterns. Takes an array of strings or just one * string. */ - unwatch(paths: string | ReadonlyArray): void; + unwatch(paths: string | ReadonlyArray): this; /** * Returns an object representing all the paths on the file system being watched by this @@ -79,7 +80,7 @@ * (the path), second time with two arguments (the path and the * [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) object of that path). */ - ignored?: any; + ignored?: Matcher; /** * If set to `false` then `add`/`addDir` events are also emitted for matching paths while diff -Nru node-chokidar-3.4.3/types/test.ts node-chokidar-3.5.3/types/test.ts --- node-chokidar-3.4.3/types/test.ts 2020-10-13 11:04:48.000000000 +0000 +++ node-chokidar-3.5.3/types/test.ts 2022-01-18 07:42:14.000000000 +0000 @@ -9,6 +9,8 @@ const log = console.log.bind(console); watcher + .add('./foo.js') + .unwatch('./bar.js') .on("add", (path: string) => { log("File", path, "has been added"); }) @@ -50,7 +52,9 @@ watcher.unwatch("new-file*"); // Only needed if watching is `persistent: true`. -watcher.close(); +(async () => { + await watcher.close(); +})(); // One-liner chokidar