semverve 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 436e6dece23a174761d954e1c1efc74d95d68b8b47d82f876bb5b785eb204748
4
- data.tar.gz: 62e9b4496586062f8e03f71d0838ddd510e5e42faa200d10fbef2560f214fa4c
3
+ metadata.gz: c12b376c6b4cb56170cff17c35f9545137b3011f1e1fe6314541dfe259351367
4
+ data.tar.gz: fae2d93ad6f546f69e081cfa5a7449d7d6de0c9eb25430421dbe41a274171d8c
5
5
  SHA512:
6
- metadata.gz: cc055ab321689871de38a8fc0276a8cc85011ea9c7765c7844d97c71962bba2765cd867cd9dbb96236b11ea695edc63e8289c087fd5a90482ab1ea376d82981a
7
- data.tar.gz: 8a4cbb86d9548b4aeeedf94bd883e300532a6d4c062dc1c1c1170d412ae5bb94a4fe50bdfbc29098482a51632a194ef32be93cee35ef8a5219d77f5957d54c98
6
+ metadata.gz: 92980247baef342765f07bf2f9a398e38b191a3707302ae84f25ca0a322a9bfd428335f680c6da34cebc1039f533cdf7298117e1e062f159413c663e58966f2c
7
+ data.tar.gz: b9016a36d15e78aa46c6e7fea92feaa48bd5dec2627fcd8e47420e11a55eed4c7083f56eaeb06f95cb1a9baa50f3559f5c9d3e63fb2bc42dae720a49447df775
data/CONTRIBUTING.md CHANGED
@@ -100,6 +100,31 @@ When changing behavior, update the README at the same time. The README is the
100
100
  primary user guide, so examples should match real task names, configuration
101
101
  names, defaults, and output.
102
102
 
103
+ ## Rake Task Interface Design
104
+ Semverve should feel natural from a shell while staying Rake-native. Prefer
105
+ Rake task arguments for direct task inputs:
106
+
107
+ ```sh
108
+ bundle exec rake 'semverve:set[x.y.z]'
109
+ bundle exec rake 'semverve:generate[simple,force]'
110
+ ```
111
+
112
+ For tasks with more than one optional value, prefer meaning-bearing tokens over
113
+ strict positional placeholders. For example, `semverve:generate` treats semantic
114
+ versions as the generated version, `module` or `simple` as the format, and
115
+ `force` as the overwrite mode. That keeps invocations like
116
+ `rake 'semverve:generate[simple]'` and `rake 'semverve:generate[force]'`
117
+ readable without requiring awkward empty slots.
118
+
119
+ Use Rake task arguments for one-off exact inputs, such as
120
+ `rake 'semverve:check[1.2.3]'` when a user wants to scan only for a specific
121
+ version.
122
+
123
+ Reserve environment variables for cross-cutting runtime toggles that compose
124
+ across related tasks, such as `SEMVERVE_REPORT_IGNORED=true rake
125
+ semverve:check`. Avoid generic environment variables like `VERSION`, `FORMAT`,
126
+ or `FORCE`; they can collide with a user's shell, CI, or parent build process.
127
+
103
128
  ## Versioning and Release Checks
104
129
  Semverve uses Semverve to maintain itself, which doubles as useful
