gem_updater 0.4.5 → 0.5.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
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