strong_versions 0.4.2 → 0.4.3

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
  SHA256:
3
- metadata.gz: 4b8013eab29eed756e82642806ffa493cdfe95b811a04cbf1a8671f438a7d941
4
- data.tar.gz: 99d19f00b86a8499cac020279583a32da2a14f3639eeb7036df0338113c60f83
3
+ metadata.gz: a19f2c731b09de210cb242a54ed087493741010a84fd98324a42834bfffb32f3
4
+ data.tar.gz: 07fde31789f1c729ede0859404cf5574c20566b3fc2e7e152cc7ee62d45a3d8c
5
5
  SHA512:
6
- metadata.gz: '047964e0861c334509ae41809d5b57ee2cc0f412223148d374d2008ecca64db6ca4eca7df9ebe2d579dcdfc4d988c1d141642b766a47d701ebb866cb281fab01'
7
- data.tar.gz: 48268429b4da20105b90fd3671488180753550f4776467d77e3de0d8c761295b767cd2502a61d99330830a95efde09c129ba9f7e615a2f18e783c885093daf7e
6
+ metadata.gz: 48f230820ee7ebe3e69c6f4e938a01ef12288d6b624869cddf9905701cd2aaeefd3797cd499ea667dd7816182140688bbf3b6a07019e24cea2bd2a98c8b53c28
7
+ data.tar.gz: 129dcaae26d6d8546e52dc7384bbd4ddac4879750399d158517b27198a1fc31a2424566322d343f4959a252dea196a809a26e1acd7fcc63628809d07b157c099
@@ -11,4 +11,8 @@ Style/FormatStringToken:
11
11
  - 'lib/strong_versions/terminal.rb'
12
12
  AllCops:
13
13
  Exclude:
14
- - 'bin/**/*'
14
+ - 'bin/rake'
15
+ - 'bin/console'
16
+ - 'bin/rspec'
17
+ - 'bin/rubocop'
18
+ - 'bin/setup'
data/Makefile CHANGED
@@ -1,6 +1,5 @@
1
1
  .PHONY: test
2
2
  test:
3
- @bin/rspec
4
- @bundle exec bin/strong_versions
5
- @bin/rubocop
6
- @bin/rubocop bin/strong_versions
3
+ @bundle exec rspec
4
+ @bundle exec strong_versions
5
+ @bundle exec rubocop
data/README.md CHANGED
@@ -13,13 +13,13 @@ _StrongVersions_ enforces a strict policy on your `Gemfile` requirements:
13
13
  * The pessimistic `~>` operator must be used for all gem requirement definitions.
14
14
  * If the gem version is greater than 1, the requirement format must be `major.minor`, e.g. `'~> 2.5`'
15
15
  * If the gem version is less than 1, the requirement format must be `major.minor.patch`, e.g. `'~> 0.8.9'`
16
- * An upper bound can be specified as long as a valid pessimistic version is also specified, e.g. `'~> 8.4', '< 8.6.7' # Bug introduced in 8.6.7`
16
+ * A lower/upper bound can be specified as long as a valid pessimistic version is also specified, e.g. `'~> 8.4', '< 8.6.7'`
17
17
  * All gems with a `path` or `git` source are ignored, e.g. `path: '/path/to/gem'`, `git: 'https://github.com/bobf/strong_versions'`
