lib/u3d/installer.rb in u3d-0.9.3 vs lib/u3d/installer.rb in u3d-0.9.4
- old
+ new
@@ -19,203 +19,86 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
## --- END LICENSE BLOCK ---
require 'u3d/utils'
+require 'u3d/installation'
require 'fileutils'
require 'file-tail'
-# Mac specific only right now
module U3d
DEFAULT_LINUX_INSTALL = '/opt/'.freeze
DEFAULT_MAC_INSTALL = '/'.freeze
DEFAULT_WINDOWS_INSTALL = 'C:/Program Files/'.freeze
UNITY_DIR = "Unity_%s".freeze
UNITY_DIR_LINUX = "unity-editor-%s".freeze
- UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/
- UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/
- class Installation
- def self.create(path: nil)
- if Helper.mac?
- MacInstallation.new path
- elsif Helper.linux?
- LinuxInstallation.new path
- else
- WindowsInstallation.new path
- end
- end
- end
-
- class MacInstallation < Installation
- attr_reader :path
-
- require 'plist'
-
- def initialize(path: nil)
- @path = path
- end
-
- def version
- plist['CFBundleVersion']
- end
-
- def default_log_file
- "#{ENV['HOME']}/Library/Logs/Unity/Editor.log"
- end
-
- def exe_path
- "#{path}/Contents/MacOS/Unity"
- end
-
- def packages
- if Utils.parse_unity_version(version)[0].to_i <= 4
- # Unity < 5 doesn't have packages
- return []
- end
- fpath = File.expand_path('../PlaybackEngines', path)
- raise "Unity installation does not seem correct. Couldn't locate PlaybackEngines." unless Dir.exist? fpath
- Dir.entries(fpath).select { |e| File.directory?(File.join(fpath, e)) && !(e == '.' || e == '..') }
- end
-
- def clean_install?
- path =~ UNITY_DIR_CHECK
- end
-
- private
-
- def plist
- @plist ||= Plist.parse_xml("#{@path}/Contents/Info.plist")
- end
- end
-
- class LinuxInstallation < Installation
- attr_reader :path
-
- def initialize(path: nil)
- @path = path
- end
-
- def version
- # I don't find an easy way to extract the version on Linux
- require 'rexml/document'
- fpath = "#{path}/Editor/Data/PlaybackEngines/LinuxStandaloneSupport/ivy.xml"
- raise "Couldn't find file #{fpath}" unless File.exist? fpath
- doc = REXML::Document.new(File.read(fpath))
- version = REXML::XPath.first(doc, 'ivy-module/info/@e:unityVersion').value
- if m = version.match(/^(.*)x(.*)Linux$/)
- version = "#{m[1]}#{m[2]}"
- end
- version
- end
-
- def default_log_file
- "#{ENV['HOME']}/.config/unity3d/Editor.log"
- end
-
- def exe_path
- "#{path}/Editor/Unity"
- end
-
- def packages
- false
- end
-
- def clean_install?
- path =~ UNITY_DIR_CHECK_LINUX
- end
- end
-
- class WindowsInstallation < Installation
- attr_reader :path
-
- def initialize(path: nil)
- @path = path
- end
-
- def version
- require 'rexml/document'
- fpath = "#{path}/Editor/Data/PlaybackEngines/windowsstandalonesupport/ivy.xml"
- raise "Couldn't find file #{fpath}" unless File.exist? fpath
- doc = REXML::Document.new(File.read(fpath))
- version = REXML::XPath.first(doc, 'ivy-module/info/@e:unityVersion').value
-
- version
- end
-
- def default_log_file
- if @logfile.nil?
- begin
- loc_appdata = Utils.windows_local_appdata
- log_dir = File.expand_path('Unity/Editor/', loc_appdata)
- UI.important "Log directory (#{log_dir}) does not exist" unless Dir.exist? log_dir
- @logfile = File.expand_path('Editor.log', log_dir)
- rescue RuntimeError => ex
- UI.error "Unable to retrieve the editor logfile: #{ex}"
- end
- end
- @logfile
- end
-
- def exe_path
- File.join(@path, 'Editor', 'Unity.exe')
- end
-
- def packages
- # Unity prior to Unity5 did not have package
- return [] if Utils.parse_unity_version(version)[0].to_i <= 4
- fpath = "#{path}/Editor/Data/PlaybackEngines/"
- raise "Unity installation does not seem correct. Couldn't locate PlaybackEngines." unless Dir.exist? fpath
- Dir.entries(fpath).select { |e| File.directory?(File.join(fpath, e)) && !(e == '.' || e == '..') }
- end
-
- def clean_install?
- path =~ UNITY_DIR_CHECK
- end
- end
-
class Installer
def self.create
installer = if Helper.mac?
MacInstaller.new
elsif Helper.linux?
LinuxInstaller.new
else
WindowsInstaller.new
end
- if UI.interactive?
- unclean = []
- installer.installed.each { |unity| unclean << unity unless unity.clean_install? }
- if !unclean.empty? && UI.confirm("#{unclean.count} Unity installation should be moved. Proceed?")
- unclean.each { |unity| installer.sanitize_install(unity) }
- end
- end
+ sanitize_installs(installer)
installer
end
+ def self.sanitize_installs(installer)
+ return unless UI.interactive? || Helper.test?
+ unclean = []
+ installer.installed.each { |unity| unclean << unity unless unity.clean_install? }
+ return if unclean.empty?
+ UI.important("u3d can optionally standardize the existing Unity3d installation names and locations.")
+ UI.important("Check the documentation for more information:")
+ UI.important("** https://github.com/DragonBox/u3d/blob/master/README.md#default-installation-paths **")
+ unclean.each { |unity| installer.sanitize_install(unity, dry_run: true) }
+ return unless UI.confirm("#{unclean.count} Unity installation(s) will be moved. Proceed??")
+ unclean.each { |unity| installer.sanitize_install(unity) }
+ end
+
def self.install_modules(files, version, installation_path: nil)
installer = Installer.create
files.each do |name, file, info|
UI.verbose "Installing #{name}#{info['mandatory'] ? ' (mandatory package)' : ''}, with file #{file}"
installer.install(file, version, installation_path: installation_path, info: info)
end
end
end
+ class CommonInstaller
+ def self.sanitize_install(source_path, new_path, command, dry_run: false)
+ if source_path == new_path
+ UI.important "sanitize_install does nothing if the path won't change (#{source_path})"
+ return
+ end
+
+ if dry_run
+ UI.message "'#{source_path}' would move to '#{new_path}'"
+ else
+ UI.important "Moving '#{source_path}' to '#{new_path}'..."
+ U3dCore::CommandExecutor.execute(command: command, admin: true)
+ UI.success "Successfully moved '#{source_path}' to '#{new_path}'"
+ end
+ rescue => e
+ UI.error "Unable to move '#{source_path}' to '#{new_path}': #{e}"
+ end
+ end
+
class MacInstaller
- def sanitize_install(unity)
+ def sanitize_install(unity, dry_run: false)
source_path = File.expand_path('..', unity.path)
parent = File.expand_path('..', source_path)
new_path = File.join(parent, UNITY_DIR % unity.version)
- UI.important "Moving #{source_path} to #{new_path}..."
- source_path = "\"#{source_path}\"" if source_path =~ / /
- new_path = "\"#{new_path}\"" if new_path =~ / /
- U3dCore::CommandExecutor.execute(command: "mv #{source_path} #{new_path}", admin: true)
- rescue => e
- UI.error "Unable to move #{source_path} to #{new_path}: #{e}"
- else
- UI.success "Successfully moved #{source_path} to #{new_path}"
+ source_path = source_path.shellescape
+ new_path = new_path.shellescape
+
+ command = "mv #{source_path} #{new_path}"
+
+ CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
end
def installed
unless (`mdutil -s /` =~ /disabled/).nil?
$stderr.puts 'Please enable Spotlight indexing for /Applications.'
@@ -232,11 +115,13 @@
# sorting should take into account stable/patch etc
versions.sort! { |x, y| x.version <=> y.version }
end
+ # rubocop:disable UnusedMethodArgument
def install(file_path, version, installation_path: nil, info: {})
+ # rubocop:enable UnusedMethodArgument
extension = File.extname(file_path)
raise "Installation of #{extension} files is not supported on Mac" if extension != '.pkg'
path = installation_path || DEFAULT_MAC_INSTALL
install_pkg(
file_path,
@@ -247,17 +132,19 @@
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}"
unity = installed.find { |u| u.version == version }
+ temp_path = File.join(target_path, 'Applications', 'Unity')
if unity.nil?
UI.verbose "No Unity install for version #{version} was found"
U3dCore::CommandExecutor.execute(command: command, admin: true)
+ destination_path = File.join(target_path, 'Applications', UNITY_DIR % version)
+ FileUtils.mv temp_path, destination_path
else
begin
path = File.expand_path('..', unity.path)
- temp_path = File.join(target_path, 'Applications', 'Unity')
move_to_temp = (temp_path != path)
if move_to_temp
UI.verbose "Temporary switching location of #{path} to #{temp_path} for installation purpose"
FileUtils.mv path, temp_path
end
@@ -272,33 +159,33 @@
UI.success "Successfully installed package from #{file_path}"
end
end
class LinuxInstaller
- def sanitize_install(unity)
+ def sanitize_install(unity, dry_run: false)
source_path = File.expand_path(unity.path)
parent = File.expand_path('..', source_path)
new_path = File.join(parent, UNITY_DIR_LINUX % unity.version)
- UI.important "Moving #{source_path} to #{new_path}..."
- source_path = "\"#{source_path}\"" if source_path =~ / /
- new_path = "\"#{new_path}\"" if new_path =~ / /
- U3dCore::CommandExecutor.execute(command: "mv #{source_path} #{new_path}", admin: true)
- rescue => e
- UI.error "Unable to move #{source_path} to #{new_path}: #{e}"
- else
- UI.success "Successfully moved #{source_path} to #{new_path}"
+ source_path = source_path.shellescape
+ new_path = new_path.shellescape
+
+ command = "mv #{source_path} #{new_path}"
+
+ CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
end
def installed
find = File.join(DEFAULT_LINUX_INSTALL, 'unity-editor-*')
versions = Dir[find].map { |path| LinuxInstallation.new(path: path) }
# sorting should take into account stable/patch etc
versions.sort! { |x, y| x.version <=> y.version }
end
+ # rubocop:disable UnusedMethodArgument
def install(file_path, version, installation_path: nil, info: {})
+ # rubocop:enable UnusedMethodArgument
extension = File.extname(file_path)
raise "Installation of #{extension} files is not supported on Linux" if extension != '.sh'
path = installation_path || DEFAULT_LINUX_INSTALL
install_sh(
file_path,
@@ -325,24 +212,23 @@
UI.success 'Installation successful'
end
end
class WindowsInstaller
- def sanitize_install(unity)
+ def sanitize_install(unity, dry_run: false)
source_path = File.expand_path(unity.path)
parent = File.expand_path('..', source_path)
new_path = File.join(parent, UNITY_DIR % unity.version)
- UI.important "Moving #{source_path} to #{new_path}..."
+
source_path.tr!('/', '\\')
new_path.tr!('/', '\\')
source_path = "\"" + source_path + "\"" if source_path =~ / /
new_path = "\"" + new_path + "\"" if new_path =~ / /
- U3dCore::CommandExecutor.execute(command: "move #{source_path} #{new_path}", admin: true)
- rescue => e
- UI.error "Unable to move #{source_path} to #{new_path}: #{e}"
- else
- UI.success "Successfully moved #{source_path} to #{new_path}"
+
+ command = "move #{source_path} #{new_path}"
+
+ CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
end
def installed
find = File.join(DEFAULT_WINDOWS_INSTALL, 'Unity*', 'Editor', 'Uninstall.exe')
versions = Dir[find].map { |path| WindowsInstallation.new(path: File.expand_path('../..', path)) }
@@ -372,37 +258,17 @@
command = info['cmd']
command.sub!(/{FILENAME}/, file_path)
command.sub!(/{INSTDIR}/, final_path)
command.sub!(/{DOCDIR}/, final_path)
command.sub!(/{MODULEDIR}/, final_path)
- command.sub!(/\/D=/, '/S /D=') unless /\/S/ =~ command
+ command.sub!(%r{\/D=}, '/S /D=') unless %r{\/S} =~ command
end
command ||= file_path.to_s
U3dCore::CommandExecutor.execute(command: command, admin: true)
rescue => e
UI.error "Failed to install exe at #{file_path}: #{e}"
else
UI.success "Successfully installed #{info['title']}"
end
- end
- end
-
- class UnityProject
- attr_reader :path
-
- def initialize(path)
- @path = path
- end
-
- def exist?
- Dir.exist?("#{@path}/Assets") && Dir.exist?("#{@path}/ProjectSettings")
- end
-
- def editor_version
- require 'yaml'
- yaml = YAML.load(File.read("#{@path}/ProjectSettings/ProjectVersion.txt"))
- version = yaml['m_EditorVersion']
- version.gsub!(/(\d+\.\d+\.\d+)(?:x)?(\w\d+)(?:Linux)?/, '\1\2') if Helper.linux?
- version
end
end
end