imap-backup 6.0.0.rc2 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/imap-backup.gemspec +5 -1
  3. data/lib/cli_coverage.rb +11 -11
  4. data/lib/email/provider/base.rb +2 -0
  5. data/lib/email/provider/unknown.rb +2 -0
  6. data/lib/email/provider.rb +2 -0
  7. data/lib/imap/backup/account/connection/backup_folders.rb +27 -0
  8. data/lib/imap/backup/account/connection/client_factory.rb +54 -0
  9. data/lib/imap/backup/account/connection/folder_names.rb +26 -0
  10. data/lib/imap/backup/account/connection.rb +11 -95
  11. data/lib/imap/backup/account/folder.rb +9 -6
  12. data/lib/imap/backup/account.rb +3 -5
  13. data/lib/imap/backup/cli/backup.rb +1 -3
  14. data/lib/imap/backup/cli/helpers.rb +24 -22
  15. data/lib/imap/backup/cli/local.rb +20 -13
  16. data/lib/imap/backup/cli/migrate.rb +4 -10
  17. data/lib/imap/backup/cli/restore.rb +8 -7
  18. data/lib/imap/backup/cli/setup.rb +10 -8
  19. data/lib/imap/backup/cli/stats.rb +78 -0
  20. data/lib/imap/backup/cli/status.rb +2 -2
  21. data/lib/imap/backup/cli/utils.rb +4 -6
  22. data/lib/imap/backup/cli.rb +24 -3
  23. data/lib/imap/backup/configuration.rb +9 -11
  24. data/lib/imap/backup/downloader.rb +48 -30
  25. data/lib/imap/backup/migrator.rb +5 -5
  26. data/lib/imap/backup/sanitizer.rb +3 -2
  27. data/lib/imap/backup/serializer/appender.rb +49 -0
  28. data/lib/imap/backup/serializer/message_enumerator.rb +29 -0
  29. data/lib/imap/backup/serializer/unused_name_finder.rb +27 -0
  30. data/lib/imap/backup/serializer.rb +24 -78
  31. data/lib/imap/backup/setup/account/header.rb +75 -0
  32. data/lib/imap/backup/setup/account.rb +14 -91
  33. data/lib/imap/backup/setup/asker.rb +4 -15
  34. data/lib/imap/backup/setup/backup_path.rb +41 -0
  35. data/lib/imap/backup/setup/email.rb +45 -0
  36. data/lib/imap/backup/setup/folder_chooser.rb +3 -3
  37. data/lib/imap/backup/setup/helpers.rb +1 -1
  38. data/lib/imap/backup/setup.rb +5 -4
  39. data/lib/imap/backup/thunderbird/mailbox_exporter.rb +39 -20
  40. data/lib/imap/backup/uploader.rb +46 -8
  41. data/lib/imap/backup/utils.rb +1 -1
  42. data/lib/imap/backup/version.rb +1 -1
  43. data/lib/imap/backup.rb +0 -1
  44. metadata +31 -134
  45. data/spec/features/backup_spec.rb +0 -100
  46. data/spec/features/configuration/minimal_configuration.rb +0 -15
  47. data/spec/features/configuration/missing_configuration.rb +0 -14
  48. data/spec/features/folders_spec.rb +0 -36
  49. data/spec/features/helper.rb +0 -2
  50. data/spec/features/local/list_accounts_spec.rb +0 -12
  51. data/spec/features/local/list_emails_spec.rb +0 -21
  52. data/spec/features/local/list_folders_spec.rb +0 -21
  53. data/spec/features/local/show_an_email_spec.rb +0 -34
  54. data/spec/features/migrate_spec.rb +0 -35
  55. data/spec/features/remote/list_account_folders_spec.rb +0 -16
  56. data/spec/features/restore_spec.rb +0 -162
  57. data/spec/features/status_spec.rb +0 -43
  58. data/spec/features/support/aruba.rb +0 -78
  59. data/spec/features/support/backup_directory.rb +0 -43
  60. data/spec/features/support/email_server.rb +0 -110
  61. data/spec/features/support/shared/connection_context.rb +0 -14
  62. data/spec/features/support/shared/message_fixtures.rb +0 -16
  63. data/spec/fixtures/connection.yml +0 -7
  64. data/spec/spec_helper.rb +0 -15
  65. data/spec/support/fixtures.rb +0 -11
  66. data/spec/support/higline_test_helpers.rb +0 -8
  67. data/spec/support/silence_logging.rb +0 -7
  68. data/spec/unit/email/mboxrd/message_spec.rb +0 -177
  69. data/spec/unit/email/provider/apple_mail_spec.rb +0 -7
  70. data/spec/unit/email/provider/base_spec.rb +0 -11
  71. data/spec/unit/email/provider/fastmail_spec.rb +0 -7
  72. data/spec/unit/email/provider/gmail_spec.rb +0 -7
  73. data/spec/unit/email/provider_spec.rb +0 -27
  74. data/spec/unit/imap/backup/account/connection_spec.rb +0 -433
  75. data/spec/unit/imap/backup/account/folder_spec.rb +0 -261
  76. data/spec/unit/imap/backup/account_spec.rb +0 -246
  77. data/spec/unit/imap/backup/cli/accounts_spec.rb +0 -58
  78. data/spec/unit/imap/backup/cli/backup_spec.rb +0 -19
  79. data/spec/unit/imap/backup/cli/folders_spec.rb +0 -39
  80. data/spec/unit/imap/backup/cli/helpers_spec.rb +0 -87
  81. data/spec/unit/imap/backup/cli/local_spec.rb +0 -100
  82. data/spec/unit/imap/backup/cli/migrate_spec.rb +0 -80
  83. data/spec/unit/imap/backup/cli/restore_spec.rb +0 -67
  84. data/spec/unit/imap/backup/cli/setup_spec.rb +0 -17
  85. data/spec/unit/imap/backup/cli/utils_spec.rb +0 -125
  86. data/spec/unit/imap/backup/cli_spec.rb +0 -93
  87. data/spec/unit/imap/backup/client/apple_mail_spec.rb +0 -9
  88. data/spec/unit/imap/backup/client/default_spec.rb +0 -22
  89. data/spec/unit/imap/backup/configuration_spec.rb +0 -238
  90. data/spec/unit/imap/backup/downloader_spec.rb +0 -96
  91. data/spec/unit/imap/backup/logger_spec.rb +0 -48
  92. data/spec/unit/imap/backup/migrator_spec.rb +0 -58
  93. data/spec/unit/imap/backup/sanitizer_spec.rb +0 -42
  94. data/spec/unit/imap/backup/serializer/directory_spec.rb +0 -37
  95. data/spec/unit/imap/backup/serializer/imap_spec.rb +0 -218
  96. data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +0 -45
  97. data/spec/unit/imap/backup/serializer/mbox_spec.rb +0 -101
  98. data/spec/unit/imap/backup/serializer_spec.rb +0 -296
  99. data/spec/unit/imap/backup/setup/account_spec.rb +0 -461
  100. data/spec/unit/imap/backup/setup/asker_spec.rb +0 -137
  101. data/spec/unit/imap/backup/setup/connection_tester_spec.rb +0 -51
  102. data/spec/unit/imap/backup/setup/folder_chooser_spec.rb +0 -146
  103. data/spec/unit/imap/backup/setup/helpers_spec.rb +0 -15
  104. data/spec/unit/imap/backup/setup_spec.rb +0 -301
  105. data/spec/unit/imap/backup/thunderbird/mailbox_exporter_spec.rb +0 -116
  106. data/spec/unit/imap/backup/uploader_spec.rb +0 -54
  107. data/spec/unit/imap/backup/utils_spec.rb +0 -92
  108. data/spec/unit/retry_on_error_spec.rb +0 -34
