imap-backup 14.4.1 → 14.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/bin/imap-backup +2 -2
  3. data/docs/api.md +20 -0
  4. data/docs/development.md +18 -7
  5. data/lib/imap/backup/account/backup.rb +6 -3
  6. data/lib/imap/backup/account/backup_folders.rb +6 -3
  7. data/lib/imap/backup/account/client_factory.rb +3 -2
  8. data/lib/imap/backup/account/folder.rb +10 -9
  9. data/lib/imap/backup/account/folder_backup.rb +5 -4
  10. data/lib/imap/backup/account/folder_ensurer.rb +5 -2
  11. data/lib/imap/backup/account/local_only_folder_deleter.rb +7 -3
  12. data/lib/imap/backup/account/restore.rb +5 -2
  13. data/lib/imap/backup/account/serialized_folders.rb +3 -2
  14. data/lib/imap/backup/account.rb +85 -0
  15. data/lib/imap/backup/cli/backup.rb +14 -12
  16. data/lib/imap/backup/cli/folder_enumerator.rb +5 -5
  17. data/lib/imap/backup/cli/local/check.rb +4 -2
  18. data/lib/imap/backup/cli/local.rb +50 -49
  19. data/lib/imap/backup/cli/remote.rb +46 -46
  20. data/lib/imap/backup/cli/restore.rb +5 -3
  21. data/lib/imap/backup/cli/setup.rb +4 -2
  22. data/lib/imap/backup/cli/single/backup.rb +3 -3
  23. data/lib/imap/backup/cli/stats.rb +54 -52
  24. data/lib/imap/backup/cli/transfer.rb +93 -93
  25. data/lib/imap/backup/cli/utils.rb +28 -28
  26. data/lib/imap/backup/cli.rb +12 -0
  27. data/lib/imap/backup/client/default.rb +5 -5
  28. data/lib/imap/backup/configuration.rb +5 -4
  29. data/lib/imap/backup/downloader.rb +6 -14
  30. data/lib/imap/backup/email/mboxrd/message.rb +2 -3
  31. data/lib/imap/backup/file_mode.rb +4 -2
  32. data/lib/imap/backup/flag_refresher.rb +3 -3
  33. data/lib/imap/backup/local_only_message_deleter.rb +5 -3
  34. data/lib/imap/backup/migrator.rb +6 -4
  35. data/lib/imap/backup/mirror/map.rb +3 -3
  36. data/lib/imap/backup/mirror.rb +5 -5
  37. data/lib/imap/backup/serializer/appender.rb +7 -4
  38. data/lib/imap/backup/serializer/delayed_metadata_serializer.rb +15 -2
  39. data/lib/imap/backup/serializer/directory.rb +12 -3
  40. data/lib/imap/backup/serializer/folder_maker.rb +12 -4
  41. data/lib/imap/backup/serializer/imap.rb +5 -1
  42. data/lib/imap/backup/serializer/integrity_checker.rb +10 -3
  43. data/lib/imap/backup/serializer/mbox.rb +2 -1
  44. data/lib/imap/backup/serializer/message.rb +10 -18
  45. data/lib/imap/backup/serializer/permission_checker.rb +5 -3
  46. data/lib/imap/backup/serializer/transaction.rb +4 -1
  47. data/lib/imap/backup/serializer/unused_name_finder.rb +4 -2
  48. data/lib/imap/backup/serializer/version2_migrator.rb +2 -2
  49. data/lib/imap/backup/serializer.rb +5 -0
  50. data/lib/imap/backup/setup/account/header.rb +3 -3
  51. data/lib/imap/backup/setup/account.rb +6 -6
  52. data/lib/imap/backup/setup/asker.rb +6 -4
  53. data/lib/imap/backup/setup/backup_path.rb +3 -4
  54. data/lib/imap/backup/setup/connection_tester.rb +4 -2
  55. data/lib/imap/backup/setup/{email.rb → email_changer.rb} +4 -4
  56. data/lib/imap/backup/setup/folder_chooser.rb +2 -2
  57. data/lib/imap/backup/setup/global_options/download_strategy_chooser.rb +2 -2
  58. data/lib/imap/backup/setup/global_options.rb +2 -2
  59. data/lib/imap/backup/setup.rb +2 -2
  60. data/lib/imap/backup/text/sanitizer.rb +2 -2
  61. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +10 -8
  62. data/lib/imap/backup/uploader.rb +3 -3
  63. data/lib/imap/backup/version.rb +1 -1
  64. metadata +4 -4
  65. data/lib/imap/backup/cli_coverage.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f83228485fa483834d66fa4fb2fd8dcfba3523100608136e8d82eb3c90765f40
