buildpack-support 1.0.0 → 1.1.0

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.
@@ -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
- def initialize(cache_root, uri)
33
- FileUtils.mkdir_p cache_root
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(@mutable_cache_root, uri)
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
- @available = available
51
- @logger.warn { "Internet availability set to #{available}: #{message}" } if message
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
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  require 'spec_helper'
17
+ require 'buildpack_support/component/application'
17
18
  require 'buildpack_support/test/environment_helper'
18
19
  require 'buildpack_support/test/scratch_helper'
19
20
 
@@ -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
@@ -18,6 +18,6 @@ require 'buildpack_support'
18
18
  module BuildpackSupport
19
19
 
20
20
  # The version of the gem
21
- VERSION = '1.0.0'
21
+ VERSION = '1.1.0'
22
22
 
23
23
  end
@@ -22,12 +22,30 @@ require 'fileutils'
22
22
  describe BuildpackSupport::Cache::CachedFile do
23
23
  include_context 'scratch_helper'
24
24
 
25
- let(:file_cache) { described_class.new(scratch_dir, 'http://foo-uri/') }
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:%2F%2Ffoo-uri%2F.#{extension}"
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:%2F%2Ffoo-uri%2F.#{extension}"
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:%2F%2Ftest-username:test-password@foo-uri%2F.#{extension}"
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.0.0
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-22 00:00:00.000000000 Z
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: 3626864302089607718
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