gemstash 2.0.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +57 -0
  3. data/exe/gemstash +3 -0
  4. data/lib/gemstash/api_key_authorization.rb +3 -0
  5. data/lib/gemstash/authorization.rb +7 -3
  6. data/lib/gemstash/cache.rb +42 -2
  7. data/lib/gemstash/cli/authorize.rb +5 -5
  8. data/lib/gemstash/cli/base.rb +4 -1
  9. data/lib/gemstash/cli/setup.rb +19 -4
  10. data/lib/gemstash/cli/start.rb +4 -1
  11. data/lib/gemstash/cli/status.rb +2 -0
  12. data/lib/gemstash/cli/stop.rb +2 -0
  13. data/lib/gemstash/cli.rb +2 -0
  14. data/lib/gemstash/config.ru +3 -3
  15. data/lib/gemstash/configuration.rb +8 -2
  16. data/lib/gemstash/db/authorization.rb +2 -0
  17. data/lib/gemstash/db/cached_rubygem.rb +3 -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 +3 -0
  21. data/lib/gemstash/db/version.rb +3 -0
  22. data/lib/gemstash/db.rb +3 -0
  23. data/lib/gemstash/dependencies.rb +6 -2
  24. data/lib/gemstash/env.rb +24 -4
  25. data/lib/gemstash/gem_fetcher.rb +4 -2
  26. data/lib/gemstash/gem_pusher.rb +7 -5
  27. data/lib/gemstash/gem_source/dependency_caching.rb +4 -4
  28. data/lib/gemstash/gem_source/private_source.rb +6 -3
  29. data/lib/gemstash/gem_source/rack_middleware.rb +3 -0
  30. data/lib/gemstash/gem_source/upstream_source.rb +9 -3
  31. data/lib/gemstash/gem_source.rb +4 -2
  32. data/lib/gemstash/gem_yanker.rb +4 -0
  33. data/lib/gemstash/health.rb +2 -0
  34. data/lib/gemstash/http_client.rb +12 -4
  35. data/lib/gemstash/logging.rb +3 -1
  36. data/lib/gemstash/man/gemstash-authorize.1.txt +0 -65
  37. data/lib/gemstash/man/gemstash-configuration.5.txt +0 -65
  38. data/lib/gemstash/man/gemstash-customize.7.txt +0 -65
  39. data/lib/gemstash/man/gemstash-debugging.7.txt +0 -65
  40. data/lib/gemstash/man/gemstash-deploy.7.txt +0 -65
  41. data/lib/gemstash/man/gemstash-mirror.7.txt +0 -65
  42. data/lib/gemstash/man/gemstash-multiple-sources.7.txt +0 -65
  43. data/lib/gemstash/man/gemstash-private-gems.7.txt +0 -65
  44. data/lib/gemstash/man/gemstash-readme.7.txt +0 -65
  45. data/lib/gemstash/man/gemstash-setup.1.txt +0 -65
  46. data/lib/gemstash/man/gemstash-start.1.txt +0 -65
  47. data/lib/gemstash/man/gemstash-status.1.txt +0 -65
  48. data/lib/gemstash/man/gemstash-stop.1.txt +0 -65
  49. data/lib/gemstash/man/gemstash-version.1.txt +0 -65
  50. data/lib/gemstash/migrations/01_gem_dependencies.rb +2 -0
  51. data/lib/gemstash/migrations/02_authorizations.rb +2 -0
  52. data/lib/gemstash/migrations/03_cached_gems.rb +2 -0
  53. data/lib/gemstash/migrations/04_health_tests.rb +2 -0
  54. data/lib/gemstash/puma.rb +2 -0
  55. data/lib/gemstash/rack_env_rewriter.rb +11 -2
  56. data/lib/gemstash/specs_builder.rb +5 -1
  57. data/lib/gemstash/storage.rb +17 -7
  58. data/lib/gemstash/upstream.rb +8 -5
  59. data/lib/gemstash/version.rb +4 -2
  60. data/lib/gemstash/web.rb +8 -4
  61. data/lib/gemstash.rb +3 -1
  62. metadata +40 -133
