semverve 0.3.0 → 0.4.1

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.
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "error"
4
+
5
+ module Semverve
6
+ ##
7
+ # Rewrites a named capture inside the first match for a safe version literal.
8
+ class VersionLiteralRewriter
9
+ ##
10
+ # Initializes a literal rewriter.
11
+ #
12
+ # @param [Regexp] pattern
13
+ # @param [String, #to_s] replacement
14
+ # @param [Symbol, String] capture
15
+ #
16
+ # @return [Semverve::VersionLiteralRewriter]
17
+ def initialize(pattern:, replacement:, capture: :version)
18
+ @pattern = pattern
19
+ @replacement = replacement.to_s
20
+ @capture_name = capture.to_s
21
+ @capture_key = capture.to_sym
22
+
23
+ validate_capture
24
+ end
25
+
26
+ ##
27
+ # Rewrites the configured capture in +text+.
28
+ #
29
+ # @param [String] text
30
+ #
31
+ # @return [String]
32
+ def rewrite(text)
33
+ text.sub(pattern) do |matched_text|
34
+ match = Regexp.last_match
35
+ capture_start = match.begin(capture_key) - match.begin(0)
36
+ capture_end = match.end(capture_key) - match.begin(0)
37
+
38
+ "#{matched_text[0...capture_start]}#{replacement}#{matched_text[capture_end..]}"
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ ##
45
+ # Safe literal pattern.
46
+ #
47
+ # @return [Regexp]
48
+ attr_reader :pattern
49
+
50
+ ##
51
+ # Replacement text.
52
+ #
53
+ # @return [String]
54
+ attr_reader :replacement
55
+
56
+ ##
57
+ # Named capture as a string.
58
+ #
59
+ # @return [String]
60
+ attr_reader :capture_name
61
+
62
+ ##
63
+ # Named capture as a symbol.
64
+ #
65
+ # @return [Symbol]
66
+ attr_reader :capture_key
67
+
68
+ ##
69
+ # Validates that the pattern can be rewritten safely.
70
+ #
71
+ # @return [void]
72
+ def validate_capture
73
+ return if pattern.named_captures.key?(capture_name)
74
+
75
+ raise Error, "version literal pattern must include a named capture called #{capture_name}."
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "error"
4
+
5
+ module Semverve
6
+ ##
7
+ # Decides whether a discovered version should be reported or fixed.
8
+ class VersionMatchPolicy
9
+ ##
10
+ # Initializes a version match policy.
11
+ #
12
+ # @param [Semverve::SemanticVersion] current_version
13
+ # @param [Symbol, String] match_mode
14
+ # @param [Semverve::SemanticVersion, nil] target_version
15
+ #
16
+ # @return [Semverve::VersionMatchPolicy]
17
+ def initialize(current_version:, match_mode:, target_version: nil)
18
+ @current_version = current_version
19
+ @match_mode = match_mode.to_sym
20
+ @target_version = target_version
21
+ end
22
+
23
+ ##
24
+ # Whether the version should be reported or fixed.
25
+ #
26
+ # @param [Semverve::SemanticVersion] version
27
+ #
28
+ # @return [Boolean]
29
+ def report?(version)
30
+ return version == target_version if target_version
31
+
32
+ case match_mode
33
+ when :older
34
+ version < current_version
35
+ when :non_current
36
+ version != current_version
37
+ else
38
+ raise Error, "Unknown version match mode #{match_mode.inspect}. Use :older or :non_current."
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ ##
45
+ # Current Semverve version.
46
+ #
47
+ # @return [Semverve::SemanticVersion]
48
+ attr_reader :current_version
49
+
50
+ ##
51
+ # Matching mode when no exact target version is supplied.
52
+ #
53
+ # @return [Symbol]
54
+ attr_reader :match_mode
55
+
56
+ ##
57
+ # Exact version to match.
58
+ #
59
+ # @return [Semverve::SemanticVersion, nil]
60
+ attr_reader :target_version
61
+ end
62
+ end
@@ -2,9 +2,11 @@
2
2
 
