omnibus 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.
- 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
|