imap-backup 1.3.0 → 1.4.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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +2 -1
  5. data/.travis.yml +1 -1
  6. data/README.md +12 -0
  7. data/bin/imap-backup +11 -6
  8. data/docker-compose.yml +15 -0
  9. data/imap-backup.gemspec +3 -2
  10. data/lib/email/mboxrd/message.rb +30 -4
  11. data/lib/email/provider.rb +2 -2
  12. data/lib/imap/backup.rb +0 -1
  13. data/lib/imap/backup/account/connection.rb +29 -15
  14. data/lib/imap/backup/account/folder.rb +3 -3
  15. data/lib/imap/backup/configuration/account.rb +15 -12
  16. data/lib/imap/backup/configuration/asker.rb +3 -1
  17. data/lib/imap/backup/configuration/folder_chooser.rb +5 -2
  18. data/lib/imap/backup/configuration/list.rb +12 -9
  19. data/lib/imap/backup/configuration/setup.rb +5 -3
  20. data/lib/imap/backup/configuration/store.rb +4 -4
  21. data/lib/imap/backup/downloader.rb +6 -2
  22. data/lib/imap/backup/serializer/base.rb +2 -2
  23. data/lib/imap/backup/serializer/mbox.rb +16 -7
  24. data/lib/imap/backup/utils.rb +8 -3
  25. data/lib/imap/backup/version.rb +1 -1
  26. data/spec/features/backup_spec.rb +27 -0
  27. data/spec/features/helper.rb +2 -0
  28. data/spec/features/support/backup_directory.rb +27 -0
  29. data/spec/features/support/email_server.rb +40 -0
  30. data/spec/features/support/shared/connection_context.rb +12 -0
  31. data/spec/features/support/shared/message_fixtures.rb +6 -0
  32. data/spec/fixtures/connection.yml +7 -0
  33. data/spec/support/fixtures.rb +6 -0
  34. data/spec/unit/account/connection_spec.rb +19 -7
  35. data/spec/unit/account/folder_spec.rb +15 -5
  36. data/spec/unit/configuration/account_spec.rb +18 -8
  37. data/spec/unit/configuration/asker_spec.rb +6 -3
  38. data/spec/unit/configuration/connection_tester_spec.rb +1 -1
  39. data/spec/unit/configuration/folder_chooser_spec.rb +21 -11
  40. data/spec/unit/configuration/list_spec.rb +13 -6
  41. data/spec/unit/configuration/setup_spec.rb +5 -3
  42. data/spec/unit/configuration/store_spec.rb +13 -8
  43. data/spec/unit/downloader_spec.rb +3 -1
  44. data/spec/unit/email/mboxrd/message_spec.rb +32 -13
  45. data/spec/unit/email/provider_spec.rb +7 -3
  46. data/spec/unit/serializer/base_spec.rb +3 -2
  47. data/spec/unit/serializer/mbox_spec.rb +9 -6
  48. data/spec/unit/utils_spec.rb +15 -13
  49. metadata +35 -5
  50. data/lib/imap/backup/serializer/directory.rb +0 -43
  51. data/spec/unit/serializer/directory_spec.rb +0 -69
@@ -1,7 +1,7 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Imap::Backup::Serializer::Mbox do
4
- let(:stat) { double("File::Stat", mode: 0700) }
4
+ let(:stat) { double("File::Stat", mode: 0o700) }
5
5
  let(:base_path) { "/base/path" }
6
6
  let(:mbox_pathname) { "/base/path/my/folder.mbox" }
7
7
  let(:mbox_exists) { true }
@@ -20,7 +20,8 @@ describe Imap::Backup::Serializer::Mbox do
20
20
  it "creates the containing directory" do
21
21
  described_class.new(base_path, "my/folder")
22
22
 
23
- expect(Imap::Backup::Utils).to have_received(:make_folder).with(base_path, "my", 0700)
23
+ expect(Imap::Backup::Utils).
24
+ to have_received(:make_folder).with(base_path, "my", 0o700)
24
25
  end
25
26
 
26
27
  context "mbox and imap files" do
@@ -73,14 +74,16 @@ describe Imap::Backup::Serializer::Mbox do
73
74
  context "#save" do
