maid 0.10.0.pre.alpha.2 → 0.10.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8d0fa40b9069dd973a12021c729407e1f98719ea96e8ede17aff4426cd8d9eb
4
- data.tar.gz: ed334d76e2cdc9ba723e600a6f371efab241ea24c080e7009425dee9a99d52f4
3
+ metadata.gz: 386fffc38404ce847ae5650376f84be904056ad5d6acd86cea9311cedade94c1
4
+ data.tar.gz: 49c5f4a3b21d583d2edd09d73d862c495c2e8d5eb36c510401bc5ff216316c57
5
5
  SHA512:
6
- metadata.gz: 4be4e2a2771566d670b9b7a5d5966c334e3ca58c7c204dab7182654821b47b6076dc2ceb0e880de1a2e6966f110fee7422d289ffa058c9ba6861287afd2f60be
7
- data.tar.gz: 124d6e7f02282b4772b4a849acfad62efdc3277c08ea0696cd32b57672e199104bf314e53b609c47960e026b2073f4aba55d441de5061600fa9f499f9e90ceae
6
+ metadata.gz: 334f18ddb7a90a62a6b3c6136930c1724e08358ab7fb0dcca7011570b1b93bffa24958a07756c52f303f617aeea8cc02142d4d6163b75cfeaad3b71c32aeb34e
7
+ data.tar.gz: 397ca948024144b6beaa7f7139df13a66ff84b2240a3ffd8a716d67286334f5e3da6520e25e6d5df2ba8a3e5f8f417ec64fd29e42f4a955ef5fb24471b3a7dc3
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+ title: "<Short description of the issue>"
5
+ labels: bug
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **👋 Before reporting a bug, please make sure you're running the latest available version of maid (`gem install maid`).**
11
+
12
+ **👋 If you're using Ruby 2.7+, please make sure you're running maid v0.10.0+ (`gem install maid --pre`)**
13
+
14
+ **Describe the bug**
15
+ A clear and concise description of what the bug is.
16
+
17
+ **To Reproduce**
18
+ Steps to trigger the issue.
19
+
20
+ **Expected behavior**
21
+ A clear and concise description of what you expected to happen.
22
+
23
+ **Logs**
24
+ If applicable, add logs to help explain your problem. You can find the logs at `~/.maid/maid.log`.
25
+
26
+ **Environment (please complete the information):**
27
+ - Maid version (`maid --version`): `<enter the command's output here>`
28
+ - OS, distribution (Linux), and version: <examples: OSX 12.0.0/Linux Mint 20.3>
29
+ - Ruby version (`ruby --version`): `<enter the command's output here>`
30
+
31
+ **Minimal `rules.rb` to reproduce the issue:**
32
+ ```ruby
33
+ # Rule(s)
34
+ ```
35
+
36
+ **Additional context**
37
+ Add any other context about the problem here.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+ title: ''
5
+ labels: feature
6
+ assignees: ''
7
+
8
+ ---
9
+
10
+ **Is your feature request related to a problem? Please describe.**
11
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
+
13
+ **Describe the solution you'd like**
14
+ A clear and concise description of what you want to happen.
15
+
16
+ **Describe alternatives you've considered**
17
+ A clear and concise description of any alternative solutions or features you've considered.
18
+
19
+ **Additional context**
20
+ Add any other context or screenshots about the feature request here.
@@ -38,8 +38,8 @@ jobs:
38
38
  token: ${{ secrets.BOT_GH_TOKEN }}
39
39
  # Uncomment for pre-releases, see
40
40
  # https://github.com/maid/maid/wiki/Release-Process
41
- prerelease: true
42
- release-as: v0.10.0-alpha.2
41
+ # prerelease: true
42
+ # release-as: v0.10.0-alpha.3
43
43
  - name: Set up Ruby
44
44
  uses: ruby/setup-ruby@v1
45
45
  with:
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "0.10.0-alpha.2"
2
+ ".": "0.10.0"
3
3
  }
data/.rubocop_todo.yml CHANGED
@@ -66,7 +66,7 @@ Metrics/MethodLength:
66
66
  # Offense count: 4
67
67
  # Configuration parameters: CountComments, CountAsOne.
68
68
  Metrics/ModuleLength:
69
- Max: 711
69
+ Max: 753
70
70
 
71
71
  # Offense count: 2
