# # Copyright 2012-2018 Chef Software, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "omnibus/core_extensions" require "cleanroom" require "pathname" unless defined?(Pathname) require "omnibus/digestable" require "omnibus/exceptions" require "omnibus/sugarable" require "omnibus/util" require "omnibus/fetcher" require "omnibus/version" module Omnibus # # The path to the default configuration file. # # @return [String] # DEFAULT_CONFIG = "omnibus.rb".freeze autoload :Builder, "omnibus/builder" autoload :BuildVersion, "omnibus/build_version" autoload :BuildVersionDSL, "omnibus/build_version_dsl" autoload :Cleaner, "omnibus/cleaner" autoload :Compressor, "omnibus/compressor" autoload :Config, "omnibus/config" autoload :Error, "omnibus/exceptions" autoload :FileSyncer, "omnibus/file_syncer" autoload :Generator, "omnibus/generator" autoload :GitCache, "omnibus/git_cache" autoload :HealthCheck, "omnibus/health_check" autoload :Instrumentation, "omnibus/instrumentation" autoload :Library, "omnibus/library" autoload :Logger, "omnibus/logger" autoload :Logging, "omnibus/logging" autoload :Metadata, "omnibus/metadata" autoload :NullArgumentable, "omnibus/null_argumentable" autoload :Ohai, "omnibus/ohai" autoload :Package, "omnibus/package" autoload :Packager, "omnibus/packager" autoload :Project, "omnibus/project" autoload :Publisher, "omnibus/publisher" autoload :Reports, "omnibus/reports" autoload :S3Cache, "omnibus/s3_cache" autoload :Software, "omnibus/software" autoload :Templating, "omnibus/templating" autoload :ThreadPool, "omnibus/thread_pool" autoload :Licensing, "omnibus/licensing" autoload :GitFetcher, "omnibus/fetchers/git_fetcher" autoload :NetFetcher, "omnibus/fetchers/net_fetcher" autoload :NullFetcher, "omnibus/fetchers/null_fetcher" autoload :PathFetcher, "omnibus/fetchers/path_fetcher" autoload :FileFetcher, "omnibus/fetchers/file_fetcher" autoload :ArtifactoryPublisher, "omnibus/publishers/artifactory_publisher" autoload :NullPublisher, "omnibus/publishers/null_publisher" autoload :S3Publisher, "omnibus/publishers/s3_publisher" autoload :Manifest, "omnibus/manifest" autoload :ManifestEntry, "omnibus/manifest_entry" autoload :ManifestDiff, "omnibus/manifest_diff" autoload :ChangeLog, "omnibus/changelog" autoload :GitRepository, "omnibus/git_repository" autoload :SemanticVersion, "omnibus/semantic_version" module Command autoload :Base, "omnibus/cli/base" autoload :Cache, "omnibus/cli/cache" autoload :Publish, "omnibus/cli/publish" autoload :ChangeLog, "omnibus/cli/changelog" end class << self # # Reset the current Omnibus configuration. This is primary an internal API # used in testing, but it can also be useful when Omnibus is used as a # library. # # Note - this persists the +Logger+ object by default. # # @param [true, false] include_logger # whether the logger object should be cleared as well # # @return [void] # def reset!(include_logger = false) instance_variables.each do |instance_variable| unless include_logger next if instance_variable == :@logger end remove_instance_variable(instance_variable) end Config.reset! # Clear caches on Project and Software Project.reset! Software.reset! end # # The logger for this Omnibus instance. # # @example # Omnibus.logger.debug { 'This is a message!' } # # @return [Logger] # def logger @logger ||= Logger.new end # # @api private # # Programatically set the logger for Omnibus. # # @param [Logger] logger # def logger=(logger) @logger = logger end # # The UI class for Omnibus. # # @return [Thor::Shell] # def ui @ui ||= Thor::Base.shell.new end # # Load in an Omnibus configuration file. Values will be merged with # and override the defaults defined in {Config}. # # @param [String] file path to a configuration file to load # # @return [void] # def load_configuration(file) Config.load(file) end # # Locate an executable in the current $PATH. # # @return [String, nil] # the path to the executable, or +nil+ if not present # def which(executable) if File.file?(executable) && File.executable?(executable) executable elsif ENV["PATH"] path = ENV["PATH"].split(File::PATH_SEPARATOR).find do |path| File.executable?(File.join(path, executable)) end path && File.expand_path(executable, path) end end # # All {Project} instances that have been loaded. # # @return [Array<:Project>] # def projects project_map.map do |name, _| Project.load(name) end end # # Load the {Project} instance with the given name. # # @param [String] name # the name of the project to get # # @return [Project] # def project(name) Project.load(name) end # # The source root is the path to the root directory of the `omnibus` gem. # # @return [Pathname] # def source_root @source_root ||= Pathname.new(File.expand_path("..", __dir__)) end # # The preferred filepath to a project with the given name on disk. # # @return [String, nil] # def project_path(name) project_map[name.to_s] end # # The preferred filepath to a software with the given name on disk. # # @return [String, nil] # def software_path(name) software_map[name.to_s] end # # The list of directories to search for the given +path+. These paths are # returned **in order** of specificity. # # @param [String] path # the subpath to search for # # @return [Array] # def possible_paths_for(path) possible_paths[path] ||= [ paths_from_project_root, paths_from_local_software_dirs, paths_from_software_gems, ].flatten.inject([]) do |array, directory| destination = File.join(directory, path) if File.directory?(destination) array << destination end array end end private # # The list of possible paths, cached as a hash for quick lookup. # # @see {Omnibus.possible_paths_for} # # @return [Hash] # def possible_paths @possible_paths ||= {} end # # Map the given file paths to the basename of their file, with the +.rb+ # extension removed. # # @example # { 'foo' => '/path/to/foo' } # # @return [Hash] # def basename_map(paths) paths.inject({}) do |hash, directory| Dir.glob("#{directory}/*.rb").each do |path| name = File.basename(path, ".rb") hash[name] ||= path end hash end end # # A hash of all softwares (by name) and their respective path on disk. These # files are **in order**, meaning the software path is the **first** # occurrence of the software in the list. If the same software is # encountered a second time, it will be skipped. # # @example # { 'preparation' => '/home/omnibus/project/config/software/preparation.rb' } # # @return [Hash] # def software_map @software_map ||= basename_map(possible_paths_for(Config.software_dir)) end # # A hash of all projects (by name) and their respective path on disk. These # files are **in order**, meaning the project path is the **first** # occurrence of the project in the list. If the same project is # encountered a second time, it will be skipped. # # @example # { 'chefdk' => '/home/omnibus/project/config/projects/chefdk.rb' } # # @return [Hash] # def project_map @project_map ||= basename_map(possible_paths_for(Config.project_dir)) end # # The list of all software paths to software from the project root. This is # always a single value, but an array is returned for consistency with the # other +software_paths_*+ methods. # # @see (Config#project_root) # @see (Config#software_dir) # # @return [Array] # def paths_from_project_root @paths_from_project_root ||= [Config.project_root] end # # The list of all software paths on disk to software files. If relative # paths are given, they are expanded relative to {Config#project_root}. # # @see (Config#local_software_dirs) # # @return [Array] # def paths_from_local_software_dirs @paths_from_local_software_dirs ||= Array(Config.local_software_dirs).inject([]) do |array, path| fullpath = File.expand_path(path, Config.project_root) if File.directory?(fullpath) array << fullpath end array end end # # The list of software paths from within the list of gems. These gems paths # are loaded from disk using +Gem::Specification+. The latest version of # the gem on disk is loaded. For this reason, it is recommended that you # add these gems to your bundle and be nice to your co-workers. # # @see (Config#software_gems) # # @return [Array] # def paths_from_software_gems @paths_from_software_gems ||= Array(Config.software_gems).inject([]) do |array, name| if (spec = Gem::Specification.find_all_by_name(name).first) array << File.expand_path(spec.gem_dir) end array end end end end