imap-backup 16.4.0 → 16.4.2

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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -92
  3. data/docs/development.md +8 -0
  4. data/docs/testing.md +93 -0
  5. data/imap-backup.gemspec +1 -1
  6. data/lib/imap/backup/account/backup.rb +5 -4
  7. data/lib/imap/backup/account/backup_folders.rb +2 -0
  8. data/lib/imap/backup/account/client_factory.rb +1 -0
  9. data/lib/imap/backup/account/folder.rb +2 -0
  10. data/lib/imap/backup/account/folder_backup.rb +10 -1
  11. data/lib/imap/backup/account/folder_mapper.rb +11 -1
  12. data/lib/imap/backup/account/local_only_folder_deleter.rb +1 -0
  13. data/lib/imap/backup/account/locker.rb +7 -3
  14. data/lib/imap/backup/account/restore.rb +3 -0
  15. data/lib/imap/backup/account/serialized_folders.rb +15 -4
  16. data/lib/imap/backup/account.rb +39 -17
  17. data/lib/imap/backup/cli/backup.rb +4 -0
  18. data/lib/imap/backup/cli/local/check.rb +5 -0
  19. data/lib/imap/backup/cli/options.rb +1 -0
  20. data/lib/imap/backup/cli/restore.rb +10 -3
  21. data/lib/imap/backup/cli/setup.rb +3 -0
  22. data/lib/imap/backup/cli/single/backup.rb +20 -0
  23. data/lib/imap/backup/cli/stats.rb +15 -1
  24. data/lib/imap/backup/cli/transfer.rb +3 -0
  25. data/lib/imap/backup/cli/utils.rb +36 -9
  26. data/lib/imap/backup/client/automatic_login_wrapper.rb +1 -0
  27. data/lib/imap/backup/client/default.rb +1 -0
  28. data/lib/imap/backup/configuration.rb +1 -0
  29. data/lib/imap/backup/downloader.rb +4 -0
  30. data/lib/imap/backup/email/mboxrd/message.rb +1 -0
  31. data/lib/imap/backup/file_mode.rb +1 -0
  32. data/lib/imap/backup/flag_refresher.rb +2 -0
  33. data/lib/imap/backup/local_only_message_deleter.rb +2 -0
  34. data/lib/imap/backup/lockfile.rb +19 -3
  35. data/lib/imap/backup/logger.rb +1 -1
  36. data/lib/imap/backup/migrator.rb +3 -0
  37. data/lib/imap/backup/mirror/map.rb +2 -1
  38. data/lib/imap/backup/mirror.rb +4 -1
  39. data/lib/imap/backup/serializer/appender.rb +17 -15
  40. data/lib/imap/backup/serializer/delayed_metadata_serializer.rb +2 -2
  41. data/lib/imap/backup/serializer/directory_maker.rb +43 -0
  42. data/lib/imap/backup/serializer/files/path.rb +27 -0
  43. data/lib/imap/backup/serializer/files.rb +167 -0
  44. data/lib/imap/backup/serializer/imap.rb +15 -12
  45. data/lib/imap/backup/serializer/mbox.rb +7 -7
  46. data/lib/imap/backup/serializer/message.rb +1 -1
  47. data/lib/imap/backup/serializer/unused_name_finder.rb +12 -7
  48. data/lib/imap/backup/serializer.rb +47 -206
  49. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +6 -0
  50. data/lib/imap/backup/uploader.rb +5 -1
  51. data/lib/imap/backup/version.rb +1 -1
  52. metadata +11 -10
  53. data/lib/imap/backup/account/folder_ensurer.rb +0 -32
  54. data/lib/imap/backup/serializer/directory.rb +0 -51
  55. data/lib/imap/backup/serializer/folder_maker.rb +0 -44
  56. data/lib/imap/backup/serializer/version2_migrator.rb +0 -123
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ec15a683d70eadabab4271afcd2231c723344e79dde55fadeea091056201fc8
4
- data.tar.gz: 946f1074220df2af38c92a5ff7f5dda8bcdcef3dc20f48d9f2c8206e29a8cd6e
3
+ metadata.gz: fc471fce2bd514e0eee4cec922e8f368df0b2fb99f8b89b2d852e07799a2be77
4
+ data.tar.gz: fd563c2ee648d5e384a10cdfc79a7d1d5be128bdce5908711396d414c801173f
5
5
  SHA512:
