safedep 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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