lib/u3d/installer.rb in u3d-1.1.5 vs lib/u3d/installer.rb in u3d-1.2.0

- old
+ new

@@ -25,10 +25,11 @@ require 'u3d_core/core_ext/string' require 'u3d/installation' require 'fileutils' require 'file-tail' require 'pathname' +require 'zip' module U3d DEFAULT_LINUX_INSTALL = '/opt/'.freeze DEFAULT_MAC_INSTALL = '/'.freeze DEFAULT_WINDOWS_INSTALL = 'C:/Program Files/'.freeze @@ -53,11 +54,11 @@ end def self.install_modules(files, version, installation_path: nil) installer = Installer.create files.each do |name, file, info| - UI.header "Installing #{info['title']} (#{name})" + UI.header "Installing #{info.name} (#{name})" UI.message 'Installing with ' + file installer.install(file, version, installation_path: installation_path, info: info) end end @@ -84,10 +85,81 @@ def installed_sorted_by_versions list = installed return [] if list.empty? list.sort { |a, b| UnityVersionComparator.new(a.version) <=> UnityVersionComparator.new(b.version) } end + + protected + + def install_po(file_path, version, info: nil) + unity = installed.find { |u| u.version == version } + root_path = package_destination(info, unity.root_path) + + target_path = File.join(root_path, File.basename(file_path)) + Utils.ensure_dir(File.dirname(target_path)) + + UI.verbose "Copying #{file_path} to #{target_path}" + FileUtils.cp(file_path, target_path) + + UI.success "Successfully installed language file #{File.basename(file_path)}" + end + + def install_zip(file_path, version, info: nil) + unity = installed.find { |u| u.version == version } + root_path = package_destination(info, unity.root_path) + + UI.verbose("Unzipping #{file_path} to #{root_path}") + + unless File.directory?(root_path) + Utils.get_write_access(File.dirname(root_path)) do + Utils.ensure_dir(root_path) + end + end + + Zip::File.open(file_path) do |zip_file| + zip_file.each do |entry| + target_path = File.join(root_path, entry.name) + Utils.ensure_dir(File.dirname(target_path)) + zip_file.extract(entry, target_path) unless File.exist?(target_path) + end + end + + if info && info.rename_from && info.rename_to + rename_from = info.rename_from.gsub(/{UNITY_PATH}/, unity.root_path) + rename_to = info.rename_to.gsub(/{UNITY_PATH}/, unity.root_path) + Utils.ensure_dir(rename_to) + UI.verbose("Renaming from #{rename_from} to #{rename_to}") + if File.file? rename_from + FileUtils.mv(rename_from, rename_to) + else + Dir.glob(rename_from + '/*').each { |path| FileUtils.mv(path, rename_to) } + end + end + + UI.success "Successfully unizpped #{File.basename(file_path)} at #{root_path}" + end + + def package_destination(info, unity_root_path) + if info && info.destination + info.destination.gsub(/{UNITY_PATH}/, unity_root_path) + else + unity_root_path + end + end + + def extra_installation_paths + return [] if ENV['U3D_EXTRA_PATHS'].nil? + ENV['U3D_EXTRA_PATHS'].strip.split(File::PATH_SEPARATOR) + end + + def find_installations_with_path(default_root_path: '', postfix: []) + ([default_root_path] | extra_installation_paths).map do |path| + UI.verbose "Looking for installed Unity version under #{path}" + pattern = File.join([path] + postfix) + Dir.glob(pattern).map { |found_path| yield found_path } + end.flatten + end end # deprecated class CommonInstaller def self.sanitize_install(source_path, new_path, command, dry_run: false) @@ -111,21 +183,22 @@ def installed paths = (list_installed_paths + spotlight_installed_paths).uniq paths.map { |path| MacInstallation.new(root_path: path) } end - # rubocop:disable UnusedMethodArgument - def install(file_path, version, installation_path: nil, info: {}) + def install(file_path, version, installation_path: nil, info: nil) # rubocop:enable UnusedMethodArgument extension = File.extname(file_path) - raise "Installation of #{extension} files is not supported on Mac" if extension != '.pkg' + raise "Installation of #{extension} files is not supported on Mac" unless %w[.zip .po .pkg].include? extension path = installation_path || DEFAULT_MAC_INSTALL - install_pkg( - file_path, - version: version, - target_path: path - ) + if extension == '.po' + install_po(file_path, version, info: info) + elsif extension == '.zip' + install_zip(file_path, version, info: info) + else + install_pkg(file_path, version: version, target_path: path) + end end def install_pkg(file_path, version: nil, target_path: nil) target_path ||= DEFAULT_MAC_INSTALL command = "installer -pkg #{file_path.shellescape} -target #{target_path.shellescape}" @@ -167,13 +240,18 @@ end private def list_installed_paths - find = File.join(DEFAULT_MAC_INSTALL, 'Applications', 'Unity*', 'Unity.app') - paths = Dir[find] - paths = paths.map { |u| Pathname.new(u).parent.to_s } + paths = find_installations_with_path( + default_root_path: DEFAULT_MAC_INSTALL, + postfix: %w[ + Applications + Unity* + Unity.app + ] + ) { |u| Pathname.new(u).parent.to_s } UI.verbose "Found list_installed_paths: #{paths}" paths end def spotlight_installed_paths @@ -211,16 +289,16 @@ def installed paths = (list_installed_paths + debian_installed_paths).uniq paths.map { |path| LinuxInstallation.new(root_path: path) } end - # rubocop:disable UnusedMethodArgument, PerceivedComplexity - def install(file_path, version, installation_path: nil, info: {}) + # rubocop:disable PerceivedComplexity + def install(file_path, version, installation_path: nil, info: nil) # rubocop:enable UnusedMethodArgument, PerceivedComplexity extension = File.extname(file_path) - raise "Installation of #{extension} files is not supported on Linux" unless ['.sh', '.xz', '.pkg'].include? extension + raise "Installation of #{extension} files is not supported on Linux" unless ['.zip', '.po', '.sh', '.xz', '.pkg'].include? extension if extension == '.sh' path = installation_path || DEFAULT_LINUX_INSTALL install_sh(file_path, installation_path: path) elsif extension == '.xz' new_path = File.join(DEFAULT_LINUX_INSTALL, format(UNITY_DIR_LINUX, version: version)) @@ -228,10 +306,14 @@ install_xz(file_path, installation_path: path) elsif extension == '.pkg' new_path = File.join(DEFAULT_LINUX_INSTALL, format(UNITY_DIR_LINUX, version: version)) path = installation_path || new_path install_pkg(file_path, installation_path: path) + elsif extension == '.po' + install_po(file_path, version, info: info) + elsif extension == '.zip' + install_zip(file_path, version, info: info) end # Forces sanitation for installation of 'weird' versions eg 5.6.1xf1Linux unity = installed.select { |u| u.version == version }.first if unity @@ -330,21 +412,29 @@ install_location.gsub(%(\/Applications\/Unity), "#{unity_root_path}/Editor/Data") end end def list_installed_paths - find = File.join(DEFAULT_LINUX_INSTALL, 'unity-editor-*', 'Editor') - paths = Dir[find] - paths = paths.map { |u| Pathname.new(u).parent.to_s } + paths = find_installations_with_path( + default_root_path: DEFAULT_LINUX_INSTALL, + postfix: %w[ + unity-editor-* + Editor + ] + ) { |u| Pathname.new(u).parent.to_s } UI.verbose "Found list_installed_paths: #{paths}" paths end def debian_installed_paths - find = File.join(DEFAULT_LINUX_INSTALL, 'Unity', 'Editor') - paths = Dir[find] - paths = paths.map { |u| Pathname.new(u).parent.to_s } + paths = find_installations_with_path( + default_root_path: DEFAULT_LINUX_INSTALL, + postfix: %w[ + Unity + Editor + ] + ) { |u| Pathname.new(u).parent.to_s } UI.verbose "Found debian_installed_paths: #{paths}" paths end end # rubocop:enable ClassLength @@ -360,33 +450,41 @@ moved = U3dCore::AdminTools.move_os_file(:win, source_path, new_path, dry_run: dry_run) unity.root_path = new_path if moved && !dry_run end def installed - find = File.join(DEFAULT_WINDOWS_INSTALL, 'Unity*', 'Editor', 'Uninstall.exe') - Dir[find].map { |path| WindowsInstallation.new(root_path: File.expand_path('../..', path)) } + find_installations_with_path( + default_root_path: DEFAULT_WINDOWS_INSTALL, + postfix: %w[ + Unity* + Editor + Uninstall.exe + ] + ) { |path| WindowsInstallation.new(root_path: File.expand_path('../..', path)) } end - def install(file_path, version, installation_path: nil, info: {}) + def install(file_path, version, installation_path: nil, info: nil) extension = File.extname(file_path) - raise "Installation of #{extension} files is not supported on Windows" unless %w[.exe .msi].include? extension + raise "Installation of #{extension} files is not supported on Windows" unless %w[.po .zip .exe .msi].include? extension path = installation_path || File.join(DEFAULT_WINDOWS_INSTALL, format(UNITY_DIR, version: version)) - install_exe( - file_path, - installation_path: path, - info: info - ) + if extension == '.po' + install_po(file_path, version, info: info) + elsif extension == '.zip' + install_zip(file_path, version, info: info) + else + install_exe(file_path, installation_path: path, info: info) + end end - def install_exe(file_path, installation_path: nil, info: {}) + def install_exe(file_path, installation_path: nil, info: nil) installation_path ||= DEFAULT_WINDOWS_INSTALL final_path = U3dCore::Helper.windows_path(installation_path) Utils.ensure_dir(final_path) begin command = nil - if info['cmd'] - command = info['cmd'] + if info.command + command = info.command if /msiexec/ =~ command command.sub!(/{FILENAME}/, '"' + U3dCore::Helper.windows_path(file_path) + '"') else command.sub!(/{FILENAME}/, file_path.argescape) end @@ -398,10 +496,10 @@ command ||= file_path.argescape U3dCore::CommandExecutor.execute(command: command, admin: true) rescue StandardError => e UI.error "Failed to install package at #{file_path}: #{e}" else - UI.success "Successfully installed #{info['title']}" + UI.success "Successfully installed #{info.name}" end end def uninstall(unity: nil) UI.verbose("Uninstalling Unity at '#{unity.root_path}'...")