6
- metadata.gz: 7c33112eb20f168c453f0cc52e86497c7a44459afa718ac12ff1ca71cf990d9566514598aae25fc22117fb30478db649bb76a1aff697d40dabb788cc54fa1508
7
- data.tar.gz: ea2dd0c673c603c71708ba550cbdf98c218c51b8ff076ba031d40a7ae33f80ff830ada659b7cc300e8511cc3da207665e6f2114c231e985a0b716e2844f7fe7a
6
+ metadata.gz: 36088caab383a7ff2528d8ad83813f58918abda4d80a56b0f2b2f1f45d5fc840934d1bc31e1907de11cc665f5aecb5b12152bb8dee686fb656294eb55440897e
7
+ data.tar.gz: 389a82b7755342dd591fd0e2d45d760eb8350f697d46414d8d90776624bd0ee7263acfe163ab1e8dd42c869d12a544c2d5faa4656d4ef5c802f4991b9f33c1b4
data/README.md CHANGED
@@ -25,102 +25,13 @@ The {file:CHANGELOG.md CHANGELOG} has a history of the changes to the program.
25
25
  * Restartable - calculate start point based on already downloaded messages
26
26
  * Standalone - do not rely on an email client or MTA
27
27
 
28
- # Repository
28
+ # Development
29
29
 
30
- After cloning the repo, run the following command to get
31
- better `git blame` output:
32
-
33
- ```sh
34
- git config --local blame.ignoreRevsFile .git-blame-ignore-revs
35
- ```
30
+ See the [development documentation](/docs/development.md).
36
31
 
37
32
  # Testing
38
33
 
39
- ## Feature Specs
40
-
41
- Specs under `specs/features` are integration specs.
42
- Some of these specs run against two local IMAP servers
43
- controlled by Podman (or Docker) Compose.
44
-
45
- Start them before running the test suite
46
-
47
- ```sh
48
- $ podman-compose -f dev/compose.yml up -d
49
- ```
50
-
51
- or, with Docker
52
-
53
- ```sh
54
- $ docker-compose -f dev/compose.yml up -d
55
- ```
56
-
57
- Then, run all specs
58
-
59
- ```sh
60
- $ rspec
61
- ```
62
-
63
- To exclude container-based tests
64
-
65
- ```sh
66
- $ rspec --tag ~container
67
- ```
68
-
69
- To run **just** the feature specs
70
-
71
- ```sh
72
- rspec spec/features/**/*_spec.rb
73
- ```
74
-
75
- ## Full Test Run
76
-
77
- The full test run includes RSpec specs **and** Rubocop checks
78
-
79
- ```sh
80
- rake
81
- ```
82
-
83
- # Test Debugging
84
-
85
- The feature specs are run 'out of process' via the Aruba gem.
86
- In order to see debugging output from the process,
87
- use `last_command_started.output`.
88
-
89
- # Older Rubies
90
-
91
- A Containerfile is available to allow testing with all available Ruby versions,
92
- see the README in the `dev` directory.
93
-
94
- # Performance Specs
95
-
96
- ```sh
97
- PERFORMANCE=1 rspec --order=defined
98
- ```
99
-
100
- Beware: the performance spec (just backup for now) takes a very
101
- long time to run, approximately 24 hours!
102
-
103
- # Access Docker imap server
104
-
105
- ```ruby
106
- require "net/imap"
107
- require_relative "spec/features/support/30_email_server_helpers"
108
-
109
- include EmailServerHelpers
110
-
111
- test_connection = test_server_connection_parameters
112
-
113
- test_imap = Net::IMAP.new(test_connection[:server], test_connection[:connection_options])
114
- test_imap.login(test_connection[:username], test_connection[:password])
115
-
116
- message = "From: #{test_connection[:username]}\nSubject: Some Subject\n\nHello!\n"
117
- response = test_imap.append("INBOX", message, nil, nil)
118
-
119
- test_imap.examine("INBOX")
120
- uids = test_imap.uid_search(["ALL"]).sort
121
-
122
- fetch_data_items = test_imap.uid_fetch(uids, ["BODY[]"])
123
- ```
34
+ See the [testing documentation](/docs/testing.md).
124
35
 
