bundler-alive 0.1.2 → 0.1.3
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.
- checksums.yaml +4 -4
- data/.rspec +1 -0
- data/Gemfile +5 -1
- data/README.md +11 -2
- data/lib/bundler/alive/announcer.rb +31 -0
- data/lib/bundler/alive/cli.rb +10 -14
- data/lib/bundler/alive/client/gems_api_client.rb +108 -0
- data/lib/bundler/alive/client/gems_api_response.rb +29 -0
- data/lib/bundler/alive/client/git_hub_api.rb +120 -20
- data/lib/bundler/alive/client/source_code_client.rb +5 -2
- data/lib/bundler/alive/doctor.rb +75 -70
- data/lib/bundler/alive/report.rb +35 -0
- data/lib/bundler/alive/reportable.rb +67 -0
- data/lib/bundler/alive/source_code_repository.rb +1 -11
- data/lib/bundler/alive/source_code_repository_url.rb +41 -8
- data/lib/bundler/alive/{gem_status.rb → status.rb} +23 -8
- data/lib/bundler/alive/status_collection.rb +149 -0
- data/lib/bundler/alive/status_result.rb +40 -0
- data/lib/bundler/alive/version.rb +1 -1
- data/lib/bundler/alive.rb +8 -3
- metadata +10 -6
- data/Gemfile.lock +0 -119
- data/lib/bundler/alive/client/gems_api.rb +0 -55
- data/lib/bundler/alive/gem_status_collection.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf64468693c247f87a2ffbce58960dd82d1313614d1433d0d032210f080e8fd4
|
4
|
+
data.tar.gz: a3d9f48ce1e8a932ae954897448acf7ab5cc82123992bd82b72ab33b7a8902b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c4d5747e3b1a133bcc8e1d757fb0ca790b280c667b7f2aa865c95363db66a878f2b0383d436a3b83cb43c19b28d06815c226d7fde09411d626ecdbc0508836f
|
7
|
+
data.tar.gz: e4ad9d70fb50258517e8cfbde02aea45435575e0e41435a26e9c5e35141b6df5e71bbebd85f11837afc6fdaa2b76c89508191234417214471f64c18b43d5f8d9
|
data/.rspec
CHANGED
data/Gemfile
CHANGED
@@ -17,7 +17,11 @@ group :development do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
group :test do
|
20
|
-
|
20
|
+
# Workaround for cc-test-reporter with SimpleCov 0.18.
|
21
|
+
# Stop upgrading SimpleCov until the following issue will be resolved.
|
22
|
+
# https://github.com/codeclimate/test-reporter/issues/418
|
23
|
+
gem "factory_bot"
|
24
|
+
gem "simplecov", "~> 0.10", "< 0.18"
|
21
25
|
gem "vcr"
|
22
26
|
gem "webmock"
|
23
27
|
end
|
data/README.md
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# bundler-alive
|
2
2
|
|
3
|
-