72
72
  # Configuration parameters: AllowedMethods, AllowedPatterns.
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.0](https://github.com/maid/maid/compare/v0.10.0-alpha.3...v0.10.0) (2023-05-01)
4
+
5
+
6
+ ### Miscellaneous Chores
7
+
8
+ * release 0.10.0 ([1f35afd](https://github.com/maid/maid/commit/1f35afd2030bd74a5175ced5cd9766273162dea4))
9
+
10
+ ## [0.10.0-alpha.3](https://github.com/maid/maid/compare/v0.10.0-alpha.2...v0.10.0-alpha.3) (2023-04-04)
11
+
12
+
13
+ ### Features
14
+
15
+ * **maid:** improve `#watch` error message ([#287](https://github.com/maid/maid/issues/287)) ([0894cd6](https://github.com/maid/maid/commit/0894cd69665d5d9fe775b6b3df5a247f22f217d6))
16
+ * **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))
17
+
3
18
  ## [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
19
 
5
20
 
data/Rakefile CHANGED
@@ -2,6 +2,7 @@ require 'bundler'
2
2
  require 'rake'
3
3
  require 'rspec/core/rake_task'
4
4
  require 'yard'
5
+ require 'rake/notes/rake_task'
5
6
 
6
7
  task default: :spec
7
8
 
data/SECURITY.md ADDED
@@ -0,0 +1,29 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ ### Maid gem
6
+ | Version | Supported |
7
+ | ------------ | ------------------ |
8
+ | >= 0.10.0 | :heavy_check_mark: |
9
+ | 0.7.0 | :heavy_check_mark: |
10
+ | < 0.7.0 | :x: |
11
+
12
+ ### Ruby
13
+ | Version | Supported |
14
+ | ------------ | ------------------ |
15
+ | >= 3.0 | :heavy_check_mark: |
16
+ | 2.7 | :warning: |
17
+ | <= 2.6 | :x: |
18
+
19
+ > :warning: Ruby 2.7 became EOL on 2023-03-31 and might be dropped in the near
20
+ > future. We strongly recommend using Ruby 3+.
21
+
22
+ ## Reporting a Vulnerability
23
+
24
+ To report a vulnerability, please open an issue. We will investigate and
25
+ respond in a timely manner.
26
+
27
+ If the vulnerability is accepted, we will work on a patch. Bear in mind that
28
+ this is a community effort and we can't commit to specific timeframes other
29
+ than best effort.
@@ -0,0 +1,42 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://nominatim.openstreetmap.org/reverse?accept-language=en&addressdetails=1&format=json&lat=-33.85608611111111&lon=151.219925
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx
23
+ Date:
24
+ - Fri, 21 Apr 2023 12:28:49 GMT
25
+ Content-Type:
26
+ - application/json; charset=UTF-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Keep-Alive:
32
+ - timeout=20
33
+ Access-Control-Allow-Origin:
34
+ - "*"
35
+ Access-Control-Allow-Methods:
36
+ - OPTIONS,GET
37
+ body:
38
+ encoding: ASCII-8BIT
39
+ string: !binary |-
40
+ eyJwbGFjZV9pZCI6Mjk4ODA4MzUxLCJsaWNlbmNlIjoiRGF0YSDCqSBPcGVuU3RyZWV0TWFwIGNvbnRyaWJ1dG9ycywgT0RiTCAxLjAuIGh0dHBzOi8vb3NtLm9yZy9jb3B5cmlnaHQiLCJvc21fdHlwZSI6InJlbGF0aW9uIiwib3NtX2lkIjo5NTk5NzIzLCJsYXQiOiItMzMuODU2Mzc3NjUiLCJsb24iOiIxNTEuMjE1NTcxODMwNzQ1MDYiLCJkaXNwbGF5X25hbWUiOiJOb3J0aGVybiBCb2FyZHdhbGssIFF1YXkgUXVhcnRlciwgU3lkbmV5LCBDb3VuY2lsIG9mIHRoZSBDaXR5IG9mIFN5ZG5leSwgTmV3IFNvdXRoIFdhbGVzLCAyMDAwLCBBdXN0cmFsaWEiLCJhZGRyZXNzIjp7InJvYWQiOiJOb3J0aGVybiBCb2FyZHdhbGsiLCJuZWlnaGJvdXJob29kIjoiUXVheSBRdWFydGVyIiwic3VidXJiIjoiU3lkbmV5IiwiY2l0eSI6IlN5ZG5leSIsIm11bmljaXBhbGl0eSI6IkNvdW5jaWwgb2YgdGhlIENpdHkgb2YgU3lkbmV5Iiwic3RhdGUiOiJOZXcgU291dGggV2FsZXMiLCJJU08zMTY2LTItbHZsNCI6IkFVLU5TVyIsInBvc3Rjb2RlIjoiMjAwMCIsImNvdW50cnkiOiJBdXN0cmFsaWEiLCJjb3VudHJ5X2NvZGUiOiJhdSJ9LCJib3VuZGluZ2JveCI6WyItMzMuODU2Njc0MiIsIi0zMy44NTYxMDk2IiwiMTUxLjIxNDU1NzkiLCIxNTEuMjE1OTA4NCJdfQ==
41
+ recorded_at: Fri, 21 Apr 2023 12:28:49 GMT
42
+ recorded_with: VCR 6.1.0
@@ -0,0 +1,42 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://nominatim.openstreetmap.org/reverse?accept-language=en&addressdetails=1&format=json&lat=-33.85608611111111&lon=151.219925
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - Ruby
16
+ response:
17
+ status:
18
+ code: 200
19
+ message: OK
20
+ headers:
21
+ Server:
22
+ - nginx
23
+ Date:
24
+ - Fri, 21 Apr 2023 12:29:51 GMT
25
+ Content-Type:
26
+ - application/json; charset=UTF-8
27
+ Transfer-Encoding:
28
+ - chunked
29
+ Connection:
30
+ - keep-alive
31
+ Keep-Alive:
32
+ - timeout=20
33
+ Access-Control-Allow-Origin:
34
+ - "*"
35
+ Access-Control-Allow-Methods:
36
+ - OPTIONS,GET
37
+ body:
38
+ encoding: ASCII-8BIT
39
+ string: !binary |-
40
+ eyJwbGFjZV9pZCI6Mjk4ODA4MzUxLCJsaWNlbmNlIjoiRGF0YSDCqSBPcGVuU3RyZWV0TWFwIGNvbnRyaWJ1dG9ycywgT0RiTCAxLjAuIGh0dHBzOi8vb3NtLm9yZy9jb3B5cmlnaHQiLCJvc21fdHlwZSI6InJlbGF0aW9uIiwib3NtX2lkIjo5NTk5NzIzLCJsYXQiOiItMzMuODU2Mzc3NjUiLCJsb24iOiIxNTEuMjE1NTcxODMwNzQ1MDYiLCJkaXNwbGF5X25hbWUiOiJOb3J0aGVybiBCb2FyZHdhbGssIFF1YXkgUXVhcnRlciwgU3lkbmV5LCBDb3VuY2lsIG9mIHRoZSBDaXR5IG9mIFN5ZG5leSwgTmV3IFNvdXRoIFdhbGVzLCAyMDAwLCBBdXN0cmFsaWEiLCJhZGRyZXNzIjp7InJvYWQiOiJOb3J0aGVybiBCb2FyZHdhbGsiLCJuZWlnaGJvdXJob29kIjoiUXVheSBRdWFydGVyIiwic3VidXJiIjoiU3lkbmV5IiwiY2l0eSI6IlN5ZG5leSIsIm11bmljaXBhbGl0eSI6IkNvdW5jaWwgb2YgdGhlIENpdHkgb2YgU3lkbmV5Iiwic3RhdGUiOiJOZXcgU291dGggV2FsZXMiLCJJU08zMTY2LTItbHZsNCI6IkFVLU5TVyIsInBvc3Rjb2RlIjoiMjAwMCIsImNvdW50cnkiOiJBdXN0cmFsaWEiLCJjb3VudHJ5X2NvZGUiOiJhdSJ9LCJib3VuZGluZ2JveCI6WyItMzMuODU2Njc0MiIsIi0zMy44NTYxMDk2IiwiMTUxLjIxNDU1NzkiLCIxNTEuMjE1OTA4NCJdfQ==
41
+ recorded_at: Fri, 21 Apr 2023 12:29:51 GMT
42
+ recorded_with: VCR 6.1.0
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](http://www.ramendik.ru/docs/trashspec.html)
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
- # Move `sources` to a `destination` directory.
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
- # ## Examples
33
- #
34
- # Single path:
35
- #
36
- # move('~/Downloads/foo.zip', '~/Archive/Software/Mac OS X/')
37
- #
38
- # Multiple paths:
39
- #
40
- # move(['~/Downloads/foo.zip', '~/Downloads/bar.zip'], '~/Archive/Software/Mac OS X/')
41
- # move(dir('~/Downloads/*.zip'), '~/Archive/Software/Mac OS X/')
42
- def move(sources, destination)
43
- expanded_destination = expand(destination)
44
-
45
- if File.directory?(expanded_destination)
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(expanded_destination)}")
48
- FileUtils.mv(source, expanded_destination, **@file_options)
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(expanded_destination)} is not a" \
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
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Maid
4
- VERSION = '0.10.0-alpha.2'
4
+ VERSION = '0.10.0'
5
5
  SUMMARY = 'Be lazy. Let Maid clean up after you, based on rules you define. ' \
6
6
  'Think of it as "Hazel for hackers".'
7
7
  end
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 = 'GPLv2'
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')
@@ -60,6 +61,8 @@ Gem::Specification.new do |s|
60
61
  s.add_development_dependency('rubocop-rspec')
61
62
  s.add_development_dependency('simplecov')
62
63
  s.add_development_dependency('timecop', '~> 0.9.6')
64
+ s.add_development_dependency('vcr', '~> 6.1.0')
65
+ s.add_development_dependency('webmock', '~> 3.18.1')
63
66
  s.add_development_dependency('yard', '>= 0.9.11')
64
67
 
65
68
  # In Vagrant, polling won't cross over the OS boundary if you develop in the host OS but run your tests in the
@@ -95,7 +95,7 @@ describe 'Dependency expectations' do
95
95
  end
96
96
  end
97
97
 
98
- describe Geocoder do
98
+ describe Geocoder, vcr: { record: :new_episodes } do
99
99
  it 'translates latitude and longitude into street addresses' do
100
100
  city = Geocoder.search('-33.85608611111111,151.219925').map { |location| location.city }.uniq.compact
101
101
  expect(city).to eq(['Sydney'])
@@ -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(FileUtils).to receive(:mkdir_p).with('/home/username/log')
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
- expect(FileUtils).to receive(:mkdir_p).with(trash_path).once
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
- expect(FileUtils).to receive(:mkdir_p).with(trash_path).once
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
- expect(FileUtils).to receive(:mkdir_p).with(trash_path).once
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
@@ -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
@@ -670,7 +723,7 @@ module Maid
670
723
 
671
724
  describe '#location_city' do
672
725
  context 'given a JPEG image' do
673
- it 'reports the known location' do
726
+ it 'reports the known location', vcr: { record: :new_episodes } do
674
727
  sydney_path = File.join(file_fixtures_path, 'sydney.jpg')
675
728
  expect(@maid.location_city(sydney_path)).to eq('Sydney, New South Wales, AU')
676
729
  end
data/spec/spec_helper.rb CHANGED
@@ -16,6 +16,7 @@ require 'rspec'
16
16
  require 'timecop'
17
17
  require 'fakefs/spec_helpers'
18
18
  require 'pry-byebug'
19
+ require 'vcr'
19
20
 
20
21
  require 'maid'
21
22
 
@@ -25,6 +26,39 @@ RSpec.configure do |config|
25
26
  end
26
27
  config.include(FakeFS::SpecHelpers, fakefs: true)
27
28
  config.raise_errors_for_deprecations!
29
+
30
+ config.filter_run focus: true
31
+ config.run_all_when_everything_filtered = true
32
+
33
+ # NOTE: If a test fails because ENOENT /usr/share/zoneinfo/Africa/Abidjan,
34
+ # add `fake_zoneinfo: true` to the describe:
35
+ # `describe(MyClass, fake_zoneinfo: true do`
36
+ config.before(:context, fake_zoneinfo: true) do
37
+ # Rufus needs zoneinfo data to run, but when using FakeFS,
38
+ # /usr/share/zoneinfo doesn't exist on the FakeFS.
39
+ # On Linux, we just have to FakeFS::FileSystem.clone the directory and it
40
+ # just works.
41
+ # OSX is, of course, special. /usr/share/zoneinfo is a symlink on that
42
+ # platform, and `.clone` doesn't seem to be following symlinks. Instead, we
43
+ # have to copy the zoneinfo data to a temporary directory on the live
44
+ # filesystem, enable the FakeFS, clone that temporary directory, create
45
+ # /usr/share/zoneinfo onto the FakeFS, and finally copy the files into it.
46
+ # This way, they're available in the FakeFS where Rufus can find them.
47
+ include FakeFS::SpecHelpers
48
+ FakeFS.activate!
49
+
50
+ if Maid::Platform.osx?
51
+ FakeFS.deactivate!
52
+ FileUtils.mkdir_p('/tmp/')
53
+ FileUtils.cp_r('/usr/share/zoneinfo/', '/tmp/')
54
+ FakeFS.activate!
55
+ FakeFS::FileSystem.clone('/tmp/zoneinfo/')
56
+ FileUtils.mkdir_p('/usr/share/')
57
+ FileUtils.cp_r('/tmp/zoneinfo/', '/usr/share/')
58
+ end
59
+
60
+ FakeFS::FileSystem.clone('/usr/share/zoneinfo') if Maid::Platform.linux?
61
+ end
28
62
  end
29
63
 
30
64
  RSpec::Matchers.define :have_deprecated_method do |expected|
@@ -32,3 +66,10 @@ RSpec::Matchers.define :have_deprecated_method do |expected|
32
66
  expect(actual).to receive(:__deprecated_run_action__).with(expected, anything) # rubocop:disable RSpec/MessageSpies
33
67
  end
34
68
  end
69
+
70
+ VCR.configure do |config|
71
+ config.cassette_library_dir = 'fixtures/vcr_cassettes'
72
+ config.hook_into :webmock
73
+ # For autogenerating VCR cassettes' names based on the tests' metadata
74
+ config.configure_rspec_metadata!
75
+ end
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.2
4
+ version: 0.10.0
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-03-31 00:00:00.000000000 Z
12
+ date: 2023-05-01 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
@@ -393,6 +407,34 @@ dependencies:
393
407
  - - "~>"
394
408
  - !ruby/object:Gem::Version
395
409
  version: 0.9.6
410
+ - !ruby/object:Gem::Dependency
411
+ name: vcr
412
+ requirement: !ruby/object:Gem::Requirement
413
+ requirements:
414
+ - - "~>"
415
+ - !ruby/object:Gem::Version
416
+ version: 6.1.0
417
+ type: :development
418
+ prerelease: false
419
+ version_requirements: !ruby/object:Gem::Requirement
420
+ requirements:
421
+ - - "~>"
422
+ - !ruby/object:Gem::Version
423
+ version: 6.1.0
424
+ - !ruby/object:Gem::Dependency
425
+ name: webmock
426
+ requirement: !ruby/object:Gem::Requirement
427
+ requirements:
428
+ - - "~>"
429
+ - !ruby/object:Gem::Version
430
+ version: 3.18.1
431
+ type: :development
432
+ prerelease: false
433
+ version_requirements: !ruby/object:Gem::Requirement
434
+ requirements:
435
+ - - "~>"
436
+ - !ruby/object:Gem::Version
437
+ version: 3.18.1
396
438
  - !ruby/object:Gem::Dependency
397
439
  name: yard
398
440
  requirement: !ruby/object:Gem::Requirement
@@ -447,6 +489,8 @@ extra_rdoc_files: []
447
489
  files:
448
490
  - ".act-env"
449
491
  - ".act-secrets.example"
492
+ - ".github/ISSUE_TEMPLATE/bug_report.md"
493
+ - ".github/ISSUE_TEMPLATE/feature_request.md"
450
494
  - ".github/workflows/coverage.yml"
451
495
  - ".github/workflows/lint.yml"
452
496
  - ".github/workflows/release.yml"
@@ -468,8 +512,11 @@ files:
468
512
  - LICENSE
469
513
  - README.md
470
514
  - Rakefile
515
+ - SECURITY.md
471
516
  - Vagrantfile
472
517
  - bin/maid
518
+ - fixtures/vcr_cassettes/Dependency_expectations/Geocoder/translates_latitude_and_longitude_into_street_addresses.yml
519
+ - fixtures/vcr_cassettes/Maid_Tools/_location_city/given_a_JPEG_image/reports_the_known_location.yml
473
520
  - lib/maid.rb
474
521
  - lib/maid/app.rb
475
522
  - lib/maid/downloading.rb
@@ -518,7 +565,7 @@ files:
518
565
  - spec/spec_helper.rb
519
566
  homepage: http://github.com/maid/maid
520
567
  licenses:
521
- - GPLv2
568
+ - GPL-2.0
522
569
  metadata:
523
570
  bug_tracker_uri: https://github.com/maid/maid/issues
524
571
  changelog_uri: https://github.com/maid/maid/blob/master/CHANGELOG.md
@@ -538,11 +585,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
538
585
  version: 2.7.0
539
586
  required_rubygems_version: !ruby/object:Gem::Requirement
540
587
  requirements:
541
- - - ">"
588
+ - - ">="
542
589
  - !ruby/object:Gem::Version
543
- version: 1.3.1
590
+ version: '0'
544
591
  requirements: []
545
- rubygems_version: 3.3.26
592
+ rubygems_version: 3.4.6
546
593
  signing_key:
547
594
  specification_version: 4
548
595
  summary: Be lazy. Let Maid clean up after you, based on rules you define. Think of