safedep 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f81a9a095d287d0acfa6085600c2c91b1fd51886
4
- data.tar.gz: 695497fc629e33cf1815523fbdf9efb63590fd04
3
+ metadata.gz: 96720d6f9fd7630c262b4c014d255ffef22a4d5e
4
+ data.tar.gz: 2f070274f4cf9a60d69ae3096b895a3ec810ef6d
5
5
  SHA512:
6
- metadata.gz: a3800b441e6346922281067c09726085e522dbf472227c18cb8ed7679754fa9535b2f85be8b189fc830964bb89f2565db680deea9f735d1839487f6b31c40daf
7
- data.tar.gz: 6301c82baa0a18e2f30e7e9283fb87fbd3056f6698358094a6d96bc736328c60d0c79720ffae31bb68fe848205deb53aa7fecb2f91199c53e4995e8b3e1a0c30
6
+ metadata.gz: 8132af95ac774d2e2236620ed445b2e8a0e864d00b5ce74a9023ca10da5003d54c8668562e4cb9c71b495e15c604020d2d15066df1437fe6d7f83b4561dadcf6
7
+ data.tar.gz: e4ccdaad7dec69b7067e26059fdb6d76be72b6442d897150a9c97cd77ffcd9559891c52c0e93b2e92411676192684f0f96f7e848e274f29c588867d5327ec2c6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Development
4
4
 
5
+ ## v0.1.0
6
+
7
+ * Add `--without` option for skipping arbitrary groups.
8
+ * Abort processing if `Gemfile` or `Gemfile.lock` does not exist.
9
+
5
10
  ## v0.0.2
6
11
 
7
12
  * Fix an error when a `Gemfile` includes `bundler` dependency without version specifier.
data/Gemfile CHANGED
@@ -1,6 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in safedep.gemspec
4
3
  gemspec
5
4
 
6
5
  group :development, :test do
@@ -11,6 +10,12 @@ group :development, :test do
11
10
  gem 'simplecov', '~> 0.9'
12
11
  end
13
12
 
13
+ group :development do
14
+ gem 'guard-rspec', '~> 4.5'
15
+ gem 'guard-rubocop', '~> 1.2'
16
+ gem 'fuubar', '~> 2.0'
17
+ end
18
+
14
19
  group :test do
15
20
  gem 'coveralls', '~> 0.7'
16
21
  end
data/Guardfile ADDED
@@ -0,0 +1,16 @@
1
+
2
+ # This group allows to skip running RuboCop if RSpec failed,
3
+ # like Red > Green (RSpec) > Refactor (RuboCop).
4
+ group :red_green_refactor, halt_on_fail: true do
5
+ guard :rspec, cmd: 'bundle exec rspec --format Fuubar' do
6
+ watch(%r{^spec/.+_spec\.rb$})
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
8
+ watch('spec/spec_helper.rb') { 'spec' }
9
+ watch(%r{^spec/support/.+\.rb$}) { 'spec' }
10
+ end
11
+
12
+ guard :rubocop, all_on_start: false, cli: '--format fuubar' do
13
+ watch(%r{.+\.rb$})
14
+ watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
15
+ end
16
+ end
data/bin/safedep CHANGED
@@ -3,4 +3,5 @@
3
3
  $LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
4
4
  require 'safedep/cli'
5
5
 
6
- Safedep::CLI.run
6
+ result = Safedep::CLI.run
7
+ exit(result ? 0 : 1)
@@ -9,7 +9,7 @@ module Safedep
9
9
  end
10
10
 
11
11
  def self.method_names
12
- fail NotImplemenetedError
12
+ fail NotImplementedError
13
13
  end
14
14
 
15
15
  def initialize(node, rewriter)
@@ -22,6 +22,10 @@ module Safedep
22
22
  name_node.children.first
23
23
  end
24
24
 
25
+ def groups
26
+ fail NotImplementedError
27
+ end
28
+
25
29
  def version_specifier
26
30
  return nil unless version_specifier_node
27
31
  version_specifier_node.children.first
@@ -37,6 +41,10 @@ module Safedep
37
41
 
38
42
  private
39
43
 
44
+ def method_name
45
+ node.children[1]
46
+ end
47
+
40
48
  def name_node
41
49
  node.children[2]
42
50
  end
