gem_updater 0.0.1
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 +7 -0
- data/bin/gem_update +13 -0
- data/lib/gem_updater.rb +49 -0
- data/lib/gem_updater/gem_file.rb +34 -0
- data/lib/gem_updater/ruby_gems_fetcher.rb +34 -0
- data/lib/gem_updater/source_page_parser.rb +131 -0
- data/lib/gem_updater_template.erb +5 -0
- metadata +108 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1b964766638c2f8ef6afc1b87b3d17ae68fec20c
|
4
|
+
data.tar.gz: 92e434d50c4d81fb9d95537afe89001fdd9536ea
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 04b7c13adf8c38658fb0a47e6df184373f826d94c5bc29f889bd86d85b942cf96506eb6d58d05b41fdf4a5f1d3f457fa2ff3d4cda224080697e5bf5939b6f92b
|
7
|
+
data.tar.gz: f01e1bc74d5618300f0728d0e2ed7bf43a8244d27beaedf12b34b4943bf061f3eada7f856ccbc31d15da5e37228d4ae493d95fe0165b31aa088f9f4a57ee32d7
|
data/bin/gem_update
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Exit cleanly from an early interrupt
|
4
|
+
Signal.trap("INT") { exit 1 }
|
5
|
+
|
6
|
+
require 'gem_updater'
|
7
|
+
|
8
|
+
gems = GemUpdater::Updater.new
|
9
|
+
gems.update!
|
10
|
+
|
11
|
+
puts "\nHere are your changes:"
|
12
|
+
puts '------------------------'
|
13
|
+
gems.format_diff
|
data/lib/gem_updater.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'gem_updater/gem_file'
|
2
|
+
require 'gem_updater/ruby_gems_fetcher'
|
3
|
+
require 'gem_updater/source_page_parser'
|
4
|
+
|
5
|
+
module GemUpdater
|
6
|
+
class Updater
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@gemfile = GemUpdater::GemFile.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# Update process.
|
13
|
+
# This will:
|
14
|
+
# 1. update gemfile
|
15
|
+
# 2. find changelogs for updated gems
|
16
|
+
def update!
|
17
|
+
@gemfile.update!
|
18
|
+
|
19
|
+
@gemfile.changes.each do |gem_name, details|
|
20
|
+
source_uri = GemUpdater::RubyGemsFetcher.new( gem_name ).source_uri
|
21
|
+
source_page = GemUpdater::SourcePageParser.new( url: source_uri, version: details[ :versions ][ :new ] )
|
22
|
+
|
23
|
+
@gemfile.changes[ gem_name ][ :changelog ] = source_page.changelog if source_page.changelog
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Format the diff to get human readable information
|
28
|
+
# on the gems that were updated.
|
29
|
+
def format_diff
|
30
|
+
@gemfile.changes.each do |gem, details|
|
31
|
+
puts ERB.new( template, nil, '<>' ).result( binding )
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Get the template for gem's diff.
|
38
|
+
# It can use a custom template.
|
39
|
+
#
|
40
|
+
# @return [ERB] the template
|
41
|
+
def template
|
42
|
+
@template ||= begin
|
43
|
+
File.read( "#{Dir.home}/.gem_updater_template.erb" )
|
44
|
+
rescue Errno::ENOENT
|
45
|
+
File.read( File.expand_path( '../../lib/gem_updater_template.erb', __FILE__ ) )
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'bundler/cli'
|
2
|
+
|
3
|
+
module GemUpdater
|
4
|
+
|
5
|
+
# GemFile is responsible for handling `Gemfile`
|
6
|
+
class GemFile
|
7
|
+
attr_accessor :changes
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@old_spec_set = Bundler.definition.specs
|
11
|
+
@changes = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
# Run `bundle update` to update gems.
|
15
|
+
# Then get new spec set.
|
16
|
+
def update!
|
17
|
+
puts "Updating gems..."
|
18
|
+
Bundler::CLI.new.update
|
19
|
+
@new_spec_set = Bundler.definition.specs
|
20
|
+
compute_changes
|
21
|
+
end
|
22
|
+
|
23
|
+
# Compute the diffs between two `Gemfile.lock`.
|
24
|
+
#
|
25
|
+
# @return [Hash] gems for which there are differences.
|
26
|
+
def compute_changes
|
27
|
+
@old_spec_set.each do |gem_specs|
|
28
|
+
unless ( old_version = gem_specs.version ) == ( new_version = @new_spec_set[ gem_specs.name ].first.version )
|
29
|
+
@changes[ gem_specs.name ] = { versions: { old: old_version.to_s, new: new_version.to_s } }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'open-uri'
|
4
|
+
|
5
|
+
module GemUpdater
|
6
|
+
|
7
|
+
# RubyGemsFetcher is a wrapper around rubygems API.
|
8
|
+
class RubyGemsFetcher
|
9
|
+
|
10
|
+
# @param gem_name [String] name of the gem
|
11
|
+
def initialize( gem_name )
|
12
|
+
@gem_name = gem_name
|
13
|
+
end
|
14
|
+
|
15
|
+
# Finds where code is hosted.
|
16
|
+
# Most likely in will be in 'source_code_uri' or 'homepage_uri'
|
17
|
+
#
|
18
|
+
# @return [String] url of gem source code
|
19
|
+
def source_uri
|
20
|
+
information[ "source_code_uri" ] || information[ "homepage_uri" ]
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Obtain information about a given gem
|
26
|
+
# from rubygems.org.
|
27
|
+
# See API: http://guides.rubygems.org/rubygems-org-api/#gem-methods
|
28
|
+
#
|
29
|
+
# @return [Hash] parse of json information
|
30
|
+
def information
|
31
|
+
@information ||= JSON.parse( open( "https://rubygems.org/api/v1/gems/#{@gem_name}.json" ).read )
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
module GemUpdater
|
5
|
+
|
6
|
+
# SourcePageParser is responsible for parsing a source page where
|
7
|
+
# the gem code is hosted.
|
8
|
+
class SourcePageParser
|
9
|
+
|
10
|
+
# @param url [String] url of page
|
11
|
+
# @param version [String] version of gem
|
12
|
+
def initialize( url: nil, version: nil )
|
13
|
+
@uri = correct_uri( url )
|
14
|
+
@version = version
|
15
|
+
end
|
16
|
+
|
17
|
+
# Get the changelog in an uri.
|
18
|
+
#
|
19
|
+
# @return [String, nil] URL of changelog
|
20
|
+
def changelog
|
21
|
+
@changelog ||= begin
|
22
|
+
puts "Looking for a changelog in #{@uri}"
|
23
|
+
doc = Nokogiri::HTML( open( @uri ) )
|
24
|
+
|
25
|
+
find_changelog( doc )
|
26
|
+
|
27
|
+
rescue OpenURI::HTTPError # Uri points to nothing
|
28
|
+
puts "Cannot find #{@uri}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Some gems have 'http://github.com' as URI which will redirect to https
|
35
|
+
# leading `open_uri` to crash.
|
36
|
+
#
|
37
|
+
# @param url [String] the url to parse
|
38
|
+
# @return [URI] valid URI
|
39
|
+
def correct_uri( url )
|
40
|
+
uri = URI( url )
|
41
|
+
uri.scheme = 'https' if uri.host == 'github.com' && uri.scheme == 'http'
|
42
|
+
|
43
|
+
uri
|
44
|
+
end
|
45
|
+
|
46
|
+
# Try to find where changelog might be.
|
47
|
+
#
|
48
|
+
# @param doc [Nokogiri::XML::Element] document of source page
|
49
|
+
def find_changelog( doc )
|
50
|
+
case @uri.host
|
51
|
+
when 'github.com'
|
52
|
+
GitHubParser.new( doc, @version ).changelog
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# List possible names for a changelog
|
57
|
+
# since humans may have many many ways to call it.
|
58
|
+
#
|
59
|
+
# @return [Array] list of possible names
|
60
|
+
def changelog_names
|
61
|
+
%w( CHANGELOG Changelog ChangeLog changelog HISTORY History history )
|
62
|
+
end
|
63
|
+
|
64
|
+
# Some documents like the one written in markdown may contain
|
65
|
+
# a direct anchor to specific version.
|
66
|
+
#
|
67
|
+
# @param file_name [String] file name of changelog
|
68
|
+
# @return [Boolean] true if file may contain an anchor
|
69
|
+
def changelog_may_contain_anchor?( file_name )
|
70
|
+
%w( .md .rdoc ).include?( File.extname( file_name ) )
|
71
|
+
end
|
72
|
+
|
73
|
+
# GitHubParser is responsible for parsing source code
|
74
|
+
# hosted on github.com.
|
75
|
+
class GitHubParser < SourcePageParser
|
76
|
+
BASE_URL = 'https://github.com'
|
77
|
+
|
78
|
+
# @param doc [Nokogiri::XML::Element] document of source page
|
79
|
+
# @param version [String] version of gem
|
80
|
+
def initialize( doc, version )
|
81
|
+
@doc = doc
|
82
|
+
@version = version
|
83
|
+
end
|
84
|
+
|
85
|
+
# Finds url of changelog.
|
86
|
+
#
|
87
|
+
# @return [String] the URL of changelog
|
88
|
+
def changelog
|
89
|
+
url = find_changelog_link
|
90
|
+
|
91
|
+
if url
|
92
|
+
full_url = BASE_URL + url
|
93
|
+
|
94
|
+
if changelog_may_contain_anchor?( full_url )
|
95
|
+
anchor = find_anchor( full_url )
|
96
|
+
full_url += anchor if anchor
|
97
|
+
end
|
98
|
+
|
99
|
+
full_url
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# Find which link corresponds to changelog.
|
106
|
+
#
|
107
|
+
# @return [String, nil] url of changelog
|
108
|
+
def find_changelog_link
|
109
|
+
changelog_names.find do |name|
|
110
|
+
node = @doc.at_css( %(table.files a[title^="#{name}"]) )
|
111
|
+
if node
|
112
|
+
break node.attr( 'href' )
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Looks into document to find it there is an anchor to new gem version.
|
118
|
+
#
|
119
|
+
# @param url [String] url of changelog
|
120
|
+
# @return [String, nil] anchor's href
|
121
|
+
def find_anchor( url )
|
122
|
+
changelog_page = Nokogiri::HTML( open( url ) )
|
123
|
+
anchor = changelog_page.css( %(a.anchor) ).find{ |element| element.attr( 'href' ).match( @version.gsub('.', '') ) }
|
124
|
+
|
125
|
+
if anchor
|
126
|
+
anchor.attr( 'href' )
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gem_updater
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maxime Demolin
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.8'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
description: It updates the gems of your Gemfile and fetches the links pointing to
|
70
|
+
where their changelogs are
|
71
|
+
email: akbarova.armia@gmail.com
|
72
|
+
executables:
|
73
|
+
- gem_update
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- bin/gem_update
|
78
|
+
- lib/gem_updater.rb
|
79
|
+
- lib/gem_updater/gem_file.rb
|
80
|
+
- lib/gem_updater/ruby_gems_fetcher.rb
|
81
|
+
- lib/gem_updater/source_page_parser.rb
|
82
|
+
- lib/gem_updater_template.erb
|
83
|
+
homepage: https://github.com/MaximeD/gem_updater
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.4.5
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Update your gems and find their changelogs
|
107
|
+
test_files: []
|
108
|
+
has_rdoc:
|