gemstash 1.0.0.pre.1-java → 2.6.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +303 -0
  3. data/exe/gemstash +3 -0
  4. data/lib/gemstash/api_key_authorization.rb +32 -0
  5. data/lib/gemstash/authorization.rb +15 -8
  6. data/lib/gemstash/cache.rb +42 -2
  7. data/lib/gemstash/cli/authorize.rb +52 -9
  8. data/lib/gemstash/cli/base.rb +14 -6
  9. data/lib/gemstash/cli/setup.rb +67 -39
  10. data/lib/gemstash/cli/start.rb +6 -2
  11. data/lib/gemstash/cli/status.rb +3 -1
  12. data/lib/gemstash/cli/stop.rb +4 -1
  13. data/lib/gemstash/cli.rb +59 -1
  14. data/lib/gemstash/config.ru +4 -3
  15. data/lib/gemstash/configuration.rb +61 -8
  16. data/lib/gemstash/db/authorization.rb +5 -3
  17. data/lib/gemstash/db/cached_rubygem.rb +20 -0
  18. data/lib/gemstash/db/dependency.rb +2 -0
  19. data/lib/gemstash/db/rubygem.rb +3 -0
  20. data/lib/gemstash/db/upstream.rb +15 -0
  21. data/lib/gemstash/db/version.rb +25 -2
  22. data/lib/gemstash/db.rb +5 -0
  23. data/lib/gemstash/dependencies.rb +6 -2
  24. data/lib/gemstash/env.rb +44 -13
  25. data/lib/gemstash/gem_fetcher.rb +5 -3
  26. data/lib/gemstash/gem_pusher.rb +25 -18
  27. data/lib/gemstash/gem_source/dependency_caching.rb +4 -4
  28. data/lib/gemstash/gem_source/private_source.rb +34 -50
  29. data/lib/gemstash/gem_source/rack_middleware.rb +3 -0
  30. data/lib/gemstash/gem_source/upstream_source.rb +71 -27
  31. data/lib/gemstash/gem_source.rb +4 -2
  32. data/lib/gemstash/gem_yanker.rb +14 -4
  33. data/lib/gemstash/health.rb +55 -0
  34. data/lib/gemstash/http_client.rb +15 -5
  35. data/lib/gemstash/logging.rb +19 -7
  36. data/lib/gemstash/man/gemstash-authorize.1 +54 -0
  37. data/lib/gemstash/man/gemstash-authorize.1.txt +52 -0
  38. data/lib/gemstash/man/gemstash-configuration.5 +186 -0
  39. data/lib/gemstash/man/gemstash-configuration.5.txt +208 -0
  40. data/lib/gemstash/man/gemstash-customize.7 +273 -0
  41. data/lib/gemstash/man/gemstash-customize.7.txt +184 -0
  42. data/lib/gemstash/man/gemstash-debugging.7 +30 -0
  43. data/lib/gemstash/man/gemstash-debugging.7.txt +27 -0
  44. data/lib/gemstash/man/gemstash-deploy.7 +63 -0
  45. data/lib/gemstash/man/gemstash-deploy.7.txt +57 -0
  46. data/lib/gemstash/man/gemstash-mirror.7 +34 -0
  47. data/lib/gemstash/man/gemstash-mirror.7.txt +31 -0
  48. data/lib/gemstash/man/gemstash-multiple-sources.7 +131 -0
  49. data/lib/gemstash/man/gemstash-multiple-sources.7.txt +116 -0
  50. data/lib/gemstash/man/gemstash-private-gems.7 +191 -0
  51. data/lib/gemstash/man/gemstash-private-gems.7.txt +154 -0
  52. data/lib/gemstash/man/gemstash-readme.7 +199 -0
  53. data/lib/gemstash/man/gemstash-readme.7.txt +177 -0
  54. data/lib/gemstash/man/gemstash-setup.1 +38 -0
  55. data/lib/gemstash/man/gemstash-setup.1.txt +38 -0
  56. data/lib/gemstash/man/gemstash-start.1 +23 -0
  57. data/lib/gemstash/man/gemstash-start.1.txt +24 -0
  58. data/lib/gemstash/man/gemstash-status.1 +17 -0
  59. data/lib/gemstash/man/gemstash-status.1.txt +20 -0
  60. data/lib/gemstash/man/gemstash-stop.1 +17 -0
  61. data/lib/gemstash/man/gemstash-stop.1.txt +20 -0
  62. data/lib/gemstash/man/gemstash-version.1 +17 -0
  63. data/lib/gemstash/man/gemstash-version.1.txt +19 -0
  64. data/lib/gemstash/migrations/01_gem_dependencies.rb +11 -9
  65. data/lib/gemstash/migrations/02_authorizations.rb +4 -2
  66. data/lib/gemstash/migrations/03_cached_gems.rb +26 -0
  67. data/lib/gemstash/migrations/04_health_tests.rb +10 -0
  68. data/lib/gemstash/migrations/05_authorization_names.rb +10 -0
  69. data/lib/gemstash/puma.rb +5 -3
  70. data/lib/gemstash/rack_env_rewriter.rb +11 -2
  71. data/lib/gemstash/specs_builder.rb +25 -15
  72. data/lib/gemstash/storage.rb +175 -32
  73. data/lib/gemstash/upstream.rb +43 -8
  74. data/lib/gemstash/version.rb +4 -2
  75. data/lib/gemstash/web.rb +13 -8
  76. data/lib/gemstash.rb +6 -2
  77. metadata +135 -110
  78. data/.gitignore +0 -10
  79. data/.rspec +0 -2
  80. data/.rubocop-bundler.yml +0 -92
  81. data/.rubocop-relax.yml +0 -11
  82. data/.rubocop.yml +0 -8
  83. data/.travis.yml +0 -20
  84. data/Gemfile +0 -4
  85. data/README.md +0 -139
  86. data/Rakefile +0 -35
  87. data/bin/console +0 -14
  88. data/bin/gemstash +0 -3
  89. data/bin/setup +0 -5
  90. data/docs/config.md +0 -136
  91. data/docs/debug.md +0 -24
  92. data/docs/deploy.md +0 -30
  93. data/docs/mirror.md +0 -30
  94. data/docs/multiple_sources.md +0 -68
  95. data/docs/private_gems.md +0 -140
  96. data/docs/reference.md +0 -308
  97. data/gemstash.gemspec +0 -47
  98. data/gemstash.png +0 -0
  99. data/lib/gemstash/gem_unyanker.rb +0 -61
