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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/imap-backup.gemspec +2 -0
  3. data/lib/imap/backup/account/connection.rb +4 -4
  4. data/lib/imap/backup/account/folder.rb +8 -0
  5. data/lib/imap/backup/cli/folders.rb +1 -1
  6. data/lib/imap/backup/cli/helpers.rb +4 -1
  7. data/lib/imap/backup/cli/local.rb +1 -1
  8. data/lib/imap/backup/cli/migrate.rb +114 -0
  9. data/lib/imap/backup/cli/remote.rb +15 -0
  10. data/lib/imap/backup/cli/restore.rb +20 -4
  11. data/lib/imap/backup/cli.rb +55 -10
  12. data/lib/imap/backup/client/default.rb +2 -2
  13. data/lib/imap/backup/downloader.rb +23 -9
  14. data/lib/imap/backup/migrator.rb +51 -0
  15. data/lib/imap/backup/sanitizer.rb +7 -4
  16. data/lib/imap/backup/version.rb +2 -2
  17. data/spec/features/backup_spec.rb +13 -12
  18. data/spec/features/configuration/minimal_configuration.rb +15 -0
  19. data/spec/features/configuration/missing_configuration.rb +14 -0
  20. data/spec/features/folders_spec.rb +36 -0
  21. data/spec/features/local/list_accounts_spec.rb +12 -0
  22. data/spec/features/local/list_emails_spec.rb +21 -0
  23. data/spec/features/local/list_folders_spec.rb +21 -0
  24. data/spec/features/local/show_an_email_spec.rb +34 -0
  25. data/spec/features/migrate_spec.rb +35 -0
  26. data/spec/features/remote/list_account_folders_spec.rb +16 -0
  27. data/spec/features/restore_spec.rb +7 -5
  28. data/spec/features/support/aruba.rb +73 -0
  29. data/spec/features/support/backup_directory.rb +0 -4
  30. data/spec/features/support/email_server.rb +1 -1
  31. data/spec/spec_helper.rb +2 -3
  32. data/spec/unit/imap/backup/account/connection_spec.rb +6 -8
  33. data/spec/unit/imap/backup/account/folder_spec.rb +26 -5
  34. data/spec/unit/imap/backup/cli/helpers_spec.rb +87 -0
  35. data/spec/unit/imap/backup/migrator_spec.rb +58 -0
  36. metadata +57 -11
  37. data/lib/thunderbird/install.rb +0 -16
  38. data/lib/thunderbird/local_folder.rb +0 -65
  39. data/lib/thunderbird/profile.rb +0 -30
  40. data/lib/thunderbird/profiles.rb +0 -71
  41. data/lib/thunderbird/subdirectory.rb +0 -93
  42. data/lib/thunderbird/subdirectory_placeholder.rb +0 -21
  43. data/lib/thunderbird.rb +0 -14
  44. data/spec/gather_rspec_coverage.rb +0 -1