125
36
  # Contributing
126
37
 
@@ -0,0 +1,8 @@
1
+ # Repository
2
+
3
+ After cloning the repo, run the following command to get
4
+ better `git blame` output:
5
+
6
+ ```sh
7
+ git config --local blame.ignoreRevsFile .git-blame-ignore-revs
8
+ ```
data/docs/testing.md ADDED
@@ -0,0 +1,93 @@
1
+ # Setup
2
+
3
+ Specs under `spec/features` are integration specs.
4
+ Some of these specs run against two local IMAP servers
5
+ controlled by Podman (or Docker) Compose.
6
+
7
+ Start them before running the test suite
8
+
9
+ ```sh
10
+ $ podman-compose -f dev/compose.yml up -d
11
+ ```
12
+
13
+ or, with Docker
14
+
15
+ ```sh
16
+ $ docker-compose -f dev/compose.yml up -d
17
+ ```
18
+
19
+ # Invocations
20
+
21
+ Run all specs
22
+
23
+ ```sh
24
+ $ rake spec
25
+ ```
26
+
27
+ Run **just** the unit specs
28
+
29
+ ```sh
30
+ $ rake spec_unit
31
+ ```
32
+
33
+ Run **just** the feature specs
34
+
35
+ ```sh
36
+ $ rake spec_feature
37
+ ```
38
+
39
+ To exclude the slow container-based tests
40
+
41
+ ```sh
42
+ $ rake spec_non_container
43
+ ```
44
+
45
+ ## Full Test Run
46
+
47
+ The full test run includes RSpec specs **and** Rubocop checks
48
+
49
+ ```sh
50
+ rake test
51
+ ```
52
+
53
+ # Debugging
54
+
55
+ The feature specs are run 'out of process' via the Aruba gem.
56
+ In order to see debugging output from the process,
57
+ use `last_command_started.output`.
58
+
59
+ # Older Rubies
60
+
61
+ A Containerfile is available to allow testing with all available Ruby versions,
62
+ see the README in the `dev` directory.
63
+
64
+ # Performance Specs
65
+
66
+ ```sh
67
+ PERFORMANCE=1 rspec --order=defined
68
+ ```
69
+
70
+ Beware: the performance spec (just backup for now) takes a very
71
+ long time to run, approximately 24 hours!
72
+
73
+ # Access Docker imap server
74
+
75
+ ```ruby
76
+ require "net/imap"
77
+ require_relative "spec/features/support/30_email_server_helpers"
78
+
79
+ include EmailServerHelpers
80
+
81
+ test_connection = test_server_connection_parameters
82
+
83
+ test_imap = Net::IMAP.new(test_connection[:server], test_connection[:connection_options])
84
+ test_imap.login(test_connection[:username], test_connection[:password])
85
+
86
+ message = "From: #{test_connection[:username]}\nSubject: Some Subject\n\nHello!\n"
87
+ response = test_imap.append("INBOX", message, nil, nil)
88
+
89
+ test_imap.examine("INBOX")
90
+ uids = test_imap.uid_search(["ALL"]).sort
91
+
92
+ fetch_data_items = test_imap.uid_fetch(uids, ["BODY[]"])
93
+ ```
data/imap-backup.gemspec CHANGED
@@ -30,7 +30,7 @@ Gem::Specification.new do |gem|
30
30
  gem.add_dependency "rake"