74
75
  let(:mbox_formatted_message) { "message in mbox format" }
75
76
  let(:message_uid) { "999" }
76
- let(:message) { double("Email::Mboxrd::Message", to_s: mbox_formatted_message) }
77
+ let(:message) do
78
+ double("Email::Mboxrd::Message", to_serialized: mbox_formatted_message)
79
+ end
77
80
  let(:mbox_file) { double("File - mbox", write: nil, close: nil) }
78
81
  let(:imap_file) { double("File - imap", write: nil, close: nil) }
79
82
 
80
83
  before do
81
84
  allow(Email::Mboxrd::Message).to receive(:new).and_return(message)
82
- allow(File).to receive(:open).with(mbox_pathname, "ab").and_return(mbox_file)
83
- allow(File).to receive(:open).with(imap_pathname, "ab").and_return(imap_file)
85
+ allow(File).to receive(:open).with(mbox_pathname, "ab") { mbox_file }
86
+ allow(File).to receive(:open).with(imap_pathname, "ab") { imap_file }
84
87
  end
85
88
 
86
89
  it "saves the message to the mbox" do
@@ -97,7 +100,7 @@ describe Imap::Backup::Serializer::Mbox do
97
100
 
98
101
  context "when the message causes parsing errors" do
99
102
  before do
100
- allow(message).to receive(:to_s).and_raise(ArgumentError)
103
+ allow(message).to receive(:to_serialized).and_raise(ArgumentError)
101
104
  end
102
105
 
103
106
  it "skips the message" do
@@ -3,7 +3,7 @@ require "spec_helper"
3
3
  describe Imap::Backup::Utils do
4
4
  let(:filename) { "foobar" }
5
5
  let(:stat) { double("File::Stat", mode: mode) }
6
- let(:mode) { 0777 }
6
+ let(:mode) { 0o777 }
7
7
  let(:exists) { true }
8
8
 
9
9
  before do
@@ -12,13 +12,13 @@ describe Imap::Backup::Utils do
12
12
  end
13
13
 
14
14
  context ".check_permissions" do
15
- let(:requested) { 0345 }
15
+ let(:requested) { 0o345 }
16
16
 
17
17
  context "with existing files" do
18
18
  [
19
- [0100, "less than the limit", true],
20
- [0345, "equal to the limit", true],
21
- [0777, "over the limit", false]
19
+ [0o100, "less than the limit", true],
20
+ [0o345, "equal to the limit", true],
21
+ [0o777, "over the limit", false]
22
22
  ].each do |mode, description, success|
23
23
  context "when permissions are #{description}" do
24
24
  let(:mode) { mode }
@@ -29,9 +29,10 @@ describe Imap::Backup::Utils do
29
29
  end
30
30
  else
31
31
  it "fails" do
32
+ message = /Permissions on '.*?' should be .*?, not .*?/
32
33
  expect do
33
34
  described_class.check_permissions(filename, requested)
34
- end.to raise_error(RuntimeError, format("Permissions on '%s' should be 0%o, not 0%o", filename, requested, mode))
35
+ end.to raise_error(RuntimeError, message)
35
36
  end
36
37
  end
37
38
  end
@@ -40,7 +41,7 @@ describe Imap::Backup::Utils do
40
41
 
41
42
  context "with non-existent files" do
42
43
  let(:exists) { false }
43
- let(:mode) { 0111 }
44
+ let(:mode) { 0o111 }
44
45
 
45
46
  it "succeeds" do
46
47
  described_class.check_permissions(filename, requested)
@@ -50,10 +51,10 @@ describe Imap::Backup::Utils do
50
51
 
51
52
  context ".stat" do
52
53
  context "with existing files" do
53
- let(:mode) { 02345 }
54
+ let(:mode) { 0o2345 }
54
55
 
55
56
  it "is the last 9 bits of the file mode" do
56
- expect(described_class.stat(filename)).to eq(0345)
57
+ expect(described_class.stat(filename)).to eq(0o345)
57
58
  end
58
59
  end
59
60
 
@@ -73,21 +74,22 @@ describe Imap::Backup::Utils do
73
74
  end
74
75
 
75
76
  it "does nothing if an empty path is supplied" do
