gem_updater 3.0.0 → 4.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/bin/gem_update +3 -1
- data/lib/gem_updater.rb +25 -22
- data/lib/gem_updater/gem_file.rb +6 -6
- data/lib/gem_updater/ruby_gems_fetcher.rb +18 -12
- data/lib/gem_updater/source_page_parser.rb +34 -39
- metadata +36 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa29e2d445cbfcb39630890068aa4c500968f5c4c1765f5dbed6e3d106e04a82
|
4
|
+
data.tar.gz: 16bc9ffd31ed48f1e00e0c776472be38fc8a978aead2aebaf708f0e89b637e4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 05c074149555f10115bf97de0ecd8b98806995b45df64a0dcbb28f8bc59faae181b113a267d857f04b9f5048886abfcff90ec22fc18af92a34664de7b684aadd
|
7
|
+
data.tar.gz: 5245415abd40b10897bacd6c5df56daf1339bf1fe4cb11b4878d15e1392250e41d26f21a17e05f74dcce02f91ae2ef267e1374131747252cf349d76fea4fb789
|
data/bin/gem_update
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
#!/usr/bin/env ruby
|
2
4
|
require 'optparse'
|
3
5
|
|
4
6
|
# Exit cleanly from an early interrupt
|
5
7
|
Signal.trap('INT') { exit 1 }
|
6
8
|
|
7
|
-
$LOAD_PATH.unshift File.expand_path('
|
9
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
|
8
10
|
require 'gem_updater'
|
9
11
|
|
10
12
|
Bundler.ui = Bundler::UI::Shell.new
|
data/lib/gem_updater.rb
CHANGED
@@ -1,12 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'memoist'
|
1
4
|
require 'gem_updater/gem_file'
|
2
5
|
require 'gem_updater/ruby_gems_fetcher'
|
3
6
|
require 'gem_updater/source_page_parser'
|
4
7
|
|
8
|
+
# Base lib.
|
5
9
|
module GemUpdater
|
6
|
-
|
7
10
|
# Updater's main responsability is to fill changes
|
8
11
|
# happened before and after update of `Gemfile`, and then format them.
|
9
12
|
class Updater
|
13
|
+
extend Memoist
|
14
|
+
|
10
15
|
attr_accessor :gemfile
|
11
16
|
|
12
17
|
def initialize
|
@@ -43,23 +48,11 @@ module GemUpdater
|
|
43
48
|
|
44
49
|
# For each gem, retrieve its changelog
|
45
50
|
def fill_changelogs
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
threads << Thread.new do
|
50
|
-
if source_uri = find_source(gem_name, details[:source])
|
51
|
-
source_page = GemUpdater::SourcePageParser.new(
|
52
|
-
url: source_uri, version: details[:versions][:new]
|
53
|
-
)
|
54
|
-
|
55
|
-
if source_page.changelog
|
56
|
-
gemfile.changes[gem_name][:changelog] = source_page.changelog
|
57
|
-
end
|
58
|
-
end
|
51
|
+
[].tap do |threads|
|
52
|
+
gemfile.changes.each do |gem_name, details|
|
53
|
+
threads << Thread.new { retrieve_gem_changes(gem_name, details) }
|
59
54
|
end
|
60
|
-
end
|
61
|
-
|
62
|
-
threads.each(&:join)
|
55
|
+
end.each(&:join)
|
63
56
|
end
|
64
57
|
|
65
58
|
# Find where is hosted the source of a gem
|
@@ -76,16 +69,26 @@ module GemUpdater
|
|
76
69
|
end
|
77
70
|
end
|
78
71
|
|
72
|
+
def retrieve_gem_changes(gem_name, details)
|
73
|
+
source_uri = find_source(gem_name, details[:source])
|
74
|
+
return unless source_uri
|
75
|
+
|
76
|
+
source_page = GemUpdater::SourcePageParser.new(
|
77
|
+
url: source_uri, version: details[:versions][:new]
|
78
|
+
)
|
79
|
+
|
80
|
+
gemfile.changes[gem_name][:changelog] = source_page.changelog if source_page.changelog
|
81
|
+
end
|
82
|
+
|
79
83
|
# Get the template for gem's diff.
|
80
84
|
# It can use a custom template.
|
81
85
|
#
|
82
86
|
# @return [ERB] the template
|
83
87
|
def template
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
File.read(File.expand_path('../../lib/gem_updater_template.erb', __FILE__))
|
88
|
-
end
|
88
|
+
File.read("#{Dir.home}/.gem_updater_template.erb")
|
89
|
+
rescue Errno::ENOENT
|
90
|
+
File.read(File.expand_path('../lib/gem_updater_template.erb', __dir__))
|
89
91
|
end
|
92
|
+
memoize :template
|
90
93
|
end
|
91
94
|
end
|
data/lib/gem_updater/gem_file.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/cli'
|
2
4
|
|
3
5
|
module GemUpdater
|
4
|
-
|
5
6
|
# GemFile is responsible for handling `Gemfile`
|
6
7
|
class GemFile
|
7
8
|
attr_accessor :changes
|
@@ -21,21 +22,20 @@ module GemUpdater
|
|
21
22
|
#
|
22
23
|
# @return [Hash] gems for which there are differences.
|
23
24
|
def compute_changes
|
24
|
-
|
25
|
+
spec_sets_diff!
|
25
26
|
|
26
27
|
old_spec_set.each do |old_gem|
|
27
28
|
updated_gem = new_spec_set.find { |new_gem| new_gem.name == old_gem.name }
|
29
|
+
next unless updated_gem && old_gem.version != updated_gem.version
|
28
30
|
|
29
|
-
|
30
|
-
fill_changes(old_gem, updated_gem)
|
31
|
-
end
|
31
|
+
fill_changes(old_gem, updated_gem)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
37
|
# Get the two spec sets (before and after `bundle update`)
|
38
|
-
def
|
38
|
+
def spec_sets_diff!
|
39
39
|
@old_spec_set = spec_set
|
40
40
|
reinitialize_spec_set!
|
41
41
|
@new_spec_set = spec_set
|
@@ -1,12 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
require 'nokogiri'
|
3
5
|
require 'open-uri'
|
4
6
|
|
5
7
|
module GemUpdater
|
6
|
-
|
7
8
|
# RubyGemsFetcher is a wrapper around rubygems API.
|
8
9
|
class RubyGemsFetcher
|
9
|
-
HTTP_TOO_MANY_REQUESTS = '429'
|
10
|
+
HTTP_TOO_MANY_REQUESTS = '429'
|
10
11
|
GEM_HOMEPAGES = %w[source_code_uri homepage_uri].freeze
|
11
12
|
|
12
13
|
attr_reader :gem_name, :source
|
@@ -35,11 +36,10 @@ module GemUpdater
|
|
35
36
|
def uri_from_rubygems
|
36
37
|
return unless source.remotes.map(&:host).include?('rubygems.org')
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
39
|
+
response = query_rubygems
|
40
|
+
return unless response
|
41
|
+
|
42
|
+
response[GEM_HOMEPAGES.find { |key| response[key] && !response[key].empty? }]
|
43
43
|
end
|
44
44
|
|
45
45
|
# Make the real query to rubygems
|
@@ -52,7 +52,7 @@ module GemUpdater
|
|
52
52
|
# We may trigger too many requests, in which case give rubygems a break
|
53
53
|
if e.io.status.include?(HTTP_TOO_MANY_REQUESTS)
|
54
54
|
if (tries += 1) < 2
|
55
|
-
sleep 1
|
55
|
+
sleep 1 && retry
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -60,6 +60,7 @@ module GemUpdater
|
|
60
60
|
# Look if gem can be found in another remote
|
61
61
|
#
|
62
62
|
# @return [String|nil] uri of source code
|
63
|
+
# rubocop:disable Metrics/MethodLength
|
63
64
|
def uri_from_other_sources
|
64
65
|
uri = nil
|
65
66
|
source.remotes.each do |remote|
|
@@ -70,24 +71,28 @@ module GemUpdater
|
|
70
71
|
when 'rails-assets.org'
|
71
72
|
uri_from_railsassets
|
72
73
|
else
|
73
|
-
Bundler.ui.error "Source #{remote} is not supported,
|
74
|
+
Bundler.ui.error "Source #{remote} is not supported, ' \
|
75
|
+
'feel free to open a PR or an issue on https://github.com/MaximeD/gem_updater"
|
74
76
|
end
|
75
77
|
end
|
76
78
|
|
77
79
|
uri
|
78
80
|
end
|
81
|
+
# rubocop:enable Metrics/MethodLength
|
79
82
|
|
80
83
|
# Ask rails-assets.org for source uri of gem.
|
81
84
|
# API is at : https://rails-assets.org/packages/package_name
|
82
85
|
#
|
83
86
|
# @return [String|nil] uri of source code
|
84
87
|
def uri_from_railsassets
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
+
response = query_railsassets
|
89
|
+
return unless response
|
90
|
+
|
91
|
+
response['url'].gsub(/^git/, 'http')
|
88
92
|
end
|
89
93
|
|
90
94
|
# Make the real query to railsassets
|
95
|
+
# rubocop:disable Lint/HandleExceptions
|
91
96
|
def query_railsassets
|
92
97
|
JSON.parse(
|
93
98
|
open(
|
@@ -99,5 +104,6 @@ module GemUpdater
|
|
99
104
|
# with html (instead of json) containing a 500...
|
100
105
|
rescue OpenURI::HTTPError
|
101
106
|
end
|
107
|
+
# rubocop:enable Lint/HandleExceptions
|
102
108
|
end
|
103
109
|
end
|
@@ -1,11 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'nokogiri'
|
2
4
|
require 'open-uri'
|
3
5
|
|
4
6
|
module GemUpdater
|
5
|
-
|
6
7
|
# SourcePageParser is responsible for parsing a source page where
|
7
8
|
# the gem code is hosted.
|
8
9
|
class SourcePageParser
|
10
|
+
extend Memoist
|
11
|
+
|
9
12
|
HOSTS = {
|
10
13
|
github: /github.com/,
|
11
14
|
bitbucket: /bitbucket.org/,
|
@@ -29,23 +32,16 @@ module GemUpdater
|
|
29
32
|
def changelog
|
30
33
|
return unless uri
|
31
34
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
false
|
41
|
-
rescue Errno::ETIMEDOUT # timeout
|
42
|
-
Bundler.ui.error "#{uri} is down"
|
43
|
-
false
|
44
|
-
rescue ArgumentError => e # x-oauth-basic raises userinfo not supported. [RFC3986]
|
45
|
-
Bundler.ui.error e
|
46
|
-
false
|
47
|
-
end
|
35
|
+
Bundler.ui.warn "Looking for a changelog in #{uri}"
|
36
|
+
find_changelog(Nokogiri::HTML(URI.open(uri)))
|
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)
|
48
43
|
end
|
44
|
+
memoize :changelog
|
49
45
|
|
50
46
|
private
|
51
47
|
|
@@ -55,15 +51,10 @@ module GemUpdater
|
|
55
51
|
# @param url [String] the url to parse
|
56
52
|
# @return [URI] valid URI
|
57
53
|
def correct_uri(url)
|
58
|
-
return unless String
|
54
|
+
return unless url.is_a?(String) && !url.empty?
|
59
55
|
|
60
56
|
uri = URI(url)
|
61
|
-
|
62
|
-
if uri.scheme == 'http'
|
63
|
-
known_https(uri)
|
64
|
-
else
|
65
|
-
uri
|
66
|
-
end
|
57
|
+
uri.scheme == 'http' ? known_https(uri) : uri
|
67
58
|
end
|
68
59
|
|
69
60
|
# Some uris are not https, but we know they should be,
|
@@ -73,13 +64,13 @@ module GemUpdater
|
|
73
64
|
# @param uri [URI::HTTP]
|
74
65
|
# @return [URI::HTTPS|URI::HTTP]
|
75
66
|
def known_https(uri)
|
76
|
-
case
|
77
|
-
when
|
67
|
+
case uri.host
|
68
|
+
when HOSTS[:github]
|
78
69
|
# remove possible subdomain like 'wiki.github.com'
|
79
70
|
URI "https://github.com#{uri.path}"
|
80
|
-
when
|
71
|
+
when HOSTS[:bitbucket]
|
81
72
|
URI "https://#{uri.host}#{uri.path}"
|
82
|
-
when
|
73
|
+
when HOSTS[:rubygems]
|
83
74
|
URI "https://#{uri.host}#{uri.path}"
|
84
75
|
else
|
85
76
|
uri
|
@@ -115,10 +106,15 @@ module GemUpdater
|
|
115
106
|
MARKUP_FILES.include?(File.extname(file_name))
|
116
107
|
end
|
117
108
|
|
109
|
+
def log_error(error_message)
|
110
|
+
Bundler.ui.error error_message
|
111
|
+
false
|
112
|
+
end
|
113
|
+
|
118
114
|
# GitHubParser is responsible for parsing source code
|
119
115
|
# hosted on github.com.
|
120
116
|
class GitHubParser < SourcePageParser
|
121
|
-
BASE_URL = 'https://github.com'
|
117
|
+
BASE_URL = 'https://github.com'
|
122
118
|
|
123
119
|
attr_reader :doc, :version
|
124
120
|
|
@@ -134,17 +130,16 @@ module GemUpdater
|
|
134
130
|
# @return [String] the URL of changelog
|
135
131
|
def changelog
|
136
132
|
url = find_changelog_link
|
133
|
+
return unless url
|
137
134
|
|
138
|
-
|
139
|
-
full_url = BASE_URL + url
|
140
|
-
|
141
|
-
if changelog_may_contain_anchor?(full_url)
|
142
|
-
anchor = find_anchor(full_url)
|
143
|
-
full_url += anchor if anchor
|
144
|
-
end
|
135
|
+
full_url = BASE_URL + url
|
145
136
|
|
146
|
-
|
137
|
+
if changelog_may_contain_anchor?(full_url)
|
138
|
+
anchor = find_anchor(full_url)
|
139
|
+
full_url += anchor if anchor
|
147
140
|
end
|
141
|
+
|
142
|
+
full_url
|
148
143
|
end
|
149
144
|
|
150
145
|
private
|
@@ -165,12 +160,12 @@ module GemUpdater
|
|
165
160
|
# @param url [String] url of changelog
|
166
161
|
# @return [String, nil] anchor's href
|
167
162
|
def find_anchor(url)
|
168
|
-
changelog_page = Nokogiri::HTML(open(url))
|
163
|
+
changelog_page = Nokogiri::HTML(URI.open(url))
|
169
164
|
anchor = changelog_page.css(%(a.anchor)).find do |element|
|
170
165
|
element.attr('href').match(version.delete('.'))
|
171
166
|
end
|
172
167
|
|
173
|
-
anchor
|
168
|
+
anchor&.attr('href')
|
174
169
|
end
|
175
170
|
end
|
176
171
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gem_updater
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.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:
|
11
|
+
date: 2019-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "<"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "<"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.1'
|
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.0
|
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.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: nokogiri
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +80,20 @@ dependencies:
|
|
66
80
|
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '3.7'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.68.1
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.68.1
|
69
97
|
description: Updates the gems of your Gemfile and fetches the links pointing to where
|
70
98
|
their changelogs are
|
71
99
|
email: akbarova.armia@gmail.com
|
@@ -92,15 +120,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
120
|
requirements:
|
93
121
|
- - ">="
|
94
122
|
- !ruby/object:Gem::Version
|
95
|
-
version: 2.
|
123
|
+
version: 2.5.0
|
96
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
125
|
requirements:
|
98
126
|
- - ">="
|
99
127
|
- !ruby/object:Gem::Version
|
100
128
|
version: '0'
|
101
129
|
requirements: []
|
102
|
-
|
103
|
-
rubygems_version: 2.7.6
|
130
|
+
rubygems_version: 3.0.6
|
104
131
|
signing_key:
|
105
132
|
specification_version: 4
|
106
133
|
summary: Update your gems and find their changelogs
|