31
31
  gem.add_dependency "sys-proctable"
32
32
  gem.add_dependency "thor", "~> 1.1"
33
- gem.add_dependency "thunderbird", "0.3.0"
33
+ gem.add_dependency "thunderbird", "~> 0.6.0"
34
34
 
35
35
  gem.metadata = {
36
36
  "rubygems_mfa_required" => "true"
@@ -1,6 +1,5 @@
1
1
  require "imap/backup/account/backup_folders"
2
2
  require "imap/backup/account/folder_backup"
3
- require "imap/backup/account/folder_ensurer"
4
3
  require "imap/backup/account/local_only_folder_deleter"
5
4
  require "imap/backup/account/locker"
6
5
 
@@ -11,6 +10,8 @@ module Imap::Backup
11
10
 
12
11
  # Carries out the backup of the configured folders of the account
13
12
  class Account::Backup
13
+ # @param account [Account] the account to back up
14
+ # @param refresh [Boolean] true to refresh folder metadata even if mirror is disabled
14
15
  def initialize(account:, refresh: false)
15
16
  @account = account
16
17
  @refresh = refresh
@@ -23,7 +24,7 @@ module Imap::Backup
23
24
  # start the connection so we get logging messages in the right order
24
25
  account.client.login
25
26
 
26
- ensure_folder
27
+ ensure_directory
27
28
  delete_local_only_folders if account.mirror_mode
28
29
 
29
30
  if backup_folders.none?
@@ -51,8 +52,8 @@ module Imap::Backup
51
52
  Account::LocalOnlyFolderDeleter.new(account: account).run
52
53
  end
53
54
 
54
- def ensure_folder
55
- Account::FolderEnsurer.new(account: account).run
55
+ def ensure_directory
56
+ Serializer::DirectoryMaker.new(files_path: account.files_path).run
56
57
  end
57
58
 
58
59
  def locker
@@ -9,6 +9,8 @@ module Imap::Backup
9
9
  class Account::BackupFolders
10
10
  include Enumerable
11
11
 
12
+ # @param client [Client::AutomaticLoginWrapper] the IMAP client that lists folders
13
+ # @param account [Account] the account whose folders are being backed up
12
14
  def initialize(client:, account:)
13
15
  @client = client
14
16
  @account = account
@@ -10,6 +10,7 @@ module Imap::Backup
10
10
 
11
11
  # Returns an IMAP client set up for the supplied account
12
12
  class Account::ClientFactory
13
+ # @param account [Account] the account whose credentials configure the client
13
14
  def initialize(account:)
14
15
  @account = account
15
16
  end
@@ -23,6 +23,8 @@ module Imap::Backup
23
23
  # @return [String] the name of the folder
24
24
  attr_reader :name
25
25
 
26
+ # @param client [Client::Default] the IMAP client used to talk to the server
27
+ # @param name [String] the UTF-7 encoded folder name
26
28
  def initialize(client, name)
27
29
  @client = client
28
30
  @name = name
@@ -4,6 +4,7 @@ require "imap/backup/flag_refresher"
4
4
  require "imap/backup/local_only_message_deleter"
5
5
  require "imap/backup/logger"
6
6
  require "imap/backup/serializer"
7
+ require "imap/backup/serializer/files/path"
7
8
 
8
9
  module Imap; end
9
10
 
@@ -12,6 +13,9 @@ module Imap::Backup
12
13
 
13
14
  # Implements backup for a single folder
14
15
  class Account::FolderBackup
16
+ # @param account [Account] the account that owns the folder
17
+ # @param folder [Account::Folder] the online folder being backed up
18
+ # @param refresh [Boolean] true to refresh metadata regardless of mirror mode
15
19
  def initialize(account:, folder:, refresh: false)
16
20
  @account = account
17
21
  @folder = folder
@@ -83,7 +87,12 @@ module Imap::Backup
83
87
  end
84
88
 
85
89
  def raw_serializer
86
- @raw_serializer ||= Serializer.new(account.local_path, folder.name)
90
+ @raw_serializer ||= begin
91
+ path = Serializer::Files::Path.new(
92
+ base_path: account.local_path, folder_name: folder.name
93
+ )
94
+ Serializer.new(files_path: path)
95
+ end
87
96
  end
88
97
  end
89
98
  end
@@ -3,6 +3,7 @@ require "pathname"
3
3
 
4
4
  require "imap/backup/account/folder"
5
5
  require "imap/backup/serializer"
6
+ require "imap/backup/serializer/files/path"
6
7
 
7
8
  module Imap; end
8
9
 
@@ -11,6 +12,12 @@ module Imap::Backup
11
12
 
12
13
  # Implements a folder enumerator for backed-up accounts
13
14
  class Account::FolderMapper
15
+ # @param account [Account] the account whose local folders are being iterated
16
+ # @param destination [Account] the destination account
17
+ # @param destination_delimiter [String] the delimiter to use for destination folder names
18
+ # @param destination_prefix [String] a prefix applied to destination folder names
19
+ # @param source_delimiter [String] the delimiter used in the source account
20
+ # @param source_prefix [String] a prefix applied to source folder names
14
21
  def initialize(
15
22
  account:,
16
23
  destination:,
@@ -38,7 +45,10 @@ module Imap::Backup
38
45
  glob = File.join(source_local_path, "**", "*.imap")
39
46
  Pathname.glob(glob) do |path|
40
47
  name = source_folder_name(path)
41
- serializer = Serializer.new(source_local_path, name)
48
+ path = Serializer::Files::Path.new(
49
+ base_path: source_local_path, folder_name: name
50
+ )
51
+ serializer = Serializer.new(files_path: path)
42
52
  folder = destination_folder_for_path(name)
43
53
  block.call(serializer, folder)
44
54
  end
@@ -10,6 +10,7 @@ module Imap::Backup
10
10
  # This is used in mirror mode, where local copies are only kept as long as they
11
11
  # exist on the server.
12
12
  class Account::LocalOnlyFolderDeleter
13
+ # @param account [Account] the account whose serialized folders are being pruned
13
14
  def initialize(account:)
14
15
  @account = account
15
16
  end
@@ -1,4 +1,3 @@
1
- require "imap/backup/account/folder_ensurer"
2
1
  require "imap/backup/lockfile"
3
2
 
4
3
  module Imap; end
@@ -9,6 +8,7 @@ module Imap::Backup
9
8
  class Account::Locker
10
9
  attr_reader :account
11
10
 
11
+ # @param account [Account] the account whose backup must be locked
12
12
  def initialize(account:)
13
13
  @account = account
14
14
  end
@@ -24,10 +24,14 @@ module Imap::Backup
24
24
  Logger.logger.info("Stale lockfile '#{account.lockfile_path}' found. Removing it.")
25
25
  lockfile.remove
26
26
  else
27
- Account::FolderEnsurer.new(account: account).run
27
+ Serializer::DirectoryMaker.new(files_path: account.files_path).run
28
28
  end
29
29
 
30
- lockfile.with_lock do
30
+ begin
31
+ lockfile.with_lock do
32
+ block.call
33
+ end
34
+ rescue Lockfile::ProcessStartTimeUnavailableError
31
35
  block.call
32
36
  end
33
37
  end
@@ -9,6 +9,9 @@ module Imap::Backup
9
9
 
10
10
  # Restores all backed up folders to the server
11
11
  class Account::Restore
12
+ # @param account [Account] the account whose backups will be restored
13
+ # @param delimiter [String] the destination folder delimiter
14
+ # @param prefix [String] a prefix applied to restored folder names
12
15
  def initialize(account:, delimiter: "/", prefix: "")
13
16
  @account = account
14
17
  @destination_delimiter = delimiter
@@ -1,8 +1,9 @@
1
1
  require "pathname"
2
2
 
3
3
  require "imap/backup/account/folder"
4
- require "imap/backup/account/folder_ensurer"
5
4
  require "imap/backup/serializer"
5
+ require "imap/backup/serializer/directory_maker"
6
+ require "imap/backup/serializer/files/path"
6
7
 
7
8
  module Imap; end
8
9
 
@@ -13,6 +14,7 @@ module Imap::Backup
13
14
  class Account::SerializedFolders
14
15
  include Enumerable
15
16
 
17
+ # @param account [Account] the account whose serialized folders are iterated
16
18
  def initialize(account:)
17
19
  @account = account
18
20
  end
@@ -26,7 +28,10 @@ module Imap::Backup
26
28
 
27
29
  glob.each do |path|
28
30
  name = path.relative_path_from(base).to_s[0..-6]
29
- serializer = Serializer.new(account.local_path, name)
31
+ files_path = Serializer::Files::Path.new(
32
+ base_path: account.local_path, folder_name: name
33
+ )
34
+ serializer = Serializer.new(files_path: files_path)
30
35
  folder = Account::Folder.new(account.client, name)
31
36
  block.call(serializer, folder)
32
37
  end
@@ -40,7 +45,10 @@ module Imap::Backup
40
45
 
41
46
  glob.each do |path|
42
47
  name = path.relative_path_from(base).to_s[0..-6]
43
- serializer = Serializer.new(account.local_path, name)
48
+ files_path = Serializer::Files::Path.new(
49
+ base_path: account.local_path, folder_name: name
50
+ )
51
+ serializer = Serializer.new(files_path: files_path)
44
52
  block.call(serializer)
45
53
  end
46
54
  end
@@ -68,7 +76,10 @@ module Imap::Backup
68
76
 
69
77
  def glob
70
78
  @glob ||= begin
71
- Account::FolderEnsurer.new(account: account).run
79
+ files_path = Serializer::Files::Path.new(
80
+ base_path: account.local_path, folder_name: nil
81
+ )
82
+ Serializer::DirectoryMaker.new(files_path: files_path).run
72
83
 
73
84
  pattern = File.join(account.local_path, "**", "*.imap")
74
85
  Pathname.glob(pattern)
@@ -4,7 +4,6 @@ require "imap/backup/account/client_factory"
4
4
 
5
5
  module Imap; end
6
6
 
7
- # rubocop:disable Metrics/ClassLength
8
7
  module Imap::Backup
9
8
  # Contains the attributes relating to an email account.
10
9
  class Account
@@ -65,6 +64,25 @@ module Imap::Backup
65
64
  # @return [String] one of "active" (the default), "archived", or "offline"
66
65
  attr_reader :status
67
66
 
67
+ # @param options [Hash] Account attributes
68
+ # @option opts [String] :username the username of the account (usually the same as the email
69
+ # address)
70
+ # @option opts [String] :password the password of the account
71
+ # @option opts [String] :local_path the path where backups will be saved
72
+ # @option opts [Array<String>] :folders (nil) the list of folders that have been configured for
73
+ # the Account
74
+ # @option opts [Boolean] :folder_blacklist (false) whether the folders attribute is a blacklist
75
+ # @option opts [Boolean] :mirror_mode (false) whether to run in mirror mode
76
+ # @option opts [String] :server the address of the IMAP server
77
+ # @option opts [Hash] :connection_options (nil) additional connection options for the IMAP
78
+ # server
79
+ # @option opts [String] :download_strategy (nil) the name of the download strategy to adopt
80
+ # during backups
81
+ # @option opts [Integer] :multi_fetch_size (nil) the number of emails to fetch from the IMAP
82
+ # server at a time
83
+ # @option opts [Boolean] :reset_seen_flags_after_fetch (false) whether to reset seen flags after
84
+ # fetching messages
85
+ # @option opts [String] :status ("active") the status of the account
68
86
  def initialize(options)
69
87
  check_options!(options)
70
88
  @username = options[:username]
@@ -131,19 +149,19 @@ module Imap::Backup
131
149
  # @return [Hash] all Account data for serialization
132
150
  def to_h
133
151
  h = {
134
- username: @username,
135
- password: @password,
152
+ username: username,
153
+ password: password,
136
154
  status: status
137
155
  }
138
- h[:local_path] = @local_path if @local_path
139
- h[:folders] = @folders if @folders
140
- h[:folder_blacklist] = true if @folder_blacklist
141
- h[:mirror_mode] = true if @mirror_mode
142
- h[:server] = @server if @server
143
- h[:connection_options] = @connection_options if connection_options
156
+ h[:local_path] = local_path if local_path
157
+ h[:folders] = folders if folders
158
+ h[:folder_blacklist] = true if folder_blacklist
159
+ h[:mirror_mode] = true if mirror_mode
160
+ h[:server] = server if server
161
+ h[:connection_options] = connection_options if connection_options
144
162
  h[:multi_fetch_size] = multi_fetch_size
145
- if @reset_seen_flags_after_fetch
146
- h[:reset_seen_flags_after_fetch] = @reset_seen_flags_after_fetch
163
+ if reset_seen_flags_after_fetch
164
+ h[:reset_seen_flags_after_fetch] = reset_seen_flags_after_fetch
147
165
  end
148
166
  h
149
167
  end
@@ -169,6 +187,11 @@ module Imap::Backup
169
187
  update(:local_path, value)
170
188
  end
171
189
 
190
+ # @return [Serializer::Files::Path] the base files path for the account
191
+ def files_path
192
+ Serializer::Files::Path.new(base_path: local_path, folder_name: nil)
193
+ end
194
+
172
195
  # @raise [RuntimeError] if the local_path is not set
173
196
  # @return [String] the path to the lockfile for the account
174
197
  def lockfile_path
@@ -216,12 +239,11 @@ module Imap::Backup
216
239
  def connection_options=(value)
217
240
  # Ensure we've loaded the connection_options
218
241
  connection_options
219
- parsed =
220
- if value == ""
221
- nil
222
- else
223
- JSON.parse(value, symbolize_names: true)
224
- end
242
+ parsed = if value == ""
243
+ nil
244
+ else
245
+ JSON.parse(value, symbolize_names: true)
246
+ end
225
247
  update(:connection_options, parsed)
226
248
  end
227
249
 
@@ -15,6 +15,10 @@ module Imap::Backup
15
15
  include Thor::Actions
16
16
  include CLI::Helpers
17
17
 
18
+ # @param options [Hash] CLI options controlling output
19
+ # @option opts [String] :config (nil) the path to the configuration file
20
+ # @option opts [String] :erb_configuration (nil) the path to the ERB configuration file
21
+ # @option opts [Boolean] :refresh (false) whether to force refresh of folder metadata
18
22
  def initialize(options)
19
23
  super([])
20
24
  @options = options
@@ -14,6 +14,11 @@ module Imap::Backup
14
14
  class CLI::Local::Check
15
15
  include CLI::Helpers
16
16
 
17
+ # @param options [Hash] CLI options controlling output
18
+ # @option opts [String] :config (nil) the path to the configuration file
19
+ # @option opts [String] :erb_configuration (nil) the path to the ERB configuration file
20
+ # @option opts [Boolean] :delete_corrupt (false) whether to delete corrupt folders
21
+ # @option opts [String] :format ("text") the output format, either "text" or "json"
17
22
  def initialize(options)
18
23
  @options = options
19
24
  end
@@ -70,6 +70,7 @@ module Imap::Backup
70
70
  }
71
71
  ].freeze