@@ -0,0 +1,75 @@
1
+ require "imap/backup/setup/helpers"
2
+
3
+ module Imap::Backup
4
+ class Setup; end
5
+ class Setup::Account; end
6
+
7
+ class Setup::Account::Header
8
+ attr_reader :account
9
+ attr_reader :menu
10
+
11
+ def initialize(menu:, account:)
12
+ @menu = menu
13
+ @account = account
14
+ end
15
+
16
+ def run
17
+ menu.header = <<~HEADER.chomp
18
+ #{helpers.title_prefix} Account#{modified_flag}
19
+
20
+ email #{space}#{account.username}
21
+ password#{space}#{masked_password}
22
+ path #{space}#{local_path}
23
+ folders #{space}#{folders.map { |f| f[:name] }.join(', ')}#{multi_fetch_size}
24
+ server #{space}#{account.server}#{connection_options}
25
+
26
+ Choose an action
27
+ HEADER
28
+ end
29
+
30
+ private
31
+
32
+ def folders
33
+ account.folders || []
34
+ end
35
+
36
+ def helpers
37
+ Setup::Helpers.new
38
+ end
39
+
40
+ def modified_flag
41
+ account.modified? ? "*" : ""
42
+ end
43
+
44
+ def multi_fetch_size
45
+ "\nmulti-fetch #{account.multi_fetch_size}" if account.multi_fetch_size > 1
46
+ end
47
+
48
+ def connection_options
49
+ return nil if !account.connection_options
50
+
51
+ escaped = JSON.generate(account.connection_options)
52
+ escaped.gsub!('"', '\"')
53
+ "\nconnection options '#{escaped}'"
54
+ end
55
+
56
+ def space
57
+ account.connection_options ? " " * 12 : " " * 4
58
+ end
59
+
60
+ def masked_password
61
+ if (account.password == "") || account.password.nil?
62
+ "(unset)"
63
+ else
64
+ account.password.gsub(/./, "x")
65
+ end
66
+ end
67
+
68
+ def local_path
69
+ # In order to handle backslashes, as Highline effectively
70
+ # does an eval (!) on its templates, we need to doubly
71
+ # escape them
72
+ account.local_path.gsub("\\", "\\\\\\\\")
73
+ end
74
+ end
75
+ end
@@ -1,11 +1,19 @@
1
- require "imap/backup/setup/helpers"
1
+ require "imap/backup/setup/account/header"
2
+ require "imap/backup/setup/backup_path"
3
+ require "imap/backup/setup/email"
2
4
 
