buildpack-support 1.0.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.
Files changed (122) hide show
  1. data/LICENSE +202 -0
  2. data/NOTICE +2 -0
  3. data/docs/cache.md +77 -0
  4. data/docs/component.md +1 -0
  5. data/docs/configuration.md +27 -0
  6. data/docs/logging.md +54 -0
  7. data/docs/other.md +1 -0
  8. data/docs/rake.md +1 -0
  9. data/docs/repository.md +116 -0
  10. data/docs/test.md +1 -0
  11. data/lib/buildpack_support.rb +18 -0
  12. data/lib/buildpack_support/base_buildpack.rb +166 -0
  13. data/lib/buildpack_support/buildpack_version.rb +124 -0
  14. data/lib/buildpack_support/cache.rb +24 -0
  15. data/lib/buildpack_support/cache/application_cache.rb +41 -0
  16. data/lib/buildpack_support/cache/cached_file.rb +103 -0
  17. data/lib/buildpack_support/cache/download_cache.rb +280 -0
  18. data/lib/buildpack_support/cache/inferred_network_failure.rb +26 -0
  19. data/lib/buildpack_support/cache/internet_availability.rb +64 -0
  20. data/lib/buildpack_support/component.rb +24 -0
  21. data/lib/buildpack_support/component/application.rb +76 -0
  22. data/lib/buildpack_support/component/base_component.rb +78 -0
  23. data/lib/buildpack_support/component/base_droplet.rb +96 -0
  24. data/lib/buildpack_support/component/downloads.rb +88 -0
  25. data/lib/buildpack_support/component/services.rb +84 -0
  26. data/lib/buildpack_support/component/versioned_dependency_component.rb +71 -0
  27. data/lib/buildpack_support/component/versioned_downloads.rb +57 -0
  28. data/lib/buildpack_support/component/with_timing.rb +40 -0
  29. data/lib/buildpack_support/configuration_utils.rb +58 -0
  30. data/lib/buildpack_support/constantize.rb +46 -0
  31. data/lib/buildpack_support/dash_case.rb +29 -0
  32. data/lib/buildpack_support/directory_finder.rb +45 -0
  33. data/lib/buildpack_support/filtering_pathname.rb +227 -0
  34. data/lib/buildpack_support/format_duration.rb +57 -0
  35. data/lib/buildpack_support/logging.rb +22 -0
  36. data/lib/buildpack_support/logging/delegating_logger.rb +48 -0
  37. data/lib/buildpack_support/logging/logger_factory.rb +148 -0
  38. data/lib/buildpack_support/qualify_path.rb +36 -0
  39. data/lib/buildpack_support/rake.rb +22 -0
  40. data/lib/buildpack_support/rake/buildpack_stage_task.rb +86 -0
  41. data/lib/buildpack_support/rake/cached_artifact_finder.rb +99 -0
  42. data/lib/buildpack_support/rake/check_api_doc_task.rb +70 -0
  43. data/lib/buildpack_support/rake/dependency_cache_task.rb +87 -0
  44. data/lib/buildpack_support/rake/disable_remote_downloads_task.rb +80 -0
  45. data/lib/buildpack_support/rake/package_task.rb +133 -0
  46. data/lib/buildpack_support/rake/package_zip_task.rb +80 -0
  47. data/lib/buildpack_support/rake/repository_configuration_finder.rb +66 -0
  48. data/lib/buildpack_support/rake/write_version_file_task.rb +82 -0
  49. data/lib/buildpack_support/repository.rb +24 -0
  50. data/lib/buildpack_support/repository/configured_item.rb +81 -0
  51. data/lib/buildpack_support/repository/repository_index.rb +98 -0
  52. data/lib/buildpack_support/repository/wildcard_version_resolver.rb +75 -0
  53. data/lib/buildpack_support/shell.rb +41 -0
  54. data/lib/buildpack_support/snake_case.rb +30 -0
  55. data/lib/buildpack_support/space_case.rb +29 -0
  56. data/lib/buildpack_support/test/application_helper.rb +41 -0
  57. data/lib/buildpack_support/test/base_component_helper.rb +59 -0
  58. data/lib/buildpack_support/test/base_droplet_helper.rb +36 -0
  59. data/lib/buildpack_support/test/console_helper.rb +57 -0
  60. data/lib/buildpack_support/test/environment_helper.rb +32 -0
  61. data/lib/buildpack_support/test/internet_availability_helper.rb +29 -0
  62. data/lib/buildpack_support/test/logging_helper.rb +50 -0
  63. data/lib/buildpack_support/test/scratch_helper.rb +32 -0
  64. data/lib/buildpack_support/test/versioned_dependency_component_helper.rb +32 -0
  65. data/lib/buildpack_support/test/with_load_path_helper.rb +27 -0
  66. data/lib/buildpack_support/to_b.rb +38 -0
  67. data/lib/buildpack_support/tokenized_version.rb +157 -0
  68. data/lib/buildpack_support/version.rb +23 -0
  69. data/spec/buildpack_support/base_buildpack_spec.rb +112 -0
  70. data/spec/buildpack_support/buildpack_version_spec.rb +122 -0
  71. data/spec/buildpack_support/cache/application_cache_spec.rb +56 -0
  72. data/spec/buildpack_support/cache/cached_file_spec.rb +94 -0
  73. data/spec/buildpack_support/cache/download_cache_spec.rb +293 -0
  74. data/spec/buildpack_support/cache/internet_availability_spec.rb +57 -0
  75. data/spec/buildpack_support/cache/yield_file_with_content.rb +30 -0
  76. data/spec/buildpack_support/component/application_spec.rb +81 -0
  77. data/spec/buildpack_support/component/base_component_spec.rb +81 -0
  78. data/spec/buildpack_support/component/base_droplet_spec.rb +72 -0
  79. data/spec/buildpack_support/component/downloads_spec.rb +63 -0
  80. data/spec/buildpack_support/component/services_spec.rb +80 -0
  81. data/spec/buildpack_support/component/versioned_dependency_component_spec.rb +58 -0
  82. data/spec/buildpack_support/component/versioned_downloads_spec.rb +58 -0
  83. data/spec/buildpack_support/component/with_timing_spec.rb +30 -0
  84. data/spec/buildpack_support/configuration_utils_spec.rb +39 -0
  85. data/spec/buildpack_support/constantize_spec.rb +34 -0
  86. data/spec/buildpack_support/dash_case_spec.rb +41 -0
  87. data/spec/buildpack_support/directory_finder_spec.rb +41 -0
  88. data/spec/buildpack_support/filtering_pathname_spec.rb +443 -0
  89. data/spec/buildpack_support/format_duration_spec.rb +60 -0
  90. data/spec/buildpack_support/logging/delegating_logger_spec.rb +62 -0
  91. data/spec/buildpack_support/logging/logger_factory_spec.rb +262 -0
  92. data/spec/buildpack_support/qualify_path_spec.rb +42 -0
  93. data/spec/buildpack_support/rake/buildpack_stage_task_spec.rb +88 -0
  94. data/spec/buildpack_support/rake/cached_artifact_finder_spec.rb +73 -0
  95. data/spec/buildpack_support/rake/check_api_doc_task_spec.rb +69 -0
  96. data/spec/buildpack_support/rake/dependency_cache_task_spec.rb +133 -0
  97. data/spec/buildpack_support/rake/disable_remote_downloads_task_spec.rb +91 -0
  98. data/spec/buildpack_support/rake/package_task_spec.rb +335 -0
  99. data/spec/buildpack_support/rake/package_zip_task_spec.rb +91 -0
  100. data/spec/buildpack_support/rake/repository_configuration_finder_spec.rb +61 -0
  101. data/spec/buildpack_support/rake/write_version_file_task_spec.rb +96 -0
  102. data/spec/buildpack_support/repository/configured_item_spec.rb +78 -0
  103. data/spec/buildpack_support/repository/repository_index_spec.rb +118 -0
  104. data/spec/buildpack_support/repository/wildcard_version_resolver_spec.rb +73 -0
  105. data/spec/buildpack_support/shell_spec.rb +32 -0
  106. data/spec/buildpack_support/snake_case_spec.rb +45 -0
  107. data/spec/buildpack_support/space_case_spec.rb +41 -0
  108. data/spec/buildpack_support/to_b_spec.rb +41 -0
  109. data/spec/buildpack_support/tokenized_version_spec.rb +132 -0
  110. data/spec/fixtures/application/test-file +0 -0
  111. data/spec/fixtures/config/found-config.yml +2 -0
  112. data/spec/fixtures/droplet-resources/droplet-resource +0 -0
  113. data/spec/fixtures/stub-download-with-top-level.zip +0 -0
  114. data/spec/fixtures/stub-download.tar.gz +0 -0
  115. data/spec/fixtures/stub-download.zip +0 -0
  116. data/spec/fixtures/test-cache.yml +18 -0
  117. data/spec/fixtures/test-index.yml +2 -0
  118. data/spec/fixtures/test_component.rb +0 -0
  119. data/spec/fixtures/zip-contents/test-directory/test-deep-file +0 -0
  120. data/spec/fixtures/zip-contents/test-file +0 -0
  121. data/spec/spec_helper.rb +30 -0
  122. metadata +416 -0
