build-files 1.3.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c4adb72625aa71340bebd18aea8d8dca1d4e8e06
4
- data.tar.gz: 5a6b6825dddfbf18889e24ee2884008d909332c3
2
+ SHA256:
3
+ metadata.gz: 4198299da23d7090752a148991d1d2287a13cd64243091b1c812fe257fec1fbe
4
+ data.tar.gz: 58e749b04d06f6311bce8232705545f2d115d3d22a7df38791c5a49797980671
5
5
  SHA512:
6
- metadata.gz: a265973dd1029a474df7ac5b843b1e79ac6e4e2458e39a8abd28be36491781c3c2f915de01bc1bcd55360ed7d95254d58727904925ec10a49ad31a5ce912085e
7
- data.tar.gz: 41de69d7681dcfe20bef304177d0a3a765bd32a242761ab579f984a9d13ddfc2a1c35d29342ced5a4e43446b5f4ee7c882d21e94a7ad4fe2dd86eb303c8b3aa7
6
+ metadata.gz: 8eac17319e61c722d12268116d85bb319944b34904cabe4c49319a181d21fe119ba38bf39823b1ca3c25c7f5d012a4c19a7ce2f589597cce1b0a4a4f18667fb1
7
+ data.tar.gz: fcf580850c89ce67f96bc4512495d12dd10eeaeb8f3ecddd77857b56c32f11c2977558bc7a89b586b335d640224d45eaaa9e190d1a3ea7841011537c1c2ac648
data/.rspec CHANGED
@@ -1,4 +1,4 @@
1
- --color
2
1
  --format documentation
3
2
  --backtrace
4
3
  --warnings
4
+ --require spec_helper
data/.travis.yml CHANGED
@@ -1,15 +1,14 @@
1
1
  language: ruby
2
- sudo: false
3
- rvm:
4
- - 2.0.0
5
- - 2.1.8
6
- - 2.2.4
7
- - 2.3.0
8
- - ruby-head
9
- - rbx-2
10
- env: COVERAGE=true
11
- matrix:
12
- allow_failures:
13
- - rvm: rbx-2
14
- - rvm: ruby-head
2
+ dist: xenial
3
+ cache: bundler
15
4
 
5
+ matrix:
6
+ include:
7
+ - rvm: 2.3
8
+ - rvm: 2.4
9
+ - rvm: 2.5
10
+ - rvm: 2.6
11
+ env: COVERAGE=BriefSummary,Coveralls
12
+ - rvm: 2.6
13
+ os: osx
14
+ env: COVERAGE=BriefSummary,Coveralls
data/Gemfile CHANGED
@@ -4,9 +4,6 @@ source 'https://rubygems.org'
4
4
  gemspec
5
5
 
6
6
  group :test do
7
- gem 'simplecov'
8
- gem 'coveralls', require: false
9
-
10
7
  gem 'rb-fsevent'
11
8
  gem 'rb-inotify'
12
9
  end
data/Rakefile CHANGED
@@ -1,8 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec) do |task|
5
- task.rspec_opts = ["--require", "simplecov"] if ENV['COVERAGE']
6
- end
4
+ RSpec::Core::RakeTask.new(:spec)
7
5
 
8
6
  task :default => :spec
data/build-files.gemspec CHANGED
@@ -1,7 +1,5 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'build/files/version'
1
+
2
+ require_relative 'lib/build/files/version'
5
3
 
6
4
  Gem::Specification.new do |spec|
7
5
  spec.name = "build-files"
@@ -20,7 +18,8 @@ Gem::Specification.new do |spec|
20
18
 
21
19
  spec.required_ruby_version = '>= 2.0'
22
20
 
23
- spec.add_development_dependency "bundler", "~> 1.3"
21
+ spec.add_development_dependency "covered"
22
+ spec.add_development_dependency "bundler"
24
23
  spec.add_development_dependency "rspec", "~> 3.4"
25
24
  spec.add_development_dependency "rake"
26
25
  end
