u3d 1.2.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +33 -10
  3. data/.github/workflows/ci.yml +35 -0
  4. data/.github_changelog_generator +3 -1
  5. data/.gitignore +1 -0
  6. data/.rubocop.yml +15 -3
  7. data/CHANGELOG.md +83 -11
  8. data/Gemfile.lock +147 -87
  9. data/Rakefile +20 -12
  10. data/appveyor.yml +25 -6
  11. data/examples/Example1/Gemfile +4 -2
  12. data/examples/Example1/Gemfile.lock +8 -6
  13. data/examples/Example1/Rakefile +2 -0
  14. data/examples/Example1/fastlane/Fastfile +2 -0
  15. data/examples/Example2/Gemfile +4 -2
  16. data/examples/Example2/Gemfile.lock +12 -7
  17. data/examples/Example2/fastlane/Fastfile +2 -0
  18. data/exe/u3d +3 -1
  19. data/lib/u3d/asset.rb +6 -2
  20. data/lib/u3d/cache.rb +14 -10
  21. data/lib/u3d/commands.rb +15 -11
  22. data/lib/u3d/commands_generator.rb +6 -4
  23. data/lib/u3d/compatibility.rb +2 -0
  24. data/lib/u3d/download_validator.rb +6 -3
  25. data/lib/u3d/downloader.rb +12 -8
  26. data/lib/u3d/failure_reporter.rb +4 -3
  27. data/lib/u3d/hub_modules_parser.rb +24 -7
  28. data/lib/u3d/ini_modules_parser.rb +10 -32
  29. data/lib/u3d/installation.rb +77 -66
  30. data/lib/u3d/installer.rb +46 -33
  31. data/lib/u3d/log_analyzer.rb +31 -27
  32. data/lib/u3d/unity_license.rb +2 -0
  33. data/lib/u3d/unity_module.rb +2 -0
  34. data/lib/u3d/unity_project.rb +4 -1
  35. data/lib/u3d/unity_runner.rb +12 -10
  36. data/lib/u3d/unity_version_definition.rb +3 -0
  37. data/lib/u3d/unity_version_number.rb +8 -2
  38. data/lib/u3d/unity_versions.rb +28 -23
  39. data/lib/u3d/utils.rb +86 -15
  40. data/lib/u3d/version.rb +8 -6
  41. data/lib/u3d.rb +13 -0
  42. data/lib/u3d_core/admin_tools.rb +2 -0
  43. data/lib/u3d_core/command_executor.rb +11 -7
  44. data/lib/u3d_core/command_runner.rb +17 -19
  45. data/lib/u3d_core/core_ext/hash.rb +2 -0
  46. data/lib/u3d_core/core_ext/operating_system_symbol.rb +3 -0
  47. data/lib/u3d_core/core_ext/string.rb +2 -0
  48. data/lib/u3d_core/credentials.rb +9 -7
  49. data/lib/u3d_core/env.rb +3 -0
  50. data/lib/u3d_core/globals.rb +7 -7
  51. data/lib/u3d_core/helper.rb +6 -4
  52. data/lib/u3d_core/ui/disable_colors.rb +2 -0
  53. data/lib/u3d_core/ui/implementations/shell.rb +8 -5
  54. data/lib/u3d_core/ui/interface.rb +3 -0
  55. data/lib/u3d_core/ui/ui.rb +5 -4
  56. data/lib/u3d_core/update_checker/changelog.rb +4 -0
  57. data/lib/u3d_core/update_checker/update_checker.rb +7 -8
  58. data/lib/u3d_core/version.rb +2 -0
  59. data/lib/u3d_core.rb +2 -0
  60. data/u3d.gemspec +19 -9
  61. metadata +101 -29
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -45,6 +47,7 @@ module U3d
45
47
  if log_file
46
48
  tail_thread = start_tail_thread(log_file, output_callback)
47
49
  return unless tail_thread.status
50
+
48
51
  tail_thread.run
49
52
  end
50
53
 
@@ -78,9 +81,9 @@ module U3d
78
81
  end
79
82
 
80
83
  class << self
81
- # rubocop:disable MethodName
84
+ # rubocop:disable Naming/MethodName
82
85
  def find_logFile_in_args(args)
83
- # rubocop:enable MethodName
86
+ # rubocop:enable Naming/MethodName
84
87
  find_arg_in_args('-logFile', args)
