0.6.2 ingore .goutputstream files during atomic writes

master
Kebler Network System Administrator 2022-01-17 19:31:45 -08:00
parent f903ef7071
commit 1563a8ffa2
5 changed files with 44 additions and 9 deletions

0
.npmignore Normal file → Executable file
View File

View File

@ -1,7 +1,7 @@
import Watcher from '../src/watcher.js' import Watcher from '../src/watcher.js'
import onDeath from 'ondeath' import onDeath from 'ondeath'
const USE_CUSTOM_HANDLER = true const USE_CUSTOM_HANDLER = false
const DEBOUNCE = 0 const DEBOUNCE = 0
const READY_TIMEOUT = null const READY_TIMEOUT = null
@ -11,6 +11,7 @@ const READY_TIMEOUT = null
source: './example/repo/**', source: './example/repo/**',
ignored: ['**/dontwatch.js'], ignored: ['**/dontwatch.js'],
ignoreList: ['./example/repo/.gitignore'], ignoreList: ['./example/repo/.gitignore'],
// ignore_goutputstream: false,
debounce: DEBOUNCE, debounce: DEBOUNCE,
readyTimeout: READY_TIMEOUT readyTimeout: READY_TIMEOUT
} }

4
package.json Normal file → Executable file
View File

@ -1,6 +1,6 @@
{ {
"name": "@uci-utils/watcher", "name": "@uci-utils/watcher",
"version": "0.6.1", "version": "0.6.2",
"description": "File System Watcher Class that emits events", "description": "File System Watcher Class that emits events",
"main": "src/watcher.js", "main": "src/watcher.js",
"type": "module", "type": "module",
@ -30,7 +30,7 @@
}, },
"homepage": "https://github.com/uCOMmandIt/uci-utils#readme", "homepage": "https://github.com/uCOMmandIt/uci-utils#readme",
"dependencies": { "dependencies": {
"@uci-utils/logger": "0.1.0", "@uci-utils/logger": "^0.2.0",
"@uci-utils/read-lines": "^0.3.0", "@uci-utils/read-lines": "^0.3.0",
"chokidar": "^3.5.1", "chokidar": "^3.5.1",
"debounce-fn": "^5.0.0" "debounce-fn": "^5.0.0"

View File

@ -27,7 +27,7 @@ opts = {
} }
``` ```
**plus any options supported by chokidar** **plus any options supported by chokidar**
[chokidar options](https://github.com/paulmillr/chokidar#persistence) [chokidar options](https://github.com/paulmillr/chokidar)
## API ## API
@ -78,3 +78,33 @@ function _handler (type, f) {
#### custom #### custom
one can use a custom handler by passing such a function in options or using registerHandler. The handler is passed two arguments the type of the change and the file changed. one can use a custom handler by passing such a function in options or using registerHandler. The handler is passed two arguments the type of the change and the file changed.
#### atomic issues
Several type of editors write atomically. They typically write a `.gpoutputstream` file temporily that "trick" choikdar. So by default this watcher ignores these files. Can you included them by passing false for `ignore_gpoutputstream`. If you still don't get a modified event using these apps (e.g. gedit) you might look at the `atomic` option and if all else fails `usePolling`
#### Chokidar Options
chokidar.watch('file', {
persistent: true,
ignored: '*.txt',
ignoreInitial: false,
followSymlinks: true,
cwd: '.',
disableGlobbing: false,
usePolling: false,
interval: 100,
binaryInterval: 300,
alwaysStat: false,
depth: 99,
awaitWriteFinish: {
stabilityThreshold: 2000,
pollInterval: 100
},
ignorePermissionErrors: false,
atomic: true // or a custom 'atomicity delay', in milliseconds (default 100)
});
details here
https://github.com/paulmillr/chokidar#api

14
src/watcher.js Normal file → Executable file
View File

@ -23,6 +23,8 @@ class Watcher extends Emitter {
this.handler = opts.handler || _handler this.handler = opts.handler || _handler
this._ready = false this._ready = false
this._watching = false this._watching = false
// .goutputstream files arise during atomic writes, ignore them by default
this.ignore_goutputstream = opts.ignore_goutputstream === false ? false : true
return this return this
} }
@ -55,6 +57,7 @@ class Watcher extends Emitter {
if (opts.delDir) this._watcher.on('unlinkDir', handler.bind(this, 'dir-deleted')) if (opts.delDir) this._watcher.on('unlinkDir', handler.bind(this, 'dir-deleted'))
if (opts.addDir) this._watcher.on('addDir', handler.bind(this, 'dir-added')) if (opts.addDir) this._watcher.on('addDir', handler.bind(this, 'dir-added'))
// these are watched by default, one can take action or not in the handler
this._watcher this._watcher
.on('add', handler.bind(this, 'added')) .on('add', handler.bind(this, 'added'))
.on('change', handler.bind(this, 'modified')) .on('change', handler.bind(this, 'modified'))
@ -79,8 +82,8 @@ class Watcher extends Emitter {
log.trace({ watching: this._watcher.getWatched(), msg: 'initial files watched' }) log.trace({ watching: this._watcher.getWatched(), msg: 'initial files watched' })
log.info(`now watching ${opts.source || this.opts.source}`) log.info(`now watching ${opts.source || this.opts.source}`)
if (this.registerHandler(opts)) { if (this.registerHandler(opts)) {
log.fatal('watcher was not initialzed so could not register handler') log.fatal('watcher was not initialized so could not register handler')
return new Error('watcher was not initialzed so could not register handler') return new Error('watcher was not initialized so could not register handler')
} }
this._watching = true this._watching = true
this.emit('watching', true, opts) this.emit('watching', true, opts)
@ -122,7 +125,7 @@ class Watcher extends Emitter {
} }
// private methods // private methods
// set up chokidar
async _init(opts = {}) { async _init(opts = {}) {
if (!opts.overwrite) { if (!opts.overwrite) {
await this._fetchIgnoreLists(this.opts.excludeFrom) await this._fetchIgnoreLists(this.opts.excludeFrom)
@ -133,9 +136,10 @@ class Watcher extends Emitter {
if (!opts.ignored) opts.ignored = [] if (!opts.ignored) opts.ignored = []
opts.ignored = Array.isArray(opts.ignored) ? opts.ignored : opts.ignored.split(',') opts.ignored = Array.isArray(opts.ignored) ? opts.ignored : opts.ignored.split(',')
opts.ignored = opts.overwrite ? opts.ignored : [...this._ignored, ...opts.ignored] opts.ignored = opts.overwrite ? opts.ignored : [...this._ignored, ...opts.ignored]
opts = Object.assign({}, this.opts, opts) // now that ingnore arrays are dealt with merge options if (this.ignore_goutputstream) opts.ignored.push('**/.goutputstream*')
opts = Object.assign({}, this.opts, opts) // now that ignore arrays are dealt with merge options
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
log.debug({ options: opts, msg: 'intializing watch with options' }) log.debug({ options: opts, msg: 'initializing watch with options' })
if (opts.source) { if (opts.source) {
// create chokidar watcher // create chokidar watcher
this._watcher = watch(opts.source, opts) this._watcher = watch(opts.source, opts)