@@ -48,6 +56,10 @@ module Safedep
48
56
  @version_specifier_node = version_node
49
57
  end
50
58
 
59
+ def options_node
60
+ node.children[3..-1].find(&:hash_type?)
61
+ end
62
+
51
63
  def content_range_of_str_node(str_node)
52
64
  map = str_node.loc
53
65
  Parser::Source::Range.new(
data/lib/safedep/cli.rb CHANGED
@@ -8,9 +8,21 @@ module Safedep
8
8
  end
9
9
 
10
10
  def run(args)
11
- OptionParser.new.parse(args)
12
- Runner.run
11
+ option_parser.parse(args)
12
+
13
+ runner = Runner.new(option_parser.configuration)
14
+ runner.run
15
+
13
16
  puts 'Done.'
17
+
18
+ true
19
+ rescue Safedep::Error => error
20
+ warn error.message
21
+ false
22
+ end
23
+
24
+ def option_parser
25
+ @option_parser ||= OptionParser.new
14
26
  end
15
27
  end
16
28
  end
@@ -1,13 +1,13 @@
1
1
  require 'optparse'
2
+ require 'safedep/configuration'
2
3
  require 'safedep/version'
3
4
 
4
5
  module Safedep
5
6
  class OptionParser
6
- def self.parse(args)
7
- new.parse(args)
8
- end
7
+ attr_reader :configuration
9
8
 
10
- def initialize
9
+ def initialize(configuration = Configuration.new)
10
+ @configuration = configuration
11
11
  setup
12
12
  end
13
13
 
@@ -20,6 +20,10 @@ module Safedep
20
20
  private
21
21
 
22
22
  def setup
23
+ define_option('--without GROUP[,GROUP...]') do |arg|
24
+ configuration.skipped_groups = arg.split(',')
25
+ end
26
+
23
27
  define_option('--version') do
24
28
  puts Version.to_s
25
29
  exit
@@ -27,7 +31,7 @@ module Safedep
27
31
  end
28
32
 
29
33
  def define_option(*options, &block)
30
- long_option = options.find { |option| option.start_with?('--') }
34
+ long_option = options.find { |option| option.start_with?('--') }.split(' ').first
31
35
  description_lines = descriptions[long_option]
32
36
  parser.on(*options, *description_lines, &block)
33
37
  end
@@ -35,7 +39,7 @@ module Safedep
35
39
  def parser
36
40
  @parser ||= begin
37
41
  banner = "Usage: #{command_name} [options]\n\n"
38
- summary_width = 32 # Default
42
+ summary_width = 20 # Default
39
43
  indentation = ' ' * 2
40
44
  ::OptionParser.new(banner, summary_width, indentation)
41
45
  end
@@ -47,6 +51,9 @@ module Safedep
47
51
 
48
52
  def descriptions
49
53
  @descriptions ||= {
54
+ '--without' => [
55
+ 'Specify groups to skip modification as comma-separated list.'
56
+ ],
50
57
  '--version' => [
51
58
  "Show #{command_name} version."
52
59
  ]
@@ -0,0 +1,11 @@
1
+ module Safedep
2
+ class Configuration
3
+ def skipped_groups
4
+ @skipped_groups ||= []
5
+ end
6
+
7
+ def skipped_groups=(groups)
8
+ @skipped_groups = groups.map(&:to_sym)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module Safedep
2
+ class Error < StandardError; end
3
+ end
@@ -1,13 +1,58 @@
1
1
  require 'safedep/abstract_dependency'
2
+ require 'astrolabe/sexp'
2
3
 
3
4
  module Safedep
4
5
  class Gemfile
5
6
  class Dependency < AbstractDependency
7
+ include Astrolabe::Sexp
8
+
6
9
  METHOD_NAMES = [:gem].freeze
7
10
 
8
11
  def self.method_names
9
12
  METHOD_NAMES
10
13
  end
14
+
15
+ def groups
16
+ @groups ||= (groups_via_block + groups_via_option).map(&:to_sym)
17
+ end
18
+
19
+ def groups_via_block
20
+ return [] unless group_node
21
+ _receiver_node, _message, *arg_nodes = *group_node
22
+ literal_nodes = arg_nodes.select { |arg_node| arg_node.sym_type? || arg_node.str_type? }
23
+ literal_nodes.map { |literal_node| literal_node.children.first }
24
+ end
25
+
26
+ def groups_via_option
27
+ return [] unless options_node
28
+
29
+ options_node.each_child_node do |pair_node|
30
+ key_node, value_node = *pair_node
31
+
32
+ next unless key_node == s(:sym, :group)
33
+
34
+ case value_node.type
35
+ when :sym
36
+ return [value_node.children.first]
37
+ when :array
38
+ literal_nodes = value_node.each_child_node(:sym, :str)
39
+ return literal_nodes.map { |literal_node| literal_node.children.first }
40
+ else
41
+ return []
42
+ end
43
+ end
44
+
45
+ []
46
+ end
47
+
48
+ def group_node
49
+ candidates = node.each_ancestor(:block).map { |block_node| block_node.children.first }
50
+
51
+ candidates.find do |send_node|
52
+ receiver_node, message, = *send_node
53
+ receiver_node.nil? && message == :group
54
+ end
55
+ end
11
56
  end
12
57
  end
13
58
  end
@@ -8,6 +8,15 @@ module Safedep
8
8
  def self.method_names
9
9
  METHOD_NAMES
10
10
  end
11
+
12
+ def groups
13
+ case method_name
14
+ when :add_development_dependency
15
+ [:development]
16
+ else
17
+ []
18
+ end
19
+ end
11
20
  end
12
21
  end
13
22
  end
@@ -1,18 +1,25 @@
1
+ require 'safedep/configuration'
1
2
  require 'safedep/gemspec'
2
3
  require 'safedep/gemfile'
3
4
  require 'safedep/gemfile_lock'
5
+ require 'safedep/error'
4
6
 
5
7
  module Safedep
6
8
  class Runner
7
- def self.run
8
- new.run
9
+ GEMFILE_PATH = 'Gemfile'.freeze
10
+ GEMFILE_LOCK_PATH = 'Gemfile.lock'.freeze
11
+
12
+ attr_reader :configuration
13
+
14
+ def initialize(configuration = Configuration.new)
15
+ @configuration = configuration
9
16
  end
10
17
 
11
18
  def run
12
- dependencies = gemfiles.map(&:dependencies).reduce(:+)
19
+ validate!
13
20
 
14
21
  dependencies.each do |dep|
15
- next if dep.version_specifier
22
+ next if should_ignore?(dep)
16
23
  lockfile_dep = gemfile_lock.find_dependency(dep.name)
17
24
  dep.version_specifier = safe_version_specifier(lockfile_dep.version)
18
25
  end
@@ -20,6 +27,15 @@ module Safedep
20
27
  gemfiles.each(&:rewrite!)
21
28
  end
22
29
 
30
+ def validate!
31
+ gemfile_lock
32
+ gemfile
33
+ end
34
+
35
+ def dependencies
36
+ @dependencies ||= gemfiles.map(&:dependencies).reduce(:+)
37
+ end
38
+
23
39
  def gemfiles
24
40
  @gemfiles ||= [gemspec, gemfile].compact
25
41
  end
@@ -32,11 +48,25 @@ module Safedep
32
48
  end
33
49
 
34
50
  def gemfile
35
- @gemfile ||= Gemfile.new('Gemfile')
51
+ @gemfile ||= begin
52
+ fail Error, "#{GEMFILE_PATH} is not found." unless File.exist?(GEMFILE_PATH)
53
+ Gemfile.new(GEMFILE_PATH)
54
+ end
36
55
  end
37
56
 
38
57
  def gemfile_lock
39
- @gemfile_lock ||= GemfileLock.new('Gemfile.lock')
58
+ @gemfile_lock ||= begin
59
+ unless File.exist?(GEMFILE_LOCK_PATH)
60
+ fail Error, "#{GEMFILE_LOCK_PATH} is not found. Please run `bundle install`."
61
+ end
62
+
63
+ GemfileLock.new(GEMFILE_LOCK_PATH)
64
+ end
65
+ end
66
+
67
+ def should_ignore?(dependency)
68
+ return true if dependency.version_specifier
69
+ !(dependency.groups & configuration.skipped_groups).empty?
40
70
  end
41
71
 
42
72
  def safe_version_specifier(version)
@@ -2,8 +2,8 @@ module Safedep
2
2
  # http://semver.org/
3
3
  module Version
4
4
  MAJOR = 0
5
- MINOR = 0
6
- PATCH = 2
5
+ MINOR = 1
6
+ PATCH = 0
7
7
 
8
8
  def self.to_s
9
9
  [MAJOR, MINOR, PATCH].join('.')
data/spec/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+
2
+ inherit_from: ../.rubocop.yml
3
+
4
+ # Lengthen for long descriptions.
5
+ LineLength:
6
+ Max: 120
7
+
8
+ # raise_error matcher always requires {} form block.
9
+ Blocks:
10
+ Enabled: false
11
+
12
+ # Sometimes block alignment does not suit RSpec syntax.
13
+ BlockAlignment:
14
+ Enabled: false
15
+
16
+ # Suppress offences for namespace classes only with #describe.
17
+ ClassLength:
18
+ Enabled: false
@@ -0,0 +1,48 @@
1
+ require 'safedep/cli'
2
+
3
+ module Safedep
4
+ describe CLI do
5
+ include FileHelper
6
+ include_context 'isolated environment'
7
+
8
+ subject(:cli) { CLI.new }
9
+
10
+ describe '#run' do
11
+ subject(:run) { cli.run(args) }
12
+ let(:args) { [] }
13
+
14
+ context 'when run successfully', :gemfile, :lockfile do
15
+ it 'returns true' do
16
+ allow(cli).to receive(:puts)
17
+ expect(run).to be true
18
+ end
19
+ end
20
+
21
+ context 'when there is no Gemfile.lock' do
22
+ it 'warns of it' do
23
+ expect { run }.to output(/Gemfile.lock/).to_stderr
24
+ end
25
+
26
+ it 'aborts processing' do
27
+ allow(cli).to receive(:warn)
28
+ expect { run }.not_to output.to_stdout
29
+ end
30
+
31
+ it 'returns false' do
32
+ allow(cli).to receive(:warn)
33
+ expect(run).to be false
34
+ end
35
+ end
36
+
37
+ context 'when unknown error is raised' do
38
+ before do
39
+ allow(Runner).to receive(:run).and_raise('foo')
40
+ end
41
+
42
+ it 'does not rescue the error' do
43
+ expect { run }.to raise_error('foo')
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -2,18 +2,11 @@ require 'safedep/gemfile'
2
2
 
3
3
  module Safedep
4
4
  class Gemfile
5
- describe Dependency do
5
+ describe Dependency, :gemfile do
6
6
  include FileHelper
7
7
  include_context 'isolated environment'
8
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 }
9
+ let(:gemfile_source) { <<-END.strip_indent }
17
10
  source 'https://rubygems.org'
18
11
 
19
12
  gemspec
@@ -33,6 +26,61 @@ module Safedep
33
26
  end
34
27
  end
35
28
 
29
+ describe '#groups' do
30
+ subject { dependency.groups }
31
+
32
+ let(:gemfile_source) { <<-END.strip_indent }
33
+ source 'https://rubygems.org'
34
+
35
+ gem 'parser'
36
+
37
+ group :development, :test do
38
+ gem 'rake'
39
+ end
40
+
41
+ group :development do
42
+ gem 'guard'
43
+ gem 'rubocop', group: :test
44
+ end
45
+
46
+ group 'development' do
47
+ gem 'fuubar'
48
+ end
49
+
50
+ gem 'rspec', group: [:test, :development]
51
+ END
52
+
53
+ context 'when the dependency is specified in top level' do
54
+ let(:dependency) { gemfile.find_dependency('parser') }
55
+ it { should be_empty }
56
+ end
57
+
58
+ context 'when the dependency is specified in :development block' do
59
+ let(:dependency) { gemfile.find_dependency('guard') }
60
+ it { should eq([:development]) }
61
+ end
62
+
63
+ context 'when the dependency is specified in "development" block' do
64
+ let(:dependency) { gemfile.find_dependency('fuubar') }
65
+ it { should eq([:development]) }
66
+ end
67
+
68
+ context 'when the dependency is specified in :development and :test group' do
69
+ let(:dependency) { gemfile.find_dependency('rake') }
70
+ it { should eq([:development, :test]) }
71
+ end
72
+
73
+ context 'when the dependency is specified with group: [:test, :development] option' do
74
+ let(:dependency) { gemfile.find_dependency('rspec') }
75
+ it { should eq([:test, :development]) }
76
+ end
77
+
78
+ context 'when the dependency is specified with group: :test option in :development group' do
79
+ let(:dependency) { gemfile.find_dependency('rubocop') }
80
+ it { should eq([:development, :test]) }
81
+ end
82
+ end
83
+
36
84
  describe '#version_specifier' do
37
85
  subject(:version_specifier) { dependency.version_specifier }
38
86
 
@@ -1,68 +1,10 @@
1
1
  require 'safedep/gemfile_lock'
2
2
 
3
3
  module Safedep
4
- describe GemfileLock do
4
+ describe GemfileLock, :lockfile do
5
5
  include FileHelper
6
6
  include_context 'isolated environment'
7
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
8
  describe '#find_dependency' do
67
9
  it 'returns the dependency matching the passed name' do
68
10
  dependency = lockfile.find_dependency('rspec')
@@ -1,29 +1,10 @@
1
1
  require 'safedep/gemfile'
2
2
 
3
3
  module Safedep
4
- describe Gemfile do
4
+ describe Gemfile, :gemfile do
5
5
  include FileHelper
6
6
  include_context 'isolated environment'
7
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
8
  describe '#find_dependency' do
28
9
  it 'returns the dependency matching the passed name' do
29
10
  dependency = gemfile.find_dependency('rspec')
@@ -2,18 +2,11 @@ require 'safedep/gemspec'
2
2
 
3
3
  module Safedep
4
4
  class Gemspec
5
- describe Dependency do
5
+ describe Dependency, :gemspec do
6
6
  include FileHelper
7
7
  include_context 'isolated environment'
8
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 }
9
+ let(:gemspec_source) { <<-END.strip_indent }
17
10
  Gem::Specification.new do |spec|