3
5
  module Imap::Backup
4
6
  class Setup; end
5
7
 
6
- Setup::Account = Struct.new(:config, :account, :highline) do
8
+ class Setup::Account
9
+ attr_reader :account
10
+ attr_reader :config
11
+ attr_reader :highline
12
+
7
13
  def initialize(config, account, highline)
8
- super
14
+ @account = account
15
+ @config = config
16
+ @highline = highline
9
17
  end
10
18
 
11
19
  def run
@@ -37,54 +45,12 @@ module Imap::Backup
37
45
  end
38
46
 
39
47
  def header(menu)
40
- modified = account.modified? ? "*" : ""
41
-
42
- if account.multi_fetch_size > 1
43
- multi_fetch_size = "\nmulti-fetch #{account.multi_fetch_size}"
44
- end
45
-
46
- if account.connection_options
47
- escaped =
48
- JSON.generate(account.connection_options)
49
- connection_options =
50
- "\nconnection options '#{escaped}'"
51
- space = " " * 12
52
- else
53
- connection_options = nil
54
- space = " " * 4
55
- end
56
-
57
- menu.header = <<~HEADER.chomp
58
- #{helpers.title_prefix} Account#{modified}
59
-
60
- email #{space}#{account.username}
61
- password#{space}#{masked_password}
62
- path #{space}#{account.local_path}
63
- folders #{space}#{folders.map { |f| f[:name] }.join(', ')}#{multi_fetch_size}
64
- server #{space}#{account.server}#{connection_options}
65
-
66
- Choose an action
67
- HEADER
48
+ Setup::Account::Header.new(menu: menu, account: account).run
68
49
  end
