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.
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
@@ -1,100 +0,0 @@
1
- describe Imap::Backup::CLI::Local do
2
- let(:accounts) do
3
- instance_double(
4
- Imap::Backup::CLI::Accounts,
5
- find: ->(&block) { [account].find { |a| block.call(a) } }
6
- )
7
- end
8
- let(:account) do
9
- instance_double(
10
- Imap::Backup::Account,
11
- username: email,
12
- marked_for_deletion?: false,
13
- modified?: false
14
- )
15
- end
16
- let(:connection) do
17
- instance_double(
18
- Imap::Backup::Account::Connection,
19
- local_folders: local_folders
20
- )
21
- end
22
- let(:local_folders) { [[serializer, folder]] }
23
- let(:folder) { instance_double(Imap::Backup::Account::Folder, name: "bar") }
24
- let(:serializer) do
25
- instance_double(
26
- Imap::Backup::Serializer,
27
- uids: uids,
28
- each_message: each_message
29
- )
30
- end
31
- let(:uids) { ["123"] }
32
- let(:each_message) { [[123, message]] }
33
- let(:message) do
34
- instance_double(
35
- Email::Mboxrd::Message,
36
- date: Date.today,
37
- subject: message_subject,
38
- supplied_body: "Supplied"
39
- )
40
- end
41
- let(:message_subject) { "Ciao" }
42
- let(:email) { "foo@example.com" }
43
-
44
- before do
45
- allow(Kernel).to receive(:puts)
46
- allow(Imap::Backup::CLI::Accounts).to receive(:new) { accounts }
47
- allow(Imap::Backup::Account::Connection).to receive(:new) { connection }
48
- allow(Mail).to receive(:new) { mail }
49
- allow(accounts).to receive(:each).and_yield(account)
50
- end
51
-
52
- describe "accounts" do
53
- it "lists configured emails" do
54
- subject.accounts
55
-
56
- expect(Kernel).to have_received(:puts).with(email)
57
- end
58
- end
59
-
60
- describe "folders" do
61
- it "lists downloaded folders in quotes" do
62
- subject.folders(email)
63
-
64
- expect(Kernel).to have_received(:puts).with(%("bar"))
65
- end
66
- end
67
-
68
- describe "list" do
69
- before { subject.list(email, "bar") }
70
-
71
- it "lists downloaded emails" do
72
- expect(Kernel).to have_received(:puts).with(/Ciao/)
73
- end
74
-
75
- context "when the subject line is too long" do
76
- let(:message_subject) { "A" * 70 }
77
-
78
- it "is shortened" do
79
- expect(Kernel).to have_received(:puts).with(/\sA{57}\.\.\./)
80
- end
81
- end
82
- end
83
-
84
- describe "show" do
85
- before { subject.show(email, "bar", uids.join(",")) }
86
-
87
- it "prints a downloaded email" do
88
- expect(Kernel).to have_received(:puts).with("Supplied")
89
- end
90
-
91
- context "when more than one email is requested" do
92
- let(:uids) { %w(123 456) }
93
- let(:each_message) { [[123, message], [456, message]] }
94
-
95
- it "prints a header" do
96
- expect(Kernel).to have_received(:puts).with(/\| UID: 123 /)
97
- end
98
- end
99
- end
100
- end
@@ -1,80 +0,0 @@
1
- module Imap::Backup
2
- describe CLI::Migrate do
3
- subject { described_class.new(source, destination, **options) }
4
-
5
- let(:source) { "source" }
6
- let(:destination) { "destination" }
7
- let(:options) { {} }
8
- let(:config) { instance_double(Configuration, accounts: [account1, account2]) }
9
- let(:account1) { instance_double(Account, username: "source", local_path: "path") }
10
- let(:account2) { instance_double(Account, username: "destination", connection: connection) }
11
- let(:connection) { instance_double(Account::Connection) }
12
- let(:migrator) { instance_double(Migrator, run: nil) }
13
- let(:imap_pathname) { Pathname.new("path/foo.imap") }
14
-
15
- before do
16
- allow(Configuration).to receive(:new) { config }
17
- allow(Pathname).to receive(:glob).and_yield(imap_pathname)
18
- allow(Migrator).to receive(:new) { migrator }
19
- allow(Account::Folder).to receive(:new).and_call_original
20
- end
21
-
22
- it "migrates each folder" do
23
- subject.run
24
-
25
- expect(migrator).to have_received(:run)
26
- end
27
-
28
- context "when source and destination emails are the same" do
29
- let(:destination) { "source" }
30
-
31
- it "fails" do
32
- expect do
33
- subject.run
34
- end.to raise_error(RuntimeError, /cannot be the same/)
35
- end
36
- end
37
-
38
- context "when the source account is not found" do
39
- let(:source) { "unknown" }
40
-
41
- it "fails" do
42
- expect do
43
- subject.run
44
- end.to raise_error(RuntimeError, /does not exist/)
45
- end
46
- end
47
-
48
- context "when the destination account is not found" do
49
- let(:destination) { "unknown" }
50
-
51
- it "fails" do
52
- expect do
53
- subject.run
54
- end.to raise_error(RuntimeError, /does not exist/)
55
- end
56
- end
57
-
58
- context "when source_prefix is supplied" do
59
- let(:options) { {source_prefix: "src/"} }
60
- let(:imap_pathname) { Pathname.new("path/src/foo.imap") }
61
-
62
- it "removes the prefix" do
63
- subject.run
64
-
65
- expect(Account::Folder).to have_received(:new).with(anything, "foo")
66
- end
67
- end
68
-
69
- context "when destination_prefix is supplied" do
70
- let(:options) { {destination_prefix: "dest/"} }
71
- let(:imap_pathname) { Pathname.new("path/foo.imap") }
72
-
73
- it "removes the prefix" do
74
- subject.run
75
-
76
- expect(Account::Folder).to have_received(:new).with(anything, "dest/foo")
77
- end
78
- end
79
- end
80
- end
@@ -1,67 +0,0 @@
1
- # rubocop:disable RSpec/SubjectStub
2
- module Imap::Backup
3
- describe CLI::Restore do
4
- subject { described_class.new(email, options) }
5
-
6
- let(:connection) { instance_double(Account::Connection, restore: nil) }
7
-
8
- describe "#run" do
9
- context "when an email is provided" do
10
- let(:email) { "email" }
11
- let(:options) { {} }
12
-
13
- before do
14
- allow(subject).to receive(:connection).with(email) { connection }
15
-
16
- subject.run
17
- end
18
-
19
- it "runs restore on the account" do
20
- expect(connection).to have_received(:restore)
21
- end
22
- end
23
-
24
- context "when neither an email nor a list of account names is provided" do
25
- let(:email) { nil }
26
- let(:options) { {} }
27
-
28
- before do
29
- allow(subject).to receive(:each_connection).with([]).and_yield(connection)
30
-
31
- subject.run
32
- end
33
-
34
- it "runs restore on each account" do
35
- expect(connection).to have_received(:restore)
36
- end
37
- end
38
-
39
- context "when an email and a list of account names is provided" do
40
- let(:email) { "email" }
41
- let(:options) { {accounts: "email2"} }
42
-
43
- it "fails" do
44
- expect do
45
- subject.run
46
- end.to raise_error(RuntimeError, /Pass either an email or the --accounts option/)
47
- end
48
- end
49
-
50
- context "when just a list of account names is provided" do
51
- let(:email) { nil }
52
- let(:options) { {accounts: "email2"} }
53
-
54
- before do
55
- allow(subject).to receive(:each_connection).with(["email2"]).and_yield(connection)
56
-
57
- subject.run
58
- end
59
-
60
- it "runs restore on each account" do
61
- expect(connection).to have_received(:restore)
62
- end
63
- end
64
- end
65
- end
66
- end
67
- # rubocop:enable RSpec/SubjectStub
@@ -1,17 +0,0 @@
1
- module Imap::Backup
2
- describe CLI::Setup do
3
- subject { described_class.new }
4
-
5
- let(:setup) { instance_double(Setup, run: nil) }
6
-
7
- before do
8
- allow(Setup).to receive(:new) { setup }
9
- end
10
-
11
- it "reruns the setup process" do
12
- subject.run
13
-
14
- expect(setup).to have_received(:run)
15
- end
16
- end
17
- end
@@ -1,125 +0,0 @@
1
- module Imap::Backup
2
- describe CLI::Utils do
3
- let(:accounts) do
4
- instance_double(
5
- CLI::Accounts,
6
- find: ->(&block) { [account].find { |a| block.call(a) } }
7
- )
8
- end
9
- let(:account) { instance_double(Account, username: email) }
10
- let(:connection) do
11
- instance_double(
12
- Account::Connection,
13
- account: account,
14
- backup_folders: [folder],
15
- local_folders: ["folder"]
16
- )
17
- end
18
- let(:account) do
19
- instance_double(
20
- Account,
21
- local_path: "path"
22
- )
23
- end
24
- let(:folder) do
25
- instance_double(
26
- Account::Folder,
27
- exist?: true,
28
- name: "name",
29
- uid_validity: "uid_validity",
30
- uids: %w(123 456)
31
- )
32
- end
33
- let(:serializer) do
34
- instance_double(
35
- Serializer,
36
- uids: %w(123 789),
37
- apply_uid_validity: nil,
38
- append: nil
39
- )
40
- end
41
- let(:exporter) { instance_double(Thunderbird::MailboxExporter, run: nil) }
42
- let(:email) { "foo@example.com" }
43
-
44
- before do
45
- allow(CLI::Accounts).to receive(:new) { accounts }
46
- allow(Account::Connection).to receive(:new) { connection }
47
- allow(Serializer).to receive(:new) { serializer }
48
- end
49
-
50
- describe "#export_to_thunderbird" do
51
- let(:command) { subject.export_to_thunderbird(email) }
52
- let(:options) { {} }
53
- let(:profiles) { instance_double(Thunderbird::Profiles, installs: installs, profile: named_profile) }
54
- let(:installs) { [install1] }
55
- let(:install1) { instance_double(Thunderbird::Install, default: default_install) }
56
- let(:default_install) { "default" }
57
- let(:named_profile) { "named" }
58
-
59
- before do
60
- allow(Thunderbird::MailboxExporter).to receive(:new) { exporter }
61
- allow(Thunderbird::Profiles).to receive(:new) { profiles }
62
- # rubocop:disable RSpec/SubjectStub
63
- allow(subject).to receive(:options) { options }
64
- # rubocop:enable RSpec/SubjectStub
65
- end
66
-
67
- context "when no profile_name is supplied" do
68
- context "when no default Thunderbird profile is found" do
69
- let(:default_install) { nil }
70
-
71
- it "fails" do
72
- expect do
73
- command
74
- end.to raise_error(RuntimeError, /Default .*? not found/)
75
- end
76
- end
77
-
78
- context "when there is more than one install" do
79
- let(:installs) { [install1, install2] }
80
- let(:install2) { instance_double(Thunderbird::Install, default: default_install) }
81
-
82
- it "fails" do
83
- expect do
84
- command
85
- end.to raise_error(RuntimeError, /multiple installs.*?supply a profile name/m)
86
- end
87
- end
88
- end
89
-
90
- context "when a profile_name is supplied" do
91
- let(:options) { {"profile" => "profile"} }
92
-
93
- context "when the supplied profile_name is not found" do
94
- let(:named_profile) { nil }
95
-
96
- it "fails" do
97
- expect do
98
- command
99
- end.to raise_error(RuntimeError, /profile 'profile' not found/)
100
- end
101
- end
102
- end
103
-
104
- it "exports the profile" do
105
- command
106
-
107
- expect(exporter).to have_received(:run)
108
- end
109
- end
110
-
111
- describe "ignore_history" do
112
- it "ensures the local UID validity matches the server" do
113
- subject.ignore_history(email)
114
-
115
- expect(serializer).to have_received(:apply_uid_validity).with("uid_validity")
116
- end
117
-
118
- it "fills the local folder with fake emails" do
119
- subject.ignore_history(email)
120
-
121
- expect(serializer).to have_received(:append).with("456", /From: fake@email.com/)
122
- end
123
- end
124
- end
125
- end
@@ -1,93 +0,0 @@
1
- module Imap::Backup
2
- RSpec.describe CLI do
3
- describe ".exit_on_failure?" do
4
- it "is true" do
5
- expect(described_class.exit_on_failure?).to be true
6
- end
7
- end
8
-
9
- describe "#backup" do
10
- let(:backup) { instance_double(CLI::Backup, run: nil) }
11
-
12
- before do
13
- allow(CLI::Backup).to receive(:new) { backup }
14
-
15
- subject.backup
16
- end
17
-
18
- it "runs Backup" do
19
- expect(backup).to have_received(:run)
20
- end
21
- end
22
-
23
- describe "#folders" do
24
- let(:folders) { instance_double(CLI::Folders, run: nil) }
25
-
26
- before do
27
- allow(CLI::Folders).to receive(:new) { folders }
28
-
29
- subject.folders
30
- end
31
-
32
- it "runs folders" do
33
- expect(folders).to have_received(:run)
34
- end
35
- end
36
-
37
- describe "#migrate" do
38
- let(:migrate) { instance_double(CLI::Migrate, run: nil) }
39
-
40
- before do
41
- allow(CLI::Migrate).to receive(:new) { migrate }
42
-
43
- subject.migrate("source", "destination")
44
- end
45
-
46
- it "runs migrate" do
47
- expect(migrate).to have_received(:run)
48
- end
49
- end
50
-
51
- describe "#restore" do
52
- let(:restore) { instance_double(CLI::Restore, run: nil) }
53
-
54
- before do
55
- allow(CLI::Restore).to receive(:new) { restore }
56
-
57
- subject.restore
58
- end
59
-
60
- it "runs restore" do
61
- expect(restore).to have_received(:run)
62
- end
63
- end
64
-
65
- describe "#setup" do
66
- let(:setup) { instance_double(CLI::Setup, run: nil) }
67
-
68
- before do
69
- allow(CLI::Setup).to receive(:new) { setup }
70
-
71
- subject.setup
72
- end
73
-
74
- it "runs setup" do
75
- expect(setup).to have_received(:run)
76
- end
77
- end
78
-
79
- describe "#status" do
80
- let(:status) { instance_double(CLI::Status, run: nil) }
81
-
82
- before do
83
- allow(CLI::Status).to receive(:new) { status }
84
-
85
- subject.status
86
- end
87
-
88
- it "runs status" do
89
- expect(status).to have_received(:run)
90
- end
91
- end
92
- end
93
- end
@@ -1,9 +0,0 @@
1
- module Imap::Backup
2
- RSpec.describe Client::AppleMail do
3
- describe "#provider_root" do
4
- it "is an empty string" do
5
- expect(subject.provider_root).to eq("")
6
- end
7
- end
8
- end
9
- end
@@ -1,22 +0,0 @@
1
- describe Imap::Backup::Client::Default do
2
- subject { described_class.new("server", {}) }
3
-
4
- let(:imap) { instance_double(Net::IMAP, list: imap_folders) }
5
- let(:imap_folders) { [] }
6
-
7
- before do
8
- allow(Net::IMAP).to receive(:new) { imap }
9
- end
10
-
11
- describe "#list" do
12
- context "with non-ASCII folder names" do
13
- let(:imap_folders) do
14
- [instance_double(Net::IMAP::MailboxList, name: "Gel&APY-scht")]
15
- end
16
-
17
- it "converts them to UTF-8" do
18
- expect(subject.list).to eq(["Gelöscht"])
19
- end
20
- end
21
- end
22
- end