@@ -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)
@@ -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
@@ -56,9 +58,7 @@ module Gemstash
56
58
  resource_exist = storage.resource(full_name).exist?
57
59
  resource_is_indexed = storage.resource(full_name).properties[:indexed] if resource_exist
58
60
 
59
- if resource_exist && resource_is_indexed
60
- raise ExistingVersionError, "Cannot push to an existing version!"
61
- end
61
+ raise ExistingVersionError, "Cannot push to an existing version!" if resource_exist && resource_is_indexed
62
62
 
63
63
  storage.resource(full_name).save({ gem: @content }, indexed: true)
64
64
  end
@@ -78,6 +78,7 @@ module Gemstash
78
78
  existing = Gemstash::DB::Version.find_by_spec(gem_id, spec)
79
79
  raise ExistingVersionError, "Cannot push to an existing version!" if existing && existing.indexed
80
80
  raise YankedVersionError, "Cannot push to a yanked version!" if existing && !existing.indexed
81
+
81
82
  version_id = Gemstash::DB::Version.insert_by_spec(gem_id, spec)
82
83
  Gemstash::DB::Dependency.insert_by_spec(version_id, spec)
83
84
  end
@@ -120,11 +121,12 @@ module Gemstash
120
121
 
121
122
  def cleanup
122
123
  return unless @tempfile
124
+
123
125
  @tempfile.close
124
126
  @tempfile.unlink
125
127
  end
126
128
  end
127
129
 
128
- GemPusher.send(:include, LegacyRubyGemsSupport)
130
+ GemPusher.include LegacyRubyGemsSupport
129
131
  end
130
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
@@ -15,6 +17,7 @@ module Gemstash
15
17
  def self.matches?(env)
16
18
  rewriter = rack_env_rewriter.for(env)
17
19
  return false unless rewriter.matches?
20
+
18
21
  rewriter.rewrite
19
22
  true
20
23
  end
@@ -44,7 +47,7 @@ module Gemstash
44
47
  end
45
48
 
46
49
  def serve_versions
47
- halt 403, "Not yet supported"
50
+ halt 404, "Not yet supported"
48
51
  end
49
52
 
50
53
  def serve_info(name)
@@ -54,7 +57,7 @@ module Gemstash
54
57
  def serve_marshal(id)
55
58
  authorization.protect(self) do
56
59
  auth.check("fetch") if gemstash_env.config[:protected_fetch]
57
- gem_full_name = id.sub(/\.gemspec\.rz\z/, "")
60
+ gem_full_name = id.delete_suffix(".gemspec.rz")
58
61
  gem = fetch_gem(gem_full_name)
59
62
  halt 404 unless gem.exist?(:spec)
60
63
  content_type "application/octet-stream"
@@ -69,7 +72,7 @@ module Gemstash
69
72
  def serve_gem(id)
70
73
  authorization.protect(self) do
71
74
  auth.check("fetch") if gemstash_env.config[:protected_fetch]
72
- gem_full_name = id.sub(/\.gem\z/, "")
75
+ gem_full_name = id.delete_suffix(".gem")
73
76
  gem = fetch_gem(gem_full_name)
74
77
  content_type "application/octet-stream"
75
78
  gem.content(:gem)
@@ -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)
@@ -90,8 +93,10 @@ module Gemstash
90
93
  private
91
94
 
92
95
  def upstream
93
- @upstream ||= Gemstash::Upstream.new(env["gemstash.upstream"],
94
- user_agent: env["gemstash.user-agent"])
96
+ @upstream ||= Gemstash::Upstream.new(
97
+ env["gemstash.upstream"],
98
+ user_agent: env["gemstash.user-agent"]
99
+ )
95
100
  end
96
101
 
97
102
  def index_upstream
@@ -135,6 +140,7 @@ module Gemstash
135
140
 
136
141
  def set_gem_headers(gem, resource_type)
137
142
  return unless gem.property?(:headers, resource_type)
143
+
138
144
  gem_headers = gem.properties[:headers][resource_type]
139
145
  headers["Content-Type"] = gem_headers["content-type"] if gem_headers.include?("content-type")