76
- described_class.make_folder("aaa", "", 0222)
77
+ described_class.make_folder("aaa", "", 0o222)
77
78
 
78
79
  expect(FileUtils).to_not have_received(:mkdir_p)
79
80
  end
80
81
 
81
82
  it "creates the path" do
82
- described_class.make_folder("/base/path", "new/folder", 0222)
83
+ described_class.make_folder("/base/path", "new/folder", 0o222)
83
84
 
84
85
  expect(FileUtils).to have_received(:mkdir_p).with("/base/path/new/folder")
85
86
  end
86
87
 
87
88
  it "sets permissions on the path" do
88
- described_class.make_folder("/base/path/new", "folder", 0222)
89
+ described_class.make_folder("/base/path/new", "folder", 0o222)
89
90
 
90
- expect(FileUtils).to have_received(:chmod).with(0222, "/base/path/new/folder")
91
+ expect(FileUtils).
92
+ to have_received(:chmod).with(0o222, "/base/path/new/folder")
91
93
  end
92
94
  end
93
95
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imap-backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joe Yates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-14 00:00:00.000000000 Z
11
+ date: 2019-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.4.8
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rspec
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -117,6 +131,7 @@ extensions: []
117
131
  extra_rdoc_files: []
118
132
  files:
119
133
  - ".gitignore"
134
+ - ".rspec"
120
135
  - ".rubocop.yml"
121
136
  - ".travis.yml"
122
137
  - Gemfile
@@ -124,6 +139,7 @@ files:
124
139
  - README.md
125
140
  - Rakefile
126
141
  - bin/imap-backup
142
+ - docker-compose.yml
127
143
  - imap-backup.gemspec
128
144
  - lib/email/mboxrd/message.rb
129
145
  - lib/email/provider.rb
@@ -139,12 +155,19 @@ files:
139
155
  - lib/imap/backup/configuration/store.rb
140
156
  - lib/imap/backup/downloader.rb
141
157
  - lib/imap/backup/serializer/base.rb
142
- - lib/imap/backup/serializer/directory.rb
143
158
  - lib/imap/backup/serializer/mbox.rb
144
159
  - lib/imap/backup/utils.rb
145
160
  - lib/imap/backup/version.rb
161
+ - spec/features/backup_spec.rb
162
+ - spec/features/helper.rb
163
+ - spec/features/support/backup_directory.rb
164
+ - spec/features/support/email_server.rb
165
+ - spec/features/support/shared/connection_context.rb
166
+ - spec/features/support/shared/message_fixtures.rb
167
+ - spec/fixtures/connection.yml
146
168
  - spec/gather_rspec_coverage.rb
147
169
  - spec/spec_helper.rb
170
+ - spec/support/fixtures.rb
148
171
  - spec/support/higline_test_helpers.rb
149
172
  - spec/support/shared_examples/account_flagging.rb
150
173
  - spec/support/silence_logging.rb
@@ -161,9 +184,9 @@ files:
161
184
  - spec/unit/email/mboxrd/message_spec.rb
162
185
  - spec/unit/email/provider_spec.rb
163
186
  - spec/unit/serializer/base_spec.rb
164
- - spec/unit/serializer/directory_spec.rb
165
187
  - spec/unit/serializer/mbox_spec.rb
166
188
  - spec/unit/utils_spec.rb
189
+ - tmp/.gitkeep
167
190
  homepage: https://github.com/joeyates/imap-backup
168
191
  licenses: []
169
192
  metadata: {}
@@ -188,8 +211,16 @@ signing_key:
188
211
  specification_version: 4
189
212
  summary: Backup GMail (or other IMAP) accounts to disk
190
213
  test_files:
214
+ - spec/features/backup_spec.rb
215
+ - spec/features/helper.rb
216
+ - spec/features/support/backup_directory.rb
217
+ - spec/features/support/email_server.rb
218
+ - spec/features/support/shared/connection_context.rb
219
+ - spec/features/support/shared/message_fixtures.rb
220
+ - spec/fixtures/connection.yml
191
221
  - spec/gather_rspec_coverage.rb
192
222
  - spec/spec_helper.rb
