gems_bond 1.0.4 → 1.1.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.
- checksums.yaml +4 -4
- data/lib/gems_bond.rb +3 -2
- data/lib/gems_bond/configuration.rb +2 -0
- data/lib/gems_bond/{examination_helper.rb → examination.rb} +30 -18
- data/lib/gems_bond/fetchers/fetcher.rb +34 -0
- data/lib/gems_bond/{fetcher → fetchers}/github.rb +54 -10
- data/lib/gems_bond/fetchers/ruby_gems.rb +82 -0
- data/lib/gems_bond/gem.rb +128 -10
- data/lib/gems_bond/helpers/concurrency_helper.rb +24 -0
- data/lib/gems_bond/helpers/formatting_helper.rb +48 -0
- data/lib/gems_bond/printers/csv.rb +54 -0
- data/lib/gems_bond/printers/html.rb +61 -0
- data/lib/gems_bond/printers/printer.rb +58 -0
- data/lib/gems_bond/printers/stdout.rb +90 -0
- data/lib/gems_bond/railtie.rb +2 -1
- data/lib/gems_bond/spy/all.rb +93 -0
- data/lib/gems_bond/spy/one.rb +59 -0
- data/lib/gems_bond/version.rb +1 -1
- data/lib/tasks/gems_bond/spy/all.rake +36 -0
- data/lib/tasks/gems_bond/spy/one.rake +29 -0
- metadata +17 -10
- data/lib/gems_bond/fetch_helper.rb +0 -71
- data/lib/gems_bond/fetcher/ruby_gems.rb +0 -58
- data/lib/gems_bond/printer.rb +0 -88
- data/lib/gems_bond/spy.rb +0 -62
- data/lib/tasks/gems_bond/spy.rake +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2cafc096896bf8383fde404d0c47020e4b8f9b1fe49c5cabfc1e8357c766682e
|
4
|
+
data.tar.gz: 48b00b4c32c30eafa88fa8c839b8ad9c7ddab251420e501c6010853062064047
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfe4e248242f9609bad37d5b72cd5a6ef1557ec59039729c76b5f5658f08dea6dcf9ab5c563bab778c27de15688ad77b3f7d9cbea4e569c22f0bfb84b3aa3fd2
|
7
|
+
data.tar.gz: b46f8529d54c8a3b3e6de88f9951bb78c61e2747bb8033de3f712556a874d58548428aa1d2fea8216997487e9962f906b112c1c268964d426f4d2a68b27a5308
|
data/lib/gems_bond.rb
CHANGED
@@ -5,11 +5,12 @@ require "gems_bond/railtie" if defined?(Rails)
|
|
5
5
|
|
6
6
|
# Gem module
|
7
7
|
module GemsBond
|
8
|
-
class Error < StandardError; end
|
9
|
-
|
10
8
|
class << self
|
11
9
|
attr_accessor :configuration
|
12
10
|
|
11
|
+
# Configures Gems Bond
|
12
|
+
# @return GemsBond::Configuration
|
13
|
+
# @yieldparam [Proc] configuration to apply
|
13
14
|
def configure
|
14
15
|
self.configuration ||= Configuration.new
|
15
16
|
yield(configuration)
|
@@ -1,16 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "yaml"
|
4
|
+
|
3
5
|
module GemsBond
|
4
6
|
# Examines gem sanity
|
5
|
-
module
|
7
|
+
module Examination
|
6
8
|
SCORES = YAML.safe_load(File.read(File.join(File.dirname(__FILE__), "scores.yml")))
|
7
9
|
BOUNDARIES = SCORES["boundaries"]
|
8
10
|
RESULTS = SCORES["results"]
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
# @!method activity_score
|
13
|
+
# Returns activity score
|
14
|
+
# @return [Integer, nil] in [0, 1] (memoized)
|
15
|
+
|
16
|
+
# @!method popularity_score
|
17
|
+
# Returns popularity score
|
18
|
+
# @return [Integer, nil] in [0, 1] (memoized)
|
13
19
|
|
20
|
+
# @!method average_score
|
21
|
+
# Returns average score
|
22
|
+
# @return [Integer, nil] in [0, 1] (memoized)
|
14
23
|
RESULTS.each do |result, values|
|
15
24
|
define_method("#{result}_score") do
|
16
25
|
memoize("#{result}_score") do
|
@@ -27,6 +36,9 @@ module GemsBond
|
|
27
36
|
|
28
37
|
# Scores getters and calculation
|
29
38
|
|
39
|
+
# For each inspected data, generate two methods:
|
40
|
+
# - <data>_score that memoizes the calculated score
|
41
|
+
# - calculate_<data>_score that calculates the score and returns [Integer, nil] in [0, 1]
|
30
42
|
BOUNDARIES.each_key do |key|
|
31
43
|
# create a _score getter for each key
|
32
44
|
define_method("#{key}_score") do
|
@@ -61,6 +73,15 @@ module GemsBond
|
|
61
73
|
end
|
62
74
|
end
|
63
75
|
|
76
|
+
# Returns a score with a logarithmic approach
|
77
|
+
# @param value [Float] the value for inspected data
|
78
|
+
# @param comparison [Numeric] the value giving the maximal score (1)
|
79
|
+
# @returns [Float]
|
80
|
+
# @example
|
81
|
+
# soften(10.to_f,100.to_f) #=> 0.46
|
82
|
+
# The idea is that a gem with half as much stars
|
83
|
+
# than rails gem (which is very high and stands for comparison here)
|
84
|
+
# should get a very high score but still be behind rails itself
|
64
85
|
def soften(value, comparison)
|
65
86
|
# returns a shaped curve
|
66
87
|
sigmoid = ->(x) { 1 / (1 + Math.exp(-x * 10)) }
|
@@ -69,8 +90,11 @@ module GemsBond
|
|
69
90
|
(sigmoid.call(value / comparison) - 0.5) * 2
|
70
91
|
end
|
71
92
|
|
72
|
-
#
|
73
|
-
|
93
|
+
# Returns an average after including weight for each value
|
94
|
+
# @param scores [Array<Array<Float, Integer>>] each hash looks like [value, weight]
|
95
|
+
# @returns [Float]
|
96
|
+
# @example
|
97
|
+
# weighted_average([[4.0, 2], [1.0, 3]]) #=> 2.2
|
74
98
|
def weighted_average(scores)
|
75
99
|
acc = 0
|
76
100
|
weight = 0
|
@@ -85,17 +109,5 @@ module GemsBond
|
|
85
109
|
|
86
110
|
acc / weight
|
87
111
|
end
|
88
|
-
|
89
|
-
# --- VERSION STATUS
|
90
|
-
|
91
|
-
def calculate_version_gap
|
92
|
-
return unless version && versions
|
93
|
-
|
94
|
-
index = versions.index { |v| v[:number] == version }
|
95
|
-
return unless index
|
96
|
-
|
97
|
-
gap = versions[0..index].count { |v| !v[:prerelease] } - 1
|
98
|
-
gap.positive? ? gap : 0
|
99
|
-
end
|
100
112
|
end
|
101
113
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "octokit"
|
4
|
+
|
5
|
+
module GemsBond
|
6
|
+
module Fetchers
|
7
|
+
class NotStartedError < StandardError; end
|
8
|
+
|
9
|
+
# Fetches data
|
10
|
+
class Fetcher
|
11
|
+
# Initializes an instance
|
12
|
+
# @param param [Object] Fetcher dependent
|
13
|
+
# @return [GemsBond::Fetchers::Fetcher]
|
14
|
+
def initialize(param); end
|
15
|
+
|
16
|
+
# Starts the service and returns self
|
17
|
+
# @note rescue connection errors with nil
|
18
|
+
def start
|
19
|
+
@started = true
|
20
|
+
end
|
21
|
+
|
22
|
+
# Starts the service and returns self
|
23
|
+
# @note rescue connection errors with nil
|
24
|
+
def stop
|
25
|
+
@started = false
|
26
|
+
end
|
27
|
+
|
28
|
+
# Is the service started?
|
29
|
+
def started?
|
30
|
+
@started
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,58 +1,79 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "octokit"
|
4
|
+
require "gems_bond/fetchers/fetcher"
|
4
5
|
|
5
6
|
module GemsBond
|
6
|
-
module
|
7
|
+
module Fetchers
|
7
8
|
# Fetches data from GitHub
|
8
|
-
class Github
|
9
|
+
class Github < Fetcher
|
10
|
+
# GitHub repository pattern, e.g.: "https://github.com/BigBigDoudou/gems_bond"
|
9
11
|
REPOSITORY_REGEX = %r{https?://github.com/(?<repository>.*/.*)}.freeze
|
10
12
|
|
11
13
|
class << self
|
14
|
+
# Validates that `url` matches GitHub repository URL
|
12
15
|
def valid_url?(url)
|
13
16
|
url&.match?(REPOSITORY_REGEX)
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
20
|
+
# Initializes an instance
|
21
|
+
# @param url [String] URL of the GitHub repository
|
22
|
+
# @return [GemsBond::Fetchers::Github]
|
17
23
|
def initialize(url)
|
24
|
+
super(url)
|
18
25
|
@url = url
|
19
26
|
end
|
20
27
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
28
|
+
# Starts the service
|
29
|
+
# @return [Boolean]
|
30
|
+
# @note rescue connection errors with nil
|
25
31
|
def start
|
32
|
+
super
|
26
33
|
parse_url
|
27
34
|
login
|
35
|
+
# ensure repository exists (otherwise it raises Octokit error)
|
28
36
|
set_repository
|
29
|
-
self
|
30
37
|
rescue Octokit::Unauthorized, Octokit::InvalidRepository, Octokit::NotFound
|
31
|
-
|
38
|
+
stop
|
32
39
|
end
|
33
40
|
|
41
|
+
# Returns number of forks
|
42
|
+
# @return [Integer]
|
34
43
|
def forks_count
|
35
44
|
@repository["forks"]
|
36
45
|
end
|
37
46
|
|
47
|
+
# Returns number of stars
|
48
|
+
# @return [Integer]
|
38
49
|
def stars_count
|
39
50
|
@repository["watchers"]
|
40
51
|
end
|
41
52
|
|
53
|
+
# Returns number of contributors
|
54
|
+
# @return [Integer]
|
55
|
+
# @note GitHub API does not provide this number out of the box
|
56
|
+
# so we fetch all repository contributors and paginate with 1 per page
|
57
|
+
# thus the last page (from headers) should equal the number of contributors
|
42
58
|
def contributors_count
|
43
59
|
client = Octokit::Client.new(access_token: token, per_page: 1)
|
44
60
|
client.contributors(@repository_path)
|
45
61
|
response = client.last_response
|
46
62
|
links = response.headers[:link]
|
63
|
+
# e.g.: "[...] <https://api.github.com/repositories/8514/contributors?per_page=1&page=377>; rel=\"last\""
|
47
64
|
return 0 unless links
|
48
65
|
|
49
|
-
Integer(links.match(/.*page=(?<last>\d+)>; rel="last"/)[:last], 10)
|
66
|
+
Integer(links.match(/.*per_page=1&page=(?<last>\d+)>; rel="last"/)[:last], 10)
|
50
67
|
end
|
51
68
|
|
69
|
+
# Returns number of open issues
|
70
|
+
# @return [Integer]
|
52
71
|
def open_issues_count
|
53
72
|
@repository["open_issues"]
|
54
73
|
end
|
55
74
|
|
75
|
+
# Returns date of last commit (on main branch)
|
76
|
+
# @return [Date]
|
56
77
|
def last_commit_date
|
57
78
|
date = client.commits(@repository_path).first[:commit][:committer][:date]
|
58
79
|
return unless date
|
@@ -60,12 +81,16 @@ module GemsBond
|
|
60
81
|
Date.parse(date.to_s)
|
61
82
|
end
|
62
83
|
|
84
|
+
# Returns number of days since last commit
|
85
|
+
# @return [Date]
|
63
86
|
def days_since_last_commit
|
64
87
|
return unless last_commit_date
|
65
88
|
|
66
|
-
Date.today - last_commit_date
|
89
|
+
Integer(Date.today - last_commit_date)
|
67
90
|
end
|
68
91
|
|
92
|
+
# Returns size of the lib directory
|
93
|
+
# @return [Integer]
|
69
94
|
def lib_size
|
70
95
|
contents_size = dir_size("lib")
|
71
96
|
return unless contents_size
|
@@ -78,6 +103,9 @@ module GemsBond
|
|
78
103
|
|
79
104
|
private
|
80
105
|
|
106
|
+
# Parses url to find out repository path
|
107
|
+
# @return [String]
|
108
|
+
# @raise Octokit::InvalidRepository if the url pattern is invalid
|
81
109
|
def parse_url
|
82
110
|
matches = @url.match(REPOSITORY_REGEX)
|
83
111
|
raise Octokit::InvalidRepository unless matches
|
@@ -86,28 +114,44 @@ module GemsBond
|
|
86
114
|
@repository_path = "#{path[0]}/#{path[1]}"
|
87
115
|
end
|
88
116
|
|
117
|
+
# Logs with client
|
118
|
+
# @return [String] GitHub'username
|
89
119
|
def login
|
120
|
+
return unless token
|
121
|
+
|
90
122
|
@login ||= client.user.login
|
91
123
|
end
|
92
124
|
|
125
|
+
# Initializes a client
|
126
|
+
# @return [Octokit::Client]
|
93
127
|
def client
|
94
128
|
Octokit::Client.new(access_token: token)
|
95
129
|
end
|
96
130
|
|
131
|
+
# Returns token from configuration
|
132
|
+
# @return [String, nil]
|
97
133
|
def token
|
98
134
|
GemsBond.configuration&.github_token
|
99
135
|
end
|
100
136
|
|
137
|
+
# Returns repository object
|
138
|
+
# @return [Sawyer::Resource]
|
101
139
|
def set_repository
|
102
140
|
@repository = client.repo(@repository_path)
|
103
141
|
end
|
104
142
|
|
143
|
+
# Returns size of the given directory
|
144
|
+
# @param dir_path [String] path to the directory, e.g.: "lib/devise/strategies"
|
145
|
+
# @return [Integer]
|
146
|
+
# @note sum size of each subdirectories recursively
|
105
147
|
def dir_size(dir_path)
|
106
148
|
contents = client.contents(@repository_path, path: dir_path)
|
149
|
+
# starts accumulator with size of files
|
107
150
|
acc =
|
108
151
|
contents
|
109
152
|
.select { |content| content[:type] == "file" }
|
110
153
|
.sum { |content| content[:size] }
|
154
|
+
# adds size of subdirectories to the accumulator, with recursion
|
111
155
|
acc +=
|
112
156
|
contents
|
113
157
|
.select { |content| content[:type] == "dir" }
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "gems"
|
4
|
+
require "rubygems"
|
5
|
+
require "gems_bond/fetchers/fetcher"
|
6
|
+
|
7
|
+
module GemsBond
|
8
|
+
module Fetchers
|
9
|
+
# Fetches data from RubyGems
|
10
|
+
class RubyGems < Fetcher
|
11
|
+
# Initializes an instance
|
12
|
+
# @param name [String] name of the gem
|
13
|
+
# @return [GemsBond::Fetchers::RubyGems]
|
14
|
+
def initialize(name)
|
15
|
+
super(name)
|
16
|
+
@name = name
|
17
|
+
end
|
18
|
+
|
19
|
+
# Starts the service
|
20
|
+
# @return [Boolean]
|
21
|
+
# @note rescue connection errors with nil
|
22
|
+
def start
|
23
|
+
super
|
24
|
+
# ensure gem exists (otherwise it raises Gems error)
|
25
|
+
@info = Gems.info(@name)
|
26
|
+
rescue Gems::NotFound
|
27
|
+
stop
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns gem description
|
31
|
+
# @return [String]
|
32
|
+
def info
|
33
|
+
@info["info"]
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns number of downloads
|
37
|
+
# @return [Integer]
|
38
|
+
def downloads_count
|
39
|
+
Gems.total_downloads(@name)[:total_downloads]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns source code URI
|
43
|
+
# @return [String]
|
44
|
+
def source_code_uri
|
45
|
+
@info["source_code_uri"]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns versions data (number, date and if it is a prerelease)
|
49
|
+
# @return [Array<Hash>]
|
50
|
+
# @note each hash structure: { number: String, created_at: Date, prerelease: Boolean }
|
51
|
+
def versions
|
52
|
+
Gems.versions(@name).map do |version|
|
53
|
+
{
|
54
|
+
number: version["number"],
|
55
|
+
created_at: Date.parse(version["created_at"]),
|
56
|
+
prerelease: version["prerelease"]
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns last version number
|
62
|
+
# @return [String]
|
63
|
+
def last_version
|
64
|
+
versions&.first&.dig(:number)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns last version date
|
68
|
+
# @return [Date]
|
69
|
+
def last_version_date
|
70
|
+
versions&.first&.dig(:created_at)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns number of days since last version
|
74
|
+
# @return [Integer]
|
75
|
+
def days_since_last_version
|
76
|
+
return unless last_version_date
|
77
|
+
|
78
|
+
Integer(Date.today - last_version_date)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/gems_bond/gem.rb
CHANGED
@@ -1,46 +1,164 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "gems_bond/
|
4
|
-
require "gems_bond/
|
3
|
+
require "gems_bond/helpers/concurrency_helper"
|
4
|
+
require "gems_bond/fetchers/ruby_gems"
|
5
|
+
require "gems_bond/fetchers/github"
|
6
|
+
require "gems_bond/examination"
|
5
7
|
|
6
8
|
module GemsBond
|
7
9
|
# Handles gem data
|
8
10
|
class Gem
|
9
|
-
include
|
10
|
-
include
|
11
|
+
include GemsBond::Helpers::ConcurrencyHelper
|
12
|
+
include GemsBond::Examination
|
11
13
|
|
12
|
-
|
14
|
+
attr_reader :unknown
|
15
|
+
|
16
|
+
RUBY_GEM_KEYS = %i[
|
17
|
+
days_since_last_version downloads_count info last_version last_version_date source_code_uri versions
|
18
|
+
].freeze
|
19
|
+
|
20
|
+
GITHUB_KEYS = %i[
|
21
|
+
contributors_count days_since_last_commit forks_count last_commit_date open_issues_count stars_count
|
22
|
+
].freeze
|
23
|
+
|
24
|
+
# Initializes an instance
|
25
|
+
# @param dependency [Bundler::Dependency]
|
26
|
+
# @param unknown [Boolean] is it a current dependency?
|
27
|
+
# @return [GemsBond::Gem]
|
28
|
+
def initialize(dependency, unknown: false)
|
13
29
|
@dependency = dependency
|
30
|
+
@unknown = unknown
|
14
31
|
end
|
15
32
|
|
33
|
+
# Is the gem hosted on RubyGems?
|
34
|
+
# @retun [Boolean]
|
35
|
+
def exist?
|
36
|
+
ruby_gems_fetcher.started?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns name
|
40
|
+
# @return [String] (memoized)
|
16
41
|
def name
|
17
42
|
memoize(__method__) { @dependency.name }
|
18
43
|
end
|
19
44
|
|
45
|
+
# Returns description
|
46
|
+
# @return [String] (memoized)
|
20
47
|
def description
|
21
|
-
memoize(__method__)
|
48
|
+
memoize(__method__) do
|
49
|
+
unknown ? info : @dependency.to_spec.description
|
50
|
+
end
|
22
51
|
end
|
23
52
|
|
53
|
+
# Returns used version
|
54
|
+
# @return [String] (memoized)
|
24
55
|
def version
|
25
|
-
memoize(__method__)
|
56
|
+
memoize(__method__) do
|
57
|
+
@dependency.to_spec.version.to_s unless unknown
|
58
|
+
end
|
26
59
|
end
|
27
60
|
|
61
|
+
# Returns homepage
|
62
|
+
# @return [String] (memoized)
|
28
63
|
def homepage
|
29
|
-
memoize(__method__)
|
64
|
+
memoize(__method__) do
|
65
|
+
@dependency.to_spec.homepage unless unknown
|
66
|
+
end
|
30
67
|
end
|
31
68
|
|
69
|
+
# Returns url
|
70
|
+
# @return [String]
|
32
71
|
def url
|
33
72
|
homepage || source_code_uri
|
34
73
|
end
|
35
74
|
|
75
|
+
# Returns GitHub url if exist
|
76
|
+
# @return [String, nil]
|
36
77
|
def github_url
|
37
|
-
|
78
|
+
[homepage, source_code_uri].find do |url|
|
79
|
+
GemsBond::Fetchers::Github.valid_url?(url)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
RUBY_GEM_KEYS.each do |key|
|
84
|
+
define_method(key) do
|
85
|
+
memoize(key) do
|
86
|
+
fetch(ruby_gems_fetcher, key)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
GITHUB_KEYS.each do |key|
|
92
|
+
define_method(key) do
|
93
|
+
memoize(key) do
|
94
|
+
fetch(github_fetcher, key)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns gap between installed and last released version, in days
|
100
|
+
# @return [Integer, nil] (memoized)
|
101
|
+
def version_gap
|
102
|
+
memoize(:version_gap) do
|
103
|
+
return unless version && versions
|
104
|
+
|
105
|
+
index = versions.index { |v| v[:number] == version }
|
106
|
+
return unless index
|
38
107
|
|
39
|
-
|
108
|
+
gap = versions[0..index].count { |v| !v[:prerelease] } - 1
|
109
|
+
gap.positive? ? gap : 0
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# Fetches data from APIs
|
114
|
+
# @param concurrency [Boolean] should it be run concurrently?
|
115
|
+
# @param verbose [Boolean] should gem's name be stdout?
|
116
|
+
# @return [void]
|
117
|
+
def prepare_data(keys: nil, concurrency: false, verbose: false)
|
118
|
+
fetch_key = ->(key) { (keys.nil? || key.in?(keys)) && __send__(key) }
|
119
|
+
if concurrency
|
120
|
+
each_concurrently(RUBY_GEM_KEYS + GITHUB_KEYS, &fetch_key)
|
121
|
+
else
|
122
|
+
(RUBY_GEM_KEYS + GITHUB_KEYS).each(&fetch_key)
|
123
|
+
end
|
124
|
+
puts(name) if verbose
|
40
125
|
end
|
41
126
|
|
42
127
|
private
|
43
128
|
|
129
|
+
# Fetches the given data with the given fetcher
|
130
|
+
# @param fetcher [GemsBond::Fetchers]
|
131
|
+
# @param key [String]
|
132
|
+
# @return [Object, nil]
|
133
|
+
def fetch(fetcher, key)
|
134
|
+
return if fetcher.nil?
|
135
|
+
raise GemsBond::Fetchers::NotStartedError unless fetcher.started?
|
136
|
+
|
137
|
+
fetcher.public_send(key)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns a started RubyGems fetcher
|
141
|
+
# @return [GemsBond::Fetchers::RubyGems, nil]
|
142
|
+
# @note #start is needed to ensure the fetcher works
|
143
|
+
def ruby_gems_fetcher
|
144
|
+
return @ruby_gems_fetcher if defined?(@ruby_gems_fetcher)
|
145
|
+
|
146
|
+
@ruby_gems_fetcher = GemsBond::Fetchers::RubyGems.new(name).tap(&:start)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Returns a started GitHub fetcher
|
150
|
+
# @return [GemsBond::Fetchers::Github, nil]
|
151
|
+
# @note #start is needed to ensure the fetcher works (especially the token)
|
152
|
+
def github_fetcher
|
153
|
+
return @github_fetcher if defined?(@github_fetcher)
|
154
|
+
|
155
|
+
@github_fetcher = github_url && GemsBond::Fetchers::Github.new(github_url).tap(&:start)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Memoizes the given key and apply the given block
|
159
|
+
# @param key [String] the instance variable key
|
160
|
+
# @yieldparam [Object] the value to memoize
|
161
|
+
# @return [Object]
|
44
162
|
def memoize(key)
|
45
163
|
return instance_variable_get("@#{key}") if instance_variable_defined?("@#{key}")
|
46
164
|
|