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.
data/lib/semverve/task.rb CHANGED
@@ -3,13 +3,12 @@
3
3
  require "rake"
4
4
 
5
5
  require_relative "../semverve"
6
+ require_relative "adapters"
6
7
  require_relative "generator"
7
8
  require_relative "published_version"
8
9
  require_relative "semantic_version"
9
10
  require_relative "version_file"
10
- require_relative "version_code_references"
11
- require_relative "version_metadata"
12
- require_relative "version_references"
11
+ require_relative "version_checks"
13
12
 
14
13
  module Semverve
15
14
  ##
@@ -115,24 +114,16 @@ module Semverve
115
114
  end
116
115
 
117
116
  desc "Check version references, code literals, and metadata"
118
- task :check do
119
- check
117
+ task :check, [:version] do |_task, args|
118
+ check(args)
120
119
  end
121
120
 
122
121
  namespace :check do
123
- desc "Check configured files for stale version references"
124
- task :references do
125
- check_references
126
- end
127
-
128
- desc "Check configured code files for version literals"
129
- task :code do
130
- check_code
131
- end
132
-
133
- desc "Check gem metadata for version mismatches"
134
- task :metadata do
135
- check_metadata
122
+ version_checks.each do |version_check|
123
+ desc version_check.check_description
124
+ task version_check.task_name, version_check.task_arguments do |_task, args|
125
+ check_version_check(version_check, args)
126
+ end
136
127
  end
137
128
 
138
129
  desc "Check whether the current gem version is already published"
@@ -147,24 +138,16 @@ module Semverve
147
138
  end
148
139
 
149
140
  desc "Fix version references, code literals, and metadata"
150
- task :fix do
151
- fix
141
+ task :fix, [:version] do |_task, args|
142
+ fix(args)
152
143
  end
153
144
 
154
145
  namespace :fix do
155
- desc "Replace stale version references in configured files"
156
- task :references do
157
- fix_references
158
- end
159
-
160
- desc "Replace safe code version literals in configured files"
161
- task :code do
162
- fix_code
163
- end
164
-
165
- desc "Fix safe gem metadata version mismatches"
166
- task :metadata do
167
- fix_metadata
146
+ version_checks.each do |version_check|
147
+ desc version_check.fix_description
148
+ task version_check.task_name, version_check.task_arguments do |_task, args|
149
+ fix_version_check(version_check, args)
150
+ end
168
151
  end
169
152
  end
170
153
  end
@@ -203,11 +186,14 @@ module Semverve
203
186
  # Checks all version-maintenance surfaces.
204
187
  #
205
188
  # @return [void]
206
- def check
189
+ def check(args = nil)
207
190
  configuration, current_version = check_context
191
+ target_version = target_version_argument(args, "semverve:check")
208
192
  report_findings(
209
- check_groups(configuration, current_version),
193
+ check_groups(configuration, current_version, target_version),
210
194
  current_version,
195
+ target_version: target_version,
196
+ fix_task_name: "semverve:fix",
211
197
  clean_message: "Version checks passed."
212
198
  )
213
199
  end
@@ -216,72 +202,79 @@ module Semverve
216
202
  # Fixes all check surfaces.
217
203
  #
218
204
  # @return [void]
219
- def fix
205
+ def fix(args = nil)
220
206
  configuration, current_version = check_context
221
- report_fix_results(fix_results(configuration, current_version))
207
+ target_version = target_version_argument(args, "semverve:fix")
208
+ return report_current_target_noop(target_version) if target_version == current_version
209
+
210
+ report_fix_results(fix_results(configuration, current_version, target_version))
222
211
  end
223
212
 
224
213
  ##
225
- # Checks configured files for stale version references.
214
+ # Checks a single registered version check.
215
+ #
216
+ # @param [#findings] version_check
217
+ # @param [Rake::TaskArguments, nil] args
226
218
  #
227
219
  # @return [void]
228
- def check_references
220
+ def check_version_check(version_check, args = nil)
229
221
  configuration, current_version = check_context
