multi_sync 0.0.1

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 (150) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.gitignore +20 -0
  4. data/.rubocop.yml +26 -0
  5. data/.travis.yml +24 -0
  6. data/.yardopts +6 -0
  7. data/CHANGELOG.md +0 -0
  8. data/CONTRIBUTING.md +44 -0
  9. data/Gemfile +17 -0
  10. data/LICENSE.md +20 -0
  11. data/README.md +134 -0
  12. data/Rakefile +45 -0
  13. data/examples/custom.rb +34 -0
  14. data/examples/rails-3-2/.gitignore +15 -0
  15. data/examples/rails-3-2/Gemfile +43 -0
  16. data/examples/rails-3-2/README.rdoc +261 -0
  17. data/examples/rails-3-2/Rakefile +7 -0
  18. data/examples/rails-3-2/app/assets/images/rails.png +0 -0
  19. data/examples/rails-3-2/app/assets/javascripts/application.js +15 -0
  20. data/examples/rails-3-2/app/assets/stylesheets/application.css +13 -0
  21. data/examples/rails-3-2/app/controllers/application_controller.rb +3 -0
  22. data/examples/rails-3-2/app/helpers/application_helper.rb +2 -0
  23. data/examples/rails-3-2/app/mailers/.gitkeep +0 -0
  24. data/examples/rails-3-2/app/models/.gitkeep +0 -0
  25. data/examples/rails-3-2/app/views/layouts/application.html.erb +14 -0
  26. data/examples/rails-3-2/config.ru +4 -0
  27. data/examples/rails-3-2/config/application.rb +62 -0
  28. data/examples/rails-3-2/config/asset_sync.yml +21 -0
  29. data/examples/rails-3-2/config/boot.rb +6 -0
  30. data/examples/rails-3-2/config/database.yml +25 -0
  31. data/examples/rails-3-2/config/environment.rb +5 -0
  32. data/examples/rails-3-2/config/environments/development.rb +37 -0
  33. data/examples/rails-3-2/config/environments/production.rb +67 -0
  34. data/examples/rails-3-2/config/environments/test.rb +37 -0
  35. data/examples/rails-3-2/config/initializers/backtrace_silencers.rb +7 -0
  36. data/examples/rails-3-2/config/initializers/inflections.rb +15 -0
  37. data/examples/rails-3-2/config/initializers/mime_types.rb +5 -0
  38. data/examples/rails-3-2/config/initializers/multi_sync.rb +29 -0
  39. data/examples/rails-3-2/config/initializers/secret_token.rb +7 -0
  40. data/examples/rails-3-2/config/initializers/session_store.rb +8 -0
  41. data/examples/rails-3-2/config/initializers/wrap_parameters.rb +14 -0
  42. data/examples/rails-3-2/config/locales/en.yml +5 -0
  43. data/examples/rails-3-2/config/routes.rb +58 -0
  44. data/examples/rails-3-2/db/seeds.rb +7 -0
  45. data/examples/rails-3-2/lib/assets/.gitkeep +0 -0
  46. data/examples/rails-3-2/lib/tasks/.gitkeep +0 -0
  47. data/examples/rails-3-2/log/.gitkeep +0 -0
  48. data/examples/rails-3-2/public/404.html +26 -0
  49. data/examples/rails-3-2/public/422.html +26 -0
  50. data/examples/rails-3-2/public/500.html +25 -0
  51. data/examples/rails-3-2/public/favicon.ico +0 -0
  52. data/examples/rails-3-2/public/index.html +241 -0
  53. data/examples/rails-3-2/public/robots.txt +5 -0
  54. data/examples/rails-3-2/script/rails +6 -0
  55. data/examples/rails-3-2/test/fixtures/.gitkeep +0 -0
  56. data/examples/rails-3-2/test/functional/.gitkeep +0 -0
  57. data/examples/rails-3-2/test/integration/.gitkeep +0 -0
  58. data/examples/rails-3-2/test/performance/browsing_test.rb +12 -0
  59. data/examples/rails-3-2/test/test_helper.rb +13 -0
  60. data/examples/rails-3-2/test/unit/.gitkeep +0 -0
  61. data/examples/rails-4-0/.gitignore +16 -0
  62. data/examples/rails-4-0/Gemfile +50 -0
  63. data/examples/rails-4-0/README.rdoc +28 -0
  64. data/examples/rails-4-0/Rakefile +6 -0
  65. data/examples/rails-4-0/app/assets/images/.keep +0 -0
  66. data/examples/rails-4-0/app/assets/javascripts/application.js +16 -0
  67. data/examples/rails-4-0/app/assets/stylesheets/application.css +13 -0
  68. data/examples/rails-4-0/app/controllers/application_controller.rb +5 -0
  69. data/examples/rails-4-0/app/controllers/concerns/.keep +0 -0
  70. data/examples/rails-4-0/app/helpers/application_helper.rb +2 -0
  71. data/examples/rails-4-0/app/mailers/.keep +0 -0
  72. data/examples/rails-4-0/app/models/.keep +0 -0
  73. data/examples/rails-4-0/app/models/concerns/.keep +0 -0
  74. data/examples/rails-4-0/app/views/layouts/application.html.erb +14 -0
  75. data/examples/rails-4-0/config.ru +4 -0
  76. data/examples/rails-4-0/config/application.rb +24 -0
  77. data/examples/rails-4-0/config/asset_sync.yml +21 -0
  78. data/examples/rails-4-0/config/boot.rb +4 -0
  79. data/examples/rails-4-0/config/database.yml +25 -0
  80. data/examples/rails-4-0/config/environment.rb +5 -0
  81. data/examples/rails-4-0/config/environments/development.rb +29 -0
  82. data/examples/rails-4-0/config/environments/production.rb +80 -0
  83. data/examples/rails-4-0/config/environments/test.rb +36 -0
  84. data/examples/rails-4-0/config/initializers/backtrace_silencers.rb +7 -0
  85. data/examples/rails-4-0/config/initializers/filter_parameter_logging.rb +4 -0
  86. data/examples/rails-4-0/config/initializers/inflections.rb +16 -0
  87. data/examples/rails-4-0/config/initializers/mime_types.rb +5 -0
  88. data/examples/rails-4-0/config/initializers/multi_sync.rb +29 -0
  89. data/examples/rails-4-0/config/initializers/secret_token.rb +12 -0
  90. data/examples/rails-4-0/config/initializers/session_store.rb +3 -0
  91. data/examples/rails-4-0/config/initializers/wrap_parameters.rb +14 -0
  92. data/examples/rails-4-0/config/locales/en.yml +23 -0
  93. data/examples/rails-4-0/config/routes.rb +56 -0
  94. data/examples/rails-4-0/db/seeds.rb +7 -0
  95. data/examples/rails-4-0/lib/assets/.keep +0 -0
  96. data/examples/rails-4-0/lib/tasks/.keep +0 -0
  97. data/examples/rails-4-0/log/.keep +0 -0
  98. data/examples/rails-4-0/public/404.html +58 -0
  99. data/examples/rails-4-0/public/422.html +58 -0
  100. data/examples/rails-4-0/public/500.html +57 -0
  101. data/examples/rails-4-0/public/favicon.ico +0 -0
  102. data/examples/rails-4-0/public/robots.txt +5 -0
  103. data/examples/rails-4-0/test/controllers/.keep +0 -0
  104. data/examples/rails-4-0/test/fixtures/.keep +0 -0
  105. data/examples/rails-4-0/test/helpers/.keep +0 -0
  106. data/examples/rails-4-0/test/integration/.keep +0 -0
  107. data/examples/rails-4-0/test/mailers/.keep +0 -0
  108. data/examples/rails-4-0/test/models/.keep +0 -0
  109. data/examples/rails-4-0/test/test_helper.rb +15 -0
  110. data/gemfiles/middleman-3.1.x.gemfile +5 -0
  111. data/gemfiles/rails-3.2.x.gemfile +5 -0
  112. data/gemfiles/rails-4.0.x.gemfile +5 -0
  113. data/lib/multi_sync.rb +92 -0
  114. data/lib/multi_sync/client.rb +243 -0
  115. data/lib/multi_sync/configuration.rb +36 -0
  116. data/lib/multi_sync/environment.rb +37 -0
  117. data/lib/multi_sync/extensions/middleman.rb +22 -0
  118. data/lib/multi_sync/extensions/rails.rb +20 -0
  119. data/lib/multi_sync/extensions/rails/asset_sync.rb +44 -0
  120. data/lib/multi_sync/extensions/rails/railtie.rb +11 -0
  121. data/lib/multi_sync/logging.rb +60 -0
  122. data/lib/multi_sync/mixins/log_helper.rb +9 -0
  123. data/lib/multi_sync/mixins/pluralize_helper.rb +15 -0
  124. data/lib/multi_sync/resource.rb +84 -0
  125. data/lib/multi_sync/resources/local_resource.rb +30 -0
  126. data/lib/multi_sync/resources/remote_resource.rb +32 -0
  127. data/lib/multi_sync/source.rb +40 -0
  128. data/lib/multi_sync/sources/local_source.rb +17 -0
  129. data/lib/multi_sync/sources/manifest_source.rb +82 -0
  130. data/lib/multi_sync/target.rb +34 -0
  131. data/lib/multi_sync/targets/aws_target.rb +80 -0
  132. data/lib/multi_sync/targets/local_target.rb +58 -0
  133. data/lib/multi_sync/version.rb +3 -0
  134. data/lib/tasks/multi_sync_rails.rake +15 -0
  135. data/multi_sync.gemspec +35 -0
  136. data/spec/spec_helper.rb +22 -0
  137. data/spec/support/celluloid.rb +14 -0
  138. data/spec/support/fakefs.rb +7 -0
  139. data/spec/support/fog.rb +25 -0
  140. data/spec/support/pry.rb +6 -0
  141. data/spec/support/timecop.rb +2 -0
  142. data/spec/unit/multi_sync/client_spec.rb +301 -0
  143. data/spec/unit/multi_sync/configuration_spec.rb +92 -0
  144. data/spec/unit/multi_sync/resources/local_resource_spec.rb +55 -0
  145. data/spec/unit/multi_sync/sources/local_source_spec.rb +48 -0
  146. data/spec/unit/multi_sync/sources/manifest_source_spec.rb +57 -0
  147. data/spec/unit/multi_sync/targets/aws_target_spec.rb +60 -0
  148. data/spec/unit/multi_sync/targets/local_target_spec.rb +41 -0
  149. data/spec/unit/multi_sync_spec.rb +55 -0
  150. metadata +377 -0
