class RightPublish::Repo
Constants
- LOCK_FILE_NAME
- LOCK_PERIOD
- LOCK_RETRY_INTERVAL
Public Class Methods
# File lib/right_publish/repo.rb, line 41 def initialize(option_key) @repository_type ||= option_key end
Public Instance Methods
Add a new package to local storage and reindex if necessary
# File lib/right_publish/repo.rb, line 107 def add(file_or_dir, targe) raise NotImplementedError, "Subclass responsibility" end
Create an index.html file to enable browsing of this repo’s subdir. @option options [String] :subdir a subdirectory (common prefix); only files matching this prefix will be included @option options [Array] :filter a whitelist of String glob patterns to filter files, i.e. [“*.rpm”, “*.deb”]
# File lib/right_publish/repo.rb, line 72 def annotate(options={}) Profile.log("Creating HTML directory listing for #{repo_human_name} files...") options[:subdir] ||= repo_config[:subdir] files = [] RightPublish::Storage.ls(local_storage, :subdir => options[:subdir]) do |file| files << file end # Build merged options hash for annotation, based on profile config plus some options # passed into our class. html_options = Profile.config[:annotation] ? Profile.config[:annotation].dup : {} html_options[:filter] = options[:filter] if options.key?(:filter) strip = options[:subdir].split('/').size html = RightPublish::Annotation.generate_html(files, strip, html_options) output = File.join(repo_config[:subdir], 'index.html') local_dir = local_storage.get_directories local_dir.files.create(:key => output, :body => html) end
Perform one-shot publish of one or more packages. “One-shot” means: pull, add, annotate and push.
# File lib/right_publish/repo.rb, line 97 def publish(file_or_dir, target) lock do pull add(file_or_dir, target) annotate push end end
Sync files from remote to local storage
# File lib/right_publish/repo.rb, line 46 def pull() Profile.log("Fetching #{repo_human_name} files from remote...") begin sync_dirs(remote_storage, local_storage, repo_config[:subdir]) rescue Exception => e RightPublish::Profile.log("Could not synchronize storage:\n\t#{e}", :error) raise RuntimeError, "pull from remote failed." end end
Sync files from local to remote storage
# File lib/right_publish/repo.rb, line 58 def push() Profile.log("Committing local #{repo_human_name} files to remote...") begin sync_dirs(local_storage, remote_storage, repo_config[:subdir]) rescue Exception => e RightPublish::Profile.log("Could not sychronize storage:\n\t#{e}", :error) raise RuntimeError, "push to remote failed." end end
Private Instance Methods
# File lib/right_publish/repo.rb, line 147 def build_glob(ext) # Transform array into glob compliant pattern '{'.concat Array(ext).join(',').concat '}' end
# File lib/right_publish/repo.rb, line 152 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
# File lib/right_publish/repo.rb, line 159 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
# File lib/right_publish/repo.rb, line 208 def get_storage(provider) type = RightPublish::StorageManager.storage_types[provider] RightPublish::StorageManager.get_storage(type) end
# File lib/right_publish/repo.rb, line 213 def install_file(file, dest) Profile.log("#{file} => #{dest}") local_dir = local_storage.get_directories File.open(file, "rb") { |chunk| local_dir.files.create(:key => File.join(dest, File.basename(file)), :body => chunk) } end
proxy method
# File lib/right_publish/repo.rb, line 204 def local_storage get_storage(Profile.config[:local_storage][:provider]) end
# File lib/right_publish/repo.rb, line 113 def lock(&block) while( (_lock_time = lock_time) != nil && Time.now.utc <= _lock_time ) do Profile.log "Lock is set to expire at #{_lock_time}, waiting for #{LOCK_RETRY_INTERVAL} second(s) ..." sleep LOCK_RETRY_INTERVAL end file = update_lock_time(LOCK_PERIOD) Profile.log "#{repo_human_name} has been locked for #{LOCK_PERIOD/60} minute(s)." yield file.destroy Profile.log "#{repo_human_name} has been unlocked." end
# File lib/right_publish/repo.rb, line 137 def lock_file remote_storage.get_directories.files.get(lock_file_path) rescue Excon::Errors::NotFound nil end
# File lib/right_publish/repo.rb, line 143 def lock_file_path File.join(repo_config[:subdir], LOCK_FILE_NAME) end
# File lib/right_publish/repo.rb, line 125 def lock_time if lock_file return Time.parse(lock_file.body) else nil end end
# File lib/right_publish/repo.rb, line 219 def prune_all(glob_pattern) Profile.log("Pruning: #{glob_pattern}") Dir.glob(glob_pattern) { |f| File.unlink(f) } end
proxy method
# File lib/right_publish/repo.rb, line 199 def remote_storage get_storage(Profile.config[:remote_storage][:provider]) end
# File lib/right_publish/repo.rb, line 224 def repo_config() Profile.config[@repository_type] end
# File lib/right_publish/repo.rb, line 228 def repo_human_name @repository_type.to_s.sub(/_/, ' ') 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.
# File lib/right_publish/repo.rb, line 189 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
# File lib/right_publish/repo.rb, line 232 def sync_dirs(src, dest, subdir='') RightPublish::Storage.sync_dirs(src, dest, :subdir => subdir, :sweep => true) end
# File lib/right_publish/repo.rb, line 133 def update_lock_time(timeout) remote_storage.get_directories.files.create(:key => lock_file_path, :body => (Time.now.utc + timeout).to_s, :acl=>'public-read', :content_type => 'text/plain') end