imap-backup 4.2.0 → 5.1.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 +2 -0
- data/lib/imap/backup/account/connection.rb +4 -4
- data/lib/imap/backup/account/folder.rb +8 -0
- data/lib/imap/backup/cli/folders.rb +1 -1
- data/lib/imap/backup/cli/helpers.rb +4 -1
- data/lib/imap/backup/cli/local.rb +1 -1
- data/lib/imap/backup/cli/migrate.rb +114 -0
- data/lib/imap/backup/cli/remote.rb +15 -0
- data/lib/imap/backup/cli/restore.rb +20 -4
- data/lib/imap/backup/cli.rb +55 -10
- data/lib/imap/backup/client/default.rb +2 -2
- data/lib/imap/backup/downloader.rb +23 -9
- data/lib/imap/backup/migrator.rb +51 -0
- data/lib/imap/backup/sanitizer.rb +7 -4
- data/lib/imap/backup/version.rb +2 -2
- data/spec/features/backup_spec.rb +13 -12
- data/spec/features/configuration/minimal_configuration.rb +15 -0
- data/spec/features/configuration/missing_configuration.rb +14 -0
- data/spec/features/folders_spec.rb +36 -0
- data/spec/features/local/list_accounts_spec.rb +12 -0
- data/spec/features/local/list_emails_spec.rb +21 -0
- data/spec/features/local/list_folders_spec.rb +21 -0
- data/spec/features/local/show_an_email_spec.rb +34 -0
- data/spec/features/migrate_spec.rb +35 -0
- data/spec/features/remote/list_account_folders_spec.rb +16 -0
- data/spec/features/restore_spec.rb +7 -5
- data/spec/features/support/aruba.rb +73 -0
- data/spec/features/support/backup_directory.rb +0 -4
- data/spec/features/support/email_server.rb +1 -1
- data/spec/spec_helper.rb +2 -3
- data/spec/unit/imap/backup/account/connection_spec.rb +6 -8
- data/spec/unit/imap/backup/account/folder_spec.rb +26 -5
- data/spec/unit/imap/backup/cli/helpers_spec.rb +87 -0
- data/spec/unit/imap/backup/migrator_spec.rb +58 -0
- metadata +57 -11
- data/lib/thunderbird/install.rb +0 -16
- data/lib/thunderbird/local_folder.rb +0 -65
- data/lib/thunderbird/profile.rb +0 -30
- data/lib/thunderbird/profiles.rb +0 -71
- data/lib/thunderbird/subdirectory.rb +0 -93
- data/lib/thunderbird/subdirectory_placeholder.rb +0 -21
- data/lib/thunderbird.rb +0 -14
- data/spec/gather_rspec_coverage.rb +0 -1
| @@ -0,0 +1,12 @@ | |
| 1 | 
            +
            require "features/helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe "Listing accounts", type: :aruba do
         | 
| 4 | 
            +
              before do
         | 
| 5 | 
            +
                create_config(accounts: [{"username": "me@example.com"}])
         | 
| 6 | 
            +
                run_command_and_stop("imap-backup local accounts")
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              it "lists accounts" do
         | 
| 10 | 
            +
                expect(last_command_started).to have_output("me@example.com")
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            require "features/helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe "Listing emails", type: :aruba do
         | 
| 4 | 
            +
              let(:email) { "me@example.com" }
         | 
| 5 | 
            +
              let(:account) do
         | 
| 6 | 
            +
                {
         | 
| 7 | 
            +
                  username: email,
         | 
| 8 | 
            +
                  local_path: File.join(config_path, email.gsub("@", "_"))
         | 
| 9 | 
            +
                }
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              before do
         | 
| 13 | 
            +
                create_config(accounts: [account])
         | 
| 14 | 
            +
                store_email(email: email, folder: "my_folder", subject: "Ciao")
         | 
| 15 | 
            +
                run_command_and_stop("imap-backup local list #{email} my_folder")
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              it "lists emails" do
         | 
| 19 | 
            +
                expect(last_command_started).to have_output(/1: Ciao/)
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            require "features/helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe "Listing account folders", type: :aruba do
         | 
| 4 | 
            +
              let(:email) { "me@example.com" }
         | 
| 5 | 
            +
              let(:account) do
         | 
| 6 | 
            +
                {
         | 
| 7 | 
            +
                  username: email,
         | 
| 8 | 
            +
                  local_path: File.join(config_path, email.gsub("@", "_"))
         | 
| 9 | 
            +
                }
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              before do
         | 
| 13 | 
            +
                create_config(accounts: [account])
         | 
| 14 | 
            +
                store_email(email: email, folder: "my_folder", body: "Hi")
         | 