data/lib/gemstash/env.rb CHANGED
@@ -1,8 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
4
+ require "active_support/core_ext/file/atomic"
2
5
  require "dalli"
3
6
  require "fileutils"
4
7
  require "sequel"
5
8
  require "uri"
9
+ require "pathname"
6
10
 
7
11
  module Gemstash
8
12
  # Storage for application-wide variables and configuration.
@@ -14,7 +18,7 @@ module Gemstash
14
18
 
15
19
  # Little module to provide easy access to the current Gemstash::Env.
16
20
  module Helper
17
- private
21
+ private # rubocop:disable Layout/AccessModifierIndentation
18
22
 
19
23
  def gemstash_env
20
24
  Gemstash::Env.current
@@ -30,6 +34,7 @@ module Gemstash
30
34
 
31
35
  def call(env)
32
36
  env["gemstash.env"] = @gemstash_env
37
+ Gemstash::Env.current = @gemstash_env
33
38
  @app.call(env)
34
39
  end
35
40
  end
@@ -46,6 +51,7 @@ module Gemstash
46
51
 
47
52
  def self.current
48
53
  raise EnvNotSetError unless Thread.current[:gemstash_env]
54
+
49
55
  Thread.current[:gemstash_env]
50
56
  end
51
57
 
@@ -54,11 +60,9 @@ module Gemstash
54
60
  end
55
61
 
56
62
  def self.daemonized?