69
50
 
70
51
  def modify_email(menu)
71
52
  menu.choice("modify email") do
72
- username = Setup::Asker.email(username)
73
- Kernel.puts "username: #{username}"
74
- other_accounts = config.accounts.reject { |a| a == account }
75
- others = other_accounts.map { |a| a.username }
76
- Kernel.puts "others: #{others.inspect}"
77
- if others.include?(username)
78
- Kernel.puts(
79
- "There is already an account set up with that email address"
80
- )
81
- else
82
- account.username = username
83
- default = default_server(username)
84
- if default && (account.server.nil? || (account.server == ""))
85
- account.server = default
86
- end
87
- end
53
+ Setup::Email.new(account: account, config: config).run
88
54
  end
89
55
  end
90
56
 
@@ -96,25 +62,9 @@ module Imap::Backup
96
62
  end
97
63
  end
98
64
 
99
- def path_modification_validator(path)
100
- same = config.accounts.find do |a|
101
- a.username != account.username && a.local_path == path
102
- end
103
- if same
104
- Kernel.puts "The path '#{path}' is used to backup " \
105
- "the account '#{same.username}'"
106
- false
107
- else
108
- true
109
- end
110
- end
111
-
112
65
  def modify_backup_path(menu)
113
66
  menu.choice("modify backup path") do
114
- existing = account.local_path.clone
115
- account.local_path = Setup::Asker.backup_path(
116
- account.local_path, ->(path) { path_modification_validator(path) }
117
- )
67
+ Setup::BackupPath.new(account: account, config: config).run
118
68
  end
119
69
  end
120
70
 
@@ -169,32 +119,5 @@ module Imap::Backup
169
119
  end
170
120
  end
171
121
  end
172
-
173
- def folders
174
- account.folders || []
175
- end
176
-
177
- def masked_password
178
- if (account.password == "") || account.password.nil?
179
- "(unset)"
180
- else
181
- account.password.gsub(/./, "x")
182
- end
183
- end
184
-
185
- def default_server(username)
186
- provider = Email::Provider.for_address(username)
187
-
188
- if provider.is_a?(Email::Provider::Unknown)
189
- Kernel.puts "Can't decide provider for email address '#{username}'"
190
- return nil
191
- end
192
-
193
- provider.host
194
- end
195
-
196
- def helpers
197
- Setup::Helpers.new
198
- end
199
122
  end
200
123
  end
@@ -1,11 +1,13 @@
1
1
  module Imap::Backup
2
2
  class Setup; end
3
3
 
4
- Setup::Asker = Struct.new(:highline) do
4
+ class Setup::Asker
5
5
  EMAIL_MATCHER = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]+$/i.freeze
6
6
 
7
+ attr_reader :highline
8
+
7
9
  def initialize(highline)
8
- super
10
+ @highline = highline
9
11
  end
10
12
 
11
13
  def email(default = "")
@@ -30,15 +32,6 @@ module Imap::Backup
30
32
  password
31
33
  end
32
34
 
33
- def backup_path(default, validator)
34
- highline.ask("backup directory: ") do |q|
35
- q.default = default
36
- q.readline = true
37
- q.validate = validator
38
- q.responses[:not_valid] = "Choose a different directory "
39
- end
40
- end
41
-
42
35
  def self.email(default = "")
43
36
  new(Setup.highline).email(default)
44
37
  end
@@ -46,9 +39,5 @@ module Imap::Backup
46
39
  def self.password
47
40
  new(Setup.highline).password
48
41
  end
