class Geminabox::Server
def all_gems
def all_gems all_gems_with_duplicates.inject(:|) end
def all_gems_with_duplicates
def all_gems_with_duplicates specs_files_paths.map do |specs_file_path| if File.exist?(specs_file_path) Marshal.load(Gem::Util.gunzip(Gem.read_binary(specs_file_path))) else [] end end end
def allow_delete?
def allow_delete? Geminabox.allow_delete end
def allow_upload?
def allow_upload? Geminabox.allow_upload end
def api_request?
def api_request? request.accept.first.to_s != "text/html" end
def combined_gem_list
def combined_gem_list GemListMerge.merge(local_gem_list, remote_gem_list, strategy: Geminabox.rubygems_proxy_merge_strategy) end
def default_platform
def default_platform 'ruby' end
def dependency_cache
def dependency_cache @dependency_cache ||= Geminabox::DiskCache.new(File.join(Geminabox.data, "_cache")) end
def dependency_cache
def dependency_cache self.class.dependency_cache end
def disallow_replace?
def disallow_replace? ! Geminabox.allow_replace end
def error_response(code, message)
def error_response(code, message) halt [code, message] if api_request? html = <<HTML l> ead><title>Error - #{code}</title></head> ody> <h1>Error - #{code}</h1> <p>#{message}</p> body> ml> halt [code, html] end
def file_class
def file_class @file_class ||= File end
def file_class=(klass)
def file_class=(klass) @file_class = klass end
def file_path
def file_path File.expand_path(File.join(Geminabox.data, *request.path_info)) end
def fixup_bundler_rubygems!
def fixup_bundler_rubygems! return if @post_reset_hook_applied Gem.post_reset{ Gem::Specification.all = nil } if defined? Bundler and Gem.respond_to? :post_reset @post_reset_hook_applied = true end
def gem_dependencies(gem_name)
def gem_dependencies(gem_name) dependency_cache.marshal_cache(gem_name) do load_gems. select { |gem| gem_name == gem.name }. map { |gem| [gem, spec_for(gem.name, gem.number, gem.platform)] }. reject { |(_, spec)| spec.nil? }. map do |(gem, spec)| { :name => gem.name, :number => gem.number.version, :platform => gem.platform, :dependencies => runtime_dependencies(spec) } end end end
def gem_list
def gem_list Geminabox.rubygems_proxy ? combined_gem_list : local_gem_list end
def h(text)
def h(text) Rack::Utils.escape_html(text) end
def handle_incoming_gem(gem)
def handle_incoming_gem(gem) begin GemStore.create(gem, params[:overwrite]) rescue GemStoreError => error error_response error.code, error.reason end begin Geminabox.on_gem_received.call(gem) if Geminabox.on_gem_received rescue # ignore errors which occur within the hook end if api_request? "Gem #{gem.name} received and indexed." else redirect url("/") end end
def href(text)
def href(text) if text && (text.start_with?('http://') || text.start_with?('https://')) Rack::Utils.escape_html(text) else '#' end end
def index_gems(gems)
def index_gems(gems) Set.new(gems.map{|gem| gem.name[0..0].downcase}) end
def indexer
def indexer Gem::Indexer.new(Geminabox.data, :build_legacy => Geminabox.build_legacy) end
def load_gems
def load_gems @loaded_gems ||= Geminabox::GemVersionCollection.new(all_gems) end
def local_gem_list
def local_gem_list query_gems.map{|query_gem| gem_dependencies(query_gem) }.flatten(1) end
def name_and_requirements_for(dep)
def name_and_requirements_for(dep) name = dep.name.kind_of?(Array) ? dep.name.first : dep.name [name, dep.requirement.to_s] end
def query_gems
def query_gems params[:gems].to_s.split(',') end
def reindex(force_rebuild = false)
def reindex(force_rebuild = false) fixup_bundler_rubygems! force_rebuild = true unless Geminabox.incremental_updates if force_rebuild indexer.generate_index dependency_cache.flush else begin require 'geminabox/indexer' updated_gemspecs = Geminabox::Indexer.updated_gemspecs(indexer) return if updated_gemspecs.empty? indexer.update_index updated_gemspecs.each { |gem| dependency_cache.flush_key(gem.name) } rescue Errno::ENOENT with_rlock { reindex(:force_rebuild) } rescue => e puts "#{e.class}:#{e.message}" puts e.backtrace.join("\n") with_rlock { reindex(:force_rebuild) } end end rescue Gem::SystemExitException end
def remote_gem_list
def remote_gem_list RubygemsDependency.for(*query_gems) end
def runtime_dependencies(spec)
def runtime_dependencies(spec) spec. dependencies. select { |dep| dep.type == :runtime }. map { |dep| name_and_requirements_for(dep) } end
def serialize_update(&block)
def serialize_update(&block) with_rlock(&block) rescue ReentrantFlock::AlreadyLocked halt 503, { 'Retry-After' => Geminabox.retry_interval.to_s }, 'Repository lock is held by another process' end
def spec_file_name(specs_file_type)
def spec_file_name(specs_file_type) [specs_file_type, Gem.marshal_version, 'gz'].join('.') end
def spec_for(gem_name, version, platform = default_platform)
def spec_for(gem_name, version, platform = default_platform) filename = [gem_name, version] filename.push(platform) if platform != default_platform spec_file = File.join(Geminabox.data, "quick", "Marshal.#{Gem.marshal_version}", "#{filename.join("-")}.gemspec.rz") File::open(spec_file, 'r') do |unzipped_spec_file| unzipped_spec_file.binmode Marshal.load(Gem::Util.inflate(unzipped_spec_file.read)) end if File.exist? spec_file end
def specs_file_types
def specs_file_types [:specs, :prerelease_specs] end
def specs_files_paths
def specs_files_paths specs_file_types.map do |specs_file_type| File.join(Geminabox.data, spec_file_name(specs_file_type)) end end
def with_rlock(&block)
def with_rlock(&block) file_class.open(Geminabox.lockfile, File::RDWR | File::CREAT) do |f| ReentrantFlock.synchronize(f, File::LOCK_EX | File::LOCK_NB, &block) end end
def with_rlock(&block)
def with_rlock(&block) self.class.with_rlock(&block) end