57
- if @daemonized.nil?
58
- raise "Daemonized hasn't been set yet!"
59
- else
60
- @daemonized
61
- end
63
+ raise "Daemonized hasn't been set yet!" if @daemonized.nil?
64
+
65
+ @daemonized
62
66
  end
63
67
 
64
68
  def self.daemonized=(value)
@@ -98,8 +102,33 @@ module Gemstash
98
102
  File.join(base_path, path)
99
103
  end
100
104
 
105
+ def log_file
106
+ if config[:log_file] == :stdout
107
+ $stdout
108
+ else
109
+ base_file(config[:log_file] || "server.log")
110
+ end
111
+ end
112
+
113
+ def pidfile
114
+ if config[:pidfile]
115
+ pathname = Pathname.new(config[:pidfile])
116
+ if pathname.relative?
117
+ base_file(pathname.to_s)
118
+ else
119
+ pathname.to_s
120
+ end
121
+ else
122
+ base_file("puma.pid")
123
+ end
124
+ end
125
+
126
+ def atomic_write(file, &block)
127
+ File.atomic_write(file, File.dirname(file), &block)
128
+ end
129
+
101
130
  def rackup
102
- File.expand_path("../config.ru", __FILE__)
131
+ File.expand_path("config.ru", __dir__)
103
132
  end
104
133
 
105
134
  def db
@@ -108,13 +137,13 @@ module Gemstash
108
137
  when "sqlite3"
109
138
  db_path = base_file("gemstash.db")
110
139
 
111
- if RUBY_PLATFORM == "java"
112
- db = Sequel.connect("jdbc:sqlite:#{db_path}", max_connections: 1)
140
+ db = if RUBY_PLATFORM == "java"
141
+ Sequel.connect("jdbc:sqlite:#{db_path}", config.database_connection_config)
113
142
  else
114
- db = Sequel.connect("sqlite://#{URI.escape(db_path)}", max_connections: 1)
143
+ Sequel.connect("sqlite://#{CGI.escape(db_path)}", config.database_connection_config)
115
144
  end
116
- when "postgres"
117
- db = Sequel.connect(config[:db_url])
145
+ when "postgres", "mysql", "mysql2"
146
+ db = Sequel.connect(config[:db_url], config.database_connection_config)
118
147
  else
119
148
  raise "Unsupported DB adapter: '#{config[:db_adapter]}'"
120
149
  end
@@ -126,7 +155,7 @@ module Gemstash
126
155
 
127
156
  def self.migrate(db)
128
157
  Sequel.extension :migration
129
- migrations_dir = File.expand_path("../migrations", __FILE__)
158
+ migrations_dir = File.expand_path("migrations", __dir__)
130
159
  Sequel::Migrator.run(db, migrations_dir, :use_transactions => true)
131
160
  end
132
161
 
@@ -141,6 +170,8 @@ module Gemstash
141
170
  Gemstash::LruReduxClient.new
142
171
  when "memcached"
143
172
  Dalli::Client.new(config[:memcached_servers])
173
+ when "redis"
174
+ Gemstash::RedisClient.new(config[:redis_servers])
144
175
  else
145
176
  raise "Invalid cache client: '#{config[:cache_type]}'"
146
177
  end
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
  require "set"
3
5
 
4
6
  module Gemstash
5
- #:nodoc:
7
+ # :nodoc:
6
8
  class GemFetcher
7
9
  def initialize(http_client)
8
10
  @http_client = http_client
9
- @valid_headers = Set.new(["etag", "content-type", "content-length", "last-modified"])
11
+ @valid_headers = Set.new(%w[etag content-type content-length last-modified])
10
12
  end
11
13
 
12
14
  def fetch(gem_id, type, &block)
@@ -31,7 +33,7 @@ module Gemstash
31
33
  end
32
34
 
33
35
  def filter_headers(headers)
34
- headers.inject({}) do|properties, (key, value)|
36
+ headers.inject({}) do |properties, (key, value)|
35
37
  properties[key.downcase] = value if @valid_headers.include?(key.downcase)
36
38
  properties