222
+ target_version = check_target_version(version_check, args, "semverve:check:#{version_check.task_name}")
230
223
  report_findings(
231
- [["version reference", VersionReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]],
224
+ [[
225
+ version_check,
226
+ version_check.finding_label,
227
+ version_check.findings(
228
+ configuration,
229
+ current_version,
230
+ include_ignored: report_ignored?,
231
+ target_version: target_version
232
+ )
233
+ ]],
232
234
  current_version,
233
- clean_message: "Version references are current."
235
+ target_version: target_version,
236
+ fix_task_name: "semverve:fix:#{version_check.task_name}",
237
+ clean_message: version_check.clean_message
234
238
  )
235
239
  end
236
240
 
237
241
  ##
238
- # Replaces stale version references in configured files.
242
+ # Fixes a single registered version check.
243
+ #
244
+ # @param [#fix] version_check
245
+ # @param [Rake::TaskArguments, nil] args
239
246
  #
240
247
  # @return [void]
241
- def fix_references
248
+ def fix_version_check(version_check, args = nil)
242
249
  configuration, current_version = check_context
250
+ target_version = check_target_version(version_check, args, "semverve:fix:#{version_check.task_name}")
251
+ return report_current_target_noop(target_version) if target_version == current_version
252
+
243
253
  report_fix_results(
244
- [["version reference", VersionReferences.new(configuration, current_version).fix]],
245
- clean_message: "Version references are current."
254
+ [[
255
+ version_check.fix_label,
256
+ version_check.fix(configuration, current_version, target_version: target_version)
257
+ ]],
258
+ clean_message: version_check.clean_message
246
259
  )
247
260
  end
248
261
 
249
262
  ##
250
- # Checks configured code files for version literals.
263
+ # Registered version checks available to tasks.
251
264
  #
252
- # @return [void]
253
- def check_code
254
- configuration, current_version = check_context
255
- report_findings(
256
- [["code version literal", VersionCodeReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]],
257
- current_version,
258
- clean_message: "Code version literals are current."
259
- )
265
+ # @return [Array<#name>]
266
+ def version_checks
267
+ VersionChecks.all(extra_checks: Adapters.checks)
260
268
  end
261
269
 
262
270
  ##
263
- # Replaces safe code version literals in configured files.
271
+ # Fetches a registered version check.
264
272
  #
265
- # @return [void]
266
- def fix_code
267
- configuration, current_version = check_context
268
- report_fix_results(
269
- [["code version literal", VersionCodeReferences.new(configuration, current_version).fix]],
270
- clean_message: "Code version literals are current."
271
- )
272
- end
273
-
274
- ##
275
- # Checks gem metadata for version mismatches.
273
+ # @param [Symbol, String] name
276
274
  #
277
- # @return [void]
278
- def check_metadata
279
- configuration, current_version = check_context
280
- report_findings(
281
- [[nil, VersionMetadata.new(configuration, current_version).findings]],
282
- current_version,
283
- clean_message: "Version metadata is current."
284
- )
275
+ # @return [#name]
276
+ def version_check(name)
277
+ VersionChecks.fetch(name, extra_checks: Adapters.checks)
285
278
  end
286
279
 
287
280
  ##
@@ -309,18 +302,6 @@ module Semverve
309
302
  puts "Release checks passed."
310
303
  end
311
304
 
312
- ##
313
- # Fixes safe gem metadata version mismatches.
314
- #
315
- # @return [void]
316
- def fix_metadata
317
- configuration, current_version = check_context
318
- report_fix_results(
319
- [["metadata version", VersionMetadata.new(configuration, current_version).fix]],
320
- clean_message: "Version metadata is current."
321
- )
322
- end
323
-
324
305
  ##
325
306
  # Resolved configuration and current version for check tasks.
326
307
  #
@@ -336,19 +317,23 @@ module Semverve
336
317
  # @param [Semverve::ResolvedConfiguration] configuration