4
- data.tar.gz: d1c52e0743c7b2922e0c5e65c388446ef344f32a42887f0069f2070b5e0903bc
3
+ metadata.gz: 0cfc1578cd412445288e4fab78e6baa0f36b1d821c5ef6d534b72b1b2e647f97
4
+ data.tar.gz: ebe6162fd0370739a141c92861f7f623ff9e4b774e6d88952cfc04e0792a9826
5
5
  SHA512:
6
- metadata.gz: 4a95165223801af4c9e72b7aa66b054caaad51300f229d105d6ca6d0636f8f3a500598eb184b7230c48e0c27492d1f14121660c96db1c515d89bf21a73fcaa89
7
- data.tar.gz: 9c3b7fe3b38ab2819285406503d61651f3df175e3ce6702e2e274183d99a361a6e986e2afb75859ea74a788688fda05856ad869b62a736b2c996a1b2593a23f3
6
+ metadata.gz: a57023ad7181a137744866b84181d307485029b7f05e9b64d3a8ccc4735a3114a814006ef82cc8c9e8eac1ea9db1055be31a8f8ff48a385836b874b5b23494bb
7
+ data.tar.gz: ffb357707b5c42a1cea36da60d1c1b0ffc056d175c32760c9551259673331c1205d3365e62bf865b6ed0245042c069ba4b610cf66b4f53e59a57e97f46ef1cbc
data/bin/imap-backup CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  $LOAD_PATH.unshift(File.expand_path("../lib/", __dir__))
4
4
 
5
- require "imap/backup/cli_coverage"
5
+ require_relative "../spec/support/cli_coverage"
6
6
 
7
- Imap::Backup::CliCoverage.conditionally_activate
7
+ CliCoverage.conditionally_activate
8
8
 
9
9
  require "imap/backup/cli"
10
10
  require "imap/backup/logger"
