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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +33 -10
- data/.github/workflows/ci.yml +35 -0
- data/.github_changelog_generator +3 -1
- data/.gitignore +1 -0
- data/.rubocop.yml +15 -3
- data/CHANGELOG.md +83 -11
- data/Gemfile.lock +147 -87
- data/Rakefile +20 -12
- data/appveyor.yml +25 -6
- data/examples/Example1/Gemfile +4 -2
- data/examples/Example1/Gemfile.lock +8 -6
- data/examples/Example1/Rakefile +2 -0
- data/examples/Example1/fastlane/Fastfile +2 -0
- data/examples/Example2/Gemfile +4 -2
- data/examples/Example2/Gemfile.lock +12 -7
- data/examples/Example2/fastlane/Fastfile +2 -0
- data/exe/u3d +3 -1
- data/lib/u3d/asset.rb +6 -2
- data/lib/u3d/cache.rb +14 -10
- data/lib/u3d/commands.rb +15 -11
- data/lib/u3d/commands_generator.rb +6 -4
- data/lib/u3d/compatibility.rb +2 -0
- data/lib/u3d/download_validator.rb +6 -3
- data/lib/u3d/downloader.rb +12 -8
- data/lib/u3d/failure_reporter.rb +4 -3
- data/lib/u3d/hub_modules_parser.rb +24 -7
- data/lib/u3d/ini_modules_parser.rb +10 -32
- data/lib/u3d/installation.rb +77 -66
- data/lib/u3d/installer.rb +46 -33
- data/lib/u3d/log_analyzer.rb +31 -27
- data/lib/u3d/unity_license.rb +2 -0
- data/lib/u3d/unity_module.rb +2 -0
- data/lib/u3d/unity_project.rb +4 -1
- data/lib/u3d/unity_runner.rb +12 -10
- data/lib/u3d/unity_version_definition.rb +3 -0
- data/lib/u3d/unity_version_number.rb +8 -2
- data/lib/u3d/unity_versions.rb +28 -23
- data/lib/u3d/utils.rb +86 -15
- data/lib/u3d/version.rb +8 -6
- data/lib/u3d.rb +13 -0
- data/lib/u3d_core/admin_tools.rb +2 -0
- data/lib/u3d_core/command_executor.rb +11 -7
- data/lib/u3d_core/command_runner.rb +17 -19
- data/lib/u3d_core/core_ext/hash.rb +2 -0
- data/lib/u3d_core/core_ext/operating_system_symbol.rb +3 -0
- data/lib/u3d_core/core_ext/string.rb +2 -0
- data/lib/u3d_core/credentials.rb +9 -7
- data/lib/u3d_core/env.rb +3 -0
- data/lib/u3d_core/globals.rb +7 -7
- data/lib/u3d_core/helper.rb +6 -4
- data/lib/u3d_core/ui/disable_colors.rb +2 -0
- data/lib/u3d_core/ui/implementations/shell.rb +8 -5
- data/lib/u3d_core/ui/interface.rb +3 -0
- data/lib/u3d_core/ui/ui.rb +5 -4
- data/lib/u3d_core/update_checker/changelog.rb +4 -0
- data/lib/u3d_core/update_checker/update_checker.rb +7 -8
- data/lib/u3d_core/version.rb +2 -0
- data/lib/u3d_core.rb +2 -0
- data/u3d.gemspec +19 -9
- metadata +101 -29
data/lib/u3d/unity_runner.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
|
#
|
@@ -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
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
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
|
|
data/lib/u3d/unity_versions.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
|
#
|
@@ -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
|
62
|
+
when Net::HTTPSuccess
|
60
63
|
UI.verbose "unexpected result"
|
61
|
-
when Net::HTTPRedirection
|
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 <<
|
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/'
|
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'
|
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'
|
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'
|
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'
|
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'
|
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'
|
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
|
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
|
127
|
-
LINUX_INSTALLER = %r{(https?://[\w
|
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
|
130
|
-
LINUX_DOWNLOAD_RECENT_PAGE = %r{"(https?://beta\.unity3d\.com/download/[a-zA-Z0-9
|
131
|
-
LINUX_DOWNLOAD_RECENT_FILE = %r{'(https?://beta\.unity3d\.com/download/[a-zA-Z0-9
|
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{
|
134
|
-
UNITY_EXTRA_DOWNLOAD_REGEX = %r{"(https
|
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
|
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'
|
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'
|
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'
|
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 =>
|
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
|
73
|
+
raise e
|
71
74
|
end
|
72
75
|
|
73
76
|
case response
|
74
|
-
when Net::HTTPSuccess
|
77
|
+
when Net::HTTPSuccess
|
75
78
|
yield(request, response)
|
76
|
-
when Net::HTTPRedirection
|
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 =
|
165
|
+
stat_command = case U3dCore::Helper.operating_system
|
166
|
+
when :linux
|
159
167
|
"stat -c \"%U,%a\" #{dir}"
|
160
|
-
|
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
|
-
|
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
|
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
|
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
|
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.
|
25
|
-
DESCRIPTION = 'Provides numerous tools for installing, managing and running the Unity game engine from command line.'
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
data/lib/u3d_core/admin_tools.rb
CHANGED
@@ -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]
|
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
|
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 =>
|
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 <<
|
111
|
+
output << e.to_s
|
110
112
|
o = output.join("\n")
|
111
113
|
UI.verbose o
|
112
|
-
raise
|
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
|
121
|
+
# rubocop:disable Naming/PredicateName
|
119
122
|
def has_admin_privileges?(retry_count: 2)
|
120
|
-
# rubocop:enable PredicateName
|
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
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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 #
|
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
|
#
|
@@ -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
|