@@ -1,16 +0,0 @@
1
- require "thunderbird/profiles"
2
-
3
- class Thunderbird::Install
4
- attr_reader :title
5
- attr_reader :entries
6
-
7
- # entries are lines from profile.ini
8
- def initialize(title, entries)
9
- @title = title
10
- @entries = entries
11
- end
12
-
13
- def default
14
- Thunderbird::Profiles.new.profile_for_path(entries[:Default])
15
- end
16
- end
@@ -1,65 +0,0 @@
1
- require "thunderbird/profile"
2
- require "thunderbird/subdirectory"
3
-
4
- # A local folder is a file containing emails
5
- class Thunderbird::LocalFolder
6
- attr_reader :path
7
- attr_reader :profile
8
-
9
- def initialize(profile, path)
10
- @profile = profile
11
- @path = path
12
- end
13
-
14
- def set_up
15
- return if path_elements.empty?
16
-
17
- return true if !in_subdirectory?
18
-
19
- subdirectory.set_up
20
- end
21
-
22
- def full_path
23
- if in_subdirectory?
24
- File.join(subdirectory.full_path, folder_name)
25
- else
26
- folder_name
27
- end
28
- end
29
-
30
- def exists?
31
- File.exist?(full_path)
32
- end
33
-
34
- def msf_path
35
- "#{path}.msf"
36
- end
37
-
38
- def msf_exists?
39
- File.exist?(msf_path)
40
- end
41
-
42
- private
43
-
44
- def in_subdirectory?
45
- path_elements.count > 1
46
- end
47
-
48
- def subdirectory
49
- return nil if !in_subdirectory?
50
-
51
- Thunderbird::Subdirectory.new(profile, subdirectory_path)
52
- end
53
-
54
- def path_elements
55
- path.split(File::SEPARATOR)
56
- end
57
-
58
- def subdirectory_path
59
- File.join(path_elements[0..-2])
60
- end
61
-
62
- def folder_name
63
- path_elements[-1]
64
- end
65
- end
@@ -1,30 +0,0 @@
1
- require "thunderbird"
2
-
3
- class Thunderbird::Profile
4
- attr_reader :title
5
- attr_reader :entries
6
-
7
- # entries are lines from profile.ini
8
- def initialize(title, entries)
9
- @title = title
10
- @entries = entries
11
- end
12
-
13
- def root
14
- if relative?
15
- File.join(Thunderbird.new.data_path, entries[:Path])
16
- else
17
- entries[:Path]
18
- end
19
- end
20
-
21
- def local_folders_path
22
- File.join(root, "Mail", "Local Folders")
23
- end
24
-
25
- private
26
-
27
- def relative?
28
- entries[:IsRelative] == "1"
29
- end
30
- end
@@ -1,71 +0,0 @@
1
- require "thunderbird"
2
- require "thunderbird/install"
3
- require "thunderbird/profile"
4
-
5
- # http://kb.mozillazine.org/Profiles.ini_file
6
- class Thunderbird::Profiles
7
- def profile_for_path(path)
8
- title, entries = blocks.find { |_name, entries| entries[:Path] == path }
9
-
10
- Thunderbird::Profile.new(title, entries) if title
11
- end
12
-
13
- def profile(name)
14
- title, entries = blocks.find { |_name, entries| entries[:Name] == name }
15
-
16
- Thunderbird::Profile.new(title, entries) if title
17
- end
18
-
19
- def installs
20
- @installs ||= begin
21
- pairs = blocks.filter { |name, _entries| name.start_with?("Install") }
22
- pairs.map { |title, entries| Thunderbird::Install.new(title, entries) }
23
- end
24
- end
25
-
26
- private
27
-
28
- # Parse profiles.ini.
29
- # Blocks start with a title, e.g. '[Abc]'
30
- # and are followed by a number of lines
31
- def blocks
32
- @blocks ||= begin
33
- blocks = {}
34
- File.open(profiles_ini_path, "rb") do |f|
35
- title = nil
36
- entries = nil
37
-
38
- loop do
39
- line = f.gets
40
- if !line
41
- blocks[title] = entries if title
42
- break
43
- end
44
-
45
- line.chomp!
46
-
47
- # Is this line the start of a new block
48
- match = line.match(/\A\[([A-Za-z0-9]+)\]\z/)
49
- if match
50
- # Store what we got before this title as a new block
51
- blocks[title] = entries if title
52
-
53
- # Start a new block
54
- title = match[1]
55
- entries = {}
56
- elsif line != ""
57
- # Collect entries until we get to the next title
58
- key, value = line.split("=")
59
- entries[key.to_sym] = value
60
- end
61
- end
62
- end
63
-
64
- blocks
65
- end
66
- end
67
-
68
- def profiles_ini_path
69
- File.join(Thunderbird.new.data_path, "profiles.ini")
70
- end
71
- end
@@ -1,93 +0,0 @@
1
- require "thunderbird/subdirectory_placeholder"
2
-
3
- class Thunderbird::Subdirectory
4
- # `path` is the UI path, it doesn't have the '.sbd' extensions
5
- # that are present in the real, file system path
6
- attr_reader :path
7
- attr_reader :profile
8
-
9
- def initialize(profile, path)
10
- @profile = profile
11
- @path = path
12
- end
13
-
14
- def set_up
15
- raise "Cannot create a subdirectory without a path" if !sub_directory?
16
-
17
- if sub_sub_directory?
18
- parent_ok = parent.set_up
19
- return false if !parent_ok
20
- end
21
-
22
- ok = check
23
- return false if !ok
24
-
25
- FileUtils.mkdir_p full_path
26
- placeholder.touch
27
-
28
- true
29
- end
30
-
31
- # subdirectory relative path is 'Foo.sbd/Bar.sbd/Baz.sbd'
32
- def full_path
33
- relative_path = File.join(subdirectories)
34
- File.join(profile.local_folders_path, relative_path)
35
- end
36
-
37
- private
38
-
39
- def sub_directory?
40
- path_elements.any?
41
- end
42
-
43
- def sub_sub_directory?
44
- path_elements.count > 1
45
- end
46
-
47
- def parent
48
- return nil if !sub_sub_directory?
49
-
50
- self.class.new(profile, File.join(path_elements[0..-2]))
51
- end
52
-
53
- # placeholder relative path is 'Foo.sbd/Bar.sbd/Baz'
54
- def placeholder
55
- @placeholder = begin
56
- relative_path = File.join(subdirectories[0..-2], path_elements[-1])
57
- path = File.join(profile.local_folders_path, relative_path)
58
- Thunderbird::SubdirectoryPlaceholder.new(path)
59
- end
60
- end
61
-
62
- def path_elements
63
- path.split(File::SEPARATOR)
64
- end
65
-
66
- def exists?
67
- File.exist?(full_path)
68
- end
69
-
70
- def directory?
71
- File.directory?(full_path)
72
- end
73
-
74
- def subdirectories
75
- path_elements.map { |p| "#{p}.sbd" }
76
- end
77
-
78
- def check
79
- case
80
- when exists? && !placeholder.exists?
81
- Kernel.puts "Can't set up folder '#{full_path}': '#{full_path}' exists, but '#{placeholder.path}' is missing"
82
- false
83
- when placeholder.exists? && !placeholder.regular?
84
- Kernel.puts "Can't set up folder '#{full_path}': '#{placeholder.path}' exists, but it is not a regular file"
85
- false
86
- when exists? && !directory?
87
- Kernel.puts "Can't set up folder '#{full_path}': '#{full_path}' exists, but it is not a directory"
88
- false
89
- else
90
- true
91
- end
92
- end
93
- end
@@ -1,21 +0,0 @@
1
- # Each subdirectory is "accompanied" by a blank
2
- # file of the same name (without the '.sbd' extension)
3
- class Thunderbird::SubdirectoryPlaceholder
4
- attr_reader :path
5
-
6
- def initialize(path)
7
- @path = path
8
- end
9
-
10
- def exists?
11
- File.exist?(path)
12
- end
13
-
14
- def regular?
15
- File.file?(path)
16
- end
17
-
18
- def touch
19
- FileUtils.touch path
20
- end
21
- end
data/lib/thunderbird.rb DELETED
@@ -1,14 +0,0 @@
1
- require "os"
2
-
3
- class Thunderbird
4
- def data_path
5
- case
6
- when OS.linux?
7
- File.join(Dir.home, ".thunderbird")
8
- when OS.mac?
9
- File.join(Dir.home, "Library", "Thunderbird")
10
- when OS.windows?
11
- File.join(ENV["APPDATA"].gsub("\\", "/"), "Thunderbird")
12
- end
13
- end
14
- end
@@ -1 +0,0 @@
1
- GATHER_RSPEC_COVERAGE = 1