| 15 | 
            +
                run_command_and_stop("imap-backup local folders #{email}")
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              it "lists folders that have been backed up" do
         | 
| 19 | 
            +
                expect(last_command_started).to have_output(%q("my_folder"))
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            require "features/helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe "Show an email", type: :aruba do
         | 
| 4 | 
            +
              let(:email) { "me@example.com" }
         | 
| 5 | 
            +
              let(:account) do
         | 
| 6 | 
            +
                {
         | 
| 7 | 
            +
                  username: email,
         | 
| 8 | 
            +
                  local_path: File.join(config_path, email.gsub("@", "_"))
         | 
| 9 | 
            +
                }
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              before do
         | 
| 13 | 
            +
                create_config(accounts: [account])
         | 
| 14 | 
            +
                store_email(
         | 
| 15 | 
            +
                  email: email,
         | 
| 16 | 
            +
                  folder: "my_folder",
         | 
| 17 | 
            +
                  uid: 99,
         | 
| 18 | 
            +
                  from: "me@example.com",
         | 
| 19 | 
            +
                  subject: "Hello",
         | 
| 20 | 
            +
                  body: "How're things?"
         | 
| 21 | 
            +
                )
         | 
| 22 | 
            +
                run_command_and_stop("imap-backup local show #{email} my_folder 99")
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              it "shows the email" do
         | 
| 26 | 
            +
                expected = <<~BODY
         | 
| 27 | 
            +
                  From: me@example.com
         | 
| 28 | 
            +
                  Subject: Hello
         | 
| 29 | 
            +
                  
         | 
| 30 | 
            +
                  How're things?
         | 
| 31 | 
            +
                BODY
         | 
| 32 | 
            +
                expect(last_command_started).to have_output(expected)
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,35 @@ | |
| 1 | 
            +
            require "features/helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe "Migration", type: :aruba, docker: true do
         | 
| 4 | 
            +
              let(:email) { "me@example.com" }
         | 
| 5 | 
            +
              let(:folder) { "my_folder" }
         | 
| 6 | 
            +
              let(:source_account) do
         | 
| 7 | 
            +
                {
         | 
| 8 | 
            +
                  username: email,
         | 
| 9 | 
            +
                  local_path: File.join(config_path, email.gsub("@", "_"))
         | 
| 10 | 
            +
                }
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
              let(:destination_account) { fixture("connection") }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              before do
         | 
| 15 | 
            +
                create_config(accounts: [source_account, destination_account])
         | 
| 16 | 
            +
                store_email(email: email, folder: folder, subject: "Ciao")
         | 
| 17 | 
            +
                run_command_and_stop("imap-backup migrate #{email} #{destination_account[:username]}")
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              after do
         | 
| 21 | 
            +
                delete_emails(folder)
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              it "copies email to the destination account" do
         | 
| 25 | 
            +
                messages = server_messages(folder)
         | 
| 26 | 
            +
                expected = <<~MESSAGE.gsub("\n", "\r\n")
         | 
| 27 | 
            +
                  From: sender@example.com
         | 
| 28 | 
            +
                  Subject: Ciao
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  body
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                MESSAGE
         | 
| 33 | 
            +
                expect(messages[0]["BODY[]"]).to eq(expected)
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            require "features/helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            RSpec.describe "List account folders", type: :aruba do
         | 
| 4 | 
            +
              let(:account) do
         | 
| 5 | 
            +
                fixture("connection")
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              before do
         | 
| 9 | 
            +
                create_config(accounts: [account])
         | 
| 10 | 
            +
                run_command_and_stop("imap-backup remote folders #{account[:username]}")
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it "lists folders" do
         | 
| 14 | 
            +
                expect(last_command_started).to have_output(/"INBOX"/)
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
            end
         | 
| @@ -1,9 +1,11 @@ | |
| 1 1 | 
             
            require "features/helper"
         | 
| 2 2 |  | 
| 3 | 
            -
            RSpec.describe "restore", type: : | 
| 3 | 
            +
            RSpec.describe "restore", type: :aruba, docker: true do
         | 
| 4 4 | 
             
              include_context "imap-backup connection"
         | 
| 5 5 | 
             
              include_context "message-fixtures"
         | 
| 6 6 |  | 
| 7 | 
            +
              let(:local_backup_path) { File.expand_path("~/backup") }
         | 
| 8 | 
            +
              let(:folder) { "my-stuff" }
         | 
| 7 9 | 
             
              let(:messages_as_mbox) do
         | 
| 8 10 | 
             
                message_as_mbox_entry(msg1) + message_as_mbox_entry(msg2)
         | 
