gem_updater 0.4.5 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 430902d1ecdddd688a1f3e2aa06979c634dfe92d
4
- data.tar.gz: c874786403e4a630a259633c8c0db0dc384e960d
3
+ metadata.gz: 66ba0cea1b0c09848cc7e9662257d9f9e366b487
4
+ data.tar.gz: 20527e80b3fc8da321ef1539a59d4e693aac2885
5
5
  SHA512:
6
- metadata.gz: 4a39b320ea39735ec2e0066d3db925f4212e28d516dace351f6661fb3f272ea40920f48c606fd21bbb9002283025affd1382c5e90ac24fa2d8e81875cf2e6fc7
7
- data.tar.gz: 790be8de469953d53b90a2d20d4d5c74940dc2802891b28814a791178ce98f472ea7a48a16131c42f244feafcc581d49472d14a07a0b398cf802d85a4d9e831d
6
+ metadata.gz: 0740383ec2b47aa3d68adeb7f96e49e7bb7210e8c08ae74d02efc9557e3fc0a17e18fa7de9be0bfae404db30a091f0ba5dc09c7fe53d8c1b4c69dd8fb8beb559
7
+ data.tar.gz: bb02299d459070caadb163aa9fe2f9624eacd5bd86aca23510844cff14ea5a19d50c52bdce416104194e45d13f51eed3c591808f5b82c95604d800bc6490440d
data/bin/gem_update CHANGED
@@ -2,34 +2,38 @@
2
2
  require 'optparse'
3
3
 
4
4
  # Exit cleanly from an early interrupt
5
- Signal.trap("INT") { exit 1 }
5
+ Signal.trap('INT') { exit 1 }
6
6
 
7
- $:.unshift File.expand_path( '../../lib', __FILE__ )
7
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
8
8
  require 'gem_updater'
9
9
 
10
10
  Bundler.ui = Bundler::UI::Shell.new
11
11
 
12
12
  options = {}
13
13
  OptionParser.new do |opts|
14
- opts.on( "-c", "--commit", "Auto commit" ) do |v|
15
- options[ :commit ] = v
14
+ opts.on('-c', '--commit', 'Auto commit') do |v|
15
+ options[:commit] = v
16
16
  end
17
17
  end.parse!
18
18
 
19
19
  gems = GemUpdater::Updater.new
20
- gems.update!( ARGV )
20
+ gems.update!(ARGV)
21
21
 
22
22
  if gems.gemfile.changes.any?
23
- if options[ :commit ]
23
+ if options[:commit]
24
24
  require 'tempfile'
25
- file = Tempfile.new( 'gem_updater' )
25
+ file = Tempfile.new('gem_updater')
26
26
  file.write "UPDATE gems\n\n"
27
27
  file.write gems.format_diff.join
28
28
  file.close
29
29
 
30
30
  gemfile = Bundler.default_gemfile.to_s
31
31
 
32
- system %(git add #{gemfile} #{gemfile}.lock && git commit -t #{file.path} --allow-empty-message)
32
+ system %(
33
+ git add #{gemfile} #{gemfile}.lock \
34
+ && git commit -t #{file.path} --allow-empty-message
35
+ )
36
+
33
37
  file.unlink
34
38
  else
35
39
  Bundler.ui.confirm "\nHere are your changes:"
data/lib/gem_updater.rb CHANGED
@@ -4,8 +4,8 @@ require 'gem_updater/source_page_parser'
4
4
 
5
5
  module GemUpdater
6
6
 
7
- # Updater's main responsability is to fill changes happened before and after update
8
- # of `Gemfile`, and then format them.
7
+ # Updater's main responsability is to fill changes
8
+ # happened before and after update of `Gemfile`, and then format them.
9
9
  class Updater
10
10
  attr_accessor :gemfile
11
11
 
@@ -19,8 +19,8 @@ module GemUpdater
19
19
  # 2. find changelogs for updated gems
20
20
  #
21
21
  # @param gems [Array] list of gems to update
22
- def update!( gems )
23
- gemfile.update!( gems )
22
+ def update!(gems)
23
+ gemfile.update!(gems)
24
24
  gemfile.compute_changes
25
25
 
26
26
  fill_changelogs
@@ -35,7 +35,7 @@ module GemUpdater
35
35
  # on the gems that were updated.
36
36
  def format_diff
37
37
  gemfile.changes.map do |gem, details|
38
- ERB.new( template, nil, '<>' ).result( binding )
38
+ ERB.new(template, nil, '<>').result(binding)
39
39
  end
40
40
  end
41
41
 
@@ -47,29 +47,32 @@ module GemUpdater
47
47
 
48
48
  gemfile.changes.each do |gem_name, details|
49
49
  threads << Thread.new do
50
- if source_uri = find_source( gem_name, details[ :source ] )
51
- source_page = GemUpdater::SourcePageParser.new( url: source_uri, version: details[ :versions ][ :new ] )
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
+ )
52
54
 
