Class: Kettle::Changelog::TransferMerger

Inherits:
Object
  • Object
show all
Defined in:
lib/kettle/changelog/transfer_merger.rb

Constant Summary collapse

STANDARD_HEADINGS =
%w[Added Changed Deprecated Removed Fixed Security].freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content:, entries:, excluded_keys: []) ⇒ TransferMerger

Returns a new instance of TransferMerger.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/kettle/changelog/transfer_merger.rb', line 12

def initialize(content:, entries:, excluded_keys: [])
  @content = content.to_s
  @entries = Array(entries).filter_map do |entry|
    next unless entry.is_a?(Hash)

    key = entry_value(entry, :key).to_s
    lines = Array(entry_value(entry, :lines))
    next if key.empty? || lines.empty?

    {
      key: key,
      section: entry_value(entry, :section),
      lines: lines
    }
  end
  @excluded_keys = Array(excluded_keys).map(&:to_s).reject(&:empty?).to_set
end

Class Method Details

.apply(content:, entries:, excluded_keys: []) ⇒ Object



8
9
10
# File 'lib/kettle/changelog/transfer_merger.rb', line 8

def self.apply(content:, entries:, excluded_keys: [])
  new(content: content, entries: entries, excluded_keys: excluded_keys).run
end

Instance Method Details

#runObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/kettle/changelog/transfer_merger.rb', line 30

def run
  normalized = remove_excluded_entries(@content)
  existing_keys = transfer_occurrences(normalized).map { |occurrence| occurrence.fetch(:key) }.to_set
  missing = @entries.reject { |entry| existing_keys.include?(entry.fetch(:key).to_s) }
  return ensure_trailing_newline(normalized) if missing.empty?

  lines = source_lines(normalized)
  unreleased = unreleased_line_index(lines)
  return ensure_trailing_newline(normalized) unless unreleased

  destination_end = unreleased_end_index(lines, unreleased)
  destination_body = lines[(unreleased + 1)...destination_end] || []
  items = changelog_items(destination_body)
  missing.group_by { |entry| entry.fetch(:section, "### Changed") }.each do |section, section_entries|
    section = STANDARD_HEADINGS.include?(section.to_s.delete_prefix("### ")) ? "### #{section.to_s.delete_prefix("### ").strip}" : "### Changed"
    items[section] ||= []
    items[section].pop while items[section].any? && items[section].last.to_s.strip.empty?
    items[section] << "" if items[section].any?
    section_entries.each do |entry|
      items[section].concat(Array(entry.fetch(:lines)).map(&:rstrip))
    end
  end

  merged_lines = lines[0...unreleased] +
    build_unreleased_section(lines.fetch(unreleased), items) +
    lines[destination_end..].to_a
  ensure_trailing_newline(merged_lines.join("\n").gsub(/\n{3,}/, "\n\n"))
end