Class: Gel::Package::Installer::GemInstaller
- Inherits:
-
Object
- Object
- Gel::Package::Installer::GemInstaller
- Defined in:
- lib/gel/package/installer.rb
Instance Attribute Summary collapse
-
#build_path ⇒ Object
readonly
Returns the value of attribute build_path.
-
#root ⇒ Object
readonly
Returns the value of attribute root.
-
#spec ⇒ Object
readonly
Returns the value of attribute spec.
-
#store ⇒ Object
readonly
Returns the value of attribute store.
Instance Method Summary collapse
- #abort! ⇒ Object
- #build_command(work_dir, log, *command, rake: false, **options) ⇒ Object
- #build_environment(rake: false) ⇒ Object
- #compile ⇒ Object
- #compile_extconf(ext, install_dir) ⇒ Object
- #compile_rakefile(ext, install_dir) ⇒ Object
- #compile_ready? ⇒ Boolean
- #file(filename, io, source_mode) ⇒ Object
- #gemfile_and_lockfile(rake: false) ⇒ Object
-
#initialize(spec, store) ⇒ GemInstaller
constructor
A new instance of GemInstaller.
- #install ⇒ Object
- #needs_compile? ⇒ Boolean
- #with_build_environment(ext, install_dir) ⇒ Object
Constructor Details
#initialize(spec, store) ⇒ GemInstaller
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 |
# File 'lib/gel/package/installer.rb', line 27 def initialize(spec, store) @spec = spec @root_store = store if store.is_a?(Gel::MultiStore) store = store[spec.architecture, spec.extensions.any?] end @store = store raise "gem already installed" if store.gem?(spec.name, spec.version) @config = Gel::Environment.config @root = store.gem_root(spec.name, spec.version) FileUtils.rm_rf(@root) if @root && Dir.exist?(@root) if spec.extensions.any? @build_path = store.extension_path(spec.name, spec.version) FileUtils.rm_rf(@build_path) if @build_path && Dir.exist?(@build_path) else @build_path = nil end @files = {} @installed_files = [] spec.require_paths.each { |reqp| @files[reqp] = [] } end |
Instance Attribute Details
#build_path ⇒ Object (readonly)
Returns the value of attribute build_path.
25 26 27 |
# File 'lib/gel/package/installer.rb', line 25 def build_path @build_path end |
#root ⇒ Object (readonly)
Returns the value of attribute root.
25 26 27 |
# File 'lib/gel/package/installer.rb', line 25 def root @root end |
#spec ⇒ Object (readonly)
Returns the value of attribute spec.
25 26 27 |
# File 'lib/gel/package/installer.rb', line 25 def spec @spec end |
#store ⇒ Object (readonly)
Returns the value of attribute store.
25 26 27 |
# File 'lib/gel/package/installer.rb', line 25 def store @store end |
Instance Method Details
#abort! ⇒ Object
55 56 57 58 59 60 |
# File 'lib/gel/package/installer.rb', line 55 def abort! $stderr.puts "FileUtils.rm_rf(#{root.inspect})" if root $stderr.puts "FileUtils.rm_rf(#{build_path.inspect})" if build_path #FileUtils.rm_rf(root) if root #FileUtils.rm_rf(build_path) if build_path end |
#build_command(work_dir, log, *command, rake: false, **options) ⇒ Object
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/gel/package/installer.rb', line 135 def build_command(work_dir, log, *command, rake: false, **) env = build_environment(rake: rake) env.merge!(command.shift) if command.first.is_a?(Hash) pid = spawn( env, *command, chdir: work_dir, in: IO::NULL, [:out, :err] => log, **, ) _, status = Process.waitpid2(pid) status end |
#build_environment(rake: false) ⇒ Object
124 125 126 127 128 129 130 131 132 133 |
# File 'lib/gel/package/installer.rb', line 124 def build_environment(rake: false) gemfile, lockfile = gemfile_and_lockfile(rake: rake) { "RUBYLIB" => Gel::Environment.modified_rubylib, "GEL_STORE" => File.(@root_store.root), "GEL_GEMFILE" => gemfile, "GEL_LOCKFILE" => lockfile, } end |
#compile ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/gel/package/installer.rb', line 202 def compile if spec.extensions.any? spec.extensions.each do |ext| case File.basename(ext) when /extconf/i compile_extconf ext, build_path when /mkrf_conf/i, /rakefile/i compile_rakefile ext, build_path else raise "Don't know how to build #{ext.inspect} yet" end end end end |
#compile_extconf(ext, install_dir) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/gel/package/installer.rb', line 152 def compile_extconf(ext, install_dir) with_build_environment(ext, install_dir) do |work_dir, short_install_dir, local_config_path, log| status = build_command( work_dir, log, { "MAKEFLAGS" => "-j3" }, RbConfig.ruby, "-r", local_config_path, File.basename(ext), *Shellwords.shellsplit(@config[:build, @spec.name] || ""), ) raise "extconf exited with #{status.exitstatus}" unless status.success? _status = build_command(work_dir, log, "make", "clean", "DESTDIR=") # Ignore exit status status = build_command(work_dir, log, "make", "-j3", "DESTDIR=") raise "make exited with #{status.exitstatus}" unless status.success? status = build_command(work_dir, log, "make", "install", "DESTDIR=") raise "make install exited with #{status.exitstatus}" unless status.success? end end |
#compile_rakefile(ext, install_dir) ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/gel/package/installer.rb', line 175 def compile_rakefile(ext, install_dir) with_build_environment(ext, install_dir) do |work_dir, short_install_dir, local_config_path, log| if File.basename(ext) =~ /mkrf_conf/i status = build_command( work_dir, log, RbConfig.ruby, "-r", local_config_path, File.basename(ext), rake: true, ) raise "mkrf_conf exited with #{status.exitstatus}" unless status.success? end status = build_command( work_dir, log, { "RUBYARCHDIR" => short_install_dir, "RUBYLIBDIR" => short_install_dir }, RbConfig.ruby, "-r", File.("../command", __dir__), "-e", "Gel::Command.run(ARGV)", "--", "exec", "rake", rake: true, ) end end |
#compile_ready? ⇒ Boolean
66 67 68 |
# File 'lib/gel/package/installer.rb', line 66 def compile_ready? true end |
#file(filename, io, source_mode) ⇒ Object
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/gel/package/installer.rb', line 242 def file(filename, io, source_mode) target = File.(filename, root) raise "invalid filename #{target.inspect} outside #{(root + "/").inspect}" unless target.start_with?("#{root}/") return if @installed_files.include?(target) @installed_files << target spec.require_paths.each do |reqp| prefix = "#{root}/#{reqp}/" if target.start_with?(prefix) @files[reqp] << target[prefix.size..-1] end end raise "won't overwrite #{target}" if File.exist?(target) FileUtils.mkdir_p(File.dirname(target)) mode = 0444 mode |= source_mode & 0200 mode |= 0111 if source_mode & 0111 != 0 if exe = spec.executables.find { |e| filename == "#{spec.bindir}/#{e}" } mode |= 0111 @root_store.stub_set.add(File.basename(@store.root), [exe]) end File.open(target, "wb", mode) do |f| f.write io.read end end |
#gemfile_and_lockfile(rake: false) ⇒ Object
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 |
# File 'lib/gel/package/installer.rb', line 94 def gemfile_and_lockfile(rake: false) @gemfile ||= begin gemfile = Tempfile.new(["#{spec.name}.gemfile", ".rb"]) gemfile.puts "source :local" spec.runtime_dependencies.each do |(name, operator_pairs)| arguments = [name, *operator_pairs.map { |op, ver| "#{op} #{ver}" }] gemfile.puts "gem #{arguments.map(&:inspect).join(", ")}" end if rake gemfile.puts "gem 'rake'" unless spec.runtime_dependencies.any? { |name, *| name == "rake" } end gemfile.close gemfile end @lockfile ||= begin lockfile = Tempfile.new(["#{spec.name}.lockfile", ".lock"]) lockfile.close Gel::Environment.lock(store: @root_store, output: nil, gemfile: Gel::GemfileParser.parse(File.read(gemfile.path), gemfile.path, 1), lockfile: lockfile.path) lockfile end [@gemfile.path, @lockfile.path] end |
#install ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/gel/package/installer.rb', line 217 def install loadable_file_types = ["rb", RbConfig::CONFIG["DLEXT"], RbConfig::CONFIG["DLEXT2"]].compact.reject(&:empty?) loadable_file_types_re = /\.#{Regexp.union loadable_file_types}\z/ loadable_file_types_pattern = "*.{#{loadable_file_types.join(",")}}" store.add_gem(spec.name, spec.version, spec.bindir, spec.executables, spec.require_paths, spec.runtime_dependencies, spec.extensions.any?) do is_first = true spec.require_paths.each do |reqp| location = is_first ? spec.version : [spec.version, reqp] store.add_lib(spec.name, location, @files[reqp].map { |s| s.sub(loadable_file_types_re, "") }) is_first = false end if build_path files = Dir["#{build_path}/**/#{loadable_file_types_pattern}"].map do |file| file[build_path.size + 1..-1] end.map do |file| file.sub(loadable_file_types_re, "") end store.add_lib(spec.name, [spec.version, Gel::StoreGem::EXTENSION_SUBDIR_TOKEN], files) end end end |
#needs_compile? ⇒ Boolean
62 63 64 |
# File 'lib/gel/package/installer.rb', line 62 def needs_compile? !!@build_path end |
#with_build_environment(ext, install_dir) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/gel/package/installer.rb', line 70 def with_build_environment(ext, install_dir) work_dir = File.(File.dirname(ext), root) FileUtils.mkdir_p(install_dir) short_install_dir = Pathname.new(install_dir).relative_path_from(Pathname.new(work_dir)).to_s local_config = Tempfile.new(["config", ".rb"]) local_config.write(" require \"rbconfig\"\n\n RbConfig::MAKEFILE_CONFIG[\"sitearchdir\"] =\n RbConfig::MAKEFILE_CONFIG[\"sitelibdir\"] =\n RbConfig::CONFIG[\"sitearchdir\"] =\n RbConfig::CONFIG[\"sitelibdir\"] = \#{short_install_dir.dump}.freeze\n RUBY\n local_config.close\n\n File.open(\"\#{install_dir}/build.log\", \"w\") do |log|\n yield work_dir, short_install_dir, local_config.path, log\n end\nensure\n local_config.unlink if local_config\nend\n") |