imap-backup 1.0.5 → 1.0.6
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/.gitignore +0 -1
- data/.travis.yml +1 -1
- data/Gemfile +0 -1
- data/README.md +0 -1
- data/Rakefile +4 -9
- data/bin/imap-backup +0 -1
- data/imap-backup.gemspec +0 -1
- data/lib/email/mboxrd/message.rb +31 -32
- data/lib/imap/backup.rb +17 -4
- data/lib/imap/backup/account/connection.rb +70 -64
- data/lib/imap/backup/account/folder.rb +21 -26
- data/lib/imap/backup/configuration/account.rb +127 -73
- data/lib/imap/backup/configuration/asker.rb +38 -31
- data/lib/imap/backup/configuration/connection_tester.rb +9 -14
- data/lib/imap/backup/configuration/folder_chooser.rb +43 -48
- data/lib/imap/backup/configuration/list.rb +19 -24
- data/lib/imap/backup/configuration/setup.rb +56 -51
- data/lib/imap/backup/configuration/store.rb +47 -52
- data/lib/imap/backup/downloader.rb +11 -14
- data/lib/imap/backup/serializer/base.rb +8 -11
- data/lib/imap/backup/serializer/directory.rb +36 -41
- data/lib/imap/backup/serializer/mbox.rb +83 -88
- data/lib/imap/backup/utils.rb +0 -3
- data/lib/imap/backup/version.rb +1 -2
- data/spec/gather_rspec_coverage.rb +0 -1
- data/spec/spec_helper.rb +2 -7
- data/spec/unit/account/connection_spec.rb +0 -1
- data/spec/unit/account/folder_spec.rb +0 -1
- data/spec/unit/configuration/account_spec.rb +207 -136
- data/spec/unit/configuration/asker_spec.rb +59 -85
- data/spec/unit/configuration/connection_tester_spec.rb +36 -26
- data/spec/unit/configuration/folder_chooser_spec.rb +3 -6
- data/spec/unit/configuration/list_spec.rb +0 -1
- data/spec/unit/configuration/setup_spec.rb +8 -9
- data/spec/unit/configuration/store_spec.rb +1 -4
- data/spec/unit/downloader_spec.rb +0 -1
- data/spec/unit/email/mboxrd/message_spec.rb +0 -1
- data/spec/unit/serializer/base_spec.rb +0 -1
- data/spec/unit/serializer/directory_spec.rb +0 -1
- data/spec/unit/serializer/mbox_spec.rb +0 -1
- data/spec/unit/utils_spec.rb +0 -1
- metadata +2 -2
@@ -2,22 +2,19 @@
|
|
2
2
|
require 'rubygems' if RUBY_VERSION < '1.9'
|
3
3
|
require 'json'
|
4
4
|
|
5
|
-
module Imap
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
5
|
+
module Imap::Backup
|
6
|
+
class Downloader
|
7
|
+
def initialize(folder, serializer)
|
8
|
+
@folder, @serializer = folder, serializer
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
11
|
+
def run
|
12
|
+
uids = @folder.uids - @serializer.uids
|
13
|
+
uids.each do |uid|
|
14
|
+
message = @folder.fetch(uid)
|
15
|
+
next if message.nil?
|
16
|
+
@serializer.save(uid, message)
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
23
|
-
|
@@ -1,17 +1,14 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
module Imap
|
4
|
-
module
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
Imap::Backup::Utils.check_permissions(@path, DIRECTORY_PERMISSIONS)
|
12
|
-
end
|
3
|
+
module Imap::Backup
|
4
|
+
module Serializer
|
5
|
+
DIRECTORY_PERMISSIONS = 0700
|
6
|
+
FILE_PERMISSIONS = 0600
|
7
|
+
class Base
|
8
|
+
def initialize(path, folder)
|
9
|
+
@path, @folder = path, folder
|
10
|
+
Imap::Backup::Utils.check_permissions(@path, DIRECTORY_PERMISSIONS)
|
13
11
|
end
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
17
|
-
|
@@ -1,47 +1,42 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
require 'fileutils'
|
3
3
|
|
4
|
-
module Imap
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def filename(uid)
|
41
|
-
"#{directory}/%012u.json" % uid.to_i
|
42
|
-
end
|
43
|
-
end
|
4
|
+
module Imap::Backup::Serializer
|
5
|
+
class Directory < Base
|
6
|
+
def initialize(path, folder)
|
7
|
+
super
|
8
|
+
Imap::Backup::Utils.make_folder(@path, @folder, DIRECTORY_PERMISSIONS)
|
9
|
+
end
|
10
|
+
|
11
|
+
def uids
|
12
|
+
return [] if ! File.exist?(directory)
|
13
|
+
|
14
|
+
d = Dir.open(directory)
|
15
|
+
as_strings = d.map do |file|
|
16
|
+
file[/^0*(\d+).json$/, 1]
|
17
|
+
end.compact
|
18
|
+
as_strings.map(&:to_i).sort
|
19
|
+
end
|
20
|
+
|
21
|
+
def exist?(uid)
|
22
|
+
message_filename = filename(uid)
|
23
|
+
File.exist?(message_filename)
|
24
|
+
end
|
25
|
+
|
26
|
+
def save(uid, message)
|
27
|
+
message_filename = filename(uid)
|
28
|
+
File.open(message_filename, 'w') { |f| f.write message.to_json }
|
29
|
+
FileUtils.chmod 0600, message_filename
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def directory
|
35
|
+
File.join(@path, @folder)
|
36
|
+
end
|
37
|
+
|
38
|
+
def filename(uid)
|
39
|
+
"#{directory}/%012u.json" % uid.to_i
|
44
40
|
end
|
45
41
|
end
|
46
42
|
end
|
47
|
-
|
@@ -2,95 +2,90 @@
|
|
2
2
|
require 'csv'
|
3
3
|
require 'email/mboxrd/message'
|
4
4
|
|
5
|
-
module Imap
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
mbox.close if mbox
|
41
|
-
imap.close if imap
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def assert_files
|
48
|
-
mbox = mbox_exist?
|
49
|
-
imap = imap_exist?
|
50
|
-
raise '.imap file missing' if mbox and not imap
|
51
|
-
raise '.mbox file missing' if imap and not mbox
|
52
|
-
end
|
53
|
-
|
54
|
-
def create_containing_directory
|
55
|
-
mbox_relative_path = File.dirname(mbox_relative_pathname)
|
56
|
-
return if mbox_relative_path == '.'
|
57
|
-
Imap::Backup::Utils.make_folder(@path, mbox_relative_path, DIRECTORY_PERMISSIONS)
|
58
|
-
end
|
59
|
-
|
60
|
-
def exist?
|
61
|
-
mbox_exist? and imap_exist?
|
62
|
-
end
|
63
|
-
|
64
|
-
def mbox_exist?
|
65
|
-
File.exist?(mbox_pathname)
|
66
|
-
end
|
67
|
-
|
68
|
-
def imap_exist?
|
69
|
-
File.exist?(imap_pathname)
|
70
|
-
end
|
71
|
-
|
72
|
-
def mbox_relative_pathname
|
73
|
-
@folder + '.mbox'
|
74
|
-
end
|
75
|
-
|
76
|
-
def mbox_pathname
|
77
|
-
File.join(@path, mbox_relative_pathname)
|
78
|
-
end
|
79
|
-
|
80
|
-
def imap_pathname
|
81
|
-
filename = @folder + '.imap'
|
82
|
-
File.join(@path, filename)
|
83
|
-
end
|
84
|
-
|
85
|
-
def lock
|
86
|
-
# lock mbox and imap files
|
87
|
-
# create both empty if missing
|
88
|
-
end
|
89
|
-
|
90
|
-
def unlock
|
91
|
-
end
|
5
|
+
module Imap::Backup::Serializer
|
6
|
+
class Mbox < Base
|
7
|
+
def initialize(path, folder)
|
8
|
+
super
|
9
|
+
create_containing_directory
|
10
|
+
assert_files
|
11
|
+
end
|
12
|
+
|
13
|
+
# TODO: cleanup locks, close file handles
|
14
|
+
|
15
|
+
def uids
|
16
|
+
return @uids if @uids
|
17
|
+
|
18
|
+
@uids = []
|
19
|
+
return @uids if not exist?
|
20
|
+
|
21
|
+
CSV.foreach(imap_pathname) do |row|
|
22
|
+
@uids << row[0]
|
23
|
+
end
|
24
|
+
@uids
|
25
|
+
end
|
26
|
+
|
27
|
+
def save(uid, message)
|
28
|
+
uid = uid.to_s
|
29
|
+
return if uids.include?(uid)
|
30
|
+
message = Email::Mboxrd::Message.new(message['RFC822'])
|
31
|
+
mbox = imap = nil
|
32
|
+
begin
|
33
|
+
mbox = File.open(mbox_pathname, 'ab')
|
34
|
+
imap = File.open(imap_pathname, 'ab')
|
35
|
+
mbox.write message.to_s
|
36
|
+
imap.write uid + "\n"
|
37
|
+
ensure
|
38
|
+
mbox.close if mbox
|
39
|
+
imap.close if imap
|
92
40
|
end
|
93
41
|
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def assert_files
|
46
|
+
mbox = mbox_exist?
|
47
|
+
imap = imap_exist?
|
48
|
+
raise '.imap file missing' if mbox and not imap
|
49
|
+
raise '.mbox file missing' if imap and not mbox
|
50
|
+
end
|
51
|
+
|
52
|
+
def create_containing_directory
|
53
|
+
mbox_relative_path = File.dirname(mbox_relative_pathname)
|
54
|
+
return if mbox_relative_path == '.'
|
55
|
+
Imap::Backup::Utils.make_folder(@path, mbox_relative_path, DIRECTORY_PERMISSIONS)
|
56
|
+
end
|
57
|
+
|
58
|
+
def exist?
|
59
|
+
mbox_exist? and imap_exist?
|
60
|
+
end
|
61
|
+
|
62
|
+
def mbox_exist?
|
63
|
+
File.exist?(mbox_pathname)
|
64
|
+
end
|
65
|
+
|
66
|
+
def imap_exist?
|
67
|
+
File.exist?(imap_pathname)
|
68
|
+
end
|
69
|
+
|
70
|
+
def mbox_relative_pathname
|
71
|
+
@folder + '.mbox'
|
72
|
+
end
|
73
|
+
|
74
|
+
def mbox_pathname
|
75
|
+
File.join(@path, mbox_relative_pathname)
|
76
|
+
end
|
77
|
+
|
78
|
+
def imap_pathname
|
79
|
+
filename = @folder + '.imap'
|
80
|
+
File.join(@path, filename)
|
81
|
+
end
|
82
|
+
|
83
|
+
def lock
|
84
|
+
# lock mbox and imap files
|
85
|
+
# create both empty if missing
|
86
|
+
end
|
87
|
+
|
88
|
+
def unlock
|
89
|
+
end
|
94
90
|
end
|
95
91
|
end
|
96
|
-
|
data/lib/imap/backup/utils.rb
CHANGED
@@ -4,7 +4,6 @@ require 'fileutils'
|
|
4
4
|
module Imap
|
5
5
|
module Backup
|
6
6
|
module Utils
|
7
|
-
|
8
7
|
def self.check_permissions(filename, limit)
|
9
8
|
actual = stat(filename)
|
10
9
|
mask = ~limit & 0777
|
@@ -37,8 +36,6 @@ module Imap
|
|
37
36
|
def self.oct(permissions)
|
38
37
|
"0%o" % permissions
|
39
38
|
end
|
40
|
-
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|
44
|
-
|
data/lib/imap/backup/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -4,7 +4,7 @@ if RUBY_VERSION < '1.9'
|
|
4
4
|
require 'rspec/autorun'
|
5
5
|
else
|
6
6
|
require 'simplecov'
|
7
|
-
if defined?(
|
7
|
+
if defined?(GATHER_RSPEC_COVERAGE)
|
8
8
|
SimpleCov.start do
|
9
9
|
add_filter "/spec/"
|
10
10
|
add_filter "/vendor/"
|
@@ -12,10 +12,9 @@ else
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
require File.expand_path(
|
15
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/imap/backup')
|
16
16
|
|
17
17
|
module HighLineTestHelpers
|
18
|
-
|
19
18
|
def prepare_highline
|
20
19
|
@input = stub('stdin', :eof? => false)
|
21
20
|
# default gets stub
|
@@ -24,11 +23,9 @@ module HighLineTestHelpers
|
|
24
23
|
Imap::Backup::Configuration::Setup.highline = HighLine.new(@input, @output)
|
25
24
|
[@input, @output]
|
26
25
|
end
|
27
|
-
|
28
26
|
end
|
29
27
|
|
30
28
|
module InputOutputTestHelpers
|
31
|
-
|
32
29
|
def capturing_output
|
33
30
|
output = StringIO.new
|
34
31
|
$stdout = output
|
@@ -37,6 +34,4 @@ module InputOutputTestHelpers
|
|
37
34
|
ensure
|
38
35
|
$stdout = STDOUT
|
39
36
|
end
|
40
|
-
|
41
37
|
end
|
42
|
-
|
@@ -2,215 +2,286 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe Imap::Backup::Configuration::Account do
|
5
|
-
|
6
|
-
|
5
|
+
class MockHighlineMenu
|
6
|
+
attr_reader :choices
|
7
|
+
attr_accessor :header
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
def initialize
|
10
|
+
@choices = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def choice(name, &block)
|
14
|
+
choices[name] = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def hidden(name, &block)
|
18
|
+
choices[name] = block
|
18
19
|
end
|
19
20
|
end
|
20
21
|
|
21
22
|
context '#run' do
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
:
|
23
|
+
let(:highline) { double('Highline') }
|
24
|
+
let(:menu) { MockHighlineMenu.new }
|
25
|
+
let(:store) { double('Imap::Backup::Configuration::Store', :data => data) }
|
26
|
+
let(:data) { {:accounts => [account, account1]} }
|
27
|
+
let(:account) do
|
28
|
+
{
|
29
|
+
:username => existing_email,
|
30
|
+
:server => existing_server,
|
31
|
+
:local_path => '/backup/path',
|
32
|
+
:folders => [{:name => 'my_folder'}],
|
33
|
+
:password => existing_password,
|
29
34
|
}
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
:
|
34
|
-
:local_path =>
|
35
|
-
:folders => []
|
35
|
+
end
|
36
|
+
let(:account1) do
|
37
|
+
{
|
38
|
+
:username => other_email,
|
39
|
+
:local_path => other_existing_path,
|
36
40
|
}
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
end
|
42
|
+
let(:existing_email) { 'user@example.com' }
|
43
|
+
let(:new_email) { 'foo@example.com' }
|
44
|
+
let(:existing_server) { 'imap.example.com' }
|
45
|
+
let(:existing_password) { 'password' }
|
46
|
+
let(:other_email) { 'other@example.com' }
|
47
|
+
let(:other_existing_path) { '/other/existing/path' }
|
48
|
+
|
49
|
+
before do
|
50
|
+
allow(subject).to receive(:system).and_return(nil)
|
51
|
+
allow(subject).to receive(:puts).and_return(nil)
|
52
|
+
allow(highline).to receive(:choose) do |&block|
|
53
|
+
block.call(menu)
|
54
|
+
throw :done
|
55
|
+
end
|
42
56
|
end
|
43
57
|
|
44
|
-
subject {
|
58
|
+
subject { described_class.new(store, account, highline) }
|
45
59
|
|
46
|
-
context '
|
47
|
-
|
48
|
-
subject.should_receive(:system).with('clear')
|
60
|
+
context 'preparation' do
|
61
|
+
before { subject.run }
|
49
62
|
|
50
|
-
|
63
|
+
it 'clears the screen' do
|
64
|
+
expect(subject).to have_received(:system).with('clear')
|
51
65
|
end
|
52
66
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
@output.string.should =~ /modify password/
|
58
|
-
@output.string.should =~ /modify backup path/
|
59
|
-
@output.string.should =~ /choose backup folders/
|
60
|
-
@output.string.should =~ /test authentication/
|
61
|
-
@output.string.should =~ /delete/
|
62
|
-
@output.string.should =~ /return to main/
|
67
|
+
context 'menu' do
|
68
|
+
it 'shows the menu' do
|
69
|
+
expect(highline).to have_received(:choose)
|
70
|
+
end
|
63
71
|
end
|
72
|
+
end
|
64
73
|
|
65
|
-
|
66
|
-
|
74
|
+
context 'menu' do
|
75
|
+
[
|
76
|
+
'modify email',
|
77
|
+
'modify password',
|
78
|
+
'modify server',
|
79
|
+
'modify backup path',
|
80
|
+
'choose backup folders',
|
81
|
+
'test connection',
|
82
|
+
'delete',
|
83
|
+
'return to main menu',
|
84
|
+
'quit', # TODO: quit is hidden
|
85
|
+
].each do |item|
|
86
|
+
before { subject.run }
|
87
|
+
|
88
|
+
it "has a '#{item}' item" do
|
89
|
+
expect(menu.choices).to include(item)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
67
93
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
94
|
+
context 'account details' do
|
95
|
+
[
|
96
|
+
['email', /email:\s+user@example.com/],
|
97
|
+
['server', /server:\s+imap.example.com/],
|
98
|
+
['password', /password:\s+x+/],
|
99
|
+
['path', %r(path:\s+/backup/path)],
|
100
|
+
['folders', /folders:\s+my_folder/],
|
101
|
+
].each do |attribute, value|
|
102
|
+
before { subject.run }
|
103
|
+
|
104
|
+
it "shows the #{attribute}" do
|
105
|
+
expect(menu.header).to match(value)
|
106
|
+
end
|
72
107
|
end
|
73
108
|
|
74
|
-
|
75
|
-
|
109
|
+
context 'with no password' do
|
110
|
+
let(:existing_password) { '' }
|
76
111
|
|
77
|
-
subject.run
|
112
|
+
before { subject.run }
|
78
113
|
|
79
|
-
|
114
|
+
it 'indicates that a password is not set' do
|
115
|
+
expect(menu.header).to include('password: (unset)')
|
116
|
+
end
|
80
117
|
end
|
81
|
-
|
82
118
|
end
|
83
119
|
|
84
120
|
context 'email' do
|
85
|
-
|
86
|
-
Imap::Backup::Configuration::Asker.
|
87
|
-
|
88
|
-
choose_menu_item 'modify email'
|
89
|
-
|
121
|
+
before do
|
122
|
+
allow(Imap::Backup::Configuration::Asker).to receive(:email).and_return(new_email)
|
90
123
|
subject.run
|
124
|
+
menu.choices['modify email'].call
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'if the server is blank' do
|
128
|
+
[
|
129
|
+
['GMail', 'foo@gmail.com', 'imap.gmail.com'],
|
130
|
+
['Fastmail', 'bar@fastmail.fm', 'mail.messagingengine.com'],
|
131
|
+
].each do |service, email, expected|
|
132
|
+
context service do
|
133
|
+
let(:new_email) { email }
|
134
|
+
|
135
|
+
context 'with nil' do
|
136
|
+
let(:existing_server) { nil }
|
137
|
+
|
138
|
+
it 'sets a default server' do
|
139
|
+
expect(account[:server]).to eq(expected)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'with an empty string' do
|
144
|
+
let(:existing_server) { '' }
|
145
|
+
|
146
|
+
it 'sets a default server' do
|
147
|
+
expect(account[:server]).to eq(expected)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
91
153
|
|
92
|
-
|
93
|
-
|
154
|
+
it 'modifies the email address' do
|
155
|
+
expect(account[:username]).to eq(new_email)
|
94
156
|
end
|
95
157
|
|
96
|
-
|
97
|
-
|
158
|
+
context 'the email already exists' do
|
159
|
+
let(:new_email) { other_email }
|
98
160
|
|
99
|
-
|
161
|
+
it 'indicates the error' do
|
162
|
+
expect(subject).to have_received(:puts).with('There is already an account set up with that email address')
|
163
|
+
end
|
100
164
|
|
101
|
-
|
102
|
-
|
103
|
-
end
|
165
|
+
it "doesn't set the email" do
|
166
|
+
expect(account[:username]).to eq(existing_email)
|
167
|
+
end
|
104
168
|
end
|
105
169
|
end
|
106
170
|
|
107
171
|
context 'password' do
|
108
|
-
|
109
|
-
Imap::Backup::Configuration::Asker.should_receive(:password).once.and_return('new_pwd')
|
110
|
-
|
111
|
-
choose_menu_item 'modify password'
|
172
|
+
let(:new_password) { 'new_password' }
|
112
173
|
|
174
|
+
before do
|
175
|
+
allow(Imap::Backup::Configuration::Asker).to receive(:password).and_return(new_password)
|
113
176
|
subject.run
|
114
|
-
|
115
|
-
@account1[:password].should == 'new_pwd'
|
177
|
+
menu.choices['modify password'].call
|
116
178
|
end
|
117
179
|
|
118
|
-
it '
|
119
|
-
|
120
|
-
|
121
|
-
choose_menu_item 'modify password'
|
180
|
+
it 'updates the password' do
|
181
|
+
expect(account[:password]).to eq(new_password)
|
182
|
+
end
|
122
183
|
|
123
|
-
|
184
|
+
context 'if the user cancels' do
|
185
|
+
let(:new_password) { nil }
|
124
186
|
|
125
|
-
|
187
|
+
it 'does nothing' do
|
188
|
+
expect(account[:password]).to eq(existing_password)
|
189
|
+
end
|
126
190
|
end
|
127
191
|
end
|
128
192
|
|
129
|
-
context '
|
130
|
-
|
131
|
-
Imap::Backup::Configuration::Asker.should_receive(:backup_path).once do |default, validator|
|
132
|
-
validator.call('new/path')
|
133
|
-
'/new/path'
|
134
|
-
end
|
193
|
+
context 'server' do
|
194
|
+
let(:server) { 'server' }
|
135
195
|
|
136
|
-
|
196
|
+
before do
|
197
|
+
allow(highline).to receive(:ask).with('server: ').and_return(server)
|
198
|
+
end
|
137
199
|
|
200
|
+
before do
|
138
201
|
subject.run
|
202
|
+
menu.choices['modify server'].call
|
203
|
+
end
|
139
204
|
|
140
|
-
|
205
|
+
it 'updates the server' do
|
206
|
+
expect(account[:server]).to eq(server)
|
141
207
|
end
|
208
|
+
end
|
142
209
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
210
|
+
context 'backup_path' do
|
211
|
+
let(:new_backup_path) { '/new/path' }
|
212
|
+
|
213
|
+
before do
|
214
|
+
@validator = nil
|
215
|
+
allow(Imap::Backup::Configuration::Asker).to receive(:backup_path) do |path, validator|
|
216
|
+
@validator = validator
|
217
|
+
new_backup_path
|
147
218
|
end
|
219
|
+
subject.run
|
220
|
+
menu.choices['modify backup path'].call
|
221
|
+
end
|
148
222
|
|
149
|
-
|
223
|
+
it 'updates the path' do
|
224
|
+
expect(account[:local_path]).to eq(new_backup_path)
|
225
|
+
end
|
150
226
|
|
151
|
-
|
152
|
-
|
153
|
-
end.should =~ %r{The path '/existing/path' is used to backup the account 'existing@example.com'}
|
227
|
+
it 'validates that the path is not used by other backups' do
|
228
|
+
expect(@validator.call(other_existing_path)).to be_false
|
154
229
|
end
|
155
230
|
end
|
156
231
|
|
157
|
-
|
158
|
-
|
159
|
-
Imap::Backup::Configuration::FolderChooser.should_receive(:new).with(@account1).and_return(@chooser)
|
160
|
-
@chooser.should_receive(:run).with().once
|
232
|
+
context 'folders' do
|
233
|
+
let(:chooser) { double(:run => nil) }
|
161
234
|
|
162
|
-
|
235
|
+
before do
|
236
|
+
allow(Imap::Backup::Configuration::FolderChooser).to receive(:new).and_return(chooser)
|
237
|
+
subject.run
|
238
|
+
menu.choices['choose backup folders'].call
|
239
|
+
end
|
163
240
|
|
164
|
-
|
241
|
+
it 'edits folders' do
|
242
|
+
expect(chooser).to have_received(:run)
|
243
|
+
end
|
165
244
|
end
|
166
245
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
capturing_output do
|
246
|
+
context 'connection test' do
|
247
|
+
before do
|
248
|
+
allow(Imap::Backup::Configuration::ConnectionTester).to receive(:test).and_return('All fine')
|
249
|
+
allow(highline).to receive(:ask)
|
173
250
|
subject.run
|
174
|
-
|
251
|
+
menu.choices['test connection'].call
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'tests the connection' do
|
255
|
+
expect(Imap::Backup::Configuration::ConnectionTester).to have_received(:test).with(account)
|
256
|
+
end
|
175
257
|
end
|
176
258
|
|
177
259
|
context 'deletion' do
|
178
|
-
|
179
|
-
Imap::Backup::Configuration::Setup.highline.should_receive(:agree).with("Are you sure? (y/n) ").and_return(true)
|
180
|
-
|
181
|
-
choose_menu_item 'delete'
|
260
|
+
let(:confirmed) { true }
|
182
261
|
|
262
|
+
before do
|
263
|
+
allow(highline).to receive(:agree).and_return(confirmed)
|
183
264
|
subject.run
|
265
|
+
catch :done do
|
266
|
+
menu.choices['delete'].call
|
267
|
+
end
|
184
268
|
end
|
185
269
|
|
186
|
-
it '
|
187
|
-
|
188
|
-
|
189
|
-
choose_menu_item 'delete'
|
190
|
-
|
191
|
-
subject.run
|
192
|
-
|
193
|
-
@data[:accounts].should_not include(@account1)
|
270
|
+
it 'asks for confirmation' do
|
271
|
+
expect(highline).to have_received(:agree)
|
194
272
|
end
|
195
273
|
|
196
|
-
it '
|
197
|
-
|
198
|
-
|
199
|
-
choose_menu_item 'delete'
|
200
|
-
|
201
|
-
subject.run
|
202
|
-
|
203
|
-
@data[:accounts].should include(@account1)
|
274
|
+
it 'deletes the account' do
|
275
|
+
expect(data[:accounts].find{|a| a[:username] == existing_email}).to be_nil
|
204
276
|
end
|
205
|
-
end
|
206
277
|
|
207
|
-
|
208
|
-
|
209
|
-
@input.stub!(:gets).with().and_return("return\n")
|
278
|
+
context 'without confirmation' do
|
279
|
+
let(:confirmed) { false }
|
210
280
|
|
211
|
-
|
281
|
+
it 'does nothing' do
|
282
|
+
expect(data[:accounts].find{|a| a[:username] == existing_email}).to eq(account)
|
283
|
+
end
|
212
284
|
end
|
213
285
|
end
|
214
286
|
end
|
215
287
|
end
|
216
|
-
|