37
39
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
  require "rubygems/package"
3
5
  require "stringio"
4
6
 
5
- #:nodoc:
7
+ # :nodoc:
6
8
  module Gemstash
7
9
  # Class that supports pushing a new gem to the private repository of gems.
8
10
  class GemPusher
@@ -16,12 +18,17 @@ module Gemstash
16
18
  class YankedVersionError < ExistingVersionError
17
19
  end
18
20
 
19
- def initialize(auth_key, content)
20
- @auth_key = auth_key
21
+ def self.serve(app)
22
+ gem = app.request.body.read
23
+ new(app.auth, gem).serve
24
+ end
25
+
26
+ def initialize(auth, content)
27
+ @auth = auth
21
28
  @content = content
22
29
  end
23
30
 
24
- def push
31
+ def serve
25
32
  check_auth
26
33
  store_gem
27
34
  store_gemspec
@@ -44,10 +51,15 @@ module Gemstash
44
51
  end
45
52
 
46
53
  def check_auth
47
- Gemstash::Authorization.check(@auth_key, "push")
54
+ @auth.check("push")
48
55
  end
49
56
 
50
57
  def store_gem
58
+ resource_exist = storage.resource(full_name).exist?
59
+ resource_is_indexed = storage.resource(full_name).properties[:indexed] if resource_exist
60
+
61
+ raise ExistingVersionError, "Cannot push to an existing version!" if resource_exist && resource_is_indexed
62
+
51
63
  storage.resource(full_name).save({ gem: @content }, indexed: true)
52
64
  end
53
65
 
@@ -64,14 +76,8 @@ module Gemstash
64
76
  gemstash_env.db.transaction do
65
77
  gem_id = Gemstash::DB::Rubygem.find_or_insert(spec)
66
78
  existing = Gemstash::DB::Version.find_by_spec(gem_id, spec)
67
-
68
- if existing
69
- if existing.indexed
70
- raise ExistingVersionError, "Cannot push to an existing version!"
71
- else
72
- raise YankedVersionError, "Cannot push to a yanked version!"
73
- end
74
- end
79
+ raise ExistingVersionError, "Cannot push to an existing version!" if existing && existing.indexed
80
+ raise YankedVersionError, "Cannot push to a yanked version!" if existing && !existing.indexed
75
81
 
76
82
  version_id = Gemstash::DB::Version.insert_by_spec(gem_id, spec)
77
83
  Gemstash::DB::Dependency.insert_by_spec(version_id, spec)
@@ -90,14 +96,14 @@ module Gemstash
90
96
  module LegacyRubyGemsSupport
91
97
  def self.included(base)
92
98
  base.class_eval do
93
- alias_method :push_without_cleanup, :push
94
- remove_method :push
99
+ alias_method :serve_without_cleanup, :serve
100
+ remove_method :serve
95
101
  remove_method :gem
96
102
  end
97
103
  end
98
104
 
99
- def push
100
- push_without_cleanup
105
+ def serve
106
+ serve_without_cleanup
101
107
  ensure
102
108
  cleanup
103
109
  end
@@ -115,11 +121,12 @@ module Gemstash
115
121
 
116
122
  def cleanup
117
123
  return unless @tempfile
124
+
118
125
  @tempfile.close
119
126
  @tempfile.unlink
120
127
  end
121
128
  end
122
129
 
123
- GemPusher.send(:include, LegacyRubyGemsSupport)
130
+ GemPusher.include LegacyRubyGemsSupport
124
131
  end
125
132
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gemstash
2
4
  module GemSource
3
5
  # Module for caching dependencies in a GemSource.
@@ -7,9 +9,7 @@ module Gemstash
7
9
  def serve_dependencies
8
10
  gems = gems_from_params
9
11
 
10
- if gems.length > API_REQUEST_LIMIT
11
- halt 422, "Too many gems (use --full-index instead)"
12
- end
12
+ halt 422, "Too many gems (use --full-index instead)" if gems.length > API_REQUEST_LIMIT
13
13
 
14
14
  content_type "application/octet-stream"