| 9 11 | 
             
              end
         | 
| @@ -12,19 +14,19 @@ RSpec.describe "restore", type: :feature, docker: true do | |
| 12 14 | 
             
              end
         | 
| 13 15 | 
             
              let(:message_uids) { [msg1[:uid], msg2[:uid]] }
         | 
| 14 16 | 
             
              let(:existing_imap_content) { imap_data(uid_validity, message_uids).to_json }
         | 
| 15 | 
            -
              let(:folder) { "my-stuff" }
         | 
| 16 17 | 
             
              let(:uid_validity) { 1234 }
         | 
| 17 18 |  | 
| 18 19 | 
             
              let!(:pre) {}
         | 
| 19 20 | 
             
              let!(:setup) do
         | 
| 21 | 
            +
                create_directory local_backup_path
         | 
| 20 22 | 
             
                File.write(imap_path(folder), existing_imap_content)
         | 
| 21 23 | 
             
                File.write(mbox_path(folder), messages_as_mbox)
         | 
| 22 | 
            -
                 | 
| 24 | 
            +
                create_config(accounts: [account.to_h])
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                run_command_and_stop("imap-backup restore #{account.username}")
         | 
| 23 27 | 
             
              end
         | 
| 24 28 | 
             
              let(:cleanup) do
         | 
| 25 | 
            -
                FileUtils.rm_rf local_backup_path
         | 
| 26 29 | 
             
                server_delete_folder folder
         | 
| 27 | 
            -
                connection.disconnect
         | 
| 28 30 | 
             
              end
         | 
| 29 31 |  | 
| 30 32 | 
             
              after { cleanup }
         | 
| @@ -0,0 +1,73 @@ | |
| 1 | 
            +
            require "aruba/rspec"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative "backup_directory"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Aruba.configure do |config|
         | 
| 6 | 
            +
              config.home_directory = File.expand_path("./tmp/home")
         | 
| 7 | 
            +
              config.allow_absolute_paths = true
         | 
| 8 | 
            +
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            module ConfigurationHelpers
         | 
| 11 | 
            +
              def config_path
         | 
| 12 | 
            +
                File.expand_path("~/.imap-backup")
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def create_config(accounts:, debug: false)
         | 
| 16 | 
            +
                pathname = File.join(config_path, "config.json")
         | 
| 17 | 
            +
                save_data = {
         | 
| 18 | 
            +
                  version: Imap::Backup::Configuration::VERSION,
         | 
| 19 | 
            +
                  accounts: accounts,
         | 
| 20 | 
            +
                  debug: debug
         | 
| 21 | 
            +
                }
         | 
| 22 | 
            +
                FileUtils.mkdir_p config_path
         | 
| 23 | 
            +
                File.open(pathname, "w") { |f| f.write(JSON.pretty_generate(save_data)) }
         | 
| 24 | 
            +
                FileUtils.chmod(0o600, pathname)
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            module StoreHelpers
         | 
| 29 | 
            +
              def store_email(
         | 
| 30 | 
            +
                email:, folder:,
         | 
| 31 | 
            +
                uid: 1,
         | 
| 32 | 
            +
                from: "sender@example.com",
         | 
| 33 | 
            +
                subject: "The Subject",
         | 
| 34 | 
            +
                body: "body"
         | 
| 35 | 
            +
              )
         | 
| 36 | 
            +
                account = config.accounts.find { |a| a.username == email }
         | 
| 37 | 
            +
                raise "Account not found" if !account
         | 
| 38 | 
            +
                FileUtils.mkdir_p account.local_path
         | 
| 39 | 
            +
                store = Imap::Backup::Serializer::MboxStore.new(account.local_path, folder)
         | 
| 40 | 
            +
                store.uid_validity = "42" if !store.uid_validity
         | 
| 41 | 
            +
                serialized = to_serialized(from: from, subject: subject, body: body)
         | 
| 42 | 
            +
                store.add(uid, serialized)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              def to_serialized(from:, subject:, body:)
         | 
| 46 | 
            +
                body_and_headers = <<~BODY
         | 
| 47 | 
            +
                  From: #{from}
         | 
| 48 | 
            +
                  Subject: #{subject}
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  #{body}
         | 
| 51 | 
            +
                BODY
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              def config
         | 
| 55 | 
            +
                Imap::Backup::Configuration.new(
         | 
| 56 | 
            +
                  File.expand_path("~/.imap-backup/config.json")
         | 
| 57 | 
            +
                )
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
            end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            RSpec.configure do |config|
         | 
| 62 | 
            +
              config.include ConfigurationHelpers, type: :aruba
         | 
