semverve 0.2.1 → 0.4.0
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/CONTRIBUTING.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +166 -32
- data/UPGRADING.md +78 -0
- data/lib/semverve/adapters.rb +292 -0
- data/lib/semverve/configuration.rb +64 -39
- data/lib/semverve/finding.rb +55 -0
- data/lib/semverve/fix_result.rb +39 -0
- data/lib/semverve/{version_metadata.rb → package_metadata.rb} +36 -116
- data/lib/semverve/presets.rb +4 -100
- data/lib/semverve/project_metadata.rb +8 -5
- data/lib/semverve/rails_config_metadata.rb +176 -0
- data/lib/semverve/railtie.rb +1 -1
- data/lib/semverve/task.rb +166 -114
- data/lib/semverve/version.rb +2 -2
- data/lib/semverve/version_checks.rb +518 -0
- data/lib/semverve/version_code_references.rb +53 -89
- data/lib/semverve/version_literal_rewriter.rb +78 -0
- data/lib/semverve/version_match_policy.rb +62 -0
- data/lib/semverve/version_references.rb +32 -88
- data/lib/semverve.rb +4 -0
- metadata +10 -2
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "bundler"
|
|
4
3
|
require "rubygems"
|
|
5
4
|
|
|
5
|
+
require_relative "finding"
|
|
6
|
+
require_relative "fix_result"
|
|
6
7
|
require_relative "semantic_version"
|
|
7
8
|
|
|
8
9
|
module Semverve
|
|
9
10
|
##
|
|
10
|
-
# Checks generated
|
|
11
|
-
class
|
|
11
|
+
# Checks generated package metadata against the configured version file.
|
|
12
|
+
class PackageMetadata
|
|
12
13
|
##
|
|
13
14
|
# Literal gemspec version assignments that can be safely rewritten.
|
|
14
15
|
#
|
|
@@ -16,117 +17,29 @@ module Semverve
|
|
|
16
17
|
GEMSPEC_LITERAL_PATTERN = /^(\s*\w+\.version\s*=\s*)(["'])(\d+\.\d+\.\d+)(\2)/
|
|
17
18
|
|
|
18
19
|
##
|
|
19
|
-
#
|
|
20
|
-
class Finding
|
|
21
|
-
##
|
|
22
|
-
# Path relative to the configured project root.
|
|
23
|
-
#
|
|
24
|
-
# @return [String]
|
|
25
|
-
attr_reader :path
|
|
26
|
-
|
|
27
|
-
##
|
|
28
|
-
# One-based line number.
|
|
29
|
-
#
|
|
30
|
-
# @return [Integer]
|
|
31
|
-
attr_reader :line
|
|
32
|
-
|
|
33
|
-
##
|
|
34
|
-
# One-based column number.
|
|
35
|
-
#
|
|
36
|
-
# @return [Integer]
|
|
37
|
-
attr_reader :column
|
|
38
|
-
|
|
39
|
-
##
|
|
40
|
-
# Metadata semantic version.
|
|
41
|
-
#
|
|
42
|
-
# @return [Semverve::SemanticVersion]
|
|
43
|
-
attr_reader :version
|
|
44
|
-
|
|
45
|
-
##
|
|
46
|
-
# Output label for the finding.
|
|
47
|
-
#
|
|
48
|
-
# @return [String]
|
|
49
|
-
attr_reader :label
|
|
50
|
-
|
|
51
|
-
##
|
|
52
|
-
# Initializes a finding.
|
|
53
|
-
#
|
|
54
|
-
# @param [String] path
|
|
55
|
-
# @param [Integer] line
|
|
56
|
-
# @param [Integer] column
|
|
57
|
-
# @param [Semverve::SemanticVersion] version
|
|
58
|
-
# @param [String] label
|
|
59
|
-
#
|
|
60
|
-
# @return [Semverve::VersionMetadata::Finding]
|
|
61
|
-
def initialize(path:, line:, column:, version:, label:)
|
|
62
|
-
@path = path
|
|
63
|
-
@line = line
|
|
64
|
-
@column = column
|
|
65
|
-
@version = version
|
|
66
|
-
@label = label
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
##
|
|
71
|
-
# Result of fixing metadata version mismatches.
|
|
72
|
-
class FixResult
|
|
73
|
-
##
|
|
74
|
-
# Files changed by the fix.
|
|
75
|
-
#
|
|
76
|
-
# @return [Array<String>]
|
|
77
|
-
attr_reader :changed_files
|
|
78
|
-
|
|
79
|
-
##
|
|
80
|
-
# Number of literal replacements made.
|
|
81
|
-
#
|
|
82
|
-
# @return [Integer]
|
|
83
|
-
attr_reader :replacement_count
|
|
84
|
-
|
|
85
|
-
##
|
|
86
|
-
# Whether bundle lock was run.
|
|
87
|
-
#
|
|
88
|
-
# @return [Boolean]
|
|
89
|
-
attr_reader :bundle_lock_ran
|
|
90
|
-
|
|
91
|
-
##
|
|
92
|
-
# Initializes a fix result.
|
|
93
|
-
#
|
|
94
|
-
# @param [Array<String>] changed_files
|
|
95
|
-
# @param [Integer] replacement_count
|
|
96
|
-
# @param [Boolean] bundle_lock_ran
|
|
97
|
-
#
|
|
98
|
-
# @return [Semverve::VersionMetadata::FixResult]
|
|
99
|
-
def initialize(changed_files:, replacement_count:, bundle_lock_ran:)
|
|
100
|
-
@changed_files = changed_files
|
|
101
|
-
@replacement_count = replacement_count
|
|
102
|
-
@bundle_lock_ran = bundle_lock_ran
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
##
|
|
107
|
-
# Initializes metadata version checking.
|
|
20
|
+
# Initializes package metadata version checking.
|
|
108
21
|
#
|
|
109
22
|
# @param [Semverve::ResolvedConfiguration] configuration
|
|
110
23
|
# @param [Semverve::SemanticVersion] current_version
|
|
111
24
|
#
|
|
112
|
-
# @return [Semverve::
|
|
25
|
+
# @return [Semverve::PackageMetadata]
|
|
113
26
|
def initialize(configuration, current_version)
|
|
114
27
|
@configuration = configuration
|
|
115
28
|
@current_version = current_version
|
|
116
29
|
end
|
|
117
30
|
|
|
118
31
|
##
|
|
119
|
-
#
|
|
32
|
+
# Package metadata mismatches.
|
|
120
33
|
#
|
|
121
|
-
# @return [Array<Semverve::
|
|
34
|
+
# @return [Array<Semverve::Finding>]
|
|
122
35
|
def findings
|
|
123
36
|
[gemspec_finding, lockfile_finding].compact
|
|
124
37
|
end
|
|
125
38
|
|
|
126
39
|
##
|
|
127
|
-
# Fixes safe metadata mismatches.
|
|
40
|
+
# Fixes safe package metadata mismatches.
|
|
128
41
|
#
|
|
129
|
-
# @return [Semverve::
|
|
42
|
+
# @return [Semverve::FixResult]
|
|
130
43
|
def fix
|
|
131
44
|
changed_files = []
|
|
132
45
|
replacement_count = fix_gemspec_literal
|
|
@@ -135,7 +48,7 @@ module Semverve
|
|
|
135
48
|
|
|
136
49
|
bundle_lock_ran = lockfile_finding ? run_bundle_lock : false
|
|
137
50
|
|
|
138
|
-
FixResult.new(
|
|
51
|
+
Semverve::FixResult.new(
|
|
139
52
|
changed_files: changed_files,
|
|
140
53
|
replacement_count: replacement_count,
|
|
141
54
|
bundle_lock_ran: bundle_lock_ran
|
|
@@ -151,7 +64,7 @@ module Semverve
|
|
|
151
64
|
attr_reader :configuration
|
|
152
65
|
|
|
153
66
|
##
|
|
154
|
-
# Current
|
|
67
|
+
# Current package version.
|
|
155
68
|
#
|
|
156
69
|
# @return [Semverve::SemanticVersion]
|
|
157
70
|
attr_reader :current_version
|
|
@@ -167,14 +80,14 @@ module Semverve
|
|
|
167
80
|
##
|
|
168
81
|
# Finding for a gemspec mismatch.
|
|
169
82
|
#
|
|
170
|
-
# @return [Semverve::
|
|
83
|
+
# @return [Semverve::Finding, nil]
|
|
171
84
|
def gemspec_finding
|
|
172
85
|
return unless gemspec_file && gemspec_version
|
|
173
86
|
return if gemspec_version == current_version
|
|
174
87
|
|
|
175
88
|
line, column = gemspec_position
|
|
176
89
|
|
|
177
|
-
Finding.new(
|
|
90
|
+
Semverve::Finding.new(
|
|
178
91
|
path: relative_path(gemspec_file),
|
|
179
92
|
line: line,
|
|
180
93
|
column: column,
|
|
@@ -186,7 +99,7 @@ module Semverve
|
|
|
186
99
|
##
|
|
187
100
|
# Finding for a lockfile mismatch.
|
|
188
101
|
#
|
|
189
|
-
# @return [Semverve::
|
|
102
|
+
# @return [Semverve::Finding, nil]
|
|
190
103
|
def lockfile_finding
|
|
191
104
|
return unless File.file?(lockfile_path)
|
|
192
105
|
|
|
@@ -196,7 +109,7 @@ module Semverve
|
|
|
196
109
|
|
|
197
110
|
line, column = lockfile_position(version)
|
|
198
111
|
|
|
199
|
-
Finding.new(
|
|
112
|
+
Semverve::Finding.new(
|
|
200
113
|
path: "Gemfile.lock",
|
|
201
114
|
line: line,
|
|
202
115
|
column: column,
|
|
@@ -210,6 +123,8 @@ module Semverve
|
|
|
210
123
|
#
|
|
211
124
|
# @return [String, nil]
|
|
212
125
|
def gemspec_file
|
|
126
|
+
return unless configuration.gem_name
|
|
127
|
+
|
|
213
128
|
@gemspec_file ||= begin
|
|
214
129
|
files = Dir.glob(File.join(root, "*.gemspec"))
|
|
215
130
|
|
|
@@ -271,18 +186,14 @@ module Semverve
|
|
|
271
186
|
#
|
|
272
187
|
# @return [Semverve::SemanticVersion, nil]
|
|
273
188
|
def lockfile_version
|
|
274
|
-
|
|
275
|
-
return unless spec
|
|
189
|
+
return unless configuration.gem_name
|
|
276
190
|
|
|
277
|
-
|
|
278
|
-
|
|
191
|
+
File.readlines(lockfile_path).each do |line|
|
|
192
|
+
match = line.match(lockfile_line_pattern)
|
|
193
|
+
return SemanticVersion.parse(match[:version]) if match
|
|
194
|
+
end
|
|
279
195
|
|
|
280
|
-
|
|
281
|
-
# Parsed Gemfile.lock.
|
|
282
|
-
#
|
|
283
|
-
# @return [Bundler::LockfileParser]
|
|
284
|
-
def lockfile_parser
|
|
285
|
-
Bundler::LockfileParser.new(File.read(lockfile_path))
|
|
196
|
+
nil
|
|
286
197
|
end
|
|
287
198
|
|
|
288
199
|
##
|
|
@@ -292,16 +203,25 @@ module Semverve
|
|
|
292
203
|
#
|
|
293
204
|
# @return [Array(Integer, Integer)]
|
|
294
205
|
def lockfile_position(version)
|
|
295
|
-
pattern = /^\s*#{Regexp.escape(configuration.gem_name)}\s+\(#{Regexp.escape(version.to_s)}\)/
|
|
296
|
-
|
|
297
206
|
File.readlines(lockfile_path).each_with_index do |line, index|
|
|
298
|
-
match = line.match(
|
|
207
|
+
match = line.match(lockfile_line_pattern(version))
|
|
299
208
|
return [index + 1, line.index(version.to_s) + 1] if match
|
|
300
209
|
end
|
|
301
210
|
|
|
302
211
|
[1, 1]
|
|
303
212
|
end
|
|
304
213
|
|
|
214
|
+
##
|
|
215
|
+
# Gemfile.lock line pattern for the configured package.
|
|
216
|
+
#
|
|
217
|
+
# @param [Semverve::SemanticVersion, nil] version
|
|
218
|
+
#
|
|
219
|
+
# @return [Regexp]
|
|
220
|
+
def lockfile_line_pattern(version = nil)
|
|
221
|
+
version_pattern = version ? Regexp.escape(version.to_s) : "\\d+\\.\\d+\\.\\d+"
|
|
222
|
+
/^\s*#{Regexp.escape(configuration.gem_name)}\s+\((?<version>#{version_pattern})\)/
|
|
223
|
+
end
|
|
224
|
+
|
|
305
225
|
##
|
|
306
226
|
# Fixes a literal gemspec version assignment.
|
|
307
227
|
#
|
data/lib/semverve/presets.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative "
|
|
3
|
+
require_relative "adapters"
|
|
4
4
|
|
|
5
5
|
module Semverve
|
|
6
6
|
##
|
|
7
|
-
#
|
|
7
|
+
# Backward-compatible framework preset lookup.
|
|
8
8
|
module Presets
|
|
9
9
|
##
|
|
10
10
|
# Returns defaults for a configured preset.
|
|
@@ -14,9 +14,7 @@ module Semverve
|
|
|
14
14
|
#
|
|
15
15
|
# @return [Hash]
|
|
16
16
|
def self.defaults_for(name, configuration)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
fetch(name).defaults(configuration)
|
|
17
|
+
Adapters.defaults_for(name, configuration)
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
##
|
|
@@ -26,101 +24,7 @@ module Semverve
|
|
|
26
24
|
#
|
|
27
25
|
# @return [#name, #defaults]
|
|
28
26
|
def self.fetch(name)
|
|
29
|
-
|
|
30
|
-
when :rails
|
|
31
|
-
Rails.new
|
|
32
|
-
else
|
|
33
|
-
raise Error, "Unknown preset #{name.inspect}. Use :rails."
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
##
|
|
38
|
-
# Rails application defaults.
|
|
39
|
-
class Rails
|
|
40
|
-
##
|
|
41
|
-
# Preset name.
|
|
42
|
-
#
|
|
43
|
-
# @return [Symbol]
|
|
44
|
-
def name
|
|
45
|
-
:rails
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
##
|
|
49
|
-
# Rails-specific Semverve defaults.
|
|
50
|
-
#
|
|
51
|
-
# @param [Semverve::Configuration] _configuration
|
|
52
|
-
#
|
|
53
|
-
# @return [Hash]
|
|
54
|
-
def defaults(_configuration)
|
|
55
|
-
root = rails_root || Dir.pwd
|
|
56
|
-
|
|
57
|
-
{
|
|
58
|
-
format: :simple,
|
|
59
|
-
module_name: rails_module_name || project_module_name(root),
|
|
60
|
-
root: root,
|
|
61
|
-
version_file: File.join("config", "version.rb")
|
|
62
|
-
}
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
|
-
##
|
|
68
|
-
# Rails.root when Rails is available.
|
|
69
|
-
#
|
|
70
|
-
# @return [String, nil]
|
|
71
|
-
def rails_root
|
|
72
|
-
return unless rails_defined?
|
|
73
|
-
return unless ::Rails.respond_to?(:root)
|
|
74
|
-
return unless ::Rails.root
|
|
75
|
-
|
|
76
|
-
::Rails.root.to_s
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
##
|
|
80
|
-
# Application module name inferred from Rails.application.
|
|
81
|
-
#
|
|
82
|
-
# @return [String, nil]
|
|
83
|
-
def rails_module_name
|
|
84
|
-
return unless rails_defined?
|
|
85
|
-
return unless ::Rails.respond_to?(:application)
|
|
86
|
-
return unless ::Rails.application
|
|
87
|
-
|
|
88
|
-
application_class = ::Rails.application.class
|
|
89
|
-
return application_class.module_parent_name if application_class.respond_to?(:module_parent_name)
|
|
90
|
-
|
|
91
|
-
class_name = application_class.name
|
|
92
|
-
return unless class_name&.include?("::")
|
|
93
|
-
|
|
94
|
-
class_name.split("::").first
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
##
|
|
98
|
-
# Module name fallback based on the project directory.
|
|
99
|
-
#
|
|
100
|
-
# @param [String] root
|
|
101
|
-
#
|
|
102
|
-
# @return [String]
|
|
103
|
-
def project_module_name(root)
|
|
104
|
-
camelize(File.basename(File.expand_path(root)))
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
##
|
|
108
|
-
# Whether Rails is loaded.
|
|
109
|
-
#
|
|
110
|
-
# @return [Boolean]
|
|
111
|
-
def rails_defined?
|
|
112
|
-
Object.const_defined?(:Rails)
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
##
|
|
116
|
-
# Converts a project directory into a Ruby module name.
|
|
117
|
-
#
|
|
118
|
-
# @param [String] value
|
|
119
|
-
#
|
|
120
|
-
# @return [String]
|
|
121
|
-
def camelize(value)
|
|
122
|
-
value.split(/[_-]/).map(&:capitalize).join
|
|
123
|
-
end
|
|
27
|
+
Adapters.fetch(name)
|
|
124
28
|
end
|
|
125
29
|
end
|
|
126
30
|
end
|
|
@@ -4,7 +4,7 @@ require_relative "error"
|
|
|
4
4
|
|
|
5
5
|
module Semverve
|
|
6
6
|
##
|
|
7
|
-
# Infers
|
|
7
|
+
# Infers project metadata from explicit configuration or project files.
|
|
8
8
|
class ProjectMetadata
|
|
9
9
|
##
|
|
10
10
|
# Initializes project metadata inference.
|
|
@@ -18,9 +18,12 @@ module Semverve
|
|
|
18
18
|
|
|
19
19
|
##
|
|
20
20
|
# Gem name from explicit config, the version-file path, or the gemspec.
|
|
21
|
+
# App adapters can disable package-name inference.
|
|
21
22
|
#
|
|
22
|
-
# @return [String]
|
|
23
|
+
# @return [String, nil]
|
|
23
24
|
def gem_name
|
|
25
|
+
return explicit_gem_name || configured_gem_name unless configuration.infer_package_name?
|
|
26
|
+
|
|
24
27
|
explicit_gem_name || configured_version_file_gem_name || gemspec_name
|
|
25
28
|
end
|
|
26
29
|
|
|
@@ -57,7 +60,7 @@ module Semverve
|
|
|
57
60
|
end
|
|
58
61
|
|
|
59
62
|
##
|
|
60
|
-
# Configured gem name after applying
|
|
63
|
+
# Configured gem name after applying adapters.
|
|
61
64
|
#
|
|
62
65
|
# @return [String, nil]
|
|
63
66
|
def configured_gem_name
|
|
@@ -73,7 +76,7 @@ module Semverve
|
|
|
73
76
|
end
|
|
74
77
|
|
|
75
78
|
##
|
|
76
|
-
# Configured Ruby module name after applying
|
|
79
|
+
# Configured Ruby module name after applying adapters.
|
|
77
80
|
#
|
|
78
81
|
# @return [String, nil]
|
|
79
82
|
def configured_module_name
|
|
@@ -81,7 +84,7 @@ module Semverve
|
|
|
81
84
|
end
|
|
82
85
|
|
|
83
86
|
##
|
|
84
|
-
# Configured version-file path after applying
|
|
87
|
+
# Configured version-file path after applying adapters.
|
|
85
88
|
#
|
|
86
89
|
# @return [String, nil]
|
|
87
90
|
def configured_version_file
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rake"
|
|
4
|
+
|
|
5
|
+
require_relative "file_list_resolver"
|
|
6
|
+
require_relative "finding"
|
|
7
|
+
require_relative "fix_result"
|
|
8
|
+
require_relative "semantic_version"
|
|
9
|
+
require_relative "version_literal_rewriter"
|
|
10
|
+
require_relative "version_match_policy"
|
|
11
|
+
|
|
12
|
+
module Semverve
|
|
13
|
+
##
|
|
14
|
+
# Finds and updates Rails-native config version literals.
|
|
15
|
+
class RailsConfigMetadata
|
|
16
|
+
##
|
|
17
|
+
# Default Rails config file patterns that can expose an app version.
|
|
18
|
+
#
|
|
19
|
+
# @return [Array<String>]
|
|
20
|
+
DEFAULT_FILE_PATTERNS = [
|
|
21
|
+
"config/application.rb",
|
|
22
|
+
"config/environments/*.rb",
|
|
23
|
+
"config/initializers/**/*.rb"
|
|
24
|
+
].freeze
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Rails config version assignments that are safe to rewrite.
|
|
28
|
+
#
|
|
29
|
+
# @return [Regexp]
|
|
30
|
+
VERSION_PATTERN = /^\s*(?:Rails\.application\.)?config\.x\.version\s*=\s*(?<quote>["'])(?<version>\d+\.\d+\.\d+)\k<quote>/
|
|
31
|
+
|
|
32
|
+
##
|
|
33
|
+
# Initializes Rails config metadata scanning.
|
|
34
|
+
#
|
|
35
|
+
# @param [Semverve::ResolvedConfiguration] configuration
|
|
36
|
+
# @param [Semverve::SemanticVersion] current_version
|
|
37
|
+
#
|
|
38
|
+
# @return [Semverve::RailsConfigMetadata]
|
|
39
|
+
def initialize(configuration, current_version)
|
|
40
|
+
@configuration = configuration
|
|
41
|
+
@current_version = current_version
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
##
|
|
45
|
+
# Rails config metadata findings.
|
|
46
|
+
#
|
|
47
|
+
# @return [Array<Semverve::Finding>]
|
|
48
|
+
def findings
|
|
49
|
+
files.flat_map { |path| findings_for_file(path) }
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
##
|
|
53
|
+
# Replaces safe stale Rails config version literals with the current version.
|
|
54
|
+
#
|
|
55
|
+
# @return [Semverve::FixResult]
|
|
56
|
+
def fix
|
|
57
|
+
changed_files = []
|
|
58
|
+
replacement_count = 0
|
|
59
|
+
|
|
60
|
+
files.each do |path|
|
|
61
|
+
content = File.read(path)
|
|
62
|
+
fixed, count = fixed_content(content)
|
|
63
|
+
|
|
64
|
+
next if count.zero?
|
|
65
|
+
|
|
66
|
+
File.write(path, fixed)
|
|
67
|
+
changed_files << relative_path(path)
|
|
68
|
+
replacement_count += count
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
Semverve::FixResult.new(changed_files: changed_files, replacement_count: replacement_count)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
private
|
|
75
|
+
|
|
76
|
+
##
|
|
77
|
+
# Resolved Semverve configuration.
|
|
78
|
+
#
|
|
79
|
+
# @return [Semverve::ResolvedConfiguration]
|
|
80
|
+
attr_reader :configuration
|
|
81
|
+
|
|
82
|
+
##
|
|
83
|
+
# Current app version.
|
|
84
|
+
#
|
|
85
|
+
# @return [Semverve::SemanticVersion]
|
|
86
|
+
attr_reader :current_version
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Absolute configured project root.
|
|
90
|
+
#
|
|
91
|
+
# @return [String]
|
|
92
|
+
def root
|
|
93
|
+
configuration.root
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
##
|
|
97
|
+
# Absolute files to scan.
|
|
98
|
+
#
|
|
99
|
+
# @return [Array<String>]
|
|
100
|
+
def files
|
|
101
|
+
@files ||= FileListResolver.new(root: root, file_list: Rake::FileList[*DEFAULT_FILE_PATTERNS]).files
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
##
|
|
105
|
+
# Findings for a single file.
|
|
106
|
+
#
|
|
107
|
+
# @param [String] path
|
|
108
|
+
#
|
|
109
|
+
# @return [Array<Semverve::Finding>]
|
|
110
|
+
def findings_for_file(path)
|
|
111
|
+
File.readlines(path).filter_map.with_index(1) do |line, line_number|
|
|
112
|
+
match = line.match(VERSION_PATTERN)
|
|
113
|
+
next unless match
|
|
114
|
+
|
|
115
|
+
version = SemanticVersion.parse(match[:version])
|
|
116
|
+
next unless match_policy.report?(version)
|
|
117
|
+
|
|
118
|
+
Semverve::Finding.new(
|
|
119
|
+
path: relative_path(path),
|
|
120
|
+
line: line_number,
|
|
121
|
+
column: match.begin(:version) + 1,
|
|
122
|
+
version: version
|
|
123
|
+
)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
##
|
|
128
|
+
# Fixed content and replacement count.
|
|
129
|
+
#
|
|
130
|
+
# @param [String] content
|
|
131
|
+
#
|
|
132
|
+
# @return [Array(String, Integer)]
|
|
133
|
+
def fixed_content(content)
|
|
134
|
+
replacement_count = 0
|
|
135
|
+
|
|
136
|
+
fixed = content.lines.map do |line|
|
|
137
|
+
match = line.match(VERSION_PATTERN)
|
|
138
|
+
next line unless match
|
|
139
|
+
|
|
140
|
+
version = SemanticVersion.parse(match[:version])
|
|
141
|
+
next line unless match_policy.report?(version)
|
|
142
|
+
|
|
143
|
+
replacement_count += 1
|
|
144
|
+
literal_rewriter.rewrite(line)
|
|
145
|
+
end.join
|
|
146
|
+
|
|
147
|
+
[fixed, replacement_count]
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
# Path relative to the project root.
|
|
152
|
+
#
|
|
153
|
+
# @param [String] path
|
|
154
|
+
#
|
|
155
|
+
# @return [String]
|
|
156
|
+
def relative_path(path)
|
|
157
|
+
path.delete_prefix("#{root}/")
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
##
|
|
161
|
+
# Rails config metadata always requires an exact current-version match.
|
|
162
|
+
#
|
|
163
|
+
# @return [Semverve::VersionMatchPolicy]
|
|
164
|
+
def match_policy
|
|
165
|
+
@match_policy ||= VersionMatchPolicy.new(current_version: current_version, match_mode: :non_current)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
# Safe literal rewriter for Rails config metadata.
|
|
170
|
+
#
|
|
171
|
+
# @return [Semverve::VersionLiteralRewriter]
|
|
172
|
+
def literal_rewriter
|
|
173
|
+
@literal_rewriter ||= VersionLiteralRewriter.new(pattern: VERSION_PATTERN, replacement: current_version)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
data/lib/semverve/railtie.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Semverve
|
|
|
7
7
|
# Rails integration for installing Semverve's Rake tasks.
|
|
8
8
|
class Railtie < ::Rails::Railtie
|
|
9
9
|
rake_tasks do
|
|
10
|
-
Semverve.configuration.
|
|
10
|
+
Semverve.configuration.adapter = :rails unless Semverve.configuration.adapter
|
|
11
11
|
|
|
12
12
|
require_relative "task"
|
|
13
13
|
Semverve::Task.install
|