gistory 0.1.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 +7 -0
- data/.gitignore +11 -0
- data/.rubocop.yml +15 -0
- data/.travis.yml +5 -0
- data/Gemfile +14 -0
- data/README.md +40 -0
- data/Rakefile +10 -0
- data/bin/console +24 -0
- data/bin/setup +8 -0
- data/exe/gistory +8 -0
- data/gistory.gemspec +28 -0
- data/lib/gistory.rb +21 -0
- data/lib/gistory/change_log.rb +43 -0
- data/lib/gistory/cli/arg_parser.rb +85 -0
- data/lib/gistory/cli/io.rb +21 -0
- data/lib/gistory/cli/main.rb +43 -0
- data/lib/gistory/commit.rb +14 -0
- data/lib/gistory/configuration.rb +10 -0
- data/lib/gistory/errors.rb +6 -0
- data/lib/gistory/git_repo.rb +40 -0
- data/lib/gistory/version.rb +4 -0
- data/lib/gistory/version_change.rb +17 -0
- metadata +121 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6f0db94a0ca0b970909c4f8118e5343ecd8bb9dd
|
4
|
+
data.tar.gz: f8d219bce6020ff7c737f3dcc70e0fe2ff08390b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 01dd9e2a1ddfb4e136f6efbe8360b676ebf5c221c1903b10daf1eb8555a77a7bba97b8b3e6cb65c0131c30e8e9c166a54a3c17763094e980428ad3e50590aed5
|
7
|
+
data.tar.gz: 12b412a19b76a0a8a4d4f0159ccb77ea2bfa25f6df209aee24d91dedb99905ae186b0889f79f36f62c406410ac4ca7be7364911545c54f29ba6bbf0957646732
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Metrics/LineLength:
|
2
|
+
Max: 120
|
3
|
+
|
4
|
+
Documentation:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Metrics/AbcSize:
|
8
|
+
# The ABC size is a calculated magnitude, so this number can be a Fixnum or a Float.
|
9
|
+
# http://c2.com/cgi/wiki?AbcMetric
|
10
|
+
Max: 20
|
11
|
+
Exclude:
|
12
|
+
- 'test/**/*_test.rb' # ignore tests which typically have high B count due to many asserts
|
13
|
+
|
14
|
+
Metrics/MethodLength:
|
15
|
+
Max: 15
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development, :test do
|
6
|
+
gem 'byebug' # debugger
|
7
|
+
gem 'pry' # better console
|
8
|
+
gem 'pry-byebug' # pry integration for byebug
|
9
|
+
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'flexmock' # mock object
|
13
|
+
gem 'simplecov', require: false # code coverage
|
14
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# Gistory
|
2
|
+
|
3
|
+
If you use bundler and git, and want to know when a gem you are using was updated, `gistory` comes to your rescue, simply:
|
4
|
+
|
5
|
+
```shell
|
6
|
+
gem install gistory
|
7
|
+
cd /path/to/repo
|
8
|
+
gistory sidekiq
|
9
|
+
```
|
10
|
+
|
11
|
+
and you'll see something like:
|
12
|
+
```
|
13
|
+
Gem: sidekiq
|
14
|
+
Current version: 4.2.7
|
15
|
+
|
16
|
+
Change history:
|
17
|
+
4.2.7 on Tue, 7 Feb 2017 16:05 +01:00 (commit c6edf321)
|
18
|
+
4.2.6 on Wed, 30 Nov 2016 13:47 +01:00 (commit bf6a0d17)
|
19
|
+
4.2.5 on Tue, 22 Nov 2016 14:48 -05:00 (commit 20ff5148)
|
20
|
+
4.1.4 on Wed, 9 Nov 2016 14:31 +01:00 (commit 05a3c549)
|
21
|
+
```
|
22
|
+
|
23
|
+
By default `gistory` only looks at the 100 last changes to Gemfile.lock
|
24
|
+
if you want to see farther in the past run:
|
25
|
+
|
26
|
+
```shell
|
27
|
+
gistory sidekiq -m10000
|
28
|
+
```
|
29
|
+
|
30
|
+
Note that if the gem was added, then removed, and then added again, `gistory` will
|
31
|
+
only show the latest version changes up until it was removed.
|
32
|
+
|
33
|
+
## Roadmap
|
34
|
+
|
35
|
+
- use red for changes in the major version, blue for changes in the minor version
|
36
|
+
- support other VCSs like subversion, mercurial, etc.
|
37
|
+
- detect if the gem was added, then removed and then added again
|
38
|
+
- use a libgit2 binding instead of the git cli, how much faster it is?
|
39
|
+
- remove bundler dep
|
40
|
+
- add yard doc
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'gistory'
|
5
|
+
require 'pry'
|
6
|
+
|
7
|
+
root_path = "#{File.dirname(__FILE__)}/.."
|
8
|
+
|
9
|
+
# require all files in lib for quick access to them in the console
|
10
|
+
Dir["#{root_path}/lib/**/*.rb"].each { |file| require file }
|
11
|
+
|
12
|
+
def reload!
|
13
|
+
verbosity = $VERBOSE
|
14
|
+
begin
|
15
|
+
$VERBOSE = nil
|
16
|
+
files = $LOADED_FEATURES.select { |feat| feat =~ %r{/gistory/} }
|
17
|
+
files.each { |file| load(file) }
|
18
|
+
ensure
|
19
|
+
$VERBOSE = verbosity
|
20
|
+
end
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
Pry.start
|
data/bin/setup
ADDED
data/exe/gistory
ADDED
data/gistory.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'gistory/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'gistory'
|
8
|
+
spec.version = Gistory::VERSION
|
9
|
+
spec.authors = ['Sergio Medina']
|
10
|
+
spec.email = ['medinasergio@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'Gistory: Know exactly when a gem was updated in your Gemfile.lock'
|
13
|
+
spec.description = 'Gistory: Know exactly when a gem was updated in your Gemfile.lock'
|
14
|
+
spec.homepage = 'https://www.github.com/serch/gistory'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_dependency 'bundler', '~> 1.14' # FIXME: what is the minimum bundler version I need?
|
24
|
+
spec.add_dependency 'colorize'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
27
|
+
spec.add_development_dependency 'minitest', '~> 5.0'
|
28
|
+
end
|
data/lib/gistory.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'gistory/version'
|
3
|
+
|
4
|
+
require 'gistory/cli/main'
|
5
|
+
require 'gistory/cli/arg_parser'
|
6
|
+
require 'gistory/cli/io'
|
7
|
+
require 'gistory/configuration'
|
8
|
+
|
9
|
+
require 'gistory/errors'
|
10
|
+
require 'gistory/commit'
|
11
|
+
require 'gistory/version_change'
|
12
|
+
require 'gistory/git_repo'
|
13
|
+
require 'gistory/change_log'
|
14
|
+
|
15
|
+
module Gistory
|
16
|
+
class << self
|
17
|
+
def config
|
18
|
+
@config ||= Gistory::Configuration.new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: truew
|
2
|
+
require 'bundler'
|
3
|
+
|
4
|
+
module Gistory
|
5
|
+
class ChangeLog
|
6
|
+
LOCKFILE = 'Gemfile.lock'.freeze
|
7
|
+
|
8
|
+
def initialize(repo:)
|
9
|
+
@repo = repo
|
10
|
+
end
|
11
|
+
|
12
|
+
def changelog_for_gem(gem_name)
|
13
|
+
version_changes = []
|
14
|
+
previous_version = nil
|
15
|
+
lockfile_changes = @repo.changes_to_file(LOCKFILE)
|
16
|
+
|
17
|
+
lockfile_changes.each do |commit|
|
18
|
+
gem_spec = gem_spec_at_commit_hash(commit.short_hash, gem_name)
|
19
|
+
|
20
|
+
# we reached the end, the gem didn't exist back then
|
21
|
+
# TODO: what if it was added then removed and then added again?
|
22
|
+
break if gem_spec.nil?
|
23
|
+
|
24
|
+
# only store version changes of this gem
|
25
|
+
unless gem_spec.version.to_s == previous_version
|
26
|
+
version_changes << VersionChange.new(commit: commit, version: gem_spec.version)
|
27
|
+
previous_version = gem_spec.version.to_s
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
version_changes
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def gem_spec_at_commit_hash(commit_hash, gem_name)
|
37
|
+
lockfile_content = @repo.file_content_at_commit(commit_hash, LOCKFILE)
|
38
|
+
lockfile = Bundler::LockfileParser.new(lockfile_content)
|
39
|
+
gem_spec = lockfile.specs.find { |spec| spec.name == gem_name }
|
40
|
+
gem_spec
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module Gistory
|
5
|
+
module Cli
|
6
|
+
class ArgParser
|
7
|
+
def initialize(args:, io: Gistory::Cli::Io.new)
|
8
|
+
@args = args
|
9
|
+
@config = Gistory.config
|
10
|
+
@parser = create_parser(@config)
|
11
|
+
@io = io
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse
|
15
|
+
@parser.parse!(@args)
|
16
|
+
|
17
|
+
parse_gem_name
|
18
|
+
@io.error("extra parameters ignored: #{@args}") unless @args.count.zero?
|
19
|
+
@config
|
20
|
+
rescue OptionParser::InvalidOption => err
|
21
|
+
raise(Gistory::ParserError, err.message)
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@parser.to_s
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def parse_gem_name
|
31
|
+
gem_name = @args.shift
|
32
|
+
raise(Gistory::ParserError, 'No gem specified') unless gem_name
|
33
|
+
@config.gem_name = gem_name
|
34
|
+
end
|
35
|
+
|
36
|
+
def create_parser(config)
|
37
|
+
parser = OptionParser.new
|
38
|
+
parser.banner = 'Usage: gistory <gem_name> [options]'
|
39
|
+
|
40
|
+
add_specific_options(parser, config)
|
41
|
+
add_common_options(parser)
|
42
|
+
|
43
|
+
parser
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_specific_options(parser, config)
|
47
|
+
parser.separator ''
|
48
|
+
parser.separator 'Specific options:'
|
49
|
+
|
50
|
+
add_max_lockfile_changes(parser, config)
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_common_options(parser)
|
54
|
+
parser.separator ''
|
55
|
+
parser.separator 'Common options:'
|
56
|
+
|
57
|
+
add_help(parser)
|
58
|
+
add_version(parser)
|
59
|
+
end
|
60
|
+
|
61
|
+
def add_max_lockfile_changes(parser, config)
|
62
|
+
default = config.max_lockfile_changes
|
63
|
+
description = "max number of changes to the lock file (default #{default})"
|
64
|
+
parser.on('-m', '--max-lockfile-changes [INTEGER]', Integer, description) do |m|
|
65
|
+
raise(Gistory::ParserError, 'argument --max-lockfile-changes must be an integer') if m.nil?
|
66
|
+
config.max_lockfile_changes = m
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_help(parser)
|
71
|
+
parser.on_tail('-h', '--help', 'Show this message') do
|
72
|
+
@io.puts parser
|
73
|
+
exit
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def add_version(parser)
|
78
|
+
parser.on_tail('--version', 'Show version') do
|
79
|
+
@io.puts "gistory version #{Gistory::VERSION}"
|
80
|
+
exit
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
module Gistory
|
5
|
+
module Cli
|
6
|
+
class Io
|
7
|
+
def initialize(out: $stdout, err: $stderr)
|
8
|
+
@out = out
|
9
|
+
@err = err
|
10
|
+
end
|
11
|
+
|
12
|
+
def puts(msg)
|
13
|
+
@out.puts(msg)
|
14
|
+
end
|
15
|
+
|
16
|
+
def error(msg)
|
17
|
+
@err.puts(msg.red)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Gistory
|
3
|
+
module Cli
|
4
|
+
class Main
|
5
|
+
def initialize(repo_path:, args:, io: Gistory::Cli::Io.new)
|
6
|
+
@repo_path = repo_path
|
7
|
+
@args = args
|
8
|
+
@io = io
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
repo = GitRepo.new(path: @repo_path)
|
13
|
+
parser = Cli::ArgParser.new(args: @args, io: @io)
|
14
|
+
config = parser.parse
|
15
|
+
history(repo, config.gem_name)
|
16
|
+
rescue Gistory::ParserError => error
|
17
|
+
@io.error error.message
|
18
|
+
@io.puts parser
|
19
|
+
rescue Gistory::Error => error
|
20
|
+
@io.error error.message
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def history(repo, gem_name)
|
26
|
+
changes = ChangeLog.new(repo: repo).changelog_for_gem(gem_name)
|
27
|
+
|
28
|
+
if changes.empty?
|
29
|
+
raise(Gistory::Error, "Gem '#{gem_name}' not found in lock file, maybe a typo?")
|
30
|
+
end
|
31
|
+
|
32
|
+
@io.puts "Gem: #{gem_name}"
|
33
|
+
@io.puts "Current version: #{changes.first.version}"
|
34
|
+
@io.puts ''
|
35
|
+
|
36
|
+
@io.puts 'Change history:'
|
37
|
+
changes.each do |change|
|
38
|
+
@io.puts "#{change.version} on #{change.date.strftime('%a, %e %b %Y %H:%M %Z')} (commit #{change.short_hash})"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'english'
|
3
|
+
|
4
|
+
module Gistory
|
5
|
+
class GitRepo
|
6
|
+
def initialize(path:)
|
7
|
+
raise(Gistory::Error, 'This is not a valid git repository') unless Dir.exist?(File.join(path, '.git'))
|
8
|
+
raise(Gistory::Error, 'git is not available, please install it') unless git_cli_available?
|
9
|
+
end
|
10
|
+
|
11
|
+
def changes_to_file(filename)
|
12
|
+
max_count = Gistory.config.max_lockfile_changes
|
13
|
+
hashes_and_dates = git("log --pretty=format:'%h|%cD' --max-count=#{max_count} --follow #{filename}")
|
14
|
+
to_commits(hashes_and_dates.split("\n"))
|
15
|
+
end
|
16
|
+
|
17
|
+
def file_content_at_commit(commit_hash, filename)
|
18
|
+
git("show #{commit_hash}:#{filename}")
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def git_cli_available?
|
24
|
+
system('which git > /dev/null 2>&1')
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_commits(hashes_and_dates)
|
28
|
+
hashes_and_dates.map do |hash_and_date|
|
29
|
+
commit_hash, date = hash_and_date.split('|')
|
30
|
+
Commit.new(short_hash: commit_hash, date: date)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def git(command)
|
35
|
+
out = `git #{command}`
|
36
|
+
raise('Git CLI command failed') unless $CHILD_STATUS.success?
|
37
|
+
out
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'forwardable'
|
3
|
+
|
4
|
+
module Gistory
|
5
|
+
class VersionChange
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@commit, :short_hash, :date
|
8
|
+
|
9
|
+
attr_reader :commit, :version
|
10
|
+
|
11
|
+
def initialize(commit:, version:)
|
12
|
+
@commit = commit
|
13
|
+
@version = version
|
14
|
+
freeze
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gistory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergio Medina
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-02-09 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.14'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: colorize
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: minitest
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '5.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '5.0'
|
69
|
+
description: 'Gistory: Know exactly when a gem was updated in your Gemfile.lock'
|
70
|
+
email:
|
71
|
+
- medinasergio@gmail.com
|
72
|
+
executables:
|
73
|
+
- gistory
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rubocop.yml"
|
79
|
+
- ".travis.yml"
|
80
|
+
- Gemfile
|
81
|
+
- README.md
|
82
|
+
- Rakefile
|
83
|
+
- bin/console
|
84
|
+
- bin/setup
|
85
|
+
- exe/gistory
|
86
|
+
- gistory.gemspec
|
87
|
+
- lib/gistory.rb
|
88
|
+
- lib/gistory/change_log.rb
|
89
|
+
- lib/gistory/cli/arg_parser.rb
|
90
|
+
- lib/gistory/cli/io.rb
|
91
|
+
- lib/gistory/cli/main.rb
|
92
|
+
- lib/gistory/commit.rb
|
93
|
+
- lib/gistory/configuration.rb
|
94
|
+
- lib/gistory/errors.rb
|
95
|
+
- lib/gistory/git_repo.rb
|
96
|
+
- lib/gistory/version.rb
|
97
|
+
- lib/gistory/version_change.rb
|
98
|
+
homepage: https://www.github.com/serch/gistory
|
99
|
+
licenses: []
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.6.8
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: 'Gistory: Know exactly when a gem was updated in your Gemfile.lock'
|
121
|
+
test_files: []
|