buildpack-support 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/buildpack_support/cache/cached_file.rb +7 -5
- data/lib/buildpack_support/cache/download_cache.rb +10 -10
- data/lib/buildpack_support/cache/internet_availability.rb +21 -2
- data/lib/buildpack_support/test/application_helper.rb +1 -0
- data/lib/buildpack_support/test/base_component_helper.rb +2 -0
- data/lib/buildpack_support/test/repository_helper.rb +38 -0
- data/lib/buildpack_support/version.rb +1 -1
- data/spec/buildpack_support/cache/cached_file_spec.rb +26 -2
- data/spec/buildpack_support/cache/download_cache_spec.rb +2 -2
- data/spec/buildpack_support/cache/internet_availability_spec.rb +18 -0
- metadata +7 -3
@@ -29,13 +29,15 @@ module BuildpackSupport
|
|
29
29
|
#
|
30
30
|
# @param [Pathname] cache_root the filesystem root for the file created and expected by this class
|
31
31
|
# @param [String] uri a uri which uniquely identifies the file in the cache
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
key = URI.escape(uri, '/')
|
32
|
+
# @param [Boolean] mutable whether the cached file should be mutable
|
33
|
+
def initialize(cache_root, uri, mutable)
|
34
|
+
key = URI.escape(uri, ':/')
|
36
35
|
@cached = cache_root + "#{key}.cached"
|
37
36
|
@etag = cache_root + "#{key}.etag"
|
38
37
|
@last_modified = cache_root + "#{key}.last_modified"
|
38
|
+
@mutable = mutable
|
39
|
+
|
40
|
+
FileUtils.mkdir_p cache_root if mutable
|
39
41
|
end
|
40
42
|
|
41
43
|
# Opens the cached file
|
@@ -58,7 +60,7 @@ module BuildpackSupport
|
|
58
60
|
|
59
61
|
# Destroys the cached file
|
60
62
|
def destroy
|
61
|
-
[@cached, @etag, @last_modified].each { |f| f.delete if f.exist? }
|
63
|
+
[@cached, @etag, @last_modified].each { |f| f.delete if f.exist? } if @mutable
|
62
64
|
end
|
63
65
|
|
64
66
|
# Opens the etag file
|
@@ -66,7 +66,7 @@ module BuildpackSupport
|
|
66
66
|
cached_file, downloaded = from_immutable_caches(uri), false unless cached_file
|
67
67
|
|
68
68
|
fail "Unable to find cached file for #{uri}" unless cached_file
|
69
|
-
cached_file.cached(File::RDONLY, downloaded, &block)
|
69
|
+
cached_file.cached(File::RDONLY | File::BINARY, downloaded, &block)
|
70
70
|
end
|
71
71
|
|
72
72
|
# Removes an item from the mutable cache.
|
@@ -74,7 +74,7 @@ module BuildpackSupport
|
|
74
74
|
# @param [String] uri the URI of the item
|
75
75
|
# @return [Void]
|
76
76
|
def evict(uri)
|
77
|
-
CachedFile.new(@mutable_cache_root, uri).destroy
|
77
|
+
CachedFile.new(@mutable_cache_root, uri, true).destroy
|
78
78
|
end
|
79
79
|
|
80
80
|
private
|
@@ -138,7 +138,7 @@ module BuildpackSupport
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def cache_content(response, cached_file)
|
141
|
-
cached_file.cached(File::CREAT | File::WRONLY) do |f|
|
141
|
+
cached_file.cached(File::CREAT | File::WRONLY | File::BINARY) do |f|
|
142
142
|
@logger.debug { "Persisting content to #{f.path}" }
|
143
143
|
|
144
144
|
f.truncate(0)
|
@@ -156,7 +156,7 @@ module BuildpackSupport
|
|
156
156
|
|
157
157
|
@logger.debug { "Persisting etag: #{etag}" }
|
158
158
|
|
159
|
-
cached_file.etag(File::CREAT | File::WRONLY) do |f|
|
159
|
+
cached_file.etag(File::CREAT | File::WRONLY | File::BINARY) do |f|
|
160
160
|
f.truncate(0)
|
161
161
|
f.write etag
|
162
162
|
f.fsync
|
@@ -170,7 +170,7 @@ module BuildpackSupport
|
|
170
170
|
|
171
171
|
@logger.debug { "Persisting last-modified: #{last_modified}" }
|
172
172
|
|
173
|
-
cached_file.last_modified(File::CREAT | File::WRONLY) do |f|
|
173
|
+
cached_file.last_modified(File::CREAT | File::WRONLY | File::BINARY) do |f|
|
174
174
|
f.truncate(0)
|
175
175
|
f.write last_modified
|
176
176
|
f.fsync
|
@@ -178,7 +178,7 @@ module BuildpackSupport
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def from_mutable_cache(uri)
|
181
|
-
cached_file = CachedFile.new
|
181
|
+
cached_file = CachedFile.new @mutable_cache_root, uri, true
|
182
182
|
cached = update URI(uri), cached_file
|
183
183
|
[cached_file, cached]
|
184
184
|
rescue => e
|
@@ -188,7 +188,7 @@ module BuildpackSupport
|
|
188
188
|
|
189
189
|
def from_immutable_caches(uri)
|
190
190
|
@immutable_cache_roots.each do |cache_root|
|
191
|
-
candidate = CachedFile.new cache_root, uri
|
191
|
+
candidate = CachedFile.new cache_root, uri, false
|
192
192
|
|
193
193
|
next unless candidate.cached?
|
194
194
|
|
@@ -226,11 +226,11 @@ module BuildpackSupport
|
|
226
226
|
request = Net::HTTP::Get.new(uri.request_uri)
|
227
227
|
|
228
228
|
if cached_file.etag?
|
229
|
-
cached_file.etag(File::RDONLY) { |f| request['If-None-Match'] = File.read(f) }
|
229
|
+
cached_file.etag(File::RDONLY | File::BINARY) { |f| request['If-None-Match'] = File.read(f) }
|
230
230
|
end
|
231
231
|
|
232
232
|
if cached_file.last_modified?
|
233
|
-
cached_file.last_modified(File::RDONLY) { |f| request['If-Modified-Since'] = File.read(f) }
|
233
|
+
cached_file.last_modified(File::RDONLY | File::BINARY) { |f| request['If-Modified-Since'] = File.read(f) }
|
234
234
|
end
|
235
235
|
|
236
236
|
@logger.debug { "Request: #{request.path}, #{request.to_hash}" }
|
@@ -265,7 +265,7 @@ module BuildpackSupport
|
|
265
265
|
def validate_size(expected_size, cached_file)
|
266
266
|
return unless expected_size
|
267
267
|
|
268
|
-
actual_size = cached_file.cached(File::RDONLY) { |f| f.size }
|
268
|
+
actual_size = cached_file.cached(File::RDONLY | File::BINARY) { |f| f.size }
|
269
269
|
@logger.debug { "Validated content size #{actual_size} is #{expected_size}" }
|
270
270
|
|
271
271
|
return if expected_size.to_i == actual_size
|
@@ -45,15 +45,34 @@ module BuildpackSupport
|
|
45
45
|
#
|
46
46
|
# @param [Boolean] available whether the internet is available
|
47
47
|
# @param [String, nil] message an optional message to be printed when the availability is set
|
48
|
+
# @yields an environment with internet availability temporarily overridden if block given
|
48
49
|
def available(available, message = nil)
|
49
50
|
@monitor.synchronize do
|
50
|
-
|
51
|
-
|
51
|
+
if block_given?
|
52
|
+
preserve_availability do
|
53
|
+
@available = available
|
54
|
+
@logger.warn { "Internet availability temporarily set to #{available}: #{message}" } if message
|
55
|
+
|
56
|
+
yield
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@available = available
|
60
|
+
@logger.warn { "Internet availability set to #{available}: #{message}" } if message
|
61
|
+
end
|
52
62
|
end
|
53
63
|
end
|
54
64
|
|
55
65
|
private
|
56
66
|
|
67
|
+
def preserve_availability
|
68
|
+
previous = @available
|
69
|
+
begin
|
70
|
+
yield
|
71
|
+
ensure
|
72
|
+
@available = previous
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
57
76
|
def remote_downloads?
|
58
77
|
BuildpackSupport::ConfigurationUtils.new.load('cache')['remote_downloads'] != 'disabled'
|
59
78
|
end
|
@@ -22,6 +22,7 @@ require 'buildpack_support/test/base_droplet_helper'
|
|
22
22
|
require 'buildpack_support/test/console_helper'
|
23
23
|
require 'buildpack_support/test/internet_availability_helper'
|
24
24
|
require 'buildpack_support/test/logging_helper'
|
25
|
+
require 'buildpack_support/test/repository_helper'
|
25
26
|
require 'buildpack_support/tokenized_version'
|
26
27
|
require 'pathname'
|
27
28
|
|
@@ -31,6 +32,7 @@ shared_context 'base_component_helper' do
|
|
31
32
|
include_context 'console_helper'
|
32
33
|
include_context 'internet_availability_helper'
|
33
34
|
include_context 'logging_helper'
|
35
|
+
include_context 'repository_helper'
|
34
36
|
|
35
37
|
let(:application_cache) { double('ApplicationCache') }
|
36
38
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Encoding: utf-8
|
2
|
+
# Copyright 2013-2014 the original author or authors.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
require 'spec_helper'
|
17
|
+
require 'buildpack_support/repository/configured_item'
|
18
|
+
require 'buildpack_support/tokenized_version'
|
19
|
+
|
20
|
+
shared_context 'repository_helper' do
|
21
|
+
|
22
|
+
let(:configured_item) { double('configured_item') }
|
23
|
+
|
24
|
+
let(:uri) { 'test-uri' }
|
25
|
+
|
26
|
+
let(:version) { '0.0.0' }
|
27
|
+
|
28
|
+
before do
|
29
|
+
tokenized_version = BuildpackSupport::TokenizedVersion.new(version)
|
30
|
+
|
31
|
+
allow(BuildpackSupport::Repository::ConfiguredItem).to receive(:new).and_return configured_item
|
32
|
+
|
33
|
+
allow(configured_item).to receive(:find_item) do |&block|
|
34
|
+
block.call(tokenized_version) if block
|
35
|
+
end.and_return([tokenized_version, uri])
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -22,12 +22,30 @@ require 'fileutils'
|
|
22
22
|
describe BuildpackSupport::Cache::CachedFile do
|
23
23
|
include_context 'scratch_helper'
|
24
24
|
|
25
|
-
let(:
|
25
|
+
let(:cache_root) { scratch_dir + 'cache/root' }
|
26
|
+
|
27
|
+
let(:file_cache) { described_class.new(scratch_dir, 'http://foo-uri/', true) }
|
26
28
|
|
27
29
|
it 'should not create any files on initialization' do
|
28
30
|
%w(cached etag last_modified).each { |extension| expect(cache_file(extension)).not_to exist }
|
29
31
|
end
|
30
32
|
|
33
|
+
it 'should create cache_root if mutable' do
|
34
|
+
expect(cache_root).not_to exist
|
35
|
+
|
36
|
+
described_class.new(cache_root, 'http://foo-uri/', true)
|
37
|
+
|
38
|
+
expect(cache_root).to exist
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should not create cache_root if immutable' do
|
42
|
+
expect(cache_root).not_to exist
|
43
|
+
|
44
|
+
described_class.new(cache_root, 'http://foo-uri/', false)
|
45
|
+
|
46
|
+
expect(cache_root).not_to exist
|
47
|
+
end
|
48
|
+
|
31
49
|
it 'should not detect cached file' do
|
32
50
|
expect(file_cache.cached?).not_to be
|
33
51
|
end
|
@@ -62,6 +80,12 @@ describe BuildpackSupport::Cache::CachedFile do
|
|
62
80
|
%w(cached etag last_modified).each { |extension| expect(cache_file(extension)).not_to exist }
|
63
81
|
end
|
64
82
|
|
83
|
+
it 'should not destroy all files if immutable' do
|
84
|
+
described_class.new(scratch_dir, 'http://foo-uri/', false).destroy
|
85
|
+
|
86
|
+
%w(cached etag last_modified).each { |extension| expect(cache_file(extension)).to exist }
|
87
|
+
end
|
88
|
+
|
65
89
|
it 'should call the block with the content of the etag file' do
|
66
90
|
expect { |b| file_cache.etag(File::RDONLY, 'test-arg', &b) }.to yield_file_with_content(/foo-etag/)
|
67
91
|
end
|
@@ -80,7 +104,7 @@ describe BuildpackSupport::Cache::CachedFile do
|
|
80
104
|
end
|
81
105
|
|
82
106
|
def cache_file(extension)
|
83
|
-
scratch_dir + "http
|
107
|
+
scratch_dir + "http%3A%2F%2Ffoo-uri%2F.#{extension}"
|
84
108
|
end
|
85
109
|
|
86
110
|
def touch(extension, content = '')
|
@@ -242,11 +242,11 @@ describe BuildpackSupport::Cache::DownloadCache do
|
|
242
242
|
end
|
243
243
|
|
244
244
|
def cache_file(root, extension)
|
245
|
-
root + "http
|
245
|
+
root + "http%3A%2F%2Ffoo-uri%2F.#{extension}"
|
246
246
|
end
|
247
247
|
|
248
248
|
def credential_cache_file(root, extension)
|
249
|
-
root + "http
|
249
|
+
root + "http%3A%2F%2Ftest-username%3Atest-password@foo-uri%2F.#{extension}"
|
250
250
|
end
|
251
251
|
|
252
252
|
def expect_complete_cache(root)
|
@@ -54,4 +54,22 @@ describe BuildpackSupport::Cache::InternetAvailability do
|
|
54
54
|
expect(log_contents).to match(/Internet availability set to false: test message/)
|
55
55
|
end
|
56
56
|
|
57
|
+
it 'should temporarily set internet unavailable' do
|
58
|
+
expect(described_class.instance.available?).to be
|
59
|
+
|
60
|
+
described_class.instance.available(false) { expect(described_class.instance.available?).not_to be }
|
61
|
+
|
62
|
+
expect(described_class.instance.available?).to be
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should temporarily set internet available',
|
66
|
+
:disable_internet do
|
67
|
+
|
68
|
+
expect(described_class.instance.available?).not_to be
|
69
|
+
|
70
|
+
described_class.instance.available(true) { expect(described_class.instance.available?).to be }
|
71
|
+
|
72
|
+
expect(described_class.instance.available?).not_to be
|
73
|
+
end
|
74
|
+
|
57
75
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: buildpack-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-05-
|
12
|
+
date: 2014-05-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -261,6 +261,7 @@ files:
|
|
261
261
|
- lib/buildpack_support/test/environment_helper.rb
|
262
262
|
- lib/buildpack_support/test/internet_availability_helper.rb
|
263
263
|
- lib/buildpack_support/test/logging_helper.rb
|
264
|
+
- lib/buildpack_support/test/repository_helper.rb
|
264
265
|
- lib/buildpack_support/test/scratch_helper.rb
|
265
266
|
- lib/buildpack_support/test/versioned_dependency_component_helper.rb
|
266
267
|
- lib/buildpack_support/test/with_load_path_helper.rb
|
@@ -346,13 +347,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
346
347
|
version: '0'
|
347
348
|
segments:
|
348
349
|
- 0
|
349
|
-
hash:
|
350
|
+
hash: 2138916088248865313
|
350
351
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
351
352
|
none: false
|
352
353
|
requirements:
|
353
354
|
- - ! '>='
|
354
355
|
- !ruby/object:Gem::Version
|
355
356
|
version: '0'
|
357
|
+
segments:
|
358
|
+
- 0
|
359
|
+
hash: 2138916088248865313
|
356
360
|
requirements: []
|
357
361
|
rubyforge_project:
|
358
362
|
rubygems_version: 1.8.23.2
|