| 63 | 
            +
              config.include StoreHelpers, type: :aruba
         | 
| 64 | 
            +
              config.include BackupDirectoryHelpers, type: :aruba
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              config.before(:suite) do
         | 
| 67 | 
            +
                FileUtils.rm_rf "./tmp/home"
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              config.after do
         | 
| 71 | 
            +
                FileUtils.rm_rf "./tmp/home"
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
            end
         | 
| @@ -87,7 +87,6 @@ module EmailServerHelpers | |
| 87 87 | 
             
                imap.delete folder
         | 
| 88 88 | 
             
                imap.disconnect
         | 
| 89 89 | 
             
              rescue StandardError => e
         | 
| 90 | 
            -
                puts e.to_s
         | 
| 91 90 | 
             
              ensure
         | 
| 92 91 | 
             
                @imap = nil
         | 
| 93 92 | 
             
              end
         | 
| @@ -106,5 +105,6 @@ module EmailServerHelpers | |
| 106 105 | 
             
            end
         | 
| 107 106 |  | 
| 108 107 | 
             
            RSpec.configure do |config|
         | 
| 108 | 
            +
              config.include EmailServerHelpers, type: :aruba
         | 
| 109 109 | 
             
              config.include EmailServerHelpers, type: :feature
         | 
| 110 110 | 
             
            end
         | 
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -3,10 +3,9 @@ require "rspec" | |
| 3 3 |  | 
| 4 4 | 
             
            CodeClimate::TestReporter.start
         | 
| 5 5 |  | 
| 6 | 
            -
             | 
| 7 | 
            -
            $LOAD_PATH << File.expand_path("../lib", spec_path)
         | 
| 6 | 
            +
            $LOAD_PATH << File.expand_path("../lib", __dir__)
         | 
| 8 7 |  | 
| 9 | 
            -
            support_glob = File.join( | 
| 8 | 
            +
            support_glob = File.join(__dir__, "support", "**", "*.rb")
         | 
| 10 9 | 
             
            Dir[support_glob].sort.each { |f| require f }
         | 
| 11 10 |  | 
| 12 11 | 
             
            require "simplecov"
         | 
| @@ -61,14 +61,6 @@ describe Imap::Backup::Account::Connection do | |
| 61 61 | 
             
                end
         | 
| 62 62 | 
             
              end
         | 
| 63 63 |  | 
| 64 | 
            -
              describe "#initialize" do
         | 
| 65 | 
            -
                it "creates the path" do
         | 
| 66 | 
            -
                  expect(Imap::Backup::Utils).to receive(:make_folder)
         | 
| 67 | 
            -
             | 
| 68 | 
            -
                  subject
         | 
| 69 | 
            -
                end
         | 
| 70 | 
            -
              end
         | 
| 71 | 
            -
             | 
| 72 64 | 
             
              describe "#client" do
         | 
| 73 65 | 
             
                let(:result) { subject.client }
         | 
| 74 66 |  | 
| @@ -127,6 +119,12 @@ describe Imap::Backup::Account::Connection do | |
| 127 119 | 
             
                  allow(Imap::Backup::Serializer::Mbox).to receive(:new) { serializer }
         | 
| 128 120 | 
             
                end
         | 
| 129 121 |  | 
| 122 | 
            +
                it "creates the path" do
         | 
| 123 | 
            +
                  expect(Imap::Backup::Utils).to receive(:make_folder)
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                  subject.status
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 130 128 | 
             
                it "returns the names of folders" do
         | 
| 131 129 | 
             
                  expect(subject.status[0][:name]).to eq(IMAP_FOLDER)
         | 
| 132 130 | 
             
                end
         | 
| @@ -12,7 +12,10 @@ describe Imap::Backup::Account::Folder do | |
| 12 12 | 
             
                  append: append_response,
         | 
| 13 13 | 
             
                  create: nil,
         | 
| 14 14 | 
             
                  examine: nil,
         | 
| 15 | 
            -
                   | 
| 15 | 
            +
                  expunge: nil,
         | 
| 16 | 
            +
                  responses: responses,
         | 
| 17 | 
            +
                  select: nil,
         | 
| 18 | 
            +
                  uid_store: nil
         | 
| 16 19 | 
             
                )
         | 
| 17 20 | 
             
              end
         | 
| 18 21 | 
             
              let(:connection) do
         | 
| @@ -27,12 +30,11 @@ describe Imap::Backup::Account::Folder do | |
| 27 30 | 
             
              end
         | 
| 28 31 | 
             
              let(:responses) { [] }
         | 
| 29 32 | 
             
              let(:append_response) { nil }
         | 