223
+ - spec/support/fixtures.rb
193
224
  - spec/support/higline_test_helpers.rb
194
225
  - spec/support/shared_examples/account_flagging.rb
195
226
  - spec/support/silence_logging.rb
@@ -206,6 +237,5 @@ test_files:
206
237
  - spec/unit/email/mboxrd/message_spec.rb
207
238
  - spec/unit/email/provider_spec.rb
208
239
  - spec/unit/serializer/base_spec.rb
209
- - spec/unit/serializer/directory_spec.rb
210
240
  - spec/unit/serializer/mbox_spec.rb
211
241
  - spec/unit/utils_spec.rb
@@ -1,43 +0,0 @@
1
- require "fileutils"
2
-
3
- module Imap::Backup
4
- module Serializer; end
5
-
6
- class Serializer::Directory < Serializer::Base
7
- def initialize(path, folder)
8
- super
9
- Utils.make_folder(@path, @folder, Serializer::DIRECTORY_PERMISSIONS)
10
- end
11
-
12
- def uids
13
- return [] if !File.exist?(directory)
14
-
15
- d = Dir.open(directory)
16
- as_strings = d.map do |file|
17
- file[/^0*(\d+).json$/, 1]
18
- end.compact
19
- as_strings.map(&:to_i).sort
20
- end
21
-
22
- def exist?(uid)
23
- message_filename = filename(uid)
24
- File.exist?(message_filename)
25
- end
26
-
27
- def save(uid, message)
28
- message_filename = filename(uid)
29
- File.open(message_filename, "w") { |f| f.write message.to_json }
30
- FileUtils.chmod 0600, message_filename
31
- end
32
-
33
- private
34
-
35
- def directory
36
- File.join(@path, @folder)
37
- end
38
-
39
- def filename(uid)
40
- "#{directory}/%012u.json" % uid.to_i
41
- end
42
- end
43
- end
@@ -1,69 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Imap::Backup::Serializer::Directory do
4
- let(:stat) { double("File::Stat", mode: 0700) }
5
- let(:files) { ["00000123.json", "000001.json"] }
6
- let(:base) { "/base/path" }
7
- let(:folder) { "/base/path/my_folder" }
8
- let(:folder_exists) { true }
9
-
10
- before do
11
- allow(FileUtils).to receive(:mkdir_p)
12
- allow(FileUtils).to receive(:chmod)
13
- allow(File).to receive(:stat).with(base).and_return(stat)
14
- allow(File).to receive(:exist?).with(base).and_return(true)
15
- allow(File).to receive(:exist?).with(folder).and_return(folder_exists)
16
- end
17
-
18
- subject { described_class.new(base, "my_folder") }
19
-
20
- context "#uids" do
21
- before do
22
- allow(Dir).to receive(:open).with(folder).and_return(files)
23
- end
24
-
25
- it "returns the backed-up uids" do
26
- expect(subject.uids).to eq([1, 123])
27
- end
28
-
29
- context "if the directory does not exist" do
30
- let(:folder_exists) { false }
31
-
32
- it "returns an empty array" do
33
- expect(subject.uids).to eq([])
34
- end
35
- end
36
- end
37
-
38
- context "#exist?" do
39
- it "checks if the file exists" do
40
- allow(File).to receive(:exist?).with(%r{/base/path/my_folder/0+123.json}).and_return(true)
41
-
42
- expect(subject.exist?(123)).to be_truthy
43
- end
44
- end
45
-
46
- context "#save" do
47
- let(:message) { {"RFC822" => "the body", "other" => "xxx"} }
48
- let(:file) { double("File", write: nil) }
49
-
50
- before do
51
- allow(File).to receive(:exist?).with(%r{/base/path/my_folder/0+1234.json}).and_return(true)
52
- allow(File).to receive(:open) do |&block|
53
- block.call file
54
- end
55
- end
56
-
57
- it "saves messages" do
58
- subject.save("1234", message)
59
-
60
- expect(file).to have_received(:write).with(message.to_json)
61
- end
62
-
63
- it "sets file permissions" do
64
- subject.save(1234, message)
65
-
66
- expect(FileUtils).to have_received(:chmod).with(0600, /0+1234.json$/)
67
- end
68
- end
69
- end