105
130
  smoke-testing. The project Rakefile requires `lib/semverve/task` and installs
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- semverve (0.2.0)
4
+ semverve (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -95,7 +95,7 @@ Semverve.configure do |config|
95
95
  config.rubygems_host = "https://rubygems.org"
96
96
  config.version_code_reference_files.append("lib/**/*.rb")
97
97
  config.version_doc_reference_files.append("doc/**/*.md")
98
- config.version_reference_mode = :non_current
98
+ config.version_match_mode = :non_current
99
99
  end
100
100
  ```
101
101
 
@@ -109,7 +109,7 @@ Semverve.configure do |config|
109
109
  config.version_checks = [:doc_references, :code_references, :metadata]
110
110
  config.release_checks = []
111
111
  config.rubygems_host = "https://rubygems.org"
112
- config.version_reference_mode = :older
112
+ config.version_match_mode = :older
113
113
  config.version_code_reference_files = Rake::FileList[]
114
114
  config.version_code_reference_pattern =
115
115
  /^\s*(?:(?:[A-Z]\w*::)*(?:[A-Z]\w*VERSION[A-Z0-9_]*|VERSION)|(?:[a-z_]\w*|self)\.version)\s*=\s*(?<quote>["'])(?<version>\d+\.\d+\.\d+)\k<quote>/
@@ -133,6 +133,7 @@ Semverve tasks use Rake task arguments for values:
133
133
  ```sh
134
134
  rake 'semverve:set[1.2.3]'
135
135
  rake 'semverve:generate[1.0.0,simple]'
136
+ rake 'semverve:generate[simple]'
136
137
  rake 'semverve:generate[force]'
137
138
  ```
138
139
 
@@ -250,6 +251,7 @@ Generate a specific version or format:
250
251
 
251
252
  ```sh
252
253
  rake 'semverve:generate[1.0.0,simple]'
254
+ rake 'semverve:generate[simple]'
253
255
  ```
254
256
 
255
257
  Generation fails if the target file already exists. To replace it:
@@ -258,11 +260,14 @@ Generation fails if the target file already exists. To replace it:
258
260
  rake 'semverve:generate[force]'
259
261
  ```
260
262
 
261
- `semverve:generate` accepts optional `version` and `format` arguments. Add a
262
- `force` token to overwrite an existing version file:
263
+ `semverve:generate` accepts optional tokens for version, format, and force.
264
+ Token order does not matter: semantic versions set the generated version,
265
+ `module` or `simple` sets the format, and `force` overwrites an existing version
266
+ file.
263
267
 
264
268
  ```sh
265
269
  rake 'semverve:generate[1.0.0,force]'
270
+ rake 'semverve:generate[simple,force]'
266
271
  rake 'semverve:generate[1.0.0,simple,force]'
267
272
  ```
268
273
 
@@ -370,6 +375,18 @@ rake semverve:fix:metadata
370
375
  `semverve:fix:metadata` rewrites literal gemspec versions when safe and
371
376
  runs `bundle lock` for `Gemfile.lock` drift.
372
377
 
378
+ Pass a semantic version when you want to check or fix only that exact version in
379
+ doc references and code literals:
380
+
381
+ ```sh
382
+ rake 'semverve:check[1.2.2]'
383
+ rake 'semverve:fix:references[1.2.2]'
384
+ ```
385
+
386
+ Metadata checks still compare metadata to the current version. If you target the
387
+ current version, check tasks list those matches but fix tasks are no-ops because
388
+ the text is already current.
389
+
373
390
  ### Version references
374
391
  Version references are prose-like references to versions. These are usually in
375
392
  README files, docs, guides, or comments. By default, Semverve scans README files
@@ -405,20 +422,21 @@ end
405
422
  Ruby files are scanned only in comments. Text files with `.md`, `.markdown`,
406
423
  `.txt`, `.rdoc`, and `.adoc` extensions are scanned as full text.
407
424
 
408
- The default reference mode is `:older`, which flags only semantic versions lower
409
- than the current version:
425
+ The default version match mode is `:older`, which flags only semantic versions
426
+ lower than the current version in doc references and code literals:
410
427
 
411
428
  ```ruby
412
429
  Semverve.configure do |config|
413
- config.version_reference_mode = :older
430
+ config.version_match_mode = :older
414
431
  end
415
432
  ```
416
433
 
417
- Use `:non_current` when every reference should match the current version:
434
+ Use `:non_current` when every doc reference and code literal should match the
435
+ current version:
418
436
 
419
437
  ```ruby
420
438
  Semverve.configure do |config|
421
- config.version_reference_mode = :non_current
439
+ config.version_match_mode = :non_current
422
440
  end
423
441
  ```
424
442
 
@@ -434,6 +452,7 @@ check tasks:
434
452
 
435
453
  ```sh
436
454
  SEMVERVE_REPORT_IGNORED=true rake semverve:check
455
+ SEMVERVE_REPORT_IGNORED=true rake 'semverve:check[1.2.2]'
437
456
  ```
438
457
 
439
458
  ### Code version literals
@@ -521,7 +540,7 @@ current version file against:
521
540
  - the matching `Gemfile.lock` entry, when a lockfile exists
522
541
 
523
542
  Metadata always requires an exact match, regardless of
524
- `config.version_reference_mode`.
543
+ `config.version_match_mode`.
525
544
 
526
545
  No file-list configuration is needed for these checks. Semverve resolves the
527
546
  gemspec from the project root and reads `Gemfile.lock` when one exists.
@@ -620,6 +639,39 @@ For release CI, run the release check before building or pushing:
620
639
  bundle exec rake semverve:check:release build
621
640
  ```
622
641
 
642
+ ## Vim
643
+ While there's no official vim support (yet), you can add the following to
644
+ `~/.vim/plugin/semverve.vim`.
645
+
646
+ ```vim
647
+ command! -bang SemverveAudit call <SID>semverve_audit(<bang>0)
648
+ function! s:semverve_audit(report_ignored) abort
649
+ let l:old_efm = &errorformat
650
+ try
651
+ let &errorformat = '%f:%l:%c:%m'
652
+ let l:string = ""
653
+ if !a:report_ignored
654
+ let l:string .= 'SEMVERVE_REPORT_IGNORED=true '
655
+ endif
656
+ let l:string .= 'bundle exec rake semverve:check 2>/dev/null'
657
+ cexpr systemlist(l:string)
658
+ if v:shell_error != 0
659
+ copen
660
+ else
661
+ cclose
662
+ echo 'Semverve checks passed.'
663
+ endif
664
+ finally
665
+ let &errorformat = l:old_efm
666
+ endtry
667
+ endfunction
668
+ ```
669
+
670
+ You can then call `:SemverveAudit`, which will call `bundle exec rake
671
+ semverve:check`, and `:SemverveAudit!` which will call the same command with
672
+ `SEMVERVE_REPORT_IGNORED=true`, and populate and open the quickfix list if any
673
+ offenses are found.
674
+
623
675
  ## Reporting Bugs and Requesting Features
624
676
  If you have an idea or find a bug, please [create an
625
677
  issue](https://github.com/evanthegrayt/semverve/issues/new). Just make sure
@@ -113,10 +113,10 @@ module Semverve
113
113
  attr_reader :version_checks
114
114
 
115
115
  ##
116
- # Version-reference comparison mode.
116
+ # Version matching mode for reference and code-literal checks.
117
117
  #
118
118
  # @return [Symbol, String]
119
- attr_accessor :version_reference_mode
119
+ attr_accessor :version_match_mode
120
120
 
121
121
  ##
122
122
  # Initializes configuration with Semverve's default settings.
@@ -137,7 +137,7 @@ module Semverve
137
137
  "tmp/**/*",
138
138
  "vendor/**/*"
139
139
  )
140
- @version_reference_mode = :older
140
+ @version_match_mode = :older
141
141
  self.release_checks = []
142
142
  self.version_checks = VALID_VERSION_CHECKS
143
143
  end
@@ -163,7 +163,7 @@ module Semverve
163
163
  version_code_reference_files: version_code_reference_files,
164
164
  version_code_reference_pattern: version_code_reference_pattern,
165
165
  version_doc_reference_files: version_doc_reference_files,
166
- version_reference_mode: normalized_version_reference_mode
166
+ version_match_mode: normalized_version_match_mode
167
167
  )
168
168
  end
169
169
 
@@ -305,11 +305,11 @@ module Semverve
305
305
  end
306
306
 
307
307
  ##
308
- # Configured version-reference mode normalized for lookup.
308
+ # Configured version matching mode normalized for lookup.
309
309
  #
310
310
  # @return [Symbol]
311
- def normalized_version_reference_mode
312
- version_reference_mode.to_sym
311
+ def normalized_version_match_mode
312
+ version_match_mode.to_sym
313
313
  end
314
314
 
315
315
  ##
@@ -478,10 +478,10 @@ module Semverve
478
478
  attr_reader :version_doc_reference_files
479
479
 
480
480
  ##
481
- # Resolved version-reference comparison mode.
481
+ # Resolved version matching mode for reference and code-literal checks.
482
482
  #
483
483
  # @return [Symbol]
484
- attr_reader :version_reference_mode
484
+ attr_reader :version_match_mode
485
485
 
486
486
  ##
487
487
  # Initializes a resolved configuration.
@@ -499,7 +499,7 @@ module Semverve
499
499
  # @param [Rake::FileList] version_code_reference_files
500
500
  # @param [Regexp] version_code_reference_pattern
501
501
  # @param [Rake::FileList] version_doc_reference_files
502
- # @param [Symbol] version_reference_mode
502
+ # @param [Symbol] version_match_mode
503
503
  #
504
504
  # @return [Semverve::ResolvedConfiguration]
505
505
  def initialize(
@@ -516,7 +516,7 @@ module Semverve
516
516
  version_code_reference_files:,
517
517
  version_code_reference_pattern:,
518
518
  version_doc_reference_files:,
519
- version_reference_mode:
519
+ version_match_mode:
520
520
  )
521
521
  @bundle_lock = bundle_lock
522
522
  @command_runner = command_runner
@@ -531,7 +531,7 @@ module Semverve
531
531
  @version_code_reference_files = version_code_reference_files
532
532
  @version_code_reference_pattern = version_code_reference_pattern
533
533
  @version_doc_reference_files = version_doc_reference_files
534
- @version_reference_mode = version_reference_mode
534
+ @version_match_mode = version_match_mode
535
535
  end
536
536
 
537
537
  ##
data/lib/semverve/task.rb CHANGED
@@ -115,19 +115,19 @@ module Semverve
115
115
  end
116
116
 
117
117
  desc "Check version references, code literals, and metadata"
118
- task :check do
119
- check
118
+ task :check, [:version] do |_task, args|
119
+ check(args)
120
120
  end
121
121
 
122
122
  namespace :check do
123
123
  desc "Check configured files for stale version references"
124
- task :references do
125
- check_references
124
+ task :references, [:version] do |_task, args|
125
+ check_references(args)
126
126
  end
127
127
 
128
128
  desc "Check configured code files for version literals"
129
- task :code do
130
- check_code
129
+ task :code, [:version] do |_task, args|
130
+ check_code(args)
131
131
  end
132
132
 
133
133
  desc "Check gem metadata for version mismatches"
@@ -147,19 +147,19 @@ module Semverve
147
147
  end
148
148
 
149
149
  desc "Fix version references, code literals, and metadata"
150
- task :fix do
151
- fix
150
+ task :fix, [:version] do |_task, args|
151
+ fix(args)
152
152
  end
153
153
 
154
154
  namespace :fix do
155
155
  desc "Replace stale version references in configured files"
156
- task :references do
157
- fix_references
156
+ task :references, [:version] do |_task, args|
157
+ fix_references(args)
158
158
  end
159
159
 
160
160
  desc "Replace safe code version literals in configured files"
161
- task :code do
162
- fix_code
161
+ task :code, [:version] do |_task, args|
162
+ fix_code(args)
163
163
  end
164
164
 
165
165
  desc "Fix safe gem metadata version mismatches"
@@ -203,11 +203,14 @@ module Semverve
203
203
  # Checks all version-maintenance surfaces.
204
204
  #
205
205
  # @return [void]
206
- def check
206
+ def check(args = nil)
207
207
  configuration, current_version = check_context
208
+ target_version = target_version_argument(args, "semverve:check")
208
209
  report_findings(
209
- check_groups(configuration, current_version),
210
+ check_groups(configuration, current_version, target_version),
210
211
  current_version,
212
+ target_version: target_version,
213
+ fix_task_name: "semverve:fix",
211
214
  clean_message: "Version checks passed."
212
215
  )
213
216
  end
@@ -216,20 +219,34 @@ module Semverve
216
219
  # Fixes all check surfaces.
217
220
  #
218
221
  # @return [void]
219
- def fix
222
+ def fix(args = nil)
220
223
  configuration, current_version = check_context
221
- report_fix_results(fix_results(configuration, current_version))
224
+ target_version = target_version_argument(args, "semverve:fix")
225
+ return report_current_target_noop(target_version) if target_version == current_version
226
+
227
+ report_fix_results(fix_results(configuration, current_version, target_version))
222
228
  end
223
229
 
224
230
  ##
225
231
  # Checks configured files for stale version references.
226
232
  #
227
233
  # @return [void]
228
- def check_references
234
+ def check_references(args = nil)
229
235
  configuration, current_version = check_context
236
+ target_version = target_version_argument(args, "semverve:check:references")
230
237
  report_findings(
231
- [["version reference", VersionReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]],
238
+ [[
239
+ "version reference",
240
+ VersionReferences.new(
241
+ configuration,
242
+ current_version,
243
+ include_ignored: report_ignored?,
244
+ target_version: target_version
245
+ ).findings
246
+ ]],
232
247
  current_version,
248
+ target_version: target_version,
249
+ fix_task_name: "semverve:fix:references",
233
250
  clean_message: "Version references are current."
234
251
  )
235
252
  end
@@ -238,10 +255,16 @@ module Semverve
238
255
  # Replaces stale version references in configured files.
239
256
  #
240
257
  # @return [void]
241
- def fix_references
258
+ def fix_references(args = nil)
242
259
  configuration, current_version = check_context
260
+ target_version = target_version_argument(args, "semverve:fix:references")
261
+ return report_current_target_noop(target_version) if target_version == current_version
262
+
243
263
  report_fix_results(
244
- [["version reference", VersionReferences.new(configuration, current_version).fix]],
264
+ [[
265
+ "version reference",
266
+ VersionReferences.new(configuration, current_version, target_version: target_version).fix
267
+ ]],
245
268
  clean_message: "Version references are current."
246
269
  )
247
270
  end
@@ -250,11 +273,22 @@ module Semverve
250
273
  # Checks configured code files for version literals.
251
274
  #
252
275
  # @return [void]
253
- def check_code
276
+ def check_code(args = nil)
254
277
  configuration, current_version = check_context
278
+ target_version = target_version_argument(args, "semverve:check:code")
255
279
  report_findings(
256
- [["code version literal", VersionCodeReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]],
280
+ [[
281
+ "code version literal",
282
+ VersionCodeReferences.new(
283
+ configuration,
284
+ current_version,
285
+ include_ignored: report_ignored?,
286
+ target_version: target_version
287
+ ).findings
288
+ ]],
257
289
  current_version,
290
+ target_version: target_version,
291
+ fix_task_name: "semverve:fix:code",
258
292
  clean_message: "Code version literals are current."
259
293
  )
260
294
  end
@@ -263,10 +297,16 @@ module Semverve
263
297
  # Replaces safe code version literals in configured files.
264
298
  #
265
299
  # @return [void]
266
- def fix_code
300
+ def fix_code(args = nil)
267
301
  configuration, current_version = check_context
302
+ target_version = target_version_argument(args, "semverve:fix:code")
303
+ return report_current_target_noop(target_version) if target_version == current_version
304
+
268
305
  report_fix_results(
269
- [["code version literal", VersionCodeReferences.new(configuration, current_version).fix]],
306
+ [[
307
+ "code version literal",
308
+ VersionCodeReferences.new(configuration, current_version, target_version: target_version).fix
309
+ ]],
270
310
  clean_message: "Code version literals are current."
271
311
  )
272
312
  end
@@ -336,14 +376,32 @@ module Semverve
336
376
  # @param [Semverve::ResolvedConfiguration] configuration
337
377
  # @param [Semverve::SemanticVersion] current_version
338
378
  #
379
+ # @param [Semverve::SemanticVersion, nil] target_version
380
+ #
339
381
  # @return [Array<Array(String, Array)>]
340
- def check_groups(configuration, current_version)
382
+ def check_groups(configuration, current_version, target_version = nil)
341
383
  groups = []
342
384
  if configuration.version_checks.include?(:doc_references)
343
- groups << ["version reference", VersionReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]
385
+ groups << [
386
+ "version reference",
387
+ VersionReferences.new(
388
+ configuration,
389
+ current_version,
390
+ include_ignored: report_ignored?,
391
+ target_version: target_version
392
+ ).findings
393
+ ]
344
394
  end
345
395
  if configuration.version_checks.include?(:code_references)
346
- groups << ["code version literal", VersionCodeReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]
396
+ groups << [
397
+ "code version literal",
398
+ VersionCodeReferences.new(
399
+ configuration,
400
+ current_version,
401
+ include_ignored: report_ignored?,
402
+ target_version: target_version
403
+ ).findings
404
+ ]
347
405
  end
348
406
  if configuration.version_checks.include?(:metadata)
349
407
  groups << [nil, VersionMetadata.new(configuration, current_version).findings]
@@ -366,17 +424,37 @@ module Semverve
366
424
  #
367
425
  # @return [Hash]
368
426
  def generate_options(args)
369
- values = args.to_a
370
- force = values.delete("force")
371
- if values.length > 2
372
- raise Error, "Run rake 'semverve:generate[VERSION,FORMAT,force]'."
427
+ args.to_a.each_with_object({force: false}) do |value, options|
428
+ assign_generate_option(value, options)
373
429
  end
430
+ end
374
431
 
375
- {
376
- version: values[0],
377
- format: values[1],
378
- force: !force.nil?
379
- }
432
+ ##
433
+ # Assigns a single +semverve:generate+ token by meaning.
434
+ #
435
+ # @param [String] value
436
+ # @param [Hash] options
437
+ #
438
+ # @return [void]
439
+ def assign_generate_option(value, options)
440
+ case value
441
+ when nil, ""
442
+ nil
443
+ when "force"
444
+ raise Error, "Duplicate generate option force." if options[:force]
445
+
446
+ options[:force] = true
447
+ when SemanticVersion::PATTERN
448
+ raise Error, "Duplicate generate version #{value.inspect}." if options[:version]
449
+
450
+ options[:version] = value
451
+ when "module", "simple"
452
+ raise Error, "Duplicate generate format #{value.inspect}." if options[:format]
453
+
454
+ options[:format] = value
455
+ else
456
+ raise Error, "Unknown generate option #{value.inspect}. Use a semantic version, module, simple, or force."
457
+ end
380
458
  end
381
459
 
382
460
  ##
@@ -392,20 +470,43 @@ module Semverve
392
470
  version
393
471
  end
394
472
 
473
+ ##
474
+ # Optional exact version argument for check and fix tasks.
475
+ #
476
+ # @param [Rake::TaskArguments, nil] args
477
+ # @param [String] task_name
478
+ #
479
+ # @return [Semverve::SemanticVersion, nil]
480
+ def target_version_argument(args, task_name)
481
+ version = args&.[](:version)
482
+ return nil if version.nil? || version.empty?
483
+
484
+ SemanticVersion.parse(version)
485
+ rescue Error
486
+ raise Error, "Run rake '#{task_name}[MAJOR.MINOR.PATCH]'."
487
+ end
488
+
395
489
  ##
396
490
  # Fix results enabled for the umbrella fix task.
397
491
  #
398
492
  # @param [Semverve::ResolvedConfiguration] configuration
399
493
  # @param [Semverve::SemanticVersion] current_version
494
+ # @param [Semverve::SemanticVersion, nil] target_version
400
495
  #
401
496
  # @return [Array<Array(String, #replacement_count, #changed_files)>]
402
- def fix_results(configuration, current_version)
497
+ def fix_results(configuration, current_version, target_version = nil)
403
498
  results = []
404
499
  if configuration.version_checks.include?(:doc_references)
405
- results << ["version reference", VersionReferences.new(configuration, current_version).fix]
500
+ results << [
501
+ "version reference",
502
+ VersionReferences.new(configuration, current_version, target_version: target_version).fix
503
+ ]
406
504
  end
407
505
  if configuration.version_checks.include?(:code_references)
408
- results << ["code version literal", VersionCodeReferences.new(configuration, current_version).fix]
506
+ results << [
507
+ "code version literal",
508
+ VersionCodeReferences.new(configuration, current_version, target_version: target_version).fix
509
+ ]
409
510
  end
410
511
  if configuration.version_checks.include?(:metadata)
411
512
  results << ["metadata version", VersionMetadata.new(configuration, current_version).fix]
@@ -418,10 +519,12 @@ module Semverve
418
519
  #
419
520
  # @param [Array<Array(String, Array)>] groups
420
521
  # @param [Semverve::SemanticVersion] current_version
522
+ # @param [Semverve::SemanticVersion, nil] target_version
523
+ # @param [String, nil] fix_task_name
421
524
  # @param [String] clean_message
422
525
  #
423
526
  # @return [void]
424
- def report_findings(groups, current_version, clean_message:)
527
+ def report_findings(groups, current_version, clean_message:, target_version: nil, fix_task_name: nil)
425
528
  findings = groups.flat_map do |(label, group_findings)|
426
529
  group_findings.map { |finding| [label || finding.label, finding] }
427
530
  end
@@ -434,11 +537,36 @@ module Semverve
434
537
  findings.each do |(label, finding)|
435
538
  puts "#{finding.path}:#{finding.line}:#{finding.column}: #{label} #{finding.version} -> #{current_version}"
436
539
  end
540
+ if target_version == current_version && fix_task_name && reference_or_code_findings?(findings)
541
+ puts "Target version #{target_version} is already current; #{fix_task_name}[#{target_version}] will not change these references."
542
+ end
437
543
 
438
544
  issue = findings.one? ? "issue" : "issues"
439
545
  raise Error, "Found #{findings.count} version check #{issue}."
440
546
  end
441
547
 
548
+ ##
549
+ # Prints a no-op message for exact fix requests targeting the current version.
550
+ #
551
+ # @param [Semverve::SemanticVersion, nil] target_version
552
+ #
553
+ # @return [void]
554
+ def report_current_target_noop(target_version)
555
+ puts "Target version #{target_version} is already current; nothing to fix."
556
+ end
557
+
558
+ ##
559
+ # Whether findings include references controlled by exact-target fixes.
560
+ #
561
+ # @param [Array<Array(String, Object)>] findings
562
+ #
563
+ # @return [Boolean]
564
+ def reference_or_code_findings?(findings)
565
+ findings.any? do |(label, _finding)|
566
+ ["version reference", "code version literal"].include?(label)
567
+ end
568
+ end
569
+
442
570
  ##
443
571
  # Prints fix results.
444
572
  #
@@ -15,7 +15,7 @@ module Semverve
15
15
  # Minor version.
16
16
  #
17
17
  # @return [Integer]
18
- MINOR = 2
18
+ MINOR = 3
19
19
 
20
20
  ##
21
21
  # Patch version.
@@ -99,10 +99,11 @@ module Semverve
99
99
  # @param [Semverve::SemanticVersion] current_version
100
100
  #
101
101
  # @return [Semverve::VersionCodeReferences]
102
- def initialize(configuration, current_version, include_ignored: false)
102
+ def initialize(configuration, current_version, include_ignored: false, target_version: nil)
103
103
  @configuration = configuration
104
104
  @current_version = current_version
105
105
  @include_ignored = include_ignored
106
+ @target_version = target_version
106
107
  end
107
108
 
108
109
  ##
@@ -155,6 +156,12 @@ module Semverve
155
156
  # @return [Boolean]
156
157
  attr_reader :include_ignored
157
158
 
159
+ ##
160
+ # Exact version to match, when supplied by the task invocation.
161
+ #
162
+ # @return [Semverve::SemanticVersion, nil]
163
+ attr_reader :target_version
164
+
158
165
  ##
159
166
  # Absolute configured project root.
160
167
  #
@@ -198,7 +205,7 @@ module Semverve
198
205
  next unless match
199
206
 
200
207
  version = SemanticVersion.parse(match[:version])
201
- next if version == current_version
208
+ next unless report?(version)
202
209
 
203
210
  Finding.new(
204
211
  path: relative_path(path),
@@ -226,7 +233,7 @@ module Semverve
226
233
  next line unless match
227
234
 
228
235
  version = SemanticVersion.parse(match[:version])
229
- next line if version == current_version
236
+ next line unless report?(version)
230
237
 
231
238
  replacement_count += 1
232
239
  replace_matched_version(line)
@@ -252,6 +259,25 @@ module Semverve
252
259
  previous_nonblank_line&.include?(IGNORE_MARKER)
253
260
  end
254
261
 
262
+ ##
263
+ # Whether a referenced version should be reported or fixed.
264
+ #
265
+ # @param [Semverve::SemanticVersion] version
266
+ #
267
+ # @return [Boolean]
268
+ def report?(version)
269
+ return version == target_version if target_version
270
+
271
+ case configuration.version_match_mode
272
+ when :older
273
+ version < current_version
274
+ when :non_current
275
+ version != current_version
276
+ else
277
+ raise Error, "Unknown version match mode #{configuration.version_match_mode.inspect}. Use :older or :non_current."
278
+ end
279
+ end
280
+
255
281
  ##
256
282
  # Replaces only the named version capture in the first pattern match.
257
283
  #
@@ -107,10 +107,11 @@ module Semverve
107
107
  # @param [Semverve::SemanticVersion] current_version
108
108
  #
109
109
  # @return [Semverve::VersionReferences]
110
- def initialize(configuration, current_version, include_ignored: false)
110
+ def initialize(configuration, current_version, include_ignored: false, target_version: nil)
111
111
  @configuration = configuration
112
112
  @current_version = current_version
113
113
  @include_ignored = include_ignored
114
+ @target_version = target_version
114
115
  end
115
116
 
116
117
  ##
@@ -163,6 +164,12 @@ module Semverve
163
164
  # @return [Boolean]
164
165
  attr_reader :include_ignored
165
166
 
167
+ ##
168
+ # Exact version to match, when supplied by the task invocation.
169
+ #
170
+ # @return [Semverve::SemanticVersion, nil]
171
+ attr_reader :target_version
172
+
166
173
  ##
167
174
  # Absolute configured project root.
168
175
  #
@@ -377,13 +384,15 @@ module Semverve
377
384
  #
378
385
  # @return [Boolean]
379
386
  def report?(version)
380
- case configuration.version_reference_mode
387
+ return version == target_version if target_version
388
+
389
+ case configuration.version_match_mode
381
390
  when :older
382
391
  version < current_version
383
392
  when :non_current
384
393
  version != current_version
385
394
  else
386
- raise Error, "Unknown version reference mode #{configuration.version_reference_mode.inspect}. Use :older or :non_current."
395
+ raise Error, "Unknown version match mode #{configuration.version_match_mode.inspect}. Use :older or :non_current."
387
396
  end
388
397
  end
389
398
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semverve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Gray