53
- gemfile.changes[ gem_name ][ :changelog ] = source_page.changelog if source_page.changelog
55
+ if source_page.changelog
56
+ gemfile.changes[gem_name][:changelog] = source_page.changelog
57
+ end
54
58
  end
55
59
  end
56
60
  end
57
61
 
58
- threads.each( &:join )
62
+ threads.each(&:join)
59
63
  end
60
64
 
61
-
62
65
  # Find where is hosted the source of a gem
63
66
  #
64
67
  # @param gem [String] the name of the gem
65
68
  # @param source [Bundler::Source] gem's source
66
69
  # @return [String] url where gem is hosted
67
- def find_source( gem, source )
70
+ def find_source(gem, source)
68
71
  case source
69
72
  when Bundler::Source::Rubygems
70
- GemUpdater::RubyGemsFetcher.new( gem, source ).source_uri
73
+ GemUpdater::RubyGemsFetcher.new(gem, source).source_uri
71
74
  when Bundler::Source::Git
72
- source.uri.gsub( /^git/, 'http' ).chomp( '.git' )
75
+ source.uri.gsub(/^git/, 'http').chomp('.git')
73
76
  end
74
77
  end
75
78
 
@@ -79,9 +82,9 @@ module GemUpdater
79
82
  # @return [ERB] the template
80
83
  def template
81
84
  @template ||= begin
82
- File.read( "#{Dir.home}/.gem_updater_template.erb" )
85
+ File.read("#{Dir.home}/.gem_updater_template.erb")
83
86
  rescue Errno::ENOENT
84
- File.read( File.expand_path( '../../lib/gem_updater_template.erb', __FILE__ ) )
87
+ File.read(File.expand_path('../../lib/gem_updater_template.erb', __FILE__))
85
88
  end
86
89
  end
87
90
  end
@@ -12,9 +12,9 @@ module GemUpdater
12
12
  end
13
13
 
14
14
  # Run `bundle update` to update gems.
15
- def update!( gems )
16
- Bundler.ui.warn "Updating gems..."
17
- Bundler::CLI.start( [ 'update' ] + gems )
15
+ def update!(gems)
16
+ Bundler.ui.warn 'Updating gems...'
17
+ Bundler::CLI.start(['update'] + gems)
18
18
  end
19
19
 
20
20
  # Compute the diffs between two `Gemfile.lock`.
@@ -24,10 +24,10 @@ module GemUpdater
24
24
  get_spec_sets
25
25
 
26
26
  old_spec_set.each do |old_gem|
27
- if updated_gem = new_spec_set.find{ |new_gem| new_gem.name == old_gem.name }
28
- unless old_gem.version == updated_gem.version
29
- changes[ old_gem.name ] = { versions: { old: old_gem.version.to_s, new: updated_gem.version.to_s }, source: updated_gem.source }
30
- end
27
+ updated_gem = new_spec_set.find { |new_gem| new_gem.name == old_gem.name }
28
+
29
+ if updated_gem && old_gem.version != updated_gem.version
30
+ fill_changes(old_gem, updated_gem)
31
31
  end
32
32
  end
33
33
  end
@@ -52,7 +52,20 @@ module GemUpdater
52
52
  # will return the same result.
53
53
  # Use a hacky way to tell bundle we want to parse the new `Gemfile.lock`
54
54
  def reinitialize_spec_set!
