gemstash 2.0.0 → 2.2.0

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.
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,