require 'right_publish/profile' require 'right_publish/storage' module RightPublish class RepoManager @@repository_type_regex = /\A(\w+)_repo/ @@repository_table = {} def self.get_repository(type) @@repository_table[type].new(type) if @@repository_table[type] end def self.repo_types() type_hash = {} @@repository_table.each_key { |k| type_hash[@@repository_type_regex.match(k.to_s)[1]] = k } type_hash end def self.register_repo(repo_type) repo_key = repo_type::REPO_KEY if repo_type.respond_to?(:new) && @@repository_type_regex.match(repo_key.to_s) @@repository_table[repo_key] = repo_type RightPublish::Profile.instance.register_section(repo_key, repo_type::REPO_OPTIONS) else raise TypeError end nil end end module Repo def initialize(option_key) @repository_type ||= option_key end def fetch() Profile.log("Fetching latest #{repo_human_name(@repository_type)} data...") begin sync_dirs( get_storage(Profile.config[:remote_storage][:provider]), get_storage(Profile.config[:local_storage][:provider]), Profile.config[@repository_type][:subdir] ) rescue Exception => e RightPublish::Profile.log("Could not synchronize storage:\n\t#{e}", :error) raise RuntimeError, "fetch from remote failed." end end def store() Profile.log("Commiting local #{repo_human_name(@repository_type)} data...") begin sync_dirs( get_storage(Profile.config[:local_storage][:provider]), get_storage(Profile.config[:remote_storage][:provider]), Profile.config[@repository_type][:subdir] ) rescue Exception => e RightPublish::Profile.log("Could not sychronize storage:\n\t#{e}", :error) raise RuntimeError, "store to remote failed." end end private def build_glob(ext) # Transform array into glob compliant pattern '{'.concat Array(ext).join(',').concat '}' end def do_in_subdir(subdir) full_path = File.expand_path(File.join(Profile.config[:local_storage][:cache_dir], subdir)) FileUtils.mkdir_p full_path Dir.chdir(full_path) { yield } end def get_pkg_list(file_or_dir, ext=nil) pkg_list = [] file_or_dir = Array(file_or_dir) file_or_dir.each do |path| path = path.gsub("\\", "/") pkg_list << if File.directory?(path) glob_filter = (ext && "*.#{build_glob(ext)}") || "*" Dir.glob(File.join(path, glob_filter)) else path.split(',') end end pkg_list.flatten! fail("No packages found") if pkg_list.empty? pkg_list.each do |pkg_path| fail("\"#{pkg_path}\" does not appear to be a valid package for the repository.") \ unless File.file?(pkg_path) && Array(ext).any? { |e| pkg_path.end_with?(e) } yield pkg_path if block_given? end if ext pkg_list end # For automation, we want to send the password, however gpg uses getpass # c function, which interacts directly with /dev/pty instead of stdin/stdout # to hide the password as its typed in. So, we need to allocate a pty. # We do this by shelling out to expect script (tcl based). Ruby 1.8 # implementation of "expect" is broken and has some race conditions with # waiting for a child processes to exist, so don't use that. def shellout_with_password(cmd) password = repo_config[:gpg_password] raise Exception, ":gpg_password must be supplied when signing packages" unless password ENV['GPG_PASSWORD'] = password bin_dir = File.expand_path("../../../bin", __FILE__) autosign = File.join(bin_dir, "autosign.expect") system("#{autosign} #{cmd}") end def get_storage(provider) type = RightPublish::StorageManager.storage_types[provider] RightPublish::StorageManager.get_storage(type) end def install_file(file, dest) Profile.log("#{file} => #{dest}") local_dir = get_storage(Profile.config[:local_storage][:provider]).get_directories File.open(file, "rb") { |chunk| local_dir.files.create(:key=>File.join(dest, File.basename(file)), :body=>chunk) } end def prune_all(glob_pattern) Profile.log("Pruning: #{glob_pattern}") Dir.glob(glob_pattern) { |f| File.unlink(f) } end def repo_config() Profile.config[@repository_type] end def repo_human_name(type) type.to_s.sub(/_/,' ') end def sync_dirs(src, dest, subdir='') RightPublish::Storage.sync_dirs(src, dest, :subdir=>subdir, :sweep=>true) end end end require 'right_publish/repos/apt' require 'right_publish/repos/gem' require 'right_publish/repos/yum' require 'right_publish/repos/zypp'