Class: Kettle::Dev::VersionBump
- Inherits:
-
Object
- Object
- Kettle::Dev::VersionBump
- Defined in:
- lib/kettle/dev/version_bump.rb
Overview
Reusable engine behind kettle-bump.
Constant Summary collapse
- BUMP_TYPES =
%w[major minor patch pre].freeze
Instance Attribute Summary collapse
-
#current_version ⇒ Object
readonly
Returns the value of attribute current_version.
-
#from_version ⇒ Object
readonly
Returns the value of attribute from_version.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#target_version ⇒ Object
readonly
Returns the value of attribute target_version.
Class Method Summary collapse
- .bumped_prerelease_version(current_version) ⇒ Object
- .bumped_version(type, current_version) ⇒ Object
- .each_node(root) ⇒ Object
- .file_edit(path, source, start_offset, end_offset, replacement) ⇒ Object
- .parse_source(source, path) ⇒ Object
- .prerelease_suffix_for(current_version, release_core) ⇒ Object
- .quote_like(original, value) ⇒ Object
- .require_prism ⇒ Object
- .resolve_target_version(target, current_version) ⇒ Object
- .string_tail(value, offset) ⇒ Object
- .validate_version(version) ⇒ Object
- .version_string_node(source, path) ⇒ Object
- .write_edits(edits) ⇒ Object
Instance Method Summary collapse
- #edits ⇒ Object
-
#initialize(root:, target_version:, current_version: nil, from_version: nil) ⇒ VersionBump
constructor
A new instance of VersionBump.
- #write! ⇒ Object
Constructor Details
#initialize(root:, target_version:, current_version: nil, from_version: nil) ⇒ VersionBump
Returns a new instance of VersionBump.
129 130 131 132 133 134 |
# File 'lib/kettle/dev/version_bump.rb', line 129 def initialize(root:, target_version:, current_version: nil, from_version: nil) @root = root @current_version = current_version || Kettle::Dev::Versioning.detect_version(root) @target_version = self.class.resolve_target_version(target_version, @current_version) @from_version = self.class.validate_version(from_version) if from_version end |
Instance Attribute Details
#current_version ⇒ Object (readonly)
Returns the value of attribute current_version.
136 137 138 |
# File 'lib/kettle/dev/version_bump.rb', line 136 def current_version @current_version end |
#from_version ⇒ Object (readonly)
Returns the value of attribute from_version.
136 137 138 |
# File 'lib/kettle/dev/version_bump.rb', line 136 def from_version @from_version end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
136 137 138 |
# File 'lib/kettle/dev/version_bump.rb', line 136 def root @root end |
#target_version ⇒ Object (readonly)
Returns the value of attribute target_version.
136 137 138 |
# File 'lib/kettle/dev/version_bump.rb', line 136 def target_version @target_version end |
Class Method Details
.bumped_prerelease_version(current_version) ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/kettle/dev/version_bump.rb', line 45 def bumped_prerelease_version(current_version) version = Gem::Version.new(current_version) segments = version.segments prerelease_index = segments.index { |segment| !segment.is_a?(Integer) } unless prerelease_index raise Kettle::Dev::Error, "cannot pre-bump version without prerelease segment #{current_version.inspect}" end release_core = segments[0...prerelease_index].join(".") prerelease_suffix = prerelease_suffix_for(current_version, release_core) "#{release_core}.#{prerelease_suffix.next}" end |
.bumped_version(type, current_version) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/kettle/dev/version_bump.rb', line 25 def bumped_version(type, current_version) return bumped_prerelease_version(current_version) if type == "pre" version = Gem::Version.new(current_version) segments = version.segments unless segments.all? { |segment| segment.is_a?(Integer) } raise Kettle::Dev::Error, "cannot #{type}-bump non-numeric version #{current_version.inspect}" end major, minor, patch = (segments + [0, 0, 0])[0, 3] case type when "major" "#{major + 1}.0.0" when "minor" "#{major}.#{minor + 1}.0" when "patch" "#{major}.#{minor}.#{patch + 1}" end end |
.each_node(root) ⇒ Object
98 99 100 101 102 103 104 105 106 107 |
# File 'lib/kettle/dev/version_bump.rb', line 98 def each_node(root) return enum_for(__method__, root) unless block_given? queue = [root] until queue.empty? node = queue.shift yield node queue.concat(node.child_nodes.compact) if node.respond_to?(:child_nodes) end end |
.file_edit(path, source, start_offset, end_offset, replacement) ⇒ Object
109 110 111 |
# File 'lib/kettle/dev/version_bump.rb', line 109 def file_edit(path, source, start_offset, end_offset, replacement) {path: path, source: source, start_offset: start_offset, end_offset: end_offset, replacement: replacement} end |
.parse_source(source, path) ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/kettle/dev/version_bump.rb', line 82 def parse_source(source, path) require_prism parse_result = Prism.parse(source) raise Kettle::Dev::Error, "could not parse #{path}" unless parse_result.success? parse_result end |
.prerelease_suffix_for(current_version, release_core) ⇒ Object
58 59 60 61 62 63 64 65 66 |
# File 'lib/kettle/dev/version_bump.rb', line 58 def prerelease_suffix_for(current_version, release_core) prefix = "#{release_core}." return string_tail(current_version, prefix.length) if current_version.start_with?(prefix) canonical_version = Gem::Version.new(current_version).to_s return string_tail(canonical_version, prefix.length) if canonical_version.start_with?(prefix) raise Kettle::Dev::Error, "cannot find prerelease segment in version #{current_version.inspect}" end |
.quote_like(original, value) ⇒ Object
113 114 115 116 |
# File 'lib/kettle/dev/version_bump.rb', line 113 def quote_like(original, value) quote = original.start_with?("'") ? "'" : '"' "#{quote}#{value}#{quote}" end |
.require_prism ⇒ Object
90 91 92 93 94 95 96 |
# File 'lib/kettle/dev/version_bump.rb', line 90 def require_prism return if defined?(Prism) require "prism" rescue LoadError => error raise Kettle::Dev::Error, "kettle-bump requires Prism; install the prism gem or run on Ruby 3.3+ (#{error.})" end |
.resolve_target_version(target, current_version) ⇒ Object
10 11 12 13 14 15 16 17 |
# File 'lib/kettle/dev/version_bump.rb', line 10 def resolve_target_version(target, current_version) target = target.to_s if BUMP_TYPES.include?(target) bumped_version(target, current_version) else validate_version(target) end end |
.string_tail(value, offset) ⇒ Object
68 69 70 |
# File 'lib/kettle/dev/version_bump.rb', line 68 def string_tail(value, offset) value[offset, value.length - offset] end |
.validate_version(version) ⇒ Object
19 20 21 22 23 |
# File 'lib/kettle/dev/version_bump.rb', line 19 def validate_version(version) Gem::Version.new(version).to_s rescue ArgumentError => error raise Kettle::Dev::Error, "invalid version #{version.inspect}: #{error.}" end |
.version_string_node(source, path) ⇒ Object
72 73 74 75 76 77 78 79 80 |
# File 'lib/kettle/dev/version_bump.rb', line 72 def version_string_node(source, path) parse_result = parse_source(source, path) constant = each_node(parse_result.value).find do |node| node.is_a?(Prism::ConstantWriteNode) && node.name == :VERSION && node.value.is_a?(Prism::StringNode) end raise Kettle::Dev::Error, "could not find string VERSION constant in #{path}" unless constant constant.value end |
.write_edits(edits) ⇒ Object
118 119 120 121 122 123 124 125 126 |
# File 'lib/kettle/dev/version_bump.rb', line 118 def write_edits(edits) edits.group_by { |edit| edit.fetch(:path) }.each_value do |file_edits| source = file_edits.first.fetch(:source) file_edits.sort_by { |edit| -edit.fetch(:start_offset) }.each do |edit| source[edit.fetch(:start_offset)...edit.fetch(:end_offset)] = edit.fetch(:replacement) end File.write(file_edits.first.fetch(:path), source) end end |
Instance Method Details
#edits ⇒ Object
138 139 140 141 |
# File 'lib/kettle/dev/version_bump.rb', line 138 def edits validate_from_version version_file_edits + gemspec_version_edits end |
#write! ⇒ Object
143 144 145 |
# File 'lib/kettle/dev/version_bump.rb', line 143 def write! self.class.write_edits(edits) end |