55
- Bundler.remove_instance_variable( "@locked_gems" )
55
+ Bundler.remove_instance_variable('@locked_gems')
56
+ end
57
+
58
+ # Add changes to between two versions of a gem
59
+ #
60
+ # @param old_gem [Bundler::LazySpecification]
61
+ # @param new_gem [Bundler::LazySpecification]
62
+ def fill_changes(old_gem, updated_gem)
63
+ changes[old_gem.name] = {
64
+ versions: {
65
+ old: old_gem.version.to_s, new: updated_gem.version.to_s
66
+ },
67
+ source: updated_gem.source
68
+ }
56
69
  end
57
70
  end
58
71
  end
@@ -6,11 +6,14 @@ module GemUpdater
6
6
 
7
7
  # RubyGemsFetcher is a wrapper around rubygems API.
8
8
  class RubyGemsFetcher
9
+ HTTP_TOO_MANY_REQUESTS = '429'.freeze
10
+ GEM_HOMEPAGES = %w[source_code_uri homepage_uri].freeze
11
+
9
12
  attr_reader :gem_name, :source
10
13
 
11
14
  # @param gem_name [String] name of the gem
12
15
  # @param source [Bundler::Source] source of gem
13
- def initialize( gem_name, source )
16
+ def initialize(gem_name, source)
14
17
  @gem_name = gem_name
15
18
  @source = source
16
19
  end
@@ -30,29 +33,30 @@ module GemUpdater
30
33
  #
31
34
  # @return [String|nil] uri of source code
32
35
  def uri_from_rubygems
33
- return unless source.remotes.map( &:host ).include?( 'rubygems.org' )
34
- tries = 0
35
-
36
- response = begin
37
- JSON.parse( open( "https://rubygems.org/api/v1/gems/#{gem_name}.json" ).read )
38
- rescue OpenURI::HTTPError => e
39
- # We may trigger too many requests, in which case give rubygems a break
40
- if e.io.status.include?( '429' )
41
- if ( tries += 1 ) < 2
42
- sleep 1 and retry
43
- end
44
- end
45
- end
36
+ return unless source.remotes.map(&:host).include?('rubygems.org')
46
37
 
47
- if response
38
+ if response = query_rubygems
48
39
  response[
49
- %w( source_code_uri homepage_uri ).find do |key|
50
- response[ key ] && !response[ key ].empty?
51
- end
40
+ GEM_HOMEPAGES.find { |key| response[key] && !response[key].empty? }
52
41
  ]
53
42
  end
54
43
  end
55
44
 
45
+ # Make the real query to rubygems
46
+ # It may fail in case we trigger too many requests
47
+ #
48
+ # @param tries [Integer|nil] (optional) how many times we tried
49
+ def query_rubygems(tries = 0)
50
+ JSON.parse(open("https://rubygems.org/api/v1/gems/#{gem_name}.json").read)
51
+ rescue OpenURI::HTTPError => e
52
+ # We may trigger too many requests, in which case give rubygems a break
53
+ if e.io.status.include?(HTTP_TOO_MANY_REQUESTS)
54
+ if (tries += 1) < 2
55
+ sleep 1 and retry
56
+ end
57
+ end
58
+ end
59
+
56
60
  # Look if gem can be found in another remote
57
61
  #
58
62
  # @return [String|nil] uri of source code
@@ -78,17 +82,22 @@ module GemUpdater
78
82
  #
79
83
  # @return [String|nil] uri of source code
80
84
  def uri_from_railsassets
81
- begin
82
- response = JSON.parse( open( "https://rails-assets.org/packages/#{gem_name.gsub( /rails-assets-/, '' )}" ).read )
83
- rescue JSON::ParserError
84
- # if gem is not found, rails-assets returns a 200
85
- # with html (instead of json) containing a 500...
86
- rescue OpenURI::HTTPError
85
+ if response = query_railsassets
86
+ response['url'].gsub(/^git/, 'http')
87
87
  end
88
+ end
88
89
 
89
- if response
90
- response[ "url" ].gsub( /^git/, 'http' )
91
- end
90
+ # Make the real query to railsassets
91
+ def query_railsassets
92
+ JSON.parse(
93
+ open(
94
+ "https://rails-assets.org/packages/#{gem_name.gsub(/rails-assets-/, '')}"
95
+ ).read
96
+ )
97
+ rescue JSON::ParserError
98
+ # if gem is not found, rails-assets returns a 200
99
+ # with html (instead of json) containing a 500...
100
+ rescue OpenURI::HTTPError
92
101
  end