72
72
 
73
+ # @param base [Thor] the command class receiving the options
73
74
  def initialize(base:)
74
75
  @base = base
75
76
  end
@@ -14,6 +14,13 @@ module Imap::Backup
14
14
  include Thor::Actions
15
15
  include CLI::Helpers
16
16
 
17
+ # @param email [String, nil] optional email address identifying the account to restore
18
+ # @param options [Hash] CLI options controlling output
19
+ # @option opts [String] :config (nil) the path to the configuration file
20
+ # @option opts [String] :erb_configuration (nil) the path to the ERB configuration file
21
+ # @option opts [Array<String>] :accounts (nil) the accounts to restore
22
+ # @option opts [String] :delimiter ("/") the destination folder delimiter
23
+ # @option opts [String] :prefix ("") a prefix applied to restored folder names
17
24
  def initialize(email = nil, options)
18
25
  super([])
19
26
  @email = email
@@ -30,9 +37,6 @@ module Imap::Backup
30
37
  when email && !options.key?(:accounts)
31
38
  account = account(config, email)
32
39
  restore(account, **restore_options)
33
- when !email && !options.key?(:accounts)
34
- Logger.logger.info "Calling restore without an EMAIL parameter is deprecated"
35
- config.accounts.each { |a| restore(a) }
36
40
  when email && options.key?(:accounts)
