gem_fresh 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +69 -0
- data/Rakefile +1 -0
- data/gemfresh.gemspec +23 -0
- data/lib/gem_fresh/calculator.rb +67 -0
- data/lib/gem_fresh/config.rb +52 -0
- data/lib/gem_fresh/gem_version.rb +13 -0
- data/lib/gem_fresh/missing.rb +48 -0
- data/lib/gem_fresh/outdated.rb +48 -0
- data/lib/gem_fresh/railtie.rb +21 -0
- data/lib/gem_fresh/reporter.rb +36 -0
- data/lib/gem_fresh/version.rb +3 -0
- data/lib/gem_fresh.rb +8 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 563e8d2d986b8d974e4fcbfb1fb3c09e9a0cc125
|
4
|
+
data.tar.gz: 310303c1f1d099669050b7d619c43681577e2da8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ef9184f6a7ef14df71c550eb9f9a738f33a64074f4b2c655dbb054d32e5a02fdf1a2c3fcfd62b10167a55862384491a42d40a80802cf88e768037005202c8d39
|
7
|
+
data.tar.gz: 3aee268d62e854ac6ec8db896933894ee0c2c8efbcbb5150801da95a56dafb2eab8597ff3cb0a66366e8d1ea3de12e23e67a6ee8cae97cba21e8c9a3658af784
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Anne Geiersbach
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# GemFresh
|
2
|
+
|
3
|
+
The purpose of GemFresh is to expose useful information about how outdated your application gems are.
|
4
|
+
|
5
|
+
## Setup
|
6
|
+
|
7
|
+
Create a file called GemFresh.rb in the root directory of your application. Fill it out like this:
|
8
|
+
|
9
|
+
# Any gems that you put in the Gemfile should also be listed here.
|
10
|
+
# The rake metrics:outdated_gems task calculates which gems are
|
11
|
+
# outdated and then combines that information with the information
|
12
|
+
# listed here about a particular gem's reach in the application code.
|
13
|
+
#
|
14
|
+
GemFresh::Config.configure do |gems|
|
15
|
+
|
16
|
+
# Updating these gems could require you to make large, system-wide changes
|
17
|
+
# to the application code.
|
18
|
+
gems.with_system_wide_impact %w(
|
19
|
+
resque
|
20
|
+
rspec
|
21
|
+
...
|
22
|
+
)
|
23
|
+
|
24
|
+
# Updating these gems could require you to make some changes to small
|
25
|
+
# sections of the application.
|
26
|
+
gems.with_local_impact %w(
|
27
|
+
fog
|
28
|
+
tabulous
|
29
|
+
...
|
30
|
+
)
|
31
|
+
|
32
|
+
# When updating these gems, you barely have to touch any code at all.
|
33
|
+
gems.with_minimal_impact %w(
|
34
|
+
airbrake
|
35
|
+
bullet
|
36
|
+
...
|
37
|
+
)
|
38
|
+
|
39
|
+
# We ignore these since we are in complete control of their update cycles.
|
40
|
+
gems.that_are_private %w(
|
41
|
+
dmc_server_admin
|
42
|
+
job_state
|
43
|
+
...
|
44
|
+
)
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
Then create a rake task like this:
|
49
|
+
|
50
|
+
namespace :metrics do
|
51
|
+
desc "display outdated gem version metrics"
|
52
|
+
task :outdated_gems do
|
53
|
+
GemFresh::Reporter.new.report
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
## Usage
|
59
|
+
|
60
|
+
See information on your outdated gems by running the rake task:
|
61
|
+
|
62
|
+
rake metrics:outdated_gems
|
63
|
+
|
64
|
+
This combines information from `bundle outdated` with the information in GemFresh.rb to give a weighted view as to how outdated your third-party Ruby code is and how much it matters.
|
65
|
+
|
66
|
+
Whenever you add a gem to your Gemfile, add it to GemFresh.rb so that the rake task knows how important the gem is.
|
67
|
+
|
68
|
+
Gems are assigned points. The more central a gem is, and the more outdated it is, the higher the points. You can think of the points as a "bounty" on the gem, telling you how badly it needs to be updated.
|
69
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/gemfresh.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gem_fresh/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gem_fresh"
|
8
|
+
spec.version = GemFresh::VERSION
|
9
|
+
spec.authors = ["Anne Geiersbach"]
|
10
|
+
spec.email = ["annasazi@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Quantifying the freshness of your gems.}
|
13
|
+
spec.homepage = "https://github.com/dmcouncil/gem_fresh"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module GemFresh
|
2
|
+
class Calculator
|
3
|
+
|
4
|
+
# If a gem is behind by a major version, it's worth more points
|
5
|
+
# than a minor version.
|
6
|
+
POINTS_FOR_MAJOR = 100
|
7
|
+
POINTS_FOR_MINOR = 10
|
8
|
+
POINTS_FOR_PATCH = 1
|
9
|
+
|
10
|
+
# Point multipliers based on how central the gem is to the application code.
|
11
|
+
MINIMAL_MULTIPLIER = 0.1
|
12
|
+
LOCAL_MULTIPLIER = 1
|
13
|
+
SYSTEM_MULTIPLIER = 10
|
14
|
+
FRAMEWORK_MULTIPLIER = 100
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@freshness_scores = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def calculate!
|
21
|
+
@gem_freshness_info = GemFresh::Outdated.new.gem_info
|
22
|
+
calculate_freshness_scores_for_each_gem
|
23
|
+
end
|
24
|
+
|
25
|
+
def total_score
|
26
|
+
@freshness_scores.values.sum.round(1)
|
27
|
+
end
|
28
|
+
|
29
|
+
def all_scores
|
30
|
+
@freshness_scores
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def calculate_freshness_scores_for_each_gem
|
36
|
+
calculate_for_gems(['rails'], FRAMEWORK_MULTIPLIER)
|
37
|
+
calculate_for_gems(Config.config.system_wide_gems, SYSTEM_MULTIPLIER)
|
38
|
+
calculate_for_gems(Config.config.local_gems, LOCAL_MULTIPLIER)
|
39
|
+
calculate_for_gems(Config.config.minimal_gems, MINIMAL_MULTIPLIER)
|
40
|
+
end
|
41
|
+
|
42
|
+
def calculate_for_gems(gems, multiplier)
|
43
|
+
gems.each do |gem_name|
|
44
|
+
@freshness_scores[gem_name] =
|
45
|
+
(calculate_freshness_score_for(gem_name) * multiplier).round(1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def calculate_freshness_score_for(gem_name)
|
50
|
+
info = @gem_freshness_info[gem_name]
|
51
|
+
return 0 if info.nil? # no outdated info means it's fresh
|
52
|
+
major_diff = (info[:available_version].major - info[:current_version].major)
|
53
|
+
minor_diff = (info[:available_version].minor - info[:current_version].minor)
|
54
|
+
patch_diff = (info[:available_version].patch - info[:current_version].patch)
|
55
|
+
score = 0
|
56
|
+
if major_diff > 0
|
57
|
+
score += major_diff * POINTS_FOR_MAJOR
|
58
|
+
elsif minor_diff > 0
|
59
|
+
score += minor_diff * POINTS_FOR_MINOR
|
60
|
+
elsif patch_diff > 0
|
61
|
+
score += patch_diff * POINTS_FOR_PATCH
|
62
|
+
end
|
63
|
+
score
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module GemFresh
|
2
|
+
class Config
|
3
|
+
|
4
|
+
attr_reader :system_wide_gems, :local_gems, :minimal_gems, :private_gems
|
5
|
+
|
6
|
+
def self.configure(&block)
|
7
|
+
@@config ||= Config.new
|
8
|
+
block.call(@@config)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.config
|
12
|
+
@@config ||= begin
|
13
|
+
config = Config.new
|
14
|
+
config.with_system_wide_impact([])
|
15
|
+
config.with_local_impact([])
|
16
|
+
config.with_minimal_impact([])
|
17
|
+
config.that_are_private([])
|
18
|
+
config
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def with_system_wide_impact(gems)
|
23
|
+
@system_wide_gems = clean_gems(gems)
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_local_impact(gems)
|
27
|
+
@local_gems = clean_gems(gems)
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_minimal_impact(gems)
|
31
|
+
@minimal_gems = clean_gems(gems)
|
32
|
+
end
|
33
|
+
|
34
|
+
def that_are_private(gems)
|
35
|
+
@private_gems = clean_gems(gems)
|
36
|
+
end
|
37
|
+
|
38
|
+
def all_gems
|
39
|
+
@system_wide_gems + @local_gems + @minimal_gems + @private_gems
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def clean_gems(gems)
|
45
|
+
if gems.include?('rails')
|
46
|
+
raise "Do not explicitly specify the rails gem in Gemfresh.rb." #TODO: why not?
|
47
|
+
end
|
48
|
+
gems
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module GemFresh
|
2
|
+
class GemVersion
|
3
|
+
attr_reader :major, :minor, :patch
|
4
|
+
|
5
|
+
# version_string is usually formatted like 7.6.2, but could be
|
6
|
+
# 7.6.2.11, 7.6, or even 7.6.2.beta. We just care about the first
|
7
|
+
# three numbers
|
8
|
+
def initialize(version_string)
|
9
|
+
@major, @minor, @patch = version_string.split('.').map(&:to_i)
|
10
|
+
@patch ||= 0
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module GemFresh
|
2
|
+
class Missing
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
parse_gemfile
|
6
|
+
end
|
7
|
+
|
8
|
+
def check_for_missing_gems!
|
9
|
+
if missing_gems.any?
|
10
|
+
message = "The following gems are in your Gemfile but not in your Gemfresh.rb file:\n"
|
11
|
+
missing_gems.each do |gem_name|
|
12
|
+
message << " #{gem_name}\n"
|
13
|
+
end
|
14
|
+
raise message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def missing_gems
|
21
|
+
missing_gems = []
|
22
|
+
gems_from_gemfresh = gemfresh.all_gems
|
23
|
+
gem_names.each do |gem_from_gemfile|
|
24
|
+
if not gems_from_gemfresh.include?(gem_from_gemfile)
|
25
|
+
missing_gems << gem_from_gemfile
|
26
|
+
end
|
27
|
+
end
|
28
|
+
missing_gems.reject!{|g| g == 'rails'}
|
29
|
+
missing_gems
|
30
|
+
end
|
31
|
+
|
32
|
+
def gem_names
|
33
|
+
@gem_lines.map do |gem_line|
|
34
|
+
gem_line.split.second.gsub(/[^A-Za-z0-9\-_]/, '')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
#TODO: we shouldn't be so tied to Rails in future
|
39
|
+
def parse_gemfile
|
40
|
+
gemfile = File.join(Rails.root, 'Gemfile')
|
41
|
+
@gem_lines = IO.readlines(gemfile).select{|line| line =~ /\A\s*gem/ }
|
42
|
+
end
|
43
|
+
|
44
|
+
def gemfresh
|
45
|
+
GemFresh::Config.config
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module GemFresh
|
2
|
+
class Outdated
|
3
|
+
|
4
|
+
attr_reader :gem_info
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
figure_out_outdated_gems
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def figure_out_outdated_gems
|
13
|
+
@gem_info ={}
|
14
|
+
raw_gem_info_from_bundler.each do |line|
|
15
|
+
#
|
16
|
+
# Sample lines from `bundle outdated` look like this:
|
17
|
+
#
|
18
|
+
# * airbrake (4.1.0 > 3.1.3)
|
19
|
+
# * annotate (2.6.5 > 2.6.0.beta2) Gemfile specifies "= 2.6.0.beta2"
|
20
|
+
# * bootstrap-multiselect-rails (0.9.5 > 0.0.4)
|
21
|
+
# * byebug (3.5.1 > 2.5.0)
|
22
|
+
# * enum_field (0.2.0 bff7873 > 0.2.0)
|
23
|
+
# or this:
|
24
|
+
# * responders (newest 2.1.0, installed 1.1.2) in group "default"
|
25
|
+
# * resque-retry (newest 1.4.0, installed 1.3.2) in group "default"
|
26
|
+
# * resque-status (newest 0.5.0, installed 0.4.1, requested = 0.4.1) in group "default"
|
27
|
+
# * rspec (newest 3.3.0, installed 3.2.0, requested ~> 3.2.0) in groups "development, test"
|
28
|
+
#
|
29
|
+
words = line.split
|
30
|
+
words_that_contain_version_numbers = words.select {|word| word =~ /\d+\.\d+/ }
|
31
|
+
version_numbers = words_that_contain_version_numbers.map {|word| word.gsub(/[\(\),]/, '') }
|
32
|
+
line =~ /\A\s*\*\s+(\S+)/
|
33
|
+
gem_name = $1
|
34
|
+
@gem_info[gem_name] = { available_version: GemVersion.new(version_numbers[0]),
|
35
|
+
current_version: GemVersion.new(version_numbers[1]) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def raw_gem_info_from_bundler
|
40
|
+
output = %x{ bundle outdated }
|
41
|
+
just_the_gem_lines = output.split("\n").map(&:strip).select do |line|
|
42
|
+
line =~ /\A\s*\*\s+\w/
|
43
|
+
end
|
44
|
+
just_the_gem_lines
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'gem_fresh'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module GemFresh
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
railtie_name :gem_fresh
|
7
|
+
|
8
|
+
puts "Woohoo, a GemFresh Railtie"
|
9
|
+
puts "env? #{Rails.env}"
|
10
|
+
puts GemFresh::Config.config
|
11
|
+
|
12
|
+
rake_tasks do
|
13
|
+
namespace :gem_fresh do
|
14
|
+
desc "outdated"
|
15
|
+
task :outdated => :environment do
|
16
|
+
GemFresh::Reporter.new.report
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module GemFresh
|
2
|
+
class Reporter
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
Missing.new.check_for_missing_gems!
|
6
|
+
@calculator = Calculator.new
|
7
|
+
@calculator.calculate!
|
8
|
+
end
|
9
|
+
|
10
|
+
def report
|
11
|
+
puts
|
12
|
+
puts "A bounty is calculated for each gem based on how outdated the gem"
|
13
|
+
puts "is and the impact the gem has on the application code. Foundational"
|
14
|
+
puts "gems like RSpec get a higher bounty, simple add-on tools like bullet"
|
15
|
+
puts "get a lower bounty. See Gemfresh.rb for details."
|
16
|
+
puts
|
17
|
+
puts "The total bounty is #{@calculator.total_score} points."
|
18
|
+
puts
|
19
|
+
puts "These are the outdated gems, sorted by highest bounty:"
|
20
|
+
puts
|
21
|
+
sorted_scores = @calculator.all_scores.sort_by{|gem_name, score| [-score, gem_name]}
|
22
|
+
sorted_scores.each do |gem_name, score|
|
23
|
+
name = " #{gem_name.ljust(25)[0..24]} "
|
24
|
+
if score >= 1000
|
25
|
+
puts "#{name} #{score}"
|
26
|
+
elsif score > 0
|
27
|
+
puts "#{name} #{score}"
|
28
|
+
else
|
29
|
+
puts "#{name} up to date"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
puts
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
data/lib/gem_fresh.rb
ADDED
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gem_fresh
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anne Geiersbach
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-08 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.9'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description:
|
42
|
+
email:
|
43
|
+
- annasazi@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- .gitignore
|
49
|
+
- .rspec
|
50
|
+
- .travis.yml
|
51
|
+
- Gemfile
|
52
|
+
- LICENSE.txt
|
53
|
+
- README.md
|
54
|
+
- Rakefile
|
55
|
+
- gemfresh.gemspec
|
56
|
+
- lib/gem_fresh.rb
|
57
|
+
- lib/gem_fresh/calculator.rb
|
58
|
+
- lib/gem_fresh/config.rb
|
59
|
+
- lib/gem_fresh/gem_version.rb
|
60
|
+
- lib/gem_fresh/missing.rb
|
61
|
+
- lib/gem_fresh/outdated.rb
|
62
|
+
- lib/gem_fresh/railtie.rb
|
63
|
+
- lib/gem_fresh/reporter.rb
|
64
|
+
- lib/gem_fresh/version.rb
|
65
|
+
homepage: https://github.com/dmcouncil/gem_fresh
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata: {}
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.0.14
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Quantifying the freshness of your gems.
|
89
|
+
test_files: []
|