| 33 | 
            +
              let(:uids) { [5678, 123] }
         | 
| 30 34 |  | 
| 31 | 
            -
               | 
| 32 | 
            -
                let(:uids) { [5678, 123] }
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                before { allow(client).to receive(:uid_search) { uids } }
         | 
| 35 | 
            +
              before { allow(client).to receive(:uid_search) { uids } }
         | 
| 35 36 |  | 
| 37 | 
            +
              describe "#uids" do
         | 
| 36 38 | 
             
                it "lists available messages" do
         | 
| 37 39 | 
             
                  expect(subject.uids).to eq(uids.reverse)
         | 
| 38 40 | 
             
                end
         | 
| @@ -233,6 +235,25 @@ describe Imap::Backup::Account::Folder do | |
| 233 235 | 
             
                  expect(subject.uid_validity).to eq(1)
         | 
| 234 236 | 
             
                end
         | 
| 235 237 | 
             
              end
         | 
| 238 | 
            +
             | 
| 239 | 
            +
              describe "#clear" do
         | 
| 240 | 
            +
                before do
         | 
| 241 | 
            +
                  subject.clear
         | 
| 242 | 
            +
                end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                it "uses select to have read-write access" do
         | 
| 245 | 
            +
                  expect(client).to have_received(:select)
         | 
| 246 | 
            +
                end
         | 
| 247 | 
            +
             | 
| 248 | 
            +
                it "marks all emails as deleted" do
         | 
| 249 | 
            +
                  expect(client).
         | 
| 250 | 
            +
                    to have_received(:uid_store).with(uids.sort, "+FLAGS", [:Deleted])
         | 
| 251 | 
            +
                end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                it "deletes marked emails" do
         | 
| 254 | 
            +
                  expect(client).to have_received(:expunge)
         | 
| 255 | 
            +
                end
         | 
| 256 | 
            +
              end
         | 
| 236 257 | 
             
            end
         | 
| 237 258 |  | 
| 238 259 | 
             
            # rubocop:enable RSpec/PredicateMatcher
         | 
| @@ -0,0 +1,87 @@ | |
| 1 | 
            +
            require "imap/backup/cli/helpers"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Imap::Backup
         | 
| 4 | 
            +
              class WithHelpers
         | 
| 5 | 
            +
                include CLI::Helpers
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              RSpec.describe CLI::Helpers do
         | 
| 9 | 
            +
                subject { WithHelpers.new }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                let(:accounts) { instance_double(CLI::Accounts) }
         | 
| 12 | 
            +
                let(:email) { "email@example.com" }
         | 
| 13 | 
            +
                let(:account1) { instance_double(Account, username: email, connection: "c1") }
         | 
| 14 | 
            +
                let(:account2) { instance_double(Account, username: "foo", connection: "c2") }
         | 
| 15 | 
            +
                let(:items) { [account1, account2] }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                before do
         | 
| 18 | 
            +
                  allow(CLI::Accounts).to receive(:new) { accounts }
         | 
| 19 | 
            +
                  allow(accounts).to receive(:each).
         | 
| 20 | 
            +
                    and_yield(account1).
         | 
| 21 | 
            +
                    and_yield(account2)
         | 
| 22 | 
            +
                  allow(accounts).to receive(:find) do |&block|
         | 
| 23 | 
            +
                    items.find { |a| block.call(a) }
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                describe ".symbolized" do
         | 
| 28 | 
            +
                  let(:arguments) { {"foo" => 1, "bar" => 2} }
         | 
| 29 | 
            +
                  let(:result) { subject.symbolized(arguments) }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  it "converts string keys to symbols" do
         | 
| 32 | 
            +
                    expect(result.keys).to eq([:foo, :bar])
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  context "when keys have hyphens" do
         | 
| 36 | 
            +
                    let(:arguments) { {"some-option"=> 3} }
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                    it "replaces them with underscores" do
         | 
| 39 | 
            +
                      expect(result.keys).to eq([:some_option])
         | 
| 40 | 
            +
                    end
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                describe ".account" do
         | 
| 45 | 
            +
                  it "returns any account with a matching username" do
         | 
| 46 | 
            +
                    expect(subject.account(email)).to eq(account1)
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  context "when no match is found" do
         | 
| 50 | 
            +
                    let(:items) { [account2] }
         | 
| 51 | 
            +
                    it "fails" do
         | 
| 52 | 
            +
                      expect do
         | 
| 53 | 
            +
                        subject.account(email)
         | 
| 54 | 
            +
                      end.to raise_error(RuntimeError, /not a configured account/)
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                describe ".connection" do
         | 
| 60 | 
            +
                  it "returns the connection for any account with a matching username" do
         | 
