smarter_bundler 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6fbba5a723688fabe832cd0ae312cb05a512185c
4
+ data.tar.gz: d8c649cad25c8f219b93065b8b508ac299fc88c7
5
+ SHA512:
6
+ metadata.gz: 3212fd4edcbc6064e82011b0b3d507334bc97323382ebe36dba899d48d8a87da94bfa8b409494012787b81618fe79501a47121e25d28486e9fad65a4230e0fbc
7
+ data.tar.gz: 6d3b40270cb45dc82afcb393ff3c5281aff40eef1f20b3153050ee80bd4a92eeb8c029d75f4f007b09fbe0ce78cc06f589e6e0623cebfd4a7eeb0a38c328b23d
data/.gitignore CHANGED
@@ -8,6 +8,6 @@ Gemfile.lock
8
8
  /pkg/
9
9
  /spec/reports/
10
10
  /tmp/
11
- /test/rails*/.bundle
12
- /test/rails*/Gemfile
13
- /test/rails*/Gemfile.lock
11
+ /test/*/.bundle
12
+ /test/*/Gemfile
13
+ /test/*/Gemfile.lock
data/README.md CHANGED
@@ -22,12 +22,30 @@ A reasonable limit would be four to ten times the time it normally takes to inst
22
22
  Once you hit that limit, then check your install log and incorporate the fixes it has found into your Gemfile
23
23
  source to remove the need for it to run bundler multiple times whilst it fixes the Gemfile.
24
24
 
25
+ ### Cleaning up afterwards
26
+
27
+ After smarter_bundle has updated the Gemfile, you should examine the changes, as some adjustments may be in order:
28
+ 1. If a gem is not already referenced in the Gemfile, then look in Gemfile.lock for the gems that depend on it and place the new line in the same group as the related gems;
29
+ 2. smarter_bundle does not backtrack and recheck earlier adjustments - this may result in a gem being restricted that is no longer needed because the gem that originally needed ended up being restricted to the point it no longer has so many prerequisites. In the Gemfile.lock you will see that the gem is not required by any other gems, nor was it a gem you directly need.
30
+ 3. smarter_bundle does not know how to handle Gemfiles that are intended to be used with multiple ruby versions, so you will need to make a Gemfile that is intended for the ruby version you are checking it with and then incorporate the changes smarter_bundle makes back into the master Gemfile manually;
31
+
32
+ ### Using in test scripts
33
+
34
+ If for some reason you do not use Gemfile.lock in automated testing (eg when testing gems with travis-ci), and you are testing against older ruby versions, then you may wish to consider using
35
+ smarter_bundler - instead of the test script failing, smarter_bundler will update the Gemfile on the fly. Of course you are swapping processing time for convienience,
36
+ so you should implement a time limit and manually update your Gemfile once the tests slow down too much.
37
+
38
+ I usually prefer to fail fast and fix it then and there rather than delay the issue, but sometimes delaying failure till later when it can be worked around is appropriate.
39
+
25
40
  ## Notes
26
41
 
27
- If the error indicates a ruby version conflict, then it will lookup the gem on rubygems to find the earliest version with the same ruby spec
42
+ If the error indicates a ruby version conflict,
43
+ then it will lookup the gem on rubygems to find the earliest version with the same ruby spec
28
44
  and update the Gemfile to specify a version prior to that. If the lookup of rubygems fails, then it will simply check the next earlier version.
29
45
 
30
- If the error was not from a ruby version conflict, it will attempt to install the gem directly once more.
46
+ Syntax errors will trigger smarter_bundle to try the immediately earlier version, without looking up rubygems, because a syntax error indicates the gemspec doesn't correctly specify the required ruby versions.
47
+
48
+ If the error was not from a ruby version conflict or syntax error, it will attempt to install the gem directly once more.
31
49
 
32
50
  It will attempt to fix the Gemfile up to 100 times before giving up as long as each attempt is making progress.
33
51
 
@@ -9,7 +9,11 @@ Vagrant.configure("2") do |config|
9
9
  # provision with a shell script.
10
10
  config.vm.provision "shell",
11
11
  path: "https://raw.githubusercontent.com/ianheggie/provision_vagrant/master/provision?cache_bust=#{Process.pid}",
12
- args: %w{ /vagrant }
12
+ args: %w{ /vagrant /vagrant/test/rails30 /vagrant/test/rails31 /vagrant/test/rails32 /vagrant/test/rails40
13
+ /vagrant/test/rails41 /vagrant/test/rails42 /vagrant/test/rails50 /vagrant/test/rails51
14
+ /vagrant/test/special_cases }
15
+
16
+
13
17
 
14
18
  # Stop nagging as this box changes daily...
15
19
  config.vm.box_check_update = true
data/bin/test CHANGED
@@ -6,30 +6,30 @@ ruby_version=`ruby -e 'puts RUBY_VERSION'`
6
6
  psych_ver='< 3.0'
7
7
  case "$ruby_version" in
8
8
  1.8.7)
9
- dirs='rails30 rails31 rails32'
9
+ dirs='rails30 rails31 rails32 special_cases'
10
10
  psych_ver=''
11
11
  ;;
12
12
  1.9.2)
13
- dirs='rails30 rails31 rails32'
13
+ dirs='rails30 rails31 rails32 special_cases'
14
14
  ;;
15
15
  1.9.3)
16
- dirs='rails30 rails31 rails32 rails40 rails41 rails42'
16
+ dirs='rails30 rails31 rails32 rails40 rails41 rails42 special_cases'
17
17
  ;;
18
18
  2.0*)
19
- dirs='rails32 rails40 rails41 rails42'
19
+ dirs='rails32 rails40 rails41 rails42 special_cases'
20
20
  ;;
21
21
  2.1*)
22
- dirs='rails41 rails42'
22
+ dirs='rails41 rails42 special_cases'
23
23
  ;;
24
24
  2.2.[01]*)
25
- dirs='rails42'
25
+ dirs='rails42 special_cases'
26
26
  ;;
27
27
  2.2.2)
28
- dirs='rails32 rails42 rails50 rails51'
28
+ dirs='rails32 rails42 rails50 rails51 special_cases'
29
29
  psych_ver='> 2.0'
30
30
  ;;
31
- 2.2.[2-9]*|2.[3-9]*)
32
- dirs='rails50 rails51'
31
+ 2.2.[2-9]*|2.[3-9]*|[3-9]*)
32
+ dirs='rails50 rails51 special_cases'
33
33
  gem install psych
34
34
  psych_ver='> 2.0'
35
35
  ;;
@@ -62,7 +62,7 @@ do
62
62
  rm -f Gemfile.lock
63
63
  cp -f Gemfile.default Gemfile
64
64
  # Exclude debugger - it breaks for many varied reasons on travis
65
- ../../exe/smarter_bundle --without debug
65
+ ../../exe/smarter_bundle --aggressive install --no-color --verbose --without debug
66
66
  echo Gemfile changes:
67
67
  diff Gemfile.default Gemfile
68
68
  echo
@@ -5,4 +5,4 @@ $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
5
5
 
6
6
  require 'smarter_bundler'
7
7
 
8
- SmarterBundler::Bundle.new.run ARGV.join(' ')
8
+ SmarterBundler::Bundle.new.run ARGV
@@ -8,18 +8,20 @@ module SmarterBundler
8
8
  class Bundle
9
9
  include SmarterBundler::Shell
10
10
 
11
- KNOWN_ISSUES_187_192 = {
11
+ # Note the versions listed in KNOWN_SOLUTIONS are the first NON working version
12
+ # for the first ruby version listed (eg 1.8.7, 1.9.3, 2.2.2)
13
+
14
+ KNOWN_SOLUTIONS_187_192 = {
12
15
  'unicorn' => '5.0',
13
16
  'nokogiri' => '1.6.0',
14
17
  'jbuilder' => '2.0.0',
15
18
  'factory_girl' => '3.0',
16
19
  'factory_bot' => '3.0',
20
+ 'listen' => '3.1.2',
21
+ 'css_parser' => '1.4.8', # syntax error
17
22
  }
18
23
 
19
- KNOWN_ISSUES_193_221 = {
20
- }
21
-
22
- KNOWN_ISSUES_222_22x = {
24
+ KNOWN_SOLUTIONS_193_221 = {
23
25
  'listen' => '3.1.2',
24
26
  'acts-as-taggable-on' => '5.0.0',
25
27
  'guard-rails' => '0.7.3',
@@ -27,13 +29,30 @@ module SmarterBundler
27
29
  'ruby_dep' => '1.4.0',
28
30
  }
29
31
 
32
+ KNOWN_SOLUTIONS_222_22x = {
33
+ }
34
+
30
35
 
31
36
  def run(bundle_args)
37
+ @aggressive = bundle_args.first == '--aggressive'
38
+ if @aggressive
39
+ bundle_args = bundle_args.drop(1)
40
+ end
32
41
  puts 'Smarter Bundler will recursively install your gems and output the successful bundler output. This may take a while.'
33
42
  count = 0
34
43
  gemfile = SmarterBundler::Gemfile.new
35
44
  previous_failure = []
36
45
  result = nil
46
+ if @aggressive
47
+ known_solutions.each do |gem, version|
48
+ if gemfile.mentions? gem
49
+ gemfile.restrict_gem_version(gem, version)
50
+ count += 1
51
+ end
52
+ end
53
+ puts "Made #{count} adjustments in Gemfile based on known solutions" if count > 0
54
+ end
55
+
37
56
  while count < 100
38
57
  result = call_bundle(bundle_args)
39
58
  failed_gem_and_version = parse_output(result)
@@ -44,15 +63,15 @@ module SmarterBundler
44
63
  end
45
64
  previous_failure = failed_gem_and_version
46
65
  gem, version = *failed_gem_and_version
47
- if !ruby_version_clash(result) && install_failed_gem(gem, version)
48
- puts 'Retrying seems to have fixed the problem'
49
- elsif gemfile.restrict_gem_version(gem, known_issues(gem))
66
+ if gemfile.restrict_gem_version(gem, known_solution(gem))
50
67
  gemfile.save
51
68
  count += 1
52
- elsif ruby_version_clash(result) && gemfile.restrict_gem_version(gem, rubygems_earlier_version(gem, version))
69
+ elsif !fatal_error(result) && install_failed_gem(gem, version)
70
+ puts 'Retrying seems to have fixed the problem'
71
+ elsif ruby_version_error(result) && gemfile.restrict_gem_version(gem, rubygems_earlier_version(gem, version))
53
72
  gemfile.save
54
73
  count += 1
55
- elsif ruby_version_clash(result) && gemfile.restrict_gem_version(gem, version)
74
+ elsif fatal_error(result) && gemfile.restrict_gem_version(gem, version)
56
75
  gemfile.save
57
76
  count += 1
58
77
  else
@@ -68,26 +87,38 @@ module SmarterBundler
68
87
  end
69
88
 
70
89
  def call_bundle(bundle_args)
71
- shell "bundle #{bundle_args}"
90
+ shell "bundle #{bundle_args.join(' ')} && ruby -e 'puts \"Checking gems can be loaded ...\" ; require \"rubygems\" ; require \"bundler/setup\" ; Bundler.require(:default) ; puts \"PASSED GEM LOAD TEST\" ' "
72
91
  end
73
92
 
74
93
  def install_failed_gem(gem, version)
75
94
  shell? "gem install '#{gem}' -v '#{version}'"
76
95
  end
77
96
 
78
- def ruby_version_clash(result)
97
+ def fatal_error(result)
98
+ ruby_version_error(result) || syntax_error(result)
99
+ end
100
+
101
+ def ruby_version_error(result)
79
102
  result.output.select { |l| l =~ /requires Ruby version/ }.any?
80
103
  end
81
104
 
82
- def known_issues(gem)
105
+ def syntax_error(result)
106
+ result.output.select { |l| l =~ /(: syntax error|SyntaxError: )/ }.any?
107
+ end
108
+
109
+ def known_solution(gem)
110
+ known_solutions[gem]
111
+ end
112
+
113
+ def known_solutions
83
114
  if RUBY_VERSION <= '1.9.2'
84
- KNOWN_ISSUES_187_192[gem]
115
+ KNOWN_SOLUTIONS_187_192
85
116
  elsif RUBY_VERSION <= '2.2.1'
86
- KNOWN_ISSUES_193_221[gem]
117
+ KNOWN_SOLUTIONS_193_221
87
118
  elsif RUBY_VERSION <= '2.3'
88
- KNOWN_ISSUES_222_22x[gem]
119
+ KNOWN_SOLUTIONS_222_22x
89
120
  else
90
- nil
121
+ { }
91
122
  end
92
123
  end
93
124
 
@@ -95,6 +126,10 @@ module SmarterBundler
95
126
  result.output.each do |line|
96
127
  if line =~ /Make sure that `gem install (\S+) -v '(\S+)'`/
97
128
  return [$1, $2]
129
+ elsif line =~ %r{SyntaxError: .*/ruby/[^/]*/gems/([^/]*)-(\d[^/]+)/}
130
+ return [$1, $2]
131
+ elsif line =~ %r{/ruby/[^/]*/gems/([^/]*)-(\d[^/]+)/\S+:\d+: syntax error}
132
+ return [$1, $2]
98
133
  end
