Skip to content

Commit

Permalink
Revert "A better workaround for atomic writes (#791)"
Browse files Browse the repository at this point in the history
This reverts commit 8f56261.
  • Loading branch information
paulmillr committed Mar 22, 2019
1 parent fc243cd commit b79120b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 22 deletions.
10 changes: 7 additions & 3 deletions README.md
Expand Up @@ -134,7 +134,7 @@ chokidar.watch('file', {
},

ignorePermissionErrors: false,
atomic: true
atomic: true // or a custom 'atomicity delay', in milliseconds (default 100)
});

```
Expand Down Expand Up @@ -223,8 +223,12 @@ Use with caution.
that don't have read permissions if possible. If watching fails due to `EPERM`
or `EACCES` with this set to `true`, the errors will be suppressed silently.
* `atomic` (default: `true` if `useFsEvents` and `usePolling` are `false`).
Uses a workaround to handle file changes by editors that use
"atomic writes" instead of writing directly to the source file.
Automatically filters out artifacts that occur when using editors that use
"atomic writes" instead of writing directly to the source file. If a file is
re-added within 100 ms of being deleted, Chokidar emits a `change` event
rather than `unlink` then `add`. If the default of 100 ms does not work well
for you, you can override it by setting `atomic` to a custom value, in
milliseconds.

### Methods & Events

Expand Down
42 changes: 23 additions & 19 deletions index.js
Expand Up @@ -113,8 +113,9 @@ function FSWatcher(_opts) {
opts.interval = parseInt(envInterval);
}

// Editor atomic write handling enabled by default with fs.watch
// Editor atomic write normalization enabled by default with fs.watch
if (undef('atomic')) opts.atomic = !opts.usePolling && !opts.useFsEvents;
if (opts.atomic) this._pendingUnlinks = Object.create(null);

if (undef('followSymlinks')) opts.followSymlinks = true;

Expand Down Expand Up @@ -175,6 +176,25 @@ FSWatcher.prototype._emit = function(event, path, val1, val2, val3) {
return this;
}

if (this.options.atomic) {
if (event === 'unlink') {
this._pendingUnlinks[path] = args;
setTimeout(function() {
Object.keys(this._pendingUnlinks).forEach(function(path) {
this.emit.apply(this, this._pendingUnlinks[path]);
this.emit.apply(this, ['all'].concat(this._pendingUnlinks[path]));
delete this._pendingUnlinks[path];
}.bind(this));
}.bind(this), typeof this.options.atomic === "number"
? this.options.atomic
: 100);
return this;
} else if (event === 'add' && this._pendingUnlinks[path]) {
event = args[0] = 'change';
delete this._pendingUnlinks[path];
}
}

var emitEvent = function() {
this.emit.apply(this, args);
if (event !== 'error') this.emit.apply(this, ['all'].concat(args));
Expand Down Expand Up @@ -335,6 +355,8 @@ FSWatcher.prototype._awaitWriteFinish = function(path, threshold, event, awfEmit
// Returns boolean
var dotRe = /\..*\.(sw[px])$|\~$|\.subl.*\.tmp/;
FSWatcher.prototype._isIgnored = function(path, stats) {
if (this.options.atomic && dotRe.test(path)) return true;

if (!this._userIgnored) {
var cwd = this.options.cwd;
var ignored = this.options.ignored;
Expand Down Expand Up @@ -598,24 +620,6 @@ FSWatcher.prototype.add = function(paths, _origAdd, _internal) {
}
});

if (this.options.atomic) {
paths = paths.map(function(path) {
// If `path` is already a glob, we do not have to do anything.
if (isGlob(path)) {
return path;
}
else {
var splits = path.split(sysPath.sep);
if (splits.length && splits[splits.length - 1]) {
// We make the last segment of the path a glob pattern.
// This type of a glob pattern is equivalent to the original name.
splits[splits.length - 1] = '@(' + splits[splits.length - 1] + ')';
}
return splits.join(sysPath.sep);
}
});
}

// set aside negated glob strings
paths = paths.filter(function(path) {
if (path[0] === '!') {
Expand Down

0 comments on commit b79120b

Please sign in to comment.