multi_sync 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/README.md +100 -56
  4. data/lib/multi_sync/attributes/pathname.rb +12 -0
  5. data/lib/multi_sync/client.rb +34 -36
  6. data/lib/multi_sync/configuration.rb +3 -5
  7. data/lib/multi_sync/extensions/middleman.rb +1 -1
  8. data/lib/multi_sync/extensions/rails/asset_sync.rb +2 -2
  9. data/lib/multi_sync/extensions/rails.rb +1 -1
  10. data/lib/multi_sync/logging.rb +2 -2
  11. data/lib/multi_sync/resource.rb +15 -32
  12. data/lib/multi_sync/resources/local_resource.rb +1 -0
  13. data/lib/multi_sync/resources/remote_resource.rb +1 -4
  14. data/lib/multi_sync/source.rb +10 -22
  15. data/lib/multi_sync/sources/manifest_source.rb +2 -2
  16. data/lib/multi_sync/target.rb +5 -16
  17. data/lib/multi_sync/targets/aws_target.rb +7 -10
  18. data/lib/multi_sync/targets/local_target.rb +6 -9
  19. data/lib/multi_sync/version.rb +1 -1
  20. data/lib/multi_sync.rb +1 -1
  21. data/lib/tasks/multi_sync_rails.rake +8 -2
  22. data/multi_sync.gemspec +2 -2
  23. data/spec/unit/multi_sync/client_spec.rb +3 -0
  24. data/spec/unit/multi_sync/resources/local_resource_spec.rb +6 -8
  25. data/spec/unit/multi_sync_spec.rb +0 -8
  26. metadata +7 -106
  27. data/examples/custom.rb +0 -34
  28. data/examples/rails-3-2/.gitignore +0 -15
  29. data/examples/rails-3-2/Gemfile +0 -43
  30. data/examples/rails-3-2/README.rdoc +0 -261
  31. data/examples/rails-3-2/Rakefile +0 -7
  32. data/examples/rails-3-2/app/assets/images/rails.png +0 -0
  33. data/examples/rails-3-2/app/assets/javascripts/application.js +0 -15
  34. data/examples/rails-3-2/app/assets/stylesheets/application.css +0 -13
  35. data/examples/rails-3-2/app/controllers/application_controller.rb +0 -3
  36. data/examples/rails-3-2/app/helpers/application_helper.rb +0 -2
  37. data/examples/rails-3-2/app/mailers/.gitkeep +0 -0
  38. data/examples/rails-3-2/app/models/.gitkeep +0 -0
  39. data/examples/rails-3-2/app/views/layouts/application.html.erb +0 -14
  40. data/examples/rails-3-2/config/application.rb +0 -62
  41. data/examples/rails-3-2/config/asset_sync.yml +0 -21
  42. data/examples/rails-3-2/config/boot.rb +0 -6
  43. data/examples/rails-3-2/config/database.yml +0 -25
  44. data/examples/rails-3-2/config/environment.rb +0 -5
  45. data/examples/rails-3-2/config/environments/development.rb +0 -37
  46. data/examples/rails-3-2/config/environments/production.rb +0 -67
  47. data/examples/rails-3-2/config/environments/test.rb +0 -37
  48. data/examples/rails-3-2/config/initializers/backtrace_silencers.rb +0 -7
  49. data/examples/rails-3-2/config/initializers/inflections.rb +0 -15
  50. data/examples/rails-3-2/config/initializers/mime_types.rb +0 -5
  51. data/examples/rails-3-2/config/initializers/multi_sync.rb +0 -29
  52. data/examples/rails-3-2/config/initializers/secret_token.rb +0 -7
  53. data/examples/rails-3-2/config/initializers/session_store.rb +0 -8
  54. data/examples/rails-3-2/config/initializers/wrap_parameters.rb +0 -14
  55. data/examples/rails-3-2/config/locales/en.yml +0 -5
  56. data/examples/rails-3-2/config/routes.rb +0 -58
  57. data/examples/rails-3-2/config.ru +0 -4
  58. data/examples/rails-3-2/db/seeds.rb +0 -7
  59. data/examples/rails-3-2/lib/assets/.gitkeep +0 -0
  60. data/examples/rails-3-2/lib/tasks/.gitkeep +0 -0
  61. data/examples/rails-3-2/log/.gitkeep +0 -0
  62. data/examples/rails-3-2/public/404.html +0 -26
  63. data/examples/rails-3-2/public/422.html +0 -26
  64. data/examples/rails-3-2/public/500.html +0 -25
  65. data/examples/rails-3-2/public/favicon.ico +0 -0
  66. data/examples/rails-3-2/public/index.html +0 -241
  67. data/examples/rails-3-2/public/robots.txt +0 -5
  68. data/examples/rails-3-2/script/rails +0 -6
  69. data/examples/rails-3-2/test/fixtures/.gitkeep +0 -0
  70. data/examples/rails-3-2/test/functional/.gitkeep +0 -0
  71. data/examples/rails-3-2/test/integration/.gitkeep +0 -0
  72. data/examples/rails-3-2/test/performance/browsing_test.rb +0 -12
  73. data/examples/rails-3-2/test/test_helper.rb +0 -13
  74. data/examples/rails-3-2/test/unit/.gitkeep +0 -0
  75. data/examples/rails-4-0/.gitignore +0 -16
  76. data/examples/rails-4-0/Gemfile +0 -50
  77. data/examples/rails-4-0/README.rdoc +0 -28
  78. data/examples/rails-4-0/Rakefile +0 -6
  79. data/examples/rails-4-0/app/assets/images/.keep +0 -0
  80. data/examples/rails-4-0/app/assets/javascripts/application.js +0 -16
  81. data/examples/rails-4-0/app/assets/stylesheets/application.css +0 -13
  82. data/examples/rails-4-0/app/controllers/application_controller.rb +0 -5
  83. data/examples/rails-4-0/app/controllers/concerns/.keep +0 -0
  84. data/examples/rails-4-0/app/helpers/application_helper.rb +0 -2
  85. data/examples/rails-4-0/app/mailers/.keep +0 -0
  86. data/examples/rails-4-0/app/models/.keep +0 -0
  87. data/examples/rails-4-0/app/models/concerns/.keep +0 -0
  88. data/examples/rails-4-0/app/views/layouts/application.html.erb +0 -14
  89. data/examples/rails-4-0/bin/bundle +0 -3
  90. data/examples/rails-4-0/bin/rails +0 -4
  91. data/examples/rails-4-0/bin/rake +0 -4
  92. data/examples/rails-4-0/config/application.rb +0 -24
  93. data/examples/rails-4-0/config/asset_sync.yml +0 -21
  94. data/examples/rails-4-0/config/boot.rb +0 -4
  95. data/examples/rails-4-0/config/database.yml +0 -25
  96. data/examples/rails-4-0/config/environment.rb +0 -5
  97. data/examples/rails-4-0/config/environments/development.rb +0 -29
  98. data/examples/rails-4-0/config/environments/production.rb +0 -80
  99. data/examples/rails-4-0/config/environments/test.rb +0 -36
  100. data/examples/rails-4-0/config/initializers/backtrace_silencers.rb +0 -7
  101. data/examples/rails-4-0/config/initializers/filter_parameter_logging.rb +0 -4
  102. data/examples/rails-4-0/config/initializers/inflections.rb +0 -16
  103. data/examples/rails-4-0/config/initializers/mime_types.rb +0 -5
  104. data/examples/rails-4-0/config/initializers/multi_sync.rb +0 -29
  105. data/examples/rails-4-0/config/initializers/secret_token.rb +0 -12
  106. data/examples/rails-4-0/config/initializers/session_store.rb +0 -3
  107. data/examples/rails-4-0/config/initializers/wrap_parameters.rb +0 -14
  108. data/examples/rails-4-0/config/locales/en.yml +0 -23
  109. data/examples/rails-4-0/config/routes.rb +0 -56
  110. data/examples/rails-4-0/config.ru +0 -4
  111. data/examples/rails-4-0/db/seeds.rb +0 -7
  112. data/examples/rails-4-0/lib/assets/.keep +0 -0
  113. data/examples/rails-4-0/lib/tasks/.keep +0 -0
  114. data/examples/rails-4-0/log/.keep +0 -0
  115. data/examples/rails-4-0/public/404.html +0 -58
  116. data/examples/rails-4-0/public/422.html +0 -58
  117. data/examples/rails-4-0/public/500.html +0 -57
  118. data/examples/rails-4-0/public/favicon.ico +0 -0
  119. data/examples/rails-4-0/public/robots.txt +0 -5
  120. data/examples/rails-4-0/test/controllers/.keep +0 -0
  121. data/examples/rails-4-0/test/fixtures/.keep +0 -0
  122. data/examples/rails-4-0/test/helpers/.keep +0 -0
  123. data/examples/rails-4-0/test/integration/.keep +0 -0
  124. data/examples/rails-4-0/test/mailers/.keep +0 -0
  125. data/examples/rails-4-0/test/models/.keep +0 -0
  126. data/examples/rails-4-0/test/test_helper.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15f64f882b07eb32c2ab67b3a86aebfce1c41c06