99
134
  end
100
135
  nil
@@ -14,9 +14,13 @@ module SmarterBundler
14
14
  @changed = false
15
15
  end
16
16
 
17
+ def mentions? gem
18
+ @contents.select { |line| line =~ /^\s*gem\s+['"]#{gem}['"]/ }.any?
19
+ end
20
+
17
21
  def restrict_gem_version gem, version_limit
18
22
  return false unless version_limit.to_s =~ /\d\.\d/
19
- if @contents.select { |line| line =~ /^\s*gem\s+['"]#{gem}['"]/ }.empty?
23
+ if ! mentions? gem
20
24
  @contents << "gem '#{gem}', '>=0'"
21
25
  end
22
26
  adjusted = false
@@ -3,7 +3,7 @@ module SmarterBundler
3
3
  def shell(command)
4
4
  puts '', "+ #{command}"
5
5
  output = []
6
- IO.popen("#{command} 2>&1") do |io|
6
+ IO.popen("( #{command} ) 2>&1 < /dev/null") do |io|
7
7
  while line = io.gets
8
8
  puts line.chomp
9
9
  output << line.chomp
@@ -1,3 +1,3 @@
1
1
  module SmarterBundler
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,81 +1,69 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: smarter_bundler
3
- version: !ruby/object:Gem::Version
4
- hash: 29
5
- prerelease:
6
- segments:
7
- - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
11
5
  platform: ruby
12
- authors:
6
+ authors:
13
7
  - Ian Heggie
14
8
  autorequire:
15
9
  bindir: exe
16
10
  cert_chain: []
17
-
18
- date: 2018-03-14 00:00:00 +11:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- version_requirements: &id001 !ruby/object:Gem::Requirement
23
- none: false
24
- requirements:
25
- - - ~>
26
- - !ruby/object:Gem::Version
27
- hash: 47
28
- segments:
29
- - 1
30
- - 16
31
- version: "1.16"
32
- prerelease: false
33
- type: :development
34
- requirement: *id001
11
+ date: 2018-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
35
14
  name: bundler
36
- - !ruby/object:Gem::Dependency
37
- version_requirements: &id002 !ruby/object:Gem::Requirement
38
- none: false
39
- requirements:
40
- - - ~>
41
- - !ruby/object:Gem::Version
42
- hash: 35
43
- segments:
44
- - 10
45
- - 0
46
- version: "10.0"
47
- prerelease: false
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
48
20
  type: :development
49
- requirement: *id002
50
- name: rake
51
- - !ruby/object:Gem::Dependency
52
- version_requirements: &id003 !ruby/object:Gem::Requirement
53
- none: false
54
- requirements:
55
- - - ~>
56
- - !ruby/object:Gem::Version
57
- hash: 31
58
- segments:
59
- - 5
60
- - 0
61
- version: "5.0"
62
21
  prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
63
34
  type: :development
64
- requirement: *id003
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
65
42
  name: minitest
66
- description: The smarter_bundle retries installing gems, and if that fails it tries installing an earlier version by adjusting the Gemfile
67
- email:
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: The smarter_bundle retries installing gems, and if that fails it tries
56
+ installing an earlier version by adjusting the Gemfile
57
+ email:
68
58
  - ian@heggie.biz
69
- executables:
59
+ executables:
70
60
  - smarter_bundle
71
61
  extensions: []
72
-
73
62
  extra_rdoc_files: []
74
-
75
- files:
76
- - .gitignore
77
- - .ruby-versions
78
- - .travis.yml
63
+ files:
64
+ - ".gitignore"
65
+ - ".ruby-versions"
66
+ - ".travis.yml"
79
67
  - CHANGELOG
80
68
  - Gemfile
81
69
  - LICENSE.txt
@@ -92,39 +80,28 @@ files:
92
80
  - lib/smarter_bundler/shell.rb
93
81
  - lib/smarter_bundler/version.rb
94
82
  - smarter_bundler.gemspec
95
- has_rdoc: true
96
83
  homepage: https://github.com/ianheggie/smarter_bundler
97
- licenses:
84
+ licenses:
98
85
  - MIT
86
+ metadata: {}
99
87
  post_install_message:
100
88
  rdoc_options: []
101
-
102
- require_paths:
89
+ require_paths:
103
90
  - lib
104
- required_ruby_version: !ruby/object:Gem::Requirement
105
- none: false
106
- requirements:
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
107
93
  - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 3
110
- segments:
111
- - 0
112
- version: "0"
113
- required_rubygems_version: !ruby/object:Gem::Requirement
114
- none: false
115
- requirements:
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
116
98
  - - ">="
117
- - !ruby/object:Gem::Version
118
- hash: 3
119
- segments:
120
- - 0
121
- version: "0"
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
122
101
  requirements: []
123
-
124
102
  rubyforge_project:
125
- rubygems_version: 1.6.2
103
+ rubygems_version: 2.5.2
126
104
  signing_key:
127
- specification_version: 3
105
+ specification_version: 4
128
106
  summary: Enhances bundler by adjusting Gemfile when correctable errors are found
129
107
  test_files: []
130
-