strong_versions 0.4.0 → 0.4.5
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 +4 -4
- data/.rubocop.yml +49 -1
- data/Makefile +3 -4
- data/README.md +6 -16
- data/bin/strong_versions +5 -3
- data/bin/strong_versions.rb +12 -9
- data/doc/images/strong-versions-example.png +0 -0
- data/lib/strong_versions.rb +3 -1
- data/lib/strong_versions/dependencies.rb +25 -16
- data/lib/strong_versions/dependency.rb +59 -36
- data/lib/strong_versions/dependency_finder.rb +6 -0
- data/lib/strong_versions/gem_version.rb +104 -0
- data/lib/strong_versions/regexes.rb +15 -0
- data/lib/strong_versions/terminal.rb +12 -12
- data/lib/strong_versions/version.rb +1 -1
- data/strong_versions.gemspec +3 -4
- metadata +11 -24
- data/lib/strong_versions/suggestion.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4e3d02b2717fbfdc7da2e7cc0d83b495e01bc6b31efae98f635abae1cf8bf837
|
4
|
+
data.tar.gz: fb28b5ddd0a45c7ca56306bcfd58013824c9949bcd723a324dde98431f0b197c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4482cf23782277e84fdbf1a3a3e9d998c5cac84202d3c21be563dc4eeb21cdd5c6ba54490ff4f2e81d85899cde8eed32e28879e3a0f861871a1cd5a45b51491
|
7
|
+
data.tar.gz: fccdb21e6f7b58966a4f6dcee95ae6c176ae7be7b5380f820b660235f7a56f80163414475e9a4799d50d369f1ab73ddd354da98ba9aba83db03eb74c82f1cce3
|
data/.rubocop.yml
CHANGED
@@ -11,4 +11,52 @@ 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'
|
19
|
+
|
20
|
+
Layout/SpaceAroundMethodCallOperator:
|
21
|
+
Enabled: true
|
22
|
+
|
23
|
+
Lint/RaiseException:
|
24
|
+
Enabled: true
|
25
|
+
|
26
|
+
Lint/StructNewOverride:
|
27
|
+
Enabled: true
|
28
|
+
|
29
|
+
Style/ExponentialNotation:
|
30
|
+
Enabled: true
|
31
|
+
|
32
|
+
Style/HashEachMethods:
|
33
|
+
Enabled: true
|
34
|
+
|
35
|
+
Style/HashTransformKeys:
|
36
|
+
Enabled: true
|
37
|
+
|
38
|
+
Style/HashTransformValues:
|
39
|
+
Enabled: true
|
40
|
+
|
41
|
+
Layout/EmptyLinesAroundAttributeAccessor:
|
42
|
+
Enabled: true
|
43
|
+
|
44
|
+
Style/SlicingWithRange:
|
45
|
+
Enabled: true
|
46
|
+
|
47
|
+
Lint/DeprecatedOpenSSLConstant:
|
48
|
+
Enabled: true
|
49
|
+
Lint/MixedRegexpCaptureTypes:
|
50
|
+
Enabled: true
|
51
|
+
Style/AccessorGrouping:
|
52
|
+
Enabled: true
|
53
|
+
Style/BisectedAttrAccessor:
|
54
|
+
Enabled: true
|
55
|
+
Style/RedundantAssignment:
|
56
|
+
Enabled: true
|
57
|
+
Style/RedundantFetchBlock:
|
58
|
+
Enabled: true
|
59
|
+
Style/RedundantRegexpCharacterClass:
|
60
|
+
Enabled: true
|
61
|
+
Style/RedundantRegexpEscape:
|
62
|
+
Enabled: true
|
data/Makefile
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,5 @@
|
|
1
1
|
# StrongVersions
|
2
2
|
|
3
|
-
```
|
4
|
-
The right thing to guide us
|
5
|
-
Is right here inside us
|
6
|
-
--Nickelback
|
7
|
-
```
|
8
|
-
|
9
3
|
# Overview
|
10
4
|
|
11
5
|
_StrongVersions_ enforces a strict policy on your `Gemfile` requirements:
|
@@ -13,13 +7,13 @@ _StrongVersions_ enforces a strict policy on your `Gemfile` requirements:
|
|
13
7
|
* The pessimistic `~>` operator must be used for all gem requirement definitions.
|
14
8
|
* If the gem version is greater than 1, the requirement format must be `major.minor`, e.g. `'~> 2.5`'
|
15
9
|
* If the gem version is less than 1, the requirement format must be `major.minor.patch`, e.g. `'~> 0.8.9'`
|
16
|
-
*
|
10
|
+
* 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
11
|
* All gems with a `path` or `git` source are ignored, e.g. `path: '/path/to/gem'`, `git: 'https://github.com/bobf/strong_versions'`
|
18
12
|
* All gems specified in the [ignore list](#ignore) are ignored.
|
19
13
|
|
20
|
-
Any gems that do not satisfy these rules will be included in
|
14
|
+
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
15
|
|
22
|
-
|
16
|
+
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
17
|
|
24
18
|

|
25
19
|
|
@@ -28,7 +22,7 @@ The benefit of applying this standard is that, if all gems follow [Semantic Vers
|
|
28
22
|
Add the gem to your `Gemfile`
|
29
23
|
|
30
24
|
```ruby
|
31
|
-
gem 'strong_versions', '~> 0.4.
|
25
|
+
gem 'strong_versions', '~> 0.4.5'
|
32
26
|
```
|
33
27
|
|
34
28
|
And rebuild your bundle:
|
@@ -37,11 +31,6 @@ And rebuild your bundle:
|
|
37
31
|
$ bundle install
|
38
32
|
```
|
39
33
|
|
40
|
-
Or install yourself:
|
41
|
-
```bash
|
42
|
-
$ gem install strong_versions -v '0.4.0'
|
43
|
-
```
|
44
|
-
|
45
34
|
## Usage
|
46
35
|
|
47
36
|
_StrongVersions_ is invoked with a provided executable:
|
@@ -54,7 +43,7 @@ The executable will output all non-passing gems and will return an exit code of
|
|
54
43
|
|
55
44
|

|
56
45
|
|
57
|
-
|
46
|
+
Auto-correct is available with the `-a/--auto-correct` option:
|
58
47
|
```bash
|
59
48
|
$ bundle exec strong_versions -a
|
60
49
|
```
|
@@ -69,6 +58,7 @@ ignore:
|
|
69
58
|
- rails
|
70
59
|
```
|
71
60
|
|
61
|
+
Gems in the ignore list will not be updated when using the `-a/--auto-correct` option.
|
72
62
|
## Contributing
|
73
63
|
|
74
64
|
Fork and create a pull request.
|
data/bin/strong_versions
CHANGED
@@ -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
|
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
|
20
|
+
opts.on('--no-auto-correct', 'Disable auto-correct') do
|
20
21
|
options[:auto_correct] = false
|
21
22
|
end
|
22
23
|
end.parse!
|
@@ -33,11 +34,12 @@ validated = StrongVersions::Dependencies.new(dependencies).validate!(
|
|
33
34
|
auto_correct: options[:auto_correct]
|
34
35
|
)
|
35
36
|
|
37
|
+
exit 0 if validated
|
38
|
+
|
36
39
|
if options[:auto_correct]
|
37
40
|
# Re-evaluate
|
38
41
|
args = original_args.map { |arg| Shellwords.escape(arg) }.join(' ')
|
39
42
|
exec "#{$PROGRAM_NAME} #{args} --no-auto-correct"
|
40
43
|
end
|
41
44
|
|
42
|
-
exit 0 if validated
|
43
45
|
exit 1
|
data/bin/strong_versions.rb
CHANGED
@@ -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 =
|
9
|
+
opts.banner = 'Usage: strong_versions [options]'
|
8
10
|
|
9
|
-
opts.on(
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
37
|
+
exit 0 if validated || revalidated
|
34
38
|
exit 1
|
35
|
-
|
Binary file
|
data/lib/strong_versions.rb
CHANGED
@@ -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'
|
@@ -10,8 +11,9 @@ require 'strong_versions/dependency'
|
|
10
11
|
require 'strong_versions/dependency_finder'
|
11
12
|
require 'strong_versions/dependencies'
|
12
13
|
require 'strong_versions/errors'
|
13
|
-
require 'strong_versions/suggestion'
|
14
14
|
require 'strong_versions/terminal'
|
15
|
+
require 'strong_versions/gem_version'
|
16
|
+
require 'strong_versions/regexes'
|
15
17
|
require 'strong_versions/version'
|
16
18
|
|
17
19
|
module StrongVersions
|
@@ -17,7 +17,7 @@ module StrongVersions
|
|
17
17
|
return true
|
18
18
|
end
|
19
19
|
|
20
|
-
return
|
20
|
+
return update_definitions(options.fetch(:except, [])) if auto_correct
|
21
21
|
|
22
22
|
raise_or_warn(options.fetch(:on_failure, 'raise'))
|
23
23
|
summary
|
@@ -45,38 +45,47 @@ module StrongVersions
|
|
45
45
|
@terminal.summary(@dependencies.size, @invalid_gems.size)
|
46
46
|
end
|
47
47
|
|
48
|
-
def
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
def updatable_dependencies(except)
|
49
|
+
@dependencies.reject { |dependency| except.include?(dependency.name) }
|
50
|
+
.select(&:updatable?)
|
51
|
+
end
|
52
52
|
|
53
|
-
|
53
|
+
def update_definitions(except)
|
54
|
+
@terminal.update_summary(update(:gemfile, except) + update(:gemspec, except))
|
55
|
+
end
|
56
|
+
|
57
|
+
def update(subject, except)
|
58
|
+
updatable_dependencies(except).reduce(0) do |count, dependency|
|
59
|
+
update_dependency(subject, dependency) ? count : count + 1
|
54
60
|
end
|
55
|
-
@terminal.update_summary(updated)
|
56
61
|
end
|
57
62
|
|
58
|
-
def update_dependency(dependency)
|
59
|
-
path = dependency.
|
63
|
+
def update_dependency(subject, dependency)
|
64
|
+
path = dependency.public_send(subject)
|
65
|
+
return if path.nil?
|
66
|
+
|
60
67
|
content = File.read(path)
|
61
|
-
update = replace_gem_definition(dependency, content)
|
68
|
+
update = replace_gem_definition(subject, dependency, content)
|
62
69
|
return false if content == update
|
63
70
|
|
64
71
|
File.write(path, update)
|
65
|
-
@terminal.gem_update(path, dependency)
|
72
|
+
@terminal.gem_update(path, dependency, subject)
|
66
73
|
true
|
67
74
|
end
|
68
75
|
|
69
|
-
def replace_gem_definition(dependency, content)
|
70
|
-
regex = gem_regex(dependency.name)
|
76
|
+
def replace_gem_definition(subject, dependency, content)
|
77
|
+
regex = gem_regex(subject, dependency.name)
|
71
78
|
match = content.match(regex)
|
72
79
|
return content unless match
|
73
80
|
|
81
|
+
# For gemspec, indent includes the `spec.` or `s.` prefix.
|
74
82
|
indent = match.captures.first
|
75
|
-
|
83
|
+
definition = dependency.suggested_definition(subject)
|
84
|
+
content.gsub(regex, "#{indent}#{definition}")
|
76
85
|
end
|
77
86
|
|
78
|
-
def gem_regex(name)
|
79
|
-
|
87
|
+
def gem_regex(subject, name)
|
88
|
+
Regexes.public_send(subject, name)
|
80
89
|
end
|
81
90
|
|
82
91
|
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
|
|
@@ -13,37 +14,73 @@ module StrongVersions
|
|
13
14
|
versions.each { |operator, version| validate_version(operator, version) }
|
14
15
|
end
|
15
16
|
|
17
|
+
def to_s
|
18
|
+
"#<StrongVersions::Dependency name=#{@dependency.name}>"
|
19
|
+
end
|
20
|
+
|
16
21
|
def gemfile
|
17
22
|
Pathname.new(@dependency.gemfile) if @dependency.respond_to?(:gemfile)
|
18
23
|
end
|
19
24
|
|
25
|
+
def gemspec
|
26
|
+
Pathname.new(gemspec_path) unless gemspec_path.nil?
|
27
|
+
end
|
28
|
+
|
20
29
|
def valid?
|
21
30
|
@errors.empty?
|
22
31
|
end
|
23
32
|
|
24
|
-
def
|
25
|
-
|
33
|
+
def suggested_version
|
34
|
+
GemVersion.new(GemVersion.new(lockfile_version).version_string)
|
26
35
|
end
|
27
36
|
|
28
|
-
def suggested_definition
|
37
|
+
def suggested_definition(subject = :gemfile)
|
29
38
|
guards = guard_versions.map { |op, version| "'#{op} #{version}'" }
|
30
|
-
|
39
|
+
constraints = [suggested_version.suggestion, *guards].join(', ')
|
40
|
+
send(:"suggested_#{subject}_definition", constraints)
|
31
41
|
end
|
32
42
|
|
33
43
|
def definition
|
34
44
|
versions.map do |operator, version|
|
35
|
-
next t('version_not_specified') if operator == '>=' && version
|
45
|
+
next t('version_not_specified') if operator == '>=' && version.zero?
|
36
46
|
|
37
47
|
"'#{operator} #{version}'"
|
38
48
|
end.join(', ')
|
39
49
|
end
|
40
50
|
|
41
51
|
def updatable?
|
42
|
-
|
52
|
+
!valid? && !suggested_version.missing? && !path_source?
|
43
53
|
end
|
44
54
|
|
45
55
|
private
|
46
56
|
|
57
|
+
def gemspec_path
|
58
|
+
_spec, path = gemspec_dependency
|
59
|
+
path
|
60
|
+
end
|
61
|
+
|
62
|
+
def gemspec_spec
|
63
|
+
spec, _path = gemspec_dependency
|
64
|
+
spec
|
65
|
+
end
|
66
|
+
|
67
|
+
def gemspec_dependency
|
68
|
+
DependencyFinder.new.gemspec_dependencies.each do |path, specs|
|
69
|
+
specs.each do |spec|
|
70
|
+
return [spec, path] if spec.name == @dependency.name
|
71
|
+
end
|
72
|
+
end
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def suggested_gemspec_definition(constraints)
|
77
|
+
"add_#{gemspec_spec.type}_dependency '#{@name}', #{constraints}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def suggested_gemfile_definition(constraints)
|
81
|
+
"gem '#{@name}', #{constraints}"
|
82
|
+
end
|
83
|
+
|
47
84
|
def versions
|
48
85
|
@dependency.requirements_list.map { |version| parse_version(version) }
|
49
86
|
end
|
@@ -54,13 +91,13 @@ module StrongVersions
|
|
54
91
|
|
55
92
|
def parse_version(requirement)
|
56
93
|
operator, version_obj = Gem::Requirement.parse(requirement)
|
57
|
-
[operator,
|
94
|
+
[operator, GemVersion.new(version_obj)]
|
58
95
|
end
|
59
96
|
|
60
97
|
def lockfile_version
|
61
98
|
@lockfile_version ||= begin
|
62
99
|
gem_spec = @lockfile.specs.find { |spec| spec.name == @name }
|
63
|
-
gem_spec.nil? ? nil :
|
100
|
+
gem_spec.nil? ? nil : gem_spec.version
|
64
101
|
end
|
65
102
|
end
|
66
103
|
|
@@ -68,19 +105,11 @@ module StrongVersions
|
|
68
105
|
Bundler::LockfileParser.new(Bundler.read_file(Bundler.default_lockfile))
|
69
106
|
end
|
70
107
|
|
71
|
-
def version(version_obj)
|
72
|
-
# Ruby >= 2.3.0: `version_obj` is a `Gem::Version`
|
73
|
-
return version_obj.version if version_obj.respond_to?(:version)
|
74
|
-
|
75
|
-
# Ruby < 2.3.0: `version_obj` is a `String`
|
76
|
-
version_obj
|
77
|
-
end
|
78
|
-
|
79
108
|
def validate_version(operator, version)
|
80
109
|
return if path_source?
|
81
110
|
return if any_valid?
|
82
111
|
|
83
|
-
check_pessimistic(operator)
|
112
|
+
check_pessimistic(operator) unless version.zero?
|
84
113
|
check_valid_version(version)
|
85
114
|
end
|
86
115
|
|
@@ -91,41 +120,34 @@ module StrongVersions
|
|
91
120
|
end
|
92
121
|
|
93
122
|
def check_valid_version(version)
|
94
|
-
return if
|
123
|
+
return if version.valid?
|
95
124
|
|
96
|
-
value = version
|
125
|
+
value = version.zero? ? t('version_not_specified') : version
|
97
126
|
@errors << { type: :version, value: value }
|
98
127
|
end
|
99
128
|
|
100
129
|
def redundant?(operator, version)
|
101
|
-
return
|
130
|
+
return true if pessimistic?(operator)
|
131
|
+
return false if guard_needed?(operator, version)
|
102
132
|
|
103
|
-
|
133
|
+
true
|
104
134
|
end
|
105
135
|
|
106
|
-
def
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end.sum
|
136
|
+
def guard_needed?(operator, version)
|
137
|
+
return false unless %w[< <= > >=].include?(operator)
|
138
|
+
return true if %(< <=).include?(operator) && suggested_version < version
|
139
|
+
return true if %(> >=).include?(operator) && suggested_version < version
|
140
|
+
|
141
|
+
false
|
113
142
|
end
|
114
143
|
|
115
144
|
def pessimistic?(operator)
|
116
145
|
operator == '~>'
|
117
146
|
end
|
118
147
|
|
119
|
-
def valid_version?(version)
|
120
|
-
return true if version =~ /^[1-9][0-9]*\.\d+$/ # major.minor, e.g. "2.5"
|
121
|
-
return true if version =~ /^0\.\d+\.\d+$/ # 0.minor.patch, e.g. "0.1.8"
|
122
|
-
|
123
|
-
false
|
124
|
-
end
|
125
|
-
|
126
148
|
def any_valid?
|
127
149
|
versions.any? do |operator, version|
|
128
|
-
pessimistic?(operator) &&
|
150
|
+
pessimistic?(operator) && version.valid?
|
129
151
|
end
|
130
152
|
end
|
131
153
|
|
@@ -139,4 +161,5 @@ module StrongVersions
|
|
139
161
|
I18n.t("strong_versions.#{name}")
|
140
162
|
end
|
141
163
|
end
|
164
|
+
# rubocop:enable Metrics/ClassLength
|
142
165
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StrongVersions
|
4
|
+
class GemVersion
|
5
|
+
def initialize(version)
|
6
|
+
@version = normalize(version) || ''
|
7
|
+
@parts = @version&.split('.')
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
@version
|
12
|
+
end
|
13
|
+
|
14
|
+
def zero?
|
15
|
+
@version == '0'
|
16
|
+
end
|
17
|
+
|
18
|
+
def suggestion
|
19
|
+
return '' if version_string.empty?
|
20
|
+
|
21
|
+
"'~> #{version_string}'"
|
22
|
+
end
|
23
|
+
|
24
|
+
def version_string
|
25
|
+
return '' unless standard?
|
26
|
+
|
27
|
+
major, minor, patch = @parts
|
28
|
+
return "#{major}.#{minor}" if stable?
|
29
|
+
return "#{major}.#{minor}.#{patch}" if unstable?
|
30
|
+
|
31
|
+
raise 'Unexpected condition met'
|
32
|
+
end
|
33
|
+
|
34
|
+
def <(other)
|
35
|
+
numeric < other.numeric
|
36
|
+
end
|
37
|
+
|
38
|
+
def <=(other)
|
39
|
+
numeric <= other.numeric
|
40
|
+
end
|
41
|
+
|
42
|
+
def >(other)
|
43
|
+
numeric > other.numeric
|
44
|
+
end
|
45
|
+
|
46
|
+
def >=(other)
|
47
|
+
numeric >= other.numeric
|
48
|
+
end
|
49
|
+
|
50
|
+
def numeric
|
51
|
+
# Support extremely precise versions e.g. '1.2.3.4.5.6.7.8.9'
|
52
|
+
components = @version.split('.').map(&:to_i)
|
53
|
+
components += [0] * (10 - components.size)
|
54
|
+
components.reverse.each_with_index.map do |component, index|
|
55
|
+
component * 10.pow(index + 1)
|
56
|
+
end.sum
|
57
|
+
end
|
58
|
+
|
59
|
+
def valid?
|
60
|
+
return true if @version =~ /^[1-9][0-9]*\.\d+$/ # major.minor, e.g. "2.5"
|
61
|
+
return true if @version =~ /^0\.\d+\.\d+$/ # 0.minor.patch, e.g. "0.1.8"
|
62
|
+
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
def missing?
|
67
|
+
return false if stable?
|
68
|
+
return false if unstable?
|
69
|
+
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def normalize(version)
|
76
|
+
# Ruby >= 2.3.0: `version_obj` is a `Gem::Version`
|
77
|
+
return version.version.to_s if version.respond_to?(:version)
|
78
|
+
|
79
|
+
# Ruby < 2.3.0: `version_obj` is a `String`
|
80
|
+
version
|
81
|
+
end
|
82
|
+
|
83
|
+
def unstable?
|
84
|
+
standard? && @parts.first.to_i.zero?
|
85
|
+
end
|
86
|
+
|
87
|
+
def stable?
|
88
|
+
standard? && @parts.first.to_i >= 1
|
89
|
+
end
|
90
|
+
|
91
|
+
def standard?(parts = @parts)
|
92
|
+
return false if parts.nil?
|
93
|
+
return false unless numeric?
|
94
|
+
return true if [2, 3, 4].include?(parts.size)
|
95
|
+
return true if parts.size == 3
|
96
|
+
|
97
|
+
false
|
98
|
+
end
|
99
|
+
|
100
|
+
def numeric?
|
101
|
+
@parts.all? { |part| part =~ /\A[0-9]+\Z/ }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StrongVersions
|
4
|
+
module Regexes
|
5
|
+
class << self
|
6
|
+
def gemfile(name)
|
7
|
+
/^(\s*)gem\s+['"]#{name}['"].*$/
|
8
|
+
end
|
9
|
+
|
10
|
+
def gemspec(name)
|
11
|
+
/^(\s*[A-Za-z]+\.)add_[a-z_]*_?dependency\s*\(?\s*['"]#{name}['"].*$/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -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(
|
17
|
-
color(
|
18
|
-
color('
|
19
|
-
color(
|
20
|
-
color(
|
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
|
@@ -77,10 +77,9 @@ module StrongVersions
|
|
77
77
|
type = t("errors.#{error[:type]}")
|
78
78
|
color(
|
79
79
|
' %{type} %{example}, found: %{found}',
|
80
|
-
:default,
|
81
|
-
|
82
|
-
|
83
|
-
found: [error[:value], :red]
|
80
|
+
:default, type: [type, :default],
|
81
|
+
example: example(error[:type]),
|
82
|
+
found: [error[:value], :red]
|
84
83
|
)
|
85
84
|
end
|
86
85
|
end
|
@@ -92,10 +91,11 @@ module StrongVersions
|
|
92
91
|
end
|
93
92
|
|
94
93
|
def suggestion_definition(gem)
|
95
|
-
|
94
|
+
version = gem.suggested_version.suggestion
|
95
|
+
unidentified = version.empty?
|
96
96
|
return [t('no-suggestion'), :yellow] if unidentified
|
97
97
|
|
98
|
-
[
|
98
|
+
[version, :green]
|
99
99
|
end
|
100
100
|
|
101
101
|
def name_and_definition(gem)
|
data/strong_versions.gemspec
CHANGED
@@ -28,14 +28,13 @@ Gem::Specification.new do |spec|
|
|
28
28
|
# stop supporting Rails 4 we need to support I18n 0.x and 1.x. At some point,
|
29
29
|
# I will do a release that is locked to '~> 1.0' and Rails 4 users can use
|
30
30
|
# an older version of the gem but we are not quite there yet.
|
31
|
-
spec.
|
31
|
+
spec.add_runtime_dependency 'i18n', '>= 0.5'
|
32
32
|
spec.add_dependency 'paint', '~> 2.0'
|
33
33
|
|
34
|
-
spec.add_development_dependency 'betterp', '~> 0.1.2'
|
35
34
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
36
|
-
spec.add_development_dependency '
|
35
|
+
spec.add_development_dependency 'devpack', '~> 0.1.1'
|
37
36
|
spec.add_development_dependency 'rake', '~> 10.0'
|
38
37
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
39
38
|
spec.add_development_dependency 'rspec-its', '~> 1.2'
|
40
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
39
|
+
spec.add_development_dependency 'rubocop', '~> 0.87.1'
|
41
40
|
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.
|
4
|
+
version: 0.4.5
|
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-
|
11
|
+
date: 2020-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: i18n
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.5
|
19
|
+
version: '0.5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.5
|
26
|
+
version: '0.5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: paint
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,20 +38,6 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: betterp
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.2
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1.2
|
55
41
|
- !ruby/object:Gem::Dependency
|
56
42
|
name: bundler
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,19 +53,19 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '1.16'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
56
|
+
name: devpack
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
59
|
- - "~>"
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: 0.1.1
|
76
62
|
type: :development
|
77
63
|
prerelease: false
|
78
64
|
version_requirements: !ruby/object:Gem::Requirement
|
79
65
|
requirements:
|
80
66
|
- - "~>"
|
81
67
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
68
|
+
version: 0.1.1
|
83
69
|
- !ruby/object:Gem::Dependency
|
84
70
|
name: rake
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -128,14 +114,14 @@ dependencies:
|
|
128
114
|
requirements:
|
129
115
|
- - "~>"
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: 0.
|
117
|
+
version: 0.87.1
|
132
118
|
type: :development
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
122
|
- - "~>"
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: 0.
|
124
|
+
version: 0.87.1
|
139
125
|
description: Ensure your gems are appropriately versioned
|
140
126
|
email:
|
141
127
|
- oss@bob.frl
|
@@ -171,7 +157,8 @@ files:
|
|
171
157
|
- lib/strong_versions/dependency.rb
|
172
158
|
- lib/strong_versions/dependency_finder.rb
|
173
159
|
- lib/strong_versions/errors.rb
|
174
|
-
- lib/strong_versions/
|
160
|
+
- lib/strong_versions/gem_version.rb
|
161
|
+
- lib/strong_versions/regexes.rb
|
175
162
|
- lib/strong_versions/terminal.rb
|
176
163
|
- lib/strong_versions/version.rb
|
177
164
|
- strong_versions.gemspec
|
@@ -1,59 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module StrongVersions
|
4
|
-
class Suggestion
|
5
|
-
def initialize(version)
|
6
|
-
return if version.nil?
|
7
|
-
|
8
|
-
@parts = version.split('.')
|
9
|
-
# Treat '4.3.2.1' as '4.3.2'
|
10
|
-
@parts.pop if standard?(@parts.first(3)) && @parts.size == 4
|
11
|
-
end
|
12
|
-
|
13
|
-
def to_s
|
14
|
-
return version.to_s if version.nil?
|
15
|
-
|
16
|
-
"'~> #{version}'"
|
17
|
-
end
|
18
|
-
|
19
|
-
def version
|
20
|
-
return nil unless standard?
|
21
|
-
|
22
|
-
major, minor, patch = @parts
|
23
|
-
return "#{major}.#{minor}" if stable?
|
24
|
-
return "#{major}.#{minor}.#{patch}" if unstable?
|
25
|
-
|
26
|
-
raise 'Unexpected condition met'
|
27
|
-
end
|
28
|
-
|
29
|
-
def missing?
|
30
|
-
return false if stable?
|
31
|
-
return false if unstable?
|
32
|
-
|
33
|
-
true
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def unstable?
|
39
|
-
standard? && @parts.first.to_i.zero?
|
40
|
-
end
|
41
|
-
|
42
|
-
def stable?
|
43
|
-
standard? && @parts.first.to_i >= 1
|
44
|
-
end
|
45
|
-
|
46
|
-
def standard?(parts = @parts)
|
47
|
-
return false if parts.nil?
|
48
|
-
return false unless numeric?
|
49
|
-
return true if [2, 3].include?(parts.size)
|
50
|
-
return true if parts.size == 3 && unstable?
|
51
|
-
|
52
|
-
false
|
53
|
-
end
|
54
|
-
|
55
|
-
def numeric?
|
56
|
-
@parts.all? { |part| part =~ /\A[0-9]+\Z/ }
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|