# -*- coding: UTF-8 -*- 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( verbose = false ) fetch( verbose ) rebase( verbose ) 0 end def fetch( verbose = false ) # 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.info"downloading #{archive_url}" if !$noop begin # We first open the archive. Will throw an exception if the url is invalid. open( archive_url ) do |file| begin # Create the local file open( archive_local_path, "wb" ) do |target| # Copy while c = file.getc target.putc( c ) end end rescue # Clean up File.unlink( archive_local_path ) if File.exist?( archive_local_path ) raise end end rescue StandardError => e msg = "Failed to download #{archive_url}: #{e.to_s}" logger.error( msg ) raise StandardError, msg end end return 0 end def guess_top_level_directory return "" if $noop # Find the command to list the archive content if archive_name =~ /(\.tgz|\.tar\.gz)$/ cmd = "gzip -dc #{archive_local_path} | tar tf -" elsif archive_name =~ /(\.txz|\.tar\.xz)$/ cmd = "xz -dc #{archive_local_path} | tar tf -" elsif archive_name =~ /(\.tar\.bz2)$/ cmd = "bzip2 -dc #{archive_local_path} | tar tf -" else raise NotImplementedError, "'#{archive_name}' has a unsupported format." end # Then check for a toplevel directory. topdir = nil self.class.execute( cmd ) do |line| rc = /^([^\/]*)\/?/.match( line ) if topdir if topdir != rc[1] return false end else topdir = rc[1] end end return topdir end def rebase( verbose = false ) # 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 # Check if there is a common top level dir # eg. my-package-0.4.7 if guess_top_level_directory() strip_components = 1 else strip_components = 0 end # Get the command to unpack if archive_name =~ /(\.tgz|\.tar\.gz)$/ cmd = "gunzip -dc #{archive_local_path} | tar --strip-components=#{strip_components} --extract --file=- --directory=#{local_path}" elsif archive_name =~ /(\.txz|\.tar\.xz)$/ cmd = "xz -dc #{archive_local_path} | tar --strip-components=#{strip_components} --extract --file=- --directory=#{local_path}" elsif archive_name =~ /\.tar\.bz2$/ cmd = "bzip2 -dc #{archive_local_path} | tar --strip-components=#{strip_components} --extract --file=- --directory=#{local_path}" else raise NotImplementedError, "'#{archive_name}' has unsupported format." end # Create the directory we want to use to checkout FileUtils.mkdir_p local_path if !$noop # Unpack if self.class.execute( cmd ) != 0 raise StandardError, "Failed to unpack the archive: $?" end 0 end def prepare_for_fetch # If our server has an associated ssh-key, add it to the ssh-agent. return check_for_sshkey( config.repository.sshkey ) end end # class Archive end; end