93
102
  end
94
103
  end
@@ -6,11 +6,16 @@ module GemUpdater
6
6
  # SourcePageParser is responsible for parsing a source page where
7
7
  # the gem code is hosted.
8
8
  class SourcePageParser
9
+ HOSTS = { github: /github.com/, bitbucket: /bitbucket.org/ }.freeze
10
+ MARKUP_FILES = %w[.md .rdoc .textile].freeze
11
+ CHANGELOG_NAMES = %w[changelog ChangeLog history changes news].freeze
12
+
13
+ attr_reader :uri, :version
9
14
 
10
15
  # @param url [String] url of page
11
16
  # @param version [String] version of gem
12
- def initialize( url: nil, version: nil )
13
- @uri = correct_uri( url )
17
+ def initialize(url: nil, version: nil)
18
+ @uri = correct_uri(url)
14
19
  @version = version
15
20
  end
16
21
 
@@ -19,16 +24,18 @@ module GemUpdater
19
24
  # @return [String, nil] URL of changelog
20
25
  def changelog
21
26
  @changelog ||= begin
22
- Bundler.ui.warn "Looking for a changelog in #{@uri}"
23
- doc = Nokogiri::HTML( open( @uri ) )
27
+ if uri
28
+ Bundler.ui.warn "Looking for a changelog in #{uri}"
29
+ doc = Nokogiri::HTML(open(uri))
24
30
 
25
- find_changelog( doc )
31
+ find_changelog(doc)
32
+ end
26
33
 
27
34
  rescue OpenURI::HTTPError # Uri points to nothing
28
- Bundler.ui.error "Cannot find #{@uri}"
35
+ Bundler.ui.error "Cannot find #{uri}"
29
36
  false
30
37
  rescue Errno::ETIMEDOUT # timeout
31
- Bundler.ui.error "#{@uri} is down"
38
+ Bundler.ui.error "#{uri} is down"
32
39
  false
33
40
  end
34
41
  end
@@ -40,28 +47,43 @@ module GemUpdater
40
47
  #
41
48
  # @param url [String] the url to parse
42
49
  # @return [URI] valid URI
43
- def correct_uri( url )
44
- uri = URI( url )
50
+ def correct_uri(url)
51
+ return unless String === url && !url.empty?
52
+
53
+ uri = URI(url)
54
+
45
55
  if uri.scheme == 'http'
46
- case
47
- when uri.host.match( 'github.com' )
48
- # remove possible subdomain like 'wiki.github.com'
49
- uri = URI "https://github.com#{uri.path}"
50
- when uri.host.match( 'bitbucket.org' )
51
- uri = URI "https://#{uri.host}#{uri.path}"
52
- end
56
+ known_https(uri)
57
+ else
58
+ uri
53
59
  end
60
+ end
54
61
 
55
- uri
62
+ # Some uris are not https, but we know they should be,
63
+ # in which case we have an https redirection
64
+ # which is not properly handled by open-uri
65
+ #
66
+ # @param uri [URI::HTTP]
67
+ # @return [URI::HTTPS|URI::HTTP]
68
+ def known_https(uri)
69
+ case
70
+ when uri.host =~ HOSTS[:github]
71
+ # remove possible subdomain like 'wiki.github.com'
72
+ URI "https://github.com#{uri.path}"
73
+ when uri.host =~ HOSTS[:bitbucket]
74
+ URI "https://#{uri.host}#{uri.path}"
75
+ else
76
+ uri
77
+ end
56
78
  end
57
79
 
58
80
  # Try to find where changelog might be.
59
81
  #
60
82
  # @param doc [Nokogiri::XML::Element] document of source page
61
- def find_changelog( doc )
62
- case @uri.host
83
+ def find_changelog(doc)
84
+ case uri.host
63
85
  when 'github.com'
64
- GitHubParser.new( doc, @version ).changelog
86
+ GitHubParser.new(doc, version).changelog
65
87
  end
66
88
  end
67
89
 
@@ -70,9 +92,9 @@ module GemUpdater
70
92
  #
71
93
  # @return [Array] list of possible names
72
94
  def changelog_names