18
11
  spec.name = 'safedep'
19
12
  spec.add_dependency 'parser'
@@ -30,6 +23,25 @@ module Safedep
30
23
  end
31
24
  end
32
25
 
26
+ describe '#groups' do
27
+ subject { dependency.groups }
28
+
29
+ context 'when the dependency is specified via #add_dependency' do
30
+ let(:dependency) { gemspec.find_dependency('parser') }
31
+ it { should be_empty }
32
+ end
33
+
34
+ context 'when the dependency is specified via #add_runtime_dependency' do
35
+ let(:dependency) { gemspec.find_dependency('astrolabe') }
36
+ it { should be_empty }
37
+ end
38
+
39
+ context 'when the dependency is specified via #add_runtime_dependency' do
40
+ let(:dependency) { gemspec.find_dependency('rspec') }
41
+ it { should eq([:development]) }
42
+ end
43
+ end
44
+
33
45
  describe '#version_specifier' do
34
46
  subject(:version_specifier) { dependency.version_specifier }
35
47
 
@@ -1,36 +1,20 @@
1
1
  require 'safedep/gemspec'
2
2
 
3
3
  module Safedep
4
- describe Gemspec do
4
+ describe Gemspec, :gemspec do
5
5
  include FileHelper
6
6
  include_context 'isolated environment'