4
- data.tar.gz: f35664cd52f5bf38d99156140f0c56aa1aa09e91
3
+ metadata.gz: 580e01265e2768d6a728b4dc3b29adad42874e7b
4
+ data.tar.gz: 09575ab0fa096363ef1deeeb94a435e6dc1a5605
5
5
  SHA512:
6
- metadata.gz: 40c4bfece43530dbc54002bb4b59787bfa59f28acca1085772de7f0a22c83be9577a2b30fe47943d5f25f269b865a1c6fdc3ce55ed327143d80b7414c48cea4e
7
- data.tar.gz: 845d7cc8cd79ab528445f057c0957a4802d7dcf4296be83fe99b1697a2867018052cfc8c64f5b5d4d597f29aeb1ecb37bd71c905fa39d8b27c8018b10861884d
6
+ metadata.gz: 5c729e36efd763755ca1d1f85827fc986a7e90823ab1199c900620d8f012f2f7182ce432d91fdf3292063f3ab74f11a146690814551c074329d33c3653dc2b4f
7
+ data.tar.gz: 3968ae066b80ef8fb122c7b90aa7817ec1e7b8646091d7ff5af8e9832bcaa9da506e8dc746800664e49df5918bc1874a847e6cc1768c41c37f281a0e8677f81a
data/Gemfile CHANGED
@@ -7,6 +7,7 @@ gem 'celluloid', github: 'celluloid/celluloid'
7
7
 
