build-files 1.6.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,145 +0,0 @@
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
@@ -1,43 +0,0 @@
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
File without changes
File without changes
@@ -1,80 +0,0 @@
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/directory'
22
-
23
- module Build::Files::DirectorySpec
24
- include Build::Files
25
-
26
- describe Build::Files::Directory do
27
- let(:path) {Path.new("/foo/bar/baz", "/foo")}
28
- let(:directory) {Directory.new(path)}
29
-
30
- it "can be constructed using join" do
31
- joined_directory = Directory.join('/foo', 'bar/baz')
32
-
33
- expect(joined_directory).to be == directory
34
- end
35
-
36
- it "has a root and path component" do
37
- expect(directory.root).to be == path
38
- expect(directory.to_path).to be == path
39
-
40
- expect(directory.roots).to be_include(path)
41
- end
42
-
43
- it "can be converted into a string" do
44
- expect(directory.to_str).to be == path.to_str
45
- end
46
-
47
- it "can be used as a key" do
48
- hash = {directory => true}
49
-
50
- expect(hash).to be_include directory
51
- end
52
-
53
- it "includes subpaths" do
54
- expect(directory).to be_include "/foo/bar/baz/bob/dole"
55
- end
56
-
57
- it "can be compared" do
58
- other_directory = Directory.new(path + 'dole')
59
-
60
- expect(directory).to be_eql directory
61
- expect(directory).to_not be_eql other_directory
62
- end
63
-
64
- it "can be rebased" do
65
- rebased_directory = directory.rebase("/fu")
66
-
67
- expect(rebased_directory.root).to be == '/fu/bar/baz'
68
- end
69
-
70
- context Directory.join(__dir__, "directory_spec") do
71
- it "can list dot files" do
72
- expect(subject).to include(subject.root + '.dot_file.yaml')
73
- end
74
-
75
- it "can list normal files" do
76
- expect(subject).to include(subject.root + 'normal_file.txt')
77
- end
78
- end
79
- end
80
- end
File without changes
@@ -1,53 +0,0 @@
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/glob'
22
-
23
- RSpec.describe Build::Files::Glob do
24
- let(:path) {Build::Files::Path.new(__dir__)}
25
-
26
- it "can glob paths" do
27
- paths = path.glob("*.rb")
28
-
29
- expect(paths.count).to be >= 1
30
- end
31
-
32
- it "can be used as key in hash" do
33
- cache = {}
34
-
35
- cache[path.glob("*.rb")] = true
36
-
37
- expect(cache).to be_include(path.glob("*.rb"))
38
- end
39
-
40
- it "should print nice string represenation" do
41
- glob = Build::Files::Glob.new(".", "*.rb")
42
-
43
- expect("#{glob}").to be == '<Glob "."/"*.rb">'
44
- end
45
-
46
- context 'with dotfiles' do
47
- it "should list files starting with dot" do
48
- paths = path.glob("glob_spec/dotfiles/**/*")
49
-
50
- expect(paths.count).to be == 1
51
- end
52
- end
53
- end
@@ -1,182 +0,0 @@
1
- # Copyright, 2012, 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'
22
- require 'build/files/list'
23
- require 'build/files/glob'
24
-
25
- module Build::Files::ListSpec
26
- include Build::Files
27
-
28
- describe Build::Files::Paths do
29
- let(:path) {Path.new("/foo/bar/baz", "/foo")}
30
-
31
- it "should be inspectable" do
32
- paths = Paths.new(path)
33
-
34
- expect(paths.inspect).to be_include path.inspect
35
- end
36
-
37
- it "should be possible to convert to paths" do
38
- paths = Paths.new(path)
39
-
40
- expect(paths.to_paths).to be paths
41
- end
42
-
43
- it "should be count number of paths" do
44
- paths = Paths.new(path)
45
-
46
- expect(paths.count).to be == 1
47
- end
48
-
49
- it "should coerce array to paths" do
50
- paths = Paths.coerce([path])
51
-
52
- expect(paths).to be_kind_of Paths
53
- expect(paths.count).to be == 1
54
- expect(paths).to be_include path
55
-
56
- same_paths = Paths.coerce(paths)
57
- expect(same_paths).to be paths
58
- end
59
-
60
- it "can add two lists of paths together" do
61
- paths_a = Paths.new(path)
62
- paths_b = Paths.new(Path.join('/foo/bar', 'alice'))
63
-
64
- paths = paths_a + paths_b
65
-
66
- expect(paths.count).to be 2
67
- expect(paths).to be_include path
68
- expect(paths).to be_kind_of Composite
69
-
70
- # Composite equality
71
- expect(paths).to be_eql paths
72
- expect(paths).to_not be_eql paths_a
73
- end
74
-
75
- it "maps paths with a new extension" do
76
- paths = Paths.new([
77
- Path.join('/foo/bar', 'alice'),
78
- Path.join('/foo/bar', 'bob'),
79
- Path.join('/foo/bar', 'charles'),
80
- path
81
- ])
82
-
83
- expect(paths).to include(path)
84
-
85
- expect(paths).to be_intersects(paths)
86
- expect(paths).to_not be_intersects(Paths::NONE)
87
-
88
- mapped_paths = paths.map {|path| path + ".o"}
89
-
90
- expect(mapped_paths).to be_kind_of(Paths)
91
- expect(mapped_paths.roots).to be == paths.roots
92
- end
93
-
94
- it "globs multiple files" do
95
- glob = Glob.new(__dir__, '*.rb')
96
-
97
- expect(glob.count).to be > 1
98
-
99
- mapped_paths = glob.map {|path| path + ".txt"}
100
-
101
- expect(glob.roots).to be == mapped_paths.roots
102
- end
103
-
104
- it "should intersect one file in the glob" do
105
- # Glob all test files:
106
- glob = Glob.new(__dir__, "*.rb")
107
-
108
- expect(glob.count).to be > 0
109
-
110
- # Should include this file:
111
- expect(glob).to include(__FILE__)
112
-
113
- # Glob should intersect self:
114
- expect(glob).to be_intersects(glob)
115
- end
116
-
117
- it "should include composites" do
118
- lib = File.join(__dir__, "../lib")
119
-
120
- test_glob = Glob.new(__dir__, "*.rb")
121
- lib_glob = Glob.new(lib, "*.rb")
122
-
123
- both = test_glob + lib_glob
124
-
125
- # List#roots is the generic accessor for Lists
126
- expect(both.roots).to include test_glob.root
127
-
128
- # The composite should include both:
129
- expect(both).to include(__FILE__)
130
- end
131
-
132
- it "should have path with correct root" do
133
- test_glob = Glob.new(__dir__, "*.rb")
134
-
135
- expect(test_glob.first).to be_kind_of Path
136
-
137
- expect(test_glob.first.root).to be == __dir__
138
- end
139
-
140
- it "maps paths with new extension" do
141
- glob = Glob.new(__dir__, "*.rb")
142
-
143
- paths = glob.map {|path| path.append ".txt"}
144
-
145
- expect(paths.first).to be == (glob.first.append ".txt")
146
- expect(paths.first.to_s).to be_end_with ".rb.txt"
147
- end
148
-
149
- it "should map paths using with" do
150
- glob = Glob.new(__dir__, "*.rb")
151
-
152
- paths = glob.with extension: ".txt"
153
- path = paths.first
154
-
155
- expect(path).to be_kind_of Array
156
-
157
- expect(path[0]).to be == glob.first
158
- expect(path[1]).to be == glob.first.append(".txt")
159
- end
160
-
161
- it "should define an empty set of files" do
162
- expect(Paths::NONE).to be_kind_of List
163
-
164
- expect(Paths::NONE.count).to be 0
165
- end
166
-
167
- it "can be used as key in hash" do
168
- cache = {}
169
-
170
- cache[Paths.new(path)] = true
171
-
172
- expect(cache).to be_include(Paths.new(path))
173
- end
174
-
175
- it "can be constructed from a list of relative paths" do
176
- paths = Paths.directory('/foo', ['bar', 'baz', 'bob'])
177
-
178
- expect(paths.count).to be 3
179
- expect(paths).to be_include Path.new('/foo/bar')
180
- end
181
- end
182
- end
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env rspec
2
-
3
- # Copyright, 2015, 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
- require 'build/files/monitor'
24
- require 'build/files/path'
25
- require 'build/files/system'
26
- require 'build/files/directory'
27
-
28
- RSpec.shared_examples_for Monitor do |driver|
29
- let(:root) {Build::Files::Path.expand('tmp', __dir__)}
30
- let(:path) {root + "test.txt"}
31
-
32
- before do
33
- root.delete
34
- root.create
35
- end
36
-
37
- let(:directory) {Build::Files::Directory.new(root)}
38
- let(:monitor) {Build::Files::Monitor.new}
39
-
40
- it "should include touched path" do
41
- path.touch
42
-
43
- expect(directory.to_a).to include(path)
44
- end
45
-
46
- it 'should detect additions' do
47
- changed = false
48
-
49
- monitor.track_changes(directory) do |state|
50
- changed = true
51
-
52
- expect(state.added).to include(path)
53
- end
54
-
55
- thread = Thread.new do
56
- sleep 1
57
- path.touch
58
- end
59
-
60
- monitor.run do
61
- throw :interrupt if changed
62
- end
63
-
64
- thread.join
65
-
66
- expect(changed).to be true
67
- end
68
-
69
- it "should add and remove monitored paths" do
70
- handler = monitor.track_changes(directory) do |state|
71
- # Do nothing.
72
- end
73
-
74
- expect(monitor.roots).to be_include root
75
-
76
- handler.remove!
77
-
78
- expect(monitor.roots).to be_empty
79
- end
80
- end
81
-
82
- RSpec.describe Build::Files::Monitor::Polling do
83
- it_behaves_like Monitor
84
- end
85
-
86
- if defined? Build::Files::Monitor::Native
87
- RSpec.describe Build::Files::Monitor::Native do
88
- it_behaves_like Monitor
89
- end
90
- end