@@ -0,0 +1,80 @@
1
+ require 'multi_sync/target'
2
+ require 'multi_sync/resources/remote_resource'
3
+
4
+ module MultiSync
5
+ class AwsTarget < Target
6
+ # Initialize a new AwsTarget object
7
+ #
8
+ # @param options [Hash]
9
+ def initialize(options = {})
10
+ super(options)
11
+ self.connection = ::Fog::Storage.new(credentials.merge(provider: :aws))
12
+ end
13
+
14
+ def files
15
+ files = []
16
+
17
+ directory = connection.directories.get(target_dir.to_s, prefix: destination_dir.to_s)
18
+ return files if directory.nil?
19
+
20
+ directory.files.lazily.each { |file|
21
+
22
+ pathname = Pathname.new(file.key)
23
+
24
+ # eg directory or overreaching AWS globbing
25
+ next unless valid_path?(pathname)
26
+
27
+ files << MultiSync::RemoteResource.new(
28
+ file: file,
29
+ with_root: target_dir + pathname, # pathname seems to already have the prefix (destination_dir)
30
+ without_root: destination_dir != '' ? pathname.relative_path_from(destination_dir).cleanpath : pathname
31
+ )
32
+
33
+ }
34
+
35
+ files
36
+ end
37
+
38
+ def upload(resource)
39
+ MultiSync.say_status :upload, resource.path_without_root.to_s
40
+ MultiSync.debug "Upload #{resource.class_name}:'#{resource.path_without_root}' to #{class_name}:'#{File.join('/', target_dir + destination_dir)}'"
41
+ directory = connection.directories.get(target_dir.to_s)
42
+ return if directory.nil?
43
+
44
+ upload_hash = {
45
+ key: (destination_dir + resource.path_without_root).to_s,
46
+ body: resource.body,
47
+ content_type: resource.content_type,
48
+ content_md5: Digest::MD5.base64digest(resource.body)
49
+ }
50
+
51
+ MultiSync::Resource::AWS_ATTRIBUTES.each do |attribute_hash|
52
+ upload_hash[attribute_hash[:name]] = resource.send(attribute_hash[:name])
53
+ end
54
+
55
+ directory.files.create(upload_hash)
56
+
57
+ resource
58
+ end
59
+
60
+ def delete(resource)
61
+ MultiSync.say_status :upload, resource.path_without_root.to_s
62
+ MultiSync.debug "Delete #{resource.class_name}:'#{resource.path_without_root}' from #{class_name}:'#{File.join('/', target_dir + destination_dir)}'"
63
+ connection.delete_object(target_dir.to_s, (destination_dir + resource.path_without_root).to_s)
64
+ resource
65
+ end
66
+
67
+ private
68
+
69
+ # directory or overreaching AWS globbing
70
+ def valid_path?(pathname)
71
+ # directory
72
+ return false if pathname.to_s =~ /\/$/
73
+
74
+ # overreaching AWS globbing
75
+ return false if !destination_dir.to_s.empty? && !(pathname.to_s =~ /^#{destination_dir.to_s}\//)
76
+
77
+ true
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,58 @@
1
+ require 'multi_sync/target'
2
+ require 'multi_sync/resources/remote_resource'
3
+
4
+ module MultiSync
5
+ class LocalTarget < Target
6
+ # Initialize a new LocalTarget object
7
+ #
8
+ # @param options [Hash]
9
+ def initialize(options = {})
10
+ super(options)
11
+ self.connection = ::Fog::Storage.new(credentials.merge(provider: :local))
12
+ end
13
+
14
+ def files
15
+ files = []
16
+
17
+ directory = connection.directories.get(destination_dir.to_s)
18
+ return files if directory.nil?
19
+
20
+ directory.files.lazily.each { |file|
21
+
22
+ pathname = Pathname.new(file.key)
23
+
24
+ # directory
25
+ next if pathname.directory?
26
+
27
+ MultiSync.debug "Found RemoteResource:'#{pathname}' from #{class_name}:'#{File.join(connection.local_root, destination_dir)}'"
28
+
29
+ files << MultiSync::RemoteResource.new(
30
+ file: file,
31
+ with_root: target_dir + destination_dir + pathname,
32
+ without_root: pathname
33
+ )
34
+
35
+ }
36
+
37
+ files
38
+ end
39
+
40
+ def upload(resource)
41
+ key = resource.path_without_root.to_s
42
+ MultiSync.say_status :upload, key
43
+ MultiSync.debug "Upload #{resource.class_name}:'#{key}' to #{class_name}:'#{File.join(connection.local_root, destination_dir)}'"
44
+ directory = connection.directories.get(destination_dir.to_s)
45
+ return if directory.nil?
46
+ directory.files.create(key: key, body: resource.body)
47
+ resource
48
+ end
49
+
50
+ def delete(resource)
51
+ key = resource.path_without_root.to_s
52
+ MultiSync.say_status :delete, key
53
+ MultiSync.debug "Delete #{resource.class_name}:'#{key}' from #{class_name}:'#{File.join(connection.local_root, destination_dir)}'"
54
+ connection.directories.get(destination_dir.to_s).files.get(key).destroy
55
+ resource
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module MultiSync
2
+ VERSION = '0.0.1' unless defined?(MultiSync::VERSION)
3
+ end
@@ -0,0 +1,15 @@
1
+ require 'multi_sync'
2
+
3
+ namespace :assets do
4
+ desc 'Synchronize assets'
5
+ task :sync => :environment do
6
+ ActiveSupport::Notifications.instrument 'multi_sync.run' do
7
+ MultiSync::Extensions::AssetSync.check_and_migrate
8
+ MultiSync.run
9
+ end
10
+ end
11
+ end
12
+
13
+ Rake::Task['assets:precompile'].enhance do
14
+ Rake::Task['assets:sync'].invoke if defined?(MultiSync) && MultiSync.run_on_build
15
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'multi_sync/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'multi_sync'
8
+ spec.version = MultiSync::VERSION
9
+ spec.authors = ['Karl Freeman']
10
+ spec.email = ['karlfreeman@gmail.com']
11
+ spec.summary = %q{A flexible synchronisation library for your assets}
12
+ spec.description = %q{A flexible synchronisation library for your assets}
13
+ spec.homepage = 'https://github.com/karlfreeman/multi_sync'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+ spec.required_ruby_version = '>= 1.9.3'
21
+
22
+ spec.add_dependency 'fog', '~> 1.12'
23
+ spec.add_dependency 'lazily', '~> 0.1'
24
+ spec.add_dependency 'virtus', '~> 0.5'
25
+ spec.add_dependency 'celluloid', '~> 0.15'
26
+ spec.add_dependency 'multi_mime', '~> 1.0'
27
+ spec.add_dependency 'multi_json', '~> 1.7'
28
+
29
+ spec.add_development_dependency 'bundler', '~> 1.5'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'kramdown', '>= 0.14'
32
+ spec.add_development_dependency 'rubocop'
33
+ spec.add_development_dependency 'pry'
34
+ spec.add_development_dependency 'yard'
35
+ end
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'bundler'
4
+ Bundler.setup
5
+
6
+ %w(support).each do |dir|
7
+ Dir.glob(File.expand_path("../#{dir}/**/*.rb", __FILE__), &method(:require))
8
+ end
9
+
10
+ require 'multi_sync'
11
+
12
+ RSpec.configure do |config|
13
+ config.expect_with :rspec do |c|
14
+ c.syntax = :expect
15
+ end
16
+
17
+ config.before(:each) do
18
+ MultiSync.reset!
19
+ MultiSync.env = :test
20
+ MultiSync.verbose = true
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ require 'celluloid/test'
2
+ Celluloid.shutdown_timeout = 1
3
+ RSpec.configure do |config|
4
+ config.around do |ex|
5
+ Celluloid.actor_system = nil
6
+ Thread.list.each do |thread|
7
+ next if thread == Thread.current
8
+ thread.kill
9
+ end
10
+ Celluloid.boot
11
+ ex.run
12
+ Celluloid.shutdown
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ require 'fakefs/safe'
2
+ require 'fakefs/spec_helpers'
3
+ require 'pathname'
4
+ require 'fileutils'
5
+ RSpec.configure do |config|
6
+ config.include FakeFS::SpecHelpers, fakefs: true
7
+ end
@@ -0,0 +1,25 @@
1
+ require 'fog'
2
+ Fog::Mock.delay = 0
3
+
4
+ module Fog
5
+ module SpecHelpers
6
+ def self.extended(example_group)
7
+ example_group.before(:each) do
8
+ Fog.mock!
9
+ Fog::Mock.reset
10
+ end
11
+
12
+ example_group.after(:each) do
13
+ Fog.unmock!
14
+ end
15
+ end
16
+
17
+ def self.included(example_group)
18
+ example_group.extend self
19
+ end
20
+ end
21
+ end
22
+
23
+ RSpec.configure do |config|
24
+ config.include Fog::SpecHelpers, fog: true
25
+ end
@@ -0,0 +1,6 @@
1
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ruby'
2
+ begin
3
+ require 'pry' unless ENV['CI']
4
+ rescue LoadError
5
+ end
6
+ end
@@ -0,0 +1,2 @@
1
+ require 'timecop'
2
+ Timecop.freeze
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+
3
+ describe MultiSync::Client, fakefs: true do
4
+
5
+ before do
6
+ FileUtils.mkdir_p('/tmp/simple')
7
+ File.open('/tmp/simple/foo.txt', 'w') do |f| f.write('foo') end
8
+ File.open('/tmp/simple/bar.txt', 'w') do |f| f.write('bar') end
9
+ FileUtils.mkdir_p('/tmp/simple/in-a-dir')
10
+ File.open('/tmp/simple/in-a-dir/baz.html', 'w') do |f| f.write('baz') end
11
+
12
+ FileUtils.cp_r('/tmp/simple', '/tmp/simple-with-missing-file')
13
+ FileUtils.rm_r('/tmp/simple-with-missing-file/foo.txt')
14
+
15
+ FileUtils.cp_r('/tmp/simple', '/tmp/simple-with-abandoned-file')
16
+ File.open('/tmp/simple-with-abandoned-file/baz.txt', 'w') do |f| f.write('baz') end
17
+
18
+ FileUtils.cp_r('/tmp/simple', '/tmp/simple-with-outdated-file')
19
+ File.open('/tmp/simple-with-outdated-file/foo.txt', 'w') do |f| f.write('not-foo') end
20
+
21
+ FileUtils.mkdir_p('/tmp/complex')
22
+ 50.times do
23
+ File.open("/tmp/complex/#{SecureRandom.urlsafe_base64}.txt", 'w') do |f| f.write(SecureRandom.random_bytes) end
24
+ end
25
+
26
+ FileUtils.mkdir_p('/tmp/complex-empty')
27
+ end
28
+
29
+ context :sync do
30
+ context :local do
31
+ context 'simple' do
32
+ it 'should work' do
33
+ missing_files_target_options = {
34
+ type: :local,
35
+ target_dir: '/tmp',
36
+ destination_dir: 'simple-with-missing-file',
37
+ credentials: {
38
+ local_root: '/tmp'
39
+ }
40
+ }
41
+
42
+ abandoned_files_target_options = {
43
+ type: :local,
44
+ target_dir: '/tmp',
45
+ destination_dir: 'simple-with-abandoned-file',
46
+ credentials: {
47
+ local_root: '/tmp'
48
+ }
49
+ }
50
+
51
+ outdated_files_target_options = {
52
+ type: :local,
53
+ target_dir: '/tmp',
54
+ destination_dir: 'simple-with-outdated-file',
55
+ credentials: {
56
+ local_root: '/tmp'
57
+ }
58
+ }
59
+
60
+ local_source_options = {
61
+ type: :local,
62
+ source_dir: '/tmp/simple'
63
+ }
64
+
65
+ missing_files_target = MultiSync::LocalTarget.new(missing_files_target_options)
66
+ abandoned_files_target = MultiSync::LocalTarget.new(abandoned_files_target_options)
67
+ outdated_files_target = MultiSync::LocalTarget.new(outdated_files_target_options)
68
+
69
+ expect(missing_files_target).to have(2).files
70
+ expect(abandoned_files_target).to have(4).files
71
+ expect(outdated_files_target).to have(3).files
72
+
73
+ local_source = MultiSync::LocalSource.new(local_source_options)
74
+ expect(local_source).to have(3).files
75
+
76
+ expect(outdated_files_target.files[1].body).to eq 'not-foo'
77
+
78
+ MultiSync.run do
79
+ target :missing_files_target, missing_files_target_options
80
+ target :abandoned_files_target, abandoned_files_target_options
81
+ target :outdated_files_target, outdated_files_target_options
82
+ source :simple, local_source_options.merge(targets: [:missing_files_target, :abandoned_files_target, :outdated_files_target])
83
+ end
84
+
85
+ expect(missing_files_target).to have(3).files
86
+ expect(abandoned_files_target).to have(3).files
87
+ expect(outdated_files_target).to have(3).files
88
+ expect(outdated_files_target.files[1].body).to eq 'foo'
89
+ end
90
+ end
91
+
92
+ context 'complex' do
93
+ it 'should work' do
94
+ complex_empty_target_options = {
95
+ type: :local,
96
+ target_dir: '/tmp',
97
+ destination_dir: 'complex-empty',
98
+ credentials: {
99
+ local_root: '/tmp'
100
+ }
101
+ }
102
+
103
+ local_source_options = {
104
+ type: :local,
105
+ source_dir: '/tmp/complex'
106
+ }
107
+
108
+ complex_empty_target = MultiSync::LocalTarget.new(complex_empty_target_options)
109
+ expect(complex_empty_target).to have(0).files
110
+
111
+ local_source = MultiSync::LocalSource.new(local_source_options)
112
+ expect(local_source).to have(50).files
113
+
114
+ MultiSync.run do
115
+ target :complex_empty_target, complex_empty_target_options
116
+ source :complex, local_source_options.merge(targets: [:complex_empty_target])
117
+ end
118
+
119
+ expect(complex_empty_target).to have(50).files
120
+ end
121
+ end
122
+ end
123
+
124
+ context :aws, fog: true do
125
+ context 'simple' do
126
+ before do
127
+ connection = Fog::Storage.new(
128
+ provider: :aws,
129
+ region: 'us-east-1',
130
+ aws_access_key_id: 'xxx',
131
+ aws_secret_access_key: 'xxx'
132
+ )
133
+
134
+ directory = connection.directories.create(key: 'multi_sync', public: true)
135
+
136
+ %w(simple simple-with-missing-file simple-with-abandoned-file simple-with-outdated-file).each do |fixture_name|
137
+ Dir.glob("/tmp/#{fixture_name}/**/*").reject { |path| File.directory?(path) }.each do |path|
138
+ directory.files.create(
139
+ key: path.gsub('/tmp/', ''),
140
+ body: File.open(path, 'r'),
141
+ public: true
142
+ )
143
+ end
144
+ end
145
+ end
146
+
147
+ it 'should work' do
148
+ missing_files_target_options = {
149
+ type: :aws,
150
+ target_dir: 'multi_sync',
151
+ destination_dir: 'simple-with-missing-file',
152
+ credentials: {
153
+ region: 'us-east-1',
154
+ aws_access_key_id: 'xxx',
155
+ aws_secret_access_key: 'xxx'
156
+ }
157
+ }
158
+
159
+ abandoned_files_target_options = {
160
+ type: :aws,
161
+ target_dir: 'multi_sync',
162
+ destination_dir: 'simple-with-abandoned-file',
163
+ credentials: {
164
+ region: 'us-east-1',
165
+ aws_access_key_id: 'xxx',
166
+ aws_secret_access_key: 'xxx'
167
+ }
168
+ }
169
+
170
+ outdated_files_target_options = {
171
+ type: :aws,
172
+ target_dir: 'multi_sync',
173
+ destination_dir: 'simple-with-outdated-file',
174
+ credentials: {
175
+ region: 'us-east-1',
176
+ aws_access_key_id: 'xxx',
177
+ aws_secret_access_key: 'xxx'
178
+ }
179
+ }
180
+
181
+ local_source_options = {
182
+ type: :local,
183
+ source_dir: '/tmp/simple'
184
+ }
185
+
186
+ missing_files_target = MultiSync::AwsTarget.new(missing_files_target_options)
187
+ abandoned_files_target = MultiSync::AwsTarget.new(abandoned_files_target_options)
188
+ outdated_files_target = MultiSync::AwsTarget.new(outdated_files_target_options)
189
+
190
+ expect(missing_files_target).to have(2).files
191
+ expect(abandoned_files_target).to have(4).files
192
+ expect(outdated_files_target).to have(3).files
193
+
194
+ local_source = MultiSync::LocalSource.new(local_source_options)
195
+ expect(local_source).to have(3).files
196
+
197
+ expect(outdated_files_target.files[1].body).to eq 'not-foo'
198
+
199
+ MultiSync.run do
200
+ target :missing_files_target, missing_files_target_options
201
+ target :abandoned_files_target, abandoned_files_target_options
202
+ target :outdated_files_target, outdated_files_target_options
203
+ source :simple, local_source_options.merge(targets: [:missing_files_target, :abandoned_files_target, :outdated_files_target])
204
+ end
205
+
206
+ expect(missing_files_target).to have(3).files
207
+ expect(abandoned_files_target).to have(3).files
208
+ expect(outdated_files_target).to have(3).files
209
+ expect(outdated_files_target.files[1].body).to eq 'foo'
210
+ end
211
+ end
212
+
213
+ context 'complex' do
214
+ before do
215
+ connection = Fog::Storage.new(
216
+ provider: :aws,
217
+ region: 'us-east-1',
218
+ aws_access_key_id: 'xxx',
219
+ aws_secret_access_key: 'xxx'
220
+ )
221
+
222
+ connection.directories.create(key: 'multi_sync', public: true)
223
+ end
224
+
225
+ it 'should work' do
226
+ complex_empty_target_options = {
227
+ type: :aws,
228
+ target_dir: 'multi_sync',
229
+ destination_dir: 'complex-empty',
230
+ credentials: {
231
+ region: 'us-east-1',
232
+ aws_access_key_id: 'xxx',
233
+ aws_secret_access_key: 'xxx'
234
+ }
235
+ }
236
+
237
+ local_source_options = {
238
+ type: :local,
239
+ source_dir: '/tmp/complex'
240
+ }
241
+
242
+ complex_empty_target = MultiSync::AwsTarget.new(complex_empty_target_options)
243
+ expect(complex_empty_target).to have(0).files
244
+
245
+ local_source = MultiSync::LocalSource.new(local_source_options)
246
+ expect(local_source).to have(50).files
247
+
248
+ MultiSync.run do
249
+ target :complex_empty_target, complex_empty_target_options
250
+ source :complex, local_source_options.merge(targets: [:complex_empty_target])
251
+ end
252
+
253
+ expect(complex_empty_target).to have(50).files
254
+ end
255
+ end
256
+
257
+ context 'without a destination_dir' do
258
+ before do
259
+ connection = Fog::Storage.new(
260
+ provider: :aws,
261
+ region: 'us-east-1',
262
+ aws_access_key_id: 'xxx',
263
+ aws_secret_access_key: 'xxx'
264
+ )
265
+
266
+ connection.directories.create(key: 'without_destination_dir', public: true)
267
+ end
268
+
269
+ it 'should work' do
270
+ without_destination_dir_target_options = {
271
+ type: :aws,
272
+ target_dir: 'without_destination_dir',
273
+ credentials: {
274
+ region: 'us-east-1',
275
+ aws_access_key_id: 'xxx',
276
+ aws_secret_access_key: 'xxx'
277
+ }
278
+ }
279
+
280
+ local_source_options = {
281
+ type: :local,
282
+ source_dir: '/tmp/simple'
283
+ }
284
+
285
+ without_destination_dir_target = MultiSync::AwsTarget.new(without_destination_dir_target_options)
286
+ expect(without_destination_dir_target).to have(0).files
287
+
288
+ local_source = MultiSync::LocalSource.new(local_source_options)
289
+ expect(local_source).to have(3).files
290
+
291
+ MultiSync.run do
292
+ target :without_destination_dir_target, without_destination_dir_target_options
293
+ source :local, local_source_options.merge(targets: :without_destination_dir_target)
294
+ end
295
+
296
+ expect(without_destination_dir_target).to have(3).files
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end