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 onDeath from 'ondeath'
const USE_CUSTOM_HANDLER = true
const USE_CUSTOM_HANDLER = false
const DEBOUNCE = 0
const READY_TIMEOUT = null
@ -11,6 +11,7 @@ const READY_TIMEOUT = null
source: './example/repo/**',
ignored: ['**/dontwatch.js'],
ignoreList: ['./example/repo/.gitignore'],
// ignore_goutputstream: false,
debounce: DEBOUNCE,
readyTimeout: READY_TIMEOUT
}

4
package.json Normal file → Executable file
View File

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

View File

@ -27,7 +27,7 @@ opts = {
}
```
**plus any options supported by chokidar**
[chokidar options](https://github.com/paulmillr/chokidar#persistence)
[chokidar options](https://github.com/paulmillr/chokidar)
## API
@ -78,3 +78,33 @@ function _handler (type, f) {
#### 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.
#### 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._ready = 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
}
@ -55,6 +57,7 @@ class Watcher extends Emitter {
if (opts.delDir) this._watcher.on('unlinkDir', handler.bind(this, 'dir-deleted'))
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
.on('add', handler.bind(this, 'added'))
.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.info(`now watching ${opts.source || this.opts.source}`)
if (this.registerHandler(opts)) {
log.fatal('watcher was not initialzed so could not register handler')
return new Error('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 initialized so could not register handler')
}
this._watching = true
this.emit('watching', true, opts)
@ -122,7 +125,7 @@ class Watcher extends Emitter {
}
// private methods
// set up chokidar
async _init(opts = {}) {
if (!opts.overwrite) {
await this._fetchIgnoreLists(this.opts.excludeFrom)
@ -133,9 +136,10 @@ class Watcher extends Emitter {
if (!opts.ignored) opts.ignored = []
opts.ignored = Array.isArray(opts.ignored) ? opts.ignored : opts.ignored.split(',')
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) => {
log.debug({ options: opts, msg: 'intializing watch with options' })
log.debug({ options: opts, msg: 'initializing watch with options' })
if (opts.source) {
// create chokidar watcher
this._watcher = watch(opts.source, opts)