85
88
  end
86
89
 
@@ -90,6 +93,7 @@ module U3d
90
93
 
91
94
  def find_arg_in_args(arg_to_find, args)
92
95
  raise 'Only arguments of type array supported right now' unless args.is_a?(Array)
96
+
93
97
  args.each_with_index do |arg, index|
94
98
  return args[index + 1] if arg == arg_to_find && index < args.count - 1
95
99
  end
@@ -101,12 +105,10 @@ module U3d
101
105
 
102
106
  def start_tail_thread(log_file, output_callback)
103
107
  tail_thread = Thread.new do
104
- begin
105
- pipe(log_file) { |line| output_callback.call(line) }
106
- rescue StandardError => e
107
- UI.error "Failure while trying to pipe #{log_file}: #{e.message}"
108
- e.backtrace.each { |l| UI.error " #{l}" }
109
- end
108
+ pipe(log_file) { |line| output_callback.call(line) }
109
+ rescue StandardError => e
110
+ UI.error "Failure while trying to pipe #{log_file}: #{e.message}"
111
+ e.backtrace.each { |l| UI.error " #{l}" }
110
112
  end
111
113
 
112
114
  # Wait for tail_thread setup to be complete
@@ -114,14 +116,14 @@ module U3d
114
116
  tail_thread
115
117
  end
116
118
 
117
- def pipe(file)
119
+ def pipe(file, &block)
118
120
  File.open(file, 'r') do |f|
119
121
  f.extend File::Tail
120
122
  f.interval = 0.1
121
123
  f.max_interval = 0.4
122
124
  f.backward 0
123
125
  Thread.stop
124
- f.tail { |l| yield l }
126
+ f.tail(&block)
125
127
  end
126
128
  end
127
129
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -51,6 +53,7 @@ module U3d
51
53
 
52
54
  def [](package)
53
55
  return nil unless available_package? package
56
+
54
57
  @packages.find { |pack| pack.id == package.downcase }
55
58
  end
56
59
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -24,14 +26,14 @@ require 'u3d/utils'
24
26
 
25
27
  module U3d
26
28
  class UnityVersionNumber
27
- attr_reader :unity_version
28
- attr_reader :parts
29
+ attr_reader :unity_version, :parts
29
30
 
30
31
  def initialize(version)
31
32
  @unity_version = version
32
33
  parsed = Utils.parse_unity_version(@unity_version)
33
34
  parsed.each_with_index do |val, index|
34
35
  next if val.nil? || (index == 3)
36
+
35
37
  parsed[index] = val.to_i
36
38
  end
37
39
  @parts = parsed
@@ -52,12 +54,16 @@ module U3d
52
54
  def <=>(other)
53
55
  comp = @version.parts[0] <=> other.version.parts[0]
54
56
  return comp if comp.nonzero?
57
+
55
58
  comp = @version.parts[1] <=> other.version.parts[1]
56
59
  return comp if comp.nonzero?
60
+
57
61
  comp = @version.parts[2] <=> other.version.parts[2]
58
62
  return comp if comp.nonzero?
63
+
59
64
  comp = RELEASE_LETTER_STRENGTH[@version.parts[3].to_sym] <=> RELEASE_LETTER_STRENGTH[other.version.parts[3].to_sym]
60
65
  return comp if comp.nonzero?
66
+
61
67
  return @version.parts[4] <=> other.version.parts[4]
62
68
  end
63
69
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -47,6 +49,7 @@ module U3d
47
49
  def fetch_cookie
48
50
  UI.verbose "FetchCookie? #{@cookie}"
49
51
  return @cookie if @cookie
52
+
50
53
  cookie_str = ''
51
54
  url = 'https://forum.unity.com/forums/linux-editor.93/' # a page that triggers cookies
52
55
  uri = URI(url)
@@ -56,15 +59,15 @@ module U3d
56
59
  response = http.request request
57
60
 
58
61
  case response
59
- when Net::HTTPSuccess then
62
+ when Net::HTTPSuccess
60
63
  UI.verbose "unexpected result"
61
- when Net::HTTPRedirection then
64
+ when Net::HTTPRedirection
62
65
  # A session must be opened with the server before accessing forum
63
66
  res = nil
64
67
  cookie_str = ''
65
68
  # Store the name and value of the cookies returned by the server