7
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
8
  describe '#find_dependency' do
25
9
  it 'returns the dependency matching the passed name' do
26
- dependency = gemspec.find_dependency('rspec')
27
- expect(dependency.name).to eq('rspec')
10
+ dependency = gemspec.find_dependency('parser')
11
+ expect(dependency.name).to eq('parser')
28
12
  end
29
13
  end
30
14
 
31
15
  describe '#dependencies' do
32
16
  it 'returns an array of the dependencies' do
33
- expect(gemspec.dependencies.size).to eq(3)
17
+ expect(gemspec.dependencies.size).to eq(2)
34
18
  expect(gemspec.dependencies).to all be_a(Gemspec::Dependency)
35
19
  end
36
20
  end
@@ -0,0 +1,79 @@
1
+ require 'safedep/runner'
2
+
3
+ module Safedep
4
+ describe Runner do
5
+ include FileHelper
6
+ include_context 'isolated environment'
7
+
8
+ subject(:runner) { Runner.new }
9
+
10
+ let(:configuration) { runner.configuration }
11
+
12
+ let(:expected_gemfile_source) { <<-END.strip_indent }
13
+ source 'https://rubygems.org'
14
+
15
+ gemspec
16
+
17
+ group :development, :test do
18
+ gem 'rake', '~> 10.4'
19
+ gem 'rspec', '~> 3.1'
20
+ gem 'rubocop', '~> 0.28', require: false
21
+ end
22
+ END
23
+
24
+ let(:expected_gemspec_source) { <<-END.strip_indent }
25
+ Gem::Specification.new do |spec|
26
+ spec.name = 'safedep'
27
+ spec.add_runtime_dependency 'parser', '~> 2.2'
28
+ spec.add_runtime_dependency 'astrolabe', '~> 1.3'
29
+ end
30
+ END
31
+
32
+ context 'when there is no Gemfile.lock' do
33
+ it 'raises error' do
34
+ expect { runner.run }.to raise_error(/Gemfile.lock/)
35
+ end
36
+ end
37
+
38
+ context 'when there is Gemfile.lock', :lockfile do
39
+ context 'but no Gemfile' do
40
+ it 'raises error' do
41
+ expect { runner.run }.to raise_error(/Gemfile /)
42
+ end
43
+ end
44
+
45
+ context 'and Gemfile', :gemfile do
46
+ it 'rewrites the Gemfile' do
47
+ runner.run
48
+ expect(rewritten_gemfile_source).to eq(expected_gemfile_source)
49
+ end
50
+
51
+ context 'and gemspec', :gemspec do
52
+ it 'rewrites both the Gemfile and the gemspec' do
53
+ runner.run
54
+ expect(rewritten_gemfile_source).to eq(expected_gemfile_source)
55
+ expect(rewritten_gemspec_source).to eq(expected_gemspec_source)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ context 'when Configuration#skipped_groups is specified', :gemspec, :gemfile, :lockfile do
62
+ before do
63
+ configuration.skipped_groups = ['development']
64
+ end
65
+
66
+ let(:development_dependencies) do
67
+ runner.dependencies.select { |dep| dep.groups.include?(:development) }
68
+ end
69
+
70
+ it 'does not modify dependencies that belong to any of the groups' do
71
+ development_dependencies.each do |dep|
72
+ expect(dep).not_to receive(:version_specifier=)
73
+ end
74
+
75
+ runner.run
76
+ end
77
+ end
78
+ end
79
+ end
@@ -9,3 +9,108 @@ shared_context 'isolated environment' do
9
9
  end
