# -*- coding: UTF-8 -*- require 'mj/tools/editor' require 'build-tool/vcs/git' require 'build-tool/vcs/git-svn' require 'build-tool/vcs/svn' require 'build-tool/vcs/archive' require 'build-tool/vcs/mercurial' require 'build-tool/vcs/bazar' require 'build-tool/model/module' require 'build-tool/model/feature' require 'build-tool/model/setting' require 'build-tool/build-system/cmake' require 'build-tool/build-system/qt' require 'build-tool/build-system/autoconf' require 'build-tool/build-system/custom' require 'build-tool/build-system/none' require 'build-tool/build-system/kdel10n' require 'build-tool/build-system/qmake' module BuildTool class Configuration def self.edit( only = [] ) settings = BuildTool::Setting::export( BuildTool::Application.instance.configuration.settings, only ) editor = MJ::Tools::TmpFileEditor.new( YAML::dump( settings ) ) editor.edit() if not Pathname.new( editor.path() ).exist? info( "File deleted!" ) return 0 end values = YAML::load( File.open( editor.path(), 'r:UTF-8' ) ) BuildTool::Setting::import( BuildTool::Application.instance.configuration.settings, values ) return 0 end attr_accessor :recipe attr_reader :modules attr_reader :environments attr_reader :features attr_accessor :active_feature attr_reader :settings def log_directory return @log_directory if @log_directory raise BuildTool::ConfigurationError, "No log directory configured" end def log_directory=( path ) path = Pathname.new( path.sub( /\$HOME/, '~' ) ) if path.to_s[0] != '~' and path.relative? raise ConfigurationError, "Log directory '#{path}' is relative!" end @log_directory = path.expand_path end def environment( name ) @environments[name] end def add_environment( env) @environments[env.name] = env end def feature( name ) @features[name] end def add_feature( feature ) @features[feature.path] = feature end def module( name ) @module[name] end def add_module( mod ) @module[mod.name] = mod @modules << mod end def repository( name ) @repository[name] end def add_repository( repo ) @repository[repo.name] = repo end def server( name ) @server[name] end def add_server( server ) @server[ server.name ] = server end def sshkey( name ) @sshkey[name] end def add_sshkey( key ) @sshkey[key.name] = key end def add_setting( s ) @settings[s.name] = s end def initialize() @recipe = nil @server = {} @log_directory = nil @environments = {} @module = {} @modules = [] @build_system = {} @repository = {} @sshkey = {} @active_feature = nil @features = {} @settings = {} end def vcs( name ) case name when "git-svn" return BuildTool::VCS::GitSvnConfiguration.new when "git" return BuildTool::VCS::GitConfiguration.new when "svn" return BuildTool::VCS::SvnConfiguration.new when "archive" return BuildTool::VCS::ArchiveConfiguration.new when "mercurial" return BuildTool::VCS::MercurialConfiguration.new when "bazar" return BuildTool::VCS::BazarConfiguration.new else raise StandardError, "Unknown Version Control System #{name}" end end def create_build_system( name, parent = nil, *args ) return case name when "none" BuildTool::BuildSystem::None.new( parent, *args ) when "cmake" BuildTool::BuildSystem::CMake.new( parent, *args ) when "kdel10n" BuildTool::BuildSystem::KdeL10n.new( parent, *args ) when "qt" BuildTool::BuildSystem::Qt.new( parent, *args ) when "qmake" BuildTool::BuildSystem::QMake.new( parent, *args ) when "custom" BuildTool::BuildSystem::Custom.new( parent, *args ) when "autoconf" BuildTool::BuildSystem::AutoConf.new( parent, *args ) else raise StandardError, "Unknown Version Control System #{name}" end end def build_system_adjust( name, parent = nil, *args ) bs = create_build_system( name, parent ) bs.defaults = build_system_defaults( name ) return bs end def build_system_defaults( name, *args ) return @build_system[name] if @build_system[name] add_build_system( create_build_system( name ) ) end def add_build_system( bs ) return @build_system[bs.name] = bs end def save logger.debug "Saving features to database." @features.each do |name, f| logger.debug2( " Feature %s (%s)" % [ f.name, f.parent_id ] ) if f.changed? f.save! if f.changed? end logger.debug "Saving modules to database." @modules.each do |m| logger.debug2( " Module %s" % [ m.name ] ) if m.changed? m.save! if m.changed? end logger.debug "Saving settings to database." @settings.each do |n, s| logger.debug2( " Setting %s: %s" % [ s.name, s.value ] ) if s.changed? s.save! if s.changed? end end def load logger.debug "Loading features from database." BuildTool::Feature.all.each do |f| logger.debug2 " - Feature %s" % [ f.name ] add_feature( f ) end logger.debug "Loading modules from database." BuildTool::Module.all.each do |m| logger.debug2 " - Module %s" % [ m.name ] add_module( m ) end logger.debug "Loading settings from database." BuildTool::Setting.all.each do |s| logger.debug2 " - Setting %s: %s" % [ s.name, s.value ] add_setting( s ) end end def truncate logger.debug "Deleting all features from database." BuildTool::Feature.delete_all() @features = {} logger.debug "Deleting all modules from database." BuildTool::Module.delete_all() @module = {} @modules = [] logger.debug "Deleting all settings from database." BuildTool::Setting.delete_all() @settings = {} end # Execute the necessary steps to adapt the configuration to the current state of the # recipe. # # The recipe has to be loaded before calling this method. With the configuration given. # The method removes obsolete stuff from the database. def migrate() logger.debug( 'Checking for obsolete modules in db.' ) for mod in @modules.reverse() do if not mod.found_in_recipe logger.info 'Module %s no longer supported by recipe. Removing it from db.' % [ mod.name ] # Remove it from our bookkeeping first. @module.delete( mod.name ) @modules.delete( mod ) # Remove it from the db mod.destroy() end end logger.debug( 'Checking for obsolete settings in db.' ) settings.each do |n, s| if not s.seen and not n.start_with? 'BUILD_TOOL.' logger.info 'Setting %s no longer supported by recipe. Removing it from db.' % [ s.name ] s.destroy() end end end # Complete buildsets def complete_buildsets( name ) if name == ':all' return complete_modules( '*' ) end end def complete_module( name, include_templates = false, all = false, resume_from = nil, resume_after = nil ) modules = complete_modules( name, include_templates, all, resume_from, resume_after ) case modules.size when 0 then return nil when 1 then return modules[0] else raise BuildTool::ConfigurationError, "#{name} is ambiguous. Please be more specific" end end def complete_modules( name, include_templates = false, all = false, resume_from = nil, resume_after = nil ) if name.start_with? ':' return complete_buildsets( name ) end res = [] found = false should_be_unique = false resume = ( resume_from.nil? and resume_after.nil? ) modules.each do |mod| take_module = false next if ( !include_templates and mod.is_template? ) # We match on the following conditions: # 1. name = mod.name # 2. name/ matches beginning of mod.name # 3. name equals last part of mod.name (behind /) and is unique if name.end_with?('/') and ( mod.name.index "/#{name}" or mod.name.start_with? name ) found = true # Now check if it is active. next if !( mod.active? || all ) take_module = true elsif mod.name == name or mod.name.end_with?( "/#{name}" ) found = true should_be_unique = true take_module = true elsif name == '*' found = true # Now check if it is active. next if !( mod.active? || @all ) take_module = true end if not resume and resume_from and mod.name == resume_from.name resume = true end res << mod if resume and take_module if not resume and resume_after and mod.name == resume_after.name resume = true end end # Raise an error if the module was not found if !found raise BuildTool::ConfigurationError, "Unknown module/package #{name}" end # Raise an error if the result should be unique but is not. if should_be_unique if res.size > 1 raise BuildTool::ConfigurationError, "#{name} is ambiguous (#{res.map { |m| m.name }.join( ', ' ) })." end mod = res[0] # If the module is inactive make sure the feature is active if not ( mod.active? || mod.feature.nil? || mod.feature.active? ) raise BuildTool::ConfigurationError, "Can't select module %s from inactive feature %s" % [ mod.name, mod.feature.name ] end end # Give a warning if all modules where warn( "All modules for #{name} are inactive! Will ignore it." ) if res.empty? return res end end # Configuration end # module BuildTool