backup 3.0.20 → 3.0.21

Sign up to get free protection for your applications and to get access to all the features.
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