49
-
50
- def self.backup_path(default, validator)
51
- new(Setup.highline).backup_path(default, validator)
52
- end
53
42
  end
54
43
  end
@@ -0,0 +1,41 @@
1
+ module Imap::Backup
2
+ class Setup; end
3
+
4
+ class Setup::BackupPath
5
+ attr_reader :account
6
+ attr_reader :config
7
+
8
+ def initialize(account:, config:)
9
+ @account = account
10
+ @config = config
11
+ end
12
+
13
+ def run
14
+ account.local_path = highline.ask("backup directory: ") do |q|
15
+ q.default = account.local_path
16
+ q.readline = true
17
+ q.validate = ->(path) { path_modification_validator(path) }
18
+ q.responses[:not_valid] = "Choose a different directory "
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def highline
25
+ Setup.highline
26
+ end
27
+
28
+ def path_modification_validator(path)
29
+ same = config.accounts.find do |a|
30
+ a.username != account.username && a.local_path == path
31
+ end
32
+ if same
33
+ Kernel.puts "The path '#{path}' is used to backup " \
34
+ "the account '#{same.username}'"
35
+ false
36
+ else
37
+ true
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ require "email/provider"
2
+
3
+ module Imap::Backup
4
+ class Setup; end
5
+
6
+ class Setup::Email
7
+ attr_reader :account
8
+ attr_reader :config
9
+
10
+ def initialize(account:, config:)
11
+ @account = account
12
+ @config = config
13
+ end
14
+
15
+ def run
16
+ username = Setup::Asker.email(account.username)
17
+ other_accounts = config.accounts.reject { |a| a == account }
18
+ others = other_accounts.map(&:username)
19
+ if others.include?(username)
20
+ Kernel.puts(
21
+ "There is already an account set up with that email address"
22
+ )
23
+ else
24
+ account.username = username
25
+ if account.server.nil? || (account.server == "")
26
+ default = default_server(username)
27
+ account.server = default if default
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def default_server(username)
35
+ provider = Email::Provider.for_address(username)
36
+
37
+ if provider.is_a?(Email::Provider::Unknown)
38
+ Kernel.puts "Can't decide provider for email address '#{username}'"
39
+ return nil
40
+ end
41
+
42
+ provider.host
43
+ end
44
+ end
45
+ end
@@ -12,13 +12,13 @@ module Imap::Backup
12
12
 
13
13
  def run
14
14
  if connection.nil?
15
- Imap::Backup::Logger.logger.warn "Connection failed"
15
+ Logger.logger.warn "Connection failed"
16
16
  highline.ask "Press a key "
17
17
  return
18
18
  end
19
19
 
20
20
  if imap_folders.nil?
21
- Imap::Backup::Logger.logger.warn "Unable to get folder list"
21
+ Logger.logger.warn "Unable to get folder list"
22
22
  highline.ask "Press a key "
23
23
  return
24
24
  end
@@ -90,7 +90,7 @@ module Imap::Backup
90
90
 
91
91
  def toggle_selection(folder_name)
92
92
  if selected?(folder_name)
93
- new_list = account.folders.select { |f| f[:name] != folder_name }
93
+ new_list = account.folders.reject { |f| f[:name] == folder_name }
94
94
  account.folders = new_list
95
95
  else
96
96
  existing = account.folders || []
@@ -5,7 +5,7 @@ module Imap::Backup
5
5
 
6
6
  class Setup::Helpers
7
7
  def title_prefix
8
- "imap-backup "
8
+ "imap-backup -"
9
9
  end
10
10
 
11
11
  def version
@@ -1,5 +1,6 @@
1
1
  require "highline"
2
2
 
3
+ require "email/provider"
3
4
  require "imap/backup/account"
4
5
  require "imap/backup/setup/helpers"
5
6
 
@@ -36,7 +37,7 @@ module Imap::Backup
36
37
  config.save
37
38
  throw :done
38
39
  end