66
69
  response['set-cookie'].gsub(/\s+/, '').split(',').each do |c|
67
- cookie_str << c.split(';', 2)[0] + '; '
70
+ cookie_str << ("#{c.split(';', 2)[0]}; ")
68
71
  end
69
72
  cookie_str.chomp!('; ')
70
73
 
@@ -78,6 +81,7 @@ module U3d
78
81
  end
79
82
 
80
83
  raise 'Unexpected result' unless res.is_a? Net::HTTPRedirection
84
+
81
85
  # It should be a redirection to the forum to perform authentication
82
86
  uri = URI(res['location'])
83
87
  UI.verbose "Redirecting to #{uri}"
@@ -90,50 +94,51 @@ module U3d
90
94
  raise 'Unable to establish a session with Unity forum' unless res.is_a? Net::HTTPRedirection
91
95
 
92
96
  UI.verbose "Found cookie_str #{cookie_str}"
93
- cookie_str << '; ' + res['set-cookie'].gsub(/\s+/, '').split(';', 2)[0]
97
+ cookie_str << ("; #{res['set-cookie'].gsub(/\s+/, '').split(';', 2)[0]}")
94
98
  end
95
99
  end
96
100
  UI.verbose "Found @cookie #{cookie_str}"
97
101
  @cookie = cookie_str
98
102
  end
99
103
  end
104
+
100
105
  # Takes care of fectching versions and version list
101
106
  module UnityVersions
102
107
  #####################################################
103
108
  # @!group URLS: Locations to fetch information from
104
109
  #####################################################
105
110
  # URL for the forum thread listing all the Linux releases
106
- UNITY_LINUX_DOWNLOADS = 'https://forum.unity.com/threads/unity-on-linux-release-notes-and-known-issues.350256/'.freeze
111
+ UNITY_LINUX_DOWNLOADS = 'https://forum.unity.com/threads/unity-on-linux-release-notes-and-known-issues.350256/'
107
112
  # URL for the main releases for Windows and Macintosh
108
- UNITY_DOWNLOADS = 'https://unity3d.com/get-unity/download/archive'.freeze
113
+ UNITY_DOWNLOADS = 'https://unity3d.com/get-unity/download/archive'
109
114
  # URL for the LTS releases for Windows and Macintosh
110
- UNITY_LTSES = 'https://unity3d.com/unity/qa/lts-releases'.freeze
115
+ UNITY_LTSES = 'https://unity3d.com/unity/qa/lts-releases'
111
116
  # URL for the patch releases for Windows and Macintosh
112
- UNITY_PATCHES = 'https://unity3d.com/unity/qa/patch-releases'.freeze
117
+ UNITY_PATCHES = 'https://unity3d.com/unity/qa/patch-releases'
113
118
  # URL for the beta releases list, they need to be accessed after
114
- UNITY_BETAS = 'https://unity3d.com/unity/beta/archive'.freeze
119
+ UNITY_BETAS = 'https://unity3d.com/unity/beta/archive'
115
120
  # URL for a specific beta, takes into parameter a version string (%s)
116
- UNITY_BETA_URL = 'https://unity3d.com/unity/beta/unity%<version>s'.freeze
121
+ UNITY_BETA_URL = 'https://unity3d.com/unity/beta/unity%<version>s'
117
122
  # URL for latest releases listing (since Unity 2017.1.5f1), takes into parameter os (windows => win32, mac => darwin)
118
- UNITY_LATEST_JSON_URL = 'https://public-cdn.cloud.unity3d.com/hub/prod/releases-%<os>s.json'.freeze
123
+ UNITY_LATEST_JSON_URL = 'https://public-cdn.cloud.unity3d.com/hub/prod/releases-%<os>s.json'
119
124
 
120
125
  #####################################################
121
126
  # @!group REGEX: expressions to interpret data
122
127
  #####################################################
123
128
  # Captures a version and its base url