73
- base_names = %w( changelog history changes news )
74
- other_names = %w( ChangeLog )
75
- base_names + base_names.map( &:upcase ) + base_names.map( &:capitalize ) + other_names
95
+ CHANGELOG_NAMES.flat_map do |name|
96
+ [name, name.upcase, name.capitalize]
97
+ end.uniq
76
98
  end
77
99
 
78
100
  # Some documents like the one written in markdown may contain
@@ -80,18 +102,20 @@ module GemUpdater
80
102
  #
81
103
  # @param file_name [String] file name of changelog
82
104
  # @return [Boolean] true if file may contain an anchor
83
- def changelog_may_contain_anchor?( file_name )
84
- %w( .md .rdoc .textile ).include?( File.extname( file_name ) )
105
+ def changelog_may_contain_anchor?(file_name)
106
+ MARKUP_FILES.include?(File.extname(file_name))
85
107
  end
86
108
 
87
109
  # GitHubParser is responsible for parsing source code
88
110
  # hosted on github.com.
89
111
  class GitHubParser < SourcePageParser
90
- BASE_URL = 'https://github.com'
112
+ BASE_URL = 'https://github.com'.freeze
113
+
114
+ attr_reader :doc, :version
91
115
 
92
116
  # @param doc [Nokogiri::XML::Element] document of source page
93
117
  # @param version [String] version of gem
94
- def initialize( doc, version )
118
+ def initialize(doc, version)
95
119
  @doc = doc
96
120
  @version = version
97
121
  end
@@ -105,8 +129,8 @@ module GemUpdater
105
129
  if url
106
130
  full_url = BASE_URL + url
107
131
 
108
- if changelog_may_contain_anchor?( full_url )
109
- anchor = find_anchor( full_url )
132
+ if changelog_may_contain_anchor?(full_url)
133
+ anchor = find_anchor(full_url)
110
134
  full_url += anchor if anchor
111
135
  end
112
136
 
@@ -121,10 +145,9 @@ module GemUpdater
121
145
  # @return [String, nil] url of changelog
122
146
  def find_changelog_link
123
147
  changelog_names.find do |name|
124
- node = @doc.at_css( %(table.files a[title^="#{name}"]) )
125
- if node
126
- break node.attr( 'href' )
127
- end
148
+ node = doc.at_css(%(table.files a[title^="#{name}"]))
149
+
150
+ break node.attr('href') if node
128
151
  end
129
152
  end
130
153
 
@@ -132,13 +155,13 @@ module GemUpdater
132
155
  #
133
156
  # @param url [String] url of changelog
134
157
  # @return [String, nil] anchor's href
135
- def find_anchor( url )
136
- changelog_page = Nokogiri::HTML( open( url ) )
137
- anchor = changelog_page.css( %(a.anchor) ).find{ |element| element.attr( 'href' ).match( @version.gsub('.', '') ) }
138
-
139
- if anchor
140
- anchor.attr( 'href' )
158
+ def find_anchor(url)
159
+ changelog_page = Nokogiri::HTML(open(url))
160
+ anchor = changelog_page.css(%(a.anchor)).find do |element|
161
+ element.attr('href').match(version.delete('.'))
141
162
  end
163
+
164
+ anchor.attr('href') if anchor
142
165
  end
143
166
  end
144
167
  end
@@ -1,5 +1,5 @@
1
- * <%= gem %> <%= details[ :versions ][ :old ] %> → <%= details[ :versions ][ :new ] %>
2
- <% if details[ :changelog ] %>
3
- [changelog](<%= details[ :changelog ] %>)
1
+ * <%= gem %> <%= details[:versions][:old] %> → <%= details[:versions][:new] %>
2
+ <% if details[:changelog] %>
3
+ [changelog](<%= details[:changelog] %>)
4
4
  <% end %>
5
5
 
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: 0.4.5
4
+ version: 0.5.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: 2016-02-13 00:00:00.000000000 Z
11
+ date: 2016-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -100,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
100
  version: '0'
101
101
  requirements: []
102
102
  rubyforge_project:
103
- rubygems_version: 2.4.5.1
103
+ rubygems_version: 2.5.1
104
104
  signing_key:
105
105
  specification_version: 4
106
106
  summary: Update your gems and find their changelogs