vara 0.17.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LEGAL.txt +13 -0
- data/README.md +297 -0
- data/bin/vara +14 -0
- data/lib/vara.rb +14 -0
- data/lib/vara/cli.rb +96 -0
- data/lib/vara/cli_helper.rb +12 -0
- data/lib/vara/content_migrations_processor.rb +62 -0
- data/lib/vara/downloader.rb +61 -0
- data/lib/vara/git_inspector.rb +66 -0
- data/lib/vara/linter.rb +40 -0
- data/lib/vara/log.rb +71 -0
- data/lib/vara/materials.rb +139 -0
- data/lib/vara/md5_creator.rb +31 -0
- data/lib/vara/metadata/compiled_packages.rb +87 -0
- data/lib/vara/metadata/release.rb +86 -0
- data/lib/vara/metadata/stemcell.rb +84 -0
- data/lib/vara/prerelease_versioner.rb +79 -0
- data/lib/vara/product.rb +98 -0
- data/lib/vara/product_artifact_validator.rb +32 -0
- data/lib/vara/product_artifact_zipper.rb +110 -0
- data/lib/vara/product_contents.rb +64 -0
- data/lib/vara/product_metadata.rb +113 -0
- data/lib/vara/product_metadata_processor.rb +98 -0
- data/lib/vara/product_resource_downloader.rb +69 -0
- data/lib/vara/static_versioner.rb +53 -0
- data/lib/vara/tarball.rb +92 -0
- data/lib/vara/version.rb +12 -0
- metadata +213 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'vara/log'
|
3
|
+
|
4
|
+
module Vara
|
5
|
+
class ContentMigrationsProcessor
|
6
|
+
include Vara::Loggable
|
7
|
+
|
8
|
+
# @param product_dir [String] path to product directory root
|
9
|
+
# @param versioner [Vara::PrereleaseVersioner,Vara::StaticVersioner]
|
10
|
+
def initialize(product_dir, versioner)
|
11
|
+
@product_dir = product_dir
|
12
|
+
@versioner = versioner
|
13
|
+
end
|
14
|
+
|
15
|
+
# Composes content_migrations_parts/base.yml and content_migrations_parts/migrations/*.yml
|
16
|
+
# into content_migrations/migrations.yml, expanding placeholders as necessary.
|
17
|
+
# @return [String] path to the generated content migration file
|
18
|
+
def process
|
19
|
+
content_migrations = load_content_migrations
|
20
|
+
processed = versioner.update_content_migrations(content_migrations)
|
21
|
+
save_content_migrations(processed)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :product_dir, :versioner
|
27
|
+
|
28
|
+
def load_content_migrations
|
29
|
+
parts_dir = File.join(product_dir, 'content_migrations_parts')
|
30
|
+
base_path = File.join(parts_dir, 'base.yml')
|
31
|
+
content_migrations = YAML.load_file(base_path) || {}
|
32
|
+
log.info("Composing content migrations: loaded #{base_path}")
|
33
|
+
Dir.glob(File.join(parts_dir, 'migrations', '*.yml')).each do |migration_path|
|
34
|
+
migration = YAML.load_file(migration_path)
|
35
|
+
log.info("Composing content migrations: loaded #{migration_path}")
|
36
|
+
content_migrations['migrations'] ||= []
|
37
|
+
content_migrations['migrations'] << migration
|
38
|
+
end
|
39
|
+
|
40
|
+
content_migrations
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_content_migrations(processed_hash)
|
44
|
+
out_path = File.join(product_dir, 'content_migrations', 'migrations.yml')
|
45
|
+
|
46
|
+
File.open(out_path, 'w') do |out|
|
47
|
+
YAML.dump(processed_hash, out)
|
48
|
+
end
|
49
|
+
|
50
|
+
out_path
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
56
|
+
# All rights reserved.
|
57
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
58
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
59
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
60
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
61
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
62
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'aws-sdk'
|
4
|
+
|
5
|
+
module Vara
|
6
|
+
class Downloader
|
7
|
+
# @param source [String] The URL from which to download
|
8
|
+
# @param target [String] The path on disk for where to save the downloaded file
|
9
|
+
def self.download(metadata, target)
|
10
|
+
fail 'URL or AWS Config required to download!' unless metadata.url || metadata.aws
|
11
|
+
if metadata.aws
|
12
|
+
download_from_aws(metadata.aws, target)
|
13
|
+
elsif metadata.url
|
14
|
+
download_from_url(metadata.url, target)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.download_from_aws(aws_config, target)
|
19
|
+
s3 = Aws::S3::Client.new(
|
20
|
+
access_key_id: aws_config.access_key_id,
|
21
|
+
secret_access_key: aws_config.secret_access_key,
|
22
|
+
force_path_style: true,
|
23
|
+
region: aws_config.region
|
24
|
+
)
|
25
|
+
|
26
|
+
s3.get_object(
|
27
|
+
response_target: target,
|
28
|
+
bucket: aws_config.bucket_name,
|
29
|
+
key: aws_config.filename
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.download_from_url(url, target)
|
34
|
+
uri = URI(url)
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
http.use_ssl = uri.scheme == 'https'
|
37
|
+
http.start { |h| stream_target(h, target, uri) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.stream_target(http, target, uri)
|
41
|
+
request = Net::HTTP::Get.new uri.request_uri
|
42
|
+
|
43
|
+
http.request request do |response|
|
44
|
+
return download_from_url(response['location'], target) if response.is_a?(Net::HTTPRedirection)
|
45
|
+
|
46
|
+
open target, 'w' do |io|
|
47
|
+
response.read_body { |chunk| io.write chunk }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
55
|
+
# All rights reserved.
|
56
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
57
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
58
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
59
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
60
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
61
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Vara
|
2
|
+
class GitInspector
|
3
|
+
# @param repo_path [String] Path to the root of the repository to inspect
|
4
|
+
# @return [String] The SHA of the current git revision
|
5
|
+
def self.current_revision(repo_path)
|
6
|
+
new(repo_path).current_revision
|
7
|
+
end
|
8
|
+
|
9
|
+
# @param repo_path [String] Path to the root of the repository to inspect
|
10
|
+
# @return [Boolean]
|
11
|
+
def self.git_repo?(repo_path)
|
12
|
+
system("cd #{repo_path} && git rev-parse --is-inside-work-tree")
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param repo_path [String] Path to the root of the repository to inspect
|
16
|
+
def initialize(repo_path)
|
17
|
+
fail "The directory #{repo_path} must be a git repo" unless self.class.git_repo?(repo_path)
|
18
|
+
@repo_path = repo_path
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String] The SHA of the current git revision
|
22
|
+
def current_revision
|
23
|
+
revision = `cd #{repo_path} && git rev-list --max-count=1 HEAD`.chomp
|
24
|
+
[revision, dirty_suffix].join('')
|
25
|
+
end
|
26
|
+
|
27
|
+
# @return [Integer] The number of commits on this git branch
|
28
|
+
def commit_count
|
29
|
+
count = `cd #{repo_path} && git rev-list HEAD | wc -l`
|
30
|
+
Integer(count)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String] The abbreviated SHA of the current git revision
|
34
|
+
def short_sha
|
35
|
+
sha = `cd #{repo_path} && git rev-parse --short HEAD`.chomp
|
36
|
+
[sha, dirty_suffix].join('')
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
attr_reader :repo_path
|
42
|
+
|
43
|
+
def dirty?
|
44
|
+
# inspired by http://stackoverflow.com/a/5737794
|
45
|
+
`cd #{repo_path} && test -n "$(git status --porcelain)"`
|
46
|
+
$?.success?
|
47
|
+
end
|
48
|
+
|
49
|
+
def dirty_suffix
|
50
|
+
if dirty?
|
51
|
+
'.dirty'
|
52
|
+
else
|
53
|
+
''
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
60
|
+
# All rights reserved.
|
61
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
62
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
63
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
64
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
65
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
66
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/vara/linter.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Vara
|
4
|
+
class Linter
|
5
|
+
def self.build(metadata_path)
|
6
|
+
new(YAML.load_file(metadata_path))
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(metadata)
|
10
|
+
@metadata = metadata
|
11
|
+
@errors = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def lint!
|
15
|
+
validate_metadata_version
|
16
|
+
fail LintError, errors.join("\n") unless errors.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def validate_metadata_version
|
22
|
+
metadata_version = metadata.fetch('metadata_version')
|
23
|
+
errors << 'metadata_version must be a string' unless metadata_version.is_a?(String)
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :metadata, :errors
|
27
|
+
end
|
28
|
+
|
29
|
+
class LintError < RuntimeError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
34
|
+
# All rights reserved.
|
35
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
36
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
37
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
38
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
39
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
40
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/lib/vara/log.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Vara
|
4
|
+
class << self
|
5
|
+
def log
|
6
|
+
Log.instance
|
7
|
+
end
|
8
|
+
|
9
|
+
def logger_for(progname)
|
10
|
+
LoggerWithProgName.new(progname)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Loggable
|
15
|
+
def log
|
16
|
+
@_releng_instance_log ||= LoggerWithProgName.new(self.class.name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.included(other_module)
|
20
|
+
def other_module.log
|
21
|
+
@_releng_class_log ||= LoggerWithProgName.new(name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Log
|
27
|
+
class << self
|
28
|
+
def instance
|
29
|
+
@instance || fail('Logging attempted without being configured first!')
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_mode!
|
33
|
+
log_path = '/tmp/vara_test.log'
|
34
|
+
File.open(log_path, 'w') {} # empty out the file in a cross-platform-safe way
|
35
|
+
@instance = ::Logger.new(log_path, File::WRONLY | File::APPEND)
|
36
|
+
instance.sev_threshold = ::Logger::DEBUG
|
37
|
+
end
|
38
|
+
|
39
|
+
def stdout_mode!
|
40
|
+
STDOUT.sync = true
|
41
|
+
@instance = ::Logger.new(STDOUT)
|
42
|
+
instance.sev_threshold = ::Logger.const_get(ENV.fetch('LOG_LEVEL', 'INFO'))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class LoggerWithProgName
|
48
|
+
def initialize(progname)
|
49
|
+
@progname = progname
|
50
|
+
end
|
51
|
+
|
52
|
+
%w(debug info warn error fatal).map(&:to_sym).each do |level|
|
53
|
+
define_method(level) do |message|
|
54
|
+
Log.instance.public_send(level, progname) { message }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
attr_reader :progname
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
65
|
+
# All rights reserved.
|
66
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
67
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
68
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
69
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
70
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
71
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'digest/md5'
|
3
|
+
require 'vara/product_metadata'
|
4
|
+
require 'vara/git_inspector'
|
5
|
+
require 'vara/log'
|
6
|
+
require 'vara/version'
|
7
|
+
|
8
|
+
module Vara
|
9
|
+
class Materials
|
10
|
+
include Vara::Loggable
|
11
|
+
|
12
|
+
# @param materials_path [String] Path to a materials YAML file
|
13
|
+
# @return [Vara::Materials] A Materials object based on the content of the file at materials_path
|
14
|
+
def self.from_file(materials_path)
|
15
|
+
new(YAML.load_file(materials_path))
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param product_metadata_path [String] Path to a product's metadata file.
|
19
|
+
# Expected to be in metadata/ folder of a product repo.
|
20
|
+
# @param product_path [String] Path to a built .pivotal file on disk
|
21
|
+
# @return [Vara::Materials]
|
22
|
+
def self.build(product_metadata_path, product_path)
|
23
|
+
product_metadata_dir = File.dirname(File.expand_path(product_metadata_path))
|
24
|
+
repo_dir = File.expand_path(File.join(product_metadata_dir, '..'))
|
25
|
+
repo_name = File.basename(repo_dir)
|
26
|
+
|
27
|
+
product_metadata = ProductMetadata.from_file(product_metadata_path)
|
28
|
+
|
29
|
+
repo_revision = if GitInspector.git_repo?(repo_dir)
|
30
|
+
GitInspector.new(repo_dir).current_revision
|
31
|
+
else
|
32
|
+
log.warn('Creating Materials from a non-git repository')
|
33
|
+
'not_a_git_repository'
|
34
|
+
end
|
35
|
+
|
36
|
+
materials_hash = {
|
37
|
+
'filename' => File.basename(product_path),
|
38
|
+
'md5' => Digest::MD5.file(product_path).hexdigest,
|
39
|
+
'contents' => {
|
40
|
+
'releases' => product_metadata.releases_metadata.map(&:basename),
|
41
|
+
'compiled_packages' => []
|
42
|
+
},
|
43
|
+
'build_info' => {
|
44
|
+
'product_repository' => repo_name,
|
45
|
+
'product_revision' => repo_revision,
|
46
|
+
'vara_version' => Vara::VERSION
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
if product_metadata.explicit_stemcell?
|
51
|
+
materials_hash['contents']['stemcells'] = [product_metadata.stemcell_metadata.basename]
|
52
|
+
|
53
|
+
if product_metadata.has_compiled_packages?
|
54
|
+
materials_hash['contents']['compiled_packages'] << product_metadata.compiled_packages_metadata.basename
|
55
|
+
end
|
56
|
+
else
|
57
|
+
materials_hash['contents']['stemcell_criteria'] = product_metadata.stemcell_criteria
|
58
|
+
end
|
59
|
+
|
60
|
+
new(materials_hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
# @param materials_hash [Hash]
|
64
|
+
def initialize(materials_hash)
|
65
|
+
@hash = materials_hash
|
66
|
+
end
|
67
|
+
|
68
|
+
def save_to(file_path)
|
69
|
+
File.open(file_path, 'w') { |file| YAML.dump(hash, file) }
|
70
|
+
end
|
71
|
+
|
72
|
+
# @return [String] The filename of the .pivotal file
|
73
|
+
def filename
|
74
|
+
hash.fetch('filename')
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String] The listed md5 of the .pivotal file
|
78
|
+
def md5
|
79
|
+
hash.fetch('md5')
|
80
|
+
end
|
81
|
+
|
82
|
+
# @return [<String>] The listed releases contained in the .pivotal file
|
83
|
+
def releases
|
84
|
+
contents.fetch('releases')
|
85
|
+
end
|
86
|
+
|
87
|
+
# @return [<String>] The listed stemcells contained in the .pivotal file
|
88
|
+
def stemcells
|
89
|
+
contents['stemcells']
|
90
|
+
end
|
91
|
+
|
92
|
+
def stemcell_criteria
|
93
|
+
contents['stemcell_criteria']
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [<String>] The listed compiled packages contained in the .pivotal file
|
97
|
+
def compiled_packages
|
98
|
+
contents.fetch('compiled_packages')
|
99
|
+
end
|
100
|
+
|
101
|
+
# @return [String] The name of the product repository
|
102
|
+
def product_repository
|
103
|
+
build_info.fetch('product_repository')
|
104
|
+
end
|
105
|
+
|
106
|
+
# @return [String] The git revision of the product repository used to build the .pivotal
|
107
|
+
def product_revision
|
108
|
+
build_info.fetch('product_revision')
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [String] the version of vara used to build the described .pivotal (will be >= 0.7.1 or 'unknown')
|
112
|
+
def vara_version
|
113
|
+
build_info.fetch('vara_version', 'unknown')
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
attr_reader :hash
|
119
|
+
|
120
|
+
# @return [Hash]
|
121
|
+
def contents
|
122
|
+
hash.fetch('contents')
|
123
|
+
end
|
124
|
+
|
125
|
+
# @return [Hash]
|
126
|
+
def build_info
|
127
|
+
hash.fetch('build_info')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
133
|
+
# All rights reserved.
|
134
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
135
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
136
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
137
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
138
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
139
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'vara/log'
|
2
|
+
|
3
|
+
module Vara
|
4
|
+
class MD5Creator
|
5
|
+
include Loggable
|
6
|
+
|
7
|
+
def self.md5(path)
|
8
|
+
expanded_path = File.expand_path(path)
|
9
|
+
md5_file = "#{expanded_path}.md5"
|
10
|
+
|
11
|
+
md5_string = Digest::MD5.file(expanded_path).hexdigest
|
12
|
+
|
13
|
+
log.warn("File #{md5_file} already exists, overwriting!") if File.exist?(md5_file)
|
14
|
+
File.open(md5_file, 'w') do |file|
|
15
|
+
file.write(md5_string)
|
16
|
+
log.info("Created md5 file: #{md5_file} with contents #{md5_string}")
|
17
|
+
end
|
18
|
+
|
19
|
+
md5_file
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Copyright (c) 2014-2015 Pivotal Software, Inc.
|
25
|
+
# All rights reserved.
|
26
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
27
|
+
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
28
|
+
# PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
29
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
30
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
31
|
+
# USE OR OTHER DEALINGS IN THE SOFTWARE.
|