8
8
  group :developement do
9
9
  gem 'rubocop', github: 'bbatsov/rubocop'
10
+ gem 'pry'
10
11
  end
11
12
 
12
13
  group :test do
data/README.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # MultiSync
2
2
 
3
- :heavy_exclamation_mark: **a WIP that is functioning but just a warning, not finished yet.** :heavy_exclamation_mark:
3
+ :heavy_exclamation_mark: **currently a functioning WIP thats not quite finished yet but its close!** :heavy_exclamation_mark:
4
4
 
5
5
  A flexible synchronisation library for your assets.
6
6
 
7
- At MultiSync's core is [Celluloid](http://celluloid.io) allowing for the synchronisation of assets to be truly parallel. Each target you define creates a pool of resources which allows for parallel execution of uploads and deletes. Meaning that when your synchronising thousands of files, you get alot more :boom: for your :dollar:.
7
+ `MultiSync` stands on the shoulders of giants. On one side is [Celluloid](http://celluloid.io) allowing for the synchronisation of assets to be highly parallel. On the other is [Fog::Storage](https://github.com/fog/fog) allowing `MulitSync` to support [various well known storage services](#storage-services).
8
8
 
9
- MultiSync tries to expose its asset synchronisation in a flexible way, allowing for it to be used in `Rails`, `Sinatra (WIP)`, `Rake (WIP)` and `Plain old ruby` as well as extensions for `Middleman (WIP)`, `Nanoc (WIP)` and others. Listed below are examples of how to get setup.
9
+ What that means is when your configuring `MultiSync` your creating various pools of workers which then distrubute the work behind synchronising your assets. Meaning that when your site has thousands of files, you get alot more :boom: for your :dollar: in less :alarm_clock:.
10
+
11
+ `MultiSync` tries to expose its asset synchronisation in a flexible way which should allow you to define how and where your assets live. Where possible though, `MultiSync` will try to provide support for [various well known libraries](#supported-libraries).
12
+
13
+ Listed below are examples of how to get setup and started.
10
14
 
11
15
  ## Installation
12
16
 
@@ -17,7 +21,7 @@ gem 'multi_sync', '~> 0.0.1'
17
21
  ```ruby
18
22
  require 'multi_sync'
19
23
 
20
- MultiSync.configuration do |config|
24
+ MultiSync.configure do |config|
21
25
  # config.verbose = false # turn on verbose logging (defaults to false)
22
26
  # config.force = false # force syncing of outdated_files (defaults to false)
23
27
  # config.run_on_build = true # when within a framework which `builds` assets, whether to sync afterwards (defaults to true)
@@ -25,79 +29,119 @@ MultiSync.configuration do |config|
25
29
  # config.delete_abandoned_files = true # when an abondoned file is found whether to remove it (defaults to true)
26
30
  # config.upload_missing_files = true # when a missing file is found whether to upload it (defaults to true)
27
31
  # config.target_pool_size = 8 # how many threads you would like to open for each target (defaults to the amount of CPU core's your machine has)
28
- # config.max_sync_attempts = 1 # how many times a file should be retried if there was an error during sync (defaults to 3)
32
+ # config.max_sync_attempts = 3 # how many times a file should be retried if there was an error during sync (defaults to 3)
29
33
  end
30
34
  ```
31
35
 
32
36
  ### Fog credentials support
33
37
 
34
- `MultiSync` supports utilising [Fog Credentials](http://fog.io/about/getting_started.html#credentials). Simply specify either a `FOG_RC` or `.fog` and we'll use it as the base for any credentials used in a target.
38
+ `MultiSync` supports utilising [Fog Credentials](http://fog.io/about/getting_started.html#credentials). Simply specify either a `FOG_RC` or `.fog` and we'll use it as the base for any `:credentials` used in a `target`.
35
39
 
36
40
  ## Features / Usage Examples
37
41
 
38
- ### AssetSync compatibility
39
-
40
- Many people use [AssetSync](https://github.com/rumblelabs/asset_sync) and for `MultiSync`'s first release compatibility with it has been built in. When within a `Rails` environment `MultiSync` will check for `asset_sync.yml` and read in its settings. You should be able to simply require `multi_sync` and try things out.
42
+ `MultiSync` in its simplist form consists of three objects. `sources`, `resources` and `targets`. A `source` defines how and where a list of files (or `resources`) can be found. A `resource` represents a file from a `source` with additional properties (such as how to compare them). A `target` is destination which `resources` can be synchronised against.
41
43
 
42
- #### Unsupported features
44
+ ### Source
43
45
 
44
- - `AssetSync`'s environment variables
45
- - `AssetSync`'s gzip_compression hack
46
+ A source takes two arguments. The first is a `name` to reference this source by and the second is a `Hash` of configuration detailed below.
46
47
 
47
- ### Rails
48
+ | Key | Type | Default | Description |
49
+ | :-- | :--- | :------ | :---------- |
50
+ | `type` | `Symbol` | `nil` | The `type` of source this is (`:local`, `:manifest`) |
51
+ | `source_dir` | `Pathname`, `String` | `nil` | The location this source should use |
52
+ | `resource_options` | `Hash` | `nil` | A hash of options for this source`s resources |
53
+ | `targets` | `Symbol`, `Array` | All targets | The target(s) this source should sync against |
54
+ | `include` | `String` ([shell glob](http://www.ruby-doc.org/core-2.1.1/Dir.html#method-c-glob)) | `**/*` | A shell globe to use for inclusion |
55
+ | `exclude` | `String` ([shell glob](http://www.ruby-doc.org/core-2.1.1/Dir.html#method-c-glob)) | `nil` | A shell globe to use for exclusion |
56
+ ___
48
57
 
49
- `MultiSync` prefers ruby backed configuration instead of `YAML` so you'll need to create an initializer `/config/initializers/multi_sync` for `MultiSync`.
58
+ ```ruby
59
+ # A source named ':build' which is ':local' and will use all files within '../build'
60
+ source :build, {
61
+ type: :local,
62
+ source_dir: '../build'
63
+ }
64
+ ```
65
+ ___
50
66
 
51
67
  ```ruby
52
- MultiSync.prepare do
53
-
54
- source :public, {
55
- type: :manifest, # load files from a Sprockets based manifest
56
- source_dir: '/path_to_your_build_folder',
57
- targets: [:assets] # an array of target names that this source should sync against
58
- }
59
-
60
- target :assets, {
61
- type: :aws, # :aws is the target's type, current options are :aws
62
- target_dir: 'your_aws_bucket',
63
- destination_dir: 'an_optional_directory_inside_your_aws_bucket',
64
- credentials: {
65
- region: 'us-east-1',
66
- aws_access_key_id: 'super_secret',
67
- aws_secret_access_key: 'super_secret'
68
- }
69
- }
68
+ # A source named ':assets' which will use a Sprockets ':manifest' within '../public/assets'
69
+ source :assets, {
70
+ type: :manifest,
71
+ source_dir: '../public/assets'
72
+ }
73
+ ```
74
+ ___
70
75
 
71
- end
76
+ ```ruby
77
+ # A source named ':video_assets' which is `:local' and will use all files
78
+ # within '../build' including only 'mp4, mpg, mov'
79
+ source :video_assets, {
80
+ type: :local,
81
+ source_dir: '../build',
82
+ include: '*.{mp4,mpg,mov}'
83
+ }
72
84
  ```
85
+ ___
73
86
 
74
- `MultiSync.prepare` simply bootstraps `MultiSync` which is then ran during `rake assets:precompile`. By having `multi_sync` included in your `Gemfile`, the rake task `rake assets:sync` will be available.
87
+ ```ruby
88
+ # A source named ':no_images' which is `:local' and will use all files
89
+ # within '../build' excluding any 'jpg, gif, png'
90
+ source :no_images, {
91
+ type: :local,
92
+ source_dir: '../build',
93
+ exclude: '*.{jpg,gif,png}'
94
+ }
95
+ ```
96
+ ___
75
97
 
76
- ### Plain Old Ruby
98
+ ```ruby
99
+ # A source named ':www' which will use a Sprockets ':manifest'
100
+ # within '../public/assets' excluding any 'jpg, gif, png' files
101
+ # and only synchronising with a target named `:www`
102
+ source :www, {
103
+ type: :manifest,
104
+ source_dir: '../public/assets',
105
+ exclude: '*.{jpg,gif,png}',
106
+ targets: :www
107
+ }
108
+ ```
109
+ ___
77
110
 
78
111
  ```ruby
79
- MultiSync.run do
80
-
81
- source :build, {
82
- type: :local, # :local is the source's type, current options are :local, :manifest
83
- source_dir: '/path_to_your_build_folder',
84
- targets: [:assets] # an array of target names that this source should sync against
85
- }
86
-
87
- target :assets, {
88
- type: :aws, # :aws is the target's type, current options are :aws
89
- target_dir: 'your_aws_bucket',
90
- destination_dir: 'an_optional_directory_inside_your_aws_bucket',
91
- credentials: {
92
- region: 'us-east-1',
93
- aws_access_key_id: 'super_secret',
94
- aws_secret_access_key: 'super_secret'
95
- }
96
- }
112
+ # A source named ':image_assets' which will use a Sprockets ':manifest'
113
+ # within '../public/assets' including only 'jpg, gif, png' files
114
+ # which sets `cache_control` and `expires` headers and
115
+ # synchronises with the target `:images`
116
+ source :image_assets, {
117
+ type: :manifest,
118
+ source_dir: '../public/assets',
119
+ include: '*.{jpg,gif,png}',
120
+ resource_options: {
121
+ cache_control: 'public, max-age=31557600',
122
+ expires: CGI.rfc1123_date(Time.now + 31557600)
123
+ },
124
+ targets: :images
125
+ }
126
+ ```
97
127
 
98
- end
128
+ ### Target
129
+
130
+ ```ruby
131
+ ...
99
132
  ```
100
133
 
134
+
135
+ ## Supported Libraries
136
+
137
+ - [Rails](https://github.com/karlfreeman/multi_sync/wiki/rails)
138
+ - Sinatra (WIP)
139
+ - Middleman (WIP)
140
+ - Jekyll (WIP)
141
+ - Nanoc (WIP)
142
+ - [POR](https://github.com/karlfreeman/multi_sync/wiki/por)
143
+ - Rake (WIP)
144
+
101
145
  ## Badges
102
146
 
103
147
  [![Gem Version](http://img.shields.io/gem/v/multi_sync.svg)][gem]
@@ -110,8 +154,8 @@ end
110
154
  Behind the scenes we're using [Fog::Storage](http://fog.io/storage) which allows us to support the most popular storage providers
111
155
 
112
156
  - [Amazon S3](http://aws.amazon.com/s3)
113
- - [Rackspace CloudFiles](http://www.rackspace.com/cloud/files)
114
- - [Google Cloud Storage](https://developers.google.com/storage)
157
+ - [Rackspace CloudFiles](http://www.rackspace.com/cloud/files) (WIP)
158
+ - [Google Cloud Storage](https://developers.google.com/storage) (WIP)
115
159
 
116
160
  ## Supported Ruby Versions
117
161
 
@@ -0,0 +1,12 @@
1
+ require 'virtus'
2
+ require 'pathname'
3
+
4
+ module MultiSync
5
+ module Attributes
6
+ class Pathname < ::Virtus::Attribute
7
+ def coerce(value)
8
+ ::Pathname.new(value)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -2,32 +2,32 @@ require 'set'
2
2
  require 'virtus'
3
3
  require 'lazily'
4
4
  require 'celluloid'
5
- require 'multi_sync/sources/local_source'
6
- require 'multi_sync/sources/manifest_source'
7
- require 'multi_sync/targets/aws_target'
8
- require 'multi_sync/targets/local_target'
5
+ %w(sources targets).each do |dir|
6
+ Dir.glob(File.expand_path("../#{dir}/**/*.rb", __FILE__), &method(:require))
7
+ end
9
8
  require 'multi_sync/mixins/pluralize_helper'
10
9
 
11
10
  module MultiSync
12
11
  class Client
13
- include Virtus
12
+ include Virtus.model
14
13
  include MultiSync::Mixins::PluralizeHelper
15
14
 
16
- attribute :supervisor
15
+ attribute :supervisor, Celluloid::SupervisionGroup
17
16
  attribute :incomplete_jobs, Set, default: Set.new
18
17
  attribute :running_jobs, Set, default: Set.new
19
18
  attribute :complete_jobs, Set, default: Set.new
20
19
  attribute :sources, Array, default: []
21
20
  attribute :sync_attempts, Integer, default: 0
22
21
  attribute :file_sync_attempts, Integer, default: 0
23
- attribute :started_at, Time
24
- attribute :finished_at, Time
22
+ attribute :started_at, Time, required: false
23
+ attribute :finished_at, Time, required: false
25
24
 
26
25
  # Initialize a new Client object
27
26
  #
28
27
  # @param options [Hash]
29
- def initialize(options = {})
28
+ def initialize(*args)
30
29
  self.supervisor = Celluloid::SupervisionGroup.run!
30
+ super
31
31
  end
32
32
 
33
33
  def add_target(name, options = {})
@@ -50,12 +50,8 @@ module MultiSync
50
50
  alias_method :source, :add_source
51
51
 
52
52
  def synchronize
53
- if sync_pointless?
54
- MultiSync.debug "Preventing synchronization as there are #{sources.length} sources to sync..."
55
- return
56
- else
57
- MultiSync.debug 'Starting synchronization...'
58
- end
53
+ MultiSync.debug 'Preventing synchronization as there are no sources found.' && return if sync_pointless?
54
+ MultiSync.debug 'Starting synchronization...'
59
55
 
60
56
  determine_sync if first_run?
61
57
  sync_attempted
@@ -69,8 +65,9 @@ module MultiSync
69
65
  running_jobs.delete_if do | job |
70
66
  begin
71
67
  completed_job = { id: job[:id], response: job[:future].value, method: job[:method] }
72
- rescue
68
+ rescue => error
73
69
  self.file_sync_attempts = file_sync_attempts + 1
70
+ MultiSync.warn error.inspect
74
71
  false
75
72
  else
76
73
  complete_jobs << completed_job
@@ -84,18 +81,23 @@ module MultiSync
84
81
  alias_method :sync, :synchronize
85
82
 
86
83
  def finalize
87
- # if finished_at
88
- # elapsed = finished_at.to_f - started_at.to_f
89
- # minutes, seconds = elapsed.divmod 60.0
90
- # kilobytes = get_total_file_size_from_complete_jobs / 1024.0
91
- # MultiSync.debug "Sync completed in #{pluralize(minutes.round, 'minute')} and #{pluralize(seconds.round, 'second')}"
92
- # MultiSync.debug "#{pluralize(complete_jobs.length, 'file')} were synchronised (#{pluralize(get_complete_deleted_jobs.length, 'deleted file')} and #{pluralize(get_complete_upload_jobs.length, 'uploaded file')}) from #{pluralize(sources.length, 'source')} to #{pluralize(supervisor.actors.length, 'target')}"
93
- # MultiSync.debug "The upload weight totalled %.#{0}f #{pluralize(kilobytes, 'KB', 'KB', false)}" % kilobytes
94
- # MultiSync.debug "#{pluralize(file_sync_attempts, 'failed request')} were detected and re-tried"
95
- # else
96
- # MultiSync.debug "Sync failed to complete with #{pluralize(incomplete_jobs.length, 'outstanding file')} to be synchronised"
97
- # MultiSync.debug "#{pluralize(complete_jobs.length, 'file')} were synchronised (#{pluralize(get_complete_deleted_jobs.length, 'deleted file')} and #{pluralize(get_complete_upload_jobs.length, 'uploaded file')}) from #{pluralize(sources.length, 'source')} to #{pluralize(supervisor.actors.length, 'target')}"
98
- # end
84
+ if finished_at
85
+ elapsed = finished_at.to_f - started_at.to_f
86
+ minutes, seconds = elapsed.divmod 60.0
87
+ bytes = get_total_file_size_from_complete_jobs
88
+ MultiSync.debug "Sync completed in #{pluralize(minutes.round, 'minute')} and #{pluralize(seconds.round, 'second')}"
89
+ MultiSync.debug "#{pluralize(complete_jobs.length, 'file')} were synchronised (#{pluralize(get_complete_deleted_jobs.length, 'deleted file')} and #{pluralize(get_complete_upload_jobs.length, 'uploaded file')}) from #{pluralize(sources.length, 'source')} to #{pluralize(supervisor.actors.length, 'target')}"
90
+ if bytes > 1024.0
91
+ kilobytes = bytes / 1024.0
92
+ MultiSync.debug "The upload weight totalled %.#{0}f #{pluralize(kilobytes, 'kilobyte', nil, false)}" % kilobytes
93
+ else
94
+ MultiSync.debug "The upload weight totalled %.#{0}f #{pluralize(bytes, 'byte', nil, false)}" % bytes
95
+ end
96
+ MultiSync.debug "#{pluralize(file_sync_attempts, 'failed request')} were detected and re-tried"
97
+ else
98
+ MultiSync.debug "Sync failed to complete with #{pluralize(incomplete_jobs.length, 'outstanding file')} to be synchronised"
99
+ MultiSync.debug "#{pluralize(complete_jobs.length, 'file')} were synchronised (#{pluralize(get_complete_deleted_jobs.length, 'deleted file')} and #{pluralize(get_complete_upload_jobs.length, 'uploaded file')}) from #{pluralize(sources.length, 'source')} to #{pluralize(supervisor.actors.length, 'target')}"
100
+ end
99
101
 
100
102
  supervisor.finalize
101
103
  end
@@ -112,12 +114,8 @@ module MultiSync
112
114
  def get_total_file_size_from_complete_jobs
113
115
  total_file_size = 0
114
116
  get_complete_upload_jobs.each do | job |
115
- # MultiSync.info job[:response]
116
- # MultiSync.info job[:response].determine_content_length
117
- if job[:response].content_length
118
- total_file_size += job[:response].content_length
119
- end
120
-
117
+ job_content_length = job[:response].content_length || job[:response].determine_content_length || 0
118
+ total_file_size += job_content_length
121
119
  end
122
120
  total_file_size
123
121
  end
@@ -164,8 +162,8 @@ module MultiSync
164
162
  abandoned_files_msg += ", however we're skipping them as :delete_abandoned_files is false" unless MultiSync.delete_abandoned_files
165
163
  MultiSync.debug abandoned_files_msg
166
164
 
167
- # remove missing_files from source_files ( as we know they are missing so don't need to check them )
168
- # remove abandoned_files from target_files ( as we know they are abandoned so don't need to check them )
165
+ # remove missing_files from source_files (as we know they are missing so don't need to check them)
166
+ # remove abandoned_files from target_files (as we know they are abandoned so don't need to check them)
169
167
  outdated_files.concat determine_outdated_files(source_files - missing_files, target_files - abandoned_files)
170
168
  MultiSync.debug "#{outdated_files.length} of the files are outdated"
171
169
 
@@ -4,7 +4,7 @@ require 'celluloid'
4
4
 
5
5
  module MultiSync
6
6
  class Configuration
7
- include Virtus
7
+ include Virtus.model
8
8
 
9
9
  attribute :verbose, Boolean, default: false
10
10
  attribute :force, Boolean, default: false
@@ -18,11 +18,9 @@ module MultiSync
18
18
  # Initialize a new Configuration object
19
19
  #
20
20
  # @param options [Hash]
21
- def initialize(options = {})
21
+ def initialize(*args)
22
22
  Celluloid.logger = MultiSync.test? ? nil : MultiSync.logger
23
- options.each_pair do |key, value|
24
- send("#{key}=", value) if attributes.keys.include?(key)
25
- end
23
+ super
26
24
  end
27
25
 
28
26
  def celluloid_cores
@@ -1,7 +1,7 @@
1
1
  module MultiSync
2
2
  module Extensions
3
3
  class Middleman
4
- MultiSync.info "Middleman -v #{::Middleman::VERSION} auto-detected"
4
+ MultiSync.debug "Middleman -v #{::Middleman::VERSION} auto-detected"
5
5
 
6
6
  class << self
7
7
  def source_dir
@@ -16,8 +16,6 @@ module MultiSync
16
16
 
17
17
  def check_and_migrate
18
18
  return unless self.asset_sync_yml_exists?
19
- MultiSync.info 'AssetSync YAML file found, migrating options...'
20
-
21
19
  MultiSync.source(:rails,
22
20
  type: :manifest,
23
21
  source_dir: MultiSync::Extensions::Rails.source_dir
@@ -37,6 +35,8 @@ module MultiSync
37
35
 
38
36
  MultiSync.delete_abandoned_files = asset_sync_yml['existing_remote_files'] == 'delete'
39
37
  MultiSync.run_on_build = asset_sync_yml['run_on_precompile']
38
+
39
+ MultiSync.info 'AssetSync YAML file found, migrating options...' if MultiSync.run_on_build
40
40
  end
41
41
  end
42
42
  end
@@ -4,7 +4,7 @@ module MultiSync
4
4
  require 'multi_sync/extensions/rails/asset_sync'
5
5
 
6
6
  class Rails
7
- MultiSync.info "Rails -v #{::Rails::VERSION::STRING} auto-detected"
7
+ MultiSync.debug "Rails -v #{::Rails::VERSION::STRING} auto-detected"
8
8
 
9
9
  class << self
10
10
  def source_dir
@@ -1,4 +1,5 @@
1
1
  require 'logger'
2
+ require 'thread'
2
3
 
3
4
  module MultiSync
4
5
  module Logging
@@ -31,9 +32,8 @@ module MultiSync
31
32
  end
32
33
 
33
34
  def log(message, level = :debug)
34
- # We're in verbose mode so disable all non-info logs
35
+ # We're not in verbose mode so disable all non-info logs
35
36
  return if !MultiSync.verbose && level != :info
36
-
37
37
  MUTEX.synchronize do
38
38
  logger.send(level, message)
39
39
  end
@@ -5,63 +5,46 @@ require 'multi_sync/mixins/log_helper'
5
5
 
6
6
  module MultiSync
7
7
  class Resource
8
- include Virtus
9
8
  include Comparable
9
+ include Virtus.model
10
10
  include MultiSync::Mixins::LogHelper
11
11
 
12
- attribute :file, File
13
12
  attribute :path_with_root, Pathname
14
13
  attribute :path_without_root, Pathname
15
14
 
16
- attribute :etag, String
17
- attribute :mtime, Time
18
- attribute :content_length, Numeric
19
- attribute :content_type, String
20
- attribute :digest, String
15
+ attribute :etag, String, default: :determine_etag, lazy: true
16
+ attribute :mtime, Time, default: :determine_mtime, lazy: true
17
+ attribute :content_length, Numeric, default: :determine_content_length, lazy: true
18
+ attribute :content_type, String, default: :determine_content_type, lazy: true
19
+ attribute :digest, String, default: ''
21
20
 
22
21
  AWS_ATTRIBUTES = [{
23
22
  name: :storage_class,
24
23
  type: String,
25
- default_value: 'STANDARD'
24
+ default: 'STANDARD'
26
25
  }, {
27
26
  name: :acl,
28
27
  type: String,
29
- default_value: 'public-read'
28
+ default: 'public-read'
30
29
  }, {
31
30
  name: :expires,
32
31
  type: String,
33
- default_value: nil
32
+ required: false
34
33
  }, {
35
34
  name: :cache_control,
36
35
  type: String,
37
- default_value: nil
36
+ required: false
38
37
  }, {
39
38
  name: :encryption,
40
39
  type: String,
41
- default_value: nil
40
+ required: false
42
41
  }]
43
42
 
44
43
  AWS_ATTRIBUTES.each do |attribute_hash|
45
- send(:attribute, attribute_hash[:name], attribute_hash[:type])
46
- end
47
-
48
- # Initialize a new Resource object
49
- #
50
- # @param options [Hash]
51
- def initialize(options = {})
52
- fail(ArgumentError, 'with_root must be present') unless options[:with_root]
53
- fail(ArgumentError, 'without_root must be present') unless options[:without_root]
54
- self.path_with_root = options.fetch(:with_root)
55
- self.path_without_root = options.fetch(:without_root)
56
- self.etag = options.fetch(:etag, determine_etag)
57
- self.mtime = options.fetch(:mtime, determine_mtime)
58
- self.content_length = options.fetch(:content_length, determine_content_length)
59
- self.content_type = options.fetch(:content_type, determine_content_type)
60
- self.digest = options.fetch(:digest, '')
61
-
62
- AWS_ATTRIBUTES.each do |attribute_hash|
63
- send("#{attribute_hash[:name]}=".to_sym, options.fetch(attribute_hash[:name], attribute_hash[:default_value]))
64
- end
44
+ def_attribute_hash = {}
45
+ def_attribute_hash[:default] = attribute_hash[:default] unless attribute_hash[:default].nil?
46
+ def_attribute_hash[:required] = attribute_hash[:required] unless attribute_hash[:required].nil?
47
+ send(:attribute, attribute_hash[:name], attribute_hash[:type], def_attribute_hash)
65
48
  end
66
49
 
67
50
  def hash
@@ -3,6 +3,7 @@ require 'multi_sync/resource'
3
3
 
4
4
  module MultiSync
5
5
  class LocalResource < Resource
6
+
6
7
  def body
7
8
  File.read(path_with_root.to_s)
8
9
  rescue
@@ -2,10 +2,7 @@ require 'multi_sync/resource'
2
2
 
3
3
  module MultiSync
4
4
  class RemoteResource < Resource
5
- def initialize(options = {})
6
- self.file = options.fetch(:file, nil)
7
- super(options)
8
- end
5
+ attribute :file
9
6
 
10
7
  def body
11
8
  file.body
@@ -1,40 +1,28 @@
1
1
  require 'virtus'
2
2
  require 'pathname'
3
3
  require 'lazily'
4
+ require 'multi_sync/attributes/pathname'
4
5
  require 'multi_sync/mixins/log_helper'
6
+ require 'multi_sync/resources/local_resource'
5
7
 
6
8
  module MultiSync
7
9
  class Source
8
- include Virtus
10
+ include Virtus.model
9
11
  include MultiSync::Mixins::LogHelper
10
12
 
11
- attribute :targets, Array, default: []
12
- attribute :source_dir, String
13
- attribute :source_options, Hash
14
- attribute :include, String
15
- attribute :exclude, String
13
+ attribute :source_dir, MultiSync::Attributes::Pathname
16
14
 
17
- # Initialize a new Source object
18
- #
19
- # @param options [Hash]
20
- def initialize(options = {})
21
- fail(ArgumentError, 'source_dir must be a present') unless options[:source_dir]
22
- targets.concat([*options.fetch(:targets, [])])
23
- self.source_dir = options.fetch(:source_dir).to_s
24
- source_dir << '/' unless source_dir.end_with?('/')
25
- self.source_dir = Pathname.new(source_dir)
26
- self.include = options.fetch(:include, '**/*')
27
- self.exclude = options.fetch(:exclude, nil)
28
- end
15
+ attribute :targets, Array, default: []
16
+ attribute :resource_options, Hash, default: {}
17
+ attribute :include, String, default: '**/*'
18
+ attribute :exclude, String, default: ''
29
19
 
30
20
  private
31
21
 
32
22
  def path_to_local_resource(path, options = {})
33
23
  pathname = Pathname.new(path)
34
- MultiSync::LocalResource.new({
35
- with_root: pathname,
36
- without_root: pathname.relative_path_from(source_dir).cleanpath
37
- }.merge(options).merge(source_options))
24
+ path_options = { path_with_root: pathname, path_without_root: pathname.relative_path_from(source_dir).cleanpath }
25
+ MultiSync::LocalResource.new(path_options.merge(options).merge(resource_options))
38
26
  end
39
27
  end
40
28
  end
@@ -22,7 +22,7 @@ module MultiSync
22
22
  # making sure to skip any that do not match the include/exclude patterns
23
23
  manifest_hash.lazily.each { |key, value|
24
24
  path = source_dir + key
25
- next if !path.fnmatch?(include.to_s) or path.fnmatch?(exclude.to_s || '')
25
+ next if !path.fnmatch?(include.to_s) || path.fnmatch?(exclude.to_s || '')
26
26
  file = path_to_local_resource(path, mtime: value['mtime'], digest: value['digest'], content_length: value['size'])
27
27
  files << file
28
28
  }
@@ -33,7 +33,7 @@ module MultiSync
33
33
  private
34
34
 
35
35
  def locate_manifest(dir)
36
- Dir.glob(dir.to_s + 'manifest*.{json,yaml,yml}').max { |f| File.ctime(f) }
36
+ Dir.glob(dir + 'manifest*.{json,yaml,yml}').max { |f| File.ctime(f) }
37
37
  end
38
38
 
39
39
  def parse_manifest(manifest_path)