Module: Kettle::Dev::ModularGemfiles

Defined in:
lib/kettle/dev/modular_gemfiles.rb

Overview

Utilities for copying modular Gemfiles and related directories
in a DRY fashion. Used by both the template rake task and the
setup CLI to ensure gemfiles/modular/* are present before use.

Constant Summary collapse

MODULAR_GEMFILE_DIR =
"gemfiles/modular"

Class Method Summary collapse

Class Method Details

.sync!(helpers:, project_root:, gem_checkout_root:, min_ruby: nil) ⇒ void

This method returns an undefined value.

Copy the modular gemfiles and nested directories from the gem
checkout into the target project, prompting where appropriate
via the provided helpers.

Parameters:

  • helpers (Kettle::Dev::TemplateHelpers)

    helper API

  • project_root (String)

    destination project root

  • gem_checkout_root (String)

    kettle-dev checkout root (source)

  • min_ruby (Gem::Version, nil) (defaults to: nil)

    minimum Ruby version (for style.gemfile tuning)



22
23
24
25
26
27
28
29
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/kettle/dev/modular_gemfiles.rb', line 22

def sync!(helpers:, project_root:, gem_checkout_root:, min_ruby: nil)
  # 4a) gemfiles/modular/*.gemfile except style.gemfile (handled below)
  modular_gemfiles = %w[
    coverage
    debug
    documentation
    injected
    optional
    runtime_heads
    x_std_libs
  ]
  modular_gemfiles.each do |base|
    modular_gemfile = "#{base}.gemfile"
    src = helpers.prefer_example(File.join(gem_checkout_root, MODULAR_GEMFILE_DIR, modular_gemfile))
    dest = File.join(project_root, MODULAR_GEMFILE_DIR, modular_gemfile)
    helpers.copy_file_with_prompt(src, dest, allow_create: true, allow_replace: true)
  end

  # 4b) gemfiles/modular/style.gemfile with dynamic rubocop constraints
  modular_gemfile = "style.gemfile"
  src = helpers.prefer_example(File.join(gem_checkout_root, MODULAR_GEMFILE_DIR, modular_gemfile))
  dest = File.join(project_root, MODULAR_GEMFILE_DIR, modular_gemfile)
  if File.basename(src).sub(/\.example\z/, "") == "style.gemfile"
    helpers.copy_file_with_prompt(src, dest, allow_create: true, allow_replace: true) do |content|
      # Adjust rubocop-lts constraint based on min_ruby
      version_map = [
        [Gem::Version.new("1.8"), "~> 0.1"],
        [Gem::Version.new("1.9"), "~> 2.0"],
        [Gem::Version.new("2.0"), "~> 4.0"],
        [Gem::Version.new("2.1"), "~> 6.0"],
        [Gem::Version.new("2.2"), "~> 8.0"],
        [Gem::Version.new("2.3"), "~> 10.0"],
        [Gem::Version.new("2.4"), "~> 12.0"],
        [Gem::Version.new("2.5"), "~> 14.0"],
        [Gem::Version.new("2.6"), "~> 16.0"],
        [Gem::Version.new("2.7"), "~> 18.0"],
        [Gem::Version.new("3.0"), "~> 20.0"],
        [Gem::Version.new("3.1"), "~> 22.0"],
        [Gem::Version.new("3.2"), "~> 24.0"],
        [Gem::Version.new("3.3"), "~> 26.0"],
        [Gem::Version.new("3.4"), "~> 28.0"],
      ]
      new_constraint = nil
      rubocop_ruby_gem_version = nil
      ruby1_8 = version_map.first
      begin
        if min_ruby
          version_map.reverse_each do |min, req|
            if min_ruby >= min
              new_constraint = req
              rubocop_ruby_gem_version = min.segments.join("_")
              break
            end
          end
        end
        if !new_constraint || !rubocop_ruby_gem_version
          # A gem with no declared minimum ruby is effectively >= 1.8.7
          new_constraint = ruby1_8[1]
          rubocop_ruby_gem_version = ruby1_8[0].segments.join("_")
        end
      rescue StandardError => e
        Kettle::Dev.debug_error(e, __method__) if defined?(Kettle::Dev.debug_error)
        # ignore, use default
      ensure
        new_constraint ||= ruby1_8[1]
        rubocop_ruby_gem_version ||= ruby1_8[0].segments.join("_")
      end
      if new_constraint && rubocop_ruby_gem_version
        token = "{RUBOCOP|LTS|CONSTRAINT}"
        content.gsub!(token, new_constraint) if content.include?(token)
        token = "{RUBOCOP|RUBY|GEM}"
        content.gsub!(token, "rubocop-ruby#{rubocop_ruby_gem_version}") if content.include?(token)
      end
      content
    end
  else
    helpers.copy_file_with_prompt(src, dest, allow_create: true, allow_replace: true)
  end

  # 4c) Copy modular directories with nested/versioned files
  %w[erb mutex_m stringio x_std_libs].each do |dir|
    src_dir = File.join(gem_checkout_root, MODULAR_GEMFILE_DIR, dir)
    dest_dir = File.join(project_root, MODULAR_GEMFILE_DIR, dir)
    helpers.copy_dir_with_prompt(src_dir, dest_dir)
  end
end