maid 0.10.0.pre.alpha.2 → 0.10.0.pre.alpha.3
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/workflows/release.yml +1 -1
- data/.release-please-manifest.json +1 -1
- data/.rubocop_todo.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/Rakefile +1 -0
- data/lib/maid/maid.rb +10 -1
- data/lib/maid/tools.rb +61 -19
- data/lib/maid/version.rb +1 -1
- data/maid.gemspec +2 -1
- data/spec/lib/maid/maid_spec.rb +34 -7
- data/spec/lib/maid/tools_spec.rb +53 -0
- data/spec/spec_helper.rb +33 -0
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0be19c0367daaad7154c2649987ff99d97702a964ca2c6af5331fd876da16d7a
|
4
|
+
data.tar.gz: cb3598e65e48db7529b0584c041eb3f87fdbf66b57030d83f2ac981251de74a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d887908840f3369f2250226d888563444431f95cd662a50cdaddde49b0883bfb82958788516e9dc56d5329a8eefbdf470c761c1645d004cba2193c050bab60c2
|
7
|
+
data.tar.gz: a6349bb2e1d6e1b7dbd8358c7cf7e5f1955f2ae873d5b3286212c955e3ae11bb3ab743f3291f25c633bbda571caa0f0e90364a151f150789c2c8020698ab84ab
|
data/.rubocop_todo.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.10.0-alpha.3](https://github.com/maid/maid/compare/v0.10.0-alpha.2...v0.10.0-alpha.3) (2023-04-04)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* **maid:** improve `#watch` error message ([#287](https://github.com/maid/maid/issues/287)) ([0894cd6](https://github.com/maid/maid/commit/0894cd69665d5d9fe775b6b3df5a247f22f217d6))
|
9
|
+
* **tools:** add option to disable clobbering destination for `#move` ([#284](https://github.com/maid/maid/issues/284)) ([979413f](https://github.com/maid/maid/commit/979413fe284b61b43b33ba2169e72ed23043bcca))
|
10
|
+
|
3
11
|
## [0.10.0-alpha.2](https://github.com/maid/maid/compare/v0.10.0-alpha.1...v0.10.0-alpha.2) (2023-03-28)
|
4
12
|
|
5
13
|
|
data/Rakefile
CHANGED
data/lib/maid/maid.rb
CHANGED
@@ -88,6 +88,15 @@ class Maid::Maid
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def watch(path, options = {}, &block)
|
91
|
+
full_path = File.expand_path(path)
|
92
|
+
|
93
|
+
unless File.directory?(full_path)
|
94
|
+
message = "#{full_path} cannot be a file and it must exist in order to watch it"
|
95
|
+
|
96
|
+
warn(message)
|
97
|
+
raise message
|
98
|
+
end
|
99
|
+
|
91
100
|
@watches << ::Maid::Watch.new(self, path, options, &block)
|
92
101
|
end
|
93
102
|
|
@@ -140,7 +149,7 @@ class Maid::Maid
|
|
140
149
|
def default_trash_path
|
141
150
|
# TODO: Refactor module declaration so this can be `Platform`
|
142
151
|
if Maid::Platform.linux?
|
143
|
-
# See the [FreeDesktop.org Trash specification](
|
152
|
+
# See the [FreeDesktop.org Trash specification](https://archive.is/cXir4)
|
144
153
|
path = "#{XDG['DATA_HOME']}/Trash/files"
|
145
154
|
elsif Maid::Platform.osx?
|
146
155
|
path = File.expand_path('~/.Trash')
|
data/lib/maid/tools.rb
CHANGED
@@ -24,33 +24,50 @@ module Maid::Tools
|
|
24
24
|
# For showing deprecation notices
|
25
25
|
include Deprecated
|
26
26
|
|
27
|
-
#
|
27
|
+
# Moves `sources` file(s) to a `destination` directory.
|
28
28
|
#
|
29
29
|
# Movement is only allowed to directories that already exist. If your
|
30
30
|
# intention is to rename, see the `rename` method.
|
31
31
|
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
32
|
+
# @example Single source file
|
33
|
+
# move('~/Downloads/foo.zip', '~/Archive/Software/Mac OS X/')
|
34
|
+
#
|
35
|
+
# @example Multiple source files
|
36
|
+
# move(['~/Downloads/foo.zip', '~/Downloads/bar.zip'],
|
37
|
+
# '~/Archive/Software/Mac OS X/')
|
38
|
+
# move(dir('~/Downloads/*.zip'), '~/Archive/Software/Mac OS X/')
|
39
|
+
#
|
40
|
+
# @example Overwrite destination file if it already exists
|
41
|
+
# move('~/Downloads/foo.zip', '~/Archive/Software/Mac OS X/')
|
42
|
+
# move('~/Downloads/foo.zip', '~/Archive/Software/Mac OS X/', clobber:
|
43
|
+
# true)
|
44
|
+
#
|
45
|
+
# @example Skip file if it already exists at destination
|
46
|
+
# move('~/Downloads/foo.zip', '~/Archive/Software/Mac OS X/', clobber:
|
47
|
+
# false)
|
48
|
+
#
|
49
|
+
# @param sources [String, Array<String>] the paths to the source files to
|
50
|
+
# move
|
51
|
+
# @param destination_dir [String] path of the directory where to move
|
52
|
+
# `sources` to
|
53
|
+
# @param [Hash] kwargs the arguments to modify behaviour
|
54
|
+
# @option kwargs [Boolean] :clobber (true) `true` to overwrite destination
|
55
|
+
# file if it exists, `false` to skip moving file if it exists
|
56
|
+
def move(sources, destination_dir, clobber: true)
|
57
|
+
expanded_destination_dir = expand(destination_dir)
|
58
|
+
|
59
|
+
if File.directory?(expanded_destination_dir)
|
46
60
|
expand_all(sources).each do |source|
|
47
|
-
log("move #{sh_escape(source)} #{sh_escape(
|
48
|
-
|
61
|
+
log("move #{sh_escape(source)} #{sh_escape(expanded_destination_dir)}")
|
62
|
+
|
63
|
+
unless skip_move?(source, expanded_destination_dir, clobber)
|
64
|
+
FileUtils.mv(source, expanded_destination_dir, **@file_options)
|
65
|
+
end
|
49
66
|
end
|
50
67
|
else
|
51
68
|
# Unix `mv` warns about the target not being a directory with multiple sources. Maid checks the same.
|
52
|
-
warn("skipping move because #{sh_escape(
|
53
|
-
"directory (use 'mkdir' to create first, or use 'rename')")
|
69
|
+
warn("skipping move because #{sh_escape(expanded_destination_dir)} " \
|
70
|
+
"is not a directory (use 'mkdir' to create first, or use 'rename')")
|
54
71
|
end
|
55
72
|
end
|
56
73
|
|
@@ -1006,4 +1023,29 @@ module Maid::Tools
|
|
1006
1023
|
[]
|
1007
1024
|
end
|
1008
1025
|
end
|
1026
|
+
|
1027
|
+
# Predicate to tell whether the file should be skipped when moving.
|
1028
|
+
# @param source_path [String] the path to the source file
|
1029
|
+
# @param destination_dir [String] the path to the destination directory
|
1030
|
+
# @param clobber [Boolean] `true` to overwrite existing destination file,
|
1031
|
+
# `false` otherwise
|
1032
|
+
# @return [Boolean] whether to skip the move
|
1033
|
+
def skip_move?(source_path, destination_dir, clobber)
|
1034
|
+
destination_path = File.join(destination_dir, File.basename(source_path))
|
1035
|
+
|
1036
|
+
# if the destination file doesn't exist, we can move.
|
1037
|
+
return false unless File.exist?(destination_path)
|
1038
|
+
|
1039
|
+
log("#{destination_path} already exists")
|
1040
|
+
|
1041
|
+
# figure out whether to overwrite the existing destination file.
|
1042
|
+
if clobber
|
1043
|
+
log("clobbering enabled, moving #{File.basename(source_path)} anyway")
|
1044
|
+
|
1045
|
+
return false
|
1046
|
+
end
|
1047
|
+
log("clobbering disabled, skipping move for #{File.basename(source_path)}")
|
1048
|
+
|
1049
|
+
true
|
1050
|
+
end
|
1009
1051
|
end
|
data/lib/maid/version.rb
CHANGED
data/maid.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ['Benjamin Oakes', 'Coaxial']
|
9
9
|
s.email = ['hello@benjaminoakes.com', 'c+rubygems@64b.it']
|
10
|
-
s.license = '
|
10
|
+
s.license = 'GPL-2.0'
|
11
11
|
s.homepage = 'http://github.com/maid/maid'
|
12
12
|
s.summary = Maid::SUMMARY
|
13
13
|
s.description = s.summary
|
@@ -53,6 +53,7 @@ Gem::Specification.new do |s|
|
|
53
53
|
s.add_development_dependency('guard-rubocop')
|
54
54
|
s.add_development_dependency('pry-byebug')
|
55
55
|
s.add_development_dependency('rake', '~> 13.0.6')
|
56
|
+
s.add_development_dependency('rake-notes')
|
56
57
|
s.add_development_dependency('redcarpet', '~> 3.6.0') # Soft dependency of `yard`
|
57
58
|
s.add_development_dependency('rspec', '~> 3.12.0')
|
58
59
|
s.add_development_dependency('rubocop')
|
data/spec/lib/maid/maid_spec.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module Maid
|
4
|
-
describe Maid do
|
4
|
+
describe Maid, fakefs: true do
|
5
5
|
let(:logger) { instance_spy('Logger') }
|
6
6
|
|
7
7
|
before do
|
8
8
|
allow(Logger).to receive(:new).and_return(logger)
|
9
|
-
allow(FileUtils).to receive(:mkdir_p)
|
10
9
|
end
|
11
10
|
|
12
11
|
describe '.new' do
|
@@ -33,8 +32,11 @@ module Maid
|
|
33
32
|
end
|
34
33
|
|
35
34
|
it 'makes the log directory in case it does not exist' do
|
36
|
-
expect(
|
35
|
+
expect(File.exist?('/home/username/log')).to be false
|
36
|
+
|
37
37
|
Maid.new(log_device: '/home/username/log/maid.log')
|
38
|
+
|
39
|
+
expect(File.exist?('/home/username/log')).to be true
|
38
40
|
end
|
39
41
|
|
40
42
|
it 'takes a logger object during intialization' do
|
@@ -58,8 +60,9 @@ module Maid
|
|
58
60
|
|
59
61
|
it 'set the trash to the correct default path' do
|
60
62
|
trash_path = "#{@home}/.local/share/Trash/files/"
|
61
|
-
|
63
|
+
|
62
64
|
maid = Maid.new
|
65
|
+
|
63
66
|
expect(maid.trash_path).to eq(trash_path)
|
64
67
|
end
|
65
68
|
end
|
@@ -71,7 +74,7 @@ module Maid
|
|
71
74
|
|
72
75
|
it 'sets the trash to the correct default path' do
|
73
76
|
trash_path = "#{@home}/.Trash/"
|
74
|
-
|
77
|
+
|
75
78
|
maid = Maid.new
|
76
79
|
expect(maid.trash_path).to eq(trash_path)
|
77
80
|
end
|
@@ -86,8 +89,9 @@ module Maid
|
|
86
89
|
|
87
90
|
it 'sets the trash to the given path, if provided' do
|
88
91
|
trash_path = '/home/username/tmp/my_trash/'
|
89
|
-
|
92
|
+
|
90
93
|
maid = Maid.new(trash_path: trash_path)
|
94
|
+
|
91
95
|
expect(maid.trash_path).not_to be_nil
|
92
96
|
expect(maid.trash_path).to eq(trash_path)
|
93
97
|
end
|
@@ -198,6 +202,7 @@ module Maid
|
|
198
202
|
before do
|
199
203
|
allow(Listen).to receive(:to)
|
200
204
|
allow(Listen).to receive(:start)
|
205
|
+
FileUtils.mkdir_p('watch_dir')
|
201
206
|
@maid = Maid.new
|
202
207
|
end
|
203
208
|
|
@@ -215,6 +220,8 @@ module Maid
|
|
215
220
|
# FIXME: Example is too long, shouldn't need the rubocop::disable
|
216
221
|
it 'accepts a hash of options and passes them to Listen' do # rubocop:disable RSpec/ExampleLength
|
217
222
|
hash = { some: :options }
|
223
|
+
FileUtils.mkdir_p('some_dir')
|
224
|
+
|
218
225
|
@maid.watch('some_dir', hash) do
|
219
226
|
rule 'test' do
|
220
227
|
end
|
@@ -232,9 +239,29 @@ module Maid
|
|
232
239
|
|
233
240
|
@maid.watches.last.run
|
234
241
|
end
|
242
|
+
|
243
|
+
context('with a non-existent directory') do
|
244
|
+
let(:maid) { Maid.new }
|
245
|
+
|
246
|
+
it 'raises with an intelligible message' do
|
247
|
+
expect { maid.watch('/doesnt_exist/') }.to raise_error(/file.*exist/)
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'logs an intelligible message' do
|
251
|
+
begin
|
252
|
+
maid.watch('/doesnt_exist')
|
253
|
+
# Suppressing the exception is fine, because we just want to test
|
254
|
+
# that the message is logged when it throws and the test above
|
255
|
+
# checks that the exception is raised.
|
256
|
+
rescue StandardError # rubocop:disable Lint/SuppressedException
|
257
|
+
end
|
258
|
+
|
259
|
+
expect(logger).to have_received(:warn).with(/file.*exist/)
|
260
|
+
end
|
261
|
+
end
|
235
262
|
end
|
236
263
|
|
237
|
-
describe '#repeat' do
|
264
|
+
describe '#repeat', fake_zoneinfo: true do
|
238
265
|
before do
|
239
266
|
@maid = Maid.new
|
240
267
|
end
|
data/spec/lib/maid/tools_spec.rb
CHANGED
@@ -73,6 +73,59 @@ module Maid
|
|
73
73
|
@maid.move([@src_file, another_file], @dst_dir)
|
74
74
|
end
|
75
75
|
end
|
76
|
+
|
77
|
+
context 'when the destination file already exists' do
|
78
|
+
let(:src_file) { '/tmp/src/test_file' }
|
79
|
+
let(:dst_dir) { '/tmp/dest/' }
|
80
|
+
let(:dst_file) { File.join(dst_dir, File.basename(src_file)) }
|
81
|
+
let(:maid) { Maid.new(logger: @logger) }
|
82
|
+
|
83
|
+
before do
|
84
|
+
FileUtils.mkdir_p(File.dirname(src_file))
|
85
|
+
FileUtils.mkdir_p(dst_dir)
|
86
|
+
FileUtils.touch(src_file)
|
87
|
+
FileUtils.touch(dst_file)
|
88
|
+
end
|
89
|
+
|
90
|
+
after do
|
91
|
+
FileUtils.rm_rf([src_file, dst_file])
|
92
|
+
end
|
93
|
+
|
94
|
+
context 'by default' do
|
95
|
+
let!(:original_mtime) { File.stat(dst_file).mtime }
|
96
|
+
|
97
|
+
before do
|
98
|
+
maid.move(src_file, dst_dir)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'logs an info message' do
|
102
|
+
expect(@logger).to have_received(:info).with(/already/)
|
103
|
+
expect(@logger).to have_received(:info).with(/anyway/)
|
104
|
+
expect(@logger).not_to have_received(:info).with(/skipping/)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'overwrites destination' do
|
108
|
+
expect(File.stat(dst_file).mtime).not_to eq(original_mtime)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'when clobber: false' do
|
113
|
+
let!(:original_mtime) { File.stat(dst_file).mtime }
|
114
|
+
|
115
|
+
before do
|
116
|
+
maid.move(src_file, dst_dir, clobber: false)
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'logs an info message' do
|
120
|
+
expect(@logger).not_to have_received(:info).with(/anyway/)
|
121
|
+
expect(@logger).to have_received(:info).with(/skipping/)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "doesn't overwrite the destination file" do
|
125
|
+
expect(File.stat(dst_file).mtime).to eq(original_mtime)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
76
129
|
end
|
77
130
|
|
78
131
|
describe '#rename' do
|
data/spec/spec_helper.rb
CHANGED
@@ -25,6 +25,39 @@ RSpec.configure do |config|
|
|
25
25
|
end
|
26
26
|
config.include(FakeFS::SpecHelpers, fakefs: true)
|
27
27
|
config.raise_errors_for_deprecations!
|
28
|
+
|
29
|
+
config.filter_run focus: true
|
30
|
+
config.run_all_when_everything_filtered = true
|
31
|
+
|
32
|
+
# NOTE: If a test fails because ENOENT /usr/share/zoneinfo/Africa/Abidjan,
|
33
|
+
# add `fake_zoneinfo: true` to the describe:
|
34
|
+
# `describe(MyClass, fake_zoneinfo: true do`
|
35
|
+
config.before(:context, fake_zoneinfo: true) do
|
36
|
+
# Rufus needs zoneinfo data to run, but when using FakeFS,
|
37
|
+
# /usr/share/zoneinfo doesn't exist on the FakeFS.
|
38
|
+
# On Linux, we just have to FakeFS::FileSystem.clone the directory and it
|
39
|
+
# just works.
|
40
|
+
# OSX is, of course, special. /usr/share/zoneinfo is a symlink on that
|
41
|
+
# platform, and `.clone` doesn't seem to be following symlinks. Instead, we
|
42
|
+
# have to copy the zoneinfo data to a temporary directory on the live
|
43
|
+
# filesystem, enable the FakeFS, clone that temporary directory, create
|
44
|
+
# /usr/share/zoneinfo onto the FakeFS, and finally copy the files into it.
|
45
|
+
# This way, they're available in the FakeFS where Rufus can find them.
|
46
|
+
include FakeFS::SpecHelpers
|
47
|
+
FakeFS.activate!
|
48
|
+
|
49
|
+
if Maid::Platform.osx?
|
50
|
+
FakeFS.deactivate!
|
51
|
+
FileUtils.mkdir_p('/tmp/')
|
52
|
+
FileUtils.cp_r('/usr/share/zoneinfo/', '/tmp/')
|
53
|
+
FakeFS.activate!
|
54
|
+
FakeFS::FileSystem.clone('/tmp/zoneinfo/')
|
55
|
+
FileUtils.mkdir_p('/usr/share/')
|
56
|
+
FileUtils.cp_r('/tmp/zoneinfo/', '/usr/share/')
|
57
|
+
end
|
58
|
+
|
59
|
+
FakeFS::FileSystem.clone('/usr/share/zoneinfo') if Maid::Platform.linux?
|
60
|
+
end
|
28
61
|
end
|
29
62
|
|
30
63
|
RSpec::Matchers.define :have_deprecated_method do |expected|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.0.pre.alpha.
|
4
|
+
version: 0.10.0.pre.alpha.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin Oakes
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-
|
12
|
+
date: 2023-04-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: deprecated
|
@@ -295,6 +295,20 @@ dependencies:
|
|
295
295
|
- - "~>"
|
296
296
|
- !ruby/object:Gem::Version
|
297
297
|
version: 13.0.6
|
298
|
+
- !ruby/object:Gem::Dependency
|
299
|
+
name: rake-notes
|
300
|
+
requirement: !ruby/object:Gem::Requirement
|
301
|
+
requirements:
|
302
|
+
- - ">="
|
303
|
+
- !ruby/object:Gem::Version
|
304
|
+
version: '0'
|
305
|
+
type: :development
|
306
|
+
prerelease: false
|
307
|
+
version_requirements: !ruby/object:Gem::Requirement
|
308
|
+
requirements:
|
309
|
+
- - ">="
|
310
|
+
- !ruby/object:Gem::Version
|
311
|
+
version: '0'
|
298
312
|
- !ruby/object:Gem::Dependency
|
299
313
|
name: redcarpet
|
300
314
|
requirement: !ruby/object:Gem::Requirement
|
@@ -518,7 +532,7 @@ files:
|
|
518
532
|
- spec/spec_helper.rb
|
519
533
|
homepage: http://github.com/maid/maid
|
520
534
|
licenses:
|
521
|
-
-
|
535
|
+
- GPL-2.0
|
522
536
|
metadata:
|
523
537
|
bug_tracker_uri: https://github.com/maid/maid/issues
|
524
538
|
changelog_uri: https://github.com/maid/maid/blob/master/CHANGELOG.md
|
@@ -542,7 +556,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
542
556
|
- !ruby/object:Gem::Version
|
543
557
|
version: 1.3.1
|
544
558
|
requirements: []
|
545
|
-
rubygems_version: 3.
|
559
|
+
rubygems_version: 3.4.6
|
546
560
|
signing_key:
|
547
561
|
specification_version: 4
|
548
562
|
summary: Be lazy. Let Maid clean up after you, based on rules you define. Think of
|