fsevents 2.0.5 → 2.0.6
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +1 -1
- package/fsevents.node +0 -0
- package/package.json +1 -2
- package/ISSUE_TEMPLATE.md +0 -8
- package/binding.gyp +0 -24
- package/lib/binding/Release/node-v67-darwin-x64/fse.node +0 -0
- package/src/constants.h +0 -112
- package/src/fsevents.c +0 -155
- package/src/rawfsevents.c +0 -151
- 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 -51
- package/test/utils/misc.js +0 -21
- 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/fsevents.node
CHANGED
Binary file
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
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": [
|
@@ -11,7 +11,6 @@
|
|
11
11
|
},
|
12
12
|
"scripts": {
|
13
13
|
"clean": "node-gyp clean && rm -f fsevents.node",
|
14
|
-
"install": "[ -f fsevents.node ] || npm run prepublishOnly",
|
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
|
},
|
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
|
-
}
|
Binary file
|
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
|
-
});
|
package/test/02_interleaved.js
DELETED
@@ -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
|
-
});
|
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 { 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
|
-
});
|
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,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;
|
package/test/utils/misc.js
DELETED
@@ -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
|