gem_updater 2.1.2 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a23a7f9c3d1169e801d5675aae8cfc43416c1dac
4
- data.tar.gz: 65022e66895b1951a6fb72d013e3e5f919cdd19d
2
+ SHA256:
3
+ metadata.gz: 8940082c41b6b94d7814b7c3327cf272f2194c18b85cfa6d32b2dbfb3db1eaf9
4
+ data.tar.gz: 5c497dff8dd408a82d49d3389d40cf858737bf5c79d9b277d342bd990fc8ce24
5
5
  SHA512:
6
- metadata.gz: ac440f9730d4b590ae97ed26b881661976f1e6ee5a8689c571ad8f3f56d617bf31bb159d44997bf58b6d2ffb82ba837ae9ea002ebd2271038ba0a8c697726a9d
7
- data.tar.gz: 8b87da6c3d7788f7f2fb84c2ef3a5baf8c9fc753eba1e937c6862ebdfda2cb3cc4a2394dc916b45354b9817916aa64a1e6f90351ada9b644102fae4cc283cd2a
6
+ metadata.gz: 77bbf48b90dd61af26fc87b57438baf821c30d38a07f4dd7112f50c087cbea8e3319f6262bba1d32c24566e4f9f443f648de425b924e1a22746b6c5c16e656cf
7
+ data.tar.gz: b1b606efbe8485c4fac85593442c2be025fdbf8d3a0d40c50e68bc77194192acd5e5937b96fc338baab757962af94d3253ee3df31271b7d0e7bacc1f6f8913f3
@@ -1,10 +1,13 @@
1
1
  #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
2
5
  require 'optparse'
3
6
 
4
7
  # Exit cleanly from an early interrupt
5
8
  Signal.trap('INT') { exit 1 }
6
9
 
7
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
10
+ $LOAD_PATH.unshift File.expand_path('../lib', __dir__)
8
11
  require 'gem_updater'
9
12
 
10
13
  Bundler.ui = Bundler::UI::Shell.new
@@ -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
- threads = []
47
-
48
- gemfile.changes.each do |gem_name, details|
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
- @template ||= begin
85
- File.read("#{Dir.home}/.gem_updater_template.erb")
86
- rescue Errno::ENOENT
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
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler'
1
4
  require 'bundler/cli'
2
5
 
3
6
  module GemUpdater
4
-
5
7
  # GemFile is responsible for handling `Gemfile`
6
8
  class GemFile
7
9
  attr_accessor :changes
@@ -21,21 +23,20 @@ module GemUpdater
21
23
  #
22
24
  # @return [Hash] gems for which there are differences.
23
25
  def compute_changes
24
- get_spec_sets
26
+ spec_sets_diff!
25
27
 
26
28
  old_spec_set.each do |old_gem|
27
29
  updated_gem = new_spec_set.find { |new_gem| new_gem.name == old_gem.name }
30
+ next unless updated_gem && old_gem.version != updated_gem.version
28
31
 
29
- if updated_gem && old_gem.version != updated_gem.version
30
- fill_changes(old_gem, updated_gem)
31
- end
32
+ fill_changes(old_gem, updated_gem)
32
33
  end
33
34
  end
34
35
 
35
36
  private
36
37
 
37
38
  # Get the two spec sets (before and after `bundle update`)
38
- def get_spec_sets
39
+ def spec_sets_diff!
39
40
  @old_spec_set = spec_set
40
41
  reinitialize_spec_set!
41
42
  @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'.freeze
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
@@ -28,6 +29,14 @@ module GemUpdater
28
29
 
29
30
  private
30
31
 
32
+ # Parse JSON from a remote url.
33
+ #
34
+ # @param url [String] remote url
35
+ # @return [Hash] parsed JSON
36
+ def parse_remote_json(url)
37
+ JSON.parse(URI.open(url).read)
38
+ end
39
+
31
40
  # Ask rubygems.org for source uri of gem.
32
41
  # See API: http://guides.rubygems.org/rubygems-org-api/#gem-methods
33
42
  #
@@ -35,11 +44,10 @@ module GemUpdater
35
44
  def uri_from_rubygems
36
45
  return unless source.remotes.map(&:host).include?('rubygems.org')
37
46
 
38
- if response = query_rubygems
39
- response[
40
- GEM_HOMEPAGES.find { |key| response[key] && !response[key].empty? }
41
- ]
42
- end
47
+ response = query_rubygems
48
+ return unless response
49
+
50
+ response[GEM_HOMEPAGES.find { |key| response[key] && !response[key].empty? }]
43
51
  end
44
52
 
45
53
  # Make the real query to rubygems
@@ -47,12 +55,12 @@ module GemUpdater
47
55
  #
48
56
  # @param tries [Integer|nil] (optional) how many times we tried
49
57
  def query_rubygems(tries = 0)
50
- JSON.parse(open("https://rubygems.org/api/v1/gems/#{gem_name}.json").read)
58
+ parse_remote_json("https://rubygems.org/api/v1/gems/#{gem_name}.json")
51
59
  rescue OpenURI::HTTPError => e
52
60
  # We may trigger too many requests, in which case give rubygems a break
53
61
  if e.io.status.include?(HTTP_TOO_MANY_REQUESTS)
54
62
  if (tries += 1) < 2
55
- sleep 1 and retry
63
+ sleep 1 && retry
56
64
  end
57
65
  end
