build-files-monitor 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c927ec94d7e43c768d9b72cc2bd22aff95dc233a6c6969731093c110d4ba575f
4
+ data.tar.gz: 35416ba5b3908a3c68739071c24abb5bcb6f5ed25ae0c7b2bc18ce8eca697e41
5
+ SHA512:
6
+ metadata.gz: 551f9e5d4a55888fb8f12424fa810e9989dc775a825b279b909d4a0e37179dcf345e1ed4113d7fa15730f31b9d018b47cf2cee4cbdf3b01f47f9d8e137b6646d
7
+ data.tar.gz: b684c90665fa6e3d97f5aba086215b48941c4443734848a844f97ea809b8696a293454ee698efccb12f0e936fe0f9d41bee58b6418bcb1ed329cb687f10dd708
@@ -0,0 +1,43 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Build
22
+ module Files
23
+ module Monitor
24
+ case RUBY_PLATFORM
25
+ when /linux/i
26
+ require_relative 'monitor/inotify'
27
+ Native = INotify
28
+ Default = Native
29
+ when /darwin/i
30
+ require_relative 'monitor/fsevent'
31
+ Native = FSEvent
32
+ Default = Native
33
+ else
34
+ require_relative 'monitor/polling'
35
+ Default = Polling
36
+ end
37
+
38
+ def self.new(*args)
39
+ Default.new(*args)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,55 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'polling'
22
+
23
+ require 'rb-fsevent'
24
+
25
+ module Build
26
+ module Files
27
+ module Monitor
28
+ class FSEvent < Polling
29
+ def run(**options, &block)
30
+ notifier = ::FSEvent.new
31
+
32
+ catch(:interrupt) do
33
+ while true
34
+ notifier.watch self.roots do |directories|
35
+ directories.collect! do |directory|
36
+ File.expand_path(directory)
37
+ end
38
+
39
+ self.update(directories)
40
+
41
+ yield
42
+
43
+ if self.updated
44
+ notifier.stop
45
+ end
46
+ end
47
+
48
+ notifier.run
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,61 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'state'
22
+
23
+ module Build
24
+ module Files
25
+ module Monitor
26
+ class Handle
27
+ def initialize(monitor, files, &block)
28
+ @monitor = monitor
29
+ @state = State.new(files)
30
+ @block = block
31
+ end
32
+
33
+ attr :monitor
34
+
35
+ def commit!
36
+ @state.update!
37
+ end
38
+
39
+ def directories
40
+ @state.files.roots
41
+ end
42
+
43
+ def remove!
44
+ @monitor.delete(self)
45
+ end
46
+
47
+ # Inform the handle that it might have been modified.
48
+ def changed!
49
+ # If @state.update! did not find any changes, don't invoke the callback:
50
+ if @state.update!
51
+ @block.call(@state)
52
+ end
53
+ end
54
+
55
+ def to_s
56
+ "\#<#{self.class} @state=#{@state} @block=#{@block}>"
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,53 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require_relative 'polling'
22
+
23
+ require 'rb-inotify'
24
+
25
+ module Build
26
+ module Files
27
+ module Monitor
28
+ class INotify < Polling
29
+ def run(**options, &block)
30
+ notifier = ::INotify::Notifier.new
31
+
32
+ catch(:interrupt) do
33
+ while true
34
+ self.roots.each do |root|
35
+ notifier.watch root, :create, :modify, :attrib, :delete do |event|
36
+ self.update([root])
37
+
38
+ yield
39
+
40
+ if self.updated
41
+ notifier.stop
42
+ end
43
+ end
44
+ end
45
+
46
+ notifier.run
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,145 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'set'
22
+ require 'logger'
23
+
24
+ require_relative 'handle'
25
+
26
+ module Build
27
+ module Files
28
+ module Monitor
29
+ class Polling
30
+ def initialize(logger: nil)
31
+ @directories = Hash.new do |hash, key|
32
+ hash[key] = Set.new
33
+ end
34
+
35
+ @updated = false
36
+
37
+ @deletions = nil
38
+
39
+ @logger = logger || Logger.new(nil)
40
+ end
41
+
42
+ attr :updated
43
+
44
+ # Notify the monitor that files in these directories have changed.
45
+ def update(directories, *args)
46
+ @logger.debug{"Update: #{directories} #{args.inspect}"}
47
+
48
+ delay_deletions do
49
+ directories.each do |directory|
50
+ @logger.debug{"Directory: #{directory}"}
51
+
52
+ @directories[directory].each do |handle|
53
+ @logger.debug{"Handle changed: #{handle.inspect}"}
54
+
55
+ # Changes here may not actually require an update to the handle:
56
+ handle.changed!(*args)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def roots
63
+ @directories.keys
64
+ end
65
+
66
+ def delete(handle)
67
+ if @deletions
68
+ @logger.debug{"Delayed delete handle: #{handle}"}
69
+ @deletions << handle
70
+ else
71
+ purge(handle)
72
+ end
73
+ end
74
+
75
+ def track_changes(files, &block)
76
+ handle = Handle.new(self, files, &block)
77
+
78
+ add(handle)
79
+ end
80
+
81
+ def add(handle)
82
+ @logger.debug{"Adding handle: #{handle}"}
83
+
84
+ handle.directories.each do |directory|
85
+ # We want the full path as a plain string:
86
+ directory = directory.to_s
87
+
88
+ @directories[directory] << handle
89
+
90
+ # We just added the first handle:
91
+ if @directories[directory].size == 1
92
+ # If the handle already existed, this might trigger unnecessarily.
93
+ @updated = true
94
+ end
95
+ end
96
+
97
+ handle
98
+ end
99
+
100
+ def run(**options, &block)
101
+ catch(:interrupt) do
102
+ while true
103
+ monitor.update(monitor.roots)
104
+
105
+ yield
106
+
107
+ sleep(options[:latency] || 1.0)
108
+ end
109
+ end
110
+ end
111
+
112
+ protected
113
+
114
+ def delay_deletions
115
+ @deletions = []
116
+
117
+ yield
118
+
119
+ @deletions.each do |handle|
120
+ purge(handle)
121
+ end
122
+
123
+ @deletions = nil
124
+ end
125
+
126
+ def purge(handle)
127
+ @logger.debug{"Purge handle: #{handle}"}
128
+
129
+ handle.directories.each do |directory|
130
+ directory = directory.to_s
131
+
132
+ @directories[directory].delete(handle)
133
+
134
+ # Remove the entire record if there are no handles:
135
+ if @directories[directory].size == 0
136
+ @directories.delete(directory)
137
+
138
+ @updated = true
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,174 @@
1
+ # Copyright, 2014, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'build/files/list'
22
+
23
+ require 'forwardable'
24
+
25
+ module Build
26
+ module Files
27
+ module Monitor
28
+ # Represents a specific file on disk with a specific mtime.
29
+ class FileTime
30
+ include Comparable
31
+
32
+ def initialize(path, time)
33
+ @path = path
34
+ @time = time
35
+ end
36
+
37
+ attr :path
38
+ attr :time
39
+
40
+ def <=> other
41
+ @time <=> other.time
42
+ end
43
+
44
+ def inspect
45
+ "<FileTime #{@path.inspect} #{@time.inspect}>"
46
+ end
47
+ end
48
+
49
+ # A stateful list of files captured at a specific time, which can then be checked for changes.
50
+ class State < List
51
+ extend Forwardable
52
+
53
+ def initialize(files)
54
+ raise ArgumentError.new("Invalid files list: #{files}") unless Files::List === files
55
+
56
+ @files = files
57
+
58
+ @times = {}
59
+
60
+ update!
61
+ end
62
+
63
+ attr :files
64
+
65
+ attr :added
66
+ attr :removed
67
+ attr :changed
68
+ attr :missing
69
+
70
+ attr :times
71
+
72
+ def_delegators :@files, :each, :roots, :count
73
+
74
+ def update!
75
+ last_times = @times
76
+ @times = {}
77
+
78
+ @added = []
79
+ @removed = []
80
+ @changed = []
81
+ @missing = []
82
+
83
+ file_times = []
84
+
85
+ @files.each do |path|
86
+ # When processing the same path twice (perhaps by accident), we should skip it otherwise it might cause issues when being deleted from last_times multuple times.
87
+ next if @times.include? path
88
+
89
+ if File.exist?(path)
90
+ modified_time = File.mtime(path)
91
+
92
+ if last_time = last_times.delete(path)
93
+ # Path was valid last update:
94
+ if modified_time != last_time
95
+ @changed << path
96
+
97
+ # puts "Changed: #{path}"
98
+ end
99
+ else
100
+ # Path didn't exist before:
101
+ @added << path
102
+
103
+ # puts "Added: #{path}"
104
+ end
105
+
106
+ @times[path] = modified_time
107
+
108
+ unless File.directory?(path)
109
+ file_times << FileTime.new(path, modified_time)
110
+ end
111
+ else
112
+ @missing << path
113
+
114
+ # puts "Missing: #{path}"
115
+ end
116
+ end
117
+
118
+ @removed = last_times.keys
119
+ # puts "Removed: #{@removed.inspect}" if @removed.size > 0
120
+
121
+ @oldest_time = file_times.min
122
+ @newest_time = file_times.max
123
+
124
+ return @added.size > 0 || @changed.size > 0 || @removed.size > 0 || @missing.size > 0
125
+ end
126
+
127
+ attr :oldest_time
128
+ attr :newest_time
129
+
130
+ def missing?
131
+ !@missing.empty?
132
+ end
133
+
134
+ def empty?
135
+ @times.empty?
136
+ end
137
+
138
+ def inspect
139
+ "<State Added:#{@added} Removed:#{@removed} Changed:#{@changed} Missing:#{@missing}>"
140
+ end
141
+
142
+ # Are these (output) files dirty with respect to the given inputs?
143
+ def dirty?(inputs)
144
+ if self.missing?
145
+ return true
146
+ end
147
+
148
+ # If there are no inputs or no outputs, we are always clean:
149
+ if inputs.empty? or self.empty?
150
+ return false
151
+ end
152
+
153
+ oldest_output_time = self.oldest_time
154
+ newest_input_time = inputs.newest_time
155
+
156
+ if newest_input_time and oldest_output_time
157
+ # We are dirty if any inputs are newer (bigger) than any outputs:
158
+ if newest_input_time > oldest_output_time
159
+ return true
160
+ else
161
+ return false
162
+ end
163
+ end
164
+
165
+ return true
166
+ end
167
+
168
+ def self.dirty?(inputs, outputs)
169
+ outputs.dirty?(inputs)
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright, 2021, by Samuel G. D. Williams. <http://www.codeotaku.com>
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module Build
24
+ module Files
25
+ module Monitor
26
+ VERSION = "0.1.0"
27
+ end
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: build-files-monitor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Samuel Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-05-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rb-fsevent
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rb-inotify
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: build-files
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: covered
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.4'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.4'
97
+ description:
98
+ email:
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - lib/build/files/monitor.rb
104
+ - lib/build/files/monitor/fsevent.rb
105
+ - lib/build/files/monitor/handle.rb
106
+ - lib/build/files/monitor/inotify.rb
107
+ - lib/build/files/monitor/polling.rb
108
+ - lib/build/files/monitor/state.rb
109
+ - lib/build/files/monitor/version.rb
110
+ homepage: https://github.com/ioquatix/build-files-monitor
111
+ licenses:
112
+ - MIT
113
+ metadata:
114
+ funding_uri: https://github.com/sponsors/ioquatix/
115
+ post_install_message:
116
+ rdoc_options: []
117
+ require_paths:
118
+ - lib
119
+ required_ruby_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: 2.4.0
124
+ required_rubygems_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ requirements: []
130
+ rubygems_version: 3.2.3
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: Efficiently monitor changes to the file system.
134
+ test_files: []