| 61 | 
            +
                    result = subject.connection(email)
         | 
| 62 | 
            +
                    expect(result).to be_a(Account::Connection)
         | 
| 63 | 
            +
                    expect(result.account).to eq(account1)
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                describe ".each_connection" do
         | 
| 68 | 
            +
                  it "yields each connection" do
         | 
| 69 | 
            +
                    expect { |b| subject.each_connection([email, "foo"], &b) }.
         | 
| 70 | 
            +
                      to yield_successive_args("c1", "c2")
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                  context "when there is no configuration" do
         | 
| 74 | 
            +
                    before do
         | 
| 75 | 
            +
                      allow(accounts).to receive(:each).
         | 
| 76 | 
            +
                        and_raise(Imap::Backup::ConfigurationNotFound)
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    it "fails" do
         | 
| 80 | 
            +
                      expect do
         | 
| 81 | 
            +
                        subject.each_connection([email])
         | 
| 82 | 
            +
                      end.to raise_error(RuntimeError, /not configured/)
         | 
| 83 | 
            +
                    end
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
            end
         | 
| @@ -0,0 +1,58 @@ | |
| 1 | 
            +
            require "imap/backup/migrator"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Imap::Backup
         | 
| 4 | 
            +
              RSpec.describe Migrator do
         | 
| 5 | 
            +
                subject { described_class.new(serializer, folder, reset: reset) }
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                let(:serializer) { instance_double(Serializer::MboxStore, uids: [1]) }
         | 
| 8 | 
            +
                let(:folder) do
         | 
| 9 | 
            +
                  instance_double(
         | 
| 10 | 
            +
                    Account::Folder,
         | 
| 11 | 
            +
                    append: nil, clear: nil, create: nil, name: "name", uids: folder_uids
         | 
| 12 | 
            +
                  )
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                let(:folder_uids) { [] }
         | 
| 15 | 
            +
                let(:reset) { false }
         | 
| 16 | 
            +
                let(:messages) { [[1, message]] }
         | 
| 17 | 
            +
                let(:message) { instance_double(Email::Mboxrd::Message, supplied_body: body) }
         | 
| 18 | 
            +
                let(:body) { "body" }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                before do
         | 
| 21 | 
            +
                  allow(serializer).to receive(:each_message) do
         | 
| 22 | 
            +
                    messages.enum_for(:each)
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                it "creates the folder" do
         | 
| 27 | 
            +
                  subject.run
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  expect(folder).to have_received(:create)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                it "uploads messages" do
         | 
| 33 | 
            +
                  subject.run
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  expect(folder).to have_received(:append).with(message)
         | 
| 36 | 
            +
                end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                context "when the folder is not empty" do
         | 
| 39 | 
            +
                  let(:folder_uids) { [99] }
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  it "fails" do
         | 
| 42 | 
            +
                    expect do
         | 
| 43 | 
            +
                      subject.run
         | 
| 44 | 
            +
                    end.to raise_error(RuntimeError, /The destination folder 'name' is not empty/)
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  context "when `reset` is true" do
         | 
| 48 | 
            +
                    let(:reset) { true }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                    it "clears the folder" do
         | 
| 51 | 
            +
                      subject.run
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                      expect(folder).to have_received(:clear)
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            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:  | 
| 4 | 
            +
              version: 5.1.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: 2022- | 
| 11 | 
            +
            date: 2022-02-12 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: highline
         | 
| @@ -80,6 +80,34 @@ dependencies: | |
| 80 80 | 
             
                - - "~>"
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 82 | 
             
                    version: '1.1'
         | 
| 83 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 84 | 
            +
              name: thunderbird
         | 
| 85 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 | 
            +
                requirements:
         | 
| 87 | 
            +
                - - ">="
         | 
| 88 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 89 | 
            +
                    version: 0.0.0
         | 
| 90 | 
            +
              type: :runtime
         | 
| 91 | 
            +
              prerelease: false
         | 
| 92 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 | 
            +
                requirements:
         | 
| 94 | 
            +
                - - ">="
         | 
| 95 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 96 | 
            +
                    version: 0.0.0
         | 
| 97 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 98 | 
            +
              name: aruba
         | 
| 99 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 | 
            +
                requirements:
         | 
| 101 | 
            +
                - - ">="
         | 
| 102 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 103 | 
            +
                    version: 0.0.0
         | 
| 104 | 
            +
              type: :development
         | 
| 105 | 
            +
              prerelease: false
         | 
| 106 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 | 
            +
                requirements:
         | 
| 108 | 
            +
                - - ">="
         | 
| 109 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 110 | 
            +
                    version: 0.0.0
         | 
