@atom/watcher
Advanced tools
Comparing version 1.2.1 to 1.3.0-0
@@ -0,3 +1,4 @@ | ||
const logger = require('./logger') | ||
let watcher = null | ||
function getWatcher () { | ||
@@ -47,2 +48,28 @@ if (!watcher) { | ||
function jsLogOption (value) { | ||
if (value === undefined) return | ||
if (value === DISABLE) { | ||
logger.disable() | ||
return | ||
} | ||
if (value === STDERR) { | ||
logger.toStderr() | ||
return | ||
} | ||
if (value === STDOUT) { | ||
logger.toStdout() | ||
return | ||
} | ||
if (typeof value === 'string' || value instanceof String) { | ||
logger.toFile(value) | ||
return | ||
} | ||
throw new Error('option jsLog must be DISABLE, STDERR, STDOUT, or a filename') | ||
} | ||
function configure (options) { | ||
@@ -58,2 +85,3 @@ if (!options) { | ||
logOption('pollingLog', options, normalized) | ||
jsLogOption(options.jsLog) | ||
@@ -60,0 +88,0 @@ if (options.workerCacheSize) normalized.workerCacheSize = options.workerCacheSize |
const path = require('path') | ||
const { log } = require('./logger') | ||
const { Tree } = require('./registry/tree') | ||
@@ -31,8 +32,11 @@ | ||
async attach (watcher) { | ||
log('attaching watcher %s to native registry.', watcher) | ||
const normalizedDirectory = await watcher.getNormalizedPathPromise() | ||
const pathSegments = normalizedDirectory.split(path.sep).filter(segment => segment.length > 0) | ||
log('adding watcher %s to tree.', watcher) | ||
this.tree.add(pathSegments, watcher.getOptions(), (native, nativePath, options) => { | ||
watcher.attachToNative(native, nativePath, options) | ||
}) | ||
log('watcher %s added. tree state:\n%s', watcher, this.print()) | ||
} | ||
@@ -39,0 +43,0 @@ |
const binding = require('./binding') | ||
const { Emitter, CompositeDisposable, Disposable } = require('event-kit') | ||
const { log } = require('./logger') | ||
@@ -40,2 +41,4 @@ const ACTIONS = new Map([ | ||
this.onError = this.onError.bind(this) | ||
log('create NativeWatcher %s with options %j.', this, this.options) | ||
} | ||
@@ -48,2 +51,3 @@ | ||
if (this.state === STARTING) { | ||
log('NativeWatcher %s is already starting.', this) | ||
await new Promise(resolve => this.emitter.once('did-start', resolve)) | ||
@@ -54,5 +58,7 @@ return | ||
if (this.state === RUNNING || this.state === STOPPING) { | ||
log('NativeWatcher %s is running or stopping.', this) | ||
return | ||
} | ||
log('Starting NativeWatcher %s.', this) | ||
this.state = STARTING | ||
@@ -70,2 +76,3 @@ | ||
}) | ||
log('NativeWatcher %s assigned channel %d.', this, this.channel) | ||
@@ -105,2 +112,3 @@ this.state = RUNNING | ||
if (this.emitter.listenerCountForEventName('did-change') === 0) { | ||
log('Last subscriber disposed on NativeWatcher %s.', this) | ||
this.stop() | ||
@@ -157,2 +165,3 @@ } | ||
if (this.state === STOPPING) { | ||
log('NativeWatcher %s is already stopping.', this) | ||
await new Promise(resolve => this.emitter.once('did-stop', resolve)) | ||
@@ -163,2 +172,3 @@ return | ||
if (this.state === STARTING) { | ||
log('NativeWatcher %s is still starting.', this) | ||
await new Promise(resolve => this.emitter.once('did-start', resolve)) | ||
@@ -168,2 +178,3 @@ } | ||
if (this.state === STOPPED) { | ||
log('NativeWatcher %s has already stopped.', this) | ||
return | ||
@@ -176,2 +187,3 @@ } | ||
log('Stopping NativeWatcher %s with split %s.', this, split) | ||
this.state = STOPPING | ||
@@ -185,2 +197,3 @@ this.emitter.emit('will-stop', split) | ||
this.state = STOPPED | ||
log('NativeWatcher %s has been stopped.', this) | ||
@@ -187,0 +200,0 @@ this.emitter.emit('did-stop') |
@@ -5,2 +5,3 @@ const fs = require('fs-extra') | ||
const { Emitter, CompositeDisposable, Disposable } = require('event-kit') | ||
const { log } = require('./logger') | ||
@@ -64,2 +65,3 @@ // Extended: Manage a subscription to filesystem events that occur beneath a root directory. Construct these by | ||
this.options = Object.assign({ recursive: true, include: () => true }, options) | ||
log('create PathWatcher at %s with options %j.', watchedPath, options) | ||
@@ -86,2 +88,3 @@ this.normalizedPath = null | ||
]).then(([real, stat]) => { | ||
log('normalized and stat path %s to %s.', watchedPath, real) | ||
if (stat.isDirectory()) { | ||
@@ -163,4 +166,6 @@ this.normalizedPath = real | ||
} else { | ||
log('attaching watcher %s to registry because a change listener has been attached.', this) | ||
// Attach to a new native listener and retry | ||
this.nativeWatcherRegistry.attach(this).then(() => { | ||
log('watcher %s attached successfully.', this) | ||
this.onDidChange(callback) | ||
@@ -174,2 +179,3 @@ }, err => this.rejectAttachedPromise(err)) | ||
sub.dispose() | ||
log('disposed subscription from watcher %s.', this) | ||
}) | ||
@@ -192,7 +198,11 @@ } | ||
this.native = native | ||
log('attaching watcher %s to native %s.', this, native) | ||
if (native.isRunning()) { | ||
log('native %s is already running.', native) | ||
this.resolveStartPromise() | ||
} else { | ||
log('waiting for native %s to start.', native) | ||
this.subs.add(native.onDidStart(() => { | ||
log('native %s has started.') | ||
this.resolveStartPromise() | ||
@@ -205,2 +215,3 @@ })) | ||
if (this.native === native) { | ||
log('transferring %d existing event subscriptions to new native %s.', this.changeCallbacks.size, native) | ||
for (const [callback, formerSub] of this.changeCallbacks) { | ||
@@ -223,2 +234,4 @@ const newSub = native.onDidChange(events => this.onNativeEvents(events, callback)) | ||
if (!options.recursive && this.normalizedPath !== watchedPath) return | ||
log('received detachment request from native %s. replacement is at path %s with options %j.', | ||
native, watchedPath, options) | ||
@@ -230,2 +243,3 @@ this.attachToNative(replacement) | ||
if (this.native === native) { | ||
log('native %s is stopping.', native) | ||
this.subs.dispose() | ||
@@ -236,2 +250,3 @@ this.native = null | ||
log('watcher %s attached successfully to native %s.', this, native) | ||
this.resolveAttachedPromise() | ||
@@ -302,2 +317,3 @@ } | ||
this.subs.dispose() | ||
log('watcher %s disposed.', this) | ||
} | ||
@@ -304,0 +320,0 @@ |
@@ -6,2 +6,3 @@ const { absolute } = require('./helper') | ||
const { NonrecursiveWatcherNode } = require('./nonrecursive-watcher-node') | ||
const { log } = require('../logger') | ||
@@ -41,2 +42,3 @@ // Private: Map userland filesystem watcher subscriptions efficiently to deliver filesystem change notifications to | ||
const absolutePath = absolute(...absolutePathSegments) | ||
log('Tree: adding %j with options %j. absolute = %s.', pathSegments, options, absolutePath) | ||
@@ -62,2 +64,4 @@ const attachToNew = (children, immediate) => { | ||
parent: (parent, remaining) => { | ||
log('Tree: discovered parent node with remaining segments %j.', remaining) | ||
// An existing NativeWatcher is watching the same directory or a parent directory of the requested path. | ||
@@ -68,2 +72,4 @@ const existingNative = parent.getNativeWatcher() | ||
if (parent.isCompatible(options)) { | ||
log('Tree: adding child path and attaching to existing native %s.', existingNative) | ||
// Attach this Watcher to it as a filtering watcher and record it as a dependent child path. | ||
@@ -73,2 +79,4 @@ parent.addChildPath(remaining, options) | ||
} else { | ||
log('Tree: broadening existing native watcher %s.', existingNative) | ||
// Construct and attach a new {NativeWatcher} that will deliver events suitable for both the old and | ||
@@ -82,2 +90,4 @@ // new watchers. Reattach consumers of the existing {NativeWatcher} and stop it. | ||
children: (children, immediate) => { | ||
log('Tree: discovered watched children %j.', children) | ||
// One or more NativeWatchers exist on child directories of the requested path. Create a new native watcher | ||
@@ -88,2 +98,3 @@ // on the parent directory. | ||
if (options.recursive) { | ||
log('Tree: adopting %d existing children.', children.length) | ||
// Create a new native watcher on the parent directory, note the subscribed child paths, and cleanly stop the | ||
@@ -100,3 +111,6 @@ // child native watchers. | ||
}, | ||
missing: () => attachToNew([], {}) | ||
missing: () => { | ||
log('Tree: creating and attaching new native watcher.') | ||
attachToNew([], {}) | ||
} | ||
}) | ||
@@ -103,0 +117,0 @@ } |
{ | ||
"name": "@atom/watcher", | ||
"version": "1.2.1", | ||
"version": "1.3.0-0", | ||
"description": "Atom filesystem watcher", | ||
@@ -18,3 +18,3 @@ "main": "lib/index.js", | ||
"build:debug": "node --harmony script/helper/gen-compilation-db.js rebuild --debug", | ||
"build:atom": "electron-rebuild --version 1.7.11", | ||
"build:atom": "electron-rebuild --version 2.0.16", | ||
"test": "mocha", | ||
@@ -46,23 +46,23 @@ "test:lldb": "lldb -- node --harmony ./node_modules/.bin/_mocha --require test/global.js --require mocha-stress --recursive", | ||
"devDependencies": { | ||
"chai": "4.1.2", | ||
"chai": "4.2.0", | ||
"chai-as-promised": "7.1.1", | ||
"electron-rebuild": "1.8.2", | ||
"eslint-plugin-import": "2.13.0", | ||
"eslint-plugin-import": "2.14.0", | ||
"eslint-plugin-promise": "4.0.1", | ||
"eslint-plugin-react": "7.11.1", | ||
"eslint-plugin-react": "7.12.3", | ||
"mocha": "5.2.0", | ||
"mocha-appveyor-reporter": "0.4.1", | ||
"mocha-appveyor-reporter": "0.4.2", | ||
"mocha-junit-reporter": "1.18.0", | ||
"mocha-stress": "1.0.0", | ||
"prebuild": "8.1.1", | ||
"prebuild": "8.1.2", | ||
"shell-quote": "1.6.1", | ||
"standard": "12.0.1", | ||
"temp": "0.8.3", | ||
"temp": "0.9.0", | ||
"test-until": "1.1.1" | ||
}, | ||
"dependencies": { | ||
"event-kit": "^2.5.0", | ||
"fs-extra": "^7.0.0", | ||
"nan": "^2.10.0", | ||
"prebuild-install": "^5.2.1" | ||
"event-kit": "2.5.3", | ||
"fs-extra": "7.0.1", | ||
"nan": "2.12.1", | ||
"prebuild-install": "5.2.2" | ||
}, | ||
@@ -69,0 +69,0 @@ "standard": { |
@@ -69,2 +69,3 @@ # Atom Filesystem Watcher | ||
await watcher.configure({ | ||
jsLog: watcher.STDOUT, | ||
mainLog: watcher.STDERR, | ||
@@ -79,3 +80,3 @@ workerLog: 'worker.log', | ||
`mainLog` configures the logging of events from the main thread, in line with libuv's event loop. It may be one of: | ||
`jsLog` configures the logging of events from the JavaScript layer. It may be one of: | ||
@@ -86,6 +87,8 @@ * A `String` specifying a path to log to a file. Be careful that you don't log to a directory that you're watching :innocent: | ||
`workerLog` configures logging for the worker thread, which is used to interact with native operating system filesystem watching APIs. It accepts the same arguments as `mainLog` and also defaults to `watcher.DISABLE`. | ||
`mainLog` configures the logging of events from the main thread, in line with libuv's event loop. It accepts the same arguments as `jsLog` and also defaults to `watcher.DISABLE`. | ||
`pollingLog` configures logging for the polling thread, which polls the filesystem when the worker thread is unable to. The polling thread only launches when at least one path needs to be polled. `pollingLog` accepts the same arguments as `mainLog` and also defaults to `watcher.DISABLE`. | ||
`workerLog` configures logging for the worker thread, which is used to interact with native operating system filesystem watching APIs. It accepts the same arguments as `jsLog` and also defaults to `watcher.DISABLE`. | ||
`pollingLog` configures logging for the polling thread, which polls the filesystem when the worker thread is unable to. The polling thread only launches when at least one path needs to be polled. `pollingLog` accepts the same arguments as `jsLog` and also defaults to `watcher.DISABLE`. | ||
`workerCacheSize` controls the number of recently seen stat results are cached within the worker thread. Increasing the cache size will improve the reliability of rename correlation and the entry kinds of deleted entries, but will consume more RAM. The default is `4096`. | ||
@@ -159,2 +162,11 @@ | ||
### Environment variables | ||
Logging may also be configured by setting environment variables. Each of these may be set to an empty string to disable that log, `"stderr"` to output to stderr, `"stdout"` to output to stdout, or a path to write output to a file at that path. | ||
* `WATCHER_LOG_JS`: JavaScript layer logging | ||
* `WATCHER_LOG_MAIN`: Main thread logging | ||
* `WATCHER_LOG_WORKER`: Worker thread logging | ||
* `WATCHER_LOG_POLLING`: Polling thread logging | ||
## CLI | ||
@@ -161,0 +173,0 @@ |
@@ -32,9 +32,2 @@ /* eslint-dev mocha */ | ||
it('configures the worker thread logger', async function () { | ||
await configure({ workerLog: fixture.workerLogFile }) | ||
const contents = await fs.readFile(fixture.workerLogFile) | ||
assert.match(contents, /FileLogger opened/) | ||
}) | ||
it('fails if the main log file cannot be written', async function () { | ||
@@ -44,4 +37,21 @@ await assert.isRejected(configure({ mainLog: badPath }), /No such file or directory/) | ||
it('fails if the worker log file cannot be written', async function () { | ||
await assert.isRejected(configure({ workerLog: badPath }), /No such file or directory/) | ||
describe('for the worker thread', function () { | ||
// There's currently no way to *stop* the worker thread, so we can't reliably test it in the stopped state. | ||
describe("after it's started", function () { | ||
it('configures the logger', async function () { | ||
await fixture.watch([], { poll: false }, () => {}) | ||
await configure({ workerLog: fixture.workerLogFile }) | ||
const contents = await fs.readFile(fixture.workerLogFile) | ||
assert.match(contents, /FileLogger opened/) | ||
}) | ||
it('fails if the worker log file cannot be written', async function () { | ||
await fixture.watch([], { poll: false }, () => {}) | ||
await assert.isRejected(configure({ workerLog: badPath }), /No such file or directory/) | ||
}) | ||
}) | ||
}) | ||
@@ -48,0 +58,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
451265
139
3356
184
2
22
+ Addedbl@1.2.3(transitive)
+ Addedbuffer-alloc@1.2.0(transitive)
+ Addedbuffer-alloc-unsafe@1.1.0(transitive)
+ Addedbuffer-fill@1.0.0(transitive)
+ Addeddecompress-response@3.3.0(transitive)
+ Addedmimic-response@1.0.1(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addednan@2.12.1(transitive)
+ Addedos-homedir@1.0.2(transitive)
+ Addedprebuild-install@5.2.2(transitive)
+ Addedpump@1.0.32.0.1(transitive)
+ Addedsimple-get@2.8.2(transitive)
+ Addedtar-fs@1.16.4(transitive)
+ Addedtar-stream@1.6.2(transitive)
+ Addedto-buffer@1.1.1(transitive)
+ Addedxtend@4.0.2(transitive)
- Removedbase64-js@1.5.1(transitive)
- Removedbl@4.1.0(transitive)
- Removedbuffer@5.7.1(transitive)
- Removeddecompress-response@4.2.1(transitive)
- Removedieee754@1.2.1(transitive)
- Removedmimic-response@2.1.0(transitive)
- Removedmkdirp-classic@0.5.3(transitive)
- Removednan@2.22.0(transitive)
- Removedprebuild-install@5.3.6(transitive)
- Removedpump@3.0.2(transitive)
- Removedreadable-stream@3.6.2(transitive)
- Removedsimple-get@3.1.1(transitive)
- Removedtar-fs@2.1.2(transitive)
- Removedtar-stream@2.2.0(transitive)
Updatedevent-kit@2.5.3
Updatedfs-extra@7.0.1
Updatednan@2.12.1
Updatedprebuild-install@5.2.2