124
- LINUX_DOWNLOAD = %r{['"](https?:\/\/[\w/\.-]+/[0-9a-f\+]{12,13}\/)(.\/)?UnitySetup-(\d+\.\d+\.\d+\w\d+)['"]}
129
+ LINUX_DOWNLOAD = %r{['"](https?://[\w/.-]+/[0-9a-f+]{12,13}/)(./)?UnitySetup-(\d+\.\d+\.\d+\w\d+)['"]}.freeze
125
130
 
126
- MAC_WIN_SHADERS = %r{"(https?://[\w/\.-]+/[0-9a-f\+]{12,13}/)builtin_shaders-(\d+\.\d+\.\d+\w\d+)\.?\w+"}
127
- LINUX_INSTALLER = %r{(https?://[\w/\.-]+/[0-9a-f\+]{12,13}/)LinuxEditorInstaller/Unity.tar.xz}
131
+ MAC_WIN_SHADERS = %r{"(https?://[\w/.-]+/[0-9a-f+]{12,13}/)builtin_shaders-(\d+\.\d+\.\d+\w\d+)\.?\w+"}.freeze
132
+ LINUX_INSTALLER = %r{(https?://[\w/.-]+/[0-9a-f+]{12,13}/)LinuxEditorInstaller/Unity.tar.xz}.freeze
128
133
 
129
- LINUX_DOWNLOAD_DATED = %r{"(https?://[\w/\._-]+/unity\-editor\-installer\-(\d+\.\d+\.\d+\w\d+).*\.sh)"}
130
- LINUX_DOWNLOAD_RECENT_PAGE = %r{"(https?://beta\.unity3d\.com/download/[a-zA-Z0-9/\.\+]+/public_download\.html)"}
131
- LINUX_DOWNLOAD_RECENT_FILE = %r{'(https?://beta\.unity3d\.com/download/[a-zA-Z0-9/\.\+]+/unity\-editor\-installer\-(\d+\.\d+\.\d+(?:x)?\w\d+).*\.sh)'}
134
+ LINUX_DOWNLOAD_DATED = %r{"(https?://[\w/._-]+/unity-editor-installer-(\d+\.\d+\.\d+\w\d+).*\.sh)"}.freeze
135
+ LINUX_DOWNLOAD_RECENT_PAGE = %r{"(https?://beta\.unity3d\.com/download/[a-zA-Z0-9/.+]+/public_download\.html)"}.freeze
136
+ LINUX_DOWNLOAD_RECENT_FILE = %r{'(https?://beta\.unity3d\.com/download/[a-zA-Z0-9/.+]+/unity-editor-installer-(\d+\.\d+\.\d+(?:x)?\w\d+).*\.sh)'}.freeze
132
137
  # Captures a beta version in html page
133
- UNITY_BETAVERSION_REGEX = %r{\/unity\/beta\/unity(\d+\.\d+\.\d+\w\d+)"}
134
- UNITY_EXTRA_DOWNLOAD_REGEX = %r{"(https?:\/\/[\w\/.-]+\.unity3d\.com\/(\w+))\/[a-zA-Z\/.-]+\/download.html"}
138
+ UNITY_BETAVERSION_REGEX = %r{/unity/beta/unity(\d+\.\d+\.\d+\w\d+)"}.freeze
139
+ UNITY_EXTRA_DOWNLOAD_REGEX = %r{"(https?://[\w/.-]+\.unity3d\.com/(\w+))/[a-zA-Z/.-]+/download.html"}.freeze
135
140
  # For the latest releases fetched from json
136
- UNITY_LATEST_JSON = %r{(https?://[\w/\.-]+/[0-9a-f\+]{12,13}/)}
141
+ UNITY_LATEST_JSON = %r{(https?://[\w/.-]+/[0-9a-f+]{12,13}/)}.freeze
137
142
 
138
143
  class << self
139
144
  def list_available(os: nil)
@@ -191,7 +196,7 @@ module U3d
191
196
  end
192
197
 
193
198
  class LinuxVersions
194
- JSON_OS = 'linux'.freeze
199
+ JSON_OS = 'linux'
195
200
 
196
201
  @unity_forums = U3d::UnityForums.new
197
202
  class << self
@@ -300,7 +305,7 @@ module U3d
300
305
  end
301
306
 
302
307
  class MacVersions
303
- JSON_OS = 'darwin'.freeze
308
+ JSON_OS = 'darwin'
304
309
 
305
310
  class << self
306
311
  def list_available
@@ -312,7 +317,7 @@ module U3d
312
317
  end
313
318
 
314
319
  class WindowsVersions
315
- JSON_OS = 'win32'.freeze
320
+ JSON_OS = 'win32'
316
321
 
317
322
  class << self
318
323
  def list_available
data/lib/u3d/utils.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -27,11 +29,11 @@ require 'u3d_core/helper'
27
29
 
28
30
  module U3d
29
31
  # Several different utility methods
30
- # rubocop:disable ModuleLength
32
+ # rubocop:disable Metrics/ModuleLength
31
33
  module Utils
32
34
  # Regex to capture each part of a version string (0.0.0x0)
33
35
  CSIDL_LOCAL_APPDATA = 0x001c
34
- UNITY_VERSION_REGEX = /(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:(\w)(?:(\d+))?)?/
36
+ UNITY_VERSION_REGEX = /(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:(\w)(?:(\d+))?)?/.freeze
35
37
 
36
38
  class << self
37
39
  def final_url(url, redirect_limit: 10)
@@ -53,6 +55,7 @@ module U3d
53
55
 
54
56
  def follow_redirects(url, redirect_limit: 10, http_method: :get, request_headers: {}, &block)
55
57
  raise 'Too many redirections' if redirect_limit.zero?
58
+
56
59
  response = nil
57
60
  request = nil
58
61
  uri = URI(url)
@@ -65,15 +68,15 @@ module U3d
65
68
  end
66
69
  response = http.request request
67
70
  end
68
- rescue OpenSSL::OpenSSLError => ssl_error
71
+ rescue OpenSSL::OpenSSLError => e
69
72
  UI.error 'SSL has faced an error, you may want to check our README to fix it'
70
- raise ssl_error
73
+ raise e
71
74
  end
72
75
 
73
76
  case response
74
- when Net::HTTPSuccess then
77
+ when Net::HTTPSuccess
75
78
  yield(request, response)
76
- when Net::HTTPRedirection then
79
+ when Net::HTTPRedirection
77
80
  UI.verbose "Redirected to #{response['location']}"
78
81
  follow_redirects(response['location'], redirect_limit: redirect_limit - 1, http_method: http_method, request_headers: request_headers, &block)
79
82
  else raise "Request failed with status #{response.code}"
@@ -83,6 +86,7 @@ module U3d
83
86
  def http_request_class(method, uri)
84
87
  return Net::HTTP::Get.new uri if method == :get
85
88
  return Net::HTTP::Head.new uri if method == :head
89
+
86
90
  raise "Unknown method #{method}"
87
91
  end
88
92
 
@@ -111,10 +115,12 @@ module U3d
111
115
  # FIXME revisits, this slows down download on fast network
112
116
  # sleep 0.08 # adjust to reduce CPU
113
117
  next unless print_progress
118
+
114
119
  print_progress_now = Time.now.to_f - last_print_update > 0.5
115
120
  # force printing when done downloading
116
121
  print_progress_now = true if !print_progress_now && size && current >= size
117
122
  next unless print_progress_now
123
+
118
124
  last_print_update = Time.now.to_f
119
125
  Utils.print_progress(current, size, started_at)
120
126
  print "\n" unless UI.interactive?
@@ -140,6 +146,7 @@ module U3d
140
146
  def hashfile(file_path, blocksize: 65_536)
141
147
  require 'digest'
142
148
  raise ArgumentError, 'Not a file' unless File.file?(file_path)
149
+
143
150
  md5 = Digest::MD5.new
144
151
  File.open(file_path, 'r') do |f|
145
152
  md5 << f.read(blocksize) until f.eof?
@@ -155,9 +162,10 @@ module U3d
155
162
  if U3dCore::Helper.operating_system == :win
156
163
  yield
157
164
  else
158
- stat_command = if U3dCore::Helper.operating_system == :linux
165
+ stat_command = case U3dCore::Helper.operating_system
166
+ when :linux
159
167
  "stat -c \"%U,%a\" #{dir}"
160
- elsif U3dCore::Helper.operating_system == :mac
168
+ when :mac
161
169
  "stat -f \"%Su,%A\" #{dir}"
162
170
  end
163
171
  owner, access = U3dCore::CommandExecutor.execute(command: stat_command, admin: false).strip.split(',')
@@ -199,29 +207,87 @@ module U3d
199
207
  ver = UNITY_VERSION_REGEX.match(version)
200
208
  if ver.nil?
201
209
  raise ArgumentError, "Version (#{version}) does not match the Unity "\
202
- 'version format 0.0.0x0'
210
+ 'version format 0.0.0x0'
203
211
  end
204
212
  [ver[1], ver[2], ver[3], ver[4], ver[5]]
205
213
  end
206
214
 
207
215
  def windows_local_appdata
208
- require 'win32api'
216
+ require "fiddle"
209
217
 
218
+ shell32 = Fiddle.dlopen('shell32')
219
+ getdir = Fiddle::Function.new(shell32['SHGetFolderPath'], [Fiddle::TYPE_LONG, Fiddle::TYPE_LONG, Fiddle::TYPE_LONG, Fiddle::TYPE_LONG, Fiddle::TYPE_VOIDP], Fiddle::TYPE_LONG)
210
220
  windir = ' ' * 261
211
-
212
- getdir = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L')
213
221
  result = getdir.call(0, CSIDL_LOCAL_APPDATA, 0, 0, windir)
222
+
214
223
  raise "Unable to get Local Appdata directory, returned with value #{result}" unless result.zero?
224
+
215
225
  windir.rstrip!
216
226
  windir = windir.encode("UTF-8", Encoding.find('filesystem'))
217
227
  windir = File.expand_path(windir.rstrip)
218
228
 
219
229
  return windir if Dir.exist? windir
230
+
220
231
  raise "Local Appdata retrieved (#{windir}) is not correct"
221
232
  end
222
233
 
234
+ def windows_fileversion(info_key, path)
235
+ require "fiddle"
236
+ version_dll = Fiddle.dlopen('version.dll')
237
+ kernel32 = Fiddle.dlopen('kernel32.dll')
238
+
239
+ get_file_version_info_size = Fiddle::Function.new(version_dll['GetFileVersionInfoSize'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_LONG)
240
+ get_file_version_info = Fiddle::Function.new(version_dll['GetFileVersionInfo'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_INT, Fiddle::TYPE_INT, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT) # FIXME: TYPE_INT => TYPE_LONG??
241
+ ver_query_value = Fiddle::Function.new(version_dll['VerQueryValue'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
242
+ rtl_move_memory = Fiddle::Function.new(kernel32['RtlMoveMemory'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_LONG, Fiddle::TYPE_LONG], Fiddle::TYPE_INT)
243
+
244
+ file = "#{path.tr('/', '\\')}\u0000"
245
+
246
+ s = [0].pack('L')
247
+ version_size = get_file_version_info_size.call(file, s)
248
+ raise StandardError if version_size.zero?
249
+
250
+ version_info = ' ' * version_size
251
+ version_ok = get_file_version_info.call(file, 0, version_size, version_info)
252
+ raise StandardError if version_ok.zero? # TODO: use GetLastError
253
+
254
+ # hack, giving up using VerQueryValue for now.
255
+ rstring = version_info.unpack('v*').map { |c| c.chr if c < 256 } * ''
256
+ r = /#{info_key}..(.*?)\000/.match(rstring)
257
+ # puts "#{info_key} = #{r ? r[1] : '??'}"
258
+ return r ? r[1] : nil
259
+
260
+ # rubocop:disable Lint/UnreachableCode
261
+ # hardcoding lang codepage
262
+ struct_path = "\\StringFileInfo\\040904b0\\#{info_key}"
263
+
264
+ addr = [0].pack('L')
265
+ size = [0].pack('L')
266
+ query_ok = ver_query_value.call(version_info, "#{struct_path}\u0000", addr, size)
267
+ raise StandardError if query_ok.zero?
268
+
269
+ raddr = addr.unpack1('L')
270
+ rsize = size.unpack1('L')
271
+
272
+ # this is not working right now, getting seg faults and other low level issues
273
+ puts "Size: #{raddr} #{rsize}"
274
+ fixed_info = Array.new(rsize, 0).pack('L*')
275
+ query_ok = rtl_move_memory.call(fixed_info, raddr, fixed_info.length)
276
+ raise StandardError if query_ok.zero?
277
+
278
+ info = fixed_info.unpack('L*')
279
+ file_version = [info[4], info[3], info[6], info[5]]
280
+ product_version = [info[8], info[7], info[10], info[9]]
281
+ [file_version, product_version]
282
+ # rubocop:enable Lint/UnreachableCode
283
+ rescue StandardError => e
284
+ UI.error("Failure to find '#{info_key}' under '#{path}': #{e}")
285
+ UI.error(e.backtrace)
286
+ nil
287
+ end
288
+
223
289
  def pretty_filesize(filesize)
224
- Filesize.from(filesize.round.to_s + ' B').pretty
290
+ Filesize.from("#{filesize.round} B").pretty
225
291
  end
226
292
 
227
293
  def windows_path(path)
@@ -249,14 +315,19 @@ module U3d
249
315
  end
250
316
  end
251
317
 
318
+ def file_exists_not_empty?(path)
319
+ File.file?(path) && File.size(path).positive?
320
+ end
321
+
252
322
  private
253
323
 
254
324
  def http_max_retries
255
- ENV['U3D_HTTP_MAX_RETRIES'].to_i if ENV['U3D_HTTP_MAX_RETRIES']
325
+ ENV.fetch('U3D_HTTP_MAX_RETRIES', nil)&.to_i
256
326
  end
257
327
 
258
328
  def http_read_timeout
259
329
  return ENV['U3D_HTTP_READ_TIMEOUT'].to_i if ENV['U3D_HTTP_READ_TIMEOUT']
330
+
260
331
  300
261
332
  end
262
333
 
@@ -270,5 +341,5 @@ module U3d
270
341
  end
271
342
  end
272
343
  end
273
- # rubocop:enable ModuleLength
344
+ # rubocop:enable Metrics/ModuleLength
274
345
  end
data/lib/u3d/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -21,11 +23,11 @@
21
23
  ## --- END LICENSE BLOCK ---
22
24
 
23
25
  module U3d
24
- VERSION = '1.2.2'.freeze
25
- DESCRIPTION = 'Provides numerous tools for installing, managing and running the Unity game engine from command line.'.freeze
26
+ VERSION = '1.3.1'
27
+ DESCRIPTION = 'Provides numerous tools for installing, managing and running the Unity game engine from command line.'
26
28
  UNITY_VERSIONS_NOTE = "Unity uses the following version formatting: 0.0.0x0. The \'x\' can takes different values:\n"\
27
- "\t. 'f' are the main release candidates for Unity\n"\
28
- "\t. 'p' are patches fixing those releases\n"\
29
- "\t. 'b' are the beta releases\n"\
30
- "\t. 'a' are the alpha releases (not currently discovered)\n".freeze
29
+ "\t. 'f' are the main release candidates for Unity\n"\
30
+ "\t. 'p' are patches fixing those releases\n"\
31
+ "\t. 'b' are the beta releases\n"\
32
+ "\t. 'a' are the alpha releases (not currently discovered)\n"
31
33
  end
data/lib/u3d.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #
@@ -48,4 +50,15 @@ require 'u3d/unity_versions'
48
50
  module U3d
49
51
  Helper = U3dCore::Helper
50
52
  UI = U3dCore::UI
53
+
54
+ def self.const_missing(const_name)
55
+ deprecated = {
56
+ PlaybackEngineUtils: IvyPlaybackEngineUtils,
57
+ INIParser: INIModulesParser
58
+ }
59
+ super unless deprecated.keys.include? const_name
60
+ replacement = deprecated[const_name]
61
+ UI.deprecated "DEPRECATION WARNING: the class U3d::#{const_name} is deprecated. Use #{replacement} instead."
62
+ replacement
63
+ end
51
64
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Original work Copyright (c) 2015-present the fastlane authors
3
5
  # Modified work Copyright 2016-present WeWantToKnow AS
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Original work Copyright (c) 2015-present the fastlane authors
3
5
  # Modified work Copyright 2016-present WeWantToKnow AS
@@ -65,7 +67,7 @@ module U3dCore
65
67
  output_callback = proc do |line|
66
68
  # Prefix the current line with a string
67
69
  prefix.each do |element|
68
- line = element[:prefix] + line if element[:block] && element[:block].call(line)
70
+ line = element[:prefix] + line if element[:block]&.call(line)
69
71
  end
70
72
  UI.command_output(line)
71
73
  end
@@ -97,27 +99,28 @@ module U3dCore
97
99
  line = l.strip # strip so that \n gets removed
98
100
  output << line
99
101
 
100
- output_callback.call(l) if output_callback
102
+ output_callback&.call(l)
101
103
  end
102
104
  end
103
105
  raise "Exit status: #{status}".red if !status.nil? && status.nonzero?
104
- rescue StandardError => ex
106
+ rescue StandardError => e
105
107
  # This could happen
106
108
  # * if the status is failed
107
109
  # * when the environment is wrong:
108
110
  # > invalid byte sequence in US-ASCII (ArgumentError)
109
- output << ex.to_s
111
+ output << e.to_s
110
112
  o = output.join("\n")
111
113
  UI.verbose o
112
- raise ex unless error_callback
114
+ raise e unless error_callback
115
+
113
116
  error_callback.call(o, nil)
114
117
  end
115
118
  return output.join("\n")
116
119
  end
117
120
 
118
- # rubocop:disable PredicateName,PerceivedComplexity
121
+ # rubocop:disable Naming/PredicateName
119
122
  def has_admin_privileges?(retry_count: 2)
120
- # rubocop:enable PredicateName,PerceivedComplexity
123
+ # rubocop:enable Naming/PredicateName
121
124
  if Helper.windows?
122
125
  begin
123
126
  result = system_no_output('reg query HKU\\S-1-5-19')
@@ -152,6 +155,7 @@ module U3dCore
152
155
  unless env_username == "root"
153
156
  cred = U3dCore::Credentials.new(user: env_username)
154
157
  raise CredentialsError, "The command \'#{command}\' must be run with admin privileges" unless has_admin_privileges?
158
+
155
159
  command = "sudo -k && echo #{cred.password.shellescape} | sudo -S bash -c \"#{command}\""
156
160
  end
157
161
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Original work Copyright (c) 2015-present the fastlane authors
3
5
  # Modified work Copyright 2016-present WeWantToKnow AS
@@ -36,6 +38,7 @@ module U3dCore
36
38
  def select_runner_impl
37
39
  # disable PTY by setting env variable
38
40
  return U3dCore::SafePopen.method(:spawn) unless ENV['U3D_NO_TTY'].nil?
41
+
39
42
  begin
40
43
  require 'pty'
41
44
  return U3dCore::SafePty.method(:spawn)
@@ -55,25 +58,20 @@ module U3dCore
55
58
  def self.spawn(command, &_block)
56
59
  require 'pty'
57
60
  PTY.spawn(command) do |r, w, p|
61
+ trap('INT') do
62
+ Process.kill("INT", p)
63
+ end
64
+ yield r, w, p
65
+ # if the process has closed, ruby might raise an exception if we try
66
+ # to do I/O on a closed stream. This behavior is platform specific
67
+ rescue Errno::EIO
68
+ ensure
58
69
  begin
59
- trap('INT') do
60
- Process.kill("INT", p)
61
- end
62
- yield r, w, p
63
- # if the process has closed, ruby might raise an exception if we try
64
- # to do I/O on a closed stream. This behavior is platform specific
65
- # rubocop:disable HandleExceptions
66
- rescue Errno::EIO
67
- # rubocop:enable HandleExceptions
68
- ensure
69
- begin
70
- Process.wait p
71
- # The process might have exited.
72
- # This behavior is also ruby version dependent.
73
- # rubocop:disable HandleExceptions
74
- rescue Errno::ECHILD, PTY::ChildExited
75
- end
76
- # rubocop:enable HandleExceptions
70
+ Process.wait p
71
+ # The process might have exited.
72
+ # This behavior is also ruby version dependent.
73
+ rescue Errno::ECHILD, PTY::ChildExited
74
+ # do nothing
77
75
  end
78
76
  end
79
77
  $CHILD_STATUS.exitstatus
@@ -88,7 +86,7 @@ module U3dCore
88
86
  def self.spawn(command, &_block)
89
87
  require 'open3'
90
88
  Open3.popen2e(command) do |r, w, p|
91
- yield w, r, p.value.pid # note the inversion
89
+ yield w, r, p.value.pid # NOTE: the inversion
92
90
 
93
91
  r.close
94
92
  w.close
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2017-present WeWantToKnow AS
3
5
  #
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2017-present WeWantToKnow AS
3
5
  #
@@ -26,6 +28,7 @@ module CoreExtensions
26
28
  return 'Windows' if self == :win
27
29
  return 'Mac OSX' if self == :mac
28
30
  return 'Linux' if self == :linux
31
+
29
32
  raise "Not a known operating system symbol #{self}"
30
33
  end
31
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ## --- BEGIN LICENSE BLOCK ---
2
4
  # Copyright (c) 2016-present WeWantToKnow AS
3
5
  #