asset_sync 2.6.0 → 2.12.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51ba6147cc39550e51d1eb1bc98420b53b0ca14fe96d90d34e7de36c8a9511b5
4
- data.tar.gz: 701e692e95ed4c8ad41a8a5d14e7356ee8c013221e675d7396a8b07816f7a226
3
+ metadata.gz: 1fbb82cb5023ce3d6e1f088aa62fa32718f8e743977c31b773e3f2a324a0a397
4
+ data.tar.gz: 504e104e3dfe839bb19b0794a7af8f4bb932fd7f7500347374c14b8862e5ae43
5
5
  SHA512:
6
- metadata.gz: f03b66ce2292d21a3e1a514307a3bf737c0ea856b46ee6e36aef40b93a2604b544e708f97f7b1e9fbfa81483545929cfb9e7714c4bf4172e6311e22f4cc7ffe2
7
- data.tar.gz: e228c684a414b1a9859ea8df91f76b1b6c5ad4234863b46307dd76b705aa8a71f18cba5ab8c959a33ac089ca9d5c355dc26391bb16441a8c802fc0f44f97c087
6
+ metadata.gz: 2945ac417bfcc350068b1c9ce3c59781f0cd7bb50bd606919803e55602a81b06d6d6fed24de0c7e62ca695a83901481d296a9ae20031b5ab1e9edfc61a69823a
7
+ data.tar.gz: b96f8274e66d1d7ec2ab182fdcb3833edd7c24b9dc9d9fd9d038a3db8608dc1102a23b2998ec5c9749e89fe6d12212488dc9733ec927328fcc0f388bf84df357
@@ -5,21 +5,24 @@ language: ruby
5
5
  cache:
6
6
  bundler: true
7
7
  rvm:
8
- - 2.2
9
8
  - 2.3
10
9
  - 2.4
11
10
  - 2.5
12
11
  - 2.6
12
+ - 2.7
13
13
  - ruby-head
14
14
  - jruby
15
15
  - jruby-head
16
16
  gemfile:
17
- - gemfiles/rails_4_2.gemfile
18
17
  - gemfiles/rails_5_0.gemfile
19
18
  - gemfiles/rails_5_1.gemfile
20
19
  - gemfiles/rails_5_2.gemfile
20
+ - gemfiles/rails_6_0.gemfile
21
21
  before_install:
22
- - gem install bundler
22
+ # Cannot use bundler 2.x due to dependency (mainly rails 4.2)
23
+ # Solution from https://github.com/rails/rails/blob/4-2-stable/.travis.yml
24
+ - "travis_retry gem update --system --no-doc || travis_retry gem update --system --no-rdoc --no-ri"
25
+ - "travis_retry gem install bundler -v '<2'"
23
26
  env:
24
27
  global:
25
28
  - FOG_DIRECTORY=asset-sync-travis
@@ -29,9 +32,13 @@ env:
29
32
  matrix:
30
33
  fast_finish: true
31
34
  allow_failures:
32
- - rvm: 2.6
33
35
  - rvm: ruby-head
34
36
  - rvm: jruby-head
37
+ exclude:
38
+ - rvm: 2.3
39
+ gemfile: gemfiles/rails_6_0.gemfile
40
+ - rvm: 2.4
41
+ gemfile: gemfiles/rails_6_0.gemfile
35
42
  notifications:
36
43
  webhooks:
37
44
  urls:
data/Appraisals CHANGED
@@ -1,8 +1,4 @@
1
1
 
2
- appraise "rails_4_2" do
3
- gem "rails", "~> 4.2.0"
4
- end
5
-
6
2
  appraise "rails_5_0" do
7
3
  gem "rails", "~> 5.0.0"
8
4
  end
@@ -14,3 +10,7 @@ end
14
10
  appraise "rails_5_2" do
15
11
  gem "rails", "~> 5.2.0"
16
12
  end
