u3d 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  #