maid 0.10.0.pre.alpha.3 → 0.11.0
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.
- checksums.yaml +4 -4
- data/.github/FUNDING.yml +14 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.github/workflows/coverage.yml +3 -3
- data/.github/workflows/lint.yml +9 -1
- data/.github/workflows/merge-gatekeeper.yml +20 -0
- data/.github/workflows/release.yml +13 -20
- data/.github/workflows/stale.yml +25 -0
- data/.github/workflows/test.yml +8 -7
- data/.gitignore +1 -1
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +3 -1
- data/.rubocop_todo.yml +105 -107
- data/.ruby-version +1 -1
- data/CHANGELOG.md +23 -0
- data/Dockerfile +13 -0
- data/Gemfile.lock +226 -0
- data/Guardfile +2 -0
- data/README.md +82 -49
- data/Rakefile +9 -0
- data/SECURITY.md +29 -0
- data/fixtures/files/test_rules.rb +3 -0
- data/fixtures/vcr_cassettes/Dependency_expectations/Geocoder/translates_latitude_and_longitude_into_street_addresses.yml +42 -0
- data/fixtures/vcr_cassettes/Maid_Tools/_location_city/given_a_JPEG_image/reports_the_known_location.yml +42 -0
- data/lib/maid/logger/logger.rb +63 -0
- data/lib/maid/maid.rb +6 -22
- data/lib/maid/repeat.rb +2 -2
- data/lib/maid/rule.rb +2 -2
- data/lib/maid/rule_container.rb +2 -2
- data/lib/maid/tools.rb +3 -3
- data/lib/maid/trash_migration.rb +2 -0
- data/lib/maid/version.rb +1 -1
- data/lib/maid/watch.rb +2 -2
- data/lib/maid.rb +3 -2
- data/maid.gemspec +14 -9
- data/release-please-config.json +18 -0
- data/script/docker-test +7 -0
- data/spec/dependency_spec.rb +1 -1
- data/spec/fakefs_helper.rb +13 -0
- data/spec/lib/maid/logger/logger_spec.rb +64 -0
- data/spec/lib/maid/maid_spec.rb +113 -103
- data/spec/lib/maid/rake/single_rule_spec.rb +1 -1
- data/spec/lib/maid/tools_spec.rb +384 -225
- data/spec/lib/maid/trash_migration_spec.rb +7 -5
- data/spec/spec_helper.rb +17 -1
- metadata +124 -44
- data/Vagrantfile +0 -14
- data/script/vagrant-provision +0 -43
- data/script/vagrant-test +0 -7
- data/script/vagrant-test-all +0 -34
data/spec/lib/maid/maid_spec.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module Maid
|
4
|
-
describe Maid
|
5
|
-
let(:logger) {
|
4
|
+
describe Maid do
|
5
|
+
let(:logger) { class_spy(::Logger) }
|
6
|
+
let(:logfile) { '/tmp/maid-specs/test.log' }
|
7
|
+
let(:rules_file) { File.expand_path(File.join(File.dirname(__dir__), '../../fixtures/files/test_rules.rb')) }
|
8
|
+
let(:test_defaults) { Maid::DEFAULTS.merge({ log_device: logfile, rules_path: rules_file }) }
|
6
9
|
|
7
10
|
before do
|
8
|
-
|
11
|
+
FileUtils.mkdir_p(File.dirname(logfile))
|
12
|
+
# Avoid FakeFS error when the logfile doesn't already exist.
|
13
|
+
FileUtils.touch(logfile) if FakeFS.activated?
|
9
14
|
end
|
10
15
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'sets up a logger with the given path, when provided' do
|
18
|
-
log_device = '/var/log/maid.log'
|
19
|
-
expect(Logger).to receive(:new).with(log_device, anything, anything)
|
20
|
-
Maid.new(log_device: log_device)
|
21
|
-
end
|
16
|
+
after do
|
17
|
+
# Cleanup afterwards
|
18
|
+
FileUtils.rm_rf(File.dirname(logfile))
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
Maid.new
|
27
|
-
end
|
21
|
+
describe '.new' do
|
22
|
+
context 'with the default options' do
|
23
|
+
before { Maid.new(**test_defaults, logger: logger) }
|
28
24
|
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
it 'sets up a logger with the default path' do
|
26
|
+
expect(logger).to have_received(:new).with(device: test_defaults[:log_device])
|
27
|
+
end
|
32
28
|
end
|
33
29
|
|
34
|
-
|
35
|
-
|
30
|
+
context 'with a custom logfile path' do
|
31
|
+
let(:device) { '/tmp/maid-specs/overridden-maid.log' }
|
36
32
|
|
37
|
-
Maid.new(log_device:
|
33
|
+
before { Maid.new(log_device: device, logger: logger) }
|
38
34
|
|
39
|
-
|
35
|
+
it 'sets up a logger with the given path, when provided' do
|
36
|
+
expect(logger).to have_received(:new).with(device: device)
|
37
|
+
end
|
40
38
|
end
|
41
39
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
context 'with a custom logger' do
|
41
|
+
let(:maid) { Maid.new(logger: logger) }
|
42
|
+
|
43
|
+
it 'uses it' do
|
44
|
+
expect(maid.logger).to eq(logger)
|
45
|
+
end
|
46
46
|
end
|
47
47
|
|
48
48
|
describe 'platform-specific behavior' do
|
@@ -87,25 +87,14 @@ module Maid
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
|
-
|
91
|
-
trash_path
|
92
|
-
|
93
|
-
maid = Maid.new(trash_path: trash_path)
|
94
|
-
|
95
|
-
expect(maid.trash_path).not_to be_nil
|
96
|
-
expect(maid.trash_path).to eq(trash_path)
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'sets the progname for the logger' do
|
100
|
-
Maid.new
|
101
|
-
|
102
|
-
expect(logger).to have_received(:progname=).with(Maid::DEFAULTS[:progname])
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'sets the progname for the logger to the given name, if provided' do
|
106
|
-
Maid.new(progname: 'Fran')
|
90
|
+
context 'with a custom trash path' do
|
91
|
+
let(:trash_path) { '/tmp/maid-specs/my_trash/' }
|
92
|
+
let(:maid) { Maid.new(log_device: test_defaults[:log_device], trash_path: trash_path) }
|
107
93
|
|
108
|
-
|
94
|
+
it 'sets the trash to the given path' do
|
95
|
+
expect(maid.trash_path).not_to be_nil
|
96
|
+
expect(maid.trash_path).to eq(trash_path)
|
97
|
+
end
|
109
98
|
end
|
110
99
|
|
111
100
|
it 'sets the file options to the defaults' do
|
@@ -133,21 +122,34 @@ module Maid
|
|
133
122
|
end
|
134
123
|
|
135
124
|
describe '#clean' do
|
125
|
+
let(:maid) { Maid.new(**test_defaults) }
|
126
|
+
|
136
127
|
before do
|
137
|
-
|
138
|
-
|
128
|
+
# Start with a clean logfile
|
129
|
+
FileUtils.rm_rf(logfile)
|
130
|
+
# Create the files that the test rules will impact
|
131
|
+
FileUtils.mkdir_p('/tmp/maid-specs')
|
132
|
+
FileUtils.touch('/tmp/maid-specs/perfect_man')
|
133
|
+
|
134
|
+
maid.load_rules
|
135
|
+
maid.clean
|
136
|
+
end
|
137
|
+
|
138
|
+
after do
|
139
|
+
FileUtils.rm_rf('/tmp/maid-specs')
|
139
140
|
end
|
140
141
|
|
141
|
-
it 'logs
|
142
|
-
|
142
|
+
it 'logs the beginning' do
|
143
|
+
expect(File.read(logfile)).to match(/Started/)
|
144
|
+
end
|
143
145
|
|
144
|
-
|
145
|
-
expect(
|
146
|
+
it 'logs the end' do
|
147
|
+
expect(File.read(logfile)).to match(/Finished/)
|
146
148
|
end
|
147
149
|
|
148
150
|
it 'follows the given rules' do
|
149
|
-
expect(
|
150
|
-
|
151
|
+
expect(File.exist?('/tmp/maid-specs/perfect_man')).to be false
|
152
|
+
expect(File.exist?('/tmp/maid-specs/buffalo_fuzz')).to be true
|
151
153
|
end
|
152
154
|
end
|
153
155
|
|
@@ -166,17 +168,17 @@ module Maid
|
|
166
168
|
end
|
167
169
|
|
168
170
|
context 'when there is a LoadError' do
|
169
|
-
let(:maid) { Maid.new }
|
171
|
+
let(:maid) { Maid.new(**test_defaults) }
|
170
172
|
|
171
173
|
before do
|
172
174
|
allow(Kernel).to receive(:load).and_raise(LoadError)
|
173
|
-
|
175
|
+
FileUtils.rm_rf(logfile)
|
174
176
|
end
|
175
177
|
|
176
178
|
it 'gives an error on STDERR if there is a LoadError' do
|
177
179
|
maid.load_rules
|
178
180
|
|
179
|
-
expect(
|
181
|
+
expect(File.read(logfile)).to match(/LoadError/)
|
180
182
|
end
|
181
183
|
end
|
182
184
|
end
|
@@ -218,30 +220,37 @@ module Maid
|
|
218
220
|
end
|
219
221
|
|
220
222
|
# FIXME: Example is too long, shouldn't need the rubocop::disable
|
221
|
-
|
222
|
-
hash
|
223
|
-
|
223
|
+
context 'with a hash of options' do
|
224
|
+
let(:hash) { { some: :options } }
|
225
|
+
let(:listener) { double('listener') }
|
224
226
|
|
225
|
-
|
226
|
-
|
227
|
+
before do
|
228
|
+
FileUtils.mkdir_p('some_dir')
|
229
|
+
@maid.watch('some_dir', hash) do
|
230
|
+
rule 'test' do
|
231
|
+
end
|
227
232
|
end
|
228
233
|
end
|
229
234
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
end
|
235
|
+
it 'passes them to Listen' do
|
236
|
+
expect(Listen).to receive(:to) do |dir, opts|
|
237
|
+
expect(dir).to eq File.expand_path('some_dir')
|
238
|
+
expect(opts).to eq(hash)
|
239
|
+
listener
|
240
|
+
end
|
237
241
|
|
238
|
-
|
242
|
+
expect(listener).to receive(:start)
|
239
243
|
|
240
|
-
|
244
|
+
@maid.watches.last.run
|
245
|
+
end
|
241
246
|
end
|
242
247
|
|
243
248
|
context('with a non-existent directory') do
|
244
|
-
let(:maid) { Maid.new }
|
249
|
+
let(:maid) { Maid.new(**test_defaults) }
|
250
|
+
|
251
|
+
before do
|
252
|
+
FileUtils.rm_rf(logfile)
|
253
|
+
end
|
245
254
|
|
246
255
|
it 'raises with an intelligible message' do
|
247
256
|
expect { maid.watch('/doesnt_exist/') }.to raise_error(/file.*exist/)
|
@@ -256,14 +265,18 @@ module Maid
|
|
256
265
|
rescue StandardError # rubocop:disable Lint/SuppressedException
|
257
266
|
end
|
258
267
|
|
259
|
-
expect(
|
268
|
+
expect(File.read(logfile)).to match(/file.*exist/)
|
260
269
|
end
|
261
270
|
end
|
262
271
|
end
|
263
272
|
|
264
|
-
describe '#repeat', fake_zoneinfo:
|
273
|
+
describe '#repeat', fake_zoneinfo: false do
|
265
274
|
before do
|
266
|
-
|
275
|
+
# Avoid FakeFS error when the logfile doesn't already exist.
|
276
|
+
FileUtils.mkdir_p(File.dirname(logfile))
|
277
|
+
FileUtils.touch(logfile)
|
278
|
+
|
279
|
+
@maid = Maid.new(log_device: logfile)
|
267
280
|
end
|
268
281
|
|
269
282
|
it 'adds a repeat to the list of repeats' do
|
@@ -277,53 +290,50 @@ module Maid
|
|
277
290
|
expect(@maid.repeats.first.timestring).to eq('1s')
|
278
291
|
end
|
279
292
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
293
|
+
context 'with a hash of options' do
|
294
|
+
let(:scheduler) { double('scheduler') }
|
295
|
+
let(:hash) { { some: :options } }
|
296
|
+
|
297
|
+
before do
|
298
|
+
allow(Rufus::Scheduler).to receive(:singleton).and_return(scheduler)
|
284
299
|
|
285
|
-
|
286
|
-
|
287
|
-
|
300
|
+
@maid.repeat('1s', hash) do
|
301
|
+
rule 'test' do
|
302
|
+
end
|
288
303
|
end
|
289
304
|
end
|
290
305
|
|
291
|
-
|
306
|
+
it 'passes them to Rufus' do
|
307
|
+
expect(scheduler).to receive(:repeat).with('1s', hash)
|
292
308
|
|
293
|
-
|
309
|
+
@maid.repeats.last.run
|
310
|
+
end
|
294
311
|
end
|
295
312
|
end
|
296
313
|
|
297
314
|
describe '#follow_rules' do
|
298
|
-
|
299
|
-
it 'follows each rule' do # rubocop:disable RSpec/ExampleLength
|
300
|
-
n = 3
|
301
|
-
maid = Maid.new
|
302
|
-
|
303
|
-
rules = (1..n).map do |i|
|
304
|
-
d = double("rule ##{i}", description: 'description')
|
305
|
-
expect(d).to receive(:follow)
|
306
|
-
d
|
307
|
-
end
|
308
|
-
maid.instance_eval { @rules = rules }
|
315
|
+
let(:maid) { Maid.new(**test_defaults) }
|
309
316
|
|
317
|
+
it 'follows each rule' do
|
318
|
+
# FIXME: This should run in a before and rules should be a let, but it
|
319
|
+
# fails when arranged that way.
|
320
|
+
rules = [spy(Rule), spy(Rule), spy(Rule)]
|
321
|
+
maid.instance_eval { @rules = rules }
|
310
322
|
maid.follow_rules
|
311
323
|
|
312
|
-
expect(
|
324
|
+
expect(rules).to all(have_received(:follow).once)
|
313
325
|
end
|
314
326
|
end
|
315
327
|
|
316
328
|
describe '#cmd' do
|
317
|
-
|
318
|
-
@maid = Maid.new
|
319
|
-
end
|
329
|
+
let(:maid) { Maid.new(log_device: logfile) }
|
320
330
|
|
321
331
|
it 'reports `not-a-real-command` as not being a supported command' do
|
322
|
-
expect {
|
332
|
+
expect { maid.cmd('not-a-real-command arg1 arg2') }.to raise_error(NotImplementedError)
|
323
333
|
end
|
324
334
|
|
325
335
|
it 'reports `echo` as a real command' do
|
326
|
-
expect {
|
336
|
+
expect { maid.cmd('echo .') }.not_to raise_error
|
327
337
|
end
|
328
338
|
end
|
329
339
|
end
|