| 83 111 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 84 112 | 
             
              name: codeclimate-test-reporter
         | 
| 85 113 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -196,6 +224,8 @@ files: | |
| 196 224 | 
             
            - lib/imap/backup/cli/folders.rb
         | 
| 197 225 | 
             
            - lib/imap/backup/cli/helpers.rb
         | 
| 198 226 | 
             
            - lib/imap/backup/cli/local.rb
         | 
| 227 | 
            +
            - lib/imap/backup/cli/migrate.rb
         | 
| 228 | 
            +
            - lib/imap/backup/cli/remote.rb
         | 
| 199 229 | 
             
            - lib/imap/backup/cli/restore.rb
         | 
| 200 230 | 
             
            - lib/imap/backup/cli/setup.rb
         | 
| 201 231 | 
             
            - lib/imap/backup/cli/status.rb
         | 
| @@ -205,6 +235,7 @@ files: | |
| 205 235 | 
             
            - lib/imap/backup/configuration.rb
         | 
| 206 236 | 
             
            - lib/imap/backup/downloader.rb
         | 
| 207 237 | 
             
            - lib/imap/backup/logger.rb
         | 
| 238 | 
            +
            - lib/imap/backup/migrator.rb
         | 
| 208 239 | 
             
            - lib/imap/backup/sanitizer.rb
         | 
| 209 240 | 
             
            - lib/imap/backup/serializer.rb
         | 
| 210 241 | 
             
            - lib/imap/backup/serializer/mbox.rb
         | 
| @@ -221,23 +252,25 @@ files: | |
| 221 252 | 
             
            - lib/imap/backup/utils.rb
         | 
| 222 253 | 
             
            - lib/imap/backup/version.rb
         | 
| 223 254 | 
             
            - lib/retry_on_error.rb
         | 
| 224 | 
            -
            - lib/thunderbird.rb
         | 
| 225 | 
            -
            - lib/thunderbird/install.rb
         | 
| 226 | 
            -
            - lib/thunderbird/local_folder.rb
         | 
| 227 | 
            -
            - lib/thunderbird/profile.rb
         | 
| 228 | 
            -
            - lib/thunderbird/profiles.rb
         | 
| 229 | 
            -
            - lib/thunderbird/subdirectory.rb
         | 
| 230 | 
            -
            - lib/thunderbird/subdirectory_placeholder.rb
         | 
| 231 255 | 
             
            - spec/features/backup_spec.rb
         | 
| 256 | 
            +
            - spec/features/configuration/minimal_configuration.rb
         | 
| 257 | 
            +
            - spec/features/configuration/missing_configuration.rb
         | 
| 258 | 
            +
            - spec/features/folders_spec.rb
         | 
| 232 259 | 
             
            - spec/features/helper.rb
         | 
| 260 | 
            +
            - spec/features/local/list_accounts_spec.rb
         | 
| 261 | 
            +
            - spec/features/local/list_emails_spec.rb
         | 
| 262 | 
            +
            - spec/features/local/list_folders_spec.rb
         | 
| 263 | 
            +
            - spec/features/local/show_an_email_spec.rb
         | 
| 264 | 
            +
            - spec/features/migrate_spec.rb
         | 
| 265 | 
            +
            - spec/features/remote/list_account_folders_spec.rb
         | 
| 233 266 | 
             
            - spec/features/restore_spec.rb
         | 
| 234 267 | 
             
            - spec/features/status_spec.rb
         | 
| 268 | 
            +
            - spec/features/support/aruba.rb
         | 
| 235 269 | 
             
            - spec/features/support/backup_directory.rb
         | 
| 236 270 | 
             
            - spec/features/support/email_server.rb
         | 
| 237 271 | 
             
            - spec/features/support/shared/connection_context.rb
         | 
| 238 272 | 
             
            - spec/features/support/shared/message_fixtures.rb
         | 
| 239 273 | 
             
            - spec/fixtures/connection.yml
         | 
| 240 | 
            -
            - spec/gather_rspec_coverage.rb
         | 
| 241 274 | 
             
            - spec/spec_helper.rb
         | 
| 242 275 | 
             
            - spec/support/fixtures.rb
         | 
| 243 276 | 
             
            - spec/support/higline_test_helpers.rb
         | 
| @@ -251,12 +284,14 @@ files: | |
| 251 284 | 
             
            - spec/unit/imap/backup/account/connection_spec.rb
         | 
| 252 285 | 
             
            - spec/unit/imap/backup/account/folder_spec.rb
         | 
| 253 286 | 
             
            - spec/unit/imap/backup/cli/accounts_spec.rb
         | 