data/lib/build/files.rb CHANGED
@@ -19,6 +19,7 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require_relative 'files/list'
22
+ require_relative 'files/composite'
22
23
  require_relative 'files/paths'
23
24
  require_relative 'files/glob'
24
25
  require_relative 'files/directory'
@@ -0,0 +1,99 @@
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 'list'
22
+
23
+ module Build
24
+ module Files
25
+ class Composite < List
26
+ def initialize(files, roots = nil)
27
+ @files = []
28
+
29
+ files.each do |list|
30
+ if list.kind_of? Composite
31
+ @files += list.files
32
+ elsif List.kind_of? List
33
+ @files << list
34
+ else
35
+ # Try to convert into a explicit paths list:
36
+ @files << Paths.new(list)
37
+ end
38
+ end
39
+
40
+ @files.freeze
41
+ @roots = roots
42
+ end
43
+
44
+ attr :files
45
+
46
+ def freeze
47
+ self.roots
48
+
49
+ super
50
+ end
51
+
52
+ def each
53
+ return to_enum(:each) unless block_given?
54
+
55
+ @files.each do |files|
56
+ files.each{|path| yield path}
57
+ end
58
+ end
59
+
60
+ def roots
61
+ @roots ||= @files.collect(&:roots).flatten.uniq
62
+ end
63
+
64
+ def eql?(other)
65
+ self.class.eql?(other.class) and @files.eql?(other.files)
66
+ end
67
+
68
+ def hash
69
+ @files.hash
70
+ end
71
+
72
+ def +(list)
73
+ if list.kind_of? Composite
74
+ self.class.new(@files + list.files)
75
+ else
76
+ self.class.new(@files + [list])
77
+ end
78
+ end
79
+
80
+ def include?(path)
81
+ @files.any? {|list| list.include?(path)}
82
+ end
83
+
84
+ def rebase(root)
85
+ self.class.new(@files.collect{|list| list.rebase(root)}, [root])
86
+ end
87
+
88
+ def to_paths
89
+ self.class.new(@files.collect(&:to_paths), roots: @roots)
90
+ end
91
+
92
+ def inspect
93
+ "<Composite #{@files.inspect}>"
94
+ end
95
+ end
96
+
97
+ List::NONE = Composite.new([]).freeze
98
+ end
99
+ end
@@ -0,0 +1,65 @@
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 'list'
22
+
23
+ module Build
24
+ module Files
25
+ class Difference < List
26
+ def initialize(list, excludes)
27
+ @list = list
28
+ @excludes = excludes
29
+ end
30
+
31
+ attr :files
32
+
33
+ def freeze
34
+ @list.freeze
35
+ @excludes.freeze
36
+
37
+ super
38
+ end
39
+
40
+ def each
41
+ return to_enum(:each) unless block_given?
42
+
43
+ @list.each do |path|
44
+ yield path unless @excludes.include?(path)
45
+ end
46
+ end
47
+
48
+ def -(list)
49
+ self.class.new(@list, Composite.new(@excludes, list))
50
+ end
51
+
52
+ def include?(path)
53
+ @list.includes?(path) and !@excludes.include?(path)
54
+ end
55
+
56
+ def rebase(root)
57
+ self.class.new(@files.collect{|list| list.rebase(root)}, [root])
58
+ end
59
+
60
+ def inspect
61
+ "<Difference #{@files.inspect} - #{@excludes.inspect}>"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,59 @@
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
+ class Handle
26
+ def initialize(monitor, files, &block)
27
+ @monitor = monitor
28
+ @state = State.new(files)
29
+ @block = block
30
+ end
31
+
32
+ attr :monitor
33
+
34
+ def commit!
35
+ @state.update!
36
+ end
37
+
38
+ def directories
39
+ @state.files.roots
40
+ end
41
+
42
+ def remove!
43
+ @monitor.delete(self)
44
+ end
45
+
46
+ # Inform the handle that it might have been modified.
47
+ def changed!
48
+ # If @state.update! did not find any changes, don't invoke the callback:
49
+ if @state.update!
50
+ @block.call(@state)
51
+ end
52
+ end
53
+
54
+ def to_s
55
+ "\#<#{self.class} @state=#{@state} @block=#{@block}>"
56
+ end
57
+ end
58
+ end
59
+ end
@@ -35,6 +35,10 @@ module Build
35
35
  Composite.new([self, list])
