require 'ftools' require 'mj/tools/ssh' module BuildTool # # Represents the information associated with a buildable module. # class Module # Create a module def initialize( name, parent = nil ) if name.nil? raise StandardError, "Module name is required!" end @active = nil @patches = Array.new @name = name @parent = parent @local_path = nil @build_prefix = nil @remote_path = nil @environment = nil @build_system = nil @repository = nil @install_prefix = nil @is_template = false @vcs_configuration = nil @feature = nil @long_description = nil @description = nil end # ### ATTRIBUTES # attr_writer :feature attr_writer :active attr_reader :patches def active? # If the module is activated that wins if @active.nil? if @feature.nil? return true else return @feature.active? end else return @active end end # not inherited def build_directory build_prefix_required.join("bld", local_path) end def build_prefix=( path ) if path @build_prefix = Pathname.new( File.expand_path( path ) ) else @build_prefix = nil end end def build_prefix # Return our own buildsystem if there is one return @build_prefix if @build_prefix # Return our parents buildsystem if there is one return @parent.build_prefix if @parent && @parent.build_prefix # Nothing nil end # Will throw a exception if build_prefix is not set def build_prefix_required return self.build_prefix if self.build_prefix raise ConfigurationError, "No build prefix configured for #{name}!" end # Build system attr_writer :build_system def build_system # Return our own buildsystem if there is one return @build_system if @build_system # Return our parents buildsystem if there is one if @parent && @parent.build_system @build_system = @parent.build_system.dup @build_system.module = self return @build_system end # Nothing nil end # Will throw a exception if build_system is not set def build_system_required return self.build_system if self.build_system # *TODO* try to guess the build system raise ConfigurationError, "No build system configured for #{name}!" end def checkedout? vcs_required.checkedout? end def configured? if build_system return build_system.configured? else return false end end attr_writer :description def description @description end # Environment attr_writer :environment def environment # Return our own buildsystem if there is one return @environment if @environment # Return our parents buildsystem if there is one return @parent.environment if @parent && @parent.environment # Nothing nil end # Will throw a exception if environment is not set def environment_required return self.environment if self.environment raise ConfigurationError, "No environment configured for #{name}!" end # Garbage collect def gc vcs.gc end # Installation prefix def install_prefix=( path ) if path @install_prefix = Pathname.new( File.expand_path( path.to_s ) ) else @install_prefix = nil end end def install_prefix # Return our own buildsystem if there is one return @install_prefix if @install_prefix # Return our parents buildsystem if there is one return @parent.install_prefix if @parent && @parent.install_prefix # Nothing nil end # Will throw a exception if install_prefix is not set def install_prefix_required return self.install_prefix if self.install_prefix raise ConfigurationError, "No install prefix configured for #{name}!" end attr_writer :is_template def is_template? @is_template end def local_path=( local_path ) raise ConfigurationError, "Attempt to set local_path for module template #{name}" if is_template? @local_path = local_path end def local_path @local_path || @name end attr_writer :long_description def long_description @long_description end # The module name attr_reader :name # Remote path def remote_path=( remote_path ) raise ConfigurationError, "Attempt to set remote_path for module template #{name}" if is_template? @remote_path = remote_path end def remote_path @remote_path || @name end # Repository def repository=( repository ) @repository = repository end def repository return @repository if @repository return @parent.repository if @parent && @parent.repository end def repository_required repo = self.repository return repo if repo raise ConfigurationError, "No repository configured for #{name}!" end def source_directory build_prefix_required.join("src", local_path) end alias source_directory_required source_directory def vcs return vcs_configuration.vcs( self ) if vcs_configuration nil end attr_writer :vcs_configuration def vcs_configuration return @vcs_configuration if @vcs_configuration return @parent.vcs_configuration if @parent nil end def vcs_configuration_required if @vcs_configuration vc = @vcs_configuration elsif @parent vc = @parent.vcs_configuration else vc = nil end if vc.nil? raise ConfigurationError, "No version control system configure for module #{name}." end return vc end def vcs_required if repository.nil? raise ConfigurationError, "No repository specified for module #{name}." end if remote_path.nil? raise ConfigurationError, "No remote path specified for module #{name}." end if source_directory.nil? raise ConfigurationError, "No source directory specified for module #{name}." end return vcs_configuration_required.vcs( self ) end # ### ACTIONS # def clean( remove_build_directory = false ) if remove_build_directory logger.info "Removing build directory." build_system_required.remove_build_directory else logger.info "Cleaning build directory." build_system_required.make( "clean" ) end end # Clone the repository. def clone vcs_required.clone if !patches.empty? if !vcs.patches_supported? raise NotImplementedError, "Patch support not implemented for vcs #{vcs.name}" end vcs_required.apply_patches( patches ) end end # Fetch changes from the remote repository. Do not change the local # checkout. def fetch vcs_required.fetch end # Update the local changes with remote changes. Do not fetch changes # from the remote repository. def rebase vcs_required.rebase if !patches.empty? if !vcs.patches_supported? raise NotImplementedError, "Patch support not implemented for vcs #{vcs.name}" end vcs_required.apply_patches( patches ) end build_system_required.after_rebase end def configure build_system_required.configure end def reconfigure build_system_required.reconfigure end # Call make def make( target = nil ) build_system_required.make( target ) end def install( fast = false ) build_system_required.install( fast ) end # Check if an ssh-key is required and active it if necessary def prepare_for_vcs_access if key = repository_required.sshkey if !MJ::Tools::SSH::has_key? key.file MJ::Tools::SSH::add_key key.file end end return true end def prepare_for_installation prefix = install_prefix_required if !prefix.exist? or !prefix.writable? begin FileUtils.mkdir_p prefix.to_s rescue Errno::EACCES => e logger.error "#{name}: The directory #{prefix.to_s} is not writable! Installation will fail!" return false end end return true end end # Module end # module BuildTool