rb-fchange 0.0.2 → 0.0.4
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.
- data/README.md +3 -2
- data/lib/rb-fchange/native.rb +15 -40
- data/lib/rb-fchange/notifier.rb +10 -3
- data/lib/rb-fchange/watcher.rb +22 -3
- data/rb-fchange.gemspec +4 -4
- metadata +34 -54
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# rb-fchange
|
2
2
|
|
3
|
-
Code
|
3
|
+
Code is working. But there is still a lot of work.
|
4
4
|
This is a simple wrapper over the Windows Kernel functions for monitoring the specified directory or subtree.
|
5
5
|
|
6
6
|
Example
|
@@ -28,4 +28,5 @@ Example
|
|
28
28
|
- default flag for events :all_events
|
29
29
|
- rework interface (should more look like rb-fsevent)
|
30
30
|
- add specs (can use specs from rb-fsevent)
|
31
|
-
-
|
31
|
+
- add none-ANSI path support
|
32
|
+
- add jRuby support
|
data/lib/rb-fchange/native.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'ffi'
|
2
2
|
|
3
3
|
module FChange
|
4
4
|
# This module contains the low-level foreign-function.
|
@@ -6,65 +6,40 @@ module FChange
|
|
6
6
|
#
|
7
7
|
# @private
|
8
8
|
module Native
|
9
|
+
extend FFI::Library
|
10
|
+
ffi_lib 'kernel32'
|
11
|
+
ffi_convention :stdcall
|
9
12
|
|
10
|
-
#
|
11
|
-
|
13
|
+
# HANDLE FindFirstChangeNotification(
|
14
|
+
# LPCTSTR lpPathName, // directory name
|
15
|
+
# BOOL bWatchSubtree, // monitoring option
|
16
|
+
# DWORD dwNotifyFilter // filter conditions
|
17
|
+
#);
|
18
|
+
attach_function :FindFirstChangeNotificationW, [:pointer, :int, :long], :long
|
12
19
|
|
13
|
-
#
|
14
|
-
WAIT_OBJECT_0 = 0x00000000
|
15
|
-
|
16
20
|
# HANDLE FindFirstChangeNotification(
|
17
21
|
# LPCTSTR lpPathName, // directory name
|
18
22
|
# BOOL bWatchSubtree, // monitoring option
|
19
23
|
# DWORD dwNotifyFilter // filter conditions
|
20
24
|
#);
|
21
|
-
|
22
|
-
Win32::API.new('FindFirstChangeNotification', ['P', 'I', 'L'], 'L')
|
25
|
+
attach_function :FindFirstChangeNotificationA, [:pointer, :int, :long], :long
|
23
26
|
|
24
|
-
# @return handle
|
25
|
-
def k32FindFirstChangeNotification(path, recursive, flag)
|
26
|
-
@_k32FindFirstChangeNotification.call(path, recursive ? 1 : 0, flag)
|
27
|
-
end
|
28
|
-
|
29
|
-
module_function "k32FindFirstChangeNotification"
|
30
|
-
|
31
27
|
# BOOL FindNextChangeNotification(
|
32
28
|
# HANDLE hChangeHandle // handle to change notification
|
33
29
|
# );
|
34
|
-
|
35
|
-
Win32::API.new('FindNextChangeNotification', ['L'], 'I')
|
36
|
-
|
37
|
-
def k32FindNextChangeNotification(handle)
|
38
|
-
@_k32FindNextChangeNotification.call(handle)
|
39
|
-
end
|
40
|
-
|
41
|
-
module_function "k32FindNextChangeNotification"
|
30
|
+
attach_function :FindNextChangeNotification, [:long], :int
|
42
31
|
|
43
|
-
#
|
32
|
+
# DAORD WaitForMultipleObjects(
|
44
33
|
# DWORD nCount, // number of handles in array
|
45
34
|
# CONST HANDLE *lpHandles, // object-handle array
|
46
35
|
# BOOL bWaitAll, // wait option
|
47
36
|
# DWORD dwMilliseconds // time-out interval
|
48
37
|
# );
|
49
|
-
|
50
|
-
Win32::API.new('WaitForMultipleObjects', ['L', 'P', 'I', 'L'], 'L')
|
51
|
-
|
52
|
-
def k32WaitForMultipleObjects(count, handles, wait_all, time)
|
53
|
-
@_k32WaitForMultipleObjects.call(count, handles, wait_all, time)
|
54
|
-
end
|
55
|
-
|
56
|
-
module_function "k32WaitForMultipleObjects"
|
38
|
+
attach_function :WaitForMultipleObjects, [:long, :pointer, :int, :long], :long
|
57
39
|
|
58
40
|
# BOOL FindCloseChangeNotification(
|
59
41
|
# HANDLE hChangeHandle
|
60
42
|
# );
|
61
|
-
|
62
|
-
Win32::API.new('FindCloseChangeNotification', ['L'], 'I')
|
63
|
-
|
64
|
-
def k32FindCloseChangeNotification(handle)
|
65
|
-
@_k32FindCloseChangeNotification.call(handle)
|
66
|
-
end
|
67
|
-
|
68
|
-
module_function "k32FindCloseChangeNotification"
|
43
|
+
attach_function :FindCloseChangeNotification, [:long], :int
|
69
44
|
end
|
70
45
|
end
|
data/lib/rb-fchange/notifier.rb
CHANGED
@@ -15,6 +15,13 @@ module FChange
|
|
15
15
|
# # Nothing happens until you run the notifier!
|
16
16
|
# notifier.run
|
17
17
|
class Notifier
|
18
|
+
|
19
|
+
#
|
20
|
+
INFINITE = 0xFFFFFFFF
|
21
|
+
|
22
|
+
#
|
23
|
+
WAIT_OBJECT_0 = 0x00000000
|
24
|
+
|
18
25
|
# A hash from {Watcher} ids to the instances themselves.
|
19
26
|
#
|
20
27
|
# @private
|
@@ -110,19 +117,19 @@ module FChange
|
|
110
117
|
def read_events
|
111
118
|
|
112
119
|
# can return WAIT_TIMEOUT = 0x00000102
|
113
|
-
dwWaitStatus = Native.
|
120
|
+
dwWaitStatus = Native.WaitForMultipleObjects(@dwChangeHandles.count,
|
114
121
|
@lp_dwChangeHandles, 0, 500)
|
115
122
|
|
116
123
|
events = []
|
117
124
|
|
118
125
|
# this call blocks all threads completely.
|
119
126
|
@dwChangeHandles.each_index do |index|
|
120
|
-
if dwWaitStatus ==
|
127
|
+
if dwWaitStatus == WAIT_OBJECT_0 + index
|
121
128
|
|
122
129
|
ev = Event.new(@watchers[@dwChangeHandles[index]])
|
123
130
|
events << ev
|
124
131
|
|
125
|
-
r = Native.
|
132
|
+
r = Native.FindNextChangeNotification(@dwChangeHandles[index])
|
126
133
|
if r == 0
|
127
134
|
raise SystemCallError.new("Failed to watch", r)
|
128
135
|
end
|
data/lib/rb-fchange/watcher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
1
3
|
module FChange
|
2
4
|
# Watchers monitor a single path for changes,
|
3
5
|
# specified by {FChange::Notifier#watch event flags}.
|
@@ -50,12 +52,26 @@ module FChange
|
|
50
52
|
#
|
51
53
|
# @raise [SystemCallError] if the watch fails to be disabled for some reason
|
52
54
|
def close
|
53
|
-
r = Native.
|
55
|
+
r = Native.FindCloseChangeNotification(@id)
|
54
56
|
#@notifier.remove_watcher(self)
|
55
57
|
return if r == 0
|
56
58
|
raise SystemCallError.new("Failed to stop watching #{@path.inspect}", r)
|
57
59
|
end
|
58
60
|
|
61
|
+
# see http://msdn.microsoft.com/en-us/library/aa365247(v=vs.85).aspx
|
62
|
+
def normalize_path(path)
|
63
|
+
if(path.size > 256)
|
64
|
+
path = "\\\\?\\" + Pathname.new(path).realpath.to_s
|
65
|
+
end
|
66
|
+
# require 'rchardet'
|
67
|
+
# require 'iconv'
|
68
|
+
# cd = CharDet.detect(path)
|
69
|
+
# encoding = cd['encoding']
|
70
|
+
# converter = Iconv.new("UTF-16LE", encoding)
|
71
|
+
# converter.iconv(path)
|
72
|
+
# path.encode!("UTF-16LE")
|
73
|
+
end
|
74
|
+
|
59
75
|
# Creates a new {Watcher}.
|
60
76
|
#
|
61
77
|
# @private
|
@@ -65,9 +81,12 @@ module FChange
|
|
65
81
|
@callback = callback || proc {}
|
66
82
|
@path = path
|
67
83
|
@flags = flags
|
68
|
-
@recursive = recursive
|
69
|
-
|
84
|
+
@recursive = recursive ? 1 : 0
|
85
|
+
|
86
|
+
@id = Native.FindFirstChangeNotificationA(path, @recursive,
|
70
87
|
Native::Flags.to_mask(flags));
|
88
|
+
# @id = Native.FindFirstChangeNotificationW(normalize_path(path), @recursive,
|
89
|
+
# Native::Flags.to_mask(flags));
|
71
90
|
|
72
91
|
unless @id < 0
|
73
92
|
@notifier.add_watcher(self)
|
data/rb-fchange.gemspec
CHANGED
@@ -6,10 +6,10 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = %q{rb-fchange}
|
7
7
|
s.version = FChange::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors
|
10
|
-
s.date = %q{2011-
|
9
|
+
s.authors = ["stereobooster"]
|
10
|
+
s.date = %q{2011-05-15}
|
11
11
|
s.description = %q{A Ruby wrapper for Windows Kernel functions for monitoring the specified directory or subtree}
|
12
|
-
s.email =
|
12
|
+
s.email = ["stereobooster@gmail.com"]
|
13
13
|
s.extra_rdoc_files = [
|
14
14
|
"README.md"
|
15
15
|
]
|
@@ -28,5 +28,5 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.require_paths = ["lib"]
|
29
29
|
s.rubygems_version = %q{1.3.7}
|
30
30
|
s.summary = %q{A Ruby wrapper for Windows Kernel functions for monitoring the specified directory or subtree}
|
31
|
-
s.add_dependency('
|
31
|
+
s.add_dependency('ffi')
|
32
32
|
end
|
metadata
CHANGED
@@ -1,48 +1,37 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rb-fchange
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 2
|
10
|
-
version: 0.0.2
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- stereobooster
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2011-04-28 00:00:00 +03:00
|
12
|
+
date: 2011-05-15 00:00:00.000000000 +03:00
|
19
13
|
default_executable:
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
name:
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ffi
|
17
|
+
requirement: &24277536 !ruby/object:Gem::Requirement
|
25
18
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 4
|
33
|
-
- 8
|
34
|
-
version: 1.4.8
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
35
23
|
type: :runtime
|
36
|
-
|
37
|
-
|
38
|
-
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *24277536
|
26
|
+
description: A Ruby wrapper for Windows Kernel functions for monitoring the specified
|
27
|
+
directory or subtree
|
28
|
+
email:
|
29
|
+
- stereobooster@gmail.com
|
39
30
|
executables: []
|
40
|
-
|
41
31
|
extensions: []
|
42
|
-
|
43
|
-
extra_rdoc_files:
|
32
|
+
extra_rdoc_files:
|
44
33
|
- README.md
|
45
|
-
files:
|
34
|
+
files:
|
46
35
|
- README.md
|
47
36
|
- Rakefile
|
48
37
|
- lib/rb-fchange.rb
|
@@ -55,36 +44,27 @@ files:
|
|
55
44
|
has_rdoc: true
|
56
45
|
homepage: http://github.com/stereobooster/rb-fchange
|
57
46
|
licenses: []
|
58
|
-
|
59
47
|
post_install_message:
|
60
48
|
rdoc_options: []
|
61
|
-
|
62
|
-
require_paths:
|
49
|
+
require_paths:
|
63
50
|
- lib
|
64
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
52
|
none: false
|
66
|
-
requirements:
|
67
|
-
- -
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
|
70
|
-
|
71
|
-
- 0
|
72
|
-
version: "0"
|
73
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
58
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
79
|
-
segments:
|
80
|
-
- 0
|
81
|
-
version: "0"
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
82
63
|
requirements: []
|
83
|
-
|
84
64
|
rubyforge_project:
|
85
65
|
rubygems_version: 1.5.2
|
86
66
|
signing_key:
|
87
67
|
specification_version: 3
|
88
|
-
summary: A Ruby wrapper for Windows Kernel functions for monitoring the specified
|
68
|
+
summary: A Ruby wrapper for Windows Kernel functions for monitoring the specified
|
69
|
+
directory or subtree
|
89
70
|
test_files: []
|
90
|
-
|