gem_updater 6.1.0 → 7.0.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/gem_updater/changelog_parser/github_parser.rb +49 -0
- data/lib/gem_updater/changelog_parser.rb +64 -0
- data/lib/gem_updater/{gem_file.rb → gemfile.rb} +2 -2
- data/lib/gem_updater/ruby_gems_fetcher.rb +9 -61
- data/lib/gem_updater/version.rb +1 -1
- data/lib/gem_updater.rb +14 -28
- metadata +5 -18
- data/lib/gem_updater/source_page_parser.rb +0 -173
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc62f5f20f9d239d4eea066d409fd9900ba139630287a2884fe2497c09ce91e7
|
4
|
+
data.tar.gz: 0dc7e3a0446c91dc1a9d24786f381623a162f95218ce1e212d701768f2f99082
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7d95be3b9d660ea9af8b2b469e49613305230b6431a4c5c0ea351e49192b035546ff0da342c904062a0518fcc1c1b2327462c4380eed69b9fe189b32fa28b9f
|
7
|
+
data.tar.gz: 722d4d3924adb67a00b844c517da2b664685a23a0ebd4964e5bf3e16fc7f4fd69ce20ee79b7c905455bef6a511b1759dc4aa6382391a99fa55b15a0bc2180825
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'open-uri'
|
5
|
+
|
6
|
+
module GemUpdater
|
7
|
+
class ChangelogParser
|
8
|
+
# ChangelogParser is responsible for parsing a changelog hosted on github.
|
9
|
+
class GithubParser
|
10
|
+
attr_reader :uri, :version
|
11
|
+
|
12
|
+
# @param uri [String] changelog uri
|
13
|
+
# @param version [String] version of gem
|
14
|
+
def initialize(uri:, version:)
|
15
|
+
@uri = uri
|
16
|
+
@version = version
|
17
|
+
end
|
18
|
+
|
19
|
+
# Finds anchor in changelog, otherwise return the base uri.
|
20
|
+
#
|
21
|
+
# @return [String] the URL of changelog
|
22
|
+
def changelog
|
23
|
+
uri + find_anchor(document).to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# Opens changelog url and parses it.
|
29
|
+
#
|
30
|
+
# @return [Nokogiri::HTML4::Document] the changelog
|
31
|
+
def document
|
32
|
+
Nokogiri::HTML(URI.parse(uri).open, nil, Encoding::UTF_8.to_s)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Looks into document to find it there is an anchor to new gem version.
|
36
|
+
#
|
37
|
+
# @param doc [Nokogiri::HTML4::Document] document
|
38
|
+
# @return [String, nil] anchor's href
|
39
|
+
def find_anchor(doc)
|
40
|
+
anchor = doc.xpath('//a[contains(@class, "heading-link")]').find do |element|
|
41
|
+
element.attr('href').match(version.delete('.'))
|
42
|
+
end
|
43
|
+
return unless anchor
|
44
|
+
|
45
|
+
anchor.attr('href').gsub(%(\\"), '')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'gem_updater/changelog_parser/github_parser'
|
6
|
+
|
7
|
+
module GemUpdater
|
8
|
+
# ChangelogParser is responsible for parsing a source page where
|
9
|
+
# the gem code is hosted.
|
10
|
+
class ChangelogParser
|
11
|
+
MARKUP_FILES = %w[.md .rdoc .textile].freeze
|
12
|
+
|
13
|
+
attr_reader :uri, :version
|
14
|
+
|
15
|
+
# @param uri [String] uri of changelog
|
16
|
+
# @param version [String] version of gem
|
17
|
+
def initialize(uri:, version:)
|
18
|
+
@uri = uri
|
19
|
+
@version = version
|
20
|
+
end
|
21
|
+
|
22
|
+
# Get the changelog in an uri.
|
23
|
+
#
|
24
|
+
# @return [String, nil] URL of changelog
|
25
|
+
def changelog
|
26
|
+
return uri unless changelog_may_contain_anchor?
|
27
|
+
|
28
|
+
parse_changelog
|
29
|
+
rescue OpenURI::HTTPError # Uri points to nothing
|
30
|
+
log_error_and_return_uri("Cannot find #{uri}")
|
31
|
+
rescue Errno::ETIMEDOUT # timeout
|
32
|
+
log_error_and_return_uri("#{URI.parse(uri).host} is down")
|
33
|
+
rescue ArgumentError => e # x-oauth-basic raises userinfo not supported. [RFC3986]
|
34
|
+
log_error_and_return_uri(e)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
# Try to find where changelog might be.
|
40
|
+
#
|
41
|
+
# @param doc [Nokogiri::XML::Element] document of source page
|
42
|
+
def parse_changelog
|
43
|
+
case URI.parse(uri).host
|
44
|
+
when 'github.com'
|
45
|
+
GithubParser.new(uri: uri, version: version).changelog
|
46
|
+
else
|
47
|
+
uri
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Some documents like the one written in markdown may contain
|
52
|
+
# a direct anchor to specific version.
|
53
|
+
#
|
54
|
+
# @return [Boolean] true if file may contain an anchor
|
55
|
+
def changelog_may_contain_anchor?
|
56
|
+
MARKUP_FILES.include?(File.extname(uri.to_s))
|
57
|
+
end
|
58
|
+
|
59
|
+
def log_error_and_return_uri(error_message)
|
60
|
+
Bundler.ui.error error_message
|
61
|
+
uri
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -4,8 +4,8 @@ require 'bundler'
|
|
4
4
|
require 'bundler/cli'
|
5
5
|
|
6
6
|
module GemUpdater
|
7
|
-
#
|
8
|
-
class
|
7
|
+
# Gemfile is responsible for handling `Gemfile`
|
8
|
+
class Gemfile
|
9
9
|
attr_accessor :changes
|
10
10
|
attr_reader :old_spec_set, :new_spec_set
|
11
11
|
|
@@ -8,23 +8,22 @@ module GemUpdater
|
|
8
8
|
# RubyGemsFetcher is a wrapper around rubygems API.
|
9
9
|
class RubyGemsFetcher
|
10
10
|
HTTP_TOO_MANY_REQUESTS = '429'
|
11
|
-
GEM_HOMEPAGES = %w[source_code_uri homepage_uri].freeze
|
12
11
|
|
13
|
-
attr_reader :gem_name
|
12
|
+
attr_reader :gem_name
|
14
13
|
|
15
14
|
# @param gem_name [String] name of the gem
|
16
|
-
|
17
|
-
def initialize(gem_name, source)
|
15
|
+
def initialize(gem_name)
|
18
16
|
@gem_name = gem_name
|
19
|
-
@source = source
|
20
17
|
end
|
21
18
|
|
22
|
-
# Finds
|
23
|
-
#
|
19
|
+
# Finds the changelog uri.
|
20
|
+
# It asks rubygems.org for changelog_uri of gem.
|
21
|
+
# See API: http://guides.rubygems.org/rubygems-org-api/#gem-methods
|
24
22
|
#
|
25
|
-
# @return [String|nil]
|
26
|
-
def
|
27
|
-
|
23
|
+
# @return [String|nil] uri of changelog
|
24
|
+
def changelog_uri
|
25
|
+
response = query_rubygems
|
26
|
+
response.to_h['changelog_uri']
|
28
27
|
end
|
29
28
|
|
30
29
|
private
|
@@ -37,19 +36,6 @@ module GemUpdater
|
|
37
36
|
JSON.parse(URI.parse(url).open.read)
|
38
37
|
end
|
39
38
|
|
40
|
-
# Ask rubygems.org for source uri of gem.
|
41
|
-
# See API: http://guides.rubygems.org/rubygems-org-api/#gem-methods
|
42
|
-
#
|
43
|
-
# @return [String|nil] uri of source code
|
44
|
-
def uri_from_rubygems
|
45
|
-
return unless source.remotes.map(&:host).include?('rubygems.org')
|
46
|
-
|
47
|
-
response = query_rubygems
|
48
|
-
return unless response
|
49
|
-
|
50
|
-
response[GEM_HOMEPAGES.find { |key| response[key] && !response[key].empty? }]
|
51
|
-
end
|
52
|
-
|
53
39
|
# Make the real query to rubygems
|
54
40
|
# It may fail in case we trigger too many requests
|
55
41
|
#
|
@@ -63,43 +49,5 @@ module GemUpdater
|
|
63
49
|
sleep 1 && retry if tries < 2
|
64
50
|
end
|
65
51
|
end
|
66
|
-
|
67
|
-
# Look if gem can be found in another remote
|
68
|
-
#
|
69
|
-
# @return [String|nil] uri of source code
|
70
|
-
def uri_from_other_sources
|
71
|
-
source.remotes.find do |remote|
|
72
|
-
case remote.host
|
73
|
-
when 'rubygems.org' then next # already checked
|
74
|
-
when 'rails-assets.org'
|
75
|
-
return uri_from_railsassets
|
76
|
-
else
|
77
|
-
Bundler.ui.error "Source #{remote} is not supported, ' \
|
78
|
-
'feel free to open a PR or an issue on https://github.com/MaximeD/gem_updater"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Ask rails-assets.org for source uri of gem.
|
84
|
-
# API is at : https://rails-assets.org/packages/package_name
|
85
|
-
#
|
86
|
-
# @return [String|nil] uri of source code
|
87
|
-
def uri_from_railsassets
|
88
|
-
response = query_railsassets
|
89
|
-
return unless response
|
90
|
-
|
91
|
-
response['url'].gsub(/^git/, 'http')
|
92
|
-
end
|
93
|
-
|
94
|
-
# Make the real query to railsassets
|
95
|
-
# rubocop:disable Lint/SuppressedException
|
96
|
-
def query_railsassets
|
97
|
-
parse_remote_json("https://rails-assets.org/packages/#{gem_name.gsub('rails-assets-', '')}")
|
98
|
-
rescue JSON::ParserError
|
99
|
-
# if gem is not found, rails-assets returns a 200
|
100
|
-
# with html (instead of json) containing a 500...
|
101
|
-
rescue OpenURI::HTTPError
|
102
|
-
end
|
103
|
-
# rubocop:enable Lint/SuppressedException
|
104
52
|
end
|
105
53
|
end
|
data/lib/gem_updater/version.rb
CHANGED
data/lib/gem_updater.rb
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'erb'
|
4
|
-
require '
|
5
|
-
require 'gem_updater/
|
4
|
+
require 'gem_updater/changelog_parser'
|
5
|
+
require 'gem_updater/gemfile'
|
6
6
|
require 'gem_updater/ruby_gems_fetcher'
|
7
|
-
require 'gem_updater/source_page_parser'
|
8
7
|
|
9
8
|
# Base lib.
|
10
9
|
module GemUpdater
|
11
10
|
# Updater's main responsability is to fill changes
|
12
11
|
# happened before and after update of `Gemfile`, and then format them.
|
13
12
|
class Updater
|
14
|
-
|
13
|
+
RUBYGEMS_SOURCE_NAME = 'rubygems repository https://rubygems.org/'
|
15
14
|
|
16
15
|
attr_accessor :gemfile
|
17
16
|
|
18
17
|
def initialize
|
19
|
-
@gemfile = GemUpdater::
|
18
|
+
@gemfile = GemUpdater::Gemfile.new
|
20
19
|
end
|
21
20
|
|
22
21
|
# Update process.
|
@@ -52,35 +51,23 @@ module GemUpdater
|
|
52
51
|
# For each gem, retrieve its changelog
|
53
52
|
def fill_changelogs
|
54
53
|
[].tap do |threads|
|
55
|
-
gemfile.changes.each do |
|
56
|
-
threads << Thread.new {
|
54
|
+
gemfile.changes.each do |gem_changes, details|
|
55
|
+
threads << Thread.new { retrieve_changelog(gem_changes, details) }
|
57
56
|
end
|
58
57
|
end.each(&:join)
|
59
58
|
end
|
60
59
|
|
61
|
-
#
|
62
|
-
|
63
|
-
|
64
|
-
# @param source [Bundler::Source] gem's source
|
65
|
-
# @return [String] url where gem is hosted
|
66
|
-
def find_source(gem, source)
|
67
|
-
case source
|
68
|
-
when Bundler::Source::Rubygems
|
69
|
-
GemUpdater::RubyGemsFetcher.new(gem, source).source_uri
|
70
|
-
when Bundler::Source::Git
|
71
|
-
source.uri.gsub(/^git/, 'http').chomp('.git')
|
72
|
-
end
|
73
|
-
end
|
60
|
+
# Get the changelog URL.
|
61
|
+
def retrieve_changelog(gem_name, details)
|
62
|
+
return unless details[:source].name == RUBYGEMS_SOURCE_NAME
|
74
63
|
|
75
|
-
|
76
|
-
source_uri = find_source(gem_name, details[:source])
|
77
|
-
return unless source_uri
|
64
|
+
changelog_uri = RubyGemsFetcher.new(gem_name).changelog_uri
|
78
65
|
|
79
|
-
|
80
|
-
url: source_uri, version: details[:versions][:new]
|
81
|
-
)
|
66
|
+
return unless changelog_uri
|
82
67
|
|
83
|
-
|
68
|
+
changelog = ChangelogParser
|
69
|
+
.new(uri: changelog_uri, version: details.dig(:versions, :new)).changelog
|
70
|
+
gemfile.changes[gem_name][:changelog] = changelog&.to_s
|
84
71
|
end
|
85
72
|
|
86
73
|
# Get the template for gem's diff.
|
@@ -92,6 +79,5 @@ module GemUpdater
|
|
92
79
|
rescue Errno::ENOENT
|
93
80
|
File.read(File.expand_path('../lib/gem_updater_template.erb', __dir__))
|
94
81
|
end
|
95
|
-
memoize :template
|
96
82
|
end
|
97
83
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gem_updater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 7.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxime Demolin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.6'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: memoist
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.16.2
|
48
|
-
type: :runtime
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 0.16.2
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: nokogiri
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -160,9 +146,10 @@ extra_rdoc_files: []
|
|
160
146
|
files:
|
161
147
|
- bin/gem_update
|
162
148
|
- lib/gem_updater.rb
|
163
|
-
- lib/gem_updater/
|
149
|
+
- lib/gem_updater/changelog_parser.rb
|
150
|
+
- lib/gem_updater/changelog_parser/github_parser.rb
|
151
|
+
- lib/gem_updater/gemfile.rb
|
164
152
|
- lib/gem_updater/ruby_gems_fetcher.rb
|
165
|
-
- lib/gem_updater/source_page_parser.rb
|
166
153
|
- lib/gem_updater/version.rb
|
167
154
|
- lib/gem_updater_template.erb
|
168
155
|
homepage: https://github.com/MaximeD/gem_updater
|
@@ -1,173 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'nokogiri'
|
4
|
-
require 'open-uri'
|
5
|
-
|
6
|
-
module GemUpdater
|
7
|
-
# SourcePageParser is responsible for parsing a source page where
|
8
|
-
# the gem code is hosted.
|
9
|
-
class SourcePageParser
|
10
|
-
extend Memoist
|
11
|
-
|
12
|
-
HOSTS = {
|
13
|
-
github: /github.com/,
|
14
|
-
bitbucket: /bitbucket.org/,
|
15
|
-
rubygems: /rubygems.org/
|
16
|
-
}.freeze
|
17
|
-
MARKUP_FILES = %w[.md .rdoc .textile].freeze
|
18
|
-
CHANGELOG_NAMES = %w[changelog ChangeLog history changes news].freeze
|
19
|
-
|
20
|
-
attr_reader :uri, :version
|
21
|
-
|
22
|
-
# @param url [String] url of page
|
23
|
-
# @param version [String] version of gem
|
24
|
-
def initialize(url: nil, version: nil)
|
25
|
-
@uri = correct_uri(url)
|
26
|
-
@version = version
|
27
|
-
end
|
28
|
-
|
29
|
-
# Get the changelog in an uri.
|
30
|
-
#
|
31
|
-
# @return [String, nil] URL of changelog
|
32
|
-
def changelog
|
33
|
-
return unless uri
|
34
|
-
|
35
|
-
Bundler.ui.warn "Looking for a changelog in #{uri}"
|
36
|
-
find_changelog(Nokogiri::HTML(uri.open))
|
37
|
-
rescue OpenURI::HTTPError # Uri points to nothing
|
38
|
-
log_error("Cannot find #{uri}")
|
39
|
-
rescue Errno::ETIMEDOUT # timeout
|
40
|
-
log_error("#{uri} is down")
|
41
|
-
rescue ArgumentError => e # x-oauth-basic raises userinfo not supported. [RFC3986]
|
42
|
-
log_error(e)
|
43
|
-
end
|
44
|
-
memoize :changelog
|
45
|
-
|
46
|
-
private
|
47
|
-
|
48
|
-
# Some gems have 'http://github.com' as URI which will redirect to https
|
49
|
-
# leading `open_uri` to crash.
|
50
|
-
#
|
51
|
-
# @param url [String] the url to parse
|
52
|
-
# @return [URI] valid URI
|
53
|
-
def correct_uri(url)
|
54
|
-
return unless url.is_a?(String) && !url.empty?
|
55
|
-
|
56
|
-
uri = URI.parse(url)
|
57
|
-
uri.scheme == 'http' ? known_https(uri) : uri
|
58
|
-
end
|
59
|
-
|
60
|
-
# Some uris are not https, but we know they should be,
|
61
|
-
# in which case we have an https redirection
|
62
|
-
# which is not properly handled by open-uri
|
63
|
-
#
|
64
|
-
# @param uri [URI::HTTP]
|
65
|
-
# @return [URI::HTTPS|URI::HTTP]
|
66
|
-
def known_https(uri)
|
67
|
-
case uri.host
|
68
|
-
when HOSTS[:github]
|
69
|
-
# remove possible subdomain like 'wiki.github.com'
|
70
|
-
URI "https://github.com#{uri.path}"
|
71
|
-
when HOSTS[:bitbucket], HOSTS[:rubygems]
|
72
|
-
URI "https://#{uri.host}#{uri.path}"
|
73
|
-
else
|
74
|
-
uri
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
# Try to find where changelog might be.
|
79
|
-
#
|
80
|
-
# @param doc [Nokogiri::XML::Element] document of source page
|
81
|
-
def find_changelog(doc)
|
82
|
-
case uri.host
|
83
|
-
when 'github.com'
|
84
|
-
GitHubParser.new(doc, version).changelog
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# List possible names for a changelog
|
89
|
-
# since humans may have many many ways to call it.
|
90
|
-
#
|
91
|
-
# @return [Array] list of possible names
|
92
|
-
def changelog_names
|
93
|
-
CHANGELOG_NAMES.flat_map do |name|
|
94
|
-
[name, name.upcase, name.capitalize]
|
95
|
-
end.uniq
|
96
|
-
end
|
97
|
-
|
98
|
-
# Some documents like the one written in markdown may contain
|
99
|
-
# a direct anchor to specific version.
|
100
|
-
#
|
101
|
-
# @param file_name [String] file name of changelog
|
102
|
-
# @return [Boolean] true if file may contain an anchor
|
103
|
-
def changelog_may_contain_anchor?(file_name)
|
104
|
-
MARKUP_FILES.include?(File.extname(file_name))
|
105
|
-
end
|
106
|
-
|
107
|
-
def log_error(error_message)
|
108
|
-
Bundler.ui.error error_message
|
109
|
-
false
|
110
|
-
end
|
111
|
-
|
112
|
-
# GitHubParser is responsible for parsing source code
|
113
|
-
# hosted on github.com.
|
114
|
-
class GitHubParser < SourcePageParser
|
115
|
-
BASE_URL = 'https://github.com'
|
116
|
-
|
117
|
-
attr_reader :doc, :version
|
118
|
-
|
119
|
-
# @param doc [Nokogiri::XML::Element] document of source page
|
120
|
-
# @param version [String] version of gem
|
121
|
-
# rubocop:disable Lint/MissingSuper
|
122
|
-
def initialize(doc, version)
|
123
|
-
@doc = doc
|
124
|
-
@version = version
|
125
|
-
end
|
126
|
-
# rubocop:enable Lint/MissingSuper
|
127
|
-
|
128
|
-
# Finds url of changelog.
|
129
|
-
#
|
130
|
-
# @return [String] the URL of changelog
|
131
|
-
def changelog
|
132
|
-
url = find_changelog_link
|
133
|
-
return unless url
|
134
|
-
|
135
|
-
full_url = BASE_URL + url
|
136
|
-
|
137
|
-
if changelog_may_contain_anchor?(full_url)
|
138
|
-
anchor = find_anchor(full_url)
|
139
|
-
full_url += anchor if anchor
|
140
|
-
end
|
141
|
-
|
142
|
-
full_url
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
|
147
|
-
# Find which link corresponds to changelog.
|
148
|
-
# Last one is taken as files come after directories. So if there is a directory plus a file
|
149
|
-
# matching a changelog name, we ensure file is preferred.
|
150
|
-
#
|
151
|
-
# @return [String, nil] url of changelog
|
152
|
-
def find_changelog_link
|
153
|
-
changelog_names.filter_map do |name|
|
154
|
-
doc.at_css(%([aria-labelledby="files"] a[title^="#{name}"]))
|
155
|
-
end.last&.attr('href')
|
156
|
-
end
|
157
|
-
|
158
|
-
# Looks into document to find it there is an anchor to new gem version.
|
159
|
-
#
|
160
|
-
# @param url [String] url of changelog
|
161
|
-
# @return [String, nil] anchor's href
|
162
|
-
def find_anchor(url)
|
163
|
-
changelog_page = Nokogiri::HTML(URI.parse(url).open)
|
164
|
-
anchor = changelog_page.xpath('//a[contains(@class, "anchor")]').find do |element|
|
165
|
-
element.attr('href').match(version.delete('.'))
|
166
|
-
end
|
167
|
-
return unless anchor
|
168
|
-
|
169
|
-
anchor.attr('href').gsub(%(\\"), '')
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|