require 'open-uri' require 'build-tool/vcs/base' require 'fileutils' module BuildTool; module VCS class ArchiveConfiguration < BaseConfiguration def name "archive" end def initialize super @repository = nil @remote_path = nil end def vcs( mod ) raise StandardError if @module and ! mod.equal?( @module ) @module = mod Archive.new( self ) end def copy_configuration( other ) super end attr_writer :repository def repository if @repository.nil? raise ConfigurationError, "No repository configured for module #{mod.name}." end @repository end attr_writer :remote_path def remote_path if @remote_path.nil? return @module.name end @remote_path end end # class ArchiveConfiguration class Archive < Base class ArchiveError < BuildTool::Error; end class FileNotFoundError < BuildTool::Error; end # ### Attributes # def name "archive" end def fetching_supported? true end def patches_supported? true end def apply_patches_after_rebase? true end def archive_local_path "#{File.dirname( local_path )}/#{archive_name}" end def archive_name File.basename( archive_url ) end def archive_url "#{config.repository.url}/#{config.remote_path}" end # ### METHODS # def checkedout? File.exist? archive_local_path end def apply_patches( patches ) patches.each do |patch| full_path = self.recipe.find_first_config_file( "custom/#{config.module.name}/patches/#{patch}.patch" ) if full_path.nil? raise FileNotFoundError, "Patch '#{patch}' not found from module #{config.module.name}." end logger.info "Applying patch #{patch}" self.class.execute( "patch -p1 -i #{full_path}", local_path ) end end def clone fetch() rebase() 0 end def fetch() # Check if the archive is already downloaded if File.exist? archive_local_path logger.trace "Archive already fetched. Skipping." return 0 end # If the archive doesn't exist we assume the unpacked archive # should not exist too. if local_path_exist? logger.trace "We fetch a new archive. Remove the old sources." FileUtils.rm_rf local_path if !$noop end # Create the directories parent dir. FileUtils.mkdir_p( File.dirname( local_path ) ) if !$noop # Download the archive logger.trace "get #{archive_name} from #{archive_url} to #{archive_local_path}" if !$noop target = open( archive_local_path, "wb" ) open( archive_url ) { |file| while c = file.getc target.putc c end } target.close() end return 0 end def guess_top_level_directory return "<topdir>" if $noop topdir = nil if archive_name =~ /(\.tgz|\.tar\.gz)$/ if self.class.execute( "gunzip -c #{archive_local_path} | tar tf -" ) { |line| rc = /^([^\/]*)\//.match( line ) if topdir and topdir != rc[1] raise StandardError, "Unable to determine toplevel directory for archive #{archive_name}!" end topdir = rc[1] } != 0 # No topdir return nil end else raise NotImplementedError, "No idea how to unpack the archive '#{archive_name}'." end return topdir end def rebase # Check if the archive is already downloaded if !File.exist? archive_local_path logger.debug "Archive not fetched. Skipping." return 0 end if local_path_exist? return 0 end # Create the directory we want to use to checkout FileUtils.mkdir_p local_path if !$noop if archive_name =~ /(\.tgz|\.tar\.gz)$/ if guess_top_level_directory() cmd = "gunzip -c #{archive_local_path} | tar --strip-components=1 --extract --file=- --directory=#{local_path}" else cmd = "gunzip -c #{archive_local_path} | tar --strip-components=0 --extract --file=- --directory=#{local_path}" end if self.class.execute( cmd ) != 0 raise StandardError, "Failed to unpack the archive: $?" end else raise NotImplementedError, "No idea how to unpack the archive" end 0 end def prepare_for_access # If our server has an associated ssh-key, add it to the ssh-agent. if config.repository.sshkey key = config.repository.sshkey logger.info "" logger.info "#### Adding required ssh-key #{key.file} to ssh-agent." MJ::Tools::SSH::add_key key.file end true end end # class Archive end; end