imap-backup 6.0.0.rc2 → 6.0.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 +4 -4
- data/imap-backup.gemspec +5 -1
- data/lib/cli_coverage.rb +11 -11
- data/lib/email/provider/base.rb +2 -0
- data/lib/email/provider/unknown.rb +2 -0
- data/lib/email/provider.rb +2 -0
- data/lib/imap/backup/account/connection/backup_folders.rb +27 -0
- data/lib/imap/backup/account/connection/client_factory.rb +54 -0
- data/lib/imap/backup/account/connection/folder_names.rb +26 -0
- data/lib/imap/backup/account/connection.rb +11 -95
- data/lib/imap/backup/account/folder.rb +9 -6
- data/lib/imap/backup/account.rb +3 -5
- data/lib/imap/backup/cli/backup.rb +1 -3
- data/lib/imap/backup/cli/helpers.rb +24 -22
- data/lib/imap/backup/cli/local.rb +20 -13
- data/lib/imap/backup/cli/migrate.rb +4 -10
- data/lib/imap/backup/cli/restore.rb +8 -7
- data/lib/imap/backup/cli/setup.rb +10 -8
- data/lib/imap/backup/cli/stats.rb +78 -0
- data/lib/imap/backup/cli/status.rb +2 -2
- data/lib/imap/backup/cli/utils.rb +4 -6
- data/lib/imap/backup/cli.rb +24 -3
- data/lib/imap/backup/configuration.rb +9 -11
- data/lib/imap/backup/downloader.rb +48 -30
- data/lib/imap/backup/migrator.rb +5 -5
- data/lib/imap/backup/sanitizer.rb +3 -2
- data/lib/imap/backup/serializer/appender.rb +49 -0
- data/lib/imap/backup/serializer/message_enumerator.rb +29 -0
- data/lib/imap/backup/serializer/unused_name_finder.rb +27 -0
- data/lib/imap/backup/serializer.rb +24 -78
- data/lib/imap/backup/setup/account/header.rb +75 -0
- data/lib/imap/backup/setup/account.rb +14 -91
- data/lib/imap/backup/setup/asker.rb +4 -15
- data/lib/imap/backup/setup/backup_path.rb +41 -0
- data/lib/imap/backup/setup/email.rb +45 -0
- data/lib/imap/backup/setup/folder_chooser.rb +3 -3
- data/lib/imap/backup/setup/helpers.rb +1 -1
- data/lib/imap/backup/setup.rb +5 -4
- data/lib/imap/backup/thunderbird/mailbox_exporter.rb +39 -20
- data/lib/imap/backup/uploader.rb +46 -8
- data/lib/imap/backup/utils.rb +1 -1
- data/lib/imap/backup/version.rb +1 -1
- data/lib/imap/backup.rb +0 -1
- metadata +31 -134
- data/spec/features/backup_spec.rb +0 -100
- data/spec/features/configuration/minimal_configuration.rb +0 -15
- data/spec/features/configuration/missing_configuration.rb +0 -14
- data/spec/features/folders_spec.rb +0 -36
- data/spec/features/helper.rb +0 -2
- data/spec/features/local/list_accounts_spec.rb +0 -12
- data/spec/features/local/list_emails_spec.rb +0 -21
- data/spec/features/local/list_folders_spec.rb +0 -21
- data/spec/features/local/show_an_email_spec.rb +0 -34
- data/spec/features/migrate_spec.rb +0 -35
- data/spec/features/remote/list_account_folders_spec.rb +0 -16
- data/spec/features/restore_spec.rb +0 -162
- data/spec/features/status_spec.rb +0 -43
- data/spec/features/support/aruba.rb +0 -78
- data/spec/features/support/backup_directory.rb +0 -43
- data/spec/features/support/email_server.rb +0 -110
- data/spec/features/support/shared/connection_context.rb +0 -14
- data/spec/features/support/shared/message_fixtures.rb +0 -16
- data/spec/fixtures/connection.yml +0 -7
- data/spec/spec_helper.rb +0 -15
- data/spec/support/fixtures.rb +0 -11
- data/spec/support/higline_test_helpers.rb +0 -8
- data/spec/support/silence_logging.rb +0 -7
- data/spec/unit/email/mboxrd/message_spec.rb +0 -177
- data/spec/unit/email/provider/apple_mail_spec.rb +0 -7
- data/spec/unit/email/provider/base_spec.rb +0 -11
- data/spec/unit/email/provider/fastmail_spec.rb +0 -7
- data/spec/unit/email/provider/gmail_spec.rb +0 -7
- data/spec/unit/email/provider_spec.rb +0 -27
- data/spec/unit/imap/backup/account/connection_spec.rb +0 -433
- data/spec/unit/imap/backup/account/folder_spec.rb +0 -261
- data/spec/unit/imap/backup/account_spec.rb +0 -246
- data/spec/unit/imap/backup/cli/accounts_spec.rb +0 -58
- data/spec/unit/imap/backup/cli/backup_spec.rb +0 -19
- data/spec/unit/imap/backup/cli/folders_spec.rb +0 -39
- data/spec/unit/imap/backup/cli/helpers_spec.rb +0 -87
- data/spec/unit/imap/backup/cli/local_spec.rb +0 -100
- data/spec/unit/imap/backup/cli/migrate_spec.rb +0 -80
- data/spec/unit/imap/backup/cli/restore_spec.rb +0 -67
- data/spec/unit/imap/backup/cli/setup_spec.rb +0 -17
- data/spec/unit/imap/backup/cli/utils_spec.rb +0 -125
- data/spec/unit/imap/backup/cli_spec.rb +0 -93
- data/spec/unit/imap/backup/client/apple_mail_spec.rb +0 -9
- data/spec/unit/imap/backup/client/default_spec.rb +0 -22
- data/spec/unit/imap/backup/configuration_spec.rb +0 -238
- data/spec/unit/imap/backup/downloader_spec.rb +0 -96
- data/spec/unit/imap/backup/logger_spec.rb +0 -48
- data/spec/unit/imap/backup/migrator_spec.rb +0 -58
- data/spec/unit/imap/backup/sanitizer_spec.rb +0 -42
- data/spec/unit/imap/backup/serializer/directory_spec.rb +0 -37
- data/spec/unit/imap/backup/serializer/imap_spec.rb +0 -218
- data/spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb +0 -45
- data/spec/unit/imap/backup/serializer/mbox_spec.rb +0 -101
- data/spec/unit/imap/backup/serializer_spec.rb +0 -296
- data/spec/unit/imap/backup/setup/account_spec.rb +0 -461
- data/spec/unit/imap/backup/setup/asker_spec.rb +0 -137
- data/spec/unit/imap/backup/setup/connection_tester_spec.rb +0 -51
- data/spec/unit/imap/backup/setup/folder_chooser_spec.rb +0 -146
- data/spec/unit/imap/backup/setup/helpers_spec.rb +0 -15
- data/spec/unit/imap/backup/setup_spec.rb +0 -301
- data/spec/unit/imap/backup/thunderbird/mailbox_exporter_spec.rb +0 -116
- data/spec/unit/imap/backup/uploader_spec.rb +0 -54
- data/spec/unit/imap/backup/utils_spec.rb +0 -92
- data/spec/unit/retry_on_error_spec.rb +0 -34
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
module Imap::Backup
|
|
2
|
-
describe Serializer::Imap do
|
|
3
|
-
subject { described_class.new(folder_path) }
|
|
4
|
-
|
|
5
|
-
let(:folder_path) { "folder_path" }
|
|
6
|
-
let(:pathname) { "folder_path.imap" }
|
|
7
|
-
let(:exists) { true }
|
|
8
|
-
let(:existing) { {uid_validity: 99, uids: [42]} }
|
|
9
|
-
let(:file) { instance_double(File, write: nil) }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
allow(File).to receive(:exist?).and_call_original
|
|
13
|
-
allow(File).to receive(:exist?).with(pathname) { exists }
|
|
14
|
-
allow(File).to receive(:open).and_call_original
|
|
15
|
-
allow(File).to receive(:open).with(pathname, "w").and_yield(file)
|
|
16
|
-
allow(File).to receive(:read).with(pathname) { existing.to_json }
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
describe "loading the metadata file" do
|
|
20
|
-
context "when it is malformed" do
|
|
21
|
-
before do
|
|
22
|
-
allow(File).to receive(:read).with(pathname).and_raise(JSON::ParserError)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it "ignores the file" do
|
|
26
|
-
subject.uid_validity
|
|
27
|
-
|
|
28
|
-
expect(subject.uids).to eq([])
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
describe "#append" do
|
|
34
|
-
context "when the metadata file exists" do
|
|
35
|
-
before { subject.append(123) }
|
|
36
|
-
|
|
37
|
-
it "loads the existing metadata" do
|
|
38
|
-
expect(subject.uids).to include(42)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
it "appends the UID" do
|
|
42
|
-
expect(subject.uids).to include(123)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it "saves the file" do
|
|
46
|
-
expect(file).to have_received(:write).
|
|
47
|
-
with(/"uids":\[42,123\]/)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
context "when the metadata file doesn't exist" do
|
|
52
|
-
let(:exists) { false }
|
|
53
|
-
|
|
54
|
-
context "when the uid_validity is set" do
|
|
55
|
-
before do
|
|
56
|
-
subject.uid_validity = 999
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it "appends the UID" do
|
|
60
|
-
subject.append(123)
|
|
61
|
-
|
|
62
|
-
expect(subject.uids).to include(123)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
it "saves the file" do
|
|
66
|
-
subject.append(123)
|
|
67
|
-
|
|
68
|
-
expect(file).to have_received(:write).
|
|
69
|
-
with(/"uids":\[123\]/)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
context "when the uid_validity is not set" do
|
|
74
|
-
it "fails" do
|
|
75
|
-
expect do
|
|
76
|
-
subject.append(123)
|
|
77
|
-
end.to raise_error(RuntimeError, /without a uid_validity/)
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
describe "#exist?" do
|
|
84
|
-
context "when the metadata file exists" do
|
|
85
|
-
it "is true" do
|
|
86
|
-
expect(subject.exist?).to be true
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
context "when the metadata file doesn't exist" do
|
|
91
|
-
let(:exists) { false }
|
|
92
|
-
|
|
93
|
-
it "is false" do
|
|
94
|
-
expect(subject.exist?).to be false
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
describe "#include?" do
|
|
100
|
-
it "loads the existing metadata" do
|
|
101
|
-
subject.include?(42)
|
|
102
|
-
|
|
103
|
-
expect(File).to have_received(:read).with(pathname)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
context "when there is a matching UID" do
|
|
107
|
-
it "is true" do
|
|
108
|
-
expect(subject.include?(42)).to be true
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
context "when there isn't a matching UID" do
|
|
113
|
-
it "is false" do
|
|
114
|
-
expect(subject.include?(99)).to be false
|
|
115
|
-
end
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
describe "#index" do
|
|
120
|
-
it "loads the existing metadata" do
|
|
121
|
-
subject.include?(42)
|
|
122
|
-
|
|
123
|
-
expect(File).to have_received(:read).with(pathname)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
context "when there is a matching UID" do
|
|
127
|
-
it "returns the index of the matcing UID" do
|
|
128
|
-
expect(subject.index(42)).to eq(0)
|
|
129
|
-
end
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
context "when there isn't a matching UID" do
|
|
133
|
-
it "is nil" do
|
|
134
|
-
expect(subject.index(99)).to be nil
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
describe "#rename" do
|
|
140
|
-
before do
|
|
141
|
-
allow(File).to receive(:rename)
|
|
142
|
-
|
|
143
|
-
subject.rename("new_path")
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
context "when the metadata file exists" do
|
|
147
|
-
it "sets the folder_path" do
|
|
148
|
-
expect(subject.folder_path).to eq("new_path")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "renames the metadata file" do
|
|
152
|
-
expect(File).to have_received(:rename).with(pathname, "new_path.imap")
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
context "when the metadata file doesn't exist" do
|
|
157
|
-
let(:exists) { false }
|
|
158
|
-
|
|
159
|
-
it "sets the folder_path" do
|
|
160
|
-
expect(subject.folder_path).to eq("new_path")
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
it "doesn't try to rename the metadata file" do
|
|
164
|
-
expect(File).to_not have_received(:rename)
|
|
165
|
-
end
|
|
166
|
-
end
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
describe "#uid_validity" do
|
|
170
|
-
it "returns the uid_validity" do
|
|
171
|
-
expect(subject.uid_validity).to eq(99)
|
|
172
|
-
end
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
describe "#uid_validity=" do
|
|
176
|
-
before { subject.uid_validity = 567 }
|
|
177
|
-
|
|
178
|
-
it "updates the uid_validity" do
|
|
179
|
-
expect(subject.uid_validity).to eq(567)
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
it "saves the file" do
|
|
183
|
-
expect(file).to have_received(:write).
|
|
184
|
-
with(/"uid_validity":567/)
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
context "when no metadata file exists" do
|
|
188
|
-
let(:exists) { false }
|
|
189
|
-
|
|
190
|
-
it "saves an empty list of UIDs" do
|
|
191
|
-
expect(file).to have_received(:write).
|
|
192
|
-
with(/"uids":\[\]/)
|
|
193
|
-
end
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
describe "#update_uid" do
|
|
198
|
-
before { subject.update_uid(42, 57) }
|
|
199
|
-
|
|
200
|
-
it "sets the UID" do
|
|
201
|
-
expect(subject.uids).to eq([57])
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
it "saves the file" do
|
|
205
|
-
expect(file).to have_received(:write).
|
|
206
|
-
with(/"uids":\[57\]/)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
context "when the UID is not present" do
|
|
210
|
-
let(:existing) { {uid_validity: 99, uids: [2]} }
|
|
211
|
-
|
|
212
|
-
it "doesn't save the file" do
|
|
213
|
-
expect(file).to_not have_received(:write)
|
|
214
|
-
end
|
|
215
|
-
end
|
|
216
|
-
end
|
|
217
|
-
end
|
|
218
|
-
end
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
require "imap/backup/serializer/mbox_enumerator"
|
|
2
|
-
|
|
3
|
-
describe Imap::Backup::Serializer::MboxEnumerator do
|
|
4
|
-
subject { described_class.new(mbox_pathname) }
|
|
5
|
-
|
|
6
|
-
let(:mbox_pathname) { "/mbox/pathname" }
|
|
7
|
-
let(:mbox_file) { instance_double(File) }
|
|
8
|
-
let(:lines) { message1 + message2 + [nil] }
|
|
9
|
-
let(:message1) do
|
|
10
|
-
[
|
|
11
|
-
"From Frida\r\n",
|
|
12
|
-
"Hello\r\n"
|
|
13
|
-
]
|
|
14
|
-
end
|
|
15
|
-
let(:message2) do
|
|
16
|
-
[
|
|
17
|
-
"From John\r\n",
|
|
18
|
-
"Hi\r\n"
|
|
19
|
-
]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
before do
|
|
23
|
-
allow(File).to receive(:open).and_call_original
|
|
24
|
-
allow(File).to receive(:open).with(mbox_pathname, "rb").and_yield(mbox_file)
|
|
25
|
-
allow(mbox_file).to receive(:gets).and_return(*lines)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
describe "#each" do
|
|
29
|
-
it "reads files as binary" do
|
|
30
|
-
expect(File).to receive(:open).with(mbox_pathname, "rb")
|
|
31
|
-
subject.each {}
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it "yields messages" do
|
|
35
|
-
expect { |b| subject.each(&b) }.
|
|
36
|
-
to yield_successive_args(message1.join, message2.join)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
context "without a block" do
|
|
40
|
-
it "returns an Enumerator" do
|
|
41
|
-
expect(subject.each).to be_a(Enumerator)
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
end
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
module Imap::Backup
|
|
2
|
-
describe Serializer::Mbox do
|
|
3
|
-
subject { described_class.new(folder_path) }
|
|
4
|
-
|
|
5
|
-
let(:folder_path) { "folder_path" }
|
|
6
|
-
let(:pathname) { "folder_path.mbox" }
|
|
7
|
-
let(:exists) { true }
|
|
8
|
-
let(:file) { instance_double(File, truncate: nil, write: nil) }
|
|
9
|
-
|
|
10
|
-
before do
|
|
11
|
-
allow(File).to receive(:exist?).and_call_original
|
|
12
|
-
allow(File).to receive(:exist?).with(pathname) { exists }
|
|
13
|
-
allow(File).to receive(:open).with(pathname, "ab").and_yield(file)
|
|
14
|
-
allow(File).to receive(:read).with(pathname) { existing.to_json }
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
describe "#append" do
|
|
18
|
-
it "appends the message" do
|
|
19
|
-
subject.append("message")
|
|
20
|
-
|
|
21
|
-
expect(file).to have_received(:write).with("message")
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
describe "#exist?" do
|
|
26
|
-
context "when the mailbox exists" do
|
|
27
|
-
it "is true" do
|
|
28
|
-
expect(subject.exist?).to be true
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
context "when the mailbox doesn't exist" do
|
|
33
|
-
let(:exists) { false }
|
|
34
|
-
|
|
35
|
-
it "is false" do
|
|
36
|
-
expect(subject.exist?).to be false
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
describe "#length" do
|
|
42
|
-
let(:stat) { instance_double(File::Stat, size: 99) }
|
|
43
|
-
|
|
44
|
-
before { allow(File).to receive(:stat) { stat } }
|
|
45
|
-
|
|
46
|
-
it "returns the length of the mailbox file" do
|
|
47
|
-
expect(subject.length).to eq(99)
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
describe "#pathname" do
|
|
52
|
-
it "is the folder_path plus .mbox" do
|
|
53
|
-
expect(subject.pathname).to eq("folder_path.mbox")
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
describe "#rename" do
|
|
58
|
-
context "when the mailbox exists" do
|
|
59
|
-
let(:exists) { true }
|
|
60
|
-
|
|
61
|
-
before do
|
|
62
|
-
allow(File).to receive(:rename)
|
|
63
|
-
|
|
64
|
-
subject.rename("new_name")
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it "renames the mailbox" do
|
|
68
|
-
expect(File).to have_received(:rename)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it "sets the folder_path" do
|
|
72
|
-
expect(subject.folder_path).to eq("new_name")
|
|
73
|
-
end
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
context "when the mailbox doesn't exist" do
|
|
77
|
-
let(:exists) { false }
|
|
78
|
-
|
|
79
|
-
it "sets the folder_path" do
|
|
80
|
-
subject.rename("new_name")
|
|
81
|
-
|
|
82
|
-
expect(subject.folder_path).to eq("new_name")
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
describe "#rewind" do
|
|
88
|
-
before do
|
|
89
|
-
allow(File).to receive(:open).
|
|
90
|
-
with(pathname, File::RDWR | File::CREAT, 0o644).
|
|
91
|
-
and_yield(file)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it "truncates the mailbox" do
|
|
95
|
-
subject.rewind(123)
|
|
96
|
-
|
|
97
|
-
expect(file).to have_received(:truncate).with(123)
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
module Imap::Backup
|
|
2
|
-
describe Serializer do
|
|
3
|
-
subject { described_class.new("path", "folder/sub") }
|
|
4
|
-
|
|
5
|
-
let(:directory) { instance_double(Serializer::Directory, ensure_exists: nil) }
|
|
6
|
-
let(:imap) do
|
|
7
|
-
instance_double(
|
|
8
|
-
Serializer::Imap,
|
|
9
|
-
exist?: true,
|
|
10
|
-
rename: nil,
|
|
11
|
-
uid_validity: existing_uid_validity,
|
|
12
|
-
"uid_validity=": nil
|
|
13
|
-
)
|
|
14
|
-
end
|
|
15
|
-
let(:mbox) do
|
|
16
|
-
instance_double(
|
|
17
|
-
Serializer::Mbox,
|
|
18
|
-
append: nil,
|
|
19
|
-
exist?: false,
|
|
20
|
-
length: 1,
|
|
21
|
-
pathname: "aaa",
|
|
22
|
-
rename: nil,
|
|
23
|
-
rewind: nil
|
|
24
|
-
)
|
|
25
|
-
end
|
|
26
|
-
let(:folder_path) { File.expand_path(File.join("path", "folder/sub")) }
|
|
27
|
-
let(:existing_uid_validity) { nil }
|
|
28
|
-
let(:enumerator) { instance_double(Serializer::MboxEnumerator) }
|
|
29
|
-
|
|
30
|
-
before do
|
|
31
|
-
allow(Serializer::Directory).to receive(:new) { directory }
|
|
32
|
-
allow(Serializer::Imap).to receive(:new).with(folder_path) { imap }
|
|
33
|
-
allow(Serializer::Mbox).to receive(:new) { mbox }
|
|
34
|
-
allow(Serializer::MboxEnumerator).to receive(:new) { enumerator }
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
describe "#apply_uid_validity" do
|
|
38
|
-
let(:imap_test) { instance_double(Serializer::Imap, exist?: imap_test_exists) }
|
|
39
|
-
let(:imap_test_exists) { false }
|
|
40
|
-
let(:test_folder_path) do
|
|
41
|
-
File.expand_path(File.join("path", "folder/sub-#{existing_uid_validity}"))
|
|
42
|
-
end
|
|
43
|
-
let(:result) { subject.apply_uid_validity("new") }
|
|
44
|
-
|
|
45
|
-
before do
|
|
46
|
-
allow(Serializer::Imap).to receive(:new).with(test_folder_path) { imap_test }
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
context "when there is no existing uid_validity" do
|
|
50
|
-
it "sets the metadata file's uid_validity" do
|
|
51
|
-
result
|
|
52
|
-
|
|
53
|
-
expect(imap).to have_received(:"uid_validity=").with("new")
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
context "when the new value is the same as the old value" do
|
|
58
|
-
let(:existing_uid_validity) { "new" }
|
|
59
|
-
|
|
60
|
-
it "does nothing" do
|
|
61
|
-
result
|
|
62
|
-
|
|
63
|
-
expect(imap).to_not have_received(:"uid_validity=")
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
context "when the new value is different from the old value" do
|
|
68
|
-
let(:existing_uid_validity) { "existing" }
|
|
69
|
-
|
|
70
|
-
it "renames the existing mailbox" do
|
|
71
|
-
result
|
|
72
|
-
|
|
73
|
-
expect(mbox).to have_received(:rename).with(test_folder_path)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "renames the existing metadata file" do
|
|
77
|
-
result
|
|
78
|
-
|
|
79
|
-
expect(imap).to have_received(:rename).with(test_folder_path)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
it "returns the new name for the old folder" do
|
|
83
|
-
expect(result).to eq("folder/sub-existing")
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
context "when the default rename is not possible" do
|
|
87
|
-
let(:imap_test_exists) { true }
|
|
88
|
-
let(:imap_test1) { instance_double(Serializer::Imap, exist?: false) }
|
|
89
|
-
let(:test_folder_path1) do
|
|
90
|
-
File.expand_path(File.join("path", "folder/sub-#{existing_uid_validity}-1"))
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
before do
|
|
94
|
-
allow(Serializer::Imap).to receive(:new).with(test_folder_path1) { imap_test1 }
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
it "renames the mailbox, appending a numeral" do
|
|
98
|
-
result
|
|
99
|
-
|
|
100
|
-
expect(mbox).to have_received(:rename).with(test_folder_path1)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it "renames the metadata file, appending a numeral" do
|
|
104
|
-
result
|
|
105
|
-
|
|
106
|
-
expect(imap).to have_received(:rename).with(test_folder_path1)
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
end
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
describe "#force_uid_validity" do
|
|
113
|
-
it "sets the metadata file's uid_validity" do
|
|
114
|
-
subject.force_uid_validity("new")
|
|
115
|
-
|
|
116
|
-
expect(imap).to have_received(:"uid_validity=").with("new")
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
describe "#append" do
|
|
121
|
-
let(:existing_uid_validity) { "42" }
|
|
122
|
-
let(:mboxrd_message) do
|
|
123
|
-
instance_double(Email::Mboxrd::Message, to_serialized: "serialized")
|
|
124
|
-
end
|
|
125
|
-
let(:uid_found) { false }
|
|
126
|
-
let(:command) { subject.append(99, "Hi") }
|
|
127
|
-
|
|
128
|
-
before do
|
|
129
|
-
allow(imap).to receive(:include?) { uid_found }
|
|
130
|
-
allow(imap).to receive(:append)
|
|
131
|
-
allow(Email::Mboxrd::Message).to receive(:new) { mboxrd_message }
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it "appends the message to the mailbox" do
|
|
135
|
-
command
|
|
136
|
-
|
|
137
|
-
expect(mbox).to have_received(:append).with("serialized")
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
it "appends the UID to the metadata" do
|
|
141
|
-
command
|
|
142
|
-
|
|
143
|
-
expect(imap).to have_received(:append).with(99)
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
context "when appending to the mailbox causes an error" do
|
|
147
|
-
before do
|
|
148
|
-
allow(mbox).to receive(:append).and_throw(RuntimeError, "Boom")
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
it "does not fail" do
|
|
152
|
-
command
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
it "leaves the metadata file unchanged" do
|
|
156
|
-
command
|
|
157
|
-
|
|
158
|
-
expect(imap).to_not have_received(:append)
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
context "when appending to the metadata file causes an error" do
|
|
163
|
-
before do
|
|
164
|
-
allow(imap).to receive(:append).and_throw(RuntimeError, "Boom")
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
it "does not fail" do
|
|
168
|
-
command
|
|
169
|
-
end
|
|
170
|
-
|
|
171
|
-
it "reset the mailbox to the previous position" do
|
|
172
|
-
command
|
|
173
|
-
|
|
174
|
-
expect(mbox).to have_received(:rewind)
|
|
175
|
-
end
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
context "when the metadata uid_validity has not been set" do
|
|
179
|
-
let(:existing_uid_validity) { nil }
|
|
180
|
-
|
|
181
|
-
it "fails" do
|
|
182
|
-
expect { command }.to raise_error(RuntimeError, /without uid_validity/)
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
context "when the message has already been backed up" do
|
|
187
|
-
let(:uid_found) { true }
|
|
188
|
-
|
|
189
|
-
it "doesn't append to the mailbox file" do
|
|
190
|
-
command
|
|
191
|
-
|
|
192
|
-
expect(mbox).to_not have_received(:append)
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
it "doesn't append to the metadata file" do
|
|
196
|
-
command
|
|
197
|
-
|
|
198
|
-
expect(imap).to_not have_received(:append)
|
|
199
|
-
end
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
|
|
203
|
-
describe "#load" do
|
|
204
|
-
let(:uid) { 999 }
|
|
205
|
-
let(:imap_index) { 0 }
|
|
206
|
-
let(:result) { subject.load(uid) }
|
|
207
|
-
|
|
208
|
-
before do
|
|
209
|
-
allow(imap).to receive(:index).with(999) { imap_index }
|
|
210
|
-
allow(enumerator).to receive(:each) { ["message"].enum_for(:each) }
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
it "returns an Email::Mboxrd::Message" do
|
|
214
|
-
expect(result).to be_a(Email::Mboxrd::Message)
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
it "returns the message" do
|
|
218
|
-
expect(result.supplied_body).to eq("message")
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
context "when the message is not found" do
|
|
222
|
-
let(:imap_index) { nil }
|
|
223
|
-
|
|
224
|
-
it "returns nil" do
|
|
225
|
-
expect(result).to be nil
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
context "when the supplied UID is a string" do
|
|
230
|
-
let(:uid) { "999" }
|
|
231
|
-
|
|
232
|
-
it "works" do
|
|
233
|
-
expect(result).to be_a(Email::Mboxrd::Message)
|
|
234
|
-
end
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
describe "#load_nth" do
|
|
239
|
-
let(:imap_index) { 0 }
|
|
240
|
-
let(:result) { subject.load_nth(imap_index) }
|
|
241
|
-
|
|
242
|
-
before do
|
|
243
|
-
allow(enumerator).to receive(:each) { ["message"].enum_for(:each) }
|
|
244
|
-
end
|
|
245
|
-
|
|
246
|
-
it "returns an Email::Mboxrd::Message" do
|
|
247
|
-
expect(result).to be_a(Email::Mboxrd::Message)
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
it "returns the message" do
|
|
251
|
-
expect(result.supplied_body).to eq("message")
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
context "when the message is not found" do
|
|
255
|
-
let(:imap_index) { 1 }
|
|
256
|
-
|
|
257
|
-
it "returns nil" do
|
|
258
|
-
expect(result).to be nil
|
|
259
|
-
end
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
describe "#each_message" do
|
|
264
|
-
let(:good_uid) { 999 }
|
|
265
|
-
|
|
266
|
-
before do
|
|
267
|
-
allow(imap).to receive(:index) { nil }
|
|
268
|
-
allow(imap).to receive(:index).with(good_uid) { 0 }
|
|
269
|
-
allow(enumerator).to receive(:each) { ["message"].enum_for(:each) }
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
it "yields matching UIDs" do
|
|
273
|
-
expect { |b| subject.each_message([good_uid], &b) }.
|
|
274
|
-
to yield_successive_args([good_uid, anything])
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
it "yields matching messages" do
|
|
278
|
-
messages = subject.each_message([good_uid]).map { |_uid, message| message }
|
|
279
|
-
expect(messages[0].supplied_body).to eq("message")
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
context "with UIDs that are not present" do
|
|
283
|
-
it "skips them" do
|
|
284
|
-
expect { |b| subject.each_message([good_uid, 1234], &b) }.
|
|
285
|
-
to yield_successive_args([good_uid, anything])
|
|
286
|
-
end
|
|
287
|
-
end
|
|
288
|
-
|
|
289
|
-
context "when called without a block" do
|
|
290
|
-
it "returns an Enumerator" do
|
|
291
|
-
expect(subject.each_message([])).to be_a(Enumerator)
|
|
292
|
-
end
|
|
293
|
-
end
|
|
294
|
-
end
|
|
295
|
-
end
|
|
296
|
-
end
|