Class: RubyInstaller::Build::Msys2Installation

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby_installer/build/msys2_installation.rb

Overview

:nodoc:

Defined Under Namespace

Classes: CommandError, MsysNotFound

Constant Summary collapse

MSYS2_INSTALL_KEY =
"SOFTWARE/Microsoft/Windows/CurrentVersion/Uninstall/"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(msys_path: nil, mingwarch: nil, mingw_package_prefix: nil, ruby_bin_dir: nil) ⇒ Msys2Installation



19
20
21
22
23
24
25
26
# File 'lib/ruby_installer/build/msys2_installation.rb', line 19

def initialize(msys_path: nil, mingwarch: nil, mingw_package_prefix: nil, ruby_bin_dir: nil)
  @msys_path = msys_path
  @msys_path_fixed = msys_path ? true : false
  @mingwdir = nil
  @mingwarch = mingwarch || (RUBY_PLATFORM=~/x64/ ? 'mingw64' : 'mingw32')
  @mingw_package_prefix = mingw_package_prefix || (RUBY_PLATFORM=~/x64/ ? "mingw-w64-x86_64" : "mingw-w64-i686")
  @ruby_bin_dir = ruby_bin_dir || File.join(RbConfig::TOPDIR, "bin")
end

Instance Attribute Details

#mingw_package_prefixObject (readonly)

Returns the value of attribute mingw_package_prefix.



16
17
18
# File 'lib/ruby_installer/build/msys2_installation.rb', line 16

def mingw_package_prefix
  @mingw_package_prefix
end

#mingwarchObject (readonly)

Returns the value of attribute mingwarch.



15
16
17
# File 'lib/ruby_installer/build/msys2_installation.rb', line 15

def mingwarch
  @mingwarch
end

#mingwdirObject (readonly)

Returns the value of attribute mingwdir.



14
15
16
# File 'lib/ruby_installer/build/msys2_installation.rb', line 14

def mingwdir
  @mingwdir
end

#ruby_bin_dirObject (readonly)

Returns the value of attribute ruby_bin_dir.



17
18
19
# File 'lib/ruby_installer/build/msys2_installation.rb', line 17

def ruby_bin_dir
  @ruby_bin_dir
end

Instance Method Details

#disable_dll_search_pathsObject



106
107
108
109
# File 'lib/ruby_installer/build/msys2_installation.rb', line 106

def disable_dll_search_paths
  @mingwdir.remove if @mingwdir
  @mingwdir = nil
end

#disable_msys_apps(if_no_msys: :hint) ⇒ Object



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/ruby_installer/build/msys2_installation.rb', line 176

def disable_msys_apps(if_no_msys: :hint)
  vars = with_msys_install_hint(if_no_msys) do
    msys_apps_envvars
  end
  changed = false
  if path=vars.delete("PATH")
    old_path = ENV['PATH']
    ENV['PATH'] = old_path.gsub(path + ";", "")
    changed = ENV['PATH'] != old_path
  end
  vars.each do |key, val|
    changed = true if ENV[key]
    ENV.delete(key)
  end

  changed
end

#disable_msys_apps_per_cmdObject

This method is used for the ridk command.



224
225
226
227
228
229
230
231
232
233
# File 'lib/ruby_installer/build/msys2_installation.rb', line 224

def disable_msys_apps_per_cmd
  vars = with_msys_install_hint{ msys_apps_envvars }
  str = "".dup
  if path=vars.delete("PATH")
    str << "PATH=#{ ENV['PATH'].gsub(path + ";", "") }\n"
  end
  str << vars.map do |key, val|
    "#{key}="
  end.join("\n")
end

#disable_msys_apps_per_ps1Object

This method is used for the ridk command.



247
248
249
250
251
252
253
254
255
256
# File 'lib/ruby_installer/build/msys2_installation.rb', line 247

def disable_msys_apps_per_ps1
  vars = with_msys_install_hint{ msys_apps_envvars }
  str = "".dup
  if path=vars.delete("PATH")
    str << "$env:PATH=\"#{ ENV['PATH'].gsub(path + ";", "").gsub('"', '`"') }\";"
  end
  str << vars.map do |key, val|
    "$env:#{key}=''"
  end.join(";")
end

#enable_dll_search_pathsObject



96
97
98
99
100
101
102
103
104
# File 'lib/ruby_installer/build/msys2_installation.rb', line 96

def enable_dll_search_paths
  @mingwdir ||= begin
    DllDirectory.set_defaults
    path = mingw_bin_path
    DllDirectory.new(path) if File.directory?(path)
  rescue MsysNotFound
    # We silently ignore this error to allow Ruby installations without MSYS2.
  end
end

#enable_msys_apps(if_no_msys: :hint, for_gem_install: false) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/ruby_installer/build/msys2_installation.rb', line 151

def enable_msys_apps(if_no_msys: :hint, for_gem_install: false)
  vars = with_msys_install_hint(if_no_msys) do
    msys_apps_envvars
  end

  changed = false

  if (path=vars.delete("PATH")) && !ENV['PATH'].include?(path)
    phrase = "Temporarily enhancing PATH for MSYS/MINGW..."
    if for_gem_install && defined?(Gem)
      Gem.ui.say(phrase) if Gem.configuration.verbose
    elsif $DEBUG
      $stderr.puts phrase
    end
    changed = true
    ENV['PATH'] = path + ";" + ENV['PATH']
  end
  vars.each do |key, val|
    changed = true if ENV[key] != val
    ENV[key] = val
  end

  changed
end

#enable_msys_apps_per_cmdObject

This method is used for the ridk command.



213
214
215
216
217
218
219
220
221
# File 'lib/ruby_installer/build/msys2_installation.rb', line 213

def enable_msys_apps_per_cmd
  vars = with_msys_install_hint{ msys_apps_envvars }
  if (path=vars.delete("PATH")) && !ENV['PATH'].include?(path)
    vars['PATH'] = path + ";" + ENV['PATH']
  end
  vars.map do |key, val|
    "#{key}=#{val}"
  end.join("\n")
end

#enable_msys_apps_per_ps1Object

This method is used for the ridk command.



236
237
238
239
240
241
242
243
244
# File 'lib/ruby_installer/build/msys2_installation.rb', line 236

def enable_msys_apps_per_ps1
  vars = with_msys_install_hint{ msys_apps_envvars }
  if (path=vars.delete("PATH")) && !ENV['PATH'].include?(path)
    vars['PATH'] = path + ";" + ENV['PATH']
  end
  vars.map do |key, val|
    "$env:#{key}=\"#{val.gsub('"', '`"')}\""
  end.join(";")