@@ -0,0 +1,66 @@
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 'buildpack_support/configuration_utils'
17
+ require 'buildpack_support/rake'
18
+ require 'buildpack_support/snake_case'
19
+ require 'yaml'
20
+
21
+ module BuildpackSupport
22
+ module Rake
23
+
24
+ # A class that finds all eligible repository configurations
25
+ class RepositoryConfigurationFinder
26
+
27
+ # Creates a new instance
28
+ def initialize
29
+ @configuration_utils = BuildpackSupport::ConfigurationUtils.new
30
+ end
31
+
32
+ # Returns a collection of hashes that contain repository configurations
33
+ #
34
+ # @return [Array<Hash>] a collection of hashes that contain repository configurations
35
+ def find
36
+ component_ids.map do |component_id|
37
+ configurations(@configuration_utils.load(component_id))
38
+ end.flatten
39
+ end
40
+
41
+ private
42
+
43
+ def component_ids
44
+ @configuration_utils.load('components').values.flatten.map { |component| component.split('::').last.snake_case }
45
+ end
46
+
47
+ def configurations(configuration)
48
+ configurations = []
49
+
50
+ if repository_configuration?(configuration)
51
+ configurations << configuration
52
+ else
53
+ configuration.values.each { |v| configurations << configurations(v) if v.is_a? Hash }
54
+ end
55
+
56
+ configurations
57
+ end
58
+
59
+ def repository_configuration?(configuration)
60
+ configuration['version'] && configuration['repository_root']
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,82 @@
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 'buildpack_support/rake'
17
+ require 'rake'
18
+ require 'rake/tasklib'
19
+ require 'yaml'
20
+
21
+ module BuildpackSupport
22
+ module Rake
23
+
24
+ # A task generator for the task that creates version file.
25
+ class WriteVersionFileTask < ::Rake::TaskLib
26
+
27
+ # @!attribute [rw] buildpack_version
28
+ # @return [BuildpackSupport::BuildpackVersion] the version of the buildpack.
29
+ attr_accessor :buildpack_version
30
+
31
+ # @!attribute [rw] package_name
32
+ # @return [String] the name of the package
33
+ attr_accessor :package_name
34
+
35
+ # @!attribute [rw] staging_dir
36
+ # @return [String] the directory to zip the contents of.
37
+ attr_accessor :staging_dir
38
+
39
+ # @!attribute [rw] verbose
40
+ # @return [Boolean] the verbosity of the task. Defaults to +false+.
41
+ attr_accessor :verbose
42
+
43
+ # Creates an instance
44
+ def initialize(&task_block)
45
+ @verbose = false
46
+
47
+ task_block.call(*[self].slice(0, task_block.arity)) if task_block
48
+ abort 'buildpack_version must be configured' unless buildpack_version
49
+ abort 'package_name must be configured' unless package_name
50
+ abort 'staging_dir must be configured' unless staging_dir
51
+
52
+ create_task buildpack_version, package_name, staging_dir, verbose
53
+ end
54
+
55
+ # Runs the task
56
+ #
57
+ # @param [String] name the file to write to
58
+ # @param [BuildpackSupport::BuildpackVersion] buildpack_version the buildpack version to write to the file
59
+ # @param [Boolean] verbose whether to print messages to the console
60
+ # @return [void]
61
+ def run_task(name, buildpack_version, verbose)
62
+ RakeFileUtils.verbose(verbose) { mkdir_p File.dirname(name) }
63
+ File.open(name, 'w') { |f| f.write(buildpack_version.to_hash.to_yaml) }
64
+ rake_output_message "Wrote buildpack version to #{name}" if verbose
65
+ end
66
+
67
+ private
68
+
69
+ def create_task(buildpack_version, package_name, staging_dir, verbose)
70
+ target = target staging_dir
71
+ task package_name => target
72
+ file(target) { |t| run_task t.name, buildpack_version, verbose }
73
+ end
74
+
75
+ def target(staging_dir)
76
+ "#{staging_dir}/config/version.yml"
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,24 @@
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 'buildpack_support'
17
+
18
+ module BuildpackSupport
19
+
20
+ # A module encapsulating all of the code for the repository utilities
21
+ module Repository
22
+ end
23
+
24
+ end
@@ -0,0 +1,81 @@
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 'buildpack_support/repository'
17
+ require 'buildpack_support/repository/repository_index'
18
+ require 'buildpack_support/repository/wildcard_version_resolver'
19
+ require 'buildpack_support/tokenized_version'
20
+
21
+ module BuildpackSupport
22
+ module Repository
23
+
24
+ # A class encapsulating details of a file stored in a versioned repository.
25
+ class ConfiguredItem
26
+
27
+ # Creates a new instance
28
+ #
29
+ # @param [VersionResolver] version_resolver the version resolver to use when finding items
30
+ def initialize(version_resolver = WildcardVersionResolver.new)
31
+ @version_resolver = version_resolver
32
+ end
33
+
34
+ # Finds an instance of the file based on the configuration and wraps any exceptions
35
+ # to identify the component.
36
+ #
37
+ # @param [String] component_name the name of the component
38
+ # @param [Hash] configuration the configuration
39
+ # @option configuration [String] :repository_root the root directory of the repository
40
+ # @option configuration [String] :version the version of the file to resolve
41
+ # @yield the version to a block for validation. An error should be raised if the version is not valid
42
+ # @yieldparam version [BuildpackSupport::TokenizedVersion] the version to validate
43
+ # @return [String] the URI of the chosen version of the file
44
+ # @return [TokenizedVersion] the chosen version of the file
45
+ def find_item(component_name, configuration)
46
+ repository_root = repository_root(configuration)
47
+ version = version(configuration)
48
+
49
+ yield version if block_given?
50
+
51
+ index = index(repository_root)
52
+ index.find_item version
53
+ rescue => e
54
+ raise RuntimeError, "#{component_name} error: #{e.message}", e.backtrace
55
+ end
56
+
57
+ private
58
+
59
+ KEY_REPOSITORY_ROOT = 'repository_root'.freeze
60
+
61
+ KEY_VERSION = 'version'.freeze
62
+
63
+ private_constant :KEY_REPOSITORY_ROOT, :KEY_VERSION
64
+
65
+ def index(repository_root)
66
+ RepositoryIndex.new(repository_root, @version_resolver)
67
+ end
68
+
69
+ def repository_root(configuration)
70
+ fail "A repository root must be specified as a key-value pair of '#{KEY_REPOSITORY_ROOT}'' to the URI of the repository." unless configuration.key? KEY_REPOSITORY_ROOT
71
+ configuration[KEY_REPOSITORY_ROOT]
72
+ end
73
+
74
+ def version(configuration)
75
+ BuildpackSupport::TokenizedVersion.new(configuration[KEY_VERSION])
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,98 @@
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 'buildpack_support/cache/download_cache'
17
+ require 'buildpack_support/configuration_utils'
18
+ require 'buildpack_support/logging/logger_factory'
19
+ require 'buildpack_support/repository'
20
+ require 'buildpack_support/repository/wildcard_version_resolver'
21
+ require 'rbconfig'
22
+ require 'yaml'
23
+
24
+ module BuildpackSupport
25
+ module Repository
26
+
27
+ # A repository index represents the index of repository containing various versions of a file.
28
+ class RepositoryIndex
29
+
30
+ # Creates a new repository index, populating it with values from an index file.
31
+ #
32
+ # @param [String] repository_root the root of the repository to create the index for
33
+ # @param [VersionResolver] version_resolver the version resolver to use when finding items
34
+ def initialize(repository_root, version_resolver = WildcardVersionResolver.new)
35
+ @logger = BuildpackSupport::Logging::LoggerFactory.instance.get_logger RepositoryIndex
36
+ @version_resolver = version_resolver
37
+
38
+ default_repository_root = BuildpackSupport::ConfigurationUtils.new.load('repository')['default_repository_root'].chomp('/')
39
+ cache.get("#{canonical default_repository_root, repository_root}#{INDEX_PATH}") do |file|
40
+ @index = YAML.load_file(file)
41
+ @logger.debug { @index }
42
+ end
43
+ end
44
+
45
+ # Finds a version of the file matching the given, possibly wildcarded, version.
46
+ #
47
+ # @param [String] version the possibly wildcarded version to find
48
+ # @return [TokenizedVersion] the version of the file found
49
+ # @return [String] the URI of the file found
50
+ def find_item(version)
51
+ version = @version_resolver.resolve(version, @index.keys)
52
+ uri = @index[version.to_s]
53
+ [version, uri]
54
+ end
55
+
56
+ private
57
+
58
+ INDEX_PATH = '/index.yml'.freeze
59
+
60
+ private_constant :INDEX_PATH
61
+
62
+ def architecture
63
+ `uname -m`.strip
64
+ end
65
+
66
+ def cache
67
+ BuildpackSupport::Cache::DownloadCache.new(Pathname.new(Dir.tmpdir),
68
+ BuildpackSupport::Cache::DownloadCache::CACHED_RESOURCES_DIRECTORY)
69
+ end
70
+
71
+ def canonical(default_root, raw)
72
+ cooked = raw
73
+ .gsub(/\{default.repository.root\}/, default_root)
74
+ .gsub(/\{platform\}/, platform)
75
+ .gsub(/\{architecture\}/, architecture)
76
+ .chomp('/')
77
+ @logger.debug { "#{raw} expanded to #{cooked}" }
78
+ cooked
79
+ end
80
+
81
+ def platform
82
+ redhat_release = Pathname.new('/etc/redhat-release')
83
+
84
+ if redhat_release.exist?
85
+ "centos#{redhat_release.read.match(/CentOS release (\d)/)[1]}"
86
+ elsif `uname -s` =~ /Darwin/
87
+ 'mountainlion'
88
+ elsif !`which lsb_release 2> /dev/null`.empty?
89
+ `lsb_release -cs`.strip
90
+ else
91
+ fail 'Unable to determine platform'
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,75 @@
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 'buildpack_support/repository'
17
+ require 'buildpack_support/tokenized_version'
18
+
19
+ module BuildpackSupport
20
+ module Repository
21
+
22
+ # A resolver that selects values from a collection based on a set of rules governing wildcards
23
+ class WildcardVersionResolver
24
+
25
+ # Resolves a version from a collection of versions. The +candidate_version+ must be structured like:
26
+ # * up to three numeric components, followed by an optional string component
27
+ # * the final component may be a +
28
+ # The resolution returns the maximum of the versions that match the candidate version
29
+ #
30
+ # @param [TokenizedVersion] candidate_version the version, possibly containing a wildcard, to resolve. If +nil+,
31
+ # substituted with +.
32
+ # @param [Array<String>] versions the collection of versions to resolve against
33
+ # @return [TokenizedVersion] the resolved version
34
+ # @raise if no version can be resolved
35
+ def resolve(candidate_version, versions)
36
+ tokenized_candidate_version = safe_candidate_version candidate_version
37
+ tokenized_versions = versions.map { |version| BuildpackSupport::TokenizedVersion.new(version, false) }
38
+
39
+ version = tokenized_versions
40
+ .select { |tokenized_version| matches? tokenized_candidate_version, tokenized_version }
41
+ .max { |a, b| a <=> b }
42
+
43
+ fail "No version resolvable for '#{candidate_version}' in #{versions.join(', ')}" if version.nil?
44
+ version
45
+ end
46
+
47
+ private
48
+
49
+ TOKENIZED_WILDCARD = BuildpackSupport::TokenizedVersion.new('+').freeze
50
+
51
+ private_constant :TOKENIZED_WILDCARD
52
+
53
+ def safe_candidate_version(candidate_version)
54
+ if candidate_version.nil?
55
+ TOKENIZED_WILDCARD
56
+ else
57
+ unless candidate_version.is_a?(BuildpackSupport::TokenizedVersion)
58
+ fail "Invalid TokenizedVersion '#{candidate_version}'"
59
+ end
60
+ candidate_version
61
+ end
62
+ end
63
+
64
+ def matches?(tokenized_candidate, tokenized_version)
65
+ (0..3).all? do |i|
66
+ tokenized_candidate[i].nil? ||
67
+ tokenized_candidate[i] == BuildpackSupport::TokenizedVersion::WILDCARD ||
68
+ tokenized_candidate[i] == tokenized_version[i]
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,41 @@
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 'buildpack_support'
17
+ require 'open3'
18
+
19
+ module BuildpackSupport
20
+
21
+ # A mixin that provides a +shell()+ command
22
+ module Shell
23
+
24
+ # A +system()+-like command that ensure that the execution fails if the command returns a non-zero exit code
25
+ #
26
+ # @param [String] command the command to run
27
+ # @return [Void]
28
+ def shell(command)
29
+ Open3.popen3(command) do |_stdin, stdout, stderr, wait_thr|
30
+ if wait_thr.value != 0
31
+ puts "\nCommand '#{command}' has failed"
32
+ puts "STDOUT: #{stdout.gets}"
33
+ puts "STDERR: #{stderr.gets}"
34
+
35
+ fail
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end