r5_geminabox 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ require 'nesty'
2
+ module Geminabox
3
+ class GemStoreError < StandardError
4
+ attr_reader :code, :reason
5
+
6
+ include Nesty::NestedError
7
+
8
+ def initialize(code, reason)
9
+ @code = code.to_s
10
+ @reason = reason
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,40 @@
1
+ module Geminabox
2
+
3
+ class GemVersion
4
+ attr_accessor :name, :number, :platform
5
+
6
+ def initialize(name, number, platform)
7
+ @name = name
8
+ @number = number
9
+ @platform = platform
10
+ end
11
+
12
+ def ruby?
13
+ !!(platform =~ /ruby/i)
14
+ end
15
+
16
+ def version
17
+ Gem::Version.create(number)
18
+ end
19
+
20
+ def <=>(other)
21
+ sort = other.name <=> name
22
+ sort = version <=> other.version if sort.zero?
23
+ sort = (other.ruby? && !ruby?) ? 1 : -1 if sort.zero? && ruby? != other.ruby?
24
+ sort = other.platform <=> platform if sort.zero?
25
+
26
+ sort
27
+ end
28
+
29
+ def ==(other)
30
+ return false unless other.class == self.class
31
+ [name, number, platform] == [other.name, other.number, other.platform]
32
+ end
33
+
34
+ def gemfile_name
35
+ included_platform = ruby? ? nil : platform
36
+ [name, number, included_platform].compact.join('-')
37
+ end
38
+ end
39
+
40
+ end
@@ -0,0 +1,65 @@
1
+ module Geminabox
2
+
3
+ # This class represents a sorted collection of Geminabox::GemVersion objects.
4
+ # It it used widely throughout the system for displaying and filtering gems.
5
+ class GemVersionCollection
6
+ include Enumerable
7
+
8
+ # Array of Geminabox::GemVersion objects, or an array of [name, version,
9
+ # platform] triples.
10
+ def initialize(initial_gems=[])
11
+ @gems = initial_gems.map{|object|
12
+ coerce_to_gem_version(object)
13
+ }.sort
14
+ end
15
+
16
+ # FIXME: Terminology makes no sense when the version are not all of the same
17
+ # name
18
+ def oldest
19
+ @gems.first
20
+ end
21
+
22
+ # FIXME: Terminology makes no sense when the version are not all of the same
23
+ # name
24
+ def newest
25
+ @gems.last
26
+ end
27
+
28
+ def size
29
+ @gems.size
30
+ end
31
+
32
+ def each(&block)
33
+ @gems.each(&block)
34
+ end
35
+
36
+ # The collection can contain gems of different names, this method groups them
37
+ # by name, and then sorts the different version of each name by version and
38
+ # platform.
39
+ #
40
+ # yields 'foo_gem', version_collection
41
+ def by_name(&block)
42
+ @grouped ||= @gems.group_by(&:name).map{|name, collection|
43
+ [name, Geminabox::GemVersionCollection.new(collection)]
44
+ }.sort_by{|name, collection|
45
+ name.downcase
46
+ }
47
+
48
+ if block_given?
49
+ @grouped.each(&block)
50
+ else
51
+ @grouped
52
+ end
53
+ end
54
+
55
+ private
56
+ def coerce_to_gem_version(object)
57
+ if object.is_a?(Geminabox::GemVersion)
58
+ object
59
+ else
60
+ Geminabox::GemVersion.new(*object)
61
+ end
62
+ end
63
+ end
64
+
65
+ end
@@ -0,0 +1,46 @@
1
+ require 'sinatra/base'
2
+
3
+ module Geminabox
4
+
5
+ class Hostess < Sinatra::Base
6
+ def serve
7
+ send_file(File.expand_path(File.join(Server.data, *request.path_info)), :type => response['Content-Type'])
8
+ end
9
+
10
+ %w[/specs.4.8.gz
11
+ /latest_specs.4.8.gz
12
+ /prerelease_specs.4.8.gz
13
+ ].each do |index|
14
+ get index do
15
+ content_type 'application/x-gzip'
16
+ serve
17
+ end
18
+ end
19
+
20
+ %w[/quick/Marshal.4.8/*.gemspec.rz
21
+ /yaml.Z
22
+ /Marshal.4.8.Z
23
+ ].each do |deflated_index|
24
+ get deflated_index do
25
+ content_type('application/x-deflate')
26
+ serve
27
+ end
28
+ end
29
+
30
+ %w[/yaml
31
+ /Marshal.4.8
32
+ /specs.4.8
33
+ /latest_specs.4.8
34
+ /prerelease_specs.4.8
35
+ ].each do |old_index|
36
+ get old_index do
37
+ serve
38
+ end
39
+ end
40
+
41
+ get "/gems/*.gem" do
42
+ serve
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'http_adapter_config_error'
2
+
3
+ module Geminabox
4
+ class HttpAdapter
5
+
6
+ def get_content(*args)
7
+ raise HttpAdapterConfigError.new(:get_content, 'the response body')
8
+ end
9
+
10
+ def get(*args)
11
+ raise HttpAdapterConfigError.new(:get, 'a response object')
12
+ end
13
+
14
+ def post(*args)
15
+ raise HttpAdapterConfigError.new(:post, 'a response object')
16
+ end
17
+
18
+ def set_auth(*args)
19
+ raise HttpAdapterConfigError.new(:set_auth, 'true')
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ Dir[File.expand_path('http_adapter/*.rb', File.dirname(__FILE__))].each do |file|
26
+ require file
27
+ end
@@ -0,0 +1,32 @@
1
+ require 'httpclient'
2
+
3
+ module Geminabox
4
+
5
+ class HttpClientAdapter < HttpAdapter
6
+
7
+ def get(*args)
8
+ http_client.get(*args)
9
+ end
10
+
11
+ def get_content(*args)
12
+ http_client.get_content(*args)
13
+ end
14
+
15
+ def post(*args)
16
+ http_client.post(*args)
17
+ end
18
+
19
+ def set_auth(url, username = nil, password = nil)
20
+ http_client.set_auth(url, username, password) if username or password
21
+ http_client.www_auth.basic_auth.challenge(url) # Workaround: https://github.com/nahi/httpclient/issues/63
22
+ http_client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
23
+ http_client.send_timeout = 0
24
+ http_client.receive_timeout = 0
25
+ end
26
+
27
+ def http_client
28
+ @http_client ||= HTTPClient.new(ENV['http_proxy'])
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,51 @@
1
+ require 'faraday'
2
+
3
+ module Geminabox
4
+
5
+ class TemplateFaradayAdapter < HttpAdapter
6
+
7
+ def get(*args)
8
+ adapter.get(*args)
9
+ end
10
+
11
+ def get_content(*args)
12
+ response = adapter.get(*args)
13
+ response.body
14
+ end
15
+
16
+ def post(*args)
17
+ adapter.post(*args)
18
+ end
19
+
20
+ # Note that this configuration turns SSL certificate verification off.
21
+ # To set up the adapter for your environment see:
22
+ # https://github.com/lostisland/faraday/wiki/Setting-up-SSL-certificates
23
+ def set_auth(uri, username = nil, password = nil)
24
+ connection = Faraday.new url: uri, ssl: {verify: false} do |faraday|
25
+ faraday.adapter http_engine
26
+ faraday.proxy(ENV['http_proxy']) if ENV['http_proxy']
27
+ end
28
+ connection.basic_auth username, password if username
29
+ connection
30
+ end
31
+
32
+ def adapter
33
+ @adapter ||= Faraday.new do |faraday|
34
+ faraday.adapter http_engine
35
+ faraday.proxy(ENV['http_proxy']) if ENV['http_proxy']
36
+ end
37
+ end
38
+
39
+ def http_engine
40
+ :net_http # make requests with Net::HTTP
41
+ end
42
+
43
+ def options
44
+ lambda {|faraday|
45
+ faraday.adapter http_engine
46
+ faraday.proxy(ENV['http_proxy']) if ENV['http_proxy']
47
+ }
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,7 @@
1
+ module Geminabox
2
+ class HttpAdapterConfigError < StandardError
3
+ def initialize(method_name, returns)
4
+ super("#{method_name} must be defined, and return #{returns}")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,70 @@
1
+ module Geminabox
2
+
3
+ class IncomingGem
4
+ def initialize(gem_data, root_path = Geminabox.data)
5
+ unless gem_data.respond_to? :read
6
+ raise ArgumentError, "Expected an instance of IO"
7
+ end
8
+
9
+ digest = Digest::SHA1.new
10
+ if RbConfig::CONFIG["MAJOR"].to_i <= 1 and RbConfig::CONFIG["MINOR"].to_i <= 8
11
+ @tempfile = Tempfile.new("gem")
12
+ else
13
+ @tempfile = Tempfile.new("gem", :encoding => 'binary', :binmode => true)
14
+ end
15
+
16
+ while data = gem_data.read(1024**2)
17
+ @tempfile.write data
18
+ digest << data
19
+ end
20
+
21
+ @tempfile.close
22
+ @sha1 = digest.hexdigest
23
+
24
+ @root_path = root_path
25
+ end
26
+
27
+ def gem_data
28
+ File.open(@tempfile.path, "rb")
29
+ end
30
+
31
+ def valid?
32
+ spec && spec.name && spec.version
33
+ rescue Gem::Package::Error
34
+ false
35
+ end
36
+
37
+ def spec
38
+ @spec ||= extract_spec
39
+ end
40
+
41
+ def extract_spec
42
+ if Gem::Package.respond_to? :open
43
+ Gem::Package.open(gem_data, "r", nil) do |pkg|
44
+ return pkg.metadata
45
+ end
46
+ else
47
+ Gem::Package.new(@tempfile.path).spec
48
+ end
49
+ end
50
+
51
+ def name
52
+ @name ||= get_name
53
+ end
54
+
55
+ def get_name
56
+ filename = %W[#{spec.name} #{spec.version}]
57
+ filename.push(spec.platform) if spec.platform && spec.platform != "ruby"
58
+ filename.join("-") + ".gem"
59
+ end
60
+
61
+ def dest_filename
62
+ File.join(@root_path, "gems", name)
63
+ end
64
+
65
+ def hexdigest
66
+ @sha1
67
+ end
68
+ end
69
+
70
+ end
@@ -0,0 +1,46 @@
1
+
2
+ # This module addresses Geminabox issue
3
+ # https://github.com/cwninja/geminabox/issues/70
4
+ #
5
+ # The underlying problem is rubygems issue
6
+ # https://github.com/rubygems/rubygems/issues/232, fixed by
7
+ # https://github.com/rubygems/rubygems/pull/364
8
+ #
9
+ # This library (and its call) should be deleted once that pull request is resolved.
10
+
11
+ require 'geminabox'
12
+ require 'rubygems/indexer'
13
+
14
+ module Geminabox::Indexer
15
+ def self.germane?
16
+ gem_version = Gem::Version.new(Gem::VERSION)
17
+ v1_8 = Gem::Version.new('1.8')
18
+ v1_8_25 = Gem::Version.new('1.8.25')
19
+
20
+ (gem_version >= v1_8) && (gem_version < v1_8_25)
21
+ end
22
+
23
+ def self.updated_gemspecs(indexer)
24
+ specs_mtime = File.stat(indexer.dest_specs_index).mtime
25
+ newest_mtime = Time.at 0
26
+
27
+ updated_gems = indexer.gem_file_list.select do |gem|
28
+ gem_mtime = File.stat(gem).mtime
29
+ newest_mtime = gem_mtime if gem_mtime > newest_mtime
30
+ gem_mtime >= specs_mtime
31
+ end
32
+
33
+ indexer.map_gems_to_specs updated_gems
34
+ end
35
+
36
+ def self.patch_rubygems_update_index_pre_1_8_25(indexer)
37
+ if germane?
38
+ specs = updated_gemspecs(indexer)
39
+
40
+ unless specs.empty?
41
+ Gem::Specification.dirs = []
42
+ Gem::Specification.add_specs(*specs)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,13 @@
1
+
2
+ module Geminabox
3
+ module Proxy
4
+ def self.proxy_path(file)
5
+ File.join File.dirname(__FILE__), 'proxy', file
6
+ end
7
+
8
+ autoload :Hostess, proxy_path('hostess')
9
+ autoload :FileHandler, proxy_path('file_handler')
10
+ autoload :Splicer, proxy_path('splicer')
11
+ autoload :Copier, proxy_path('copier')
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+
2
+
3
+ module Geminabox
4
+ module Proxy
5
+ class Copier < FileHandler
6
+
7
+ def self.copy(file_name)
8
+ copier = new(file_name)
9
+ copier.get_file
10
+ copier
11
+ end
12
+
13
+ def get_file
14
+ return true if proxy_file_exists?
15
+ return copy_local if local_file_exists?
16
+ get_remote
17
+ end
18
+
19
+ def copy_local
20
+ FileUtils.cp local_path, proxy_path
21
+ end
22
+
23
+ def get_remote
24
+ File.open(proxy_path, 'w'){|f| f.write(remote_content)}
25
+ end
26
+
27
+ end
28
+ end
29
+ end