end

#install_mingw_packages(packages, verbose: false) ⇒ Object



274
275
276
277
# File 'lib/ruby_installer/build/msys2_installation.rb', line 274

def install_mingw_packages(packages, verbose: false)
  packages = packages.map{|pack| "#{mingw_package_prefix}-#{pack}" }
  install_packages(packages, verbose: verbose)
end

#install_packages(packages, verbose: false) ⇒ Object



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/ruby_installer/build/msys2_installation.rb', line 258

def install_packages(packages, verbose: false)
  return if packages.empty?

  with_msys_apps_enabled do
    Gem.ui.say("Installing required msys2 packages: #{packages.join(" ")}") if verbose

    args = ["pacman", "-S", "--needed", "--noconfirm", *packages]
    Gem.ui.say("> #{args.join(" ")}") if verbose==1

    res = IO.popen(args, &:read)
    raise CommandError, "pacman failed with the following output:\n#{res}" if !$? || $?.exitstatus != 0

    Gem.ui.say(res) if verbose==1
  end
end

#iterate_msys_paths {|File.join(RbConfig::TOPDIR, "msys64")| ... } ⇒ Object

Yields:

  • (File.join(RbConfig::TOPDIR, "msys64"))

Raises:



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
# File 'lib/ruby_installer/build/msys2_installation.rb', line 32

def iterate_msys_paths
  # Prefer MSYS2 when installed within the ruby directory.
  yield File.join(RbConfig::TOPDIR, "msys64")
  yield File.join(RbConfig::TOPDIR, "msys32")

  # Then try MSYS2 next to the ruby directory.
  yield File.join(File.dirname(RbConfig::TOPDIR), "msys64")
  yield File.join(File.dirname(RbConfig::TOPDIR), "msys32")

  # If msys2 is installed at the default location
  yield "c:/msys64"
  yield "c:/msys32"

  # If msys2 is installed per installer.exe
  require "win32/registry"
  begin
    Win32::Registry::HKEY_CURRENT_USER.open(backslachs(MSYS2_INSTALL_KEY)) do |reg|
      reg.each_key do |subkey|
        subreg = reg.open(subkey)
        begin
          if subreg['DisplayName'] =~ /^MSYS2 / && File.directory?(il=subreg['InstallLocation'])
            yield il
          end
        rescue Encoding::InvalidByteSequenceError, Win32::Registry::Error
          # Ignore entries without valid installer data or broken character encoding
        end
      end
    end
  rescue Win32::Registry::Error
  end

  ENV['PATH'].split(";").each do |path|
    # If /path/to/msys64 is in the PATH (e.g. Chocolatey)
    yield path
  end

  # If msys2 is installed by scoop package manager
  yield IO.popen(["scoop", "prefix", "msys2"], &:read).strip rescue StandardError

  raise MsysNotFound, "MSYS2 could not be found"
end

#mingw_bin_pathObject



88
89
90
# File 'lib/ruby_installer/build/msys2_installation.rb', line 88

def mingw_bin_path
  backslachs( File.join(msys_path, mingwarch, "bin") )
end

#mingw_prefixObject



92
93
94
# File 'lib/ruby_installer/build/msys2_installation.rb', line 92

def mingw_prefix
  "/#{mingwarch}"
end

#msys_bin_pathObject



84
85
86
# File 'lib/ruby_installer/build/msys2_installation.rb', line 84

def msys_bin_path
  backslachs( File.join(msys_path, "/usr/bin") )
end

#msys_pathObject



74
75
76
77
78
79
80
81
82
# File 'lib/ruby_installer/build/msys2_installation.rb', line 74

def msys_path
  @msys_path ||= begin
    iterate_msys_paths do |path|
      if File.exist?(File.join(path, "usr/bin/msys-2.0.dll"))
        break backslachs(path)
      end
    end
  end
end

#reset_cacheObject



28
29
30
# File 'lib/ruby_installer/build/msys2_installation.rb', line 28

def reset_cache
  @msys_path = nil unless @msys_path_fixed
end

#with_msys_apps_disabled(**args) ⇒ Object



203
204
205
206
207
208
209
210
# File 'lib/ruby_installer/build/msys2_installation.rb', line 203

def with_msys_apps_disabled(**args)
  changed = disable_msys_apps(**args)
  begin
    yield
  ensure
    enable_msys_apps(**args) if changed
  end
end

#with_msys_apps_enabled(**args) ⇒ Object



194
195
196
197
198
199
200
201
# File 'lib/ruby_installer/build/msys2_installation.rb', line 194

def with_msys_apps_enabled(**args)
  changed = enable_msys_apps(**args)
  begin
    yield
  ensure
    disable_msys_apps(**args) if changed
  end
end