3
3
  require "ripper"
4
4
 
5
- require_relative "error"
6
5
  require_relative "file_list_resolver"
6
+ require_relative "finding"
7
+ require_relative "fix_result"
7
8
  require_relative "semantic_version"
9
+ require_relative "version_match_policy"
8
10
 
9
11
  module Semverve
10
12
  ##
@@ -28,78 +30,6 @@ module Semverve
28
30
  # @return [Array<String>]
29
31
  TEXT_EXTENSIONS = %w[.adoc .markdown .md .rdoc .txt].freeze
30
32
 
31
- ##
32
- # A stale or non-current version reference found in a project file.
33
- class Finding
34
- ##
35
- # Path relative to the configured project root.
36
- #
37
- # @return [String]
38
- attr_reader :path
39
-
40
- ##
41
- # One-based line number.
42
- #
43
- # @return [Integer]
44
- attr_reader :line
45
-
46
- ##
47
- # One-based column number.
48
- #
49
- # @return [Integer]
50
- attr_reader :column
51
-
52
- ##
53
- # Referenced semantic version.
54
- #
55
- # @return [Semverve::SemanticVersion]
56
- attr_reader :version
57
-
58
- ##
59
- # Initializes a finding.
60
- #
61
- # @param [String] path
62
- # @param [Integer] line
63
- # @param [Integer] column
64
- # @param [Semverve::SemanticVersion] version
65
- #
66
- # @return [Semverve::VersionReferences::Finding]
67
- def initialize(path:, line:, column:, version:)
68
- @path = path
69
- @line = line
70
- @column = column
71
- @version = version
72
- end
73
- end
74
-
75
- ##
76
- # Result of fixing version references.
77
- class FixResult
78
- ##
79
- # Files changed by the fix.
80
- #
81
- # @return [Array<String>]
82
- attr_reader :changed_files
83
-
84
- ##
85
- # Number of replacements made.
86
- #
87
- # @return [Integer]
88
- attr_reader :replacement_count
89
-
90
- ##
91
- # Initializes a fix result.
92
- #
93
- # @param [Array<String>] changed_files
94
- # @param [Integer] replacement_count
95
- #
96
- # @return [Semverve::VersionReferences::FixResult]
97
- def initialize(changed_files:, replacement_count:)
98
- @changed_files = changed_files
99
- @replacement_count = replacement_count
100
- end
101
- end
102
-
103
33
  ##
104
34
  # Initializes version-reference scanning.
105
35
  #
@@ -117,7 +47,7 @@ module Semverve
117
47
  ##
118
48
  # Version-reference findings in configured files.
119
49
  #
120
- # @return [Array<Semverve::VersionReferences::Finding>]
50
+ # @return [Array<Semverve::Finding>]
121
51
  def findings
122
52
  files.flat_map { |path| findings_for_file(path) }
123
53
  end
@@ -125,7 +55,7 @@ module Semverve
125
55
  ##
126
56
  # Replaces found version references with the current version.
127
57
  #
128
- # @return [Semverve::VersionReferences::FixResult]
58
+ # @return [Semverve::FixResult]
129
59
  def fix
130
60
  changed_files = []
131
61
  replacement_count = 0
@@ -141,7 +71,7 @@ module Semverve
141
71
  replacement_count += count
142
72
  end
143
73
 
144
- FixResult.new(changed_files: changed_files, replacement_count: replacement_count)
74
+ Semverve::FixResult.new(changed_files: changed_files, replacement_count: replacement_count)
145
75
  end
146
76
 
147
77
  private
@@ -202,7 +132,7 @@ module Semverve
202
132
  #
203
133
  # @param [String] path
204
134
  #
205
- # @return [Array<Semverve::VersionReferences::Finding>]
135
+ # @return [Array<Semverve::Finding>]
206
136
  def findings_for_file(path)
207
137
  content = File.read(path)
208
138
 
@@ -324,10 +254,10 @@ module Semverve
324
254
  # @param [Hash] segment