140
146
  headers["Last-Modified"] = gem_headers["last-modified"] if gem_headers.include?("last-modified")
@@ -192,7 +198,7 @@ module Gemstash
192
198
  # default upstream).
193
199
  class RubygemsSource < Gemstash::GemSource::UpstreamSource
194
200
  def self.matches?(env)
195
- env["gemstash.upstream"] = if env["HTTP_X_GEMFILE_SOURCE"].to_s.empty?
201
+ env["gemstash.upstream"] = if env["gemstash.env"].config[:ignore_gemfile_source] || env["HTTP_X_GEMFILE_SOURCE"].to_s.empty?
196
202
  env["gemstash.env"].config[:rubygems_url]
197
203
  else
198
204
  env["HTTP_X_GEMFILE_SOURCE"]
@@ -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
@@ -52,9 +54,11 @@ module Gemstash
52
54
  def update_database
53
55
  gemstash_env.db.transaction do
54
56
  raise UnknownGemError, "Cannot yank an unknown gem!" unless Gemstash::DB::Rubygem[name: @gem_name]
57
+
55
58
  version = Gemstash::DB::Version.find_by_full_name(full_name)
56
59
  raise UnknownVersionError, "Cannot yank an unknown version!" unless version
57
60
  raise YankedVersionError, "Cannot yank an already yanked version!" unless version.indexed
61
+
58
62
  version.deindex
59
63
  storage.resource(version.storage_id).update_properties(indexed: false)
60
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
  require "date"
3
5
  require "server_health_check_rack"
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "gemstash"
2
4
  require "faraday"
3
5
  require "faraday_middleware"
4
6
 
5
7
  module Gemstash
6
- #:nodoc:
8
+ # :nodoc:
7
9
  class WebError < StandardError
8
10
  attr_reader :code
9
11
 
@@ -13,19 +15,19 @@ module Gemstash
13
15
  end
14
16
  end
15
17
 
16
- #:nodoc:
18
+ # :nodoc:
17
19
  class ConnectionError < WebError
18
20
  def initialize(message)
19
21
  super(message, 502) # Bad Gateway
20
22
  end
21
23
  end
22
24
 
23
- #:nodoc:
25
+ # :nodoc:
24
26
  class HTTPClient
25
27
  extend Gemstash::Env::Helper
26
28
  include Gemstash::Logging
27
29
 
28
- DEFAULT_USER_AGENT = "Gemstash/#{Gemstash::VERSION}".freeze
30
+ DEFAULT_USER_AGENT = "Gemstash/#{Gemstash::VERSION}"
29
31
 
30
32
  def self.for(upstream)
31
33
  client = Faraday.new(upstream.to_s) do |config|
@@ -33,12 +35,17 @@ module Gemstash
33
35
  config.adapter :net_http
34
36
  config.options.timeout = gemstash_env.config[:fetch_timeout]
35
37
  end
38
+
39
+ client.basic_auth(upstream.user, upstream.password) if upstream.auth?
40
+
36
41
  user_agent = "#{upstream.user_agent} " unless upstream.user_agent.to_s.empty?
37
42
  user_agent = user_agent.to_s + DEFAULT_USER_AGENT
38
43
 
39
44
  new(client, user_agent: user_agent)
40
45
  end
41
46
 
47
+ attr_reader :client
48
+
42
49
  def initialize(client = nil, user_agent: nil)
43
50
  @client = client
44
51
  @user_agent = user_agent || DEFAULT_USER_AGENT
@@ -71,6 +78,7 @@ module Gemstash
71
78
  rescue Faraday::ConnectionFailed => e
72
79
  log_error("Connection failure", e)
73
80
  raise(ConnectionError, e.message) unless times > 0
81
+
74
82
  log.info "retrying... #{times} more times"
75
83
  end
76
84
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "logger"
2
4
  require "puma/events"
3
5
 
4
6
  module Gemstash
5
- #:nodoc:
7
+ # :nodoc:
6
8
  module Logging
7
9
  LEVELS = {
8
10
  debug: Logger::DEBUG,