337
318
  # @param [Semverve::SemanticVersion] current_version
338
319
  #
339
- # @return [Array<Array(String, Array)>]
340
- def check_groups(configuration, current_version)
341
- groups = []
342
- if configuration.version_checks.include?(:doc_references)
343
- groups << ["version reference", VersionReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]
344
- end
345
- if configuration.version_checks.include?(:code_references)
346
- groups << ["code version literal", VersionCodeReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]
347
- end
348
- if configuration.version_checks.include?(:metadata)
349
- groups << [nil, VersionMetadata.new(configuration, current_version).findings]
320
+ # @param [Semverve::SemanticVersion, nil] target_version
321
+ #
322
+ # @return [Array<Array(#name, String, Array)>]
323
+ def check_groups(configuration, current_version, target_version = nil)
324
+ configuration.version_checks.map do |check_name|
325
+ version_check = version_check(check_name)
326
+ [
327
+ version_check,
328
+ version_check.finding_label,
329
+ version_check.findings(
330
+ configuration,
331
+ current_version,
332
+ include_ignored: report_ignored?,
333
+ target_version: target_version_for(version_check, target_version)
334
+ )
335
+ ]
350
336
  end
351
- groups
352
337
  end
353
338
 
354
339
  ##
@@ -412,25 +397,67 @@ module Semverve
412
397
  version
413
398
  end
414
399
 
400
+ ##
401
+ # Optional exact version argument for check and fix tasks.
402
+ #
403
+ # @param [Rake::TaskArguments, nil] args
404
+ # @param [String] task_name
405
+ #
406
+ # @return [Semverve::SemanticVersion, nil]
407
+ def target_version_argument(args, task_name)
408
+ version = args&.[](:version)
409
+ return nil if version.nil? || version.empty?
410
+
411
+ SemanticVersion.parse(version)
412
+ rescue Error
413
+ raise Error, "Run rake '#{task_name}[MAJOR.MINOR.PATCH]'."
414
+ end
415
+
416
+ ##
417
+ # Optional exact version argument for checks that support targeting.
418
+ #
419
+ # @param [#targetable?] version_check
420
+ # @param [Rake::TaskArguments, nil] args
421
+ # @param [String] task_name
422
+ #
423
+ # @return [Semverve::SemanticVersion, nil]
424
+ def check_target_version(version_check, args, task_name)
425
+ return nil unless version_check.targetable?
426
+
427
+ target_version_argument(args, task_name)
428
+ end
429
+
430
+ ##
431
+ # Applies an umbrella target only to checks that support targeting.
432
+ #
433
+ # @param [#targetable?] version_check
434
+ # @param [Semverve::SemanticVersion, nil] target_version
435
+ #
436
+ # @return [Semverve::SemanticVersion, nil]
437
+ def target_version_for(version_check, target_version)
438
+ version_check.targetable? ? target_version : nil
439
+ end
440
+
415
441
  ##
416
442
  # Fix results enabled for the umbrella fix task.
417
443
  #
418
444
  # @param [Semverve::ResolvedConfiguration] configuration
419
445
  # @param [Semverve::SemanticVersion] current_version
446
+ # @param [Semverve::SemanticVersion, nil] target_version
420
447
  #
421
448
  # @return [Array<Array(String, #replacement_count, #changed_files)>]
422
- def fix_results(configuration, current_version)
423
- results = []
424
- if configuration.version_checks.include?(:doc_references)
425
- results << ["version reference", VersionReferences.new(configuration, current_version).fix]
426
- end
427
- if configuration.version_checks.include?(:code_references)
428
- results << ["code version literal", VersionCodeReferences.new(configuration, current_version).fix]
449
+ def fix_results(configuration, current_version, target_version = nil)
450
+ configuration.version_checks.map do |check_name|
451
+ version_check = version_check(check_name)
452
+ [
453
+ version_check.fix_label,
454
+ version_check.fix(
455
+ configuration,
456
+ current_version,
457
+ target_version: target_version_for(version_check, target_version)
458
+ )
459
+ ]
429
460
  end
