fsevents 2.0.5 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
package/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
1
  MIT License
2
2
  -----------
3
3
 
4
- Copyright (C) 2010-2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
4
+ Copyright (C) 2010-2019 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller
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 CHANGED
@@ -11,6 +11,8 @@ uses fsevents, check out [Chokidar](https://github.com/paulmillr/chokidar).
11
11
 
12
12
  ## Installation
13
13
 
14
+ Supports only **Node.js v8.16 and higher**.
15
+
14
16
  ```sh
15
17
  npm install fsevents
16
18
  ```
@@ -28,13 +30,15 @@ stop(); // To end observation
28
30
  The callback passed as the second parameter to `.watch` get's called whenever the operating system detects a
29
31
  a change in the file system. It takes three arguments:
30
32
 
31
- `(path: String, flags: Number, id: String) => {}`
33
+ ###### `fsevents.watch(dirname: string, (path: string, flags: number, id: string) => void): Function`
32
34
 
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
35
+ * `path: string` - the item in the filesystem that have been changed
36
+ * `flags: number` - a numeric value describing what the change was
37
+ * `id: string` - an unique-id identifying this specific event
38
+
39
+ Returns closer callback.
36
40
 
37
- ###### `fsevents.getInfo(path, flags, id): FsEventInfo => {}`
41
+ ###### `fsevents.getInfo(path: string, flags: number, id: string): FsEventInfo`
38
42
 
39
43
  The `getInfo` function takes the `path`, `flags` and `id` arguments and converts those parameters into a structure
40
44
  that is easier to digest to determine what the change was.
@@ -62,6 +66,6 @@ The `FsEventsInfo` has the following shape:
62
66
 
63
67
  ## License
64
68
 
65
- The MIT License Copyright (C) 2010-2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar — see LICENSE file.
69
+ The MIT License Copyright (C) 2010-2019 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller — see LICENSE file.
66
70
 
67
71
  Visit our [GitHub page](https://github.com/fsevents/fsevents) and [NPM Page](https://npmjs.org/package/fsevents)
package/fsevents.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
- ** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
3
- ** Licensed under MIT License.
4
- */
2
+ ** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar, Paul Miller
3
+ ** Licensed under MIT License.
4
+ */
5
5
 
6
6
  /* jshint node:true */
7
7
  'use strict';
@@ -11,11 +11,15 @@ if (process.platform !== 'darwin') {
11
11
  }
12
12
 
13
13
  const Native = require('./fsevents.node');
14
- const con = Native.constants;
14
+ const events = Native.constants;
15
15
 
16
16
  function watch(path, handler) {
17
- if ('string' !== typeof path) throw new TypeError(`argument 1 must be a string and not a ${typeof path}`);
18
- if ('function' !== typeof handler) throw new TypeError(`argument 2 must be a function and not a ${typeof handler}`);
17
+ if (typeof path !== 'string') {
18
+ throw new TypeError(`fsevents argument 1 must be a string and not a ${typeof path}`);
19
+ }
20
+ if (typeof handler !== 'function') {
21
+ throw new TypeError(`fsevents argument 2 must be a function and not a ${typeof handler}`);
22
+ }
19
23
 
20
24
  let instance = Native.start(path, handler);
21
25
  if (!instance) throw new Error(`could not watch: ${path}`);
@@ -25,9 +29,11 @@ function watch(path, handler) {
25
29
  return result;
26
30
  };
27
31
  }
32
+
28
33
  function getInfo(path, flags) {
29
34
  return {
30
- path, flags,
35
+ path,
36
+ flags,
31
37
  event: getEventType(flags),
32
38
  type: getFileType(flags),
33
39
  changes: getFileChanges(flags)
@@ -35,28 +41,35 @@ function getInfo(path, flags) {
35
41
  }
36
42
 
37
43
  function getFileType(flags) {
38
- if (con.kFSEventStreamEventFlagItemIsFile & flags) return 'file';
39
- if (con.kFSEventStreamEventFlagItemIsDir & flags) return 'directory';
40
- if (con.kFSEventStreamEventFlagItemIsSymlink & flags) return 'symlink';
44
+ if (events.ItemIsFile & flags) return 'file';
45
+ if (events.ItemIsDir & flags) return 'directory';
46
+ if (events.ItemIsSymlink & flags) return 'symlink';
47
+ }
48
+ function anyIsTrue(obj) {
49
+ for (let key in obj) {
50
+ if (obj[key]) return true;
51
+ }
52
+ return false;
41
53
  }
42
54
  function getEventType(flags) {
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';
48
-
55
+ if (events.ItemRemoved & flags) return 'deleted';
56
+ if (events.ItemRenamed & flags) return 'moved';
57
+ if (events.ItemCreated & flags) return 'created';
58
+ if (events.ItemModified & flags) return 'modified';
59
+ if (events.RootChanged & flags) return 'root-changed';
60
+ if (events.ItemCloned & flags) return 'cloned';
61
+ if (anyIsTrue(flags)) return 'modified';
49
62
  return 'unknown';
50
63
  }
51
64
  function getFileChanges(flags) {
52
65
  return {
53
- inode: !!(con.kFSEventStreamEventFlagItemInodeMetaMod & flags),
54
- finder: !!(con.kFSEventStreamEventFlagItemFinderInfoMod & flags),
55
- access: !!(con.kFSEventStreamEventFlagItemChangeOwner & flags),
56
- xattrs: !!(con.kFSEventStreamEventFlagItemXattrMod & flags)
66
+ inode: !!(events.ItemInodeMetaMod & flags),
67
+ finder: !!(events.ItemFinderInfoMod & flags),
68
+ access: !!(events.ItemChangeOwner & flags),
69
+ xattrs: !!(events.ItemXattrMod & flags)
57
70
  };
58
71
  }
59
72
 
60
73
  exports.watch = watch;
61
74
  exports.getInfo = getInfo;
62
- exports.constants = con;
75
+ exports.constants = events;
package/fsevents.node CHANGED
Binary file
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "fsevents",
3
- "version": "2.0.5",
4
- "description": "Native Access to Mac OS-X FSEvents",
3
+ "version": "2.1.1",
4
+ "description": "Native Access to MacOS FSEvents",
5
5
  "main": "fsevents.js",
6
6
  "os": [
7
7
  "darwin"
8
8
  ],
9
+ "files": ["fsevents.js", "fsevents.node"],
9
10
  "engines": {
10
11
  "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
11
12
  },
12
13
  "scripts": {
13
14
  "clean": "node-gyp clean && rm -f fsevents.node",
14
- "install": "[ -f fsevents.node ] || npm run prepublishOnly",
15
+ "build": "node-gyp clean && rm -f fsevents.node && node-gyp rebuild && node-gyp clean",
15
16
  "test": "/bin/bash ./test.sh 2>/dev/null",
16
- "prepublishOnly": "node-gyp clean && rm -f fsevents.node && node-gyp rebuild && node-gyp clean"
17
+ "prepublishOnly": "npm run build"
17
18
  },
18
19
  "repository": {
19
20
  "type": "git",
@@ -39,12 +40,15 @@
39
40
  {
40
41
  "name": "Miroslav Bajtoš",
41
42
  "email": "mbajtoss@gmail.com"
43
+ },
44
+ {
45
+ "name": "Paul Miller",
46
+ "url": "https://paulmillr.com"
42
47
  }
43
48
  ],
44
49
  "license": "MIT",
45
50
  "bugs": {
46
51
  "url": "https://github.com/fsevents/fsevents/issues"
47
52
  },
48
- "homepage": "https://github.com/fsevents/fsevents",
49
- "devDependencies": {}
53
+ "homepage": "https://github.com/fsevents/fsevents"
50
54
  }
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/binding.gyp DELETED
@@ -1,24 +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
- "-Wl,-bind_at_load",
10
- "-framework CoreFoundation -framework CoreServices"
11
- ]
12
- }
13
- }, {
14
- "target_name": "action_after_build",
15
- "type": "none",
16
- "dependencies": ["fsevents"],
17
- "copies": [{
18
- "files": ["<(PRODUCT_DIR)/fsevents.node"],
19
- "destination": "./"
20
- }]
21
- }]
22
- }]
23
- ]
24
- }
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,155 +0,0 @@
1
- /*
2
- ** © 2018 by Philipp Dunkel, Ben Noordhuis, Elan Shankar
3
- ** Licensed under MIT License.
4
- */
5
-
6
- #include <assert.h>
7
-
8
- #define NAPI_VERSION 4
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
- if (context == NULL) {
59
- return;
60
- }
61
- napi_threadsafe_function callback = (napi_threadsafe_function)context;
62
- CHECK(napi_acquire_threadsafe_function(callback) == napi_ok);
63
- }
64
- void fse_watcher_ended(void *context) {
65
- if (context == NULL) {
66
- return;
67
- }
68
- napi_threadsafe_function callback = (napi_threadsafe_function)context;
69
- CHECK(napi_release_threadsafe_function(callback, napi_tsfn_abort) == napi_ok);
70
- }
71
-
72
- static napi_value FSEStart(napi_env env, napi_callback_info info) {
73
- size_t argc = 2;
74
- napi_value argv[argc];
75
- char path[PATH_MAX];
76
- napi_threadsafe_function callback = NULL;
77
- napi_value asyncResource, asyncName;
78
-
79
- CHECK(napi_get_cb_info(env, info, &argc, argv, NULL, NULL) == napi_ok);
80
- CHECK(napi_get_value_string_utf8(env, argv[0], path, PATH_MAX, &argc) == napi_ok);
81
- CHECK(napi_create_object(env, &asyncResource) == napi_ok);
82
- CHECK(napi_create_string_utf8(env, "fsevents", NAPI_AUTO_LENGTH, &asyncName) == napi_ok);
83
- CHECK(napi_create_threadsafe_function(env, argv[1], asyncResource, asyncName, 0, 2, NULL, NULL, NULL, fse_dispatch_events, &callback) == napi_ok);
84
- CHECK(napi_ref_threadsafe_function(env, callback) == napi_ok);
85
-
86
- napi_value result;
87
- if (!callback) {
88
- CHECK(napi_get_undefined(env, &result) == napi_ok);
89
- return result;
90
- }
91
- fse_watcher_t watcher = fse_alloc();
92
- CHECK(watcher);
93
- fse_watch(path, fse_propagate_event, callback, fse_watcher_started, fse_watcher_ended, watcher);
94
-
95
- CHECK(napi_create_external(env, watcher, fse_free_watcher, callback, &result) == napi_ok);
96
- return result;
97
- }
98
- static napi_value FSEStop(napi_env env, napi_callback_info info) {
99
- size_t argc = 1;
100
- napi_value external;
101
- fse_watcher_t watcher;
102
- CHECK(napi_get_cb_info(env, info, &argc, &external, NULL, NULL) == napi_ok);
103
- CHECK(napi_get_value_external(env, external, (void**)&watcher) == napi_ok);
104
- napi_threadsafe_function callback = (napi_threadsafe_function)fse_context_of(watcher);
105
- if (callback) {
106
- CHECK(napi_unref_threadsafe_function(env, callback) == napi_ok);
107
- }
108
- fse_unwatch(watcher);
109
- napi_value result;
110
- CHECK(napi_get_undefined(env, &result) == napi_ok);
111
- return result;
112
- }
113
-
114
- #define CONSTANT(name) do {\
115
- CHECK(napi_create_int32(env, name, &value) == napi_ok);\
116
- CHECK(napi_set_named_property(env, constants, #name, value) == napi_ok);\
117
- } while (0)
118
-
119
- napi_value Init(napi_env env, napi_value exports) {
120
- fse_init();
121
- napi_value value, constants;
122
-
123
- CHECK(napi_create_object(env, &constants) == napi_ok);
124
- napi_property_descriptor descriptors[] = {
125
- { "start", NULL, FSEStart, NULL, NULL, NULL, napi_default, NULL },
126
- { "stop", NULL, FSEStop, NULL, NULL, NULL, napi_default, NULL },
127
- { "constants", NULL, NULL, NULL, NULL, constants, napi_default, NULL }
128
- };
129
- CHECK(napi_define_properties(env, exports, 3, descriptors) == napi_ok);
130
-
131
- CONSTANT(kFSEventStreamEventFlagNone);
132
- CONSTANT(kFSEventStreamEventFlagMustScanSubDirs);
133
- CONSTANT(kFSEventStreamEventFlagUserDropped);
134
- CONSTANT(kFSEventStreamEventFlagKernelDropped);
135
- CONSTANT(kFSEventStreamEventFlagEventIdsWrapped);
136
- CONSTANT(kFSEventStreamEventFlagHistoryDone);
137
- CONSTANT(kFSEventStreamEventFlagRootChanged);
138
- CONSTANT(kFSEventStreamEventFlagMount);
139
- CONSTANT(kFSEventStreamEventFlagUnmount);
140
- CONSTANT(kFSEventStreamEventFlagItemCreated);
141
- CONSTANT(kFSEventStreamEventFlagItemRemoved);
142
- CONSTANT(kFSEventStreamEventFlagItemInodeMetaMod);
143
- CONSTANT(kFSEventStreamEventFlagItemRenamed);
144
- CONSTANT(kFSEventStreamEventFlagItemModified);
145
- CONSTANT(kFSEventStreamEventFlagItemFinderInfoMod);
146
- CONSTANT(kFSEventStreamEventFlagItemChangeOwner);
147
- CONSTANT(kFSEventStreamEventFlagItemXattrMod);
148
- CONSTANT(kFSEventStreamEventFlagItemIsFile);
149
- CONSTANT(kFSEventStreamEventFlagItemIsDir);
150
- CONSTANT(kFSEventStreamEventFlagItemIsSymlink);
151
-
152
- return exports;
153
- }
154
-
155
- NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
package/src/rawfsevents.c DELETED
@@ -1,151 +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
- CFRunLoopPerformBlock(fsevents.loop, kCFRunLoopDefaultMode, ^(void){
117
- if (hookstart) hookstart(watcher->context);
118
- FSEventStreamContext streamcontext = { 0, watcher, NULL, NULL, NULL };
119
- CFStringRef dirs[] = { CFStringCreateWithCString(NULL, watcher->path, kCFStringEncodingUTF8) };
120
- watcher->stream = FSEventStreamCreate(NULL, &fse_handle_events, &streamcontext, CFArrayCreate(NULL, (const void **)&dirs, 1, NULL), kFSEventStreamEventIdSinceNow, (CFAbsoluteTime) 0.1, kFSEventStreamCreateFlagNone | kFSEventStreamCreateFlagWatchRoot | kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagUseCFTypes);
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) {
136
- CFRunLoopPerformBlock(fsevents.loop, kCFRunLoopDefaultMode, ^(void){
137
- if (stream) {
138
- FSEventStreamStop(stream);
139
- FSEventStreamUnscheduleFromRunLoop(stream, fsevents.loop, kCFRunLoopDefaultMode);
140
- FSEventStreamInvalidate(stream);
141
- FSEventStreamRelease(stream);
142
- }
143
- if (hookend) hookend(context);
144
- });
145
- }
146
- pthread_mutex_unlock(&fsevents.lock);
147
- }
148
-
149
- void *fse_context_of(fse_watcher_t watcher) {
150
- return watcher->context;
151
- }
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 { rm, 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
- });
@@ -1,40 +0,0 @@
1
- const native = require('../fsevents.node');
2
- const { mkdir, rm, 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(100);
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
- });
@@ -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 { rm, 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
- });
@@ -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,51 +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
-
19
- exports.rm = async (file, stat) => {
20
- stat = stat || await exports.stat(file);
21
- return await new Promise((resolve, reject) => {
22
- fs[stat.isDirectory() ? 'rmdir' : 'unlink'](file, (err) => {
23
- if (err) return reject(err);
24
- resolve();
25
- });
26
- });
27
- };
28
- exports.readdir = async (dir) => {
29
- const files = await fs.promises.readdir(dir);
30
- return files.map((child) => path.join(file, child));
31
- };
32
- exports.stat = fs.promises.stat;
33
- exports.mkdir = fs.promises.mkdir;
34
- exports.write = fs.promises.writeFile;
35
- exports.read = fs.promises.readFile;
36
- exports.chmod = fs.promises.chmod
37
- exports.touch = async (file) => {
38
- try {
39
- await exports.stat(file);
40
- } catch(err) {
41
- await exports.write(file, '');
42
- }
43
-
44
- return await new Promise((resolve, reject) => {
45
- fs.utimes(file, Date.now(), Date.now(), (err) => {
46
- if (err) return reject(err);
47
- resolve();
48
- });
49
- });
50
- };
51
- exports.rename = fs.promises.rename;
@@ -1,21 +0,0 @@
1
- exports.sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2
- exports.capture = () => {
3
- const events = [];
4
- events.callback = (...args) => events.push(args);
5
- return events;
6
- };
7
-
8
- exports.run = async (test) => {
9
- try {
10
- await test();
11
- process.exit(0);
12
- } catch(err) {
13
- console.log(' ---');
14
- console.log(` message: ${err.message}`);
15
- console.log(` actual: ${JSON.stringify(err.actual)}`);
16
- console.log(` expected: ${JSON.stringify(err.expected)}`);
17
- console.log(` source: ${err.stack.split(/\r?\n/)[1].trim()}`);
18
- console.log(' ...');
19
- process.exit(1);
20
- }
21
- };
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