fsevents 2.0.2-pre-1 → 2.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +67 -0
- package/fsevents.js +17 -15
- package/fsevents.node +0 -0
- package/package.json +6 -7
- package/ISSUE_TEMPLATE.md +0 -8
- package/Readme.md +0 -80
- package/binding.gyp +0 -23
- package/src/constants.h +0 -112
- package/src/fsevents.c +0 -145
- package/src/rawfsevents.c +0 -149
- package/src/rawfsevents.h +0 -23
- package/test/01_native.js +0 -34
- package/test/02_interleaved.js +0 -40
- package/test/02_structure.js +0 -30
- package/test/03_simple.js +0 -61
- package/test/03_waiting.js +0 -28
- package/test/utils/fs.js +0 -97
- package/test/utils/misc.js +0 -26
- package/test.sh +0 -29
package/LICENSE
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
MIT License
|
2
2
|
-----------
|
3
3
|
|
4
|
-
Copyright (C) 2010-
|
4
|
+
Copyright (C) 2010-2019 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
|
5
5
|
|
6
6
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
7
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# fsevents [](https://nodei.co/npm/fsevents/)
|
2
|
+
|
3
|
+
Native access to MacOS FSEvents in [Node.js](https://nodejs.org/)
|
4
|
+
|
5
|
+
The FSEvents API in MacOS allows applications to register for notifications of
|
6
|
+
changes to a given directory tree. It is a very fast and lightweight alternative
|
7
|
+
to kqueue.
|
8
|
+
|
9
|
+
This is a low-level library. For a cross-platform file watching module that
|
10
|
+
uses fsevents, check out [Chokidar](https://github.com/paulmillr/chokidar).
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
```sh
|
15
|
+
npm install fsevents
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
```js
|
21
|
+
const fsevents = require('fsevents');
|
22
|
+
const stop = fsevents.watch(__dirname, (path, flags, id) => {
|
23
|
+
const info = fsevents.getInfo(path, flags, id);
|
24
|
+
}); // To start observation
|
25
|
+
stop(); // To end observation
|
26
|
+
```
|
27
|
+
|
28
|
+
The callback passed as the second parameter to `.watch` get's called whenever the operating system detects a
|
29
|
+
a change in the file system. It takes three arguments:
|
30
|
+
|
31
|
+
`(path: String, flags: Number, id: String) => {}`
|
32
|
+
|
33
|
+
* `path` - the item in the filesystem that have been changed
|
34
|
+
* `flags` - a numeric value describing what the change was
|
35
|
+
* `id` - an unique-id identifying this specific event
|
36
|
+
|
37
|
+
###### `fsevents.getInfo(path, flags, id): FsEventInfo => {}`
|
38
|
+
|
39
|
+
The `getInfo` function takes the `path`, `flags` and `id` arguments and converts those parameters into a structure
|
40
|
+
that is easier to digest to determine what the change was.
|
41
|
+
|
42
|
+
The `FsEventsInfo` has the following shape:
|
43
|
+
|
44
|
+
```js
|
45
|
+
/**
|
46
|
+
* @typedef {'created'|'modified'|'deleted'|'moved'|'root-changed'|'unknown'} FsEventsEvent
|
47
|
+
* @typedef {'file'|'directory'|'symlink'} FsEventsType
|
48
|
+
*/
|
49
|
+
{
|
50
|
+
"event": "created",
|
51
|
+
"path": "file.txt", // {FsEventsEvent}
|
52
|
+
"type": "file", // {FsEventsType}
|
53
|
+
"changes": {
|
54
|
+
"inode": true, // Had iNode Meta-Information changed
|
55
|
+
"finder": false, // Had Finder Meta-Data changed
|
56
|
+
"access": false, // Had access permissions changed
|
57
|
+
"xattrs": false // Had xAttributes changed
|
58
|
+
},
|
59
|
+
"flags": 0x100000000
|
60
|
+
}
|
61
|
+
```
|
62
|
+
|
63
|
+
## License
|
64
|
+
|
65
|
+
The MIT License Copyright (C) 2010-2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar — see LICENSE file.
|
66
|
+
|
67
|
+
Visit our [GitHub page](https://github.com/fsevents/fsevents) and [NPM Page](https://npmjs.org/package/fsevents)
|
package/fsevents.js
CHANGED
@@ -11,14 +11,15 @@ if (process.platform !== 'darwin') {
|
|
11
11
|
}
|
12
12
|
|
13
13
|
const Native = require('./fsevents.node');
|
14
|
+
const con = Native.constants;
|
14
15
|
|
15
16
|
function watch(path, handler) {
|
16
17
|
if ('string' !== typeof path) throw new TypeError(`argument 1 must be a string and not a ${typeof path}`);
|
17
18
|
if ('function' !== typeof handler) throw new TypeError(`argument 2 must be a function and not a ${typeof handler}`);
|
18
19
|
|
19
|
-
|
20
20
|
let instance = Native.start(path, handler);
|
21
|
-
|
21
|
+
if (!instance) throw new Error(`could not watch: ${path}`);
|
22
|
+
return () => {
|
22
23
|
const result = instance ? Promise.resolve(instance).then(Native.stop) : null;
|
23
24
|
instance = null;
|
24
25
|
return result;
|
@@ -32,29 +33,30 @@ function getInfo(path, flags) {
|
|
32
33
|
changes: getFileChanges(flags)
|
33
34
|
};
|
34
35
|
}
|
36
|
+
|
35
37
|
function getFileType(flags) {
|
36
|
-
if (
|
37
|
-
if (
|
38
|
-
if (
|
38
|
+
if (con.kFSEventStreamEventFlagItemIsFile & flags) return 'file';
|
39
|
+
if (con.kFSEventStreamEventFlagItemIsDir & flags) return 'directory';
|
40
|
+
if (con.kFSEventStreamEventFlagItemIsSymlink & flags) return 'symlink';
|
39
41
|
}
|
40
42
|
function getEventType(flags) {
|
41
|
-
if (
|
42
|
-
if (
|
43
|
-
if (
|
44
|
-
if (
|
45
|
-
if (
|
43
|
+
if (con.kFSEventStreamEventFlagItemRemoved & flags) return 'deleted';
|
44
|
+
if (con.kFSEventStreamEventFlagItemRenamed & flags) return 'moved';
|
45
|
+
if (con.kFSEventStreamEventFlagItemCreated & flags) return 'created';
|
46
|
+
if (con.kFSEventStreamEventFlagItemModified & flags) return 'modified';
|
47
|
+
if (con.kFSEventStreamEventFlagRootChanged & flags) return 'root-changed';
|
46
48
|
|
47
49
|
return 'unknown';
|
48
50
|
}
|
49
51
|
function getFileChanges(flags) {
|
50
52
|
return {
|
51
|
-
inode: !!(
|
52
|
-
finder: !!(
|
53
|
-
access: !!(
|
54
|
-
xattrs: !!(
|
53
|
+
inode: !!(con.kFSEventStreamEventFlagItemInodeMetaMod & flags),
|
54
|
+
finder: !!(con.kFSEventStreamEventFlagItemFinderInfoMod & flags),
|
55
|
+
access: !!(con.kFSEventStreamEventFlagItemChangeOwner & flags),
|
56
|
+
xattrs: !!(con.kFSEventStreamEventFlagItemXattrMod & flags)
|
55
57
|
};
|
56
58
|
}
|
57
59
|
|
58
60
|
exports.watch = watch;
|
59
61
|
exports.getInfo = getInfo;
|
60
|
-
exports.constants =
|
62
|
+
exports.constants = con;
|
package/fsevents.node
CHANGED
Binary file
|
package/package.json
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
{
|
2
2
|
"name": "fsevents",
|
3
|
-
"version": "2.0.
|
3
|
+
"version": "2.0.6",
|
4
4
|
"description": "Native Access to Mac OS-X FSEvents",
|
5
5
|
"main": "fsevents.js",
|
6
6
|
"os": [
|
7
7
|
"darwin"
|
8
8
|
],
|
9
9
|
"engines": {
|
10
|
-
"node": "^10.6.0 || >=11.0.0"
|
10
|
+
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
11
11
|
},
|
12
12
|
"scripts": {
|
13
13
|
"clean": "node-gyp clean && rm -f fsevents.node",
|
14
|
-
"install": "[ -f fsevents.node ] || npm run prepare",
|
15
14
|
"test": "/bin/bash ./test.sh 2>/dev/null",
|
16
|
-
"
|
15
|
+
"prepublishOnly": "node-gyp clean && rm -f fsevents.node && node-gyp rebuild && node-gyp clean"
|
17
16
|
},
|
18
17
|
"repository": {
|
19
18
|
"type": "git",
|
20
|
-
"url": "https://github.com/
|
19
|
+
"url": "https://github.com/fsevents/fsevents.git"
|
21
20
|
},
|
22
21
|
"keywords": [
|
23
22
|
"fsevents",
|
@@ -43,8 +42,8 @@
|
|
43
42
|
],
|
44
43
|
"license": "MIT",
|
45
44
|
"bugs": {
|
46
|
-
"url": "https://github.com/
|
45
|
+
"url": "https://github.com/fsevents/fsevents/issues"
|
47
46
|
},
|
48
|
-
"homepage": "https://github.com/
|
47
|
+
"homepage": "https://github.com/fsevents/fsevents",
|
49
48
|
"devDependencies": {}
|
50
49
|
}
|
package/ISSUE_TEMPLATE.md
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
If you are NOT on OS X and have come here to file an issue about compatibility problems,
|
2
|
-
please stop and go to #115 for your answer.
|
3
|
-
|
4
|
-
You can look through many other similar closed issues as well if you're interested:
|
5
|
-
https://github.com/strongloop/fsevents/search?utf8=%E2%9C%93&q=%22notsup%22+OR+%22EBADPLATFORM%22&type=Issues.
|
6
|
-
|
7
|
-
If you are here to report an issue observed while using this module on OS X, please delete
|
8
|
-
all this pre-filled text then go ahead and submit your report.
|
package/Readme.md
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
# fsevents [](https://nodei.co/npm/fsevents/)
|
2
|
-
|
3
|
-
Native access to OS X FSEvents in [Node.js](http://nodejs.org/)
|
4
|
-
|
5
|
-
The FSEvents API in OS X allows applications to register for notifications of
|
6
|
-
changes to a given directory tree. It is a very fast and lightweight alternative
|
7
|
-
to kqueue.
|
8
|
-
|
9
|
-
This is a low-level library. For a cross-compatible file watching module that
|
10
|
-
uses fsevents, check out [Chokidar](https://www.npmjs.com/package/chokidar).
|
11
|
-
|
12
|
-
* [Module Site & GitHub](https://github.com/strongloop/fsevents)
|
13
|
-
* [NPM Page](https://npmjs.org/package/fsevents)
|
14
|
-
|
15
|
-
## Installation
|
16
|
-
|
17
|
-
$ npm install fsevents
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
```js
|
22
|
-
const fsevents = require('fsevents');
|
23
|
-
let stop = fsevents.watch(__dirname, (path, flags, id)=>{
|
24
|
-
const info = fsevents.getInfo(path, flags, id);
|
25
|
-
}); // To start observation
|
26
|
-
stop(); // To end observation
|
27
|
-
```
|
28
|
-
|
29
|
-
### Callback
|
30
|
-
|
31
|
-
The callback passed as the second parameter to `.watch` get's called whenever the operating system detects a
|
32
|
-
a change in the file system. It takes three arguments:
|
33
|
-
|
34
|
-
* `path` - which is a string naming the path of the item in the filesystem that changed
|
35
|
-
* `flags` - a numeric value describing what the change was
|
36
|
-
* `id` - a unique-id identifying this specific event
|
37
|
-
|
38
|
-
### `getInfo(path, flags, id) => {info-object}`
|
39
|
-
|
40
|
-
The `getInfo` function takes the `path`, `flags` and `id` arguments and converts those parameters into a structure
|
41
|
-
that is easier to digest to determine what the change was.
|
42
|
-
|
43
|
-
The `info-object` has the following shape:
|
44
|
-
|
45
|
-
```js
|
46
|
-
{
|
47
|
-
"event": "<deleted|moved|created|modified|root-changed|unknown>",
|
48
|
-
"path": "<path-that-this-is-about>",
|
49
|
-
"type": "<file|directory|symlink>",
|
50
|
-
"changes": {
|
51
|
-
"inode": true, // Has the iNode Meta-Information changed
|
52
|
-
"finder": false, // Has the Finder Meta-Data changed
|
53
|
-
"access": false, // Have the access permissions changed
|
54
|
-
"xattrs": false // Have the xAttributes changed
|
55
|
-
},
|
56
|
-
"flags": <raw-flags>
|
57
|
-
}
|
58
|
-
```
|
59
|
-
|
60
|
-
## MIT License
|
61
|
-
|
62
|
-
Copyright (C) 2010-2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
|
63
|
-
|
64
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
65
|
-
of this software and associated documentation files (the "Software"), to deal
|
66
|
-
in the Software without restriction, including without limitation the rights
|
67
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
68
|
-
copies of the Software, and to permit persons to whom the Software is
|
69
|
-
furnished to do so, subject to the following conditions:
|
70
|
-
|
71
|
-
The above copyright notice and this permission notice shall be included in
|
72
|
-
all copies or substantial portions of the Software.
|
73
|
-
|
74
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
75
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
76
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
77
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
78
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
79
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
80
|
-
THE SOFTWARE.
|
package/binding.gyp
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"conditions": [
|
3
|
-
['OS=="mac"', {
|
4
|
-
"targets": [{
|
5
|
-
"target_name": "fsevents",
|
6
|
-
"sources": [ "src/fsevents.c", "src/rawfsevents.c" ],
|
7
|
-
"xcode_settings": {
|
8
|
-
"OTHER_LDFLAGS": [
|
9
|
-
"-framework CoreFoundation -framework CoreServices"
|
10
|
-
]
|
11
|
-
}
|
12
|
-
}, {
|
13
|
-
"target_name": "action_after_build",
|
14
|
-
"type": "none",
|
15
|
-
"dependencies": ["fsevents"],
|
16
|
-
"copies": [{
|
17
|
-
"files": ["<(PRODUCT_DIR)/fsevents.node"],
|
18
|
-
"destination": "./"
|
19
|
-
}]
|
20
|
-
}]
|
21
|
-
}]
|
22
|
-
]
|
23
|
-
}
|
package/src/constants.h
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
#ifndef __constants_h
|
2
|
-
#define __constants_h
|
3
|
-
|
4
|
-
#include "CoreFoundation/CoreFoundation.h"
|
5
|
-
|
6
|
-
// constants from https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/index.html#//apple_ref/doc/constant_group/FSEventStreamEventFlags
|
7
|
-
#ifndef kFSEventStreamEventFlagNone
|
8
|
-
#define kFSEventStreamEventFlagNone 0x00000000
|
9
|
-
#endif
|
10
|
-
|
11
|
-
#ifndef kFSEventStreamEventFlagMustScanSubDirs
|
12
|
-
#define kFSEventStreamEventFlagMustScanSubDirs 0x00000001
|
13
|
-
#endif
|
14
|
-
|
15
|
-
#ifndef kFSEventStreamEventFlagUserDropped
|
16
|
-
#define kFSEventStreamEventFlagUserDropped 0x00000002
|
17
|
-
#endif
|
18
|
-
|
19
|
-
#ifndef kFSEventStreamEventFlagKernelDropped
|
20
|
-
#define kFSEventStreamEventFlagKernelDropped 0x00000004
|
21
|
-
#endif
|
22
|
-
|
23
|
-
#ifndef kFSEventStreamEventFlagEventIdsWrapped
|
24
|
-
#define kFSEventStreamEventFlagEventIdsWrapped 0x00000008
|
25
|
-
#endif
|
26
|
-
|
27
|
-
#ifndef kFSEventStreamEventFlagHistoryDone
|
28
|
-
#define kFSEventStreamEventFlagHistoryDone 0x00000010
|
29
|
-
#endif
|
30
|
-
|
31
|
-
#ifndef kFSEventStreamEventFlagRootChanged
|
32
|
-
#define kFSEventStreamEventFlagRootChanged 0x00000020
|
33
|
-
#endif
|
34
|
-
|
35
|
-
#ifndef kFSEventStreamEventFlagMount
|
36
|
-
#define kFSEventStreamEventFlagMount 0x00000040
|
37
|
-
#endif
|
38
|
-
|
39
|
-
#ifndef kFSEventStreamEventFlagUnmount
|
40
|
-
#define kFSEventStreamEventFlagUnmount 0x00000080
|
41
|
-
#endif
|
42
|
-
|
43
|
-
#ifndef kFSEventStreamEventFlagItemCreated
|
44
|
-
#define kFSEventStreamEventFlagItemCreated 0x00000100
|
45
|
-
#endif
|
46
|
-
|
47
|
-
#ifndef kFSEventStreamEventFlagItemRemoved
|
48
|
-
#define kFSEventStreamEventFlagItemRemoved 0x00000200
|
49
|
-
#endif
|
50
|
-
|
51
|
-
#ifndef kFSEventStreamEventFlagItemInodeMetaMod
|
52
|
-
#define kFSEventStreamEventFlagItemInodeMetaMod 0x00000400
|
53
|
-
#endif
|
54
|
-
|
55
|
-
#ifndef kFSEventStreamEventFlagItemRenamed
|
56
|
-
#define kFSEventStreamEventFlagItemRenamed 0x00000800
|
57
|
-
#endif
|
58
|
-
|
59
|
-
#ifndef kFSEventStreamEventFlagItemModified
|
60
|
-
#define kFSEventStreamEventFlagItemModified 0x00001000
|
61
|
-
#endif
|
62
|
-
|
63
|
-
#ifndef kFSEventStreamEventFlagItemFinderInfoMod
|
64
|
-
#define kFSEventStreamEventFlagItemFinderInfoMod 0x00002000
|
65
|
-
#endif
|
66
|
-
|
67
|
-
#ifndef kFSEventStreamEventFlagItemChangeOwner
|
68
|
-
#define kFSEventStreamEventFlagItemChangeOwner 0x00004000
|
69
|
-
#endif
|
70
|
-
|
71
|
-
#ifndef kFSEventStreamEventFlagItemXattrMod
|
72
|
-
#define kFSEventStreamEventFlagItemXattrMod 0x00008000
|
73
|
-
#endif
|
74
|
-
|
75
|
-
#ifndef kFSEventStreamEventFlagItemIsFile
|
76
|
-
#define kFSEventStreamEventFlagItemIsFile 0x00010000
|
77
|
-
#endif
|
78
|
-
|
79
|
-
#ifndef kFSEventStreamEventFlagItemIsDir
|
80
|
-
#define kFSEventStreamEventFlagItemIsDir 0x00020000
|
81
|
-
#endif
|
82
|
-
|
83
|
-
#ifndef kFSEventStreamEventFlagItemIsSymlink
|
84
|
-
#define kFSEventStreamEventFlagItemIsSymlink 0x00040000
|
85
|
-
#endif
|
86
|
-
|
87
|
-
// constants from https://developer.apple.com/library/mac/documentation/Darwin/Reference/FSEvents_Ref/index.html#//apple_ref/doc/constant_group/FSEventStreamCreateFlags
|
88
|
-
#ifndef kFSEventStreamCreateFlagNone
|
89
|
-
#define kFSEventStreamCreateFlagNone 0x00000000
|
90
|
-
#endif
|
91
|
-
|
92
|
-
#ifndef kFSEventStreamCreateFlagUseCFTypes
|
93
|
-
#define kFSEventStreamCreateFlagUseCFTypes 0x00000001
|
94
|
-
#endif
|
95
|
-
|
96
|
-
#ifndef kFSEventStreamCreateFlagNoDefer
|
97
|
-
#define kFSEventStreamCreateFlagNoDefer 0x00000002
|
98
|
-
#endif
|
99
|
-
|
100
|
-
#ifndef kFSEventStreamCreateFlagWatchRoot
|
101
|
-
#define kFSEventStreamCreateFlagWatchRoot 0x00000004
|
102
|
-
#endif
|
103
|
-
|
104
|
-
#ifndef kFSEventStreamCreateFlagIgnoreSelf
|
105
|
-
#define kFSEventStreamCreateFlagIgnoreSelf 0x00000008
|
106
|
-
#endif
|
107
|
-
|
108
|
-
#ifndef kFSEventStreamCreateFlagFileEvents
|
109
|
-
#define kFSEventStreamCreateFlagFileEvents 0x00000010
|
110
|
-
#endif
|
111
|
-
|
112
|
-
#endif
|
package/src/fsevents.c
DELETED
@@ -1,145 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
|
3
|
-
** Licensed under MIT License.
|
4
|
-
*/
|
5
|
-
|
6
|
-
#include <assert.h>
|
7
|
-
#define NAPI_VERSION 3
|
8
|
-
#define NAPI_EXPERIMENTAL
|
9
|
-
#include <node_api.h>
|
10
|
-
|
11
|
-
#include "rawfsevents.h"
|
12
|
-
#include "constants.h"
|
13
|
-
|
14
|
-
#ifndef CHECK
|
15
|
-
#ifdef NDEBUG
|
16
|
-
#define CHECK(x) do { if (!(x)) abort(); } while (0)
|
17
|
-
#else
|
18
|
-
#define CHECK assert
|
19
|
-
#endif
|
20
|
-
#endif
|
21
|
-
|
22
|
-
|
23
|
-
typedef struct {
|
24
|
-
size_t count;
|
25
|
-
fse_event_t *events;
|
26
|
-
} fse_js_event;
|
27
|
-
|
28
|
-
void fse_propagate_event(void *callback, size_t numevents, fse_event_t *events) {
|
29
|
-
fse_js_event *event = malloc(sizeof(*event));
|
30
|
-
CHECK(event);
|
31
|
-
event->count = numevents;
|
32
|
-
event->events = events;
|
33
|
-
CHECK(napi_call_threadsafe_function((napi_threadsafe_function)callback, event, napi_tsfn_blocking) == napi_ok);
|
34
|
-
}
|
35
|
-
|
36
|
-
void fse_dispatch_events(napi_env env, napi_value callback, void* context, void* data) {
|
37
|
-
fse_js_event *event = data;
|
38
|
-
napi_value recv, args[3];
|
39
|
-
size_t idx;
|
40
|
-
CHECK(napi_get_null(env, &recv) == napi_ok);
|
41
|
-
|
42
|
-
for (idx = 0; idx < event->count; idx++) {
|
43
|
-
CHECK(napi_create_string_utf8(env, event->events[idx].path, NAPI_AUTO_LENGTH, &args[0]) == napi_ok);
|
44
|
-
CHECK(napi_create_uint32(env, event->events[idx].flags, &args[1]) == napi_ok);
|
45
|
-
CHECK(napi_create_int64(env, event->events[idx].id, &args[2]) == napi_ok);
|
46
|
-
CHECK(napi_call_function(env, recv, callback, 3, args, &recv) == napi_ok);
|
47
|
-
}
|
48
|
-
|
49
|
-
free(event->events);
|
50
|
-
free(event);
|
51
|
-
}
|
52
|
-
|
53
|
-
void fse_free_watcher(napi_env env, void* watcher, void* callback) {
|
54
|
-
fse_free(watcher);
|
55
|
-
}
|
56
|
-
|
57
|
-
void fse_watcher_started(void *context) {
|
58
|
-
napi_threadsafe_function callback = (napi_threadsafe_function)context;
|
59
|
-
CHECK(napi_acquire_threadsafe_function(callback) == napi_ok);
|
60
|
-
}
|
61
|
-
void fse_watcher_ended(void *context) {
|
62
|
-
napi_threadsafe_function callback = (napi_threadsafe_function)context;
|
63
|
-
CHECK(napi_release_threadsafe_function(callback, napi_tsfn_abort) == napi_ok);
|
64
|
-
}
|
65
|
-
|
66
|
-
static napi_value FSEStart(napi_env env, napi_callback_info info) {
|
67
|
-
size_t argc = 2;
|
68
|
-
napi_value argv[argc];
|
69
|
-
char path[PATH_MAX];
|
70
|
-
napi_threadsafe_function callback;
|
71
|
-
napi_value asyncResource, asyncName;
|
72
|
-
|
73
|
-
CHECK(napi_get_cb_info(env, info, &argc, argv, NULL, NULL) == napi_ok);
|
74
|
-
CHECK(napi_get_value_string_utf8(env, argv[0], path, PATH_MAX, &argc) == napi_ok);
|
75
|
-
CHECK(napi_create_object(env, &asyncResource) == napi_ok);
|
76
|
-
CHECK(napi_create_string_utf8(env, "fsevents", NAPI_AUTO_LENGTH, &asyncName) == napi_ok);
|
77
|
-
CHECK(napi_create_threadsafe_function(env, argv[1], asyncResource, asyncName, 0, 1, NULL, NULL, NULL, fse_dispatch_events, &callback) == napi_ok);
|
78
|
-
CHECK(napi_ref_threadsafe_function(env, callback) == napi_ok);
|
79
|
-
|
80
|
-
fse_watcher_t watcher = fse_alloc();
|
81
|
-
CHECK(watcher);
|
82
|
-
fse_watch(path, fse_propagate_event, callback, fse_watcher_started, fse_watcher_ended, watcher);
|
83
|
-
|
84
|
-
napi_value result;
|
85
|
-
CHECK(napi_create_external(env, watcher, fse_free_watcher, callback, &result) == napi_ok);
|
86
|
-
return result;
|
87
|
-
}
|
88
|
-
static napi_value FSEStop(napi_env env, napi_callback_info info) {
|
89
|
-
size_t argc = 1;
|
90
|
-
napi_value external;
|
91
|
-
fse_watcher_t watcher;
|
92
|
-
CHECK(napi_get_cb_info(env, info, &argc, &external, NULL, NULL) == napi_ok);
|
93
|
-
CHECK(napi_get_value_external(env, external, (void**)&watcher) == napi_ok);
|
94
|
-
napi_threadsafe_function callback = (napi_threadsafe_function)fse_context_of(watcher);
|
95
|
-
if (callback) {
|
96
|
-
CHECK(napi_unref_threadsafe_function(env, callback) == napi_ok);
|
97
|
-
}
|
98
|
-
fse_unwatch(watcher);
|
99
|
-
napi_value result;
|
100
|
-
CHECK(napi_get_undefined(env, &result) == napi_ok);
|
101
|
-
return result;
|
102
|
-
}
|
103
|
-
|
104
|
-
#define CONSTANT(name) do {\
|
105
|
-
CHECK(napi_create_int32(env, name, &value) == napi_ok);\
|
106
|
-
CHECK(napi_set_named_property(env, constants, #name, value) == napi_ok);\
|
107
|
-
} while (0)
|
108
|
-
|
109
|
-
napi_value Init(napi_env env, napi_value exports) {
|
110
|
-
fse_init();
|
111
|
-
napi_value value, constants;
|
112
|
-
|
113
|
-
CHECK(napi_create_object(env, &constants) == napi_ok);
|
114
|
-
napi_property_descriptor descriptors[] = {
|
115
|
-
{ "start", NULL, FSEStart, NULL, NULL, NULL, napi_default, NULL },
|
116
|
-
{ "stop", NULL, FSEStop, NULL, NULL, NULL, napi_default, NULL },
|
117
|
-
{ "constants", NULL, NULL, NULL, NULL, constants, napi_default, NULL }
|
118
|
-
};
|
119
|
-
CHECK(napi_define_properties(env, exports, 3, descriptors) == napi_ok);
|
120
|
-
|
121
|
-
CONSTANT(kFSEventStreamEventFlagNone);
|
122
|
-
CONSTANT(kFSEventStreamEventFlagMustScanSubDirs);
|
123
|
-
CONSTANT(kFSEventStreamEventFlagUserDropped);
|
124
|
-
CONSTANT(kFSEventStreamEventFlagKernelDropped);
|
125
|
-
CONSTANT(kFSEventStreamEventFlagEventIdsWrapped);
|
126
|
-
CONSTANT(kFSEventStreamEventFlagHistoryDone);
|
127
|
-
CONSTANT(kFSEventStreamEventFlagRootChanged);
|
128
|
-
CONSTANT(kFSEventStreamEventFlagMount);
|
129
|
-
CONSTANT(kFSEventStreamEventFlagUnmount);
|
130
|
-
CONSTANT(kFSEventStreamEventFlagItemCreated);
|
131
|
-
CONSTANT(kFSEventStreamEventFlagItemRemoved);
|
132
|
-
CONSTANT(kFSEventStreamEventFlagItemInodeMetaMod);
|
133
|
-
CONSTANT(kFSEventStreamEventFlagItemRenamed);
|
134
|
-
CONSTANT(kFSEventStreamEventFlagItemModified);
|
135
|
-
CONSTANT(kFSEventStreamEventFlagItemFinderInfoMod);
|
136
|
-
CONSTANT(kFSEventStreamEventFlagItemChangeOwner);
|
137
|
-
CONSTANT(kFSEventStreamEventFlagItemXattrMod);
|
138
|
-
CONSTANT(kFSEventStreamEventFlagItemIsFile);
|
139
|
-
CONSTANT(kFSEventStreamEventFlagItemIsDir);
|
140
|
-
CONSTANT(kFSEventStreamEventFlagItemIsSymlink);
|
141
|
-
|
142
|
-
return exports;
|
143
|
-
}
|
144
|
-
|
145
|
-
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|
package/src/rawfsevents.c
DELETED
@@ -1,149 +0,0 @@
|
|
1
|
-
#include "rawfsevents.h"
|
2
|
-
#include "CoreFoundation/CoreFoundation.h"
|
3
|
-
#include "CoreServices/CoreServices.h"
|
4
|
-
#include <pthread.h>
|
5
|
-
#include <assert.h>
|
6
|
-
|
7
|
-
#ifndef CHECK
|
8
|
-
#ifdef NDEBUG
|
9
|
-
#define CHECK(x) do { if (!(x)) abort(); } while (0)
|
10
|
-
#else
|
11
|
-
#define CHECK assert
|
12
|
-
#endif
|
13
|
-
#endif
|
14
|
-
|
15
|
-
typedef struct {
|
16
|
-
pthread_t thread;
|
17
|
-
CFRunLoopRef loop;
|
18
|
-
pthread_mutex_t lock;
|
19
|
-
pthread_cond_t init;
|
20
|
-
} fse_loop_t;
|
21
|
-
|
22
|
-
struct fse_watcher_s {
|
23
|
-
char path[PATH_MAX];
|
24
|
-
FSEventStreamRef stream;
|
25
|
-
fse_event_handler_t handler;
|
26
|
-
fse_thread_hook_t hookend;
|
27
|
-
void *context;
|
28
|
-
};
|
29
|
-
|
30
|
-
static fse_loop_t fsevents;
|
31
|
-
|
32
|
-
void fse_init() {
|
33
|
-
fsevents.thread = NULL;
|
34
|
-
fsevents.loop = NULL;
|
35
|
-
pthread_mutex_init(&fsevents.lock, NULL);
|
36
|
-
pthread_cond_init(&fsevents.init, NULL);
|
37
|
-
}
|
38
|
-
|
39
|
-
void *fse_run_loop(void *data) {
|
40
|
-
|
41
|
-
fsevents.loop = CFRunLoopGetCurrent();
|
42
|
-
pthread_mutex_unlock(&fsevents.lock);
|
43
|
-
|
44
|
-
pthread_cond_signal(&fsevents.init);
|
45
|
-
pthread_mutex_lock(&fsevents.lock);
|
46
|
-
CFRunLoopPerformBlock(fsevents.loop, kCFRunLoopDefaultMode, ^(void){
|
47
|
-
pthread_mutex_unlock(&fsevents.lock);
|
48
|
-
});
|
49
|
-
CFRunLoopRun();
|
50
|
-
|
51
|
-
pthread_mutex_lock(&fsevents.lock);
|
52
|
-
fsevents.loop = NULL;
|
53
|
-
pthread_mutex_unlock(&fsevents.lock);
|
54
|
-
|
55
|
-
return NULL;
|
56
|
-
}
|
57
|
-
|
58
|
-
void fse_handle_events(
|
59
|
-
ConstFSEventStreamRef stream,
|
60
|
-
void *data,
|
61
|
-
size_t numEvents,
|
62
|
-
void *eventPaths,
|
63
|
-
const FSEventStreamEventFlags eventFlags[],
|
64
|
-
const FSEventStreamEventId eventIds[]
|
65
|
-
) {
|
66
|
-
fse_watcher_t watcher = data;
|
67
|
-
if (!watcher->handler) return;
|
68
|
-
fse_event_t *events = malloc(sizeof(*events) * numEvents);
|
69
|
-
CHECK(events);
|
70
|
-
size_t idx;
|
71
|
-
for (idx=0; idx < numEvents; idx++) {
|
72
|
-
fse_event_t *event = &events[idx];
|
73
|
-
CFStringRef path = (CFStringRef)CFArrayGetValueAtIndex((CFArrayRef)eventPaths, idx);
|
74
|
-
strncpy(event->path, CFStringGetCStringPtr(path, kCFStringEncodingUTF8), sizeof(event->path));
|
75
|
-
event->id = eventIds[idx];
|
76
|
-
event->flags = eventFlags[idx];
|
77
|
-
}
|
78
|
-
if (!watcher->handler) {
|
79
|
-
free(events);
|
80
|
-
} else {
|
81
|
-
watcher->handler(watcher->context, numEvents, events);
|
82
|
-
}
|
83
|
-
}
|
84
|
-
|
85
|
-
void fse_clear(fse_watcher_t watcher) {
|
86
|
-
watcher->path[0] = 0;
|
87
|
-
watcher->handler = NULL;
|
88
|
-
watcher->stream = NULL;
|
89
|
-
watcher->context = NULL;
|
90
|
-
watcher->hookend = NULL;
|
91
|
-
}
|
92
|
-
|
93
|
-
fse_watcher_t fse_alloc() {
|
94
|
-
fse_watcher_t watcher = malloc(sizeof(*watcher));
|
95
|
-
CHECK(watcher);
|
96
|
-
fse_clear(watcher);
|
97
|
-
return watcher;
|
98
|
-
}
|
99
|
-
|
100
|
-
void fse_free(fse_watcher_t watcher) {
|
101
|
-
fse_unwatch(watcher);
|
102
|
-
free(watcher);
|
103
|
-
}
|
104
|
-
|
105
|
-
void fse_watch(const char *path, fse_event_handler_t handler, void *context, fse_thread_hook_t hookstart, fse_thread_hook_t hookend, fse_watcher_t watcher) {
|
106
|
-
pthread_mutex_lock(&fsevents.lock);
|
107
|
-
if (!fsevents.loop) {
|
108
|
-
pthread_create(&fsevents.thread, NULL, fse_run_loop, NULL);
|
109
|
-
pthread_mutex_unlock(&fsevents.lock);
|
110
|
-
pthread_cond_wait(&fsevents.init, &fsevents.lock);
|
111
|
-
}
|
112
|
-
|
113
|
-
strncpy(watcher->path, path, PATH_MAX);
|
114
|
-
watcher->handler = handler;
|
115
|
-
watcher->context = context;
|
116
|
-
FSEventStreamContext streamcontext = { 0, watcher, NULL, NULL, NULL };
|
117
|
-
CFStringRef dirs[] = { CFStringCreateWithCString(NULL, watcher->path, kCFStringEncodingUTF8) };
|
118
|
-
watcher->stream = FSEventStreamCreate(NULL, &fse_handle_events, &streamcontext, CFArrayCreate(NULL, (const void **)&dirs, 1, NULL), kFSEventStreamEventIdSinceNow, (CFAbsoluteTime) 0.1, kFSEventStreamCreateFlagNone | kFSEventStreamCreateFlagWatchRoot | kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagUseCFTypes);
|
119
|
-
CFRunLoopPerformBlock(fsevents.loop, kCFRunLoopDefaultMode, ^(void){
|
120
|
-
if (hookstart) hookstart(watcher->context);
|
121
|
-
FSEventStreamScheduleWithRunLoop(watcher->stream, fsevents.loop, kCFRunLoopDefaultMode);
|
122
|
-
FSEventStreamStart(watcher->stream);
|
123
|
-
});
|
124
|
-
CFRunLoopWakeUp(fsevents.loop);
|
125
|
-
pthread_mutex_unlock(&fsevents.lock);
|
126
|
-
}
|
127
|
-
|
128
|
-
void fse_unwatch(fse_watcher_t watcher) {
|
129
|
-
FSEventStreamRef stream = watcher->stream;
|
130
|
-
fse_thread_hook_t hookend = watcher->hookend;
|
131
|
-
void *context = watcher->context;
|
132
|
-
fse_clear(watcher);
|
133
|
-
|
134
|
-
pthread_mutex_lock(&fsevents.lock);
|
135
|
-
if (fsevents.loop && stream) {
|
136
|
-
CFRunLoopPerformBlock(fsevents.loop, kCFRunLoopDefaultMode, ^(void){
|
137
|
-
FSEventStreamStop(stream);
|
138
|
-
FSEventStreamUnscheduleFromRunLoop(stream, fsevents.loop, kCFRunLoopDefaultMode);
|
139
|
-
FSEventStreamInvalidate(stream);
|
140
|
-
FSEventStreamRelease(stream);
|
141
|
-
if (hookend) hookend(context);
|
142
|
-
});
|
143
|
-
}
|
144
|
-
pthread_mutex_unlock(&fsevents.lock);
|
145
|
-
}
|
146
|
-
|
147
|
-
void *fse_context_of(fse_watcher_t watcher) {
|
148
|
-
return watcher->context;
|
149
|
-
}
|
package/src/rawfsevents.h
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
#ifndef __loop_h
|
2
|
-
#define __loop_h
|
3
|
-
|
4
|
-
#include <stdlib.h>
|
5
|
-
#include <limits.h>
|
6
|
-
|
7
|
-
typedef struct {
|
8
|
-
unsigned long long id;
|
9
|
-
char path[PATH_MAX];
|
10
|
-
unsigned int flags;
|
11
|
-
} fse_event_t;
|
12
|
-
|
13
|
-
typedef void (*fse_event_handler_t)(void *context, size_t numevents, fse_event_t *events);
|
14
|
-
typedef void (*fse_thread_hook_t)(void *context);
|
15
|
-
typedef struct fse_watcher_s* fse_watcher_t;
|
16
|
-
|
17
|
-
void fse_init();
|
18
|
-
fse_watcher_t fse_alloc();
|
19
|
-
void fse_free(fse_watcher_t watcherp);
|
20
|
-
void fse_watch(const char *path, fse_event_handler_t handler, void *context, fse_thread_hook_t hookstart, fse_thread_hook_t hookend, fse_watcher_t watcher_p);
|
21
|
-
void fse_unwatch(fse_watcher_t watcher);
|
22
|
-
void *fse_context_of(fse_watcher_t watcher);
|
23
|
-
#endif
|
package/test/01_native.js
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
const native = require('../fsevents.node');
|
2
|
-
const { mkdir, rm, rmrf, touch, rename } = require('./utils/fs.js');
|
3
|
-
const { run, sleep } = require('./utils/misc.js');
|
4
|
-
const path = require('path');
|
5
|
-
const assert = require('assert');
|
6
|
-
|
7
|
-
const DIR = process.argv[2];
|
8
|
-
|
9
|
-
run(async ()=>{
|
10
|
-
const events = [];
|
11
|
-
const listener = native.start(DIR, (...args) => events.push(args));
|
12
|
-
|
13
|
-
await touch(path.join(DIR, 'created'));
|
14
|
-
await sleep(250);
|
15
|
-
await rename(path.join(DIR, 'created'), path.join(DIR, 'renamed'));
|
16
|
-
await sleep(250);
|
17
|
-
await rm(path.join(DIR, 'renamed'));
|
18
|
-
await sleep(500);
|
19
|
-
|
20
|
-
native.stop(listener);
|
21
|
-
|
22
|
-
const expected = [
|
23
|
-
[path.join(DIR, 'created'), 66816, 80865],
|
24
|
-
[path.join(DIR, 'created'), 68864, 80887],
|
25
|
-
[path.join(DIR, 'renamed'), 67584, 80888],
|
26
|
-
[path.join(DIR, 'renamed'), 68096, 80910]
|
27
|
-
];
|
28
|
-
assert.equal(events.length, expected.length);
|
29
|
-
for (let idx = 0; idx < events.length; idx++) {
|
30
|
-
assert.equal(events[idx].length, expected[idx].length);
|
31
|
-
assert.equal(events[idx][0], expected[idx][0]);
|
32
|
-
assert.equal(events[idx][1], expected[idx][1]);
|
33
|
-
}
|
34
|
-
});
|
package/test/02_interleaved.js
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
const native = require('../fsevents.node');
|
2
|
-
const { mkdir, rm, rmrf, touch, rename } = require('./utils/fs.js');
|
3
|
-
const { run, sleep } = require('./utils/misc.js');
|
4
|
-
const path = require('path');
|
5
|
-
const assert = require('assert');
|
6
|
-
|
7
|
-
const DIR = process.argv[2];
|
8
|
-
|
9
|
-
run(async () => {
|
10
|
-
await mkdir(`${DIR}/A`);
|
11
|
-
await mkdir(`${DIR}/B`);
|
12
|
-
await sleep(500);
|
13
|
-
const events = [];
|
14
|
-
|
15
|
-
const listenerA = native.start(`${DIR}/A`, (...args) => events.push(args));
|
16
|
-
|
17
|
-
await touch(path.join(`${DIR}/A`, 'created'));
|
18
|
-
await sleep(500);
|
19
|
-
const listenerB = native.start(`${DIR}/B`, (...args) => events.push(args));
|
20
|
-
await sleep(500);
|
21
|
-
native.stop(listenerA);
|
22
|
-
await rename(path.join(`${DIR}/A`, 'created'), path.join(`${DIR}/B`, 'renamed'));
|
23
|
-
await sleep(500);
|
24
|
-
await rm(path.join(`${DIR}/B`, 'renamed'));
|
25
|
-
await sleep(500);
|
26
|
-
|
27
|
-
native.stop(listenerB);
|
28
|
-
|
29
|
-
const expected = [
|
30
|
-
[path.join(`${DIR}/A`, 'created'), 66816, 80865],
|
31
|
-
[path.join(`${DIR}/B`, 'renamed'), 67584, 80888],
|
32
|
-
[path.join(`${DIR}/B`, 'renamed'), 68096, 80910]
|
33
|
-
];
|
34
|
-
assert.equal(events.length, expected.length);
|
35
|
-
for (let idx = 0; idx < events.length; idx++) {
|
36
|
-
assert.equal(events[idx].length, expected[idx].length);
|
37
|
-
assert.equal(events[idx][0], expected[idx][0]);
|
38
|
-
assert.equal(events[idx][1], expected[idx][1]);
|
39
|
-
}
|
40
|
-
});
|
package/test/02_structure.js
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
|
3
|
-
** Licensed under MIT License.
|
4
|
-
*/
|
5
|
-
|
6
|
-
/* jshint node:true */
|
7
|
-
'use strict';
|
8
|
-
|
9
|
-
const assert = require('assert');
|
10
|
-
const fsevents = require('../fsevents');
|
11
|
-
const { run } = require('./utils/misc.js');
|
12
|
-
|
13
|
-
run(async ()=>{
|
14
|
-
assert.equal('object', typeof fsevents);
|
15
|
-
assert.equal('function', typeof fsevents.watch);
|
16
|
-
assert.equal('function', typeof fsevents.getInfo);
|
17
|
-
assert.equal('object', typeof fsevents.constants);
|
18
|
-
|
19
|
-
assert.equal('file', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemIsFile).type);
|
20
|
-
assert.equal('directory', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemIsDir).type);
|
21
|
-
assert.equal('symlink', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemIsSymlink).type);
|
22
|
-
|
23
|
-
assert.equal('deleted', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemRemoved).event);
|
24
|
-
assert.equal('moved', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemRenamed).event);
|
25
|
-
assert.equal('created', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemCreated).event);
|
26
|
-
assert.equal('modified', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagItemModified).event);
|
27
|
-
assert.equal('root-changed', fsevents.getInfo('path', fsevents.constants.kFSEventStreamEventFlagRootChanged).event);
|
28
|
-
|
29
|
-
assert.deepEqual()
|
30
|
-
});
|
package/test/03_simple.js
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
|
3
|
-
** Licensed under MIT License.
|
4
|
-
*/
|
5
|
-
|
6
|
-
/* jshint node:true */
|
7
|
-
'use strict';
|
8
|
-
|
9
|
-
const { mkdir, rm, rmrf, touch, rename } = require('./utils/fs.js');
|
10
|
-
const { sleep, capture, run } = require('./utils/misc.js');
|
11
|
-
|
12
|
-
const path = require('path');
|
13
|
-
const assert = require('assert');
|
14
|
-
const fsevents = require('../fsevents');
|
15
|
-
|
16
|
-
const DIR = process.argv[2];
|
17
|
-
|
18
|
-
run(async ()=>{
|
19
|
-
const events = capture();
|
20
|
-
const stop = fsevents.watch(DIR, events.callback);
|
21
|
-
|
22
|
-
await touch(path.join(DIR, 'created'));
|
23
|
-
await sleep(250);
|
24
|
-
await rename(path.join(DIR, 'created'), path.join(DIR, 'renamed'));
|
25
|
-
await sleep(250);
|
26
|
-
await rm(path.join(DIR, 'renamed'));
|
27
|
-
await sleep(1500);
|
28
|
-
|
29
|
-
await stop();
|
30
|
-
|
31
|
-
const expected = [
|
32
|
-
{
|
33
|
-
path: path.join(DIR, 'created'),
|
34
|
-
event: 'created',
|
35
|
-
type: 'file'
|
36
|
-
},
|
37
|
-
{
|
38
|
-
path: path.join(DIR, 'created'),
|
39
|
-
event: 'moved',
|
40
|
-
type: 'file'
|
41
|
-
},
|
42
|
-
{
|
43
|
-
path: path.join(DIR, 'renamed'),
|
44
|
-
event: 'moved',
|
45
|
-
type: 'file'
|
46
|
-
},
|
47
|
-
{
|
48
|
-
path: path.join(DIR, 'renamed'),
|
49
|
-
event: 'deleted',
|
50
|
-
type: 'file'
|
51
|
-
}
|
52
|
-
];
|
53
|
-
|
54
|
-
const parsed = events.map((args) => fsevents.getInfo(...args));
|
55
|
-
parsed.forEach((actual, idx)=>{
|
56
|
-
const expect = expected[idx];
|
57
|
-
assert.equal(actual.path, expect.path);
|
58
|
-
assert.equal(actual.type, expect.type);
|
59
|
-
assert.equal(actual.event, expect.event);
|
60
|
-
})
|
61
|
-
});
|
package/test/03_waiting.js
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
|
3
|
-
** Licensed under MIT License.
|
4
|
-
*/
|
5
|
-
|
6
|
-
/* jshint node:true */
|
7
|
-
'use strict';
|
8
|
-
|
9
|
-
const path = require('path');
|
10
|
-
const assert = require('assert');
|
11
|
-
const fsevents = require('../fsevents');
|
12
|
-
const { run, sleep } = require('./utils/misc.js');
|
13
|
-
const { touch } = require('./utils/fs.js');
|
14
|
-
|
15
|
-
const DIR = process.argv[2];
|
16
|
-
|
17
|
-
run(async ()=>{
|
18
|
-
const events = [];
|
19
|
-
const stopWatching = fsevents.watch(DIR, (...args)=>events.push(args));
|
20
|
-
await sleep(500);
|
21
|
-
for (let idx = 0; idx < 10; idx++) {
|
22
|
-
await touch(path.join(DIR, `${idx + 1}.touch`));
|
23
|
-
await sleep(250);
|
24
|
-
}
|
25
|
-
await sleep(500);
|
26
|
-
assert.equal(events.length, 10)
|
27
|
-
await stopWatching();
|
28
|
-
});
|
package/test/utils/fs.js
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
const fs = require('fs');
|
2
|
-
const path = require('path');
|
3
|
-
|
4
|
-
exports.rmrf = async (file)=>{
|
5
|
-
let stat;
|
6
|
-
try {
|
7
|
-
stat = await exports.stat(file);
|
8
|
-
} catch(err) {
|
9
|
-
//ignore
|
10
|
-
}
|
11
|
-
if (!stat) return;
|
12
|
-
if (stat.isDirectory()) {
|
13
|
-
const files = await exports.readdir(file);
|
14
|
-
await Promise.all(files.map(exports.rmrf));
|
15
|
-
}
|
16
|
-
await exports.rm(file, stat);
|
17
|
-
}
|
18
|
-
exports.rm = async (file, stat)=>{
|
19
|
-
stat = stat || await exports.stat(file);
|
20
|
-
return await new Promise((resolve, reject) => {
|
21
|
-
fs[stat.isDirectory() ? 'rmdir' : 'unlink'](file, (err) => {
|
22
|
-
if (err) return reject(err);
|
23
|
-
resolve();
|
24
|
-
});
|
25
|
-
});
|
26
|
-
};
|
27
|
-
exports.readdir = async (file)=>{
|
28
|
-
return await new Promise((resolve, reject)=>{
|
29
|
-
fs.readdir(file, (err, files)=>{
|
30
|
-
if (err) return reject(err);
|
31
|
-
resolve(files.map((child) => path.join(file, child)));
|
32
|
-
});
|
33
|
-
});
|
34
|
-
};
|
35
|
-
exports.stat = async (file)=>{
|
36
|
-
return await new Promise((resolve, reject)=>{
|
37
|
-
fs.stat(file, (err, stat)=>{
|
38
|
-
if (err) return reject(err);
|
39
|
-
if (!stat) return reject(new Error(`no stat for: ${file}`));
|
40
|
-
resolve(stat);
|
41
|
-
});
|
42
|
-
});
|
43
|
-
};
|
44
|
-
exports.mkdir = async (file)=>{
|
45
|
-
return await new Promise((resolve, reject)=>{
|
46
|
-
fs.mkdir(file, (err)=>{
|
47
|
-
if (err) return reject(err);
|
48
|
-
resolve();
|
49
|
-
});
|
50
|
-
});
|
51
|
-
};
|
52
|
-
exports.write = async (file, content)=>{
|
53
|
-
return await new Promise((resolve, reject)=>{
|
54
|
-
fs.writeFile(file, content, (err) => {
|
55
|
-
if (err) return reject(err);
|
56
|
-
resolve();
|
57
|
-
});
|
58
|
-
});
|
59
|
-
};
|
60
|
-
exports.read = async (file) => {
|
61
|
-
return await new Promise((resolve, reject)=>{
|
62
|
-
fs.readFile(file, 'utf-8', (err, content)=>{
|
63
|
-
if (err) return reject(err);
|
64
|
-
resolve(content);
|
65
|
-
});
|
66
|
-
});
|
67
|
-
};
|
68
|
-
exports.chmod = async (file, mode) => {
|
69
|
-
return await new Promise((resolve, reject) => {
|
70
|
-
fs.chmod(file, mode, (err)=> {
|
71
|
-
if (err) return reject(err);
|
72
|
-
resolve();
|
73
|
-
});
|
74
|
-
});
|
75
|
-
};
|
76
|
-
exports.touch = async (file) => {
|
77
|
-
try {
|
78
|
-
await exports.stat(file);
|
79
|
-
} catch(err) {
|
80
|
-
await exports.write(file, '');
|
81
|
-
}
|
82
|
-
|
83
|
-
return await new Promise((resolve, reject) => {
|
84
|
-
fs.utimes(file, Date.now(), Date.now(), (err) => {
|
85
|
-
if (err) return reject(err);
|
86
|
-
resolve();
|
87
|
-
});
|
88
|
-
});
|
89
|
-
};
|
90
|
-
exports.rename = async (orig, name) => {
|
91
|
-
return await new Promise((resolve, reject)=>{
|
92
|
-
fs.rename(orig, name, (err)=>{
|
93
|
-
if (err) return reject(err);
|
94
|
-
resolve();
|
95
|
-
});
|
96
|
-
});
|
97
|
-
};
|
package/test/utils/misc.js
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
exports.sleep = (ms)=>{
|
2
|
-
return new Promise((resolve)=>{
|
3
|
-
setTimeout(()=>resolve(), ms);
|
4
|
-
});
|
5
|
-
};
|
6
|
-
|
7
|
-
exports.capture = () => {
|
8
|
-
const events = [];
|
9
|
-
events.callback = (...args) => events.push(args);
|
10
|
-
return events;
|
11
|
-
};
|
12
|
-
|
13
|
-
exports.run = async (test)=>{
|
14
|
-
try {
|
15
|
-
await test();
|
16
|
-
process.exit(0);
|
17
|
-
} catch(err) {
|
18
|
-
console.log(' ---');
|
19
|
-
console.log(` message: ${err.message}`);
|
20
|
-
console.log(` actual: ${JSON.stringify(err.actual)}`);
|
21
|
-
console.log(` expected: ${JSON.stringify(err.expected)}`);
|
22
|
-
console.log(` source: ${err.stack.split(/\r?\n/)[1].trim()}`);
|
23
|
-
console.log(' ...');
|
24
|
-
process.exit(1);
|
25
|
-
}
|
26
|
-
};
|
package/test.sh
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
#!/bin/bash
|
2
|
-
|
3
|
-
N=0
|
4
|
-
F=0
|
5
|
-
T="$(pwd)/temp"
|
6
|
-
V=$(node -v)
|
7
|
-
D=$(date +%F_%T)
|
8
|
-
|
9
|
-
echo "TAP version 13"
|
10
|
-
echo "# Node Version: $V"
|
11
|
-
for FILE in $(ls test/*.js); do
|
12
|
-
DIR="$T/$D/$N"
|
13
|
-
rm -rf "$DIR"
|
14
|
-
mkdir -p "$DIR"
|
15
|
-
N=$(($N + 1))
|
16
|
-
echo "# File: $FILE" 1>&2
|
17
|
-
echo "# Directory: $DIR" 1>&2
|
18
|
-
node "$FILE" "$DIR"
|
19
|
-
if [ $? = 0 ]; then
|
20
|
-
echo "ok $N $FILE"
|
21
|
-
else
|
22
|
-
F=$(($F + 1))
|
23
|
-
echo "not ok $N $FILE"
|
24
|
-
fi
|
25
|
-
done
|
26
|
-
echo "1..$N"
|
27
|
-
rm -rf "$T"
|
28
|
-
|
29
|
-
exit $F
|