15
15
  Marshal.dump dependencies.fetch(gems)
@@ -21,7 +21,7 @@ module Gemstash
21
21
  if gems.length > API_REQUEST_LIMIT
22
22
  halt 422, {
23
23
  "error" => "Too many gems (use --full-index instead)",
24
- "code" => 422
24
+ "code" => 422
25
25
  }.to_json
26
26
  end
27
27
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
 
3
5
  module Gemstash
@@ -6,6 +8,7 @@ module Gemstash
6
8
  class PrivateSource < Gemstash::GemSource::Base
7
9
  include Gemstash::GemSource::DependencyCaching
8
10
  include Gemstash::Env::Helper
11
+ attr_accessor :auth
9
12
 
10
13
  def self.rack_env_rewriter
11
14
  @rack_env_rewriter ||= Gemstash::RackEnvRewriter.new(%r{\A/private})
@@ -14,6 +17,7 @@ module Gemstash
14
17
  def self.matches?(env)
15
18
  rewriter = rack_env_rewriter.for(env)
16
19
  return false unless rewriter.matches?
20
+
17
21
  rewriter.rewrite
18
22
  true
19
23
  end
@@ -23,27 +27,11 @@ module Gemstash
23
27
  end
24
28
 
25
29
  def serve_add_gem
26
- authenticated("Gemstash Private Gems") do
27
- auth = request.env["HTTP_AUTHORIZATION"]
28
- gem = request.body.read
29
- Gemstash::GemPusher.new(auth, gem).push
30
- end
30
+ protected(Gemstash::GemPusher)
31
31
  end
32
32
 
33
33
  def serve_yank
34
- authenticated("Gemstash Private Gems") do
35
- auth = request.env["HTTP_AUTHORIZATION"]
36
- gem_name = params[:gem_name]
37
- Gemstash::GemYanker.new(auth, gem_name, slug_param).yank
38
- end
39
- end
40
-
41
- def serve_unyank
42
- authenticated("Gemstash Private Gems") do
43
- auth = request.env["HTTP_AUTHORIZATION"]
44
- gem_name = params[:gem_name]
45
- Gemstash::GemUnyanker.new(auth, gem_name, slug_param).unyank
46
- end
34
+ protected(Gemstash::GemYanker)
47
35
  end
48
36
 
49
37
  def serve_add_spec_json
@@ -59,7 +47,7 @@ module Gemstash
59
47
  end
60
48
 
61
49
  def serve_versions
62
- halt 403, "Not yet supported"
50
+ halt 404, "Not yet supported"
63
51
  end
64
52
 
65
53
  def serve_info(name)
@@ -67,11 +55,14 @@ module Gemstash
67
55
  end
68
56
 
69
57
  def serve_marshal(id)
70
- gem_full_name = id.sub(/\.gemspec\.rz\z/, "")
71
- gem = fetch_gem(gem_full_name)
72
- halt 404 unless gem.exist?(:spec)
73
- content_type "application/octet-stream"
74
- gem.load(:spec).content(:spec)
58
+ authorization.protect(self) do
59
+ auth.check("fetch") if gemstash_env.config[:protected_fetch]
60
+ gem_full_name = id.delete_suffix(".gemspec.rz")
61
+ gem = fetch_gem(gem_full_name)
62
+ halt 404 unless gem.exist?(:spec)
63
+ content_type "application/octet-stream"
64
+ gem.content(:spec)
65
+ end
75
66
  end
76
67
 
77
68
  def serve_actual_gem(id)
@@ -79,44 +70,38 @@ module Gemstash
79
70
  end
80
71
 
81
72
  def serve_gem(id)
82
- gem_full_name = id.sub(/\.gem\z/, "")
83
- gem = fetch_gem(gem_full_name)
84
- content_type "application/octet-stream"
85
- gem.content(:gem)
73
+ authorization.protect(self) do
74
+ auth.check("fetch") if gemstash_env.config[:protected_fetch]
75
+ gem_full_name = id.delete_suffix(".gem")
76
+ gem = fetch_gem(gem_full_name)
77
+ content_type "application/octet-stream"
78
+ gem.content(:gem)
79
+ end
86
80
  end