| 287 | 
            +
            - spec/unit/imap/backup/cli/helpers_spec.rb
         | 
| 254 288 | 
             
            - spec/unit/imap/backup/cli/local_spec.rb
         | 
| 255 289 | 
             
            - spec/unit/imap/backup/cli/utils_spec.rb
         | 
| 256 290 | 
             
            - spec/unit/imap/backup/client/default_spec.rb
         | 
| 257 291 | 
             
            - spec/unit/imap/backup/configuration_spec.rb
         | 
| 258 292 | 
             
            - spec/unit/imap/backup/downloader_spec.rb
         | 
| 259 293 | 
             
            - spec/unit/imap/backup/logger_spec.rb
         | 
| 294 | 
            +
            - spec/unit/imap/backup/migrator_spec.rb
         | 
| 260 295 | 
             
            - spec/unit/imap/backup/serializer/mbox_enumerator_spec.rb
         | 
| 261 296 | 
             
            - spec/unit/imap/backup/serializer/mbox_spec.rb
         | 
| 262 297 | 
             
            - spec/unit/imap/backup/serializer/mbox_store_spec.rb
         | 
| @@ -302,10 +337,12 @@ test_files: | |
| 302 337 | 
             
            - spec/unit/imap/backup/setup/connection_tester_spec.rb
         | 
| 303 338 | 
             
            - spec/unit/imap/backup/setup/asker_spec.rb
         | 
| 304 339 | 
             
            - spec/unit/imap/backup/setup/folder_chooser_spec.rb
         | 
| 340 | 
            +
            - spec/unit/imap/backup/cli/helpers_spec.rb
         | 
| 305 341 | 
             
            - spec/unit/imap/backup/cli/accounts_spec.rb
         | 
| 306 342 | 
             
            - spec/unit/imap/backup/cli/utils_spec.rb
         | 
| 307 343 | 
             
            - spec/unit/imap/backup/cli/local_spec.rb
         | 
| 308 344 | 
             
            - spec/unit/imap/backup/downloader_spec.rb
         | 
| 345 | 
            +
            - spec/unit/imap/backup/migrator_spec.rb
         | 
| 309 346 | 
             
            - spec/unit/imap/backup/uploader_spec.rb
         | 
| 310 347 | 
             
            - spec/unit/imap/backup/account/folder_spec.rb
         | 
| 311 348 | 
             
            - spec/unit/imap/backup/account/connection_spec.rb
         | 
| @@ -317,16 +354,25 @@ test_files: | |
| 317 354 | 
             
            - spec/unit/email/provider/fastmail_spec.rb
         | 
| 318 355 | 
             
            - spec/unit/email/provider/base_spec.rb
         | 
| 319 356 | 
             
            - spec/unit/email/provider_spec.rb
         | 
| 357 | 
            +
            - spec/features/folders_spec.rb
         | 
| 358 | 
            +
            - spec/features/configuration/missing_configuration.rb
         | 
| 359 | 
            +
            - spec/features/configuration/minimal_configuration.rb
         | 
| 320 360 | 
             
            - spec/features/backup_spec.rb
         | 
| 321 361 | 
             
            - spec/features/helper.rb
         | 
| 322 362 | 
             
            - spec/features/restore_spec.rb
         | 
| 363 | 
            +
            - spec/features/local/list_emails_spec.rb
         | 
| 364 | 
            +
            - spec/features/local/list_accounts_spec.rb
         | 
| 365 | 
            +
            - spec/features/local/show_an_email_spec.rb
         | 
| 366 | 
            +
            - spec/features/local/list_folders_spec.rb
         | 
| 323 367 | 
             
            - spec/features/status_spec.rb
         | 
| 324 368 | 
             
            - spec/features/support/email_server.rb
         | 
| 325 369 | 
             
            - spec/features/support/backup_directory.rb
         | 
| 370 | 
            +
            - spec/features/support/aruba.rb
         | 
| 326 371 | 
             
            - spec/features/support/shared/connection_context.rb
         | 
| 327 372 | 
             
            - spec/features/support/shared/message_fixtures.rb
         | 
| 373 | 
            +
            - spec/features/migrate_spec.rb
         | 
| 374 | 
            +
            - spec/features/remote/list_account_folders_spec.rb
         | 
| 328 375 | 
             
            - spec/support/fixtures.rb
         | 
| 329 376 | 
             
            - spec/support/silence_logging.rb
         | 
| 330 377 | 
             
            - spec/support/higline_test_helpers.rb
         | 
| 331 378 | 
             
            - spec/fixtures/connection.yml
         | 
| 332 | 
            -
            - spec/gather_rspec_coverage.rb
         |