module U3d::Utils
Several different utility methods rubocop:disable ModuleLength
Constants
- CSIDL_LOCAL_APPDATA
Regex to capture each part of a version string (0.0.0x0)
- UNITY_VERSION_REGEX
Public Class Methods
download_file(path, url, size: nil)
click to toggle source
size a hint of the expected size
# File lib/u3d/utils.rb, line 90 def download_file(path, url, size: nil) File.open(path, 'wb') do |f| uri = URI(url) current = 0 last_print_update = 0 print_progress = UI.interactive? || U3dCore::Globals.verbose? Net::HTTP.start(uri.host, uri.port, http_opts(use_ssl: uri.scheme == 'https')) do |http| request = Net::HTTP::Get.new uri http.request request do |response| begin # override with actual results, this should help with # innacurrate declared sizes, especially on Windows platform size = Integer(response['Content-Length']) rescue ArgumentError UI.verbose 'Unable to get length of file in download' end started_at = Time.now.to_i - 1 response.read_body do |segment| f.write(segment) current += segment.length # wait for Net::HTTP buffer on slow networks # FIXME revisits, this slows down download on fast network # sleep 0.08 # adjust to reduce CPU next unless print_progress print_progress_now = Time.now.to_f - last_print_update > 0.5 # force printing when done downloading print_progress_now = true if !print_progress_now && size && current >= size next unless print_progress_now last_print_update = Time.now.to_f Utils.print_progress(current, size, started_at) print "\n" unless UI.interactive? end end end print "\n" if print_progress end end
ensure_dir(dir)
click to toggle source
# File lib/u3d/utils.rb, line 150 def ensure_dir(dir) FileUtils.mkpath(dir) unless File.directory?(dir) end
final_url(url, redirect_limit: 10)
click to toggle source
# File lib/u3d/utils.rb, line 37 def final_url(url, redirect_limit: 10) follow_redirects(url, redirect_limit: redirect_limit, http_method: :head) do |request, _response| request.uri.to_s end end
follow_redirects(url, redirect_limit: 10, http_method: :get, request_headers: {}) { |request, response| ... }
click to toggle source
# File lib/u3d/utils.rb, line 54 def follow_redirects(url, redirect_limit: 10, http_method: :get, request_headers: {}, &block) raise 'Too many redirections' if redirect_limit.zero? response = nil request = nil uri = URI(url) begin use_ssl = /^https/.match(url) Net::HTTP.start(uri.host, uri.port, http_opts(use_ssl: use_ssl)) do |http| request = http_request_class http_method, uri request_headers.each do |k, v| request[k] = v end response = http.request request end rescue OpenSSL::OpenSSLError => ssl_error UI.error 'SSL has faced an error, you may want to check our README to fix it' raise ssl_error end case response when Net::HTTPSuccess then yield(request, response) when Net::HTTPRedirection then UI.verbose "Redirected to #{response['location']}" follow_redirects(response['location'], redirect_limit: redirect_limit - 1, http_method: http_method, request_headers: request_headers, &block) else raise "Request failed with status #{response.code}" end end
get_ssl(url, redirect_limit: 10, request_headers: {})
click to toggle source
FIXME: alias deprecated
# File lib/u3d/utils.rb, line 44 def get_ssl(url, redirect_limit: 10, request_headers: {}) page_content(url, redirect_limit: redirect_limit, request_headers: request_headers) end
get_url_content_length(url)
click to toggle source
# File lib/u3d/utils.rb, line 128 def get_url_content_length(url) UI.verbose "get_url_content_length #{url}" uri = URI(url) size = nil Net::HTTP.start(uri.host, uri.port, http_opts) do |http| response = http.request_head url size = Integer(response['Content-Length']) end UI.verbose "get_url_content_length #{url}: #{size}" size end
get_write_access(dir) { || ... }
click to toggle source
# File lib/u3d/utils.rb, line 154 def get_write_access(dir) if U3dCore::Helper.operating_system == :win yield else stat_command = if U3dCore::Helper.operating_system == :linux "stat -c \"%U,%a\" #{dir}" elsif U3dCore::Helper.operating_system == :mac "stat -f \"%Su,%A\" #{dir}" end owner, access = U3dCore::CommandExecutor.execute(command: stat_command, admin: false).strip.split(',') current_user = U3dCore::CommandExecutor.execute(command: 'whoami', admin: false) U3dCore::CommandExecutor.execute(command: "chown #{current_user}: #{dir}", admin: true) U3dCore::CommandExecutor.execute(command: "chmod u+w #{dir}", admin: true) begin yield ensure U3dCore::CommandExecutor.execute(command: "chown #{owner}: #{dir}", admin: true) U3dCore::CommandExecutor.execute(command: "chmod #{access} #{dir}", admin: true) end end end
hashfile(file_path, blocksize: 65_536)
click to toggle source
# File lib/u3d/utils.rb, line 140 def hashfile(file_path, blocksize: 65_536) require 'digest' raise ArgumentError, 'Not a file' unless File.file?(file_path) md5 = Digest::MD5.new File.open(file_path, 'r') do |f| md5 << f.read(blocksize) until f.eof? end md5.hexdigest end
http_request_class(method, uri)
click to toggle source
# File lib/u3d/utils.rb, line 83 def http_request_class(method, uri) return Net::HTTP::Get.new uri if method == :get return Net::HTTP::Head.new uri if method == :head raise "Unknown method #{method}" end
page_content(url, redirect_limit: 10, request_headers: {})
click to toggle source
# File lib/u3d/utils.rb, line 48 def page_content(url, redirect_limit: 10, request_headers: {}) follow_redirects(url, redirect_limit: redirect_limit, request_headers: request_headers) do |_request, response| response.body end end
parse_unity_version(version)
click to toggle source
# File lib/u3d/utils.rb, line 198 def parse_unity_version(version) ver = UNITY_VERSION_REGEX.match(version) if ver.nil? raise ArgumentError, "Version (#{version}) does not match the Unity "\ 'version format 0.0.0x0' end [ver[1], ver[2], ver[3], ver[4], ver[5]] end
pretty_filesize(filesize)
click to toggle source
# File lib/u3d/utils.rb, line 223 def pretty_filesize(filesize) Filesize.from(filesize.round.to_s + ' B').pretty end
print_progress(current, total, started_at)
click to toggle source
if total is nil (unknown, falls back to print_progress_nosize
)
# File lib/u3d/utils.rb, line 177 def print_progress(current, total, started_at) if total.nil? print_progress_nosize(current, started_at) return end ratio = [current.to_f / total, 1.0].min percent = (ratio * 100.0).round(1) arrow = (ratio * 20.0).floor time_spent = Time.now.to_i - started_at print("\r[") print('=' * [arrow - 1, 0].max) print('>') print('.' * (20 - arrow)) print("] #{pretty_filesize(current)}/#{pretty_filesize(total)} (#{percent}% at #{pretty_filesize(current.to_f / time_spent)}/s) ") end
print_progress_nosize(current, started_at)
click to toggle source
# File lib/u3d/utils.rb, line 193 def print_progress_nosize(current, started_at) time_spent = Time.now.to_i - started_at print("\r>#{pretty_filesize(current)} downloaded at #{pretty_filesize(current.to_f / time_spent)}/s) ") end
strings(path)
click to toggle source
Ruby implementation of binutils strings
# File lib/u3d/utils.rb, line 233 def strings(path) min = 4 Enumerator.new do |y| File.open(path, "rb") do |f| s = "" f.each_char do |c| if c =~ /[[:print:]]/ # is there a cleaner way to do this check? s += c next else y.yield s if s.length >= min s = "" end end y.yield s if s.length >= min end end end
windows_local_appdata()
click to toggle source
# File lib/u3d/utils.rb, line 207 def windows_local_appdata require 'win32api' windir = ' ' * 261 getdir = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L') result = getdir.call(0, CSIDL_LOCAL_APPDATA, 0, 0, windir) raise "Unable to get Local Appdata directory, returned with value #{result}" unless result.zero? windir.rstrip! windir = windir.encode("UTF-8", Encoding.find('filesystem')) windir = File.expand_path(windir.rstrip) return windir if Dir.exist? windir raise "Local Appdata retrieved (#{windir}) is not correct" end
windows_path(path)
click to toggle source
# File lib/u3d/utils.rb, line 227 def windows_path(path) UI.deprecated("Use U3dCore::Helper.windows_path") U3dCore::Helper.windows_path(path) end
Private Class Methods
http_max_retries()
click to toggle source
# File lib/u3d/utils.rb, line 254 def http_max_retries ENV['U3D_HTTP_MAX_RETRIES'].to_i if ENV['U3D_HTTP_MAX_RETRIES'] end
http_opts(opt = {})
click to toggle source
# File lib/u3d/utils.rb, line 263 def http_opts(opt = {}) # the keys are #ca_file, #ca_path, cert, #cert_store, ciphers, #close_on_empty_response, key, #open_timeout, # #read_timeout, #ssl_timeout, #ssl_version, use_ssl, #verify_callback, #verify_depth and verify_mode opt[:max_retries] = http_max_retries if http_max_retries opt[:read_timeout] = http_read_timeout if http_read_timeout UI.verbose "Using http opts: #{opt}" opt end
http_read_timeout()
click to toggle source
# File lib/u3d/utils.rb, line 258 def http_read_timeout return ENV['U3D_HTTP_READ_TIMEOUT'].to_i if ENV['U3D_HTTP_READ_TIMEOUT'] 300 end