omnibus 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/.yardopts +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +9 -0
- data/LICENSE +201 -0
- data/NOTICE +9 -0
- data/README.md +186 -0
- data/Rakefile +7 -0
- data/bin/makeself-header.sh +401 -0
- data/bin/makeself.sh +407 -0
- data/bin/omnibus +11 -0
- data/lib/omnibus.rb +280 -0
- data/lib/omnibus/build_version.rb +281 -0
- data/lib/omnibus/builder.rb +323 -0
- data/lib/omnibus/clean_tasks.rb +30 -0
- data/lib/omnibus/cli.rb +35 -0
- data/lib/omnibus/cli/application.rb +136 -0
- data/lib/omnibus/cli/base.rb +112 -0
- data/lib/omnibus/cli/build.rb +66 -0
- data/lib/omnibus/cli/cache.rb +60 -0
- data/lib/omnibus/config.rb +186 -0
- data/lib/omnibus/exceptions.rb +54 -0
- data/lib/omnibus/fetcher.rb +184 -0
- data/lib/omnibus/fetchers.rb +22 -0
- data/lib/omnibus/fetchers/git_fetcher.rb +212 -0
- data/lib/omnibus/fetchers/net_fetcher.rb +191 -0
- data/lib/omnibus/fetchers/path_fetcher.rb +65 -0
- data/lib/omnibus/fetchers/s3_cache_fetcher.rb +42 -0
- data/lib/omnibus/health_check.rb +260 -0
- data/lib/omnibus/library.rb +70 -0
- data/lib/omnibus/overrides.rb +69 -0
- data/lib/omnibus/project.rb +566 -0
- data/lib/omnibus/reports.rb +99 -0
- data/lib/omnibus/s3_cacher.rb +136 -0
- data/lib/omnibus/software.rb +430 -0
- data/lib/omnibus/templates/Berksfile.erb +3 -0
- data/lib/omnibus/templates/Gemfile.erb +4 -0
- data/lib/omnibus/templates/README.md.erb +102 -0
- data/lib/omnibus/templates/Vagrantfile.erb +95 -0
- data/lib/omnibus/templates/gitignore.erb +8 -0
- data/lib/omnibus/templates/omnibus.rb.example.erb +5 -0
- data/lib/omnibus/templates/package_scripts/makeselfinst.erb +27 -0
- data/lib/omnibus/templates/package_scripts/postinst.erb +17 -0
- data/lib/omnibus/templates/package_scripts/postrm.erb +9 -0
- data/lib/omnibus/templates/project.rb.erb +21 -0
- data/lib/omnibus/templates/software/c-example.rb.erb +42 -0
- data/lib/omnibus/templates/software/erlang-example.rb.erb +38 -0
- data/lib/omnibus/templates/software/ruby-example.rb.erb +24 -0
- data/lib/omnibus/util.rb +61 -0
- data/lib/omnibus/version.rb +20 -0
- data/omnibus.gemspec +34 -0
- data/spec/build_version_spec.rb +228 -0
- data/spec/data/overrides/bad_line.overrides +3 -0
- data/spec/data/overrides/good.overrides +5 -0
- data/spec/data/overrides/with_dupes.overrides +4 -0
- data/spec/data/software/erchef.rb +40 -0
- data/spec/overrides_spec.rb +114 -0
- data/spec/software_spec.rb +71 -0
- data/spec/spec_helper.rb +28 -0
- metadata +239 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Omnibus
|
19
|
+
|
20
|
+
module Reports
|
21
|
+
extend self
|
22
|
+
|
23
|
+
|
24
|
+
PADDING = 3
|
25
|
+
|
26
|
+
# Determine how wide a column should be, taking into account both
|
27
|
+
# the column name as well as all data in that column. If no data
|
28
|
+
# will be stored in the column, the width is 0 (i.e., nothing
|
29
|
+
# should be printed, not even the column header)
|
30
|
+
def column_width(items, column_name)
|
31
|
+
widest_item = items.max{|a,b| a.size <=> b.size}
|
32
|
+
if widest_item
|
33
|
+
widest = (widest_item.size >= column_name.size) ? widest_item : column_name
|
34
|
+
widest.size + PADDING
|
35
|
+
else
|
36
|
+
0
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def non_nil_values(hashes, selector_key)
|
41
|
+
hashes.map{|v| v[selector_key]}.compact
|
42
|
+
end
|
43
|
+
|
44
|
+
def pretty_version_map(project)
|
45
|
+
out = ""
|
46
|
+
version_map = Omnibus.library.version_map(project)
|
47
|
+
|
48
|
+
|
49
|
+
# Pull out data to print out
|
50
|
+
versions = non_nil_values(version_map.values, :version)
|
51
|
+
guids = non_nil_values(version_map.values, :version_guid)
|
52
|
+
|
53
|
+
# We only want the versions that have truly been overridden;
|
54
|
+
# because we want to output a column only if something was
|
55
|
+
# overridden, but nothing if no packages were changed
|
56
|
+
overridden_versions = non_nil_values(version_map.values.select{|v| v[:overridden]},
|
57
|
+
:given_version)
|
58
|
+
|
59
|
+
|
60
|
+
# Determine how wide the printed table columns need to be
|
61
|
+
name_width = column_width(version_map.keys, "Component")
|
62
|
+
version_width = column_width(versions, "Installed Version")
|
63
|
+
guid_width = column_width(guids, "Version GUID")
|
64
|
+
override_width = column_width(overridden_versions, "Overridden From")
|
65
|
+
|
66
|
+
total_width = name_width + version_width + guid_width + override_width
|
67
|
+
divider = "-" * total_width
|
68
|
+
|
69
|
+
# Print out the column headers
|
70
|
+
out << "Component".ljust(name_width)
|
71
|
+
out << "Installed Version".ljust(version_width)
|
72
|
+
out << "Version GUID".ljust(guid_width)
|
73
|
+
# Only print out column if something was overridden
|
74
|
+
out << "Overridden From".ljust(override_width) if override_width > 0
|
75
|
+
out << "\n"
|
76
|
+
out << divider << "\n"
|
77
|
+
|
78
|
+
# Print out the table body
|
79
|
+
version_map.keys.sort.each do |name|
|
80
|
+
version = version_map[name][:version]
|
81
|
+
version_guid = version_map[name][:version_guid]
|
82
|
+
|
83
|
+
given_version = version_map[name][:given_version]
|
84
|
+
overridden = version_map[name][:overridden]
|
85
|
+
|
86
|
+
out << "#{name}".ljust(name_width)
|
87
|
+
out << version.to_s.ljust(version_width)
|
88
|
+
out << version_guid.to_s.ljust(guid_width) if version_guid
|
89
|
+
# Only print out column if something was overridden
|
90
|
+
out << given_version.ljust(override_width) if overridden
|
91
|
+
out << "\n"
|
92
|
+
end
|
93
|
+
out
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'fileutils'
|
19
|
+
require 'uber-s3'
|
20
|
+
require 'omnibus/fetchers'
|
21
|
+
|
22
|
+
module Omnibus
|
23
|
+
|
24
|
+
|
25
|
+
module SoftwareS3URLs
|
26
|
+
|
27
|
+
class InsufficientSpecification < ArgumentError
|
28
|
+
end
|
29
|
+
|
30
|
+
def config
|
31
|
+
Omnibus.config
|
32
|
+
end
|
33
|
+
|
34
|
+
def url_for(software)
|
35
|
+
"http://#{config.s3_bucket}.s3.amazonaws.com/#{key_for_package(software)}"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def key_for_package(package)
|
41
|
+
package.name or raise InsufficientSpecification, "Software must have a name to cache it in S3 (#{package.inspect})"
|
42
|
+
package.version or raise InsufficientSpecification, "Software must set a version to cache it in S3 (#{package.inspect})"
|
43
|
+
package.checksum or raise InsufficientSpecification, "Software must specify a checksum (md5) to cache it in S3 (#{package.inspect})"
|
44
|
+
"#{package.name}-#{package.version}-#{package.checksum}"
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class S3Cache
|
50
|
+
|
51
|
+
include SoftwareS3URLs
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
unless config.s3_bucket && config.s3_access_key && config.s3_secret_key
|
55
|
+
raise InvalidS3Configuration.new(config.s3_bucket, config.s3_access_key, config.s3_secret_key)
|
56
|
+
end
|
57
|
+
@client = UberS3.new(
|
58
|
+
:access_key => config.s3_access_key,
|
59
|
+
:secret_access_key => config.s3_secret_key,
|
60
|
+
:bucket => config.s3_bucket,
|
61
|
+
:adaper => :net_http
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def log(msg)
|
66
|
+
puts "[S3 Cacher] #{msg}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def config
|
70
|
+
Omnibus.config
|
71
|
+
end
|
72
|
+
|
73
|
+
def list
|
74
|
+
existing_keys = list_by_key
|
75
|
+
tarball_software.select {|s| existing_keys.include?(key_for_package(s))}
|
76
|
+
end
|
77
|
+
|
78
|
+
def list_by_key
|
79
|
+
bucket.objects('/').map(&:key)
|
80
|
+
end
|
81
|
+
|
82
|
+
def missing
|
83
|
+
already_cached = list_by_key
|
84
|
+
tarball_software.delete_if {|s| already_cached.include?(key_for_package(s))}
|
85
|
+
end
|
86
|
+
|
87
|
+
def tarball_software
|
88
|
+
Omnibus.library.select {|s| s.source && s.source.key?(:url)}
|
89
|
+
end
|
90
|
+
|
91
|
+
def populate
|
92
|
+
missing.each do |software|
|
93
|
+
fetch(software)
|
94
|
+
|
95
|
+
key = key_for_package(software)
|
96
|
+
content = IO.read(software.project_file)
|
97
|
+
|
98
|
+
log "Uploading #{software.project_file} as #{config.s3_bucket}/#{key}"
|
99
|
+
@client.store(key, content, :access => :public_read, :content_md5 => software.checksum)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def fetch_missing
|
104
|
+
missing.each do |software|
|
105
|
+
fetch(software)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def ensure_cache_dir
|
112
|
+
FileUtils.mkdir_p(config.cache_dir)
|
113
|
+
end
|
114
|
+
|
115
|
+
def fetch(software)
|
116
|
+
log "Fetching #{software.name}"
|
117
|
+
fetcher = Fetcher.without_caching_for(software)
|
118
|
+
if fetcher.fetch_required?
|
119
|
+
fetcher.download
|
120
|
+
fetcher.verify_checksum!
|
121
|
+
else
|
122
|
+
log "Cached copy up to date, skipping."
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def bucket
|
127
|
+
@bucket ||= begin
|
128
|
+
b = UberS3::Bucket.new(@client, @client.bucket)
|
129
|
+
# creating the bucket is idempotent, make sure it's created:
|
130
|
+
@client.connection.put("/")
|
131
|
+
b
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,430 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2012 Opscode, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'digest/md5'
|
19
|
+
require 'mixlib/shellout'
|
20
|
+
require 'net/ftp'
|
21
|
+
require 'net/http'
|
22
|
+
require 'net/https'
|
23
|
+
require 'uri'
|
24
|
+
|
25
|
+
require 'omnibus/fetcher'
|
26
|
+
require 'omnibus/builder'
|
27
|
+
require 'omnibus/config'
|
28
|
+
|
29
|
+
require 'rake'
|
30
|
+
|
31
|
+
module Omnibus
|
32
|
+
|
33
|
+
# Omnibus software DSL reader
|
34
|
+
class Software
|
35
|
+
include Rake::DSL
|
36
|
+
|
37
|
+
NULL_ARG = Object.new
|
38
|
+
|
39
|
+
# It appears that this is not used
|
40
|
+
attr_reader :builder
|
41
|
+
|
42
|
+
# @todo Why do we apparently use two different ways of
|
43
|
+
# implementing what are effectively the same DSL methods? Compare
|
44
|
+
# with Omnibus::Project.
|
45
|
+
attr_reader :description
|
46
|
+
|
47
|
+
# @todo This doesn't appear to be used at all
|
48
|
+
attr_reader :fetcher
|
49
|
+
|
50
|
+
attr_reader :project
|
51
|
+
|
52
|
+
attr_reader :given_version
|
53
|
+
attr_reader :override_version
|
54
|
+
|
55
|
+
def self.load(filename, project, overrides={})
|
56
|
+
new(IO.read(filename), filename, project, overrides)
|
57
|
+
end
|
58
|
+
|
59
|
+
# @param io [String]
|
60
|
+
# @param filename [String]
|
61
|
+
# @param project [???] Is this a string or an Omnibus::Project?
|
62
|
+
# @param overrides [Hash]
|
63
|
+
#
|
64
|
+
# @see Omnibus::Overrides
|
65
|
+
#
|
66
|
+
# @todo See comment on {Omnibus::NullBuilder}
|
67
|
+
# @todo does `filename` need to be absolute, or does it matter?
|
68
|
+
# @ @todo Any reason to not have this just take a filename,
|
69
|
+
# project, and override hash directly? That is, why io AND a
|
70
|
+
# filename, if the filename can always get you the contents you
|
71
|
+
# need anyway?
|
72
|
+
def initialize(io, filename, project, overrides={})
|
73
|
+
@given_version = nil
|
74
|
+
@override_version = nil
|
75
|
+
@name = nil
|
76
|
+
@description = nil
|
77
|
+
@source = nil
|
78
|
+
@relative_path = nil
|
79
|
+
@source_uri = nil
|
80
|
+
@source_config = filename
|
81
|
+
@project = project
|
82
|
+
@always_build = false
|
83
|
+
|
84
|
+
# Seems like this should just be Builder.new(self) instead
|
85
|
+
@builder = NullBuilder.new(self)
|
86
|
+
|
87
|
+
@dependencies = Array.new
|
88
|
+
instance_eval(io, filename, 0)
|
89
|
+
|
90
|
+
# Set override information after the DSL file has been consumed
|
91
|
+
@override_version = overrides[name]
|
92
|
+
|
93
|
+
render_tasks
|
94
|
+
end
|
95
|
+
|
96
|
+
def name(val=NULL_ARG)
|
97
|
+
@name = val unless val.equal?(NULL_ARG)
|
98
|
+
@name
|
99
|
+
end
|
100
|
+
|
101
|
+
def description(val)
|
102
|
+
@description = val
|
103
|
+
end
|
104
|
+
|
105
|
+
# Add an Omnibus software dependency.
|
106
|
+
#
|
107
|
+
# @param val [String] the name of a Software dependency
|
108
|
+
# @return [void]
|
109
|
+
def dependency(val)
|
110
|
+
@dependencies << val
|
111
|
+
end
|
112
|
+
|
113
|
+
# Set or retrieve the list of software dependencies for this
|
114
|
+
# project. As this is a DSL method, only pass the names of
|
115
|
+
# software components, not {Omnibus::Software} objects.
|
116
|
+
#
|
117
|
+
# These is the software that comprises your project, and is
|
118
|
+
# distinct from runtime dependencies.
|
119
|
+
#
|
120
|
+
# @note This will reinitialize the internal depdencies Array
|
121
|
+
# and overwrite any dependencies that may have been set using
|
122
|
+
# {#dependency}.
|
123
|
+
#
|
124
|
+
# @param val [Array<String>] a list of names of Software components
|
125
|
+
# @return [Array<String>]
|
126
|
+
def dependencies(val=NULL_ARG)
|
127
|
+
@dependencies = val unless val.equal?(NULL_ARG)
|
128
|
+
@dependencies
|
129
|
+
end
|
130
|
+
|
131
|
+
# Set or retrieve the source for the software
|
132
|
+
#
|
133
|
+
# @param val [Hash<Symbol, String>] a single key/pair that defines
|
134
|
+
# the kind of source and a path specifier
|
135
|
+
# @option val [String] :git (nil) a Git URL
|
136
|
+
# @option val [String] :url (nil) a general URL
|
137
|
+
# @option val [String] :path (nil) a fully-qualified local file system path
|
138
|
+
#
|
139
|
+
# @todo Consider changing this to accept two arguments instead
|
140
|
+
# @todo This should throw an error if an invalid key is given, or
|
141
|
+
# if more than one pair is given, or if no source value is ever
|
142
|
+
# set.
|
143
|
+
def source(val=NULL_ARG)
|
144
|
+
@source = val unless val.equal?(NULL_ARG)
|
145
|
+
@source
|
146
|
+
end
|
147
|
+
|
148
|
+
# Set a version from a software descriptor file, or receive the
|
149
|
+
# effective version, taking into account any override information
|
150
|
+
# (if set)
|
151
|
+
def version(val=NULL_ARG)
|
152
|
+
@given_version = val unless val.equal?(NULL_ARG)
|
153
|
+
@override_version || @given_version
|
154
|
+
end
|
155
|
+
|
156
|
+
# Was this software version overridden externally, relative to the
|
157
|
+
# version declared within the software DSL file?
|
158
|
+
#
|
159
|
+
# @return [Boolean]
|
160
|
+
def overridden?
|
161
|
+
@override_version && (@override_version != @given_version)
|
162
|
+
end
|
163
|
+
|
164
|
+
# @todo see comments on {Omnibus::Fetcher#without_caching_for}
|
165
|
+
def version_guid
|
166
|
+
Fetcher.for(self).version_guid
|
167
|
+
end
|
168
|
+
|
169
|
+
# @todo Define as a delegator
|
170
|
+
def build_version
|
171
|
+
@project.build_version
|
172
|
+
end
|
173
|
+
|
174
|
+
# @todo Judging by existing usage, this should sensibly default to
|
175
|
+
# the name of the software, since that's what it effectively does down in #project_dir
|
176
|
+
def relative_path(val)
|
177
|
+
@relative_path = val
|
178
|
+
end
|
179
|
+
|
180
|
+
# @todo Code smell... this only has meaning if the software was
|
181
|
+
# defined with a :uri, and this is only used in
|
182
|
+
# {Omnibus::NetFetcher}. This responsibility is distributed
|
183
|
+
# across two classes, one of which is a specific interface
|
184
|
+
# implementation
|
185
|
+
# @todo Why the caching of the URI?
|
186
|
+
def source_uri
|
187
|
+
@source_uri ||= URI(@source[:url])
|
188
|
+
end
|
189
|
+
|
190
|
+
# @param val [Boolean]
|
191
|
+
# @return void
|
192
|
+
#
|
193
|
+
# @todo Doesn't necessarily need to be a Boolean if #always_build?
|
194
|
+
# uses !! operator
|
195
|
+
def always_build(val)
|
196
|
+
@always_build = val
|
197
|
+
end
|
198
|
+
|
199
|
+
# @return [Boolean]
|
200
|
+
def always_build?
|
201
|
+
# Should do !!(@always_build)
|
202
|
+
@always_build
|
203
|
+
end
|
204
|
+
|
205
|
+
# @todo Code smell... this only has meaning if the software was
|
206
|
+
# defined with a :uri, and this is only used in
|
207
|
+
# {Omnibus::NetFetcher}. This responsibility is distributed
|
208
|
+
# across two classes, one of which is a specific interface
|
209
|
+
# implementation
|
210
|
+
def checksum
|
211
|
+
@source[:md5]
|
212
|
+
end
|
213
|
+
|
214
|
+
# @todo Should this ever be legitimately used in the DSL? It
|
215
|
+
# seems that that facility shouldn't be provided, and thus this
|
216
|
+
# should be made a private function (if it even really needs to
|
217
|
+
# exist at all).
|
218
|
+
def config
|
219
|
+
Omnibus.config
|
220
|
+
end
|
221
|
+
|
222
|
+
# @!group Directory Accessors
|
223
|
+
|
224
|
+
def source_dir
|
225
|
+
config.source_dir
|
226
|
+
end
|
227
|
+
|
228
|
+
def cache_dir
|
229
|
+
config.cache_dir
|
230
|
+
end
|
231
|
+
|
232
|
+
# The directory that the software will be built in
|
233
|
+
#
|
234
|
+
# @return [String] an absolute filesystem path
|
235
|
+
def build_dir
|
236
|
+
"#{config.build_dir}/#{camel_case_path(install_dir)}"
|
237
|
+
end
|
238
|
+
|
239
|
+
# @todo Why the different name (i.e. *_dir instead of *_path, or
|
240
|
+
# vice versa?) Given the patterns that are being set up
|
241
|
+
# elsewhere, this is just confusing inconsistency.
|
242
|
+
def install_dir
|
243
|
+
@project.install_path
|
244
|
+
end
|
245
|
+
|
246
|
+
# @!endgroup
|
247
|
+
|
248
|
+
# @todo It seems like this isn't used, and if it were, it should
|
249
|
+
# probably be part of Opscode::Builder instead
|
250
|
+
def max_build_jobs
|
251
|
+
if OHAI.cpu == nil
|
252
|
+
2
|
253
|
+
else
|
254
|
+
OHAI.cpu[:total] + 1
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# @todo See comments for {#source_uri}... same applies here. If
|
259
|
+
# this is called in a non-source-software context, bad things will
|
260
|
+
# happen.
|
261
|
+
def project_file
|
262
|
+
filename = source_uri.path.split('/').last
|
263
|
+
"#{cache_dir}/#{filename}"
|
264
|
+
end
|
265
|
+
|
266
|
+
# @todo this would be simplified and clarified if @relative_path
|
267
|
+
# defaulted to @name... see the @todo tag for #relative_path
|
268
|
+
# @todo Move this up with the other *_dir methods for better
|
269
|
+
# logical grouping
|
270
|
+
def project_dir
|
271
|
+
@relative_path ? "#{source_dir}/#{@relative_path}" : "#{source_dir}/#{@name}"
|
272
|
+
end
|
273
|
+
|
274
|
+
# @todo all the *_file methods should be next to each other for
|
275
|
+
# better logical grouping
|
276
|
+
def manifest_file
|
277
|
+
manifest_file_from_name(@name)
|
278
|
+
end
|
279
|
+
|
280
|
+
# @todo Seems like this should be a private method, since it's
|
281
|
+
# just used internally
|
282
|
+
def manifest_file_from_name(software_name)
|
283
|
+
"#{build_dir}/#{software_name}.manifest"
|
284
|
+
end
|
285
|
+
|
286
|
+
# The name of the sentinel file that marks the most recent fetch
|
287
|
+
# time of the software
|
288
|
+
#
|
289
|
+
# @return [String] an absolute path
|
290
|
+
#
|
291
|
+
# @see Omnibus::Fetcher
|
292
|
+
# @todo seems like this should be a private
|
293
|
+
# method, since it's an implementation detail.
|
294
|
+
def fetch_file
|
295
|
+
"#{build_dir}/#{@name}.fetch"
|
296
|
+
end
|
297
|
+
|
298
|
+
# @todo This is actually "snake case", not camel case
|
299
|
+
# @todo this should be a private method
|
300
|
+
def camel_case_path(project_path)
|
301
|
+
path = project_path.dup
|
302
|
+
# split the path and remmove and empty strings
|
303
|
+
if platform == 'windows'
|
304
|
+
path.sub!(":", "")
|
305
|
+
parts = path.split("\\") - [""]
|
306
|
+
parts.join("_")
|
307
|
+
else
|
308
|
+
parts = path.split("/") - [""]
|
309
|
+
parts.join("_")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Define a series of {Omnibus::Builder} DSL commands that are
|
314
|
+
# required to successfully build the software.
|
315
|
+
#
|
316
|
+
# @param block [block] a block of build commands
|
317
|
+
# @return void
|
318
|
+
#
|
319
|
+
# @see Omnibus::Builder
|
320
|
+
#
|
321
|
+
# @todo Not quite sure the proper way to document a "block"
|
322
|
+
# parameter in Yard
|
323
|
+
# @todo Seems like this renders the setting of @builder in the
|
324
|
+
# initializer moot
|
325
|
+
# @todo Rename this to something like "build_commands", since it
|
326
|
+
# doesn't actually do any building
|
327
|
+
def build(&block)
|
328
|
+
@builder = Builder.new(self, &block)
|
329
|
+
end
|
330
|
+
|
331
|
+
# Returns the platform of the machine on which Omnibus is running,
|
332
|
+
# as determined by Ohai.
|
333
|
+
#
|
334
|
+
# @return [String]
|
335
|
+
def platform
|
336
|
+
OHAI.platform
|
337
|
+
end
|
338
|
+
|
339
|
+
# Return the architecture of the machine, as determined by Ohai.
|
340
|
+
# @return [String] Either "sparc" or "intel", as appropriate
|
341
|
+
# @todo Is this used? Doesn't appear to be...
|
342
|
+
def architecture
|
343
|
+
OHAI.kernel['machine'] =~ /sun/ ? "sparc" : "intel"
|
344
|
+
end
|
345
|
+
|
346
|
+
private
|
347
|
+
|
348
|
+
# @todo What?!
|
349
|
+
# @todo It seems that this is not used... remove it
|
350
|
+
# @deprecated Use something else (?)
|
351
|
+
def command(*args)
|
352
|
+
raise "Method Moved."
|
353
|
+
end
|
354
|
+
|
355
|
+
def execute_build(fetcher)
|
356
|
+
fetcher.clean
|
357
|
+
@builder.build
|
358
|
+
touch manifest_file
|
359
|
+
end
|
360
|
+
|
361
|
+
def render_tasks
|
362
|
+
namespace "projects:#{@project.name}" do
|
363
|
+
namespace :software do
|
364
|
+
fetcher = Fetcher.for(self)
|
365
|
+
|
366
|
+
#
|
367
|
+
# set up inter-project dependencies
|
368
|
+
#
|
369
|
+
(@dependencies - [@name]).uniq.each do |dep|
|
370
|
+
task @name => dep
|
371
|
+
file manifest_file => manifest_file_from_name(dep)
|
372
|
+
end
|
373
|
+
|
374
|
+
directory source_dir
|
375
|
+
directory cache_dir
|
376
|
+
directory build_dir
|
377
|
+
directory project_dir
|
378
|
+
namespace @name do
|
379
|
+
task :fetch => [ build_dir, source_dir, cache_dir, project_dir ] do
|
380
|
+
if !File.exists?(fetch_file) || fetcher.fetch_required?
|
381
|
+
# force build to run if we need to do an updated fetch
|
382
|
+
fetcher.fetch
|
383
|
+
touch fetch_file
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
task :build => :fetch do
|
388
|
+
if !always_build? && uptodate?(manifest_file, [fetch_file])
|
389
|
+
# if any direct deps have been built for any reason, we will need to
|
390
|
+
# clean/build ourselves
|
391
|
+
(@dependencies - [@name]).uniq.each do |dep|
|
392
|
+
unless uptodate?(manifest_file, [manifest_file_from_name(dep)])
|
393
|
+
execute_build(fetcher)
|
394
|
+
break
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
else
|
399
|
+
# if fetch has occurred, or the component is configured to
|
400
|
+
# always build, do a clean and build.
|
401
|
+
execute_build(fetcher)
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
#
|
407
|
+
# make the manifest file dependent on the latest file in the
|
408
|
+
# source tree in order to shrink the multi-thousand-node
|
409
|
+
# dependency graph that Rake was generating
|
410
|
+
#
|
411
|
+
latest_file = FileList["#{project_dir}/**/*"].sort { |a,b|
|
412
|
+
File.mtime(a) <=> File.mtime(b)
|
413
|
+
}.last
|
414
|
+
|
415
|
+
file manifest_file => (file latest_file)
|
416
|
+
|
417
|
+
file fetch_file => "#{name}:fetch"
|
418
|
+
file manifest_file => "#{name}:build"
|
419
|
+
|
420
|
+
file fetch_file => (file @source_config)
|
421
|
+
file manifest_file => (file fetch_file)
|
422
|
+
|
423
|
+
desc "fetch and build #{@name} for #{@project.name}"
|
424
|
+
task @name => manifest_file
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
|
429
|
+
end
|
430
|
+
end
|