10
10
  end
11
11
  end
12
+
13
+ shared_context 'with gemspec', :gemspec do
14
+ let!(:gemspec) do
15
+ require 'safedep/gemspec'
16
+ create_file(gemspec_path, gemspec_source)
17
+ Safedep::Gemspec.new(gemspec_path)
18
+ end
19
+
20
+ let(:gemspec_path) { 'safedep.gemspec' }
21
+
22
+ let(:gemspec_source) { <<-END.strip_indent }
23
+ Gem::Specification.new do |spec|
24
+ spec.name = 'safedep'
25
+ spec.add_runtime_dependency 'parser'
26
+ spec.add_runtime_dependency 'astrolabe'
27
+ end
28
+ END
29
+
30
+ let(:rewritten_gemspec_source) { File.read(gemspec_path) }
31
+ end
32
+
33
+ shared_context 'with Gemfile', :gemfile do
34
+ let!(:gemfile) do
35
+ require 'safedep/gemfile'
36
+ create_file(gemfile_path, gemfile_source)
37
+ Safedep::Gemfile.new(gemfile_path)
38
+ end
39
+
40
+ let(:gemfile_path) { 'Gemfile' }
41
+
42
+ let(:gemfile_source) { <<-END.strip_indent }
43
+ source 'https://rubygems.org'
44
+
45
+ gemspec
46
+
47
+ group :development, :test do
48
+ gem 'rake'
49
+ gem 'rspec'
50
+ gem 'rubocop', require: false
51
+ end
52
+ END
53
+
54
+ let(:rewritten_gemfile_source) { File.read(gemfile_path) }
55
+ end
56
+
57
+ shared_context 'with Gemfile.lock', :lockfile do
58
+ let!(:lockfile) do
59
+ require 'safedep/gemfile_lock'
60
+ create_file(lockfile_path, lockfile_source)
61
+ Safedep::GemfileLock.new(lockfile_path)
62
+ end
63
+
64
+ let(:lockfile_path) { 'Gemfile.lock' }
65
+
66
+ let(:lockfile_source) { <<-END.strip_indent }
67
+ PATH
68
+ remote: .
69
+ specs:
70
+ safedep (0.0.1)
71
+ astrolabe
72
+ bundler (~> 1.7)
73
+ parser
74
+
75
+ GEM
76
+ remote: https://rubygems.org/
77
+ specs:
78
+ ast (2.0.0)
79
+ astrolabe (1.3.0)
80
+ parser (>= 2.2.0.pre.3, < 3.0)
81
+ diff-lcs (1.2.5)
82
+ parser (2.2.0.2)
83
+ ast (>= 1.1, < 3.0)
84
+ powerpack (0.0.9)
85
+ rainbow (2.0.0)
86
+ rake (10.4.2)
87
+ rspec (3.1.0)
88
+ rspec-core (~> 3.1.0)
89
+ rspec-expectations (~> 3.1.0)
90
+ rspec-mocks (~> 3.1.0)
91
+ rspec-core (3.1.7)
92
+ rspec-support (~> 3.1.0)
93
+ rspec-expectations (3.1.2)
94
+ diff-lcs (>= 1.2.0, < 2.0)
95
+ rspec-support (~> 3.1.0)
96
+ rspec-mocks (3.1.3)
97
+ rspec-support (~> 3.1.0)
98
+ rspec-support (3.1.2)
99
+ rubocop (0.28.0)
100
+ astrolabe (~> 1.3)
101
+ parser (>= 2.2.0.pre.7, < 3.0)
102
+ powerpack (~> 0.0.6)
103
+ rainbow (>= 1.99.1, < 3.0)
104
+ ruby-progressbar (~> 1.4)
105
+ ruby-progressbar (1.7.1)
106
+
107
+ PLATFORMS
108
+ ruby
109
+
110
+ DEPENDENCIES
111
+ rake (~> 10.4)
112
+ rspec (~> 3.1)
113
+ rubocop (~> 0.28)
114
+ safedep!
115
+ END
116
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safedep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yuji Nakayama
@@ -66,6 +66,7 @@ files:
66
66
  - ".travis.yml"