430
- if configuration.version_checks.include?(:metadata)
431
- results << ["metadata version", VersionMetadata.new(configuration, current_version).fix]
432
- end
433
- results
434
461
  end
435
462
 
436
463
  ##
@@ -438,12 +465,14 @@ module Semverve
438
465
  #
439
466
  # @param [Array<Array(String, Array)>] groups
440
467
  # @param [Semverve::SemanticVersion] current_version
468
+ # @param [Semverve::SemanticVersion, nil] target_version
469
+ # @param [String, nil] fix_task_name
441
470
  # @param [String] clean_message
442
471
  #
443
472
  # @return [void]
444
- def report_findings(groups, current_version, clean_message:)
445
- findings = groups.flat_map do |(label, group_findings)|
446
- group_findings.map { |finding| [label || finding.label, finding] }
473
+ def report_findings(groups, current_version, clean_message:, target_version: nil, fix_task_name: nil)
474
+ findings = groups.flat_map do |(version_check, label, group_findings)|
475
+ group_findings.map { |finding| [version_check, label || finding.label, finding] }
447
476
  end
448
477
 
449
478
  if findings.empty?
@@ -451,14 +480,37 @@ module Semverve
451
480
  return
452
481
  end
453
482
 
454
- findings.each do |(label, finding)|
483
+ findings.each do |(_version_check, label, finding)|
455
484
  puts "#{finding.path}:#{finding.line}:#{finding.column}: #{label} #{finding.version} -> #{current_version}"
456
485
  end
486
+ if target_version == current_version && fix_task_name && exact_target_fix_noop_findings?(findings)
487
+ puts "Target version #{target_version} is already current; #{fix_task_name}[#{target_version}] will not change these references."
488
+ end
457
489
 
458
490
  issue = findings.one? ? "issue" : "issues"
459
491
  raise Error, "Found #{findings.count} version check #{issue}."
460
492
  end
461
493
 
494
+ ##
495
+ # Prints a no-op message for exact fix requests targeting the current version.
496
+ #
497
+ # @param [Semverve::SemanticVersion, nil] target_version
498
+ #
499
+ # @return [void]
500
+ def report_current_target_noop(target_version)
501
+ puts "Target version #{target_version} is already current; nothing to fix."
502
+ end
503
+
504
+ ##
505
+ # Whether findings include surfaces controlled by exact-target fixes.
506
+ #
507
+ # @param [Array<Array(#exact_target_fix_noop_notice?, String, Object)>] findings
508
+ #
509
+ # @return [Boolean]
510
+ def exact_target_fix_noop_findings?(findings)
511
+ findings.any? { |(version_check, _label, _finding)| version_check.exact_target_fix_noop_notice? }
512
+ end
513
+
462
514
  ##
463
515
  # Prints fix results.
464
516
  #
@@ -468,7 +520,7 @@ module Semverve
468
520
  # @return [void]
469
521
  def report_fix_results(results, clean_message: "Version checks passed.")
470
522
  replacement_count = results.sum { |(_label, result)| result.replacement_count }
471
- bundle_lock_ran = results.any? { |(_label, result)| result.respond_to?(:bundle_lock_ran) && result.bundle_lock_ran }
523
+ bundle_lock_ran = results.any? { |(_label, result)| result.bundle_lock_ran }
472
524
 
473
525
  if replacement_count.zero? && !bundle_lock_ran
474
526
  puts clean_message
@@ -15,13 +15,13 @@ module Semverve
15
15
  # Minor version.
16
16
  #
17
17
  # @return [Integer]
18
- MINOR = 2
18
+ MINOR = 4
19
19
 
20
20
  ##
21
21
  # Patch version.
22
22
  #
23
23
  # @return [Integer]
24
- PATCH = 1
24
+ PATCH = 0
25
25
 
26
26
  module_function
27
27