summaryrefslogtreecommitdiff
path: root/spec/bundler/support/rubygems_ext.rb
blob: 62ba4d56c48b64948e5b048fba20a7078f8413a4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# frozen_string_literal: true

require_relative "path"

$LOAD_PATH.unshift(Spec::Path.source_lib_dir.to_s)

module Spec
  module Rubygems
    extend self

    def dev_setup
      install_gems(dev_gemfile)
    end

    def gem_load(gem_name, bin_container)
      require_relative "switch_rubygems"

      gem_load_and_activate(gem_name, bin_container)
    end

    def gem_require(gem_name)
      gem_activate(gem_name)
      require gem_name
    end

    def test_setup
      setup_test_paths

      require "fileutils"

      FileUtils.mkdir_p(Path.home)
      FileUtils.mkdir_p(Path.tmpdir)

      ENV["HOME"] = Path.home.to_s
      ENV["TMPDIR"] = Path.tmpdir.to_s

      require "rubygems/user_interaction"
      Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
    end

    def install_parallel_test_deps
      Gem.clear_paths

      require "parallel"
      require "fileutils"

      install_test_deps

      (2..Parallel.processor_count).each do |n|
        source = Path.source_root.join("tmp", "1")
        destination = Path.source_root.join("tmp", n.to_s)

        FileUtils.rm_rf destination
        FileUtils.cp_r source, destination
      end
    end

    def setup_test_paths
      Gem.clear_paths

      ENV["BUNDLE_PATH"] = nil
      ENV["GEM_HOME"] = ENV["GEM_PATH"] = Path.base_system_gem_path.to_s
      ENV["PATH"] = [Path.system_gem_path.join("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
      ENV["PATH"] = [Path.bindir, ENV["PATH"]].join(File::PATH_SEPARATOR) if Path.ruby_core?
    end

    def install_test_deps
      install_gems(test_gemfile, Path.base_system_gems.to_s)
      install_gems(rubocop_gemfile, Path.rubocop_gems.to_s)
      install_gems(standard_gemfile, Path.standard_gems.to_s)
    end

    def check_source_control_changes(success_message:, error_message:)
      require "open3"

      output, status = Open3.capture2e("git status --porcelain")

      if status.success? && output.empty?
        puts
        puts success_message
        puts
      else
        system("git status --porcelain")

        puts
        puts error_message
        puts

        exit(1)
      end
    end

    private

    def gem_load_and_activate(gem_name, bin_container)
      gem_activate(gem_name)
      load Gem.bin_path(gem_name, bin_container)
    rescue Gem::LoadError => e
      abort "We couldn't activate #{gem_name} (#{e.requirement}). Run `gem install #{gem_name}:'#{e.requirement}'`"
    end

    def gem_activate(gem_name)
      require "bundler"
      gem_requirement = Bundler::LockfileParser.new(File.read(dev_lockfile)).dependencies[gem_name]&.requirement
      gem gem_name, gem_requirement
    end

    def install_gems(gemfile, path = nil)
      old_gemfile = ENV["BUNDLE_GEMFILE"]
      old_orig_gemfile = ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"]
      ENV["BUNDLE_GEMFILE"] = gemfile.to_s
      ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = nil

      if path
        old_path = ENV["BUNDLE_PATH"]
        ENV["BUNDLE_PATH"] = path
      else
        old_path__system = ENV["BUNDLE_PATH__SYSTEM"]
        ENV["BUNDLE_PATH__SYSTEM"] = "true"
      end

      output = `#{Gem.ruby} #{File.expand_path("support/bundle.rb", Path.spec_dir)} install`
      raise "Error when installing gems in #{gemfile}: #{output}" unless $?.success?
    ensure
      if path
        ENV["BUNDLE_PATH"] = old_path
      else
        ENV["BUNDLE_PATH__SYSTEM"] = old_path__system
      end

      ENV["BUNDLER_ORIG_BUNDLE_GEMFILE"] = old_orig_gemfile
      ENV["BUNDLE_GEMFILE"] = old_gemfile
    end

    def test_gemfile
      Path.test_gemfile
    end

    def rubocop_gemfile
      Path.rubocop_gemfile
    end

    def standard_gemfile
      Path.standard_gemfile
    end

    def dev_gemfile
      Path.dev_gemfile
    end

    def dev_lockfile
      lockfile_for(dev_gemfile)
    end

    def lockfile_for(gemfile)
      Pathname.new("#{gemfile.expand_path}.lock")
    end
  end
end