67
67
  - CHANGELOG.md
68
68
  - Gemfile
69
+ - Guardfile
69
70
  - LICENSE.txt
70
71
  - README.md
71
72
  - Rakefile
@@ -74,6 +75,8 @@ files:
74
75
  - lib/safedep/abstract_gemfile.rb
75
76
  - lib/safedep/cli.rb
76
77
  - lib/safedep/cli/option_parser.rb
78
+ - lib/safedep/configuration.rb
79
+ - lib/safedep/error.rb
77
80
  - lib/safedep/gemfile.rb
78
81
  - lib/safedep/gemfile/dependency.rb
79
82
  - lib/safedep/gemfile_lock.rb
@@ -82,11 +85,14 @@ files:
82
85
  - lib/safedep/runner.rb
83
86
  - lib/safedep/version.rb
84
87
  - safedep.gemspec
88
+ - spec/.rubocop.yml
89
+ - spec/safedep/cli_spec.rb
85
90
  - spec/safedep/gemfile/dependency_spec.rb
86
91
  - spec/safedep/gemfile_lock_spec.rb
87
92
  - spec/safedep/gemfile_spec.rb
88
93
  - spec/safedep/gemspec/dependency_spec.rb
89
94
  - spec/safedep/gemspec_spec.rb
95
+ - spec/safedep/runner_spec.rb
90
96
  - spec/spec_helper.rb
91
97
  - spec/support/file_helper.rb
92
98
  - spec/support/shared_contexts.rb
@@ -115,11 +121,14 @@ signing_key:
115
121
  specification_version: 4
116
122
  summary: Make your Gemfile safe by adding dependency version specifiers automatically.
117
123
  test_files:
124
+ - spec/.rubocop.yml
125
+ - spec/safedep/cli_spec.rb
118
126
  - spec/safedep/gemfile/dependency_spec.rb
119
127
  - spec/safedep/gemfile_lock_spec.rb
120
128
  - spec/safedep/gemfile_spec.rb
121
129
  - spec/safedep/gemspec/dependency_spec.rb
122
130
  - spec/safedep/gemspec_spec.rb
131
+ - spec/safedep/runner_spec.rb
123
132
  - spec/spec_helper.rb
124
133
  - spec/support/file_helper.rb
125
134
  - spec/support/shared_contexts.rb