safedep 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f1cb012ac2d4a305d3336571face073efbb280cb
4
+ data.tar.gz: 0869786aa9865ba2b5c0e0244bb1b1c5c9dcf4f9
5
+ SHA512:
6
+ metadata.gz: b0758ba09057c0dbdd8f1bb469f4acb38b92b6dcab88d22b9be1b51557c54126df2a3f1ef5ebd3ad93cb2a0fb5151e5334795fb964c351aaef0dbe6f5d22d0d3
7
+ data.tar.gz: 0f6f50bfd5adc9aed4ed7cf266131b1b7d53323e6e02d79376ce711f08f16e41ed4b22111677634842b226e4c6ba85db2ae4e4b3af02da0512abfaa5c0f0ec2b
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,55 @@
1
+
2
+ AllCops:
3
+ Include:
4
+ - '*.gemspec'
5
+ - 'Rakefile'
6
+ - 'Gemfile'
7
+ - 'Guardfile'
8
+ Exclude:
9
+ - 'vendor/**/*'
10
+
11
+ LineLength:
12
+ Max: 100
13
+
14
+ MethodLength:
15
+ Max: 15
16
+
17
+ RegexpLiteral:
18
+ Exclude:
19
+ - '*.gemspec'
20
+ - 'Guardfile'
21
+
22
+ EmptyElse:
23
+ Enabled: false
24
+
25
+ AlignHash:
26
+ # Alignment of entries using hash rocket as separator. Valid values are:
27
+ #
28
+ # key - left alignment of keys
29
+ # 'a' => 2
30
+ # 'bb' => 3
31
+ # separator - alignment of hash rockets, keys are right aligned
32
+ # 'a' => 2
33
+ # 'bb' => 3
34
+ # table - left alignment of keys, hash rockets, and values
35
+ # 'a' => 2
36
+ # 'bb' => 3
37
+ EnforcedHashRocketStyle: table
38
+ # Alignment of entries using colon as separator. Valid values are:
39
+ #
40
+ # key - left alignment of keys
41
+ # a: 0
42
+ # bb: 1
43
+ # separator - alignment of colons, keys are right aligned
44
+ # a: 0
45
+ # bb: 1
46
+ # table - left alignment of keys and values
47
+ # a: 0
48
+ # bb: 1
49
+ EnforcedColonStyle: separator
50
+
51
+ GuardClause:
52
+ Enabled: false
53
+
54
+ Documentation:
55
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1
6
+ - 2.2
7
+ - ruby-head
8
+ - jruby-19mode
9
+ script: bundle exec rake ci
10
+ sudo: false
11
+ cache: bundler
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ ## Development
4
+
5
+ ## v0.0.1
6
+
7
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in safedep.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem 'rake', '~> 10.4'
8
+ gem 'rspec', '~> 3.1'
9
+ gem 'rubocop', '~> 0.28'
10
+ gem 'powerpack', '~> 0.0'
11
+ gem 'simplecov', '~> 0.9'
12
+ end
13
+
14
+ group :test do
15
+ gem 'coveralls', '~> 0.7'
16
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Yuji Nakayama
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,86 @@
1
+ [![Gem Version](http://img.shields.io/gem/v/safedep.svg?style=flat)](http://badge.fury.io/rb/safedep)
2
+ [![Dependency Status](http://img.shields.io/gemnasium/yujinakayama/safedep.svg?style=flat)](https://gemnasium.com/yujinakayama/safedep)
3
+ [![Build Status](https://travis-ci.org/yujinakayama/safedep.svg?branch=master&style=flat)](https://travis-ci.org/yujinakayama/safedep)
4
+ [![Coverage Status](http://img.shields.io/coveralls/yujinakayama/safedep/master.svg?style=flat)](https://coveralls.io/r/yujinakayama/safedep)
5
+ [![Code Climate](https://img.shields.io/codeclimate/github/yujinakayama/safedep.svg?style=flat)](https://codeclimate.com/github/yujinakayama/safedep)
6
+
7
+ # Safedep
8
+
9
+ **safedep** automatically writes missing version specifiers for dependencies in your `Gemfile`.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ $ gem install safedep
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ Just run `safedep` command in your project's root directory,
20
+ and then you should see the `Gemfile` is modified.
21
+
22
+ ```bash
23
+ $ cd your-project
24
+ $ safedep
25
+ ```
26
+
27
+ ## Example
28
+
29
+ Here's a `Gemfile` with dependencies without version specifier:
30
+
31
+ ```bash
32
+ $ cat Gemfile
33
+ source 'https://rubygems.org'
34
+
35
+ group :development, :test do
36
+ gem 'rake'
37
+ gem 'rspec'
38
+ gem 'rubocop'
39
+ end
40
+ ```
41
+
42
+ And they have already been installed via `bundle install`:
43
+
44
+ ```bash
45
+ $ egrep '(rake|rspec|rubocop) ' Gemfile.lock
46
+ rake (10.4.2)
47
+ rspec (3.1.0)
48
+ rubocop (0.28.0)
49
+ ```
50
+
51
+ Then run `safedep`:
52
+
53
+ ```bash
54
+ $ safedep
55
+ ```
56
+
57
+ Now the `Gemfile` should have safe version specifiers in the SemVer way:
58
+
59
+ ```bash
60
+ $ git diff
61
+ diff --git a/Gemfile b/Gemfile
62
+ index 5ff2c3c..488dd41 100644
63
+ --- a/Gemfile
64
+ +++ b/Gemfile
65
+ @@ -1,7 +1,7 @@
66
+ source 'https://rubygems.org'
67
+
68
+ group :development, :test do
69
+ - gem 'rake'
70
+ - gem 'rspec'
71
+ - gem 'rubocop'
72
+ + gem 'rake', '~> 10.4'
73
+ + gem 'rspec', '~> 3.1'
74
+ + gem 'rubocop', '~> 0.28'
75
+ end
76
+ ```
77
+
78
+ ## Compatibility
79
+
80
+ Tested on MRI 1.9.3, 2.0, 2.1, 2.2 and JRuby in 1.9 mode.
81
+
82
+ ## License
83
+
84
+ Copyright (c) 2015 Yuji Nakayama
85
+
86
+ See the [LICENSE.txt](LICENSE.txt) for details.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'rspec/core/rake_task'
4
+ require 'rubocop/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec) do |task|
7
+ task.verbose = false
8
+ end
9
+
10
+ RuboCop::RakeTask.new(:style)
11
+
12
+ task ci: [:spec, :style]
data/bin/safedep ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
+ require 'safedep/runner'
5
+
6
+ Safedep::Runner.run
@@ -0,0 +1,60 @@
1
+ module Safedep
2
+ class AbstractDependency
3
+ attr_reader :node, :rewriter
4
+
5
+ def self.valid_node?(node)
6
+ return false unless node.send_type?
7
+ _receiver_node, message, name_node, = *node
8
+ method_names.include?(message) && name_node.str_type?
9
+ end
10
+
11
+ def self.method_names
12
+ fail NotImplemenetedError
13
+ end
14
+
15
+ def initialize(node, rewriter)
16
+ fail 'Invalid node.' unless self.class.valid_node?(node)
17
+ @node = node
18
+ @rewriter = rewriter
19
+ end
20
+
21
+ def name
22
+ name_node.children.first
23
+ end
24
+
25
+ def version_specifier
26
+ return nil unless version_specifier_node
27
+ version_specifier_node.children.first
28
+ end
29
+
30
+ def version_specifier=(version_specifier)
31
+ if version_specifier_node
32
+ rewriter.replace(content_range_of_str_node(version_specifier_node), version_specifier)
33
+ else
34
+ rewriter.insert_after(name_node.loc.expression, ", '#{version_specifier}'")
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def name_node
41
+ node.children[2]
42
+ end
43
+
44
+ def version_specifier_node
45
+ return @version_specifier_node if instance_variable_defined?(:@version_specifier_node)
46
+ version_node = node.children[3]
47
+ return @version_specifier_node = nil if version_node.nil? || !version_node.str_type?
48
+ @version_specifier_node = version_node
49
+ end
50
+
51
+ def content_range_of_str_node(str_node)
52
+ map = str_node.loc
53
+ Parser::Source::Range.new(
54
+ map.expression.source_buffer,
55
+ map.begin.end_pos,
56
+ map.end.begin_pos
57
+ )
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,50 @@
1
+ require 'astrolabe/builder'
2
+ require 'parser/current'
3
+
4
+ module Safedep
5
+ class AbstractGemfile
6
+ attr_reader :path
7
+
8
+ def initialize(path)
9
+ @path = path
10
+ end
11
+
12
+ def find_dependency(name)
13
+ dependencies.find { |dep| dep.name == name }
14
+ end
15
+
16
+ def dependencies
17
+ @dependencies ||= ast.each_node.with_object([]) do |node, dependencies|
18
+ next unless dependency_class.valid_node?(node)
19
+ dependencies << dependency_class.new(node, source_rewriter)
20
+ end
21
+ end
22
+
23
+ def rewrite!
24
+ rewritten_source = source_rewriter.process
25
+ File.write(path, rewritten_source)
26
+ end
27
+
28
+ private
29
+
30
+ def dependency_class
31
+ fail NotImplementedError
32
+ end
33
+
34
+ def ast
35
+ @ast ||= begin
36
+ builder = Astrolabe::Builder.new
37
+ parser = Parser::CurrentRuby.new(builder)
38
+ parser.parse(source_buffer)
39
+ end
40
+ end
41
+
42
+ def source_rewriter
43
+ @source_rewriter ||= Parser::Source::Rewriter.new(source_buffer)
44
+ end
45
+
46
+ def source_buffer
47
+ @source_buffer ||= Parser::Source::Buffer.new(path).read
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,13 @@
1
+ require 'safedep/abstract_dependency'
2
+
3
+ module Safedep
4
+ class Gemfile
5
+ class Dependency < AbstractDependency
6
+ METHOD_NAMES = [:gem].freeze
7
+
8
+ def self.method_names
9
+ METHOD_NAMES
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'safedep/abstract_gemfile'
2
+
3
+ module Safedep
4
+ class Gemfile < AbstractGemfile
5
+ require 'safedep/gemfile/dependency'
6
+
7
+ private
8
+
9
+ def dependency_class
10
+ Gemfile::Dependency
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,28 @@
1
+ require 'bundler'
2
+
3
+ module Safedep
4
+ class GemfileLock
5
+ attr_reader :path
6
+
7
+ def initialize(path)
8
+ @path = path
9
+ end
10
+
11
+ def find_dependency(name)
12
+ dependencies.find { |dep| dep.name == name }
13
+ end
14
+
15
+ def dependencies
16
+ lockfile.specs
17
+ end
18
+
19
+ private
20
+
21
+ def lockfile
22
+ @lockfile ||= begin
23
+ content = File.read(path)
24
+ Bundler::LockfileParser.new(content)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ require 'safedep/abstract_dependency'
2
+
3
+ module Safedep
4
+ class Gemspec
5
+ class Dependency < AbstractDependency
6
+ METHOD_NAMES = [:add_runtime_dependency, :add_development_dependency, :add_dependency].freeze
7
+
8
+ def self.method_names
9
+ METHOD_NAMES
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require 'safedep/abstract_gemfile'
2
+
3
+ module Safedep
4
+ class Gemspec < AbstractGemfile
5
+ require 'safedep/gemspec/dependency'
6
+
7
+ private
8
+
9
+ def dependency_class
10
+ Gemspec::Dependency
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,46 @@
1
+ require 'safedep/gemspec'
2
+ require 'safedep/gemfile'
3
+ require 'safedep/gemfile_lock'
4
+
5
+ module Safedep
6
+ class Runner
7
+ def self.run
8
+ new.run
9
+ end
10
+
11
+ def run
12
+ dependencies = gemfiles.map(&:dependencies).reduce(:+)
13
+
14
+ dependencies.each do |dep|
15
+ next if dep.version_specifier
16
+ lockfile_dep = gemfile_lock.find_dependency(dep.name)
17
+ dep.version_specifier = safe_version_specifier(lockfile_dep.version)
18
+ end
19
+
20
+ gemfiles.each(&:rewrite!)
21
+ end
22
+
23
+ def gemfiles
24
+ @gemfiles ||= [gemspec, gemfile].compact
25
+ end
26
+
27
+ def gemspec
28
+ @gemspec ||= begin
29
+ path = Dir['*.gemspec'].first
30
+ Gemspec.new(path) if path
31
+ end
32
+ end
33
+
34
+ def gemfile
35
+ @gemfile ||= Gemfile.new('Gemfile')
36
+ end
37
+
38
+ def gemfile_lock
39
+ @gemfile_lock ||= GemfileLock.new('Gemfile.lock')
40
+ end
41
+
42
+ def safe_version_specifier(version)
43
+ '~> ' << version.to_s.split('.').first(2).join('.')
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ module Safedep
2
+ # http://semver.org/
3
+ module Version
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ PATCH = 1
7
+
8
+ def self.to_s
9
+ [MAJOR, MINOR, PATCH].join('.')
10
+ end
11
+ end
12
+ end
data/lib/safedep.rb ADDED
@@ -0,0 +1,5 @@
1
+ require 'safedep/version'
2
+
3
+ module Safedep
4
+ # Your code goes here...
5
+ end
data/safedep.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'safedep/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'safedep'
8
+ spec.version = Safedep::Version.to_s
9
+ spec.authors = ['Yuji Nakayama']
10
+ spec.email = ['nkymyj@gmail.com']
11
+ spec.summary = 'Make your Gemfile safe by adding dependency version specifiers ' \
12
+ 'automatically.'
13
+ spec.description = spec.summary
14
+ spec.homepage = 'https://github.com/yujinakayama/safedep'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_runtime_dependency 'parser', '~> 2.2'
23
+ spec.add_runtime_dependency 'astrolabe', '~> 1.3'
24
+ spec.add_runtime_dependency 'bundler', '~> 1.7'
25
+ end
@@ -0,0 +1,133 @@
1
+ require 'safedep/gemfile'
2
+
3
+ module Safedep
4
+ class Gemfile
5
+ describe Dependency do
6
+ include FileHelper
7
+ include_context 'isolated environment'
8
+
9
+ let(:gemfile) do
10
+ create_file(path, source)
11
+ Gemfile.new(path)
12
+ end
13
+
14
+ let(:path) { 'Gemfile' }
15
+
16
+ let(:source) { <<-END.strip_indent }
17
+ source 'https://rubygems.org'
18
+
19
+ gemspec
20
+
21
+ group :development, :test do
22
+ gem 'rake'
23
+ gem 'rspec', '~> 3.1'
24
+ gem 'rubocop', require: false
25
+ end
26
+ END
27
+
28
+ describe '#name' do
29
+ let(:dependency) { gemfile.dependencies.first }
30
+
31
+ it 'returns the name of the gem' do
32
+ expect(dependency.name).to eq('rake')
33
+ end
34
+ end
35
+
36
+ describe '#version_specifier' do
37
+ subject(:version_specifier) { dependency.version_specifier }
38
+
39
+ context 'when the dependency has version specifier' do
40
+ let(:dependency) { gemfile.find_dependency('rspec') }
41
+
42
+ it 'returns the specifier' do
43
+ expect(version_specifier).to eq('~> 3.1')
44
+ end
45
+ end
46
+
47
+ context 'when the dependency has no version specifier' do
48
+ context 'and has no options' do
49
+ let(:dependency) { gemfile.find_dependency('rake') }
50
+ it { should be_nil }
51
+ end
52
+
53
+ context 'but has options' do
54
+ let(:dependency) { gemfile.find_dependency('rubocop') }
55
+ it { should be_nil }
56
+ end
57
+ end
58
+ end
59
+
60
+ describe '#version_specifier=' do
61
+ let(:rewritten_source) { File.read(gemfile.path) }
62
+
63
+ context 'when the dependency has version specifier' do
64
+ let(:dependency) { gemfile.find_dependency('rspec') }
65
+
66
+ let(:expected_source) { <<-END.strip_indent }
67
+ source 'https://rubygems.org'
68
+
69
+ gemspec
70
+
71
+ group :development, :test do
72
+ gem 'rake'
73
+ gem 'rspec', '> 4.0'
74
+ gem 'rubocop', require: false
75
+ end
76
+ END
77
+
78
+ it 'replaces the existing specifier with the passed specifier' do
79
+ dependency.version_specifier = '> 4.0'
80
+ gemfile.rewrite!
81
+ expect(rewritten_source).to eq(expected_source)
82
+ end
83
+ end
84
+
85
+ context 'when the dependency has no version specifier' do
86
+ context 'and has no options' do
87
+ let(:dependency) { gemfile.find_dependency('rake') }
88
+
89
+ let(:expected_source) { <<-END.strip_indent }
90
+ source 'https://rubygems.org'
91
+
92
+ gemspec
93
+
94
+ group :development, :test do
95
+ gem 'rake', '~> 10.1'
96
+ gem 'rspec', '~> 3.1'
97
+ gem 'rubocop', require: false
98
+ end
99
+ END
100
+
101
+ it 'adds the passed specifier' do
102
+ dependency.version_specifier = '~> 10.1'
103
+ gemfile.rewrite!
104
+ expect(rewritten_source).to eq(expected_source)
105
+ end
106
+ end
107
+
108
+ context 'but has options' do
109
+ let(:dependency) { gemfile.find_dependency('rubocop') }
110
+
111
+ let(:expected_source) { <<-END.strip_indent }
112
+ source 'https://rubygems.org'
113
+
114
+ gemspec
115
+
116
+ group :development, :test do
117
+ gem 'rake'
118
+ gem 'rspec', '~> 3.1'
119
+ gem 'rubocop', '~> 0.28', require: false
120
+ end
121
+ END
122
+
123
+ it 'adds the passed specifier' do
124
+ dependency.version_specifier = '~> 0.28'
125
+ gemfile.rewrite!
126
+ expect(rewritten_source).to eq(expected_source)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,81 @@
1
+ require 'safedep/gemfile_lock'
2
+
3
+ module Safedep
4
+ describe GemfileLock do
5
+ include FileHelper
6
+ include_context 'isolated environment'
7
+
8
+ let(:lockfile) do
9
+ create_file(path, source)
10
+ GemfileLock.new(path)
11
+ end
12
+
13
+ let(:path) { 'Gemfile.lock' }
14
+
15
+ let(:source) { <<-END.strip_indent }
16
+ PATH
17
+ remote: .
18
+ specs:
19
+ safedep (0.0.1)
20
+ astrolabe
21
+ bundler (~> 1.7)
22
+ parser
23
+
24
+ GEM
25
+ remote: https://rubygems.org/
26
+ specs:
27
+ ast (2.0.0)
28
+ astrolabe (1.3.0)
29
+ parser (>= 2.2.0.pre.3, < 3.0)
30
+ diff-lcs (1.2.5)
31
+ parser (2.2.0.2)
32
+ ast (>= 1.1, < 3.0)
33
+ powerpack (0.0.9)
34
+ rainbow (2.0.0)
35
+ rake (10.4.2)
36
+ rspec (3.1.0)
37
+ rspec-core (~> 3.1.0)
38
+ rspec-expectations (~> 3.1.0)
39
+ rspec-mocks (~> 3.1.0)
40
+ rspec-core (3.1.7)
41
+ rspec-support (~> 3.1.0)
42
+ rspec-expectations (3.1.2)
43
+ diff-lcs (>= 1.2.0, < 2.0)
44
+ rspec-support (~> 3.1.0)
45
+ rspec-mocks (3.1.3)
46
+ rspec-support (~> 3.1.0)
47
+ rspec-support (3.1.2)
48
+ rubocop (0.28.0)
49
+ astrolabe (~> 1.3)
50
+ parser (>= 2.2.0.pre.7, < 3.0)
51
+ powerpack (~> 0.0.6)
52
+ rainbow (>= 1.99.1, < 3.0)
53
+ ruby-progressbar (~> 1.4)
54
+ ruby-progressbar (1.7.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ rake (~> 10.4)
61
+ rspec (~> 3.1)
62
+ rubocop (~> 0.28)
63
+ safedep!
64
+ END
65
+
66
+ describe '#find_dependency' do
67
+ it 'returns the dependency matching the passed name' do
68
+ dependency = lockfile.find_dependency('rspec')
69
+ expect(dependency.name).to eq('rspec')
70
+ end
71
+ end
72
+
73
+ describe '#dependencies' do
74
+ let(:dep_names) { lockfile.dependencies.map(&:name) }
75
+
76
+ it 'returns an array of the specifications' do
77
+ expect(dep_names).to include('rake', 'rspec', 'rubocop')
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,41 @@
1
+ require 'safedep/gemfile'
2
+
3
+ module Safedep
4
+ describe Gemfile do
5
+ include FileHelper
6
+ include_context 'isolated environment'
7
+
8
+ subject(:gemfile) do
9
+ create_file(path, source)
10
+ Gemfile.new(path)
11
+ end
12
+
13
+ let(:path) { 'Gemfile' }
14
+
15
+ let(:source) { <<-END.strip_indent }
16
+ source 'https://rubygems.org'
17
+
18
+ gemspec
19
+
20
+ group :development, :test do
21
+ gem 'rake'
22
+ gem 'rspec', '~> 3.1'
23
+ gem 'rubocop', '~> 0.28'
24
+ end
25
+ END
26
+
27
+ describe '#find_dependency' do
28
+ it 'returns the dependency matching the passed name' do
29
+ dependency = gemfile.find_dependency('rspec')
30
+ expect(dependency.name).to eq('rspec')
31
+ end
32
+ end
33
+
34
+ describe '#dependencies' do
35
+ it 'returns an array of the dependencies' do
36
+ expect(gemfile.dependencies.size).to eq(3)
37
+ expect(gemfile.dependencies).to all be_a(Gemfile::Dependency)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,93 @@
1
+ require 'safedep/gemspec'
2
+
3
+ module Safedep
4
+ class Gemspec
5
+ describe Dependency do
6
+ include FileHelper
7
+ include_context 'isolated environment'
8
+
9
+ let(:gemspec) do
10
+ create_file(path, source)
11
+ Gemspec.new(path)
12
+ end
13
+
14
+ let(:path) { 'example.gemspec' }
15
+
16
+ let(:source) { <<-END.strip_indent }
17
+ Gem::Specification.new do |spec|
18
+ spec.name = 'safedep'
19
+ spec.add_dependency 'parser'
20
+ spec.add_runtime_dependency 'astrolabe', '~> 1.3'
21
+ spec.add_development_dependency 'rspec', '~> 3.1'
22
+ end
23
+ END
24
+
25
+ describe '#name' do
26
+ let(:dependency) { gemspec.dependencies.first }
27
+
28
+ it 'returns the name of the gem' do
29
+ expect(dependency.name).to eq('parser')
30
+ end
31
+ end
32
+
33
+ describe '#version_specifier' do
34
+ subject(:version_specifier) { dependency.version_specifier }
35
+
36
+ context 'when the dependency has version specifier' do
37
+ let(:dependency) { gemspec.find_dependency('rspec') }
38
+
39
+ it 'returns the specifier' do
40
+ expect(version_specifier).to eq('~> 3.1')
41
+ end
42
+ end
43
+
44
+ context 'when the dependency has no version specifier' do
45
+ let(:dependency) { gemspec.find_dependency('parser') }
46
+ it { should be_nil }
47
+ end
48
+ end
49
+
50
+ describe '#version_specifier=' do
51
+ let(:rewritten_source) { File.read(gemspec.path) }
52
+
53
+ context 'when the dependency has version specifier' do
54
+ let(:dependency) { gemspec.find_dependency('rspec') }
55
+
56
+ let(:expected_source) { <<-END.strip_indent }
57
+ Gem::Specification.new do |spec|
58
+ spec.name = 'safedep'
59
+ spec.add_dependency 'parser'
60
+ spec.add_runtime_dependency 'astrolabe', '~> 1.3'
61
+ spec.add_development_dependency 'rspec', '> 4.0'
62
+ end
63
+ END
64
+
65
+ it 'replaces the existing specifier with the passed specifier' do
66
+ dependency.version_specifier = '> 4.0'
67
+ gemspec.rewrite!
68
+ expect(rewritten_source).to eq(expected_source)
69
+ end
70
+ end
71
+
72
+ context 'when the dependency has no version specifier' do
73
+ let(:dependency) { gemspec.find_dependency('parser') }
74
+
75
+ let(:expected_source) { <<-END.strip_indent }
76
+ Gem::Specification.new do |spec|
77
+ spec.name = 'safedep'
78
+ spec.add_dependency 'parser', '~> 2.2'
79
+ spec.add_runtime_dependency 'astrolabe', '~> 1.3'
80
+ spec.add_development_dependency 'rspec', '~> 3.1'
81
+ end
82
+ END
83
+
84
+ it 'adds the passed specifier' do
85
+ dependency.version_specifier = '~> 2.2'
86
+ gemspec.rewrite!
87
+ expect(rewritten_source).to eq(expected_source)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,38 @@
1
+ require 'safedep/gemspec'
2
+
3
+ module Safedep
4
+ describe Gemspec do
5
+ include FileHelper
6
+ include_context 'isolated environment'
7
+
8
+ subject(:gemspec) do
9
+ create_file(path, source)
10
+ Gemspec.new(path)
11
+ end
12
+
13
+ let(:path) { 'example.gemspec' }
14
+
15
+ let(:source) { <<-END.strip_indent }
16
+ Gem::Specification.new do |spec|
17
+ spec.name = 'safedep'
18
+ spec.add_dependency 'parser'
19
+ spec.add_runtime_dependency 'astrolabe', '~> 1.3'
20
+ spec.add_development_dependency 'rspec', '~> 3.1'
21
+ end
22
+ END
23
+
24
+ describe '#find_dependency' do
25
+ it 'returns the dependency matching the passed name' do
26
+ dependency = gemspec.find_dependency('rspec')
27
+ expect(dependency.name).to eq('rspec')
28
+ end
29
+ end
30
+
31
+ describe '#dependencies' do
32
+ it 'returns an array of the dependencies' do
33
+ expect(gemspec.dependencies.size).to eq(3)
34
+ expect(gemspec.dependencies).to all be_a(Gemspec::Dependency)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,108 @@
1
+ require 'powerpack/string/strip_indent'
2
+
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
6
+ # file to always be loaded, without a need to explicitly require it in any files.
7
+ #
8
+ # Given that it is always loaded, you are encouraged to keep this file as
9
+ # light-weight as possible. Requiring heavyweight dependencies from this file
10
+ # will add to the boot time of your test suite on EVERY test run, even for an
11
+ # individual file that may not need all of that loaded. Instead, consider making
12
+ # a separate helper file that requires the additional dependencies and performs
13
+ # the additional setup, and require it from the spec files that actually need it.
14
+ #
15
+ # The `.rspec` file also contains a few flags that are not defaults but that
16
+ # users commonly want.
17
+ #
18
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
19
+ RSpec.configure do |config|
20
+ # rspec-expectations config goes here. You can use an alternate
21
+ # assertion/expectation library such as wrong or the stdlib/minitest
22
+ # assertions if you prefer.
23
+ config.expect_with :rspec do |expectations|
24
+ expectations.syntax = :expect
25
+ # This option will default to `true` in RSpec 4. It makes the `description`
26
+ # and `failure_message` of custom matchers include text for helper methods
27
+ # defined using `chain`, e.g.:
28
+ # be_bigger_than(2).and_smaller_than(4).description
29
+ # # => "be bigger than 2 and smaller than 4"
30
+ # ...rather than:
31
+ # # => "be bigger than 2"
32
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
33
+ end
34
+
35
+ # rspec-mocks config goes here. You can use an alternate test double
36
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
37
+ config.mock_with :rspec do |mocks|
38
+ mocks.syntax = :expect
39
+
40
+ # Prevents you from mocking or stubbing a method that does not exist on
41
+ # a real object. This is generally recommended, and will default to
42
+ # `true` in RSpec 4.
43
+ mocks.verify_partial_doubles = true
44
+ end
45
+
46
+ # These two settings work together to allow you to limit a spec run
47
+ # to individual examples or groups you care about by tagging them with
48
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
49
+ # get run.
50
+ config.filter_run :focus
51
+ config.run_all_when_everything_filtered = true
52
+
53
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
54
+ # For more details, see:
55
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
56
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
57
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
58
+ # config.disable_monkey_patching!
59
+
60
+ # This setting enables warnings. It's recommended, but in some cases may
61
+ # be too noisy due to issues in dependencies.
62
+ # config.warnings = true
63
+
64
+ # Many RSpec users commonly either run the entire suite or an individual
65
+ # file, and it's useful to allow more verbose output when running an
66
+ # individual spec file.
67
+ if config.files_to_run.one?
68
+ # Use the documentation formatter for detailed output,
69
+ # unless a formatter has already been configured
70
+ # (e.g. via a command-line flag).
71
+ config.default_formatter = 'doc'
72
+ end
73
+
74
+ # Print the 10 slowest examples and example groups at the
75
+ # end of the spec run, to help surface which specs are running
76
+ # particularly slow.
77
+ # config.profile_examples = 10
78
+
79
+ # Run specs in random order to surface order dependencies. If you find an
80
+ # order dependency and want to debug it, you can fix the order by providing
81
+ # the seed, which is printed after each run.
82
+ # --seed 1234
83
+ config.order = :random
84
+
85
+ # Seed global randomization in this process using the `--seed` CLI option.
86
+ # Setting this allows you to use `--seed` to deterministically reproduce
87
+ # test failures related to randomization by passing the same `--seed` value
88
+ # as the one that triggered the failure.
89
+ Kernel.srand config.seed
90
+ end
91
+
92
+ Dir[File.join(File.dirname(__FILE__), 'support', '*')].each do |path|
93
+ require path
94
+ end
95
+
96
+ if ENV['TRAVIS'] || ENV['COVERAGE']
97
+ require 'simplecov'
98
+
99
+ if ENV['TRAVIS']
100
+ require 'coveralls'
101
+ SimpleCov.formatter = Coveralls::SimpleCov::Formatter
102
+ end
103
+
104
+ SimpleCov.start do
105
+ add_filter '/spec/'
106
+ add_filter '/vendor/'
107
+ end
108
+ end
@@ -0,0 +1,22 @@
1
+ module FileHelper
2
+ module_function
3
+
4
+ def create_file(file_path, content)
5
+ require 'fileutils'
6
+
7
+ file_path = File.expand_path(file_path)
8
+ dir_path = File.dirname(file_path)
9
+ FileUtils.makedirs(dir_path) unless File.exist?(dir_path)
10
+
11
+ File.open(file_path, 'w') do |file|
12
+ case content
13
+ when String
14
+ file.puts content
15
+ when Array
16
+ file.puts content.join("\n")
17
+ else
18
+ fail 'Unsupported type!'
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+
2
+ shared_context 'isolated environment' do
3
+ around do |example|
4
+ require 'tmpdir'
5
+ Dir.mktmpdir do |tmpdir|
6
+ Dir.chdir(tmpdir) do
7
+ example.run
8
+ end
9
+ end
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: safedep
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yuji Nakayama
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: astrolabe
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ description: Make your Gemfile safe by adding dependency version specifiers automatically.
56
+ email:
57
+ - nkymyj@gmail.com
58
+ executables:
59
+ - safedep
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".rubocop.yml"
66
+ - ".travis.yml"
67
+ - CHANGELOG.md
68
+ - Gemfile
69
+ - LICENSE.txt
70
+ - README.md
71
+ - Rakefile
72
+ - bin/safedep
73
+ - lib/safedep.rb
74
+ - lib/safedep/abstract_dependency.rb
75
+ - lib/safedep/abstract_gemfile.rb
76
+ - lib/safedep/gemfile.rb
77
+ - lib/safedep/gemfile/dependency.rb
78
+ - lib/safedep/gemfile_lock.rb
79
+ - lib/safedep/gemspec.rb
80
+ - lib/safedep/gemspec/dependency.rb
81
+ - lib/safedep/runner.rb
82
+ - lib/safedep/version.rb
83
+ - safedep.gemspec
84
+ - spec/safedep/gemfile/dependency_spec.rb
85
+ - spec/safedep/gemfile_lock_spec.rb
86
+ - spec/safedep/gemfile_spec.rb
87
+ - spec/safedep/gemspec/dependency_spec.rb
88
+ - spec/safedep/gemspec_spec.rb
89
+ - spec/spec_helper.rb
90
+ - spec/support/file_helper.rb
91
+ - spec/support/shared_contexts.rb
92
+ homepage: https://github.com/yujinakayama/safedep
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.4.5
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Make your Gemfile safe by adding dependency version specifiers automatically.
116
+ test_files:
117
+ - spec/safedep/gemfile/dependency_spec.rb
118
+ - spec/safedep/gemfile_lock_spec.rb
119
+ - spec/safedep/gemfile_spec.rb
120
+ - spec/safedep/gemspec/dependency_spec.rb
121
+ - spec/safedep/gemspec_spec.rb
122
+ - spec/spec_helper.rb
123
+ - spec/support/file_helper.rb
124
+ - spec/support/shared_contexts.rb