class Omnibus::Software

Omnibus software DSL reader

Constants

NULL_ARG

Attributes

builder[R]

It appears that this is not used

description[R]

@todo Why do we apparently use two different ways of

implementing what are effectively the same DSL methods?  Compare
with Omnibus::Project.
fetcher[R]

@todo This doesn’t appear to be used at all

given_version[R]
override_version[R]
project[R]
whitelist_files[R]

Public Class Methods

load(filename, project, overrides={}) click to toggle source
# File lib/omnibus/software.rb, line 56
def self.load(filename, project, overrides={})
  new(IO.read(filename), filename, project, overrides)
end
new(io, filename, project, overrides={}) click to toggle source

@param io [String] @param filename [String] @param project [???] Is this a string or an Omnibus::Project? @param overrides [Hash]

@see Omnibus::Overrides

@todo See comment on {Omnibus::NullBuilder} @todo does ‘filename` need to be absolute, or does it matter? @ @todo Any reason to not have this just take a filename,

project, and override hash directly?  That is, why io AND a
filename, if the filename can always get you the contents you
need anyway?
# File lib/omnibus/software.rb, line 73
def initialize(io, filename, project, overrides={})
  @given_version    = nil
  @override_version = nil
  @name             = nil
  @description      = nil
  @source           = nil
  @relative_path    = nil
  @source_uri       = nil
  @source_config    = filename
  @project          = project
  @always_build     = false

  # Seems like this should just be Builder.new(self) instead
  @builder = NullBuilder.new(self)

  @dependencies = Array.new
  @whitelist_files = Array.new
  instance_eval(io, filename, 0)

  # Set override information after the DSL file has been consumed
  @override_version = overrides[name]

  render_tasks
end

Public Instance Methods

always_build(val) click to toggle source

@param val [Boolean] @return void

@todo Doesn’t necessarily need to be a Boolean if always_build?

uses !! operator
# File lib/omnibus/software.rb, line 206
def always_build(val)
  @always_build = val
end
always_build?() click to toggle source

@return [Boolean]

# File lib/omnibus/software.rb, line 211
def always_build?
  # Should do !!(@always_build)
  @always_build
end
architecture() click to toggle source

Return the architecture of the machine, as determined by Ohai. @return [String] Either “sparc” or “intel”, as appropriate @todo Is this used? Doesn’t appear to be…

# File lib/omnibus/software.rb, line 353
def architecture
  OHAI.kernel['machine'] =~ /sun/ ? "sparc" : "intel"
end
build(&block) click to toggle source

Define a series of {Omnibus::Builder} DSL commands that are required to successfully build the software.

@param block [block] a block of build commands @return void

@see Omnibus::Builder

@todo Not quite sure the proper way to document a “block”

parameter in Yard

@todo Seems like this renders the setting of @builder in the

initializer moot

@todo Rename this to something like “build_commands”, since it

doesn't actually do any building
# File lib/omnibus/software.rb, line 338
def build(&block)
  @builder = Builder.new(self, &block)
end
build_dir() click to toggle source

The directory that the software will be built in

@return [String] an absolute filesystem path

# File lib/omnibus/software.rb, line 246
def build_dir
  "#{config.build_dir}/#{@project.name}"
end
build_version() click to toggle source

@todo Define as a delegator

# File lib/omnibus/software.rb, line 181
def build_version
  @project.build_version
end
cache_dir() click to toggle source
# File lib/omnibus/software.rb, line 239
def cache_dir
  config.cache_dir
end
camel_case_path(project_path) click to toggle source

@todo This is actually “snake case”, not camel case @todo this should be a private method

# File lib/omnibus/software.rb, line 311
def camel_case_path(project_path)
  path = project_path.dup
  # split the path and remmove and empty strings
  if platform == 'windows'
    path.sub!(":", "")
    parts = path.split("\\") - [""]
    parts.join("_")
  else
    parts = path.split("/") - [""]
    parts.join("_")
  end
end
checksum() click to toggle source

@todo Code smell… this only has meaning if the software was

defined with a :uri, and this is only used in
{Omnibus::NetFetcher}.  This responsibility is distributed
across two classes, one of which is a specific interface
implementation
# File lib/omnibus/software.rb, line 221
def checksum
  @source[:md5]
end
config() click to toggle source

@todo Should this ever be legitimately used in the DSL? It

seems that that facility shouldn't be provided, and thus this
should be made a private function (if it even really needs to
exist at all).
# File lib/omnibus/software.rb, line 229
def config
  Omnibus.config
end
dependencies(val=NULL_ARG) click to toggle source

Set or retrieve the list of software dependencies for this project. As this is a DSL method, only pass the names of software components, not {Omnibus::Software} objects.

These is the software that comprises your project, and is distinct from runtime dependencies.

@note This will reinitialize the internal depdencies Array

and overwrite any dependencies that may have been set using
{#dependency}.

@param val [Array<String>] a list of names of Software components @return [Array<String>]

# File lib/omnibus/software.rb, line 128
def dependencies(val=NULL_ARG)
  @dependencies = val unless val.equal?(NULL_ARG)
  @dependencies
end
dependency(val) click to toggle source

Add an Omnibus software dependency.

@param val [String] the name of a Software dependency @return [void]

# File lib/omnibus/software.rb, line 111
def dependency(val)
  @dependencies << val
end
fetch_file() click to toggle source

The name of the sentinel file that marks the most recent fetch time of the software

@return [String] an absolute path

@see Omnibus::Fetcher @todo seems like this should be a private

method, since it's an implementation detail.
# File lib/omnibus/software.rb, line 305
def fetch_file
  "#{build_dir}/#{@name}.fetch"
end
install_dir() click to toggle source

@todo Why the different name (i.e. *_dir instead of *_path, or

vice versa?)  Given the patterns that are being set up
elsewhere, this is just confusing inconsistency.
# File lib/omnibus/software.rb, line 253
def install_dir
  @project.install_path
end
manifest_file() click to toggle source

@todo all the *_file methods should be next to each other for

better logical grouping
# File lib/omnibus/software.rb, line 287
def manifest_file
  manifest_file_from_name(@name)
end
manifest_file_from_name(software_name) click to toggle source

@todo Seems like this should be a private method, since it’s

just used internally
# File lib/omnibus/software.rb, line 293
def manifest_file_from_name(software_name)
  "#{build_dir}/#{software_name}.manifest"
end
max_build_jobs() click to toggle source

@todo It seems like this isn’t used, and if it were, it should probably be part of Opscode::Builder instead

# File lib/omnibus/software.rb, line 261
def max_build_jobs
  if OHAI.cpu && OHAI.cpu[:total] && OHAI.cpu[:total].to_s =~ /^\d+$/
    OHAI.cpu[:total].to_i + 1
  else
    3
  end
end
name(val=NULL_ARG) click to toggle source
# File lib/omnibus/software.rb, line 98
def name(val=NULL_ARG)
  @name = val unless val.equal?(NULL_ARG)
  @name
end
overridden?() click to toggle source

Was this software version overridden externally, relative to the version declared within the software DSL file?

@return [Boolean]

# File lib/omnibus/software.rb, line 171
def overridden?
  @override_version && (@override_version != @given_version)
end
platform() click to toggle source

Returns the platform of the machine on which Omnibus is running, as determined by Ohai.

@return [String]

# File lib/omnibus/software.rb, line 346
def platform
  OHAI.platform
end
project_dir() click to toggle source

@todo this would be simplified and clarified if @relative_path

defaulted to @name... see the @todo tag for #relative_path

@todo Move this up with the other *_dir methods for better

logical grouping
# File lib/omnibus/software.rb, line 281
def project_dir
  @relative_path ? "#{source_dir}/#{@relative_path}" : "#{source_dir}/#{@name}"
end
project_file() click to toggle source

@todo See comments for {#source_uri}… same applies here. If

this is called in a non-source-software context, bad things will
happen.
# File lib/omnibus/software.rb, line 272
def project_file
  filename = source_uri.path.split('/').last
  "#{cache_dir}/#{filename}"
end
relative_path(val) click to toggle source

@todo Judging by existing usage, this should sensibly default to

the name of the software, since that's what it effectively does down in #project_dir
# File lib/omnibus/software.rb, line 187
def relative_path(val)
  @relative_path = val
end
source(val=NULL_ARG) click to toggle source

Set or retrieve the source for the software

@param val [Hash<Symbol, String>] a single key/pair that defines

the kind of source and a path specifier

@option val [String] :git (nil) a Git URL @option val [String] :url (nil) a general URL @option val [String] :path (nil) a fully-qualified local file system path

@todo Consider changing this to accept two arguments instead @todo This should throw an error if an invalid key is given, or

if more than one pair is given, or if no source value is ever
set.
# File lib/omnibus/software.rb, line 145
def source(val=NULL_ARG)
  @source = val unless val.equal?(NULL_ARG)
  @source
end
source_dir() click to toggle source

@!group Directory Accessors

# File lib/omnibus/software.rb, line 235
def source_dir
  config.source_dir
end
source_uri() click to toggle source

@todo Code smell… this only has meaning if the software was

defined with a :uri, and this is only used in
{Omnibus::NetFetcher}.  This responsibility is distributed
across two classes, one of which is a specific interface
implementation

@todo Why the caching of the URI?

# File lib/omnibus/software.rb, line 197
def source_uri
  @source_uri ||= URI(@source[:url])
end
version(val=NULL_ARG) click to toggle source

Set a version from a software descriptor file, or receive the effective version, taking into account any override information (if set)

# File lib/omnibus/software.rb, line 153
def version(val=NULL_ARG)
  @given_version = val unless val.equal?(NULL_ARG)
  @override_version || @given_version
end
version_guid() click to toggle source

@todo see comments on {Omnibus::Fetcher#without_caching_for}

# File lib/omnibus/software.rb, line 176
def version_guid
  Fetcher.for(self).version_guid
end
whitelist_file(file) click to toggle source

Add an Omnibus software dependency.

@param file [String, Regexp] the name of a file to ignore in the healthcheck @return [void]

# File lib/omnibus/software.rb, line 162
def whitelist_file(file)
  file = Regexp.new(file) unless file.kind_of?(Regexp)
  @whitelist_files << file
end

Private Instance Methods

command(*args) click to toggle source

@todo What?! @todo It seems that this is not used… remove it @deprecated Use something else (?)

# File lib/omnibus/software.rb, line 362
def command(*args)
  raise "Method Moved."
end
execute_build(fetcher) click to toggle source
# File lib/omnibus/software.rb, line 366
def execute_build(fetcher)
  fetcher.clean
  @builder.build
  touch manifest_file
end
render_tasks() click to toggle source
# File lib/omnibus/software.rb, line 372
def render_tasks
  namespace "projects:#{@project.name}" do
  namespace :software do
    fetcher = Fetcher.for(self)

    #
    # set up inter-project dependencies
    #
    (@dependencies - [@name]).uniq.each do |dep|
      task @name => dep
      file manifest_file => manifest_file_from_name(dep)
    end

    directory source_dir
    directory cache_dir
    directory build_dir
    directory project_dir
    namespace @name do
      task :fetch => [ build_dir, source_dir, cache_dir, project_dir ] do
        if !File.exists?(fetch_file) || fetcher.fetch_required?
          # force build to run if we need to do an updated fetch
          fetcher.fetch
          touch fetch_file
        end
      end

      task :build => :fetch do
        if !always_build? && uptodate?(manifest_file, [fetch_file])
          # if any direct deps have been built for any reason, we will need to
          # clean/build ourselves
          (@dependencies - [@name]).uniq.each do |dep|
            unless uptodate?(manifest_file, [manifest_file_from_name(dep)])
              execute_build(fetcher)
              break
            end
          end

        else
          # if fetch has occurred, or the component is configured to
          # always build, do a clean and build.
          execute_build(fetcher)
        end
      end
    end

    #
    # make the manifest file dependent on the latest file in the
    # source tree in order to shrink the multi-thousand-node
    # dependency graph that Rake was generating
    #
    latest_file = FileList["#{project_dir}/**/*"].sort { |a,b|
      File.mtime(a) <=> File.mtime(b)
    }.last

    file manifest_file => (file latest_file)

    file fetch_file => "#{name}:fetch"
    file manifest_file => "#{name}:build"

    file fetch_file => (file @source_config)
    file manifest_file => (file fetch_file)

    desc "fetch and build #{@name} for #{@project.name}"
    task @name => manifest_file
  end
  end
end