18
18
  * All gems specified in the [ignore list](#ignore) are ignored.
19
19
 
20
- Any gems that do not satisfy these rules will be included in included in the _StrongVersions_ output with details on why they did not meet the standard.
20
+ Any gems that do not satisfy these rules will be included in the _StrongVersions_ output with details on why they did not meet the standard.
21
21
 
22
- The benefit of applying this standard is that, if all gems follow [Semantic Versioning](https://semver.org/) always be relatively safe to run `bundle update` to upgrade to the latest compatible versions of all dependencies. Running `bundle update` often brings advantages both in terms of bug fixes and security updates.
22
+ When all gems in a `Gemfile` follow this convention it SHOULD always be safe to run `bundle update` (assuming all gems adhere to [Semantic Versioning](https://semver.org/)).
23
23
 
24
24
  ![StrongVersions](doc/images/strong-versions-example.png)
25
25
 
@@ -28,7 +28,7 @@ The benefit of applying this standard is that, if all gems follow [Semantic Vers
28
28
  Add the gem to your `Gemfile`
29
29
 
30
30
  ```ruby
31
- gem 'strong_versions', '~> 0.4.2'
31
+ gem 'strong_versions', '~> 0.4.3'
32
32
  ```
33
33
 
34
34
  And rebuild your bundle:
@@ -39,7 +39,7 @@ $ bundle install
39
39
 
40
40
  Or install yourself:
41
41
  ```bash
42
- $ gem install strong_versions -v '0.4.2'
42
+ $ gem install strong_versions -v '0.4.3'
43
43
  ```
44
44
 
45
45
  ## Usage
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require 'bundler/setup'
4
5
  require 'optparse'
5
6
  require 'shellwords'
6
7
 
@@ -12,11 +13,11 @@ options = {}
12
13
  OptionParser.new do |opts|
13
14
  opts.banner = 'Usage: strong_versions [options]'
14
15
 
15
- opts.on('-a', '--auto-correct', 'Auto-correct (use with caution)') do |_v|
16
+ opts.on('-a', '--auto-correct', 'Auto-correct (use with caution)') do
16
17
  options[:auto_correct] = true
17
18
  end
18
19
 
19
- opts.on('--no-auto-correct', 'Disable auto-correct') do |_v|
20
+ opts.on('--no-auto-correct', 'Disable auto-correct') do
20
21
  options[:auto_correct] = false
21
22
  end
22
23
  end.parse!
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
 
3
5
  require 'strong_versions'
4
6
 
5
7
  options = {}
6
8
  OptionParser.new do |opts|
7
- opts.banner = "Usage: strong_versions [options]"
9
+ opts.banner = 'Usage: strong_versions [options]'
8
10
 
9
- opts.on("-a", "--auto-correct", "Auto-correct (use with caution)") do |v|
11
+ opts.on('-a', '--auto-correct', 'Auto-correct (use with caution)') do |_v|
10
12
  options[:auto_correct] = true
11
13
  end
12
14
  end.parse!
@@ -24,12 +26,13 @@ validated = StrongVersions::Dependencies.new(dependencies).validate!(
24
26
  )
25
27
 
26
28
  revalidated = false
27
- revalidated = StrongVersions::Dependencies.new(dependencies).validate!(
28
- except: config.exceptions,
29
- on_failure: 'warn',
30
- auto_correct: false
31
- ) if options[:auto_correct]
29
+ if options[:auto_correct]
30
+ revalidated = StrongVersions::Dependencies.new(dependencies).validate!(
31
+ except: config.exceptions,
32
+ on_failure: 'warn',
33
+ auto_correct: false
34
+ )
35
+ end
32
36
 
33
- exit 0 if validated or revalidated
37
+ exit 0 if validated || revalidated
34
38
  exit 1
35
-
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
3
4
  require 'yaml'
4
5
 
5
6
  require 'i18n'
@@ -17,7 +17,7 @@ module StrongVersions
17
17
  return true
18
18
  end
19
19
 
20
- return update_gemfile if auto_correct
20
+ return update_definitions if auto_correct
21
21
 
22
22
  raise_or_warn(options.fetch(:on_failure, 'raise'))
23
23
  summary
@@ -45,38 +45,50 @@ module StrongVersions
45
45
  @terminal.summary(@dependencies.size, @invalid_gems.size)
46
46
  end
47
47
 
48
- def update_gemfile
49
- updated = 0
50
- @dependencies.each do |dependency|
51
- next unless dependency.updatable?
48
+ def updatable_dependencies
49
+ @dependencies.select(&:updatable?)
50
+ end
51
+
52
+ def update_definitions
53
+ @terminal.update_summary(update(:gemfile) + update(:gemspec))
54
+ end
55
+
56
+ def update(subject)
57
+ updatable_dependencies.reduce(0) do |count, dependency|
58
+ next count unless dependency.updatable?
52
59
 
53
- updated += 1 if update_dependency(dependency)
60
+ update_dependency(subject, dependency) ? count : count + 1
54
61
  end
55
- @terminal.update_summary(updated)
56
62
  end
57
63
 
58
- def update_dependency(dependency)
59
- path = dependency.gemfile
64
+ def update_dependency(subject, dependency)
65
+ path = dependency.public_send(subject)
66
+ return if path.nil?
67
+
60
68
  content = File.read(path)
61
- update = replace_gem_definition(dependency, content)
69
+ update = replace_gem_definition(subject, dependency, content)
62
70
  return false if content == update
63
71
 
64
72
  File.write(path, update)
65
- @terminal.gem_update(path, dependency)
73
+ @terminal.gem_update(path, dependency, subject)
66
74
  true
67
75
  end
68
76
 
69
- def replace_gem_definition(dependency, content)
70
- regex = gem_regex(dependency.name)
77
+ def replace_gem_definition(subject, dependency, content)
78
+ regex = gem_regex(subject, dependency.name)
71
79
  match = content.match(regex)
72
80
  return content unless match
73
81
 
74
82
  indent = match.captures.first
75
- content.gsub(regex, "#{indent}#{dependency.suggested_definition}")
83
+ definition = dependency.suggested_definition(subject)
84
+ content.gsub(regex, "#{indent}#{definition}")
76
85
  end
77
86
 
78
- def gem_regex(name)
79
- /^(\s*)gem\s+['"]#{name}['"].*$/
87
+ def gem_regex(subject, name)
88
+ {
89
+ gemfile: /^(\s*)gem\s+['"]#{name}['"].*$/,
90
+ gemspec: /^(\s*)spec.add_[a-z_]*_dependency\s+['"]#{name}['"].*$/
91
+ }.fetch(subject)
80
92
  end
81
93
 
82
94
  def raise_or_warn(on_failure)
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StrongVersions
4
+ # rubocop:disable Metrics/ClassLength
4
5
  class Dependency
5
6
  attr_reader :name, :errors
6
7
 
@@ -17,6 +18,10 @@ module StrongVersions
17
18
  Pathname.new(@dependency.gemfile) if @dependency.respond_to?(:gemfile)
18
19
  end
19
20
 
21
+ def gemspec
22
+ Pathname.new(gemspec_path) unless gemspec_path.nil?
23
+ end
24
+
20
25
  def valid?
21
26
  @errors.empty?
22
27
  end
@@ -25,9 +30,10 @@ module StrongVersions
25
30
  GemVersion.new(GemVersion.new(lockfile_version).version_string)
26
31
  end
27
32
 
28
- def suggested_definition
33
+ def suggested_definition(subject = :gemfile)
29
34
  guards = guard_versions.map { |op, version| "'#{op} #{version}'" }
30
- "gem '#{@name}', #{[suggested_version.suggestion, *guards].join(', ')}"
35
+ constraints = [suggested_version.suggestion, *guards].join(', ')
36
+ send(:"suggested_#{subject}_definition", constraints)
31
37
  end
32
38
 
33
39
  def definition
@@ -39,11 +45,38 @@ module StrongVersions
39
45
  end
40
46
 
41
47
  def updatable?
42
- !valid? && gemfile && !suggested_version.missing? && !path_source?
48
+ !valid? && !suggested_version.missing? && !path_source?
43
49
  end
44
50
 
45
51
  private
46
52
 
53
+ def gemspec_path
54
+ _spec, path = gemspec_dependency
55
+ path
56
+ end
57
+
58
+ def gemspec_spec
59
+ spec, _path = gemspec_dependency
60
+ spec
61
+ end
62
+
63
+ def gemspec_dependency
64
+ DependencyFinder.new.gemspec_dependencies.each do |path, specs|
65
+ specs.each do |spec|
66
+ return [spec, path] if spec.name == @dependency.name
67
+ end
68
+ end
69
+ nil
70
+ end
71
+
72
+ def suggested_gemspec_definition(constraints)
73
+ "spec.add_#{gemspec_spec.type}_dependency '#{@name}', #{constraints}"
74
+ end
75
+
76
+ def suggested_gemfile_definition(constraints)
77
+ "gem '#{@name}', #{constraints}"
78
+ end
79
+
47
80
  def versions
48
81
  @dependency.requirements_list.map { |version| parse_version(version) }
49
82
  end
@@ -124,4 +157,5 @@ module StrongVersions
124
157
  I18n.t("strong_versions.#{name}")
125
158
  end
126
159
  end
160
+ # rubocop:enable Metrics/ClassLength
127
161
  end
@@ -6,6 +6,12 @@ module StrongVersions
6
6
  development + runtime
7
7
  end
8
8
 
9
+ def gemspec_dependencies
10
+ Hash[gemspecs.compact.map do |gemspec|
11
+ [gemspec.loaded_from, dependencies]
12
+ end]
13
+ end
14
+
9
15
  private
10
16
 
11
17
  def development
@@ -10,14 +10,14 @@ module StrongVersions
10
10
  puts(color(string, :bright, :red))
11
11
  end
12
12
 
13
- def gem_update(path, gem)
13
+ def gem_update(path, gem, subject)
14
14
  relpath = path.relative_path_from(Pathname.new(Dir.pwd))
15
15
  output = [
16
- color("[#{relpath}] ", :cyan),
17
- color(gem.suggested_definition, :green),
18
- color(' (was: ', :default),
19
- color(gem.definition, :red),
20
- color(')', :default)
16
+ color('[', :cyan),
17
+ color(relpath.to_s, :green),
18
+ color('] ', :cyan),
19
+ color('updated: ', :default),
20
+ color(gem.suggested_definition(subject), :green)
21
21
  ].join
22
22
  puts(output)
23
23
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StrongVersions
4
- VERSION = '0.4.2'
4
+ VERSION = '0.4.3'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strong_versions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Farrell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-26 00:00:00.000000000 Z
11
+ date: 2020-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n