|
4
3
|
[](https://badge.fury.io/rb/bundler-alive)
|
4
|
+

|
5
|
+
[](https://codeclimate.com/github/kyoshidajp/bundler-alive/maintainability)
|
6
|
+
[](https://codeclimate.com/github/kyoshidajp/bundler-alive/test_coverage)
|
5
7
|
|
6
8
|
`bunder-alive` checks if gems in a RubyGem's `Gemfile.lock` are active.
|
7
9
|
|
@@ -17,10 +19,17 @@ $ gem install bunlder-alive
|
|
17
19
|
|
18
20
|
```
|
19
21
|
$ bundle-alive
|
22
|
+
6 gems are in Gemfile.lock
|
23
|
+
..W....
|
24
|
+
Get all source code repository URLs of gems are done!
|
25
|
+
.....
|
20
26
|
Name: journey
|
21
27
|
URL: http://github.com/rails/journey
|
22
28
|
Status: false
|
23
29
|
|
30
|
+
Gem: bundle-alive is not found in RubyGems.org.
|
31
|
+
|
32
|
+
Total: 6 (Dead: 1, Alive: 4, Unknown: 1)
|
24
33
|
Not alive gems are found!
|
25
34
|
```
|
26
35
|
|
@@ -30,7 +39,7 @@ Default `Gemfile.lock` location is in your current directory. You can specify it
|
|
30
39
|
$ bundle-alive -G /path/to/Gemfile.lock
|
31
40
|
```
|
32
41
|
|
33
|
-
In
|
42
|
+
In some cases, the following error is output.
|
34
43
|
|
35
44
|
```
|
36
45
|
Too many requested! Retry later.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler"
|
4
|
+
|
5
|
+
module Bundler
|
6
|
+
module Alive
|
7
|
+
#
|
8
|
+
# Announces check progress
|
9
|
+
#
|
10
|
+
class Announcer
|
11
|
+
DOT = "."
|
12
|
+
|
13
|
+
private_constant :DOT
|
14
|
+
|
15
|
+
#
|
16
|
+
# A new instance of Reporter
|
17
|
+
#
|
18
|
+
def initialize
|
19
|
+
@output = $stdout
|
20
|
+
end
|
21
|
+
|
22
|
+
def announce
|
23
|
+
output.write DOT
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :output
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/bundler/alive/cli.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "bundler/alive"
|
4
4
|
require "bundler/alive/doctor"
|
5
|
+
require "bundler/alive/reportable"
|
5
6
|
|
6
7
|
require "thor"
|
7
8
|
|
@@ -17,19 +18,17 @@ module Bundler
|
|
17
18
|
desc "check [DIR]", "Checks the Gemfile.lock"
|
18
19
|
method_option :gemfile_lock, type: :string, aliases: "-G",
|
19
20
|
default: "Gemfile.lock"
|
21
|
+
method_option :result, type: :string, aliases: "-r",
|
22
|
+
default: "result.toml"
|
20
23
|
|
21
24
|
def check(_dir = Dir.pwd)
|
22
|
-
|
25
|
+
extend Reportable
|
26
|
+
report = check_by_doctor
|
27
|
+
report.save_as_file(options[:result])
|
28
|
+
print_report(report)
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
exit 1
|
27
|
-
end
|
28
|
-
|
29
|
-
exit 0 if doctor.all_alive
|
30
|
-
|
31
|
-
puts "Not alive gems are found!"
|
32
|
-
exit 1
|
30
|
+
exit_status = report.result.all_alive? ? 0 : 1
|
31
|
+
exit exit_status
|
33
32
|
end
|
34
33
|
|
35
34
|
desc "version", "Prints the bundler-alive version"
|
@@ -41,15 +40,12 @@ module Bundler
|
|
41
40
|
|
42
41
|
def check_by_doctor
|
43
42
|
doctor = begin
|
44
|
-
Doctor.new(options[:gemfile_lock])
|
43
|
+
Doctor.new(options[:gemfile_lock], options[:result])
|
45
44
|
rescue Bundler::GemfileLockNotFound
|
46
45
|
exit 1
|
47
46
|
end
|
48
47
|
|
49
48
|
doctor.diagnose
|
50
|
-
doctor.report
|
51
|
-
doctor.save_as_file
|
52
|
-
doctor
|
53
49
|
end
|
54
50
|
end
|
55
51
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "faraday"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
module Bundler
|
7
|
+
module Alive
|
8
|
+
module Client
|
9
|
+
#
|
10
|
+
# RubyGems.org API Client
|
11
|
+
#
|
12
|
+
# @see https://guides.rubygems.org/rubygems-org-api/
|
13
|
+
#
|
14
|
+
class GemsApiClient
|
15
|
+
#
|
16
|
+
# Not found in rubygems.org error
|
17
|
+
#
|
18
|
+
class NotFound < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@error_messages = []
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Gets gems from RubyGems.org
|
27
|
+
#
|
28
|
+
# @param [Array<String>] gem_names
|
29
|
+
#
|
30
|
+
# @return [Client::GemsApiResponse]
|
31
|
+
#
|
32
|
+
def gems_api_response(gem_names, &block)
|
33
|
+
urls = service_with_urls(gem_names, &block)
|
34
|
+
$stdout.puts <<~MESSAGE
|
35
|
+
|
36
|
+
Get all source code repository URLs of gems are done!
|
37
|
+
MESSAGE
|
38
|
+
Client::GemsApiResponse.new(
|
39
|
+
service_with_urls: urls,
|
40
|
+
error_messages: error_messages
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
attr_accessor :error_messages
|
47
|
+
|
48
|
+
def api_url(gem_name)
|
49
|
+
"https://rubygems.org/api/v1/gems/#{gem_name}.json"
|
50
|
+
end
|
51
|
+
|
52
|
+
def connection
|
53
|
+
Faraday.new do |connection|
|
54
|
+
connection.adapter :net_http
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def service_with_urls(gem_names, &block)
|
59
|
+
urls = get_repository_urls(gem_names, &block)
|
60
|
+
urls.each_with_object({}) do |url, hash|
|
61
|
+
service_name = url.service_name
|
62
|
+
hash[service_name] = Array(hash[service_name]) << url
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Returns repository url
|
68
|
+
#
|
69
|
+
# @param [String] gem_name
|
70
|
+
#
|
71
|
+
# @return [SourceCodeRepositoryUrl]
|
72
|
+
#
|
73
|
+
def get_repository_url(gem_name)
|
74
|
+
url = api_url(gem_name)
|
75
|
+
response = connection.get(url)
|
76
|
+
|
77
|
+
raise NotFound, "Gem: #{gem_name} is not found in RubyGems.org." unless response.success?
|
78
|
+
|
79
|
+
body = JSON.parse(response.body)
|
80
|
+
raw_url = source_code_url(body: body, gem_name: gem_name)
|
81
|
+
SourceCodeRepositoryUrl.new(raw_url, gem_name)
|
82
|
+
end
|
83
|
+
|
84
|
+
def source_code_url(body:, gem_name:)
|
85
|
+
url = body["source_code_uri"]
|
86
|
+
return url if SourceCodeRepositoryUrl.support_url?(url)
|
87
|
+
|
88
|
+
url = body["homepage_uri"]
|
89
|
+
return url if SourceCodeRepositoryUrl.support_url?(url)
|
90
|
+
|
91
|
+
raise NotFound, "[#{gem_name}] source code repository is not found in RubyGems.org."
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_repository_urls(gem_names)
|
95
|
+
result = gem_names.map do |gem_name|
|
96
|
+
yield if block_given?
|
97
|
+
get_repository_url(gem_name)
|
98
|
+
rescue StandardError => e
|
99
|
+
$stdout.write "W"
|
100
|
+
error_messages << e.message
|
101
|
+
end
|
102
|
+
|
103
|
+
result.find_all { |obj| obj.instance_of?(Alive::SourceCodeRepositoryUrl) }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bundler
|
4
|
+
module Alive
|
5
|
+
module Client
|
6
|
+
#
|
7
|
+
# Represents API Response of RubyGems.org
|
8
|
+
#
|
9
|
+
class GemsApiResponse
|
10
|
+
attr_reader :service_with_urls, :error_messages
|
11
|
+
|
12
|
+
#
|
13
|
+
# Creates a new StatusResult instance
|
14
|
+
#
|
15
|
+
# @param [StatusCollection|nil] :collection
|
16
|
+
# @param [Array] :error_messages
|
17
|
+
#
|
18
|
+
# @return [GemsApiResponse]
|
19
|
+
#
|
20
|
+
def initialize(service_with_urls:, error_messages:)
|
21
|
+
@service_with_urls = service_with_urls
|
22
|
+
@error_messages = error_messages
|
23
|
+
|
24
|
+
freeze
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -9,9 +9,36 @@ module Bundler
|
|
9
9
|
#
|
10
10
|
# API Client for GitHub API
|
11
11
|
#
|
12
|
+
# @see https://docs.github.com/en/rest/search#search-repositories
|
13
|
+
#
|
12
14
|
module GitHubApi
|
15
|
+
# Environment variable name of GitHub Access Token
|
13
16
|
ACCESS_TOKEN_ENV_NAME = "BUNDLER_ALIVE_GITHUB_TOKEN"
|
14
17
|
|
18
|
+
# Separator of query condition
|
19
|
+
QUERY_CONDITION_SEPARATOR = " "
|
20
|
+
|
21
|
+
# Number of attempts to request after too many requests
|
22
|
+
RETRIES_ON_TOO_MANY_REQUESTS = 3
|
23
|
+
|
24
|
+
# Interval second when retrying request
|
25
|
+
RETRY_INTERVAL_SEC_ON_TOO_MANY_REQUESTS = 120
|
26
|
+
|
27
|
+
#
|
28
|
+
# Max number of conditional operator at once
|
29
|
+
#
|
30
|
+
# @see https://docs.github.com/en/rest/search#limitations-on-query-length
|
31
|
+
QUERY_MAX_OPERATORS_AT_ONCE = 6
|
32
|
+
|
33
|
+
private_constant :QUERY_MAX_OPERATORS_AT_ONCE
|
34
|
+
|
35
|
+
def self.extended(base)
|
36
|
+
base.instance_eval do
|
37
|
+
@rate_limit_exceeded = false
|
38
|
+
@retries_on_too_many_requests = 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
15
42
|
#
|
16
43
|
# Creates a GitHub client
|
17
44
|
#
|
@@ -22,39 +49,112 @@ module Bundler
|
|
22
49
|
end
|
23
50
|
|
24
51
|
#
|
25
|
-
#
|
52
|
+
# Query repository statuses
|
53
|
+
#
|
54
|
+
# @param [Array<RepositoryUrl>] :urls
|
55
|
+
#
|
56
|
+
# @return [StatusResult]
|
57
|
+
#
|
58
|
+
# rubocop:disable Metrics/MethodLength
|
59
|
+
def query(urls:)
|
60
|
+
collection = StatusCollection.new
|
61
|
+
name_with_archived = get_name_with_statuses(urls)
|
62
|
+
urls.each do |url|
|
63
|
+
yield if block_given?
|
64
|
+
|
65
|
+
gem_name = url.gem_name
|
66
|
+
alive = !name_with_archived[gem_name]
|
67
|
+
status = Status.new(name: gem_name, repository_url: url, alive: alive, checked_at: Time.now)
|
68
|
+
collection = collection.add(gem_name, status)
|
69
|
+
end
|
70
|
+
|
71
|
+
StatusResult.new(collection: collection, error_messages: @error_messages,
|
72
|
+
rate_limit_exceeded: @rate_limit_exceeded)
|
73
|
+
end
|
74
|
+
# rubocop:enable Metrics/MethodLength
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
#
|
79
|
+
# Search status of repositories
|
26
80
|
#
|
27
|
-
# @param [
|
81
|
+
# @param [Array<RepositoryUrl>] urls
|
28
82
|
#
|
29
|
-
# @
|
30
|
-
#
|
83
|
+
# @return [Hash<String, Boolean>]
|
84
|
+
# gem name with archived or not
|
85
|
+
#
|
86
|
+
# rubocop:disable Metrics/MethodLength
|
87
|
+
def get_name_with_statuses(urls)
|
88
|
+
raise ArgumentError unless urls.instance_of?(Array)
|
89
|
+
|
90
|
+
name_with_status = {}
|
91
|
+
urls.each_slice(QUERY_MAX_OPERATORS_AT_ONCE) do |sliced_urls|
|
92
|
+
q = search_query(sliced_urls)
|
93
|
+
repositories = search_repositories_with_retry(q)
|
94
|
+
next if repositories.nil?
|
95
|
+
|
96
|
+
repositories.each do |repository|
|
97
|
+
name = repository["name"]
|
98
|
+
name_with_status[name] = repository["archived"]
|
99
|
+
end
|
100
|
+
end
|
101
|
+
name_with_status
|
102
|
+
end
|
103
|
+
# rubocop:enable Metrics/MethodLength
|
104
|
+
|
105
|
+
#
|
106
|
+
# Search query of repositories
|
107
|
+
#
|
108
|
+
# @param [Array<RepositoryUrl>] urls
|
109
|
+
#
|
110
|
+
# @return [String]
|
111
|
+
#
|
112
|
+
def search_query(urls)
|
113
|
+
urls.map do |url|
|
114
|
+
"repo:#{slug(url.url)}"
|
115
|
+
end.join(QUERY_CONDITION_SEPARATOR)
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Search repositories
|
120
|
+
#
|
121
|
+
# @param [String] query
|
31
122
|
#
|
32
123
|
# @raise [Octokit::TooManyRequests]
|
33
124
|
# when too many requested to GitHub.com
|
34
|
-
#
|
35
125
|
# @raise [SourceCodeClient::SearchRepositoryError]
|
36
126
|
# when Error without `Octokit::TooManyRequests`
|
37
127
|
#
|
38
|
-
# @return [
|
128
|
+
# @return [Array<Sawyer::Resource>|nil]
|
39
129
|
#
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
130
|
+
def search_repositories(query)
|
131
|
+
result = @client.search_repositories(query)
|
132
|
+
result[:items]
|
133
|
+
rescue Octokit::TooManyRequests => e
|
134
|
+
raise e
|
135
|
+
rescue StandardError => e
|
136
|
+
@error_messages << e.message
|
137
|
+
[]
|
138
|
+
end
|
139
|
+
|
140
|
+
def search_repositories_with_retry(query)
|
141
|
+
search_repositories(query)
|
142
|
+
rescue Octokit::TooManyRequests
|
143
|
+
if @retries_on_too_many_requests < RETRIES_ON_TOO_MANY_REQUESTS
|
144
|
+
@retries_on_too_many_requests += 1
|
145
|
+
sleep_with_message
|
146
|
+
retry
|
44
147
|
end
|
45
148
|
|
46
|
-
|
149
|
+
@rate_limit_exceeded = true
|
150
|
+
[]
|
151
|
+
end
|
47
152
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
raise SourceCodeClient::RateLimitExceededError, e.message
|
53
|
-
rescue StandardError => e
|
54
|
-
raise SourceCodeClient::SearchRepositoryError, e.message
|
55
|
-
end
|
153
|
+
def sleep_with_message
|
154
|
+
puts "Too many requested. Sleep #{RETRY_INTERVAL_SEC_ON_TOO_MANY_REQUESTS} sec."
|
155
|
+
sleep RETRY_INTERVAL_SEC_ON_TOO_MANY_REQUESTS
|
156
|
+
puts "Retry request (#{@retries_on_too_many_requests}/#{RETRIES_ON_TOO_MANY_REQUESTS})"
|
56
157
|
end
|
57
|
-
# rubocop:enable Metrics/MethodLength
|
58
158
|
|
59
159
|
#
|
60
160
|
# Returns slug of repository URL
|
@@ -7,9 +7,11 @@ module Bundler
|
|
7
7
|
# Represents a source code client
|
8
8
|
#
|
9
9
|
class SourceCodeClient
|
10
|
+
# Error of searching repository
|
10
11
|
class SearchRepositoryError < StandardError
|
11
12
|
end
|
12
13
|
|
14
|
+
# Error of rate limit exceeded
|
13
15
|
class RateLimitExceededError < StandardError
|
14
16
|
end
|
15
17
|
|
@@ -31,10 +33,11 @@ module Bundler
|
|
31
33
|
def initialize(service_name:)
|
32
34
|
raise ArgumentError, "Unknown service: #{service_name}" unless SERVICE_WITH_STRATEGIES.key?(service_name)
|
33
35
|
|
34
|
-
|
35
|
-
extend
|
36
|
+
strategy = SERVICE_WITH_STRATEGIES[service_name]
|
37
|
+
extend strategy
|
36
38
|
|
37
39
|
@client = create_client
|
40
|
+
@error_messages = []
|
38
41
|
|
39
42
|
super()
|
40
43
|
end
|
data/lib/bundler/alive/doctor.rb
CHANGED
@@ -10,113 +10,118 @@ module Bundler
|
|
10
10
|
# Diagnoses a `Gemfile.lock` with a TOML file
|
11
11
|
#
|
12
12
|
class Doctor
|
13
|
-
attr_reader :all_alive, :rate_limit_exceeded_error
|
14
|
-
|
15
13
|
#
|
16
14
|
# A new instance of Doctor
|
17
15
|
#
|
18
16
|
# @param [String] lock_file lock file of gem
|
19
17
|
# @param [String] result_file file of result
|
20
18
|
#
|
21
|
-
def initialize(lock_file, result_file
|
19
|
+
def initialize(lock_file, result_file)
|
22
20
|
@lock_file = lock_file
|
23
21
|
@result_file = result_file
|
24
|
-
@gem_client = Client::
|
22
|
+
@gem_client = Client::GemsApiClient.new
|
25
23
|
@result = nil
|
26
|
-
@
|
27
|
-
@
|
24
|
+
@rate_limit_exceeded = false
|
25
|
+
@announcer = Announcer.new
|
26
|
+
@error_messages = []
|
28
27
|
end
|
29
28
|
|
30
29
|
#
|
31
30
|
# Diagnoses gems in lock file of gem
|
32
31
|
#
|
32
|
+
# @raise [Client::SourceCodeClient::RateLimitExceededError]
|
33
|
+
# When exceeded access rate limit
|
34
|
+
#
|
35
|
+
# @raise [StandardError]
|
36
|
+
# When raised unexpected error
|
37
|
+
#
|
38
|
+
# @return [Report]
|
39
|
+
#
|
33
40
|
def diagnose
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
collection.add(gem_name, gem_status)
|
39
|
-
end
|
41
|
+
$stdout.puts "#{collection_from_gemfile.total_size} gems are in Gemfile.lock"
|
42
|
+
result = _diagnose
|
43
|
+
Report.new(result)
|
40
44
|
end
|
41
45
|
|
46
|
+
private
|
47
|
+
|
48
|
+
attr_reader :lock_file, :result_file, :gem_client, :announcer,
|
49
|
+
:result, :error_messages, :rate_limit_exceeded
|
50
|
+
|
42
51
|
#
|
43
|
-
#
|
52
|
+
# @return [Array<String>]
|
44
53
|
#
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
def no_need_to_get_gems
|
55
|
+
return [] unless File.exist?(result_file)
|
56
|
+
|
57
|
+
toml_hash = TomlRB.load_file(result_file)
|
58
|
+
toml_hash.each_with_object([]) do |(gem_name, v), array|
|
59
|
+
alive = v["alive"]
|
60
|
+
array << gem_name unless alive
|
50
61
|
end
|
51
62
|
end
|
52
63
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
File.write(result_file, body)
|
64
|
+
def diagnose_by_service(service, urls)
|
65
|
+
client = Client::SourceCodeClient.new(service_name: service)
|
66
|
+
client.query(urls: urls) do
|
67
|
+
announcer.announce
|
68
|
+
end
|
59
69
|
end
|
60
70
|
|
61
|
-
|
71
|
+
def result_by_search(collection)
|
72
|
+
gems_api_response = gem_client.gems_api_response(collection.names) do
|
73
|
+
announcer.announce
|
74
|
+
end
|
62
75
|
|
63
|
-
|
76
|
+
service_with_urls = gems_api_response.service_with_urls
|
77
|
+
error_messages.concat(gems_api_response.error_messages)
|
64
78
|
|
65
|
-
|
66
|
-
|
79
|
+
result = StatusResult.new
|
80
|
+
service_with_urls.each do |service, urls|
|
81
|
+
result = result.merge(diagnose_by_service(service, urls))
|
82
|
+
end
|
83
|
+
result
|
67
84
|
end
|
68
85
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
|
86
|
+
def fetch_target_collection(base_collection, gem_names)
|
87
|
+
collection = StatusCollection.new
|
88
|
+
base_collection.each do |name, status|
|
89
|
+
next if gem_names.include?(name)
|
73
90
|
|
74
|
-
|
75
|
-
|
91
|
+
collection = collection.add(name, status)
|
92
|
+
end
|
93
|
+
collection
|
76
94
|
end
|
77
95
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
checked_at: v["checked_at"])
|
87
|
-
collection.add(gem_name, gem_status)
|
96
|
+
def collection_from_gemfile
|
97
|
+
gems_from_lockfile.each_with_object(StatusCollection.new) do |gem, collection|
|
98
|
+
gem_name = gem.name
|
99
|
+
status = Status.new(name: gem_name,
|
100
|
+
repository_url: nil,
|
101
|
+
alive: nil,
|
102
|
+
checked_at: nil)
|
103
|
+
collection.add(gem_name, status)
|
88
104
|
end
|
89
105
|
end
|
90
106
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
107
|
+
def _diagnose
|
108
|
+
collection = fetch_target_collection(collection_from_gemfile, no_need_to_get_gems)
|
109
|
+
result = result_by_search(collection)
|
110
|
+
collection_from_toml_file = StatusCollection.new_from_toml_file(result_file)
|
111
|
+
new_collection = collection_from_gemfile.merge(collection_from_toml_file)
|
112
|
+
.merge(result.collection)
|
113
|
+
|
114
|
+
messages = error_messages.concat(result.error_messages)
|
115
|
+
StatusResult.new(collection: new_collection,
|
116
|
+
error_messages: messages,
|
117
|
+
rate_limit_exceeded: result.rate_limit_exceeded)
|
95
118
|
end
|
96
119
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
unless @rate_limit_exceeded_error
|
103
|
-
begin
|
104
|
-
source_code_url = gem_client.get_repository_url(gem_name)
|
105
|
-
is_alive = SourceCodeRepository.new(url: source_code_url).alive?
|
106
|
-
rescue Client::SourceCodeClient::RateLimitExceededError => e
|
107
|
-
@rate_limit_exceeded_error = true
|
108
|
-
puts e.message
|
109
|
-
rescue StandardError => e
|
110
|
-
puts e.message
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
GemStatus.new(name: gem_name,
|
115
|
-
repository_url: source_code_url,
|
116
|
-
alive: is_alive,
|
117
|
-
checked_at: Time.now)
|
120
|
+
def gems_from_lockfile
|
121
|
+
lock_file_body = File.read(@lock_file)
|
122
|
+
lock_file = Bundler::LockfileParser.new(lock_file_body)
|
123
|
+
lock_file.specs
|
118
124
|
end
|
119
|
-
# rubocop:enable Metrics/MethodLength
|
120
125
|
end
|
121
126
|
end
|
122
127
|
end
|