36
36
  end
37
37
 
38
+ def -(list)
39
+ Difference.new(self, list)
40
+ end
41
+
38
42
  # This isn't very efficient, but it IS generic.
39
43
  def ==(other)
40
44
  if self.class == other.class
@@ -91,79 +95,5 @@ module Build
91
95
  inspect
92
96
  end
93
97
  end
94
-
95
- class Composite < List
96
- def initialize(files, roots = nil)
97
- @files = []
98
-
99
- files.each do |list|
100
- if list.kind_of? Composite
101
- @files += list.files
102
- elsif List.kind_of? List
103
- @files << list
104
- else
105
- # Try to convert into a explicit paths list:
106
- @files << Paths.new(list)
107
- end
108
- end
109
-
110
- @files.freeze
111
- @roots = roots
112
- end
113
-
114
- attr :files
115
-
116
- def freeze
117
- self.roots
118
-
119
- super
120
- end
121
-
122
- def each
123
- return to_enum(:each) unless block_given?
124
-
125
- @files.each do |files|
126
- files.each{|path| yield path}
127
- end
128
- end
129
-
130
- def roots
131
- @roots ||= @files.collect(&:roots).flatten.uniq
132
- end
133
-
134
- def eql?(other)
135
- self.class.eql?(other.class) and @files.eql?(other.files)
136
- end
137
-
138
- def hash
139
- @files.hash
140
- end
141
-
142
- def +(list)
143
- if list.kind_of? Composite
144
- self.class.new(@files + list.files)
145
- else
146
- self.class.new(@files + [list])
147
- end
148
- end
149
-
150
- def include?(path)
151
- @files.any? {|list| list.include?(path)}
152
- end
153
-
154
- def rebase(root)
155
- self.class.new(@files.collect{|list| list.rebase(root)}, [root])
156
- end
157
-
158
- def to_paths
159
- self.class.new(@files.collect(&:to_paths), roots: @roots)
160
- end
161
-
162
- def inspect
163
- "<Composite #{@files.inspect}>"
164
- end
165
- end
166
-
167
- List::NONE = Composite.new([]).freeze
168
98
  end
169
99
  end
@@ -18,214 +18,26 @@
18
18
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
19
  # THE SOFTWARE.
20
20
 
21
- require 'set'
22
- require 'logger'
23
-
24
- require 'build/files/state'
25
-
26
21
  module Build
27
22
  module Files
