backup 3.0.20 → 3.0.21

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 (178) hide show
  1. data/Gemfile +1 -5
  2. data/Gemfile.lock +46 -50
  3. data/README.md +54 -27
  4. data/lib/backup.rb +16 -39
  5. data/lib/backup/archive.rb +42 -18
  6. data/lib/backup/cleaner.rb +110 -25
  7. data/lib/backup/cli/helpers.rb +17 -32
  8. data/lib/backup/cli/utility.rb +46 -107
  9. data/lib/backup/compressor/base.rb +14 -2
  10. data/lib/backup/compressor/bzip2.rb +10 -24
  11. data/lib/backup/compressor/gzip.rb +10 -24
  12. data/lib/backup/compressor/lzma.rb +10 -23
  13. data/lib/backup/compressor/pbzip2.rb +12 -32
  14. data/lib/backup/config.rb +171 -0
  15. data/lib/backup/configuration/compressor/base.rb +1 -2
  16. data/lib/backup/configuration/compressor/pbzip2.rb +4 -4
  17. data/lib/backup/configuration/database/base.rb +2 -1
  18. data/lib/backup/configuration/database/mongodb.rb +8 -0
  19. data/lib/backup/configuration/database/mysql.rb +4 -0
  20. data/lib/backup/configuration/database/postgresql.rb +4 -0
  21. data/lib/backup/configuration/database/redis.rb +4 -0
  22. data/lib/backup/configuration/database/riak.rb +5 -1
  23. data/lib/backup/configuration/encryptor/base.rb +1 -2
  24. data/lib/backup/configuration/encryptor/open_ssl.rb +1 -1
  25. data/lib/backup/configuration/helpers.rb +7 -2
  26. data/lib/backup/configuration/notifier/base.rb +4 -28
  27. data/lib/backup/configuration/storage/base.rb +1 -1
  28. data/lib/backup/configuration/storage/dropbox.rb +14 -4
  29. data/lib/backup/configuration/syncer/base.rb +10 -0
  30. data/lib/backup/configuration/syncer/rsync/base.rb +28 -0
  31. data/lib/backup/configuration/syncer/rsync/local.rb +11 -0
  32. data/lib/backup/configuration/syncer/rsync/pull.rb +11 -0
  33. data/lib/backup/configuration/syncer/rsync/push.rb +31 -0
  34. data/lib/backup/configuration/syncer/s3.rb +0 -4
  35. data/lib/backup/database/base.rb +25 -7
  36. data/lib/backup/database/mongodb.rb +112 -75
  37. data/lib/backup/database/mysql.rb +54 -29
  38. data/lib/backup/database/postgresql.rb +60 -42
  39. data/lib/backup/database/redis.rb +61 -39
  40. data/lib/backup/database/riak.rb +35 -11
  41. data/lib/backup/dependency.rb +4 -5
  42. data/lib/backup/encryptor/base.rb +13 -1
  43. data/lib/backup/encryptor/gpg.rb +39 -39
  44. data/lib/backup/encryptor/open_ssl.rb +28 -38
  45. data/lib/backup/logger.rb +20 -11
  46. data/lib/backup/model.rb +206 -163
  47. data/lib/backup/notifier/base.rb +27 -25
  48. data/lib/backup/notifier/campfire.rb +7 -13
  49. data/lib/backup/notifier/hipchat.rb +28 -28
  50. data/lib/backup/notifier/mail.rb +24 -26
  51. data/lib/backup/notifier/presently.rb +10 -18
  52. data/lib/backup/notifier/prowl.rb +9 -17
  53. data/lib/backup/notifier/twitter.rb +11 -18
  54. data/lib/backup/package.rb +47 -0
  55. data/lib/backup/packager.rb +81 -16
  56. data/lib/backup/splitter.rb +48 -35
  57. data/lib/backup/storage/base.rb +44 -172
  58. data/lib/backup/storage/cloudfiles.rb +31 -46
  59. data/lib/backup/storage/cycler.rb +117 -0
  60. data/lib/backup/storage/dropbox.rb +92 -76
  61. data/lib/backup/storage/ftp.rb +30 -40
  62. data/lib/backup/storage/local.rb +44 -45
  63. data/lib/backup/storage/ninefold.rb +55 -49
  64. data/lib/backup/storage/rsync.rb +49 -56
  65. data/lib/backup/storage/s3.rb +33 -44
  66. data/lib/backup/storage/scp.rb +21 -48
  67. data/lib/backup/storage/sftp.rb +26 -40
  68. data/lib/backup/syncer/base.rb +7 -0
  69. data/lib/backup/syncer/rsync/base.rb +78 -0
  70. data/lib/backup/syncer/rsync/local.rb +53 -0
  71. data/lib/backup/syncer/rsync/pull.rb +38 -0
  72. data/lib/backup/syncer/rsync/push.rb +113 -0
  73. data/lib/backup/syncer/s3.rb +42 -32
  74. data/lib/backup/version.rb +1 -1
  75. data/spec/archive_spec.rb +235 -69
  76. data/spec/cleaner_spec.rb +304 -0
  77. data/spec/cli/helpers_spec.rb +142 -1
  78. data/spec/cli/utility_spec.rb +338 -13
  79. data/spec/compressor/base_spec.rb +31 -0
  80. data/spec/compressor/bzip2_spec.rb +60 -35
  81. data/spec/compressor/gzip_spec.rb +60 -35
  82. data/spec/compressor/lzma_spec.rb +60 -35
  83. data/spec/compressor/pbzip2_spec.rb +98 -37
  84. data/spec/config_spec.rb +321 -0
  85. data/spec/configuration/base_spec.rb +4 -4
  86. data/spec/configuration/compressor/bzip2_spec.rb +1 -0
  87. data/spec/configuration/compressor/gzip_spec.rb +1 -0
  88. data/spec/configuration/compressor/lzma_spec.rb +1 -0
  89. data/spec/configuration/compressor/pbzip2_spec.rb +32 -0
  90. data/spec/configuration/database/base_spec.rb +2 -1
  91. data/spec/configuration/database/mongodb_spec.rb +26 -16
  92. data/spec/configuration/database/mysql_spec.rb +4 -0
  93. data/spec/configuration/database/postgresql_spec.rb +4 -0
  94. data/spec/configuration/database/redis_spec.rb +4 -0
  95. data/spec/configuration/database/riak_spec.rb +4 -0
  96. data/spec/configuration/encryptor/gpg_spec.rb +1 -0
  97. data/spec/configuration/encryptor/open_ssl_spec.rb +1 -0
  98. data/spec/configuration/notifier/base_spec.rb +32 -0
  99. data/spec/configuration/notifier/campfire_spec.rb +1 -0
  100. data/spec/configuration/notifier/hipchat_spec.rb +1 -0
  101. data/spec/configuration/notifier/mail_spec.rb +1 -0
  102. data/spec/configuration/notifier/presently_spec.rb +1 -0
  103. data/spec/configuration/notifier/prowl_spec.rb +1 -0
  104. data/spec/configuration/notifier/twitter_spec.rb +1 -0
  105. data/spec/configuration/storage/cloudfiles_spec.rb +1 -0
  106. data/spec/configuration/storage/dropbox_spec.rb +4 -3
  107. data/spec/configuration/storage/ftp_spec.rb +1 -0
  108. data/spec/configuration/storage/local_spec.rb +1 -0
  109. data/spec/configuration/storage/ninefold_spec.rb +1 -0
  110. data/spec/configuration/storage/rsync_spec.rb +3 -1
  111. data/spec/configuration/storage/s3_spec.rb +1 -0
  112. data/spec/configuration/storage/scp_spec.rb +1 -0
  113. data/spec/configuration/storage/sftp_spec.rb +1 -0
  114. data/spec/configuration/syncer/rsync/base_spec.rb +33 -0
  115. data/spec/configuration/syncer/rsync/local_spec.rb +10 -0
  116. data/spec/configuration/syncer/rsync/pull_spec.rb +10 -0
  117. data/spec/configuration/syncer/{rsync_spec.rb → rsync/push_spec.rb} +12 -15
  118. data/spec/configuration/syncer/s3_spec.rb +2 -3
  119. data/spec/database/base_spec.rb +35 -20
  120. data/spec/database/mongodb_spec.rb +298 -119
  121. data/spec/database/mysql_spec.rb +147 -72
  122. data/spec/database/postgresql_spec.rb +155 -100
  123. data/spec/database/redis_spec.rb +200 -97
  124. data/spec/database/riak_spec.rb +82 -24
  125. data/spec/dependency_spec.rb +49 -0
  126. data/spec/encryptor/base_spec.rb +30 -0
  127. data/spec/encryptor/gpg_spec.rb +105 -28
  128. data/spec/encryptor/open_ssl_spec.rb +85 -114
  129. data/spec/logger_spec.rb +74 -8
  130. data/spec/model_spec.rb +528 -220
  131. data/spec/notifier/base_spec.rb +89 -0
  132. data/spec/notifier/campfire_spec.rb +147 -119
  133. data/spec/notifier/hipchat_spec.rb +140 -145
  134. data/spec/notifier/mail_spec.rb +190 -248
  135. data/spec/notifier/presently_spec.rb +147 -282
  136. data/spec/notifier/prowl_spec.rb +79 -111
  137. data/spec/notifier/twitter_spec.rb +87 -106
  138. data/spec/package_spec.rb +61 -0
  139. data/spec/packager_spec.rb +154 -0
  140. data/spec/spec_helper.rb +36 -13
  141. data/spec/splitter_spec.rb +90 -41
  142. data/spec/storage/base_spec.rb +95 -239
  143. data/spec/storage/cloudfiles_spec.rb +185 -75
  144. data/spec/storage/cycler_spec.rb +239 -0
  145. data/spec/storage/dropbox_spec.rb +318 -87
  146. data/spec/storage/ftp_spec.rb +165 -152
  147. data/spec/storage/local_spec.rb +206 -54
  148. data/spec/storage/ninefold_spec.rb +264 -128
  149. data/spec/storage/rsync_spec.rb +244 -163
  150. data/spec/storage/s3_spec.rb +175 -64
  151. data/spec/storage/scp_spec.rb +156 -150
  152. data/spec/storage/sftp_spec.rb +153 -135
  153. data/spec/syncer/base_spec.rb +22 -0
  154. data/spec/syncer/rsync/base_spec.rb +118 -0
  155. data/spec/syncer/rsync/local_spec.rb +121 -0
  156. data/spec/syncer/rsync/pull_spec.rb +90 -0
  157. data/spec/syncer/rsync/push_spec.rb +327 -0
  158. data/spec/syncer/s3_spec.rb +180 -91
  159. data/templates/cli/utility/config +1 -1
  160. data/templates/cli/utility/database/mongodb +4 -0
  161. data/templates/cli/utility/database/mysql +3 -0
  162. data/templates/cli/utility/database/postgresql +3 -0
  163. data/templates/cli/utility/database/redis +3 -0
  164. data/templates/cli/utility/database/riak +3 -0
  165. data/templates/cli/utility/storage/dropbox +4 -1
  166. data/templates/cli/utility/syncer/rsync_local +12 -0
  167. data/templates/cli/utility/syncer/{rsync → rsync_pull} +2 -2
  168. data/templates/cli/utility/syncer/rsync_push +17 -0
  169. data/templates/storage/dropbox/authorization_url.erb +1 -1
  170. metadata +42 -17
  171. data/lib/backup/configuration/syncer/rsync.rb +0 -45
  172. data/lib/backup/finder.rb +0 -87
  173. data/lib/backup/storage/object.rb +0 -47
  174. data/lib/backup/syncer/rsync.rb +0 -152
  175. data/spec/backup_spec.rb +0 -11
  176. data/spec/finder_spec.rb +0 -91
  177. data/spec/storage/object_spec.rb +0 -74
  178. data/spec/syncer/rsync_spec.rb +0 -195
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Syncer
5
+ module RSync
6
+ class Pull < Push
7
+
8
+ ##
9
+ # Performs the RSync::Pull operation
10
+ # debug options: -vhP
11
+ def perform!
12
+ write_password_file!
13
+
14
+ @directories.each do |directory|
15
+ Logger.message("#{ syncer_name } started syncing '#{ directory }'.")
16
+ Logger.silent(
17
+ run("#{ utility(:rsync) } #{ options } " +
18
+ "'#{ username }@#{ ip }:#{ directory.sub(/^\~\//, '') }' " +
19
+ "'#{ dest_path }'")
20
+ )
21
+ end
22
+
23
+ ensure
24
+ remove_password_file!
25
+ end
26
+
27
+ private
28
+
29
+ ##
30
+ # Return expanded @path
31
+ def dest_path
32
+ @dest_path ||= File.expand_path(@path)
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,113 @@
1
+ # encoding: utf-8
2
+
3
+ module Backup
4
+ module Syncer
5
+ module RSync
6
+ class Push < Base
7
+
8
+ ##
9
+ # Server credentials
10
+ attr_accessor :username, :password
11
+
12
+ ##
13
+ # Server IP Address and SSH port
14
+ attr_accessor :ip
15
+
16
+ ##
17
+ # The SSH port to connect to
18
+ attr_accessor :port
19
+
20
+ ##
21
+ # Flag for compressing (only compresses for the transfer)
22
+ attr_accessor :compress
23
+
24
+ ##
25
+ # Instantiates a new RSync::Push or RSync::Pull Syncer object.
26
+ # Default configuration values and any specified in
27
+ # Backup::Configuration::Syncer::RSync::[Push/Pull] are set from Base.
28
+ # The user's configuration file is then evaluated to overwrite
29
+ # these values or provide additional configuration.
30
+ def initialize(&block)
31
+ super
32
+
33
+ @port ||= 22
34
+ @compress ||= false
35
+
36
+ instance_eval(&block) if block_given?
37
+ end
38
+
39
+ ##
40
+ # Performs the RSync:Push operation
41
+ # debug options: -vhP
42
+ def perform!
43
+ write_password_file!
44
+
45
+ Logger.message(
46
+ "#{ syncer_name } started syncing the following directories:\n\s\s" +
47
+ @directories.join("\n\s\s")
48
+ )
49
+ Logger.silent(
50
+ run("#{ utility(:rsync) } #{ options } #{ directories_option } " +
51
+ "'#{ username }@#{ ip }:#{ dest_path }'")
52
+ )
53
+
54
+ ensure
55
+ remove_password_file!
56
+ end
57
+
58
+ private
59
+
60
+ ##
61
+ # Return @path with any preceeding "~/" removed
62
+ def dest_path
63
+ @dest_path ||= @path.sub(/^\~\//, '')
64
+ end
65
+
66
+ ##
67
+ # Returns all the specified Rsync::[Push/Pull] options,
68
+ # concatenated, ready for the CLI
69
+ def options
70
+ ([archive_option, mirror_option, compress_option, port_option,
71
+ password_option] + additional_options).compact.join("\s")
72
+ end
73
+
74
+ ##
75
+ # Returns Rsync syntax for compressing the file transfers
76
+ def compress_option
77
+ '--compress' if @compress
78
+ end
79
+
80
+ ##
81
+ # Returns Rsync syntax for defining a port to connect to
82
+ def port_option
83
+ "-e 'ssh -p #{@port}'"
84
+ end
85
+
86
+ ##
87
+ # Returns Rsync syntax for setting a password (via a file)
88
+ def password_option
89
+ "--password-file='#{@password_file.path}'" if @password_file
90
+ end
91
+
92
+ ##
93
+ # Writes the provided password to a temporary file so that
94
+ # the rsync utility can read the password from this file
95
+ def write_password_file!
96
+ unless @password.nil?
97
+ @password_file = Tempfile.new('backup-rsync-password')
98
+ @password_file.write(@password)
99
+ @password_file.close
100
+ end
101
+ end
102
+
103
+ ##
104
+ # Removes the previously created @password_file
105
+ # (temporary file containing the password)
106
+ def remove_password_file!
107
+ @password_file.delete if @password_file
108
+ @password_file = nil
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -14,7 +14,7 @@ module Backup
14
14
 
15
15
  ##
16
16
  # Directories to sync
17
- attr_accessor :directories
17
+ attr_writer :directories
18
18
 
19
19
  ##
20
20
  # Flag to enable mirroring
@@ -26,75 +26,85 @@ module Backup
26
26
 
27
27
  ##
28
28
  # Instantiates a new S3 Syncer object and sets the default configuration
29
- # specified in the Backup::Configuration::Syncer::S3. Then it sets the object
30
- # defaults if particular properties weren't set. Finally it'll evaluate the users
31
- # configuration file and overwrite anything that's been defined
29
+ # specified in the Backup::Configuration::Syncer::S3.
30
+ # Then it sets the object defaults if particular properties weren't set.
31
+ # Finally it'll evaluate the users configuration file and overwrite
32
+ # anything that's been defined
32
33
  def initialize(&block)
33
34
  load_defaults!
34
35
 
35
36
  @path ||= 'backups'
36
- @directories ||= Array.new
37
+ @directories = Array.new
37
38
  @mirror ||= false
38
39
  @additional_options ||= []
39
40
 
40
41
  instance_eval(&block) if block_given?
41
-
42
- @path = path.sub(/^\//, '')
43
42
  end
44
43
 
45
44
  ##
46
- # Performs the S3Sync operation
47
- # First it'll set the Amazon S3 credentials for S3Sync before invoking it,
48
- # and once it's finished syncing the files and directories to Amazon S3, it'll
49
- # unset these credentials (back to nil values)
45
+ # Sets the Amazon S3 credentials for S3Sync, performs the S3Sync
46
+ # operation, then unsets the credentials (back to nil values)
50
47
  def perform!
51
48
  set_environment_variables!
52
49
 
53
- directories.each do |directory|
54
- Logger.message("#{ self.class } started syncing '#{ directory }'.")
55
- Logger.silent( run("#{ utility(:s3sync) } #{ options } '#{ directory }' '#{ bucket }:#{ path }'") )
50
+ @directories.each do |directory|
51
+ Logger.message("#{ syncer_name } started syncing '#{ directory }'.")
52
+ Logger.silent(
53
+ run("#{ utility(:s3sync) } #{ options } " +
54
+ "'#{ File.expand_path(directory) }' '#{ bucket }:#{ dest_path }'")
55
+ )
56
56
  end
57
57
 
58
58
  unset_environment_variables!
59
59
  end
60
60
 
61
61
  ##
62
- # Returns all the specified S3Sync options, concatenated, ready for the CLI
62
+ # Syntactical suger for the DSL for adding directories
63
+ def directories(&block)
64
+ return @directories unless block_given?
65
+ instance_eval(&block)
66
+ end
67
+
68
+ ##
69
+ # Adds a path to the @directories array
70
+ def add(path)
71
+ @directories << path
72
+ end
73
+
74
+ private
75
+
76
+ ##
77
+ # Return @path with preceeding '/' slash removed
78
+ def dest_path
79
+ @dest_path ||= @path.sub(/^\//, '')
80
+ end
81
+
82
+ ##
83
+ # Returns all the specified S3Sync options,
84
+ # concatenated, ready for the CLI
63
85
  def options
64
- ([verbose, recursive, mirror] + additional_options).compact.join("\s")
86
+ ([verbose_option, recursive_option, mirror_option] +
87
+ additional_options).compact.join("\s")
65
88
  end
66
89
 
67
90
  ##
68
91
  # Returns S3Sync syntax for enabling mirroring
69
- def mirror
92
+ def mirror_option
70
93
  '--delete' if @mirror
71
94
  end
72
95
 
73
96
  ##
74
97
  # Returns S3Sync syntax for syncing recursively
75
- def recursive
98
+ def recursive_option
76
99
  '--recursive'
77
100
  end
78
101
 
79
102
  ##
80
103
  # Returns S3Sync syntax for making output verbose
81
- def verbose
104
+ def verbose_option
82
105
  '--verbose'
83
106
  end
84
107
 
85
- ##
86
- # Syntactical suger for the DSL for adding directories
87
- def directories(&block)
88
- return @directories unless block_given?
89
- instance_eval(&block)
90
- end
91
-
92
- ##
93
- # Adds a path to the @directories array
94
- def add(path)
95
- @directories << path
96
- end
97
-
98
108
  ##
99
109
  # In order for S3Sync to know what credentials to use, we have to set the
100
110
  # AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables, these
@@ -13,7 +13,7 @@ module Backup
13
13
  # Defines the minor version
14
14
  # PATCH:
15
15
  # Defines the patch version
16
- MAJOR, MINOR, PATCH = 3, 0, 20
16
+ MAJOR, MINOR, PATCH = 3, 0, 21
17
17
 
18
18
  ##
19
19
  # Returns the major version ( big release based off of multiple minor releases )
@@ -3,112 +3,278 @@
3
3
  require File.expand_path('../spec_helper.rb', __FILE__)
4
4
 
5
5
  describe Backup::Archive do
6
+ let(:model) { Backup::Model.new(:test_trigger, 'test model') }
7
+ let(:archive) { Backup::Archive.new(model, :test_archive) }
6
8
 
7
- let(:archive) do
8
- Backup::Archive.new(:dummy_archive) do |a|
9
- a.add '/home/rspecuser/somefile'
10
- a.add '/home/rspecuser/logs'
11
- a.add '/home/rspecuser/dotfiles'
12
- a.exclude '/home/rspecuser/badfile'
13
- a.exclude '/home/rspecuser/wrongdir'
9
+ describe '#initialize' do
10
+
11
+ it 'should have no paths' do
12
+ archive.paths.should == []
14
13
  end
15
- end
16
14
 
17
- it 'should have no paths' do
18
- archive = Backup::Archive.new(:dummy_archive) { |a| }
19
- archive.paths.count.should == 0
20
- end
15
+ it 'should have no excludes' do
16
+ archive.excludes.should == []
17
+ end
21
18
 
22
- it 'should have no excludes' do
23
- archive = Backup::Archive.new(:dummy_archive) { |a| }
24
- archive.excludes.count.should == 0
25
- end
19
+ it 'should have no tar_args' do
20
+ archive.tar_args.should == ''
21
+ end
26
22
 
27
- it 'should have 3 paths' do
28
- archive.paths.count.should == 3
29
- end
23
+ it 'should set a reference to the given model' do
24
+ archive.instance_variable_get(:@model).should be(model)
25
+ end
30
26
 
31
- it 'should have 2 excludes' do
32
- archive.excludes.count.should == 2
33
- end
27
+ it 'should convert name to a String' do
28
+ archive.name.should be_a_kind_of String
29
+ archive.name.should == 'test_archive'
30
+ end
34
31
 
35
- it do
36
- archive.name.should == :dummy_archive
37
- end
32
+ context 'when a configuration block is given' do
33
+ let(:archive) do
34
+ Backup::Archive.new(model, :test_archive) do |a|
35
+ a.add 'added_path'
36
+ a.add 'another/added_path'
37
+ a.exclude 'excluded_path'
38
+ a.exclude 'another/excluded_path'
39
+ a.tar_options '-h --xattrs'
40
+ end
41
+ end
38
42
 
39
- describe '#paths_to_package' do
40
- it 'should return a tar -c friendly string' do
41
- archive.send(:paths_to_package).should ==
42
- "'/home/rspecuser/somefile' '/home/rspecuser/logs' '/home/rspecuser/dotfiles'"
43
+ before do
44
+ File.stubs(:exist?).returns(true)
45
+ end
46
+
47
+ it 'should add @paths' do
48
+ archive.paths.should == [
49
+ File.expand_path('added_path'),
50
+ File.expand_path('another/added_path')
51
+ ]
52
+ end
53
+
54
+ it 'should add @excludes' do
55
+ archive.excludes.should == [
56
+ File.expand_path('excluded_path'),
57
+ File.expand_path('another/excluded_path')
58
+ ]
59
+ end
60
+
61
+ it 'should add @tar_args' do
62
+ archive.tar_args.should == '-h --xattrs'
63
+ end
64
+ end
65
+
66
+ end # describe '#initialize'
67
+
68
+ describe '#add' do
69
+
70
+ context 'when the path exists' do
71
+ it 'should expand and add the path to @paths' do
72
+ File.expects(:exist?).with(File.expand_path('foo')).returns(true)
73
+ Backup::Logger.expects(:warn).never
74
+
75
+ archive.add 'foo'
76
+ archive.paths.should == [File.expand_path('foo')]
77
+ end
78
+ end
79
+
80
+ context 'when a path does not exist' do
81
+ it 'should omit the path and log a warning' do
82
+ File.expects(:exist?).with(
83
+ File.expand_path('path')
84
+ ).returns(true)
85
+ File.expects(:exist?).with(
86
+ File.expand_path('foo')
87
+ ).returns(false)
88
+ File.expects(:exist?).with(
89
+ File.expand_path('another/path')
90
+ ).returns(true)
91
+
92
+ Backup::Logger.expects(:warn).with do |err|
93
+ err.should be_an_instance_of Backup::Errors::Archive::NotFoundError
94
+ err.message.should ==
95
+ "Archive::NotFoundError: The following path was not found:\n" +
96
+ " #{ File.expand_path('foo') }\n" +
97
+ " This path will be omitted from the 'test_archive' Archive."
98
+ end
99
+
100
+ archive.add 'path'
101
+ archive.add 'foo'
102
+ archive.add 'another/path'
103
+ archive.paths.should == [
104
+ File.expand_path('path'),
105
+ File.expand_path('another/path')
106
+ ]
107
+ end
43
108
  end
44
109
  end
45
110
 
46
- describe '#paths_to_exclude' do
47
- it 'should be empty' do
48
- archive = Backup::Archive.new(:dummy_archive) { |a| }
49
- archive.send(:paths_to_exclude).should be_nil
111
+ describe '#exclude' do
112
+ it 'should expand and add the given path to #excludes' do
113
+ archive.exclude 'path'
114
+ archive.exclude 'another/path'
115
+ archive.excludes.should == [
116
+ File.expand_path('path'),
117
+ File.expand_path('another/path')
118
+ ]
50
119
  end
120
+ end
51
121
 
52
- it 'should return a tar -c friendly string' do
53
- archive.send(:paths_to_exclude).should ==
54
- "--exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir'"
122
+ describe '#tar_options' do
123
+ it 'should set #tar_options to the given string' do
124
+ archive = Backup::Archive.new(model, :test_archive) do |a|
125
+ a.tar_options '-h --xattrs'
126
+ end
127
+ archive.tar_args.should == '-h --xattrs'
55
128
  end
56
129
  end
57
130
 
58
131
  describe '#perform!' do
132
+ let(:archive_path) do
133
+ File.join(Backup::Config.tmp_path, 'test_trigger', 'archives')
134
+ end
135
+ let(:paths) { ['/path/to/add', '/another/path/to/add'] }
136
+ let(:excludes) { ['/path/to/exclude', '/another/path/to/exclude'] }
137
+
59
138
  before do
60
- [:mkdir, :run, :utility].each { |method| archive.stubs(method) }
139
+ archive.expects(:utility).with(:tar).returns('tar')
140
+ FileUtils.expects(:mkdir_p).with(archive_path)
61
141
  end
62
142
 
63
- context 'when both paths were added and paths that should be excluded were added' do
64
- it 'should render both the syntax for the paths that be included as well as excluded' do
65
- archive.expects(:mkdir).with(File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive'))
143
+ context 'when both #paths and #excludes were added' do
144
+ before do
145
+ archive.instance_variable_set(:@paths, paths)
146
+ archive.instance_variable_set(:@excludes, excludes)
147
+ end
148
+
149
+ it 'should render the syntax for both' do
150
+ Backup::Logger.expects(:message).with(
151
+ "Backup::Archive started packaging and archiving:\n" +
152
+ " /path/to/add\n" +
153
+ " /another/path/to/add"
154
+ )
155
+
66
156
  archive.expects(:run).with(
67
- "tar -cf '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' --exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir' '/home/rspecuser/somefile' '/home/rspecuser/logs' '/home/rspecuser/dotfiles'",
68
- :ignore_exit_codes => [1]
157
+ "tar -cf - " +
158
+ "--exclude='/path/to/exclude' --exclude='/another/path/to/exclude' " +
159
+ "'/path/to/add' '/another/path/to/add' " +
160
+ "> '#{ File.join(archive_path, 'test_archive.tar') }'"
69
161
  )
70
- archive.expects(:utility).with(:tar).returns(:tar)
162
+
71
163
  archive.perform!
72
164
  end
73
- end
165
+ end # context 'when both #paths and #excludes were added'
74
166
 
75
- context 'when there are paths to add, and no exclude patterns were defined' do
76
- it 'should only render syntax for the defined paths' do
77
- archive = Backup::Archive.new(:dummy_archive) do |a|
78
- a.add '/path/to/archive'
79
- end
167
+ context 'when no excludes were added' do
168
+ before do
169
+ archive.instance_variable_set(:@paths, paths)
170
+ end
171
+
172
+ it 'should render only the syntax for adds' do
173
+ Backup::Logger.expects(:message).with(
174
+ "Backup::Archive started packaging and archiving:\n" +
175
+ " /path/to/add\n" +
176
+ " /another/path/to/add"
177
+ )
80
178
 
81
- archive.stubs(:utility).returns(:tar)
82
179
  archive.expects(:run).with(
83
- "tar -cf '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' '/path/to/archive'",
84
- :ignore_exit_codes => [1]
180
+ "tar -cf - " +
181
+ "'/path/to/add' '/another/path/to/add' " +
182
+ "> '#{ File.join(archive_path, 'test_archive.tar') }'"
85
183
  )
184
+
86
185
  archive.perform!
87
186
  end
88
- end
187
+ end # context 'when no excludes were added'
188
+ context 'with #paths, #excludes and #tar_args' do
189
+ before do
190
+ archive.instance_variable_set(:@paths, paths)
191
+ archive.instance_variable_set(:@excludes, excludes)
192
+ archive.instance_variable_set(:@tar_args, '-h --xattrs')
193
+ end
89
194
 
90
- context 'when tar_options are given' do
91
- it 'should add the options to the tar command' do
92
- archive = Backup::Archive.new(:dummy_archive) do |a|
93
- a.add '/path/to/archive'
94
- a.tar_options '-h --xattrs'
95
- end
195
+ it 'should render the syntax for all three' do
196
+ Backup::Logger.expects(:message).with(
197
+ "Backup::Archive started packaging and archiving:\n" +
198
+ " /path/to/add\n" +
199
+ " /another/path/to/add"
200
+ )
201
+
202
+ archive.expects(:run).with(
203
+ "tar -h --xattrs -cf - " +
204
+ "--exclude='/path/to/exclude' --exclude='/another/path/to/exclude' " +
205
+ "'/path/to/add' '/another/path/to/add' " +
206
+ "> '#{ File.join(archive_path, 'test_archive.tar') }'"
207
+ )
208
+
209
+ archive.perform!
210
+ end
211
+ end # context 'with #paths, #excludes and #tar_args'
212
+
213
+ context 'with #paths, #excludes, #tar_args and a Gzip Compressor' do
214
+ before do
215
+ archive.instance_variable_set(:@paths, paths)
216
+ archive.instance_variable_set(:@excludes, excludes)
217
+ archive.instance_variable_set(:@tar_args, '-h --xattrs')
218
+ compressor = mock
219
+ model.expects(:compressor).twice.returns(compressor)
220
+ compressor.expects(:compress_with).yields('gzip', '.gz')
221
+ end
222
+
223
+ it 'should render the syntax with compressor modifications' do
224
+ Backup::Logger.expects(:message).with(
225
+ "Backup::Archive started packaging and archiving:\n" +
226
+ " /path/to/add\n" +
227
+ " /another/path/to/add"
228
+ )
96
229
 
97
- archive.stubs(:utility).returns(:tar)
98
230
  archive.expects(:run).with(
99
- "tar -h --xattrs -cf '#{File.join(Backup::TMP_PATH, Backup::TRIGGER, 'archive', "#{:dummy_archive}.tar")}' '/path/to/archive'",
100
- :ignore_exit_codes => [1]
231
+ "tar -h --xattrs -cf - " +
232
+ "--exclude='/path/to/exclude' --exclude='/another/path/to/exclude' " +
233
+ "'/path/to/add' '/another/path/to/add' " +
234
+ "| gzip > '#{ File.join(archive_path, 'test_archive.tar.gz') }'"
101
235
  )
236
+
102
237
  archive.perform!
103
238
  end
239
+ end # context 'with #paths, #excludes, #tar_args and a Gzip Compressor'
240
+
241
+ end # describe '#perform!'
242
+
243
+ describe '#paths_to_package' do
244
+ before do
245
+ archive.instance_variable_set(
246
+ :@paths,
247
+ ['/home/rspecuser/somefile',
248
+ '/home/rspecuser/logs',
249
+ '/home/rspecuser/dotfiles']
250
+ )
104
251
  end
105
- it 'should log the status' do
106
- Backup::Logger.expects(:message).
107
- with("Backup::Archive started packaging and archiving:\n" +
108
- " /home/rspecuser/somefile\n" +
109
- " /home/rspecuser/logs\n" +
110
- " /home/rspecuser/dotfiles")
111
- archive.perform!
252
+
253
+ it 'should return a tar friendly string' do
254
+ archive.send(:paths_to_package).should ==
255
+ "'/home/rspecuser/somefile' '/home/rspecuser/logs' '/home/rspecuser/dotfiles'"
256
+ end
257
+ end
258
+
259
+ describe '#paths_to_exclude' do
260
+ context 'when no excludes are added' do
261
+ it 'should return nil' do
262
+ archive.send(:paths_to_exclude).should be_nil
263
+ end
264
+ end
265
+
266
+ context 'when excludes are added' do
267
+ before do
268
+ archive.instance_variable_set(
269
+ :@excludes,
270
+ ['/home/rspecuser/badfile',
271
+ '/home/rspecuser/wrongdir']
272
+ )
273
+ end
274
+ it 'should return a tar friendly string' do
275
+ archive.send(:paths_to_exclude).should ==
276
+ "--exclude='/home/rspecuser/badfile' --exclude='/home/rspecuser/wrongdir'"
277
+ end
112
278
  end
113
279
  end
114
280
  end