39
- menu.choice("exit without saving changes") { throw :done }
40
+ menu.choice("exit without saving changes") { throw :done }
40
41
  else
41
42
  menu.choice("quit") { throw :done }
42
43
  end
@@ -67,7 +68,7 @@ module Imap::Backup
67
68
  new_setting = !config.debug?
68
69
  menu.choice(menu_item) do
69
70
  config.debug = new_setting
70
- Imap::Backup::Logger.setup_logging(config)
71
+ Logger.setup_logging(config)
71
72
  end
72
73
  end
73
74
 
@@ -76,13 +77,13 @@ module Imap::Backup
76
77
  end
77
78
 
78
79
  def default_account_config(username)
79
- ::Imap::Backup::Account.new(
80
+ Imap::Backup::Account.new(
80
81
  username: username,
81
82
  password: "",
82
83
  local_path: File.join(config.path, username.tr("@", "_")),
83
84
  folders: []
84
85
  ).tap do |a|
85
- server = Email::Provider.for_address(username)
86
+ server = ::Email::Provider.for_address(username)
86
87
  a.server = server.host if server.host
87
88
  end
88
89
  end
@@ -21,28 +21,51 @@ module Imap::Backup
21
21
  local_folder_ok = local_folder.set_up
22
22
  return false if !local_folder_ok
23
23
 
24
- if local_folder.msf_exists?
25
- if force
26
- Kernel.puts "Deleting '#{local_folder.msf_path}' as --force option was supplied"
27
- File.unlink local_folder.msf_path
28
- else
29
- Kernel.puts "Skipping export of '#{serializer.folder}' as '#{local_folder.msf_path}' exists"
30
- return false
31
- end
24
+ skip_for_msf = check_msf
25
+ return false if skip_for_msf
26
+
27
+ skip_for_local_folder = check_local_folder
28
+ return false if skip_for_local_folder
29
+
30
+ copy_messages
31
+
32
+ true
33
+ end
34
+
35
+ private
36
+
37
+ def check_local_folder
38
+ return false if !local_folder.exists?
39
+
40
+ if force
41
+ Kernel.puts "Overwriting '#{local_folder.path}' as --force option was supplied"
42
+ return false
32
43
  end
33
44
 
34
- if local_folder.exists?
35
- if force
36
- Kernel.puts "Overwriting '#{local_folder.path}' as --force option was supplied"
37
- else
38
- Kernel.puts "Skipping export of '#{serializer.folder}' as '#{local_folder.path}' exists"
39
- return false
40
- end
45
+ Kernel.puts "Skipping export of '#{serializer.folder}' as '#{local_folder.path}' exists"
46
+ true
47
+ end
48
+
49
+ def check_msf
50
+ return false if !local_folder.msf_exists?
51
+
52
+ if force
53
+ Kernel.puts "Deleting '#{local_folder.msf_path}' as --force option was supplied"
54
+ File.unlink local_folder.msf_path
55
+ return false
41
56
  end
42
57
 
58
+ Kernel.puts(
59
+ "Skipping export of '#{serializer.folder}' " \
60
+ "as '#{local_folder.msf_path}' exists"
61
+ )
62
+ true
63
+ end
64
+
65
+ def copy_messages
43
66
  File.open(local_folder.full_path, "w") do |f|
44
67
  enumerator = Serializer::MboxEnumerator.new(serializer.mbox_pathname)
45
- enumerator.each.with_index do |raw, i|
68
+ enumerator.each do |raw|
46
69
  clean = Email::Mboxrd::Message.clean_serialized(raw)
47
70
  timestamp = Time.now.strftime("%a %b %d %H:%M:%S %Y")
48
71
  thunderbird_fom_line = "From - #{timestamp}"
@@ -50,12 +73,8 @@ module Imap::Backup
50
73
  f.write output
51
74
  end
52
75
  end
53
-
54
- true
55
76
  end
56
77
 
57
- private
58
-
59
78
  def local_folder
60
79
  @local_folder ||= begin
61
80
  top_level_folders = [EXPORT_PREFIX, email]
@@ -9,27 +9,65 @@ module Imap::Backup
9
9
  end
10
10
 
11
11
  def run
12
- count = missing_uids.count
12
+ if folder.uids.any?
13
+ rename_serialized_folder
14
+ else
15
+ folder.create
16
+ serializer.force_uid_validity(folder.uid_validity)
17
+ end
18
+
13
19
  return if count.zero?
14
20
 
15
- Imap::Backup::Logger.logger.debug "[#{folder.name}] #{count} to restore"
21
+ Logger.logger.debug "[#{folder.name}] #{count} to restore"
16
22
  serializer.each_message(missing_uids).with_index do |(uid, message), i|
17
- next if message.nil?
23
+ upload_message uid, message, i + 1
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def upload_message(uid, message, index)
30
+ return if message.nil?
18
31
 
19
- log_prefix = "[#{folder.name}] uid: #{uid} (#{i + 1}/#{count}) -"
20
- Imap::Backup::Logger.logger.debug(
21
- "#{log_prefix} #{message.supplied_body.size} bytes"
22
- )
32
+ log_prefix = "[#{folder.name}] uid: #{uid} (#{index}/#{count}) -"
33
+ Logger.logger.debug(
34
+ "#{log_prefix} #{message.supplied_body.size} bytes"
35
+ )
23
36
 
37
+ begin
24
38
  new_uid = folder.append(message)
25
39
  serializer.update_uid(uid, new_uid)
40
+ rescue StandardError => e
41
+ Logger.logger.warn "#{log_prefix} append error: #{e}"
26
42
  end
27
43
  end
28
44
 
29
- private
45
+ def count
46
+ @count ||= missing_uids.count
47
+ end
30
48
 
31
49
  def missing_uids
32
50
  serializer.uids - folder.uids
33
51
  end
52
+
53
+ def rename_serialized_folder
54
+ Logger.logger.debug(
55
+ "There's already a '#{folder.name}' folder with emails"
56
+ )
57
+
58
+ # Rename the local folder to a unique name
59
+ new_name = serializer.apply_uid_validity(folder.uid_validity)
60
+
61
+ return if !new_name
62
+
63
+ # Restore the renamed folder
64
+ Logger.logger.debug(
65
+ "Backup '#{serializer.folder}' renamed and restored to '#{new_name}'"
66
+ )
67
+ @folder = Account::Folder.new(folder.connection, new_name)
68
+ folder.create
69
+ @serializer = Serializer.new(serializer.path, new_name)
70
+ serializer.force_uid_validity(@folder.uid_validity)
71
+ end
34
72
  end
35
73
  end
@@ -11,7 +11,7 @@ module Imap::Backup
11
11
 
12
12
  message = format(
13
13
  "Permissions on '%<filename>s' " \
14
- "should be 0%<limit>o, not 0%<actual>o",
14
+ "should be 0%<limit>o, not 0%<actual>o",
15
15
  filename: filename, limit: limit, actual: actual
16
16
  )
17
17
  raise message
@@ -4,6 +4,6 @@ module Imap::Backup
4
4
  MAJOR = 6
5
5
  MINOR = 0
6
6
  REVISION = 0
7
- PRE = "rc2".freeze
7
+ PRE = nil
8
8
  VERSION = [MAJOR, MINOR, REVISION, PRE].compact.map(&:to_s).join(".")
9
9
  end
data/lib/imap/backup.rb CHANGED
@@ -14,7 +14,6 @@ require "imap/backup/setup/asker"
14
14
  require "imap/backup/setup/connection_tester"
15
15
  require "imap/backup/setup/folder_chooser"
16
16
  require "imap/backup/version"
17
- require "email/provider"
18
17
 
19
18
  module Imap::Backup
20
19
  class ConfigurationNotFound < StandardError; end