13
+
14
+ appraise "rails_6_0" do
15
+ gem "rails", "~> 6.0.0"
16
+ end
@@ -18,6 +18,96 @@ This project adheres to [Semantic Versioning](http://semver.org/).
18
18
  - Nothing
19
19
 
20
20
 
21
+ ## [2.12.1] - 2020-06-17
22
+
23
+ ### Fixed
24
+
25
+ - Fix initializer template in generator
26
+ (https://github.com/AssetSync/asset_sync/pull/404)
27
+
28
+
29
+ ## [2.12.0] - 2020-06-11
30
+
31
+ ### Added
32
+
33
+ - Add option `aws_session_token` to support AWS Temporary Security Credentials
34
+ (https://github.com/AssetSync/asset_sync/pull/403)
35
+
36
+
37
+ ## [2.11.0] - 2020-03-13
38
+
39
+ ### Added
40
+
41
+ - Add option `remote_file_list_cache_file_path` to skip scanning remote
42
+ (https://github.com/AssetSync/asset_sync/pull/400)
43
+
44
+
45
+ ## [2.10.0] - 2020-02-26
46
+
47
+ ### Added
48
+
49
+ - Add option `concurrent_uploads_max_threads` to limit number of threads for uploading files
50
+ (https://github.com/AssetSync/asset_sync/pull/398)
51
+
52
+
53
+ ## [2.9.1] - 2020-02-20
54
+
55
+ ### Fixed
56
+
57
+ - Fix uploading of sprockets manifest file
58
+ (https://github.com/AssetSync/asset_sync/pull/397)
59
+
60
+
61
+ ## [2.9.0] - 2020-01-15
62
+
63
+ ### Added
64
+
65
+ - Add option `concurrent_uploads` to improve speed of uploading
66
+ (https://github.com/AssetSync/asset_sync/pull/393)
67
+
68
+
69
+ ## [2.8.2] - 2019-12-27
70
+
71
+ ### Changed
72
+
73
+ - Use `delete_multiple_objects` when storage is `aws`
74
+ (https://github.com/AssetSync/asset_sync/pull/392)
75
+
76
+
77
+ ## [2.8.1] - 2019-07-25
78
+
79
+ ### Changed
80
+
81
+ - Removed `rubyforge_project` from gemspec
82
+ (https://github.com/AssetSync/asset_sync/pull/386)
83
+
84
+ ### Fixed
85
+
86
+ - Fixed when `fog_public` set to `false`, file were still set to be public
87
+ (https://github.com/AssetSync/asset_sync/pull/387)
88
+
89
+
90
+ ## [2.8.0] - 2019-06-17
91
+
92
+ ### Added
93
+
94
+ - Add option `fog_port`
95
+ (https://github.com/AssetSync/asset_sync/pull/385)
96
+
97
+
98
+ ## [2.7.0] - 2019-03-15
99
+
100
+ ### Added
101
+
102
+ - Adds JSON API support when using Google Storage
103
+ (https://github.com/AssetSync/asset_sync/pull/381)
104
+
105
+ ### Changed
106
+
107
+ - Update `AssetSync::MultiMime.lookup` to always return strings (kind of internal change)
108
+ (https://github.com/AssetSync/asset_sync/pull/380)
109
+
110
+
21
111
  ## [2.6.0] - 2018-12-07
22
112
 
23
113
  ### Added
@@ -105,7 +195,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
105
195
 
106
196
  - Only support mime-type >= 2.99,
107
197
  which is released at the end of 2015
108
- - Only support mactivemodel >= 4.1,
198
+ - Only support activemodel >= 4.1,
109
199
  which is released in 2014
110
200
 
111
201
 
@@ -888,7 +978,17 @@ Changes:
888
978
  * Merge branch 'sinatra'
889
979
 
890
980
 
891
- [Unreleased]: https://github.com/AssetSync/asset_sync/compare/v2.6.0...HEAD
981
+ [Unreleased]: https://github.com/AssetSync/asset_sync/compare/v2.12.1...HEAD
982
+ [2.12.1]: https://github.com/AssetSync/asset_sync/compare/v2.12.0...v2.12.1
983
+ [2.12.0]: https://github.com/AssetSync/asset_sync/compare/v2.11.0...v2.12.0
984
+ [2.11.0]: https://github.com/AssetSync/asset_sync/compare/v2.10.0...v2.11.0
985
+ [2.10.0]: https://github.com/AssetSync/asset_sync/compare/v2.9.1...v2.10.0
986
+ [2.9.1]: https://github.com/AssetSync/asset_sync/compare/v2.9.0...v2.9.1
987
+ [2.9.0]: https://github.com/AssetSync/asset_sync/compare/v2.8.2...v2.9.0
988
+ [2.8.2]: https://github.com/AssetSync/asset_sync/compare/v2.8.1...v2.8.2
989
+ [2.8.1]: https://github.com/AssetSync/asset_sync/compare/v2.8.0...v2.8.1
990
+ [2.8.0]: https://github.com/AssetSync/asset_sync/compare/v2.7.0...v2.8.0
991
+ [2.7.0]: https://github.com/AssetSync/asset_sync/compare/v2.6.0...v2.7.0
892
992
  [2.6.0]: https://github.com/AssetSync/asset_sync/compare/v2.5.0...v2.6.0
893
993
  [2.5.0]: https://github.com/AssetSync/asset_sync/compare/v2.4.0...v2.5.0
894
994
  [2.4.0]: https://github.com/AssetSync/asset_sync/compare/v2.3.0...v2.4.0
data/README.md CHANGED
@@ -103,10 +103,10 @@ On **non default S3 bucket region**: If your bucket is set to a region that is n
103
103
 
104
104
  If you wish to have your assets sync to a sub-folder of your bucket instead of into the root add the following to your ``production.rb`` file
105
105
 
106
- ```ruby
106
+ ``` ruby
107
107
  # store assets in a 'folder' instead of bucket root
108
108
  config.assets.prefix = "/production/assets"
109
- ````
109
+ ```
110
110
 
111
111
  Also, ensure the following are defined (in production.rb or application.rb)
112
112
 
@@ -170,7 +170,17 @@ heroku config:add FOG_DIRECTORY=xxxx
170
170
  heroku config:add FOG_PROVIDER=Rackspace
171
171
  ```
172
172
 
173
- Google Storage Cloud configuration is supported as well
173
+ Google Storage Cloud configuration is supported as well. The preferred option is using the [GCS JSON API](https://github.com/fog/fog-google#storage) which requires that you create an appropriate service account, generate the signatures and make them accessible to asset sync at the prescribed location
174
+
175
+ ```bash
176
+ heroku config:add FOG_PROVIDER=Google
177
+ heroku config:add GOOGLE_PROJECT=xxxx
178
+ heroku config:add GOOGLE_JSON_KEY_LOCATION=xxxx
179
+ heroku config:add FOG_DIRECTORY=xxxx
180
+ ```
181
+
182
+ If using the S3 API the following config is required
183
+
174
184
  ``` bash
175
185
  heroku config:add FOG_PROVIDER=Google
176
186
  heroku config:add GOOGLE_STORAGE_ACCESS_KEY_ID=xxxx
@@ -198,6 +208,7 @@ AssetSync.configure do |config|
198
208
  config.fog_directory = ENV['FOG_DIRECTORY']
199
209
  config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
200
210
  config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
211
+ config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.key?('AWS_SESSION_TOKEN')
201
212
 
202
213
  # Don't delete files from the store
203
214
  # config.existing_remote_files = 'keep'
@@ -216,6 +227,9 @@ AssetSync.configure do |config|
216
227
  # Change host option in fog (only if you need to)
217
228
  # config.fog_host = 's3.amazonaws.com'
218
229
  #
230
+ # Change port option in fog (only if you need to)
231
+ # config.fog_port = "9000"
232
+ #
219
233
  # Use http instead of https.
220
234
  # config.fog_scheme = 'http'
221
235
  #
@@ -229,6 +243,15 @@ AssetSync.configure do |config|
229
243
  # Upload the manifest file also.
230
244
  # config.include_manifest = false
231
245
  #
246
+ # Upload files concurrently
247
+ # config.concurrent_uploads = false
248
+ #
249
+ # Number of threads when concurrent_uploads is enabled
250
+ # config.concurrent_uploads_max_threads = 10
251
+ #
252
+ # Path to cache file to skip scanning remote
253
+ # config.remote_file_list_cache_file_path = './.asset_sync_remote_file_list_cache.json'
254
+ #
232
255
  # Fail silently. Useful for environments such as Heroku
233
256
  # config.fail_silently = true
234
257
  #
@@ -325,6 +348,9 @@ AssetSync.config.gzip_compression == ENV['ASSET_SYNC_GZIP_COMPRESSION']
325
348
  * **gzip\_compression**: (`true, false`) when enabled, will automatically replace files that have a gzip compressed equivalent with the compressed version. **default:** `'false'`
326
349
  * **manifest**: (`true, false`) when enabled, will use the `manifest.yml` generated by Rails to get the list of local files to upload. **experimental**. **default:** `'false'`
327
350
  * **include_manifest**: (`true, false`) when enabled, will upload the `manifest.yml` generated by Rails. **default:** `'false'`
351
+ * **concurrent_uploads**: (`true, false`) when enabled, will upload the files in different Threads, this greatly improves the upload speed. **default:** `'false'`
352
+ * **concurrent_uploads_max_threads**: when concurrent_uploads is enabled, this determines the number of threads that will be created. **default:** `10`
353
+ * **remote_file_list_cache_file_path**: if present, use this path to cache remote file list to skip scanning remote **default:** `nil`
328
354
  * **enabled**: (`true, false`) when false, will disable asset sync. **default:** `'true'` (enabled)
329
355
  * **ignored\_files**: an array of files to ignore e.g. `['ignore_me.js', %r(ignore_some/\d{32}\.css)]` Useful if there are some files that are created dynamically on the server and you don't want to upload on deploy **default**: `[]`
330
356
  * **cache\_asset\_regexps**: an array of files to add cache headers e.g. `['cache_me.js', %r(cache_some\.\d{8}\.css)]` Useful if there are some files that are added to sprockets assets list and need to be set as 'Cacheable' on uploaded server. Only rails compiled regexp is matched internally **default**: `[]`
@@ -385,6 +411,14 @@ The blocks are run when local files are being scanned and uploaded
385
411
  * **rackspace\_api\_key**: your Rackspace API Key.
386
412
 
387
413
  #### Google Storage
414
+
415
+ When using the JSON API
416
+
417
+ - **google\_project**: your Google Cloud Project name where the Google Cloud Storage bucket resides
418
+ - **google\_json\_key\_location**: path to the location of the service account key. The service account key must be a JSON type key
419
+
420
+ When using the S3 API
421
+
388
422
  * **google\_storage\_access\_key\_id**: your Google Storage access key
389
423
  * **google\_storage\_secret\_access\_key**: your Google Storage access secret
390
424
 
@@ -515,6 +549,10 @@ AssetSync.configure do |config|
515
549
  config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
516
550
  config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
517
551
  config.prefix = 'assets'
552
+ # Can be a `Pathname` or `String`
553
+ # Will be converted into an `Pathname`
554
+ # If relative, will be converted into an absolute path
555
+ # via `::Rails.root` or `::Dir.pwd`
518
556
  config.public_path = Pathname('./public')
519
557
  end
520
558
  ```
@@ -584,7 +622,7 @@ Make sure you have a .env file with these details:-
584
622
  AWS_SECRET_ACCESS_KEY=<yoursecretkey>
585
623
  FOG_DIRECTORY=<yourbucket>
586
624
  FOG_REGION=<youbucketregion>
587
-
625
+
588
626
  # for AzureRM provider
589
627
  AZURE_STORAGE_ACCOUNT_NAME=<youraccountname>
590
628
  AZURE_STORAGE_ACCESS_KEY=<youraccesskey>
@@ -15,8 +15,6 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.license = 'MIT'
17
17
 
18
- s.rubyforge_project = "asset_sync"
19
-
20
18
  s.add_dependency("fog-core")
21
19
  s.add_dependency('unf')
22
20
  s.add_dependency('activemodel', ">= 4.1.0")
@@ -5,6 +5,6 @@ source "https://rubygems.org"
5
5
  gem "rcov", platforms: :mri_18, group: [:development, :test]
6
6
  gem "simplecov", platforms: [:jruby, :mri_19, :ruby_19, :mri_20, :rbx], group: [:development, :test], require: false
7
7
  gem "jruby-openssl", platform: :jruby
8
- gem "rails", "~> 4.2.0"
8
+ gem "rails", "~> 6.0.0"
9
9
 
10
10
  gemspec path: "../"
@@ -26,7 +26,9 @@ module AssetSync
26
26
  attr_accessor :cdn_distribution_id
27
27
  attr_accessor :cache_asset_regexps
28
28
  attr_accessor :include_manifest
29
- attr_writer :public_path
29
+ attr_accessor :concurrent_uploads
30
+ attr_accessor :concurrent_uploads_max_threads
31
+ attr_accessor :remote_file_list_cache_file_path
30
32
 
31
33
  # FOG configuration
32
34
  attr_accessor :fog_provider # Currently Supported ['AWS', 'Rackspace']
@@ -35,8 +37,9 @@ module AssetSync
35
37
  attr_reader :fog_public # e.g. true, false, "default"
36
38
 
37
39
  # Amazon AWS
38
- attr_accessor :aws_access_key_id, :aws_secret_access_key, :aws_reduced_redundancy, :aws_iam_roles, :aws_signature_version
40
+ attr_accessor :aws_access_key_id, :aws_secret_access_key, :aws_session_token, :aws_reduced_redundancy, :aws_iam_roles, :aws_signature_version
39
41
  attr_accessor :fog_host # e.g. 's3.amazonaws.com'
42
+ attr_accessor :fog_port # e.g. '9000'
40
43
  attr_accessor :fog_path_style # e.g. true
41
44
  attr_accessor :fog_scheme # e.g. 'http'
42
45
 
@@ -44,7 +47,9 @@ module AssetSync
44
47
  attr_accessor :rackspace_username, :rackspace_api_key, :rackspace_auth_url
45
48
 
46
49
  # Google Storage
47
- attr_accessor :google_storage_secret_access_key, :google_storage_access_key_id
50
+ attr_accessor :google_storage_secret_access_key, :google_storage_access_key_id # when using S3 interop
51
+ attr_accessor :google_json_key_location # when using service accounts
52
+ attr_accessor :google_project # when using service accounts
48
53
 
49
54
  # Azure Blob with Fog::AzureRM
50
55
  attr_accessor :azure_storage_account_name
@@ -59,8 +64,11 @@ module AssetSync
59
64
  validates :aws_secret_access_key, :presence => true, :if => proc {aws? && !aws_iam?}
60
65
  validates :rackspace_username, :presence => true, :if => :rackspace?
61
66
  validates :rackspace_api_key, :presence => true, :if => :rackspace?
62
- validates :google_storage_secret_access_key, :presence => true, :if => :google?
63
- validates :google_storage_access_key_id, :presence => true, :if => :google?
67
+ validates :google_storage_secret_access_key, :presence => true, :if => :google_interop?
68
+ validates :google_storage_access_key_id, :presence => true, :if => :google_interop?
69
+ validates :google_json_key_location, :presence => true, :if => :google_service_account?
70
+ validates :google_project, :presence => true, :if => :google_service_account?
71
+ validates :concurrent_uploads, :inclusion => { :in => [true, false] }
64
72
 
65
73
  def initialize
66
74
  self.fog_region = nil
@@ -79,6 +87,9 @@ module AssetSync
79
87
  self.invalidate = []
80
88
  self.cache_asset_regexps = []
81
89
  self.include_manifest = false
90
+ self.concurrent_uploads = false
91
+ self.concurrent_uploads_max_threads = 10
92
+ self.remote_file_list_cache_file_path = nil
82
93
  @additional_local_file_paths_procs = []
83
94
 
84
95
  load_yml! if defined?(::Rails) && yml_exists?
@@ -130,6 +141,14 @@ module AssetSync
130
141
  fog_provider =~ /google/i
131
142
  end
132
143
 
144
+ def google_interop?
145
+ google? && google_json_key_location.nil?
146
+ end
147
+
148
+ def google_service_account?
149
+ google? && google_json_key_location
150
+ end
151
+
133
152
  def azure_rm?
134
153
  fog_provider =~ /azurerm/i
135
154
  end
@@ -159,10 +178,24 @@ module AssetSync
159
178
  @public_path || ::Rails.public_path
160
179
  end
161
180
 
181
+ def public_path=(path)
182
+ # Generate absolute path even when relative path passed in
183
+ # Required for generating relative sprockets manifest path
184
+ pathname = Pathname(path)
185
+ @public_path = if pathname.absolute?
186
+ pathname
187
+ elsif defined?(::Rails.root)
188
+ ::Rails.root.join(pathname)
189
+ else
190
+ Pathname(::Dir.pwd).join(pathname)
191
+ end
192
+ end
193
+
162
194
  def load_yml!
163
195
  self.enabled = yml["enabled"] if yml.has_key?('enabled')
164
196
  self.fog_provider = yml["fog_provider"]
165
197
  self.fog_host = yml["fog_host"]
198
+ self.fog_port = yml["fog_port"]
166
199
  self.fog_directory = yml["fog_directory"]
167
200
  self.fog_region = yml["fog_region"]
168
201
  self.fog_public = yml["fog_public"] if yml.has_key?("fog_public")
@@ -170,14 +203,17 @@ module AssetSync
170
203
  self.fog_scheme = yml["fog_scheme"]
171
204
  self.aws_access_key_id = yml["aws_access_key_id"]
172
205
  self.aws_secret_access_key = yml["aws_secret_access_key"]
206
+ self.aws_session_token = yml["aws_session_token"] if yml.has_key?("aws_session_token")
173
207
  self.aws_reduced_redundancy = yml["aws_reduced_redundancy"]
174
208
  self.aws_iam_roles = yml["aws_iam_roles"]
175
209
  self.aws_signature_version = yml["aws_signature_version"]
176
210
  self.rackspace_username = yml["rackspace_username"]
177
211
  self.rackspace_auth_url = yml["rackspace_auth_url"] if yml.has_key?("rackspace_auth_url")
178
212
  self.rackspace_api_key = yml["rackspace_api_key"]
179
- self.google_storage_secret_access_key = yml["google_storage_secret_access_key"]
180
- self.google_storage_access_key_id = yml["google_storage_access_key_id"]
213
+ self.google_json_key_location = yml["google_json_key_location"] if yml.has_key?("google_json_key_location")
214
+ self.google_project = yml["google_project"] if yml.has_key?("google_project")
215
+ self.google_storage_secret_access_key = yml["google_storage_secret_access_key"] if yml.has_key?("google_storage_secret_access_key")
216
+ self.google_storage_access_key_id = yml["google_storage_access_key_id"] if yml.has_key?("google_storage_access_key_id")
181
217
  self.existing_remote_files = yml["existing_remote_files"] if yml.has_key?("existing_remote_files")
182
218
  self.gzip_compression = yml["gzip_compression"] if yml.has_key?("gzip_compression")
183
219
  self.manifest = yml["manifest"] if yml.has_key?("manifest")
@@ -190,6 +226,9 @@ module AssetSync
190
226
  self.cdn_distribution_id = yml['cdn_distribution_id'] if yml.has_key?("cdn_distribution_id")
191
227
  self.cache_asset_regexps = yml['cache_asset_regexps'] if yml.has_key?("cache_asset_regexps")
192
228
  self.include_manifest = yml['include_manifest'] if yml.has_key?("include_manifest")
229
+ self.concurrent_uploads = yml['concurrent_uploads'] if yml.has_key?('concurrent_uploads')
230
+ self.concurrent_uploads_max_threads = yml['concurrent_uploads_max_threads'] if yml.has_key?('concurrent_uploads_max_threads')
231
+ self.remote_file_list_cache_file_path = yml['remote_file_list_cache_file_path'] if yml.has_key?('remote_file_list_cache_file_path')
193
232
 
194
233
  self.azure_storage_account_name = yml['azure_storage_account_name'] if yml.has_key?("azure_storage_account_name")
195
234
  self.azure_storage_access_key = yml['azure_storage_access_key'] if yml.has_key?("azure_storage_access_key")
@@ -222,8 +261,10 @@ module AssetSync
222
261
  :aws_access_key_id => aws_access_key_id,
223
262
  :aws_secret_access_key => aws_secret_access_key
224
263
  })
264
+ options.merge!({:aws_session_token => aws_session_token}) if aws_session_token
225
265
  end
226
266
  options.merge!({:host => fog_host}) if fog_host
267
+ options.merge!({:port => fog_port}) if fog_port
227
268
  options.merge!({:scheme => fog_scheme}) if fog_scheme
228
269
  options.merge!({:aws_signature_version => aws_signature_version}) if aws_signature_version
229
270
  options.merge!({:path_style => fog_path_style}) if fog_path_style
@@ -236,10 +277,14 @@ module AssetSync
236
277
  options.merge!({ :rackspace_region => fog_region }) if fog_region
237
278
  options.merge!({ :rackspace_auth_url => rackspace_auth_url }) if rackspace_auth_url
238
279
  elsif google?
239
- options.merge!({
240
- :google_storage_secret_access_key => google_storage_secret_access_key,
241
- :google_storage_access_key_id => google_storage_access_key_id
242
- })
280
+ if google_json_key_location
281
+ options.merge!({:google_json_key_location => google_json_key_location, :google_project => google_project})
282
+ else
283
+ options.merge!({
284
+ :google_storage_secret_access_key => google_storage_secret_access_key,
285
+ :google_storage_access_key_id => google_storage_access_key_id
286
+ })
287
+ end
243
288
  options.merge!({:region => fog_region}) if fog_region
244
289
  elsif azure_rm?
245
290
  require 'fog/azurerm'
@@ -340,7 +385,7 @@ module AssetSync
340
385
  end
341
386
 
342
387
  def to_bool
343
- !@value.nil?
388
+ !!@value
344
389
  end
345
390
  end
346
391
  end
@@ -17,11 +17,13 @@ module AssetSync
17
17
  config.fog_directory = ENV['FOG_DIRECTORY'] if ENV.has_key?('FOG_DIRECTORY')
18
18
  config.fog_region = ENV['FOG_REGION'] if ENV.has_key?('FOG_REGION')
19
19
  config.fog_host = ENV['FOG_HOST'] if ENV.has_key?('FOG_HOST')
20
+ config.fog_port = ENV['FOG_PORT'] if ENV.has_key?('FOG_PORT')
20
21
  config.fog_scheme = ENV['FOG_SCHEMA'] if ENV.has_key?('FOG_SCHEMA')
21
22
  config.fog_path_style = ENV['FOG_PATH_STYLE'] if ENV.has_key?('FOG_PATH_STYLE')
22
23
 
23
24
  config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID'] if ENV.has_key?('AWS_ACCESS_KEY_ID')
24
25
  config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] if ENV.has_key?('AWS_SECRET_ACCESS_KEY')
26
+ config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.has_key?('AWS_SESSION_TOKEN')
25
27
  config.aws_signature_version = ENV['AWS_SIGNATURE_VERSION'] if ENV.has_key?('AWS_SIGNATURE_VERSION')
26
28
  config.aws_reduced_redundancy = ENV['AWS_REDUCED_REDUNDANCY'] == true if ENV.has_key?('AWS_REDUCED_REDUNDANCY')
27
29
 
@@ -41,6 +43,8 @@ module AssetSync
41
43
  config.gzip_compression = (ENV['ASSET_SYNC_GZIP_COMPRESSION'] == 'true') if ENV.has_key?('ASSET_SYNC_GZIP_COMPRESSION')
42
44
  config.manifest = (ENV['ASSET_SYNC_MANIFEST'] == 'true') if ENV.has_key?('ASSET_SYNC_MANIFEST')
43
45
  config.include_manifest = (ENV['ASSET_SYNC_INCLUDE_MANIFEST'] == 'true') if ENV.has_key?('ASSET_SYNC_INCLUDE_MANIFEST')
46
+ config.concurrent_uploads = (ENV['ASSET_SYNC_CONCURRENT_UPLOADS'] == 'true') if ENV.has_key?('ASSET_SYNC_CONCURRENT_UPLOADS')
47
+ config.remote_file_list_cache_file_path = ENV['ASSET_SYNC_REMOTE_FILE_LIST_CACHE_FILE_PATH'] if ENV.has_key?('ASSET_SYNC_REMOTE_FILE_LIST_CACHE_FILE_PATH')
44
48
  end
45
49
 
46
50
  config.prefix = ENV['ASSET_SYNC_PREFIX'] if ENV.has_key?('ASSET_SYNC_PREFIX')
@@ -11,9 +11,9 @@ module AssetSync
11
11
  end
12
12
 
13
13
  if defined?(::MIME::Types)
14
- ::MIME::Types.type_for(ext).first
14
+ ::MIME::Types.type_for(ext).first.to_s
15
15
  elsif defined?(::Mime::Type)
16
- ::Mime::Type.lookup_by_extension(ext)
16
+ ::Mime::Type.lookup_by_extension(ext).to_s
17
17
  elsif defined?(::Rack::Mime)
18
18
  ext_with_dot = ".#{ext}"
19
19
  ::Rack::Mime.mime_type(ext_with_dot)
@@ -37,6 +37,10 @@ module AssetSync
37
37
  self.config.public_path
38
38
  end
39
39
 
40
+ def remote_file_list_cache_file_path
41
+ self.config.remote_file_list_cache_file_path
42
+ end
43
+
40
44
  def ignored_files
41
45
  expand_file_names(self.config.ignored_files)
42
46
  end
@@ -58,6 +62,32 @@ module AssetSync
58
62
  (get_local_files + config.additional_local_file_paths).uniq
59
63
  end
60
64
 
65
+ def remote_files
66
+ return [] if ignore_existing_remote_files?
67
+ return @remote_files if @remote_files
68
+
69
+ if remote_file_list_cache_file_path && File.file?(remote_file_list_cache_file_path)
70
+ begin
71
+ content = File.read(remote_file_list_cache_file_path)
72
+ return @remote_files = JSON.parse(content)
73
+ rescue JSON::ParserError
74
+ warn "Failed to parse #{remote_file_list_cache_file_path} as json"
75
+ end
76
+ end
77
+
78
+ @remote_files = get_remote_files
79
+ end
80
+
81
+ def update_remote_file_list_cache(local_files_to_upload)
82
+ return unless remote_file_list_cache_file_path
83
+ return if ignore_existing_remote_files?
84
+
85
+ File.open(self.remote_file_list_cache_file_path, 'w') do |file|
86
+ uploaded = local_files_to_upload + remote_files
87
+ file.write(uploaded.to_json)
88
+ end
89
+ end
90
+
61
91
  def always_upload_files
62
92
  expand_file_names(self.config.always_upload) + get_manifest_path
63
93
  end
@@ -132,9 +162,15 @@ module AssetSync
132
162
  from_remote_files_to_delete = remote_files - local_files - ignored_files - always_upload_files
133
163
 
134
164
  log "Flagging #{from_remote_files_to_delete.size} file(s) for deletion"
135
- # Delete unneeded remote files
136
- bucket.files.each do |f|
137
- delete_file(f, from_remote_files_to_delete)
165
+ # Delete unneeded remote files, if we are on aws delete in bulk else use sequential delete
166
+ if self.config.aws? && connection.respond_to?(:delete_multiple_objects)
167
+ from_remote_files_to_delete.each_slice(500) do |slice|
168
+ connection.delete_multiple_objects(config.fog_directory, slice)
169
+ end
170
+ else
171
+ bucket.files.each do |f|
172
+ delete_file(f, from_remote_files_to_delete)
173
+ end
138
174
  end
139
175
  end
140
176
 
@@ -231,28 +267,38 @@ module AssetSync
231
267
  })
232
268
  end
233
269
 
234
- if config.azure_rm?
235
- # converts content_type from MIME::Type to String.
236
- # because Azure::Storage (called from Fog::AzureRM) expects content_type as a String like "application/json; charset=utf-8"
237
- file[:content_type] = file[:content_type].content_type if file[:content_type].is_a?(::MIME::Type)
238
- end
239
-
240
270
  bucket.files.create( file ) unless ignore
241
271
  file_handle.close
242
272
  gzip_file_handle.close if gzip_file_handle
243
273
  end
244
274
 
245
275
  def upload_files
246
- # get a fresh list of remote files
247
- remote_files = ignore_existing_remote_files? ? [] : get_remote_files
248
276
  # fixes: https://github.com/rumblelabs/asset_sync/issues/19
249
277
  local_files_to_upload = local_files - ignored_files - remote_files + always_upload_files
250
278
  local_files_to_upload = (local_files_to_upload + get_non_fingerprinted(local_files_to_upload)).uniq
251
-
252
- # Upload new files
253
- local_files_to_upload.each do |f|
254
- next unless File.file? "#{path}/#{f}" # Only files.
255
- upload_file f
279
+ # Only files.
280
+ local_files_to_upload = local_files_to_upload.select { |f| File.file? "#{path}/#{f}" }
281
+
282
+ if self.config.concurrent_uploads
283
+ jobs = Queue.new
284
+ local_files_to_upload.each { |f| jobs.push(f) }
285
+ jobs.close
286
+
287
+ num_threads = [self.config.concurrent_uploads_max_threads, local_files_to_upload.length].min
288
+ # Upload new files
289
+ workers = Array.new(num_threads) do
290
+ Thread.new do
291
+ while f = jobs.pop
292
+ upload_file(f)
293
+ end
294
+ end
295
+ end
296
+ workers.map(&:join)
297
+ else
298
+ # Upload new files
299
+ local_files_to_upload.each do |f|
300
+ upload_file f
301
+ end
256
302
  end
257
303
 
258
304
  if self.config.cdn_distribution_id && files_to_invalidate.any?
@@ -261,6 +307,8 @@ module AssetSync
261
307
  data = cdn.post_invalidation(self.config.cdn_distribution_id, files_to_invalidate)
262
308
  log "Invalidation id: #{data.body["Id"]}"
263
309
  end
310
+
311
+ update_remote_file_list_cache(local_files_to_upload)
264
312
  end
265
313
 
266
314
  def sync
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AssetSync
4
- VERSION = "2.6.0".freeze
4
+ VERSION = "2.12.1"
5
5
  end
@@ -35,6 +35,10 @@ module AssetSync
35
35
  "<%= ENV['AWS_SECRET_ACCESS_KEY'] %>"
36
36
  end
37
37
 
38
+ def aws_session_token
39
+ "<%= ENV['AWS_SESSION_TOKEN'] %>"
40
+ end
41
+
38
42
  def google_storage_access_key_id
39
43
  "<%= ENV['GOOGLE_STORAGE_ACCESS_KEY_ID'] %>"
40
44
  end
@@ -4,6 +4,7 @@ if defined?(AssetSync)
4
4
  config.fog_provider = 'AWS'
5
5
  config.aws_access_key_id = ENV['AWS_ACCESS_KEY_ID']
6
6
  config.aws_secret_access_key = ENV['AWS_SECRET_ACCESS_KEY']
7
+ config.aws_session_token = ENV['AWS_SESSION_TOKEN'] if ENV.key?('AWS_SESSION_TOKEN')
7
8
  # To use AWS reduced redundancy storage.
8
9
  # config.aws_reduced_redundancy = true
9
10
  #
@@ -13,6 +14,9 @@ if defined?(AssetSync)
13
14
  # Change host option in fog (only if you need to)
14
15
  # config.fog_host = "s3.amazonaws.com"
15
16
  #
17
+ # Change port option in fog (only if you need to)
18
+ # config.fog_port = "9000"
19
+ #
16
20
  # Use http instead of https. Default should be "https" (at least for fog-aws)
17
21
  # config.fog_scheme = "http"
18
22
  <%- elsif google? -%>
@@ -60,6 +64,12 @@ if defined?(AssetSync)
60
64
  # Upload the manifest file also.
61
65
  # config.include_manifest = false
62
66
  #
67
+ # Upload files concurrently
68
+ # config.concurrent_uploads = false
69
+ #
70
+ # Path to cache file to skip scanning remote
71
+ # config.remote_file_list_cache_file_path = './.asset_sync_remote_file_list_cache.json'
72
+ #
63
73
  # Fail silently. Useful for environments such as Heroku
64
74
  # config.fail_silently = true
65
75
  #
@@ -13,6 +13,9 @@ defaults: &defaults
13
13
  # Change host option in fog (only if you need to)
14
14
  # fog_host: "s3.amazonaws.com"
15
15
  #
16
+ # Change port option in fog (only if you need to)
17
+ # config.fog_port = "9000"
18
+ #
16
19
  # Use http instead of https. Default should be "https" (at least for fog-aws)
17
20
  # fog_scheme: "http"
18
21
  <%- elsif google? -%>
@@ -0,0 +1,19 @@
1
+ defaults: &defaults
2
+ fog_provider: "Google"
3
+ google_json_key_location: 'gcs.json'
4
+ google_project: 'some-project'
5
+
6
+ development:
7
+ <<: *defaults
8
+ fog_directory: "rails_app_development"
9
+ existing_remote_files: keep
10
+
11
+ test:
12
+ <<: *defaults
13
+ fog_directory: "rails_app_test"
14
+ existing_remote_files: keep
15
+
16
+ production:
17
+ <<: *defaults
18
+ fog_directory: "rails_app_production"
19
+ existing_remote_files: delete
@@ -145,7 +145,7 @@ describe AssetSync do
145
145
 
146
146
  it "should default asset_regexps to match regexps" do
147
147
  expect(AssetSync.config.cache_asset_regexps).to eq(['cache_me.js', /cache_some\.\d{8}\.css/])
148
- end
148
+ end
149
149
  end
150
150
 
151
151
  describe 'from yml, exporting to a mobile hybrid development directory' do
@@ -255,12 +255,12 @@ describe AssetSync do
255
255
  expect(AssetSync.config.manifest_path).to match(/public\/custom_assets\/manifest.yml/)
256
256
  end
257
257
  end
258
-
258
+
259
259
  describe 'with cache_asset_regexps' do
260
260
  before(:each) do
261
261
  AssetSync.config = AssetSync::Config.new
262
262
  end
263
-
263
+
264
264
  it "config.cache_asset_regexp should set cache_asset_regexps" do
265
265
  AssetSync.config.cache_asset_regexp = /\.[a-f0-9]{8}/i
266
266
  expect(AssetSync.config.cache_asset_regexps.size).to eq(1)
@@ -283,4 +283,36 @@ describe AssetSync do
283
283
  expect{ AssetSync::Config.new }.to raise_error(Psych::SyntaxError)
284
284
  end
285
285
  end
286
+
287
+ describe 'FogPublicValue' do
288
+ describe "#to_bool" do
289
+ it "true should be converted to true" do
290
+ expect(AssetSync::Config::FogPublicValue.new(true).to_bool).to be_truthy
291
+ end
292
+ it "false should be converted to false" do
293
+ expect(AssetSync::Config::FogPublicValue.new(false).to_bool).to be_falsey
294
+ end
295
+ it "nil should be converted to false" do
296
+ expect(AssetSync::Config::FogPublicValue.new(nil).to_bool).to be_falsey
297
+ end
298
+ it "'default' should be converted to false" do
299
+ expect(AssetSync::Config::FogPublicValue.new("default").to_bool).to be_truthy
300
+ end
301
+ end
302
+
303
+ describe "#use_explicit_value?" do
304
+ it "true should be converted to true" do
305
+ expect(AssetSync::Config::FogPublicValue.new(true).use_explicit_value?).to be_truthy
306
+ end
307
+ it "false should be converted to true" do
308
+ expect(AssetSync::Config::FogPublicValue.new(false).use_explicit_value?).to be_truthy
309
+ end
310
+ it "nil should be converted to true" do
311
+ expect(AssetSync::Config::FogPublicValue.new(nil).use_explicit_value?).to be_truthy
312
+ end
313
+ it "'default' should be converted to false" do
314
+ expect(AssetSync::Config::FogPublicValue.new("default").use_explicit_value?).to be_falsey
315
+ end
316
+ end
317
+ end
286
318
  end
@@ -8,8 +8,6 @@ describe AssetSync do
8
8
  AssetSync.config = AssetSync::Config.new
9
9
  AssetSync.configure do |config|
10
10
  config.fog_provider = 'Google'
11
- config.google_storage_access_key_id = 'aaaa'
12
- config.google_storage_secret_access_key = 'bbbb'
13
11
  config.fog_directory = 'mybucket'
14
12
  config.existing_remote_files = "keep"
15
13
  end
@@ -24,14 +22,6 @@ describe AssetSync do
24
22
  expect(AssetSync.config.existing_remote_files?).to eq(true)
25
23
  end
26
24
 
27
- it "should configure google_storage_access_key_id" do
28
- expect(AssetSync.config.google_storage_access_key_id).to eq("aaaa")
29
- end
30
-
31
- it "should configure google_storage_secret_access_key" do
32
- expect(AssetSync.config.google_storage_secret_access_key).to eq("bbbb")
33
- end
34
-
35
25
  it "should configure fog_directory" do
36
26
  expect(AssetSync.config.fog_directory).to eq("mybucket")
37
27
  end
@@ -47,36 +37,119 @@ describe AssetSync do
47
37
  it "should default manifest to false" do
48
38
  expect(AssetSync.config.manifest).to be_falsey
49
39
  end
50
- end
51
40
 
52
- describe 'from yml' do
53
- before(:each) do
54
- set_rails_root('google_with_yml')
55
- AssetSync.config = AssetSync::Config.new
56
- end
41
+ describe "when using S3 interop API" do
42
+ before(:each) do
43
+ AssetSync.configure do |config|
44
+ config.google_storage_access_key_id = 'aaaa'
45
+ config.google_storage_secret_access_key = 'bbbb'
46
+ end
47
+ end
57
48
 
58
- it "should configure google_storage_access_key_id" do
59
- expect(AssetSync.config.google_storage_access_key_id).to eq("xxxx")
60
- end
49
+ it "should configure google_storage_access_key_id" do
50
+ expect(AssetSync.config.google_storage_access_key_id).to eq("aaaa")
51
+ end
61
52
 
62
- it "should configure google_storage_secret_access_key" do
63
- expect(AssetSync.config.google_storage_secret_access_key).to eq("zzzz")
64
- end
53
+ it "should configure google_storage_secret_access_key" do
54
+ expect(AssetSync.config.google_storage_secret_access_key).to eq("bbbb")
55
+ end
65
56
 
66
- it "should configure google_storage_access_key" do
67
- expect(AssetSync.config.fog_directory).to eq("rails_app_test")
57
+ it "should return the correct fog_options" do
58
+ expected_fog_options = { google_storage_access_key_id: "aaaa",
59
+ google_storage_secret_access_key: "bbbb",
60
+ provider: "Google"}
61
+ expect(AssetSync.config.fog_options).to eq(expected_fog_options)
62
+ end
63
+
64
+ it "should not require that google_json_key_location be set" do
65
+ expect(AssetSync.config.valid?).to eq(true)
66
+ end
67
+
68
+ it "should require that google_storage_secret_access_key or access_key_id be set" do
69
+
70
+ AssetSync.configure do |config|
71
+ config.google_storage_access_key_id = nil
72
+ config.google_storage_secret_access_key = nil
73
+ end
74
+
75
+ expect(AssetSync.config.valid?).to eq(false)
76
+ end
68
77
  end
69
78
 
70
- it "should configure google_storage_access_key" do
71
- expect(AssetSync.config.existing_remote_files).to eq("keep")
79
+ describe "when using service account" do
80
+ before(:each) do
81
+ AssetSync.configure do |config|
82
+ config.google_json_key_location = '/path/to.json'
83
+ config.google_project = 'a-google-project-name'
84
+ end
85
+ end
86
+
87
+ it "should configure google_json_key_location" do
88
+ expect(AssetSync.config.google_json_key_location).to eq("/path/to.json")
89
+ end
90
+
91
+ it "should return the correct fog_options" do
92
+ expected_fog_options = { google_json_key_location: "/path/to.json",
93
+ google_project: 'a-google-project-name',
94
+ provider: "Google"}
95
+ expect(AssetSync.config.fog_options).to eq(expected_fog_options)
96
+ end
97
+ it "should not require that google_storage_secret_access_key or access_key_id be set" do
98
+ expect(AssetSync.config.valid?).to eq(true)
99
+ end
72
100
  end
73
101
 
74
- it "should default gzip_compression to false" do
75
- expect(AssetSync.config.gzip_compression).to be_falsey
102
+ end
103
+
104
+ describe 'from yml' do
105
+ describe 'when using S3 interop API' do
106
+ before(:each) do
107
+ set_rails_root('google_with_yml')
108
+ AssetSync.config = AssetSync::Config.new
109
+ end
110
+
111
+ it "should configure google_storage_access_key_id" do
112
+ expect(AssetSync.config.google_storage_access_key_id).to eq("xxxx")
113
+ end
114
+
115
+ it "should configure google_storage_secret_access_key" do
116
+ expect(AssetSync.config.google_storage_secret_access_key).to eq("zzzz")
117
+ end
118
+
119
+ it "should not configure google_json_key_location" do
120
+ expect(AssetSync.config.google_json_key_location).to eq(nil)
121
+ end
122
+
123
+ it "should configure fog_directory" do
124
+ expect(AssetSync.config.fog_directory).to eq("rails_app_test")
125
+ end
126
+
127
+ it "should configure existing_remote_files" do
128
+ expect(AssetSync.config.existing_remote_files).to eq("keep")
129
+ end
130
+
131
+ it "should default gzip_compression to false" do
132
+ expect(AssetSync.config.gzip_compression).to be_falsey
133
+ end
134
+
135
+ it "should default manifest to false" do
136
+ expect(AssetSync.config.manifest).to be_falsey
137
+ end
76
138
  end
77
139
 
78
- it "should default manifest to false" do
79
- expect(AssetSync.config.manifest).to be_falsey
140
+ describe 'when using service account API' do
141
+ before(:each) do
142
+ set_rails_root('google_with_service_account_yml')
143
+ AssetSync.config = AssetSync::Config.new
144
+ end
145
+
146
+ it "should configure google_json_key_location" do
147
+ expect(AssetSync.config.google_json_key_location).to eq("gcs.json")
148
+ end
149
+
150
+ it "should not configure google_storage_secret_access_key" do
151
+ expect(AssetSync.config.google_storage_secret_access_key).to eq(nil)
152
+ end
80
153
  end
81
154
  end
82
155
 
@@ -14,7 +14,7 @@ describe AssetSync do
14
14
  config.fog_region = 'eu-west-1'
15
15
  config.existing_remote_files = "keep"
16
16
  config.prefix = "assets"
17
- config.public_path = Pathname("./public")
17
+ config.public_path = "./public"
18
18
  end
19
19
  end
20
20
 
@@ -22,8 +22,9 @@ describe AssetSync do
22
22
  expect(AssetSync.config.prefix).to eq("assets")
23
23
  end
24
24
 
25
- it "should have prefix of assets" do
26
- expect(AssetSync.config.public_path.to_s).to eq("./public")
25
+ it "should have public_path" do
26
+ expect(AssetSync.config.public_path.to_s).to be_end_with("/public")
27
+ expect(AssetSync.config.public_path).to be_absolute
27
28
  end
28
29
 
29
30
  it "should default AssetSync to enabled" do
@@ -54,6 +54,87 @@ describe AssetSync::Storage do
54
54
  storage.upload_files
55
55
  end
56
56
 
57
+ it 'should upload files concurrently if enabled' do
58
+ @config.concurrent_uploads = true
59
+ storage = AssetSync::Storage.new(@config)
60
+
61
+ allow(storage).to receive(:get_local_files).and_return(@local_files)
62
+ allow(storage).to receive(:get_remote_files).and_return(@remote_files)
63
+ allow(File).to receive(:file?).and_return(true) # Pretend they all exist
64
+
65
+ expect(Thread).to receive(:new).exactly(3).times.and_call_original
66
+ (@local_files - @remote_files + storage.always_upload_files).each do |file|
67
+ expect(storage).to receive(:upload_file).with(file)
68
+ end
69
+
70
+ storage.upload_files
71
+ end
72
+
73
+ it 'should allow custom number of threads' do
74
+ @config.concurrent_uploads = true
75
+ @config.concurrent_uploads_max_threads = 2
76
+ storage = AssetSync::Storage.new(@config)
77
+
78
+ allow(storage).to receive(:get_local_files).and_return(@local_files)
79
+ allow(storage).to receive(:get_remote_files).and_return(@remote_files)
80
+ allow(File).to receive(:file?).and_return(true) # Pretend they all exist
81
+
82
+ expect(Thread).to receive(:new).exactly(2).times.and_call_original
83
+ (@local_files - @remote_files + storage.always_upload_files).each do |file|
84
+ expect(storage).to receive(:upload_file).with(file)
85
+ end
86
+
87
+ storage.upload_files
88
+ end
89
+
90
+ it 'should allow remote_file_list_cache_file_path configuration' do
91
+ file_path = './foo.json'
92
+ @config.remote_file_list_cache_file_path = file_path
93
+ storage = AssetSync::Storage.new(@config)
94
+
95
+ allow(storage).to receive(:get_local_files).and_return(@local_files)
96
+ File.write(file_path, @remote_files.to_json)
97
+ expect(storage).not_to receive(:get_remote_files)
98
+ allow(File).to receive(:file?).and_return(true) # Pretend they all exist
99
+
100
+ (@local_files - @remote_files + storage.always_upload_files).each do |file|
101
+ expect(storage).to receive(:upload_file).with(file)
102
+ end
103
+
104
+ expect(storage).not_to receive(:warn)
105
+ storage.upload_files
106
+
107
+ # update remote_file_list_cache corretly
108
+ updated = JSON.parse(File.read(file_path))
109
+ expect(updated.sort.uniq).to eq (@remote_files + @local_files + storage.always_upload_files).sort.uniq
110
+
111
+ File.delete(file_path)
112
+ end
113
+
114
+ it 'should work with broken cache' do
115
+ file_path = './foo.json'
116
+ @config.remote_file_list_cache_file_path = file_path
117
+
118
+ storage = AssetSync::Storage.new(@config)
119
+
120
+ File.write(file_path, 'some non-json text file content')
121
+
122
+ allow(storage).to receive(:get_local_files).and_return(@local_files)
123
+ allow(storage).to receive(:get_remote_files).and_return(@remote_files)
124
+ allow(File).to receive(:file?).and_return(true) # Pretend they all exist
125
+
126
+ (@local_files - @remote_files + storage.always_upload_files).each do |file|
127
+ expect(storage).to receive(:upload_file).with(file)
128
+ end
129
+
130
+ # when broken, warning message should be prompted
131
+ expect(storage).to receive(:warn)
132
+
133
+ storage.upload_files
134
+
135
+ File.delete(file_path)
136
+ end
137
+
57
138
  it 'should upload updated non-fingerprinted files' do
58
139
  @local_files = [
59
140
  'public/image.png',
@@ -125,7 +206,7 @@ describe AssetSync::Storage do
125
206
  end
126
207
  end
127
208
 
128
- it 'should upload additonal files' do
209
+ it 'should upload additonal files' do
129
210
  @local_files = [
130
211
  'public/image.png',
131
212
  'public/image-82389298328.png',
@@ -307,4 +388,59 @@ describe AssetSync::Storage do
307
388
  storage.upload_file('assets/some_longer_path/local_image2.jpg')
308
389
  end
309
390
  end
391
+
392
+ describe '#delete_extra_remote_files' do
393
+ it 'should delete the files in bulk' do
394
+ remote_files = ['public/image.png']
395
+ connection = double
396
+ config = double
397
+
398
+ storage = AssetSync::Storage.new(@config)
399
+
400
+ [:local_files, :ignored_files, :always_upload_files].each do |method|
401
+ expect(storage).to receive(method).and_return([])
402
+ end
403
+
404
+ allow(storage).to receive(:get_remote_files).and_return(remote_files)
405
+ allow(storage).to receive(:connection).and_return(connection).twice
406
+ allow(storage).to receive(:config).and_return(config).twice
407
+ allow(config).to receive(:aws?).and_return(true)
408
+ allow(config).to receive(:fog_directory).and_return('foo')
409
+ expect(connection).to receive(:delete_multiple_objects).with('foo', remote_files)
410
+
411
+ storage.delete_extra_remote_files
412
+ end
413
+
414
+ context 'when not aws' do
415
+ it 'deletes files sequentially' do
416
+ remote_files = ['public/image.png']
417
+ connection = double
418
+ config = double
419
+ directories = double
420
+ directory = double
421
+ file = double
422
+
423
+ storage = AssetSync::Storage.new(@config)
424
+
425
+ [:local_files, :ignored_files, :always_upload_files].each do |method|
426
+ expect(storage).to receive(method).and_return([])
427
+ end
428
+
429
+ allow(storage).to receive(:get_remote_files).and_return(remote_files)
430
+ allow(storage).to receive(:connection).and_return(connection).twice
431
+ allow(storage).to receive(:config).and_return(config)
432
+ allow(config).to receive(:aws?).and_return(false)
433
+ allow(config).to receive(:fog_directory).and_return('foo')
434
+ allow(config).to receive(:assets_prefix).and_return('foo')
435
+ allow(directories).to receive(:get).and_return(directory)
436
+ allow(directory).to receive(:files).and_return([file])
437
+ allow(file).to receive(:key).and_return('public/image.png')
438
+ allow(connection).to receive(:directories).and_return(directories)
439
+ expect(connection).not_to receive(:delete_multiple_objects)
440
+ expect(file).to receive(:destroy)
441
+
442
+ storage.delete_extra_remote_files
443
+ end
444
+ end
445
+ end
310
446
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asset_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.12.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Simon Hamilton
8
8
  - David Rice
9
9
  - Phil McClure
10
10
  - Toby Osbourn
11
- autorequire:
11
+ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2018-12-07 00:00:00.000000000 Z
14
+ date: 2020-06-17 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: fog-core
@@ -203,10 +203,10 @@ files:
203
203
  - UPGRADING.md
204
204
  - asset_sync.gemspec
205
205
  - docs/heroku.md
206
- - gemfiles/rails_4_2.gemfile
207
206
  - gemfiles/rails_5_0.gemfile
208
207
  - gemfiles/rails_5_1.gemfile
209
208
  - gemfiles/rails_5_2.gemfile
209
+ - gemfiles/rails_6_0.gemfile
210
210
  - lib/asset_sync.rb
211
211
  - lib/asset_sync/asset_sync.rb
212
212
  - lib/asset_sync/config.rb
@@ -223,6 +223,7 @@ files:
223
223
  - spec/dummy_app/app/assets/javascripts/application.js
224
224
  - spec/fixtures/aws_with_yml/config/asset_sync.yml
225
225
  - spec/fixtures/azure_rm_with_yml/config/asset_sync.yml
226
+ - spec/fixtures/google_with_service_account_yml/config/asset_sync.yml
226
227
  - spec/fixtures/google_with_yml/config/asset_sync.yml
227
228
  - spec/fixtures/rackspace_with_yml/config/asset_sync.yml
228
229
  - spec/fixtures/with_invalid_yml/config/asset_sync.yml
@@ -240,7 +241,7 @@ homepage: https://github.com/rumblelabs/asset_sync
240
241
  licenses:
241
242
  - MIT
242
243
  metadata: {}
243
- post_install_message:
244
+ post_install_message:
244
245
  rdoc_options: []
245
246
  require_paths:
246
247
  - lib
@@ -255,9 +256,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
255
256
  - !ruby/object:Gem::Version
256
257
  version: '0'
257
258
  requirements: []
258
- rubyforge_project: asset_sync
259
- rubygems_version: 2.7.8
260
- signing_key:
259
+ rubygems_version: 3.1.4
260
+ signing_key:
261
261
  specification_version: 4
262
262
  summary: Synchronises Assets in a Rails 3 application and Amazon S3/Cloudfront and
263
263
  Rackspace Cloudfiles
@@ -266,6 +266,7 @@ test_files:
266
266
  - spec/dummy_app/app/assets/javascripts/application.js
267
267
  - spec/fixtures/aws_with_yml/config/asset_sync.yml
268
268
  - spec/fixtures/azure_rm_with_yml/config/asset_sync.yml
269
+ - spec/fixtures/google_with_service_account_yml/config/asset_sync.yml
269
270
  - spec/fixtures/google_with_yml/config/asset_sync.yml
270
271
  - spec/fixtures/rackspace_with_yml/config/asset_sync.yml
271
272
  - spec/fixtures/with_invalid_yml/config/asset_sync.yml