data/docs/api.md ADDED
@@ -0,0 +1,20 @@
1
+ # @title Index
2
+ # imap-backup API Documentation
3
+
4
+ ![Version](https://img.shields.io/gem/v/imap-backup?label=Version&logo=rubygems)
5
+ [![Build Status](https://github.com/joeyates/imap-backup/actions/workflows/main.yml/badge.svg)][CI Status]
6
+ ![Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/joeyates/b54fe758bfb405c04bef72dad293d707/raw/coverage.json)
7
+ ![License](https://img.shields.io/github/license/joeyates/imap-backup?color=brightgreen&label=License)
8
+ [![Stars](https://img.shields.io/github/stars/joeyates/imap-backup?style=social)][GitHub Stars]
9
+
10
+ [CI Status]: https://github.com/joeyates/imap-backup/actions/workflows/main.yml
11
+ [GitHub Stars]: https://github.com/joeyates/imap-backup/stargazers "GitHub Stars"
12
+
13
+ This is the developer documentation for imap-backup's **code**.
14
+
15
+ Usage documentation is on [GitHub](https://github.com/joeyates/imap-backup).
16
+
17
+ You can get an overview of the program's structure from the
18
+ {file:ARCHITECTURE.md ARCHITECTURE} file.
19
+
20
+ The {file:CHANGELOG.md CHANGELOG} has a history of the changes to the program.
data/docs/development.md CHANGED
@@ -17,8 +17,9 @@ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
17
17
 
18
18
  ## Feature Specs
19
19
 
20
- Specs under `specs/features` are integration specs run against
21
- two local IMAP servers controlled by Podman (or Docker) Compose.
20
+ Specs under `specs/features` are integration specs.
21
+ Some of these specs run against two local IMAP servers
22
+ controlled by Podman (or Docker) Compose.
22
23
 
23
24
  Start them before running the test suite
24
25
 
@@ -32,20 +33,30 @@ or, with Podman
32
33
  $ podman-compose -f dev/compose.yml up -d
33
34
  ```
34
35
 
36
+ Then, run all specs
37
+
35
38
  ```sh
36
- $ rake
39
+ $ rspec
37
40
  ```
38
41
 
39
- To exclude container-based tests:
42
+ To exclude container-based tests
40
43
 
41
44
  ```sh
42
- rake no-docker
45
+ $ rspec --tag ~docker
43
46
  ```
44
47
 
45
- or
48
+ To run **just** the feature specs
46
49
 
47
50
  ```sh
48
- $ rspec --tag ~docker
51
+ rspec spec/features/**/*_spec.rb
52
+ ```
53
+
54
+ ## Full Test Run
55
+
56
+ The full test run includes RSpec specs **and** Runbocop checks
57
+
58
+ ```sh
59
+ rake
49
60
  ```
50
61
 
51
62
  # Older Rubies
@@ -8,10 +8,8 @@ module Imap; end
8
8
  module Imap::Backup
9
9
  class Account; end
10
10
 
11
+ # Carries out the backup of the configured folders of the account
11
12
  class Account::Backup
12
- attr_reader :account
13
- attr_reader :refresh
14
-
15
13
  def initialize(account:, refresh: false)
16
14
  @account = account
17
15
  @refresh = refresh
@@ -35,5 +33,10 @@ module Imap::Backup
35
33
  Account::FolderBackup.new(account: account, folder: folder, refresh: refresh).run
36
34
  end
37
35
  end
36
+
37
+ private
38
+
39
+ attr_reader :account
40
+ attr_reader :refresh
38
41
  end
39
42
  end
@@ -5,12 +5,10 @@ module Imap; end
5
5
  module Imap::Backup
6
6
  class Account; end
7
7
 
8
+ # Iterates over the account folders that are to be backed up
8
9
  class Account::BackupFolders
9
10
  include Enumerable
10
11
 
11
- attr_reader :account
12
- attr_reader :client
13
-
14
12
  def initialize(client:, account:)
15
13
  @client = client
16
14
  @account = account
@@ -46,5 +44,10 @@ module Imap::Backup
46
44
  block.call(folder)
47
45
  end
48
46
  end
47
+
48
+ private
49
+
50
+ attr_reader :account
51
+ attr_reader :client
49
52
  end
50
53
  end
@@ -10,9 +10,8 @@ module Imap; end
10
10
  module Imap::Backup
11
11
  class Account; end
12
12
 
13
+ # Returns an IMAP client set up for the supplied account
13
14
  class Account::ClientFactory
14
- attr_reader :account
15
-
16
15
  def initialize(account:)
17
16
  @account = account
18
17
  @provider = nil
@@ -35,6 +34,8 @@ module Imap::Backup
35
34
 
36
35
  private
37
36
 
37
+ attr_reader :account
38
+
38
39
  def provider
39
40
  @provider ||= Email::Provider.for_address(account.username)
40
41
  end
@@ -10,19 +10,13 @@ module Imap; end
10
10
  module Imap::Backup
11
11
  class Account; end
12
12
 
13
- class FolderNotFound < StandardError; end
14
-
13
+ # Handles access to a folder on an IMAP server
15
14
  class Account::Folder
15
+ class FolderNotFound < StandardError; end
16
+
16
17
  extend Forwardable
17
18
  include RetryOnError
18
19
 
19
- BODY_ATTRIBUTE = "BODY[]".freeze
20
- UID_FETCH_RETRY_CLASSES = [::EOFError, ::Errno::ECONNRESET, ::IOError].freeze
21
- APPEND_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
22
- CREATE_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
23
- EXAMINE_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
24
- PERMITTED_FLAGS = %i(Answered Draft Flagged Seen).freeze
25
-
26
20
  attr_reader :client
27
21
  attr_reader :name
28
22
 
@@ -156,6 +150,13 @@ module Imap::Backup
156
150
 
157
151
  private
158
152
 
153
+ BODY_ATTRIBUTE = "BODY[]".freeze
154
+ UID_FETCH_RETRY_CLASSES = [::EOFError, ::Errno::ECONNRESET, ::IOError].freeze
155
+ APPEND_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
156
+ CREATE_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
157
+ EXAMINE_RETRY_CLASSES = [::Net::IMAP::BadResponseError].freeze
158
+ PERMITTED_FLAGS = %i(Answered Draft Flagged Seen).freeze
159
+
159
160
  def examine
160
161
  client.examine(utf7_encoded_name)
161
162
  rescue Net::IMAP::NoResponseError
@@ -10,11 +10,8 @@ module Imap; end
10
10
  module Imap::Backup
11
11
  class Account; end
12
12
 
13
+ # Runs a backup for a single account folder
13
14
  class Account::FolderBackup
14
- attr_reader :account
15
- attr_reader :folder
16
- attr_reader :refresh
17
-
18
15
  def initialize(account:, folder:, refresh: false)
19
16
  @account = account
20
17
  @folder = folder
@@ -38,6 +35,10 @@ module Imap::Backup
38
35
 
39
36
  private
40
37
 
38
+ attr_reader :account
39
+ attr_reader :folder
40
+ attr_reader :refresh
41
+
41
42
  def folder_ok?
42
43
  begin
43
44
  return false if !folder.exist?
@@ -6,9 +6,8 @@ module Imap; end
6
6
  module Imap::Backup
7
7
  class Account; end
8
8
 
9
+ # Handles creation of directories for backup storage
9
10
  class Account::FolderEnsurer
10
- attr_reader :account
11
-
12
11
  def initialize(account:)
13
12
  @account = account
14
13
  end
@@ -22,5 +21,9 @@ module Imap::Backup
22
21
  permissions: Serializer::Directory::DIRECTORY_PERMISSIONS
23
22
  ).run
24
23
  end
24
+
25
+ private
26
+
27
+ attr_reader :account
25
28
  end
26
29
  end
@@ -6,10 +6,10 @@ module Imap; end
6
6
  module Imap::Backup
7
7
  class Account; end
8
8
 
9
- # Deletes serialized folders that are not configured to be backed up
9
+ # Deletes serialized folders that are not configured to be backed up.
10
+ # This is used in mirror mode, where local copies are only kept as long as they
11
+ # exist on the server.
10
12
  class Account::LocalOnlyFolderDeleter
11
- attr_reader :account
12
-
13
13
  def initialize(account:)
14
14
  @account = account
15
15
  end
@@ -24,5 +24,9 @@ module Imap::Backup
24
24
  serializer.delete if !wanted.include?(serializer.folder)
25
25
  end
26
26
  end
27
+
28
+ private
29
+
30
+ attr_reader :account
27
31
  end
28
32
  end
@@ -6,9 +6,8 @@ module Imap; end
6
6
  module Imap::Backup
7
7
  class Account; end
8
8
 
9
+ # Restores all backed up folders to the server
9
10
  class Account::Restore
10
- attr_reader :account
11
-
12
11
  def initialize(account:)
13
12
  @account = account
14
13
  end
@@ -19,5 +18,9 @@ module Imap::Backup
19
18
  Uploader.new(folder, serializer).run
20
19
  end
21
20
  end
21
+
22
+ private
23
+
24
+ attr_reader :account
22
25
  end
23
26
  end
@@ -9,11 +9,10 @@ module Imap; end
9
9
  module Imap::Backup
10
10
  class Account; end
11
11
 
12
+ # Enumerates over the folders that are backed up to an account
12
13
  class Account::SerializedFolders
13
14
  include Enumerable
14
15
 
15
- attr_reader :account
16
-
17
16
  def initialize(account:)
18
17
  @account = account
19
18
  end
@@ -31,6 +30,8 @@ module Imap::Backup
31
30
 
32
31
  private
33
32
 
33
+ attr_reader :account
34
+
34
35
  def base
35
36
  @base ||= Pathname.new(account.local_path)
36
37
  end
@@ -6,19 +6,62 @@ require "imap/backup/account/restore"
6
6
  module Imap; end
7
7
 
8
8
  module Imap::Backup
9
+ # Contains the attributes relating to an email account.
9
10
  class Account
11
+ # By default, the backup process fetches one email at a time
10
12
  DEFAULT_MULTI_FETCH_SIZE = 1
11
13
 
14
+ # The username of the account (usually the same as the email address)
15
+ # @return [String]
12
16
  attr_reader :username
17
+ # The password of the Account
13
18
  attr_reader :password
19
+ # The path where backups will be saved
20
+ # @return [String]
14
21
  attr_reader :local_path
22
+ # @overload folders
23
+ # The list of folders that have been configured for the Account
24
+ # @see #folder_blacklist how this list is interpreted.
25
+ # @return [Array<String>, void]
26
+ # @overload folders=(value)
27
+ # Sets the folders attribute and marks it as modified, storing the original value
28
+ # @param value [Array<String>] a list of folders
29
+ # @return [void]
15
30
  attr_reader :folders
31
+ # Indicates whether the configured folders are a whitelist or a blacklist.
32
+ # When true, any folders attribute will be taken as a list of folders to
33
+ # skip when running backups.
34
+ # When false, the folders attribute is used as the list of folders to backup.
35
+ # If no folders are configured, all folders on the server are backed up
36
+ # irrespective of the folder_blacklist setting
37
+ # @return [Boolean]
16
38
  attr_reader :folder_blacklist
39
+ # Should all emails be backed up progressively, or should emails
40
+ # which are deleted from the server be deleted locally?
17
41
  attr_reader :mirror_mode
42
+ # The address of the IMAP server
43
+ # @return [String]
18
44
  attr_reader :server
45
+ # Extra options to be passed to the IMAP server when connecting
46
+ # @return [Hash, void]
19
47
  attr_reader :connection_options
48
+ # The name of the download strategy to adopt during backups
49
+ # @return [String]
20
50
  attr_accessor :download_strategy
51
+ # Should 'Seen' flags be cached before fetchiong emails and
52
+ # rewritten to the server afterwards?
53
+ #
54
+ # Some IMAP providers, notably Apple Mail, set the '\Seen' flag
55
+ # on emails when they are fetched. By setting `:reset_seen_flags_after_fetch`,
56
+ # a workaround is activated which checks which emails are 'unseen' before
57
+ # and after the fetch, and removes the '\Seen' flag from those which have changed.
58
+ # As this check is susceptible to 'race conditions', i.e. when a different
59
+ # client sets the '\Seen' flag while imap-backup is fetching, it is best
60
+ # to only use it when required (i.e. for IMAP providers which always
61
+ # mark messages as '\Seen' when accessed).
62
+ # @return [Boolean]
21
63
  attr_reader :reset_seen_flags_after_fetch
64
+ # Tracks changes to the Account's attributes
22
65
  attr_reader :changes
23
66
 
24
67
  def initialize(options)
@@ -38,23 +81,39 @@ module Imap::Backup
38
81
  @marked_for_deletion = false
39
82
  end
40
83
 
84
+ # Initializes a client for the account's IMAP server
85
+ #
86
+ # @return [Account::Client::Default] the client
41
87
  def client
42
88
  @client ||= Account::ClientFactory.new(account: self).run
43
89
  end
44
90
 
91
+ # Returns the namespaces configured for the account on the IMAP server
92
+ #
93
+ # @return [Array<String>] the namespaces
45
94
  def namespaces
46
95
  client.namespace
47
96
  end
48
97
 
98
+ # Returns the capabilites of the IMAP server
99
+ #
100
+ # @return [Array<String>] the capabilities
49
101
  def capabilities
50
102
  client.capability
51
103
  end
52
104
 
105
+ # Restore the local backup to the server
106
+ #
107
+ # @return [void]
53
108
  def restore
54
109
  restore = Account::Restore.new(account: self)
55
110
  restore.run
56
111
  end
57
112
 
113
+ # Indicates whether the account has been configured, and is ready
114
+ # to be used
115
+ #
116
+ # @return [Boolean]
58
117
  def valid?
59
118
  username && password ? true : false
60
119
  end
@@ -63,18 +122,28 @@ module Imap::Backup
63
122
  changes.any?
64
123
  end
65
124
 
125
+ # Resets the store of changes, indicating that the current state is the saved state
66
126
  def clear_changes
67
127
  @changes = {}
68
128
  end
69
129
 
130
+ # Sets a flag indicating the Account should be excluded from the next save operation
131
+ #
132
+ # @return [void]
70
133
  def mark_for_deletion
71
134
  @marked_for_deletion = true
72
135
  end
73
136
 
137
+ # Indicates whether the account has been flagged for deletion during setup
138
+ #
139
+ # @return [Boolean]
74
140
  def marked_for_deletion?
75
141
  @marked_for_deletion
76
142
  end
77
143
 
144
+ # Returns all Account data for serialization
145
+ #
146
+ # @return [Hash]
78
147
  def to_h
79
148
  h = {username: @username, password: @password}
80
149
  h[:local_path] = @local_path if @local_path
@@ -90,14 +159,23 @@ module Imap::Backup
90
159
  h
91
160
  end
92
161
 
162
+ # Sets the username attribute and marks it as modified, storing the original value
163
+ #
164
+ # @return [void]
93
165
  def username=(value)
94
166
  update(:username, value)
95
167
  end
96
168
 
169
+ # Sets the password attribute and marks it as modified, storing the original value
170
+ #
171
+ # @return [void]
97
172
  def password=(value)
98
173
  update(:password, value)
99
174
  end
100
175
 
176
+ # Sets the local_path attribute and marks it as modified, storing the original value
177
+ #
178
+ # @return [void]
101
179
  def local_path=(value)
102
180
  update(:local_path, value)
103
181
  end
@@ -130,6 +208,9 @@ module Imap::Backup
130
208
  update(:connection_options, parsed)
131
209
  end
132
210
 
211
+ # The number of emails to fetch from the IMAP server at a time
212
+ #
213
+ # @return [Integer]
133
214
  def multi_fetch_size
134
215
  @multi_fetch_size ||= begin
135
216
  int = @multi_fetch_size_orignal.to_i
@@ -141,6 +222,10 @@ module Imap::Backup
141
222
  end
142
223
  end
143
224
 
225
+ # Sets the multi_fetch_size attribute and marks it as modified, storing the original value.
226
+ # If the supplied value is not a positive integer, uses {DEFAULT_MULTI_FETCH_SIZE}
227
+ #
228
+ # @return [void]
144
229
  def multi_fetch_size=(value)
145
230
  parsed = value.to_i
146
231
  parsed = DEFAULT_MULTI_FETCH_SIZE if !parsed.positive?
@@ -14,8 +14,6 @@ module Imap::Backup
14
14
  include Thor::Actions
15
15
  include CLI::Helpers
16
16
 
17
- attr_reader :options
18
-
19
17
  def initialize(options)
20
18
  super([])
21
19
  @options = options
@@ -44,18 +42,22 @@ module Imap::Backup
44
42
  end
45
43
  exit(exit_code) if exit_code
46
44
  end
45
+ end
47
46
 
48
- def refresh
49
- options.key?(:refresh) ? !!options[:refresh] : false
50
- end
47
+ private
51
48
 
52
- def choose_exit_code(exception)
53
- case exception
54
- when Net::IMAP::NoResponseError, Errno::ECONNREFUSED
55
- 111
56
- else
57
- 1
58
- end
49
+ attr_reader :options
50
+
51
+ def refresh
52
+ options.key?(:refresh) ? !!options[:refresh] : false
53
+ end
54
+
55
+ def choose_exit_code(exception)
56
+ case exception
57
+ when Net::IMAP::NoResponseError, Errno::ECONNREFUSED
58
+ 111
59
+ else
60
+ 1
59
61
  end
60
62
  end
61
63
  end
@@ -10,11 +10,6 @@ module Imap::Backup
10
10
  class CLI < Thor; end
11
11
 
12
12
  class CLI::FolderEnumerator
13
- attr_reader :destination
14
- attr_reader :destination_delimiter
15
- attr_reader :source
16
- attr_reader :source_delimiter
17
-
18
13
  def initialize(
19
14
  destination:,
20
15
  source:,
@@ -45,6 +40,11 @@ module Imap::Backup
45
40
 
46
41
  private
47
42
 
43
+ attr_reader :destination
44
+ attr_reader :destination_delimiter
45
+ attr_reader :source
46
+ attr_reader :source_delimiter
47
+
48
48
  def destination_prefix_clipped
49
49
  @destination_prefix_clipped ||=
50
50
  if @destination_prefix.end_with?(destination_delimiter)
@@ -13,8 +13,6 @@ module Imap::Backup
13
13
  class CLI::Local::Check
14
14
  include CLI::Helpers
15
15
 
16
- attr_reader :options
17
-
18
16
  def initialize(options)
19
17
  @options = options
20
18
  end
@@ -48,6 +46,10 @@ module Imap::Backup
48
46
  end
49
47
  end
50
48
 
49
+ private
50
+
51
+ attr_reader :options
52
+
51
53
  def print_check_results_as_json(results)
52
54
  Kernel.puts results.to_json
53
55
  end