87
81
 
88
- def serve_latest_specs
89
- halt 403, "Not yet supported"
82
+ def serve_specs
83
+ params[:prerelease] = false
84
+ protected(Gemstash::SpecsBuilder)
90
85
  end
91
86
 
92
- def serve_specs
93
- content_type "application/octet-stream"
94
- Gemstash::SpecsBuilder.all
87
+ def serve_latest_specs
88
+ params[:latest] = true
89
+ protected(Gemstash::SpecsBuilder)
95
90
  end
96
91
 
97
92
  def serve_prerelease_specs
98
- content_type "application/octet-stream"
99
- Gemstash::SpecsBuilder.prerelease
93
+ params[:prerelease] = true
94
+ protected(Gemstash::SpecsBuilder)
100
95
  end
101
96
 
102
97
  private
103
98
 
104
- def slug_param
105
- version = params[:version]
106
- platform = params[:platform]
107
-
108
- if platform.to_s.empty?
109
- version
110
- else
111
- "#{version}-#{platform}"
112
- end
99
+ def protected(servable)
100
+ authorization.protect(self) { servable.serve(self) }
113
101
  end
114
102
 
115
- def authenticated(realm)
116
- yield
117
- rescue Gemstash::NotAuthorizedError => e
118
- headers["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
119
- halt 401, e.message
103
+ def authorization
104
+ Gemstash::ApiKeyAuthorization
120
105
  end
121
106
 
122
107
  def dependencies
@@ -130,7 +115,6 @@ module Gemstash
130
115
  def fetch_gem(gem_full_name)
131
116
  gem = storage.resource(gem_full_name)
132
117
  halt 404 unless gem.exist?(:gem)
133
- gem.load(:gem)
134
118
  halt 403, "That gem has been yanked" unless gem.properties[:indexed]
135
119
  gem
136
120
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
 
3
5
  module Gemstash
@@ -11,6 +13,7 @@ module Gemstash
11
13
  def call(env)
12
14
  Gemstash::GemSource.sources.each do |source|
13
15
  next unless source.matches?(env)
16
+
14
17
  env["gemstash.gem_source"] = source
15
18
  break
16
19
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
  require "cgi"
3
5
 
@@ -12,6 +14,7 @@ module Gemstash
12
14
  def self.matches?(env)
13
15
  rewriter = rack_env_rewriter.for(env)
14
16
  return false unless rewriter.matches?
17
+
15
18
  rewriter.rewrite
16
19
  env["gemstash.upstream"] = rewriter.captures["upstream_url"]
17
20
  capture_user_agent(env)
@@ -35,10 +38,6 @@ module Gemstash
35
38
  halt 403, "Cannot yank from an upstream server!"
36
39
  end
37
40
 
38
- def serve_unyank
39
- halt 403, "Cannot unyank from an upstream server!"
40
- end
41
-
42
41
  def serve_add_spec_json
43
42
  halt 403, "Cannot add spec to an upstream server!"
44
43
  end
@@ -60,11 +59,11 @@ module Gemstash
60
59
  end
61
60
 
62
61
  def serve_versions
63
- redirect upstream.url("versions", request.query_string)
62
+ redirect index_upstream.url("versions", request.query_string)
64
63
  end
65
64
 
66
65
  def serve_info(name)
67
- redirect upstream.url("info/#{name}", request.query_string)
66
+ redirect index_upstream.url("info/#{name}", request.query_string)
68
67
  end
69
68
 
70
69
  def serve_marshal(id)
@@ -94,8 +93,21 @@ module Gemstash
94
93
  private
95
94
 
96
95
  def upstream
97
- @upstream ||= Gemstash::Upstream.new(env["gemstash.upstream"],
98
- user_agent: env["gemstash.user-agent"])
96
+ @upstream ||= Gemstash::Upstream.new(
97
+ env["gemstash.upstream"],
98
+ user_agent: env["gemstash.user-agent"]
99
+ )
100
+ end
101
+
102
+ def index_upstream
103
+ @index_upstream ||=
104
+ if upstream.uri.host == "rubygems.org"
105
+ uri = upstream.uri.dup
106
+ uri.host = "index.rubygems.org"
107
+ Gemstash::Upstream.new(uri, user_agent: upstream.user_agent)
108
+ else
109
+ upstream
110
+ end
99
111
  end
100
112
  end
101
113
 
@@ -116,16 +128,40 @@ module Gemstash
116
128
  serve_cached(id, :gem)
117
129
  end
118
130
 
131
+ def serve_latest_specs
132
+ http_client = http_client_for(upstream)
133
+ http_client.get("latest_specs.4.8.gz")
134
+ end
135
+
136
+ def serve_prerelease_specs
137
+ http_client = http_client_for(upstream)
138
+ http_client.get("prerelease_specs.4.8.gz")
139
+ end
140
+
141
+ def serve_specs
142
+ http_client = http_client_for(upstream)
143
+ http_client.get("specs.4.8.gz")
144
+ end
145
+
119
146
  private
120
147
 
121
- def serve_cached(id, key)
122
- gem = fetch_gem(id, key)
123
- headers.update(gem.properties[:headers][key]) if gem.properties[:headers] && gem.properties[:headers][key]
124
- gem.content(key)
148
+ def serve_cached(id, resource_type)
149
+ gem = fetch_gem(id, resource_type)
150
+ set_gem_headers(gem, resource_type)
151
+ gem.content(resource_type)
125
152
  rescue Gemstash::WebError => e
126
153
  halt e.code
127
154
  end
128
155
 
156
+ def set_gem_headers(gem, resource_type)
157
+ return unless gem.property?(:headers, resource_type)
158
+
159
+ gem_headers = gem.properties[:headers][resource_type]
160
+ headers["Content-Type"] = gem_headers["content-type"] if gem_headers.include?("content-type")
161
+ headers["Last-Modified"] = gem_headers["last-modified"] if gem_headers.include?("last-modified")
162
+ headers["ETag"] = gem_headers["etag"] if gem_headers.include?("etag")
163
+ end
164
+
129
165
  def dependencies
130
166
  @dependencies ||= begin
131
167
  http_client = http_client_for(upstream)
@@ -142,25 +178,33 @@ module Gemstash
142
178
  @gem_fetcher ||= Gemstash::GemFetcher.new(http_client_for(upstream))
143
179
  end
144
180
 
145
- def fetch_gem(id, key)
181
+ def fetch_gem(id, resource_type)
146
182
  gem_name = Gemstash::Upstream::GemName.new(upstream, id)
147
183
  gem_resource = storage.resource(gem_name.name)
148
- if gem_resource.exist?(key)
149
- fetch_local_gem(gem_name, gem_resource, key)
184
+ if gem_resource.exist?(resource_type)
185
+ fetch_local_gem(gem_name, gem_resource, resource_type)
150
186
  else
151
- fetch_remote_gem(gem_name, gem_resource, key)
187
+ fetch_remote_gem(gem_name, gem_resource, resource_type)
152
188
  end
153
189
  end
154
190
 
155
- def fetch_local_gem(gem_name, gem_resource, key)
156
- log.info "Gem #{gem_name.name} exists, returning cached #{key}"
157
- gem_resource.load(key)
191
+ def fetch_local_gem(gem_name, gem_resource, resource_type)
192
+ log.info "Gem #{gem_name.name} exists, returning cached #{resource_type}"
193
+ gem_resource
158
194
  end
159
195
 
160
- def fetch_remote_gem(gem_name, gem_resource, key)
161
- log.info "Gem #{gem_name.name} is not cached, fetching #{key}"
162
- gem_fetcher.fetch(gem_name.id, key) do |content, properties|
163
- gem_resource.save({ key => content }, headers: { key => properties })
196
+ def fetch_remote_gem(gem_name, gem_resource, resource_type)
197
+ log.info "Gem #{gem_name.name} is not cached, fetching #{resource_type}"
198
+ gem_fetcher.fetch(gem_name.id, resource_type) do |content, properties|
199
+ resource_properties = {
200
+ upstream: upstream.to_s,
201
+ gem_name: gem_name.name,
202
+ headers: { resource_type => properties }
203
+ }
204
+
205
+ gem = gem_resource.save({ resource_type => content }, resource_properties)
206
+ Gemstash::DB::CachedRubygem.store(upstream, gem_name, resource_type)
207
+ gem
164
208
  end
165
209
  end
166
210
  end
@@ -169,13 +213,13 @@ module Gemstash
169
213
  # default upstream).
170
214
  class RubygemsSource < Gemstash::GemSource::UpstreamSource
171
215
  def self.matches?(env)
172
- if env["HTTP_X_GEMFILE_SOURCE"].to_s.empty?
173
- env["gemstash.upstream"] = env["gemstash.env"].config[:rubygems_url]
216
+ env["gemstash.upstream"] = if env["gemstash.env"].config[:ignore_gemfile_source] || env["HTTP_X_GEMFILE_SOURCE"].to_s.empty?
217
+ env["gemstash.env"].config[:rubygems_url]
174
218
  else
175
- env["gemstash.upstream"] = env["HTTP_X_GEMFILE_SOURCE"]
219
+ env["HTTP_X_GEMFILE_SOURCE"]
176
220
  end
177
- capture_user_agent(env)
178
221
 
222
+ capture_user_agent(env)
179
223
  true
180
224
  end
181
225
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
  require "forwardable"
3
5
 
4
6
  module Gemstash
5
- #:nodoc:
7
+ # :nodoc:
6
8
  module GemSource
7
9
  autoload :DependencyCaching, "gemstash/gem_source/dependency_caching"
8
10
  autoload :PrivateSource, "gemstash/gem_source/private_source"
@@ -27,7 +29,7 @@ module Gemstash
27
29
  include Gemstash::Logging
28
30
 
29
31
  def_delegators :@app, :cache_control, :content_type, :env, :halt,
30
- :headers, :http_client_for, :params, :redirect, :request
32
+ :headers, :http_client_for, :params, :redirect, :request
31
33
 
32
34
  def initialize(app)
33
35
  @app = app
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
 
3
5
  module Gemstash
@@ -17,13 +19,19 @@ module Gemstash
17
19
  class YankedVersionError < StandardError
18
20
  end
19
21
 
20
- def initialize(auth_key, gem_name, slug)
21
- @auth_key = auth_key
22
+ def self.serve(app)
23
+ gem_name = app.params[:gem_name]
24
+ slug = Gemstash::DB::Version.slug(app.params)
25
+ new(app.auth, gem_name, slug).serve
26
+ end
27
+
28
+ def initialize(auth, gem_name, slug)
29
+ @auth = auth
22
30
  @gem_name = gem_name
23
31
  @slug = slug
24
32
  end
25
33
 
26
- def yank
34
+ def serve
27
35
  check_auth
28
36
  update_database
29
37
  invalidate_cache
@@ -40,15 +48,17 @@ module Gemstash
40
48
  end
41
49
 
42
50
  def check_auth
43
- Gemstash::Authorization.check(@auth_key, "yank")
51
+ @auth.check("yank")
44
52
  end
45
53
 
46
54
  def update_database
47
55
  gemstash_env.db.transaction do
48
56
  raise UnknownGemError, "Cannot yank an unknown gem!" unless Gemstash::DB::Rubygem[name: @gem_name]
57
+
49
58
  version = Gemstash::DB::Version.find_by_full_name(full_name)
50
59
  raise UnknownVersionError, "Cannot yank an unknown version!" unless version
51
60
  raise YankedVersionError, "Cannot yank an already yanked version!" unless version.indexed
61
+
52
62
  version.deindex
53
63
  storage.resource(version.storage_id).update_properties(indexed: false)
54
64
  end