37
41
  raise "Missing EMAIL parameter"
38
42
  when !email && options.key?(:accounts)
@@ -41,6 +45,9 @@ module Imap::Backup
41
45
  "please pass a single EMAIL parameter"
42
46
  )
43
47
  requested_accounts(config).each { |a| restore(a) }
48
+ else
49
+ Logger.logger.info "Calling restore without an EMAIL parameter is deprecated"
50
+ config.accounts.each { |a| restore(a) }
44
51
  end
45
52
  end
46
53
  end
@@ -13,6 +13,9 @@ module Imap::Backup
13
13
  include Thor::Actions
14
14
  include CLI::Helpers
15
15
 
16
+ # @param options [Hash] CLI options controlling output
17
+ # @option opts [String] :config (nil) the path to the configuration file
18
+ # @option opts [String] :erb_configuration (nil) the path to the ERB configuration file
16
19
  def initialize(options)
17
20
  super([])
18
21
  @options = options
@@ -12,6 +12,26 @@ module Imap::Backup
12
12
 
13
13
  # Runs a backup without relying on existing configuration
14
14
  class CLI::Single::Backup
15
+ # @param options [Hash] CLI options controlling output
16
+ # @option opts [String] :config (nil) the path to the configuration file
17
+ # @option opts [String] :erb_configuration (nil) the path to the ERB configuration file
18
+ # @option opts [String] :email the email address identifying the account to backup
19
+ # @option opts [String] :password (nil) the password for the account
20
+ # @option opts [String] :password_environment_variable (nil) the name of an environment variable
21
+ # containing the password
22
+ # @option opts [String] :password_file (nil) the path to a file containing the password
23
+ # @option opts [String] :server the IMAP server address
24
+ # @option opts [String] :download_strategy (nil) the download strategy to use, either "delay"
25
+ # or "direct"
26
+ # @option opts [Boolean] :folder_blacklist (false) whether to treat folder list as a blacklist
27
+ # @option opts [Array<String>] :folder ([]) the folders to backup
28
+ # @option opts [String] :path (nil) the local path to store the backup
29
+ # @option opts [Boolean] :mirror (false) whether to run in mirror mode
30
+ # @option opts [Integer] :multi_fetch_size (nil) the number of messages to fetch in a single
31
+ # operation
32
+ # @option opts [Boolean] :refresh (false) whether to force refresh of folder metadata
33
+ # @option opts [Boolean] :reset_seen_flags_after_fetch (false) whether to reset seen flags
34
+ # after fetching messages
15
35
  def initialize(options)
16
36
  @options = options
17
37
  @password = nil