325
255
  # @param [String] content
326
256
  #
327
- # @return [Array<Semverve::VersionReferences::Finding>]
257
+ # @return [Array<Semverve::Finding>]
328
258
  def findings_for_segment(path, segment, content)
329
259
  references_for_segment(segment, content).map do |reference|
330
- Finding.new(
260
+ Semverve::Finding.new(
331
261
  path: relative_path(path),
332
262
  line: segment[:line],
333
263
  column: reference[:column],
@@ -386,14 +316,7 @@ module Semverve
386
316
  def report?(version)
387
317
  return version == target_version if target_version
388
318
 
389
- case configuration.version_match_mode
390
- when :older
391
- version < current_version
392
- when :non_current
393
- version != current_version
394
- else
395
- raise Error, "Unknown version match mode #{configuration.version_match_mode.inspect}. Use :older or :non_current."
396
- end
319
+ match_policy.report?(version)
397
320
  end
398
321
 
399
322
  ##
@@ -414,6 +337,18 @@ module Semverve
414
337
  previous_nonblank_line&.include?(IGNORE_MARKER)
415
338
  end
416
339
 
340
+ ##
341
+ # Version matching behavior for references.
342
+ #
343
+ # @return [Semverve::VersionMatchPolicy]
344
+ def match_policy
345
+ @match_policy ||= VersionMatchPolicy.new(
346
+ current_version: current_version,
347
+ match_mode: configuration.version_match_mode,
348
+ target_version: target_version
349
+ )
350
+ end
351
+
417
352
  ##
418
353
  # Starting index for each line in content.
419
354
  #
data/lib/semverve.rb CHANGED
@@ -1,5 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "semverve/finding"
4
+ require_relative "semverve/fix_result"
5
+ require_relative "semverve/version_literal_rewriter"
6
+ require_relative "semverve/version_match_policy"
3
7
  require_relative "semverve/configuration"
4
8
  require_relative "semverve/version"
5
9
 
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.3.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Gray
@@ -107,26 +107,32 @@ files:
107
107
  - LICENSE
108
108
  - README.md
109
109
  - Rakefile
110
+ - UPGRADING.md
110
111
  - lib/semverve.rb
112
+ - lib/semverve/adapters.rb
111
113
  - lib/semverve/configuration.rb
112
- - lib/semverve/docs_publisher.rb
113
- - lib/semverve/docs_publisher/task.rb
114
114
  - lib/semverve/error.rb
115
115
  - lib/semverve/file_list_resolver.rb
116
+ - lib/semverve/finding.rb
117
+ - lib/semverve/fix_result.rb
116
118
  - lib/semverve/formats.rb
117
119
  - lib/semverve/formats/module_constants.rb
118
120
  - lib/semverve/formats/simple_string.rb
119
121
  - lib/semverve/generator.rb
122
+ - lib/semverve/package_metadata.rb
120
123
  - lib/semverve/presets.rb
121
124
  - lib/semverve/project_metadata.rb
122
125
  - lib/semverve/published_version.rb
126
+ - lib/semverve/rails_config_metadata.rb
123
127
  - lib/semverve/railtie.rb
124
128
  - lib/semverve/semantic_version.rb
125
129
  - lib/semverve/task.rb
126
130
  - lib/semverve/version.rb
131
+ - lib/semverve/version_checks.rb
127
132
  - lib/semverve/version_code_references.rb
128
133
  - lib/semverve/version_file.rb
129
- - lib/semverve/version_metadata.rb
134
+ - lib/semverve/version_literal_rewriter.rb
135
+ - lib/semverve/version_match_policy.rb
130
136
  - lib/semverve/version_references.rb
131
137
  - semverve.gemspec
132
138
  homepage: https://github.com/evanthegrayt/semverve
@@ -1,166 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rake"
4
-
5
- require_relative "../docs_publisher"
6
-
7
- module Semverve
8
- class DocsPublisher
9
- ##
10
- # Defines Rake tasks for publishing generated documentation.
11
- class Task
12
- include Rake::DSL
13
-
14
- ##
15
- # Source project root.
16
- #
17
- # @return [String]
18
- attr_accessor :root
19
-
20
- ##
21
- # Rake task that builds documentation before publishing.
22
- #
23
- # @return [String]
24
- attr_accessor :build_task
25
-
26
- ##
27
- # Directory containing generated documentation.
28
- #
29
- # @return [String]
30
- attr_accessor :source_dir
31
-
32
- ##
33
- # Documentation directory on the publishing branch.
34
- #
35
- # @return [String]
36
- attr_accessor :target_dir
37
-
38
- ##
39
- # Branch that receives generated documentation.
40
- #
41
- # @return [String]
42
- attr_accessor :branch
43
-
44
- ##
45
- # Remote used when pushing the publishing branch.
46
- #
47
- # @return [String]
48
- attr_accessor :remote
49
-
50
- ##
51
- # Commit message for generated documentation updates.
52
- #
53
- # @return [String]
54
- attr_accessor :commit_message
55
-
56
- ##
57
- # Optional path for the temporary worktree.
58
- #
59
- # @return [String, nil]
60
- attr_accessor :worktree_path
61
-
62
- ##
63
- # Whether dirty source working trees are allowed.
64
- #
65
- # @return [Boolean]
66
- attr_accessor :allow_dirty
67
-
68
- ##
69
- # Whether the publishing branch should be pushed.
70
- #
71
- # @return [Boolean]
72
- attr_accessor :push
73
-
74
- ##
75
- # Output stream for status messages.
76
- #
77
- # @return [#puts]
78
- attr_accessor :output
79
-
80
- ##
81
- # Namespace for the generated tasks.
82
- #
83
- # @return [Symbol, String]
84
- attr_accessor :task_namespace
85
-
86
- ##
87
- # Initializes and defines documentation publishing tasks.
88
- #
89
- # @yieldparam [Semverve::DocsPublisher::Task] task
90
- #
91
- # @return [Semverve::DocsPublisher::Task]
92
- def initialize
93
- @root = Dir.pwd
94
- @build_task = "rerdoc"
95
- @source_dir = "docs"
96
- @target_dir = "docs"
97
- @branch = "gh-pages"
98
- @remote = "origin"
99
- @commit_message = "Update generated documentation"
100
- @worktree_path = nil
101
- @allow_dirty = false
102
- @push = true
103
- @output = $stdout
104
- @task_namespace = :docs
105
-
106
- yield self if block_given?
107
-
108
- define
109
- end
110
-
111
- ##
112
- # Defines the documentation publishing tasks.
113
- #
114
- # @return [void]
115
- def define
116
- namespace namespace_name do
117
- desc "Publish generated documentation to #{branch}"
118
- task :publish do
119
- publish(dry_run: false)
120
- end
121
-
122
- namespace :publish do
123
- desc "Show whether generated documentation would change #{branch}"
124
- task :dry_run do
125
- publish(dry_run: true)
126
- end
127
- end
128
- end
129
- end
130
-
131
- private
132
-
133
- ##
134
- # Normalized namespace name.
135
- #
136
- # @return [Symbol]
137
- def namespace_name
138
- task_namespace.to_sym
139
- end
140
-
141
- ##
142
- # Builds and publishes documentation.
143
- #
144
- # @param [Boolean] dry_run
145
- #
146
- # @return [void]
147
- def publish(dry_run:)
148
- Rake::Task[build_task].invoke
149
-
150
- DocsPublisher.new do |publisher|
151
- publisher.root = root
152
- publisher.source_dir = source_dir
153
- publisher.target_dir = target_dir
154
- publisher.branch = branch
155
- publisher.remote = remote
156
- publisher.commit_message = commit_message
157
- publisher.worktree_path = worktree_path
158
- publisher.allow_dirty = allow_dirty
159
- publisher.push = push
160
- publisher.dry_run = dry_run
161
- publisher.output = output
162
- end.publish
163
- end
164
- end
165
- end
166
- end