28
- class Handle
29
- def initialize(monitor, files, &block)
30
- @monitor = monitor
31
- @state = State.new(files)
32
- @on_changed = block
33
- end
34
-
35
- attr :monitor
36
-
37
- def commit!
38
- @state.update!
39
- end
40
-
41
- def directories
42
- @state.files.roots
43
- end
44
-
45
- def remove!
46
- monitor.delete(self)
47
- end
48
-
49
- # Inform the handle that it might have been modified.
50
- def changed!
51
- # If @state.update! did not find any changes, don't invoke the callback:
52
- if @state.update!
53
- @on_changed.call(@state)
54
- end
55
- end
56
- end
57
-
58
- class Monitor
59
- def initialize(logger: nil)
60
- @directories = Hash.new { |hash, key| hash[key] = Set.new }
61
-
62
- @updated = false
63
-
64
- @deletions = nil
65
-
66
- @logger = logger || Logger.new(nil)
67
- end
68
-
69
- attr :updated
70
-
71
- # Notify the monitor that files in these directories have changed.
72
- def update(directories, *args)
73
- @logger.debug{"Update: #{directories} #{args.inspect}"}
74
-
75
- delay_deletions do
76
- directories.each do |directory|
77
- @logger.debug{"Directory: #{directory}"}
78
-
79
- @directories[directory].each do |handle|
80
- @logger.debug{"Handle changed: #{handle.inspect}"}
81
-
82
- # Changes here may not actually require an update to the handle:
83
- handle.changed!(*args)
84
- end
85
- end
86
- end
87
- end
88
-
89
- def roots
90
- @directories.keys
91
- end
92
-
93
- def delete(handle)
94
- if @deletions
95
- @logger.debug{"Delayed delete handle: #{handle}"}
96
- @deletions << handle
97
- else
98
- purge(handle)
99
- end
100
- end
101
-
102
- def track_changes(files, &block)
103
- handle = Handle.new(self, files, &block)
104
-
105
- add(handle)
106
- end
107
-
108
- def add(handle)
109
- @logger.debug{"Adding handle: #{handle}"}
110
-
111
- handle.directories.each do |directory|
112
- @directories[directory] << handle
113
-
114
- # We just added the first handle:
115
- if @directories[directory].size == 1
116
- # If the handle already existed, this might trigger unnecessarily.
117
- @updated = true
118
- end
119
- end
120
-
121
- handle
122
- end
123
-
124
- def default_driver
125
- case RUBY_PLATFORM
126
- when /linux/i then :inotify
127
- when /darwin/i then :fsevent
128
- else :polling
129
- end
130
- end
131
-
132
- def run(options = {}, &block)
133
- if driver = (options[:driver] || default_driver)
134
- method_name = "run_with_#{driver}"
135
- Files.send(method_name, self, options, &block)
136
- else
137
- raise ArgumentError.new("Could not find driver for platform #{RUBY_PLATFORM}!")
138
- end
139
- end
140
-
141
- protected
142
-
143
- def delay_deletions
144
- @deletions = []
145
-
146
- yield
147
-
148
- @deletions.each do |handle|
149
- purge(handle)
150
- end
151
-
152
- @deletions = nil
153
- end
154
-
155
- def purge(handle)
156
- @logger.debug{"Purge handle: #{handle}"}
157
-
158
- handle.directories.each do |directory|
159
- @directories[directory].delete(handle)
160
-
161
- # Remove the entire record if there are no handles:
162
- if @directories[directory].size == 0
163
- @directories.delete(directory)
164
-
165
- @updated = true
166
- end
167
- end
168
- end
169
- end
170
-
171
- def self.run_with_inotify(monitor, options = {}, &block)
172
- require 'rb-inotify'
173
-
174
- notifier = INotify::Notifier.new
175
-
176
- catch(:interrupt) do
177
- while true
178
- monitor.roots.each do |root|
179
- notifier.watch root, :create, :modify, :attrib, :delete do |event|
180
- monitor.update([root])
181
-
182
- yield
183
-
184
- if monitor.updated
185
- notifier.stop
186
- end
187
- end
188
- end
189
-
190
- notifier.run
191
- end
192
- end
193
- end
194
-
195
- def self.run_with_fsevent(monitor, options = {}, &block)
196
- require 'rb-fsevent'
197
-
198
- notifier = FSEvent.new
199
-
200
- catch(:interrupt) do
201
- while true
202
- notifier.watch monitor.roots do |directories|
203
- directories.collect!{|directory| File.expand_path(directory)}
204
-
205
- monitor.update(directories)
206
-
207
- yield
208
-
209
- if monitor.updated
210
- notifier.stop
211
- end
212
- end
213
-
214
- notifier.run
215
- end
216
- end
217
- end
218
-
219
- def self.run_with_polling(monitor, options = {}, &block)
220
- catch(:interrupt) do
221
- while true
222
- monitor.update(monitor.roots)
223
-
224
- yield
225
-
226
- sleep(options[:latency] || 1.0)
227
- end
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)
228
40
  end
229
41
  end
230
42
  end
231
- end
43
+ end