lib/u3d/installation.rb in u3d-1.0.19 vs lib/u3d/installation.rb in u3d-1.0.20

- old
+ new

@@ -107,10 +107,14 @@ def version plist['CFBundleVersion'] end + def build_number + plist['UnityBuildNumber'] + end + def default_log_file "#{ENV['HOME']}/Library/Logs/Unity/Editor.log" end def exe_path @@ -161,10 +165,43 @@ Plist.parse_xml(fpath) end end end + class LinuxInstallationHelper + STRINGS_FULL_VERSION_MATCHER = /^[0-9\.abfp]+_[0-9a-f]{12}/ + + def find_build_number(root) + known_rev_locations.each do |p| + rev = find_build_number_in("#{root}#{p}") + return rev if rev + end + end + + private + + def strings(path) + command = "strings #{path.shellescape}" + `#{command}`.split("\n") + end + + # sorted by order of speed to fetch the strings data + def known_rev_locations + ['/Editor/BugReporter/unity.bugreporter', + '/Editor/Data/PlaybackEngines/WebGLSupport/BuildTools/lib/UnityNativeJs/UnityNative.js.mem', + '/Editor/Data/PlaybackEngines/LinuxStandaloneSupport/Variations/linux32_headless_nondevelopment_mono/LinuxPlayer', + '/Editor/Unity'] + end + + def find_build_number_in(path = nil) + return nil unless File.exist? path + str = strings(path) + lines = str.select { |l| l =~ STRINGS_FULL_VERSION_MATCHER } + lines.empty? ? nil : lines[0].split('_')[1] + end + end + class LinuxInstallation < Installation def version # I don't find an easy way to extract the version on Linux path = "#{root_path}/Editor/Data/" package = PlaybackEngineUtils.list_module_configs(path).first @@ -174,10 +211,14 @@ version = "#{m[1]}#{m[2]}" end version end + def build_number + @build_number ||= LinuxInstallationHelper.new.find_build_number(root_path) + end + def default_log_file "#{ENV['HOME']}/.config/unity3d/Editor.log" end def exe_path @@ -218,15 +259,69 @@ def clean_install? !(root_path =~ UNITY_DIR_CHECK_LINUX).nil? end end + class WindowsInstallationHelper + def build_number(exe_path) + s = string_file_info("Unity Version", exe_path) + if s + a = s.split("_") + return a[1] if a.count > 1 + end + nil + end + + private + + def string_file_info(info, path) + require "Win32API" + get_file_version_info_size = Win32API.new('version.dll', 'GetFileVersionInfoSize', 'PP', 'L') + get_file_version_info = Win32API.new('version.dll', 'GetFileVersionInfo', 'PIIP', 'I') + ver_query_value = Win32API.new('version.dll', 'VerQueryValue', 'PPPP', 'I') + rtl_move_memory = Win32API.new('kernel32.dll', 'RtlMoveMemory', 'PLL', 'I') + + file = path.tr("/", "\\") + + buf = [0].pack('L') + version_size = get_file_version_info_size.call(file + "\0", buf) + raise Exception if version_size.zero? # TODO: use GetLastError + + version_info = 0.chr * version_size + version_ok = get_file_version_info.call(file, 0, version_size, version_info) + raise Exception if version_ok.zero? # TODO: use GetLastError + + # hardcoding lang codepage + struct_path = "\\StringFileInfo\\040904b0\\#{info}" + + addr = [0].pack('L') + size = [0].pack('L') + query_ok = ver_query_value.call(version_info, struct_path + "\0", addr, size) + raise Exception if query_ok.zero? + + raddr = addr.unpack('L')[0] + rsize = size.unpack('L')[0] + + info = Array.new(rsize, 0).pack('L*') + rtl_move_memory.call(info, raddr, info.length) + info.strip + rescue StandardError => e + UI.verbose("Failure to find '#{info}' under '#{path}': #{e}") + UI.verbose(e.backtrace) + nil + end + end + class WindowsInstallation < Installation def version path = "#{root_path}/Editor/Data/" package = PlaybackEngineUtils.list_module_configs(path).first raise "Couldn't find a module under #{path}" unless package PlaybackEngineUtils.unity_version(package) + end + + def build_number + @build_number ||= WindowsInstallationHelper.new.build_number(exe_path) end def default_log_file if @logfile.nil? begin