58
66
  end
@@ -60,6 +68,7 @@ module GemUpdater
60
68
  # Look if gem can be found in another remote
61
69
  #
62
70
  # @return [String|nil] uri of source code
71
+ # rubocop:disable Metrics/MethodLength
63
72
  def uri_from_other_sources
64
73
  uri = nil
65
74
  source.remotes.each do |remote|
@@ -70,34 +79,35 @@ module GemUpdater
70
79
  when 'rails-assets.org'
71
80
  uri_from_railsassets
72
81
  else
73
- Bundler.ui.error "Source #{remote} is not supported, feel free to open a PR or an issue on https://github.com/MaximeD/gem_updater"
82
+ Bundler.ui.error "Source #{remote} is not supported, ' \
83
+ 'feel free to open a PR or an issue on https://github.com/MaximeD/gem_updater"
74
84
  end
75
85
  end
76
86
 
77
87
  uri
78
88
  end
89
+ # rubocop:enable Metrics/MethodLength
79
90
 
80
91
  # Ask rails-assets.org for source uri of gem.
81
92
  # API is at : https://rails-assets.org/packages/package_name
82
93
  #
83
94
  # @return [String|nil] uri of source code
84
95
  def uri_from_railsassets
85
- if response = query_railsassets
86
- response['url'].gsub(/^git/, 'http')
87
- end
96
+ response = query_railsassets
97
+ return unless response
98
+
99
+ response['url'].gsub(/^git/, 'http')
88
100
  end
89
101
 
90
102
  # Make the real query to railsassets
103
+ # rubocop:disable Lint/SuppressedException
91
104
  def query_railsassets
92
- JSON.parse(
93
- open(
94
- "https://rails-assets.org/packages/#{gem_name.gsub(/rails-assets-/, '')}"
95
- ).read
96
- )
105
+ parse_remote_json("https://rails-assets.org/packages/#{gem_name.gsub(/rails-assets-/, '')}")
97
106
  rescue JSON::ParserError
98
107
  # if gem is not found, rails-assets returns a 200
99
108
  # with html (instead of json) containing a 500...
100
109
  rescue OpenURI::HTTPError
101
110
  end
111
+ # rubocop:enable Lint/SuppressedException
102
112
  end
103
113
  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
- @changelog ||= begin
33
- Bundler.ui.warn "Looking for a changelog in #{uri}"
34
- doc = Nokogiri::HTML(open(uri))
35
-
36
- find_changelog(doc)
37
-
38
- rescue OpenURI::HTTPError # Uri points to nothing
39
- Bundler.ui.error "Cannot find #{uri}"
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 === url && !url.empty?
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 uri.host =~ HOSTS[:github]
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 uri.host =~ HOSTS[:bitbucket]
71
+ when HOSTS[:bitbucket]
81
72
  URI "https://#{uri.host}#{uri.path}"
82
- when uri.host =~ HOSTS[:rubygems]
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'.freeze
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
- if url
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
- full_url
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
@@ -154,7 +149,7 @@ module GemUpdater
154
149
  # @return [String, nil] url of changelog
155
150
  def find_changelog_link
156
151
  changelog_names.find do |name|
157
- node = doc.at_css(%(table.files .content a[title^="#{name}"]))
152
+ node = doc.at_css(%([aria-labelledby="files"] a[title^="#{name}"]))
158
153
 
159
154
  break node.attr('href') if node
160
155
  end
@@ -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.attr('href') if 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: 2.1.2
4
+ version: 4.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maxime Demolin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-02 00:00:00.000000000 Z
11
+ date: 2020-06-29 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: '1.15'
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: '1.15'
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
@@ -58,14 +72,70 @@ dependencies:
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '3.6'
75
+ version: '3.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
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.78'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.78'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-performance
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.5.2
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.5.2
111
+ - !ruby/object:Gem::Dependency
112
+ name: vcr
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '6.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '6.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '3.8'
62
132
  type: :development
63
133
  prerelease: false
64
134
  version_requirements: !ruby/object:Gem::Requirement
65
135
  requirements:
66
136
  - - "~>"
67
137
  - !ruby/object:Gem::Version
68
- version: '3.6'
138
+ version: '3.8'
69
139
  description: Updates the gems of your Gemfile and fetches the links pointing to where
70
140
  their changelogs are
71
141
  email: akbarova.armia@gmail.com
@@ -84,7 +154,7 @@ homepage: https://github.com/MaximeD/gem_updater
84
154
  licenses:
85
155
  - MIT
86
156
  metadata: {}
87
- post_install_message:
157
+ post_install_message:
88
158
  rdoc_options: []
89
159
  require_paths:
90
160
  - lib
@@ -92,16 +162,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
92
162
  requirements:
93
163
  - - ">="
94
164
  - !ruby/object:Gem::Version
95
- version: 2.1.0
165
+ version: 2.5.0
96
166
  required_rubygems_version: !ruby/object:Gem::Requirement
97
167
  requirements:
98
168
  - - ">="
99
169
  - !ruby/object:Gem::Version
100
170
  version: '0'
101
171
  requirements: []
102
- rubyforge_project:
103
- rubygems_version: 2.6.11
104
- signing_key:
172
+ rubygems_version: 3.1.2
173
+ signing_key:
105
174
  specification_version: 4
106
175
  summary: Update your gems and find their changelogs
107
176
  test_files: []