omnibus-sonian 1.2.0.1

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