multi_sync 0.0.1 → 0.0.2

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 (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)