u3d 1.2.3 → 1.3.0
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 +5 -5
- 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 +62 -11
- data/Gemfile.lock +147 -87
- data/Rakefile +12 -7
- 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 +14 -9
- 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 -8
- data/lib/u3d/installation.rb +31 -49
- data/lib/u3d/installer.rb +44 -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 +82 -15
- data/lib/u3d/version.rb +8 -6
- data/lib/u3d.rb +2 -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 -30
data/lib/u3d/cache.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
|
#
|
@@ -32,12 +34,12 @@ module U3d
|
|
32
34
|
using ::CoreExtensions::OperatingSystem
|
33
35
|
|
34
36
|
# Name of the cache file
|
35
|
-
DEFAULT_NAME = 'cache.json'
|
37
|
+
DEFAULT_NAME = 'cache.json'
|
36
38
|
# Maximum duration after which the cache is considered outdated
|
37
39
|
# Currently set to 24h
|
38
40
|
CACHE_LIFE = 60 * 60 * 24
|
39
41
|
|
40
|
-
GLOBAL_CACHE_URL = 'https://dragonbox.github.io/unities/v1/versions.json'
|
42
|
+
GLOBAL_CACHE_URL = 'https://dragonbox.github.io/unities/v1/versions.json'
|
41
43
|
|
42
44
|
private
|
43
45
|
|
@@ -49,11 +51,13 @@ module U3d
|
|
49
51
|
|
50
52
|
def [](key)
|
51
53
|
return nil if @cache[key].nil?
|
54
|
+
|
52
55
|
@cache[key]
|
53
56
|
end
|
54
57
|
|
55
58
|
def initialize(path: nil, force_os: nil, force_refresh: false, offline: false, central_cache: false)
|
56
59
|
raise "Cache: cannot specify both offline and force_refresh" if offline && force_refresh
|
60
|
+
|
57
61
|
@path = path || Cache.default_os_path
|
58
62
|
@cache = {}
|
59
63
|
os = force_os || U3dCore::Helper.operating_system
|
@@ -78,23 +82,23 @@ module U3d
|
|
78
82
|
def check_for_update(file_path, os)
|
79
83
|
need_update = false
|
80
84
|
data = {}
|
81
|
-
if
|
82
|
-
need_update = true
|
83
|
-
else
|
85
|
+
if File.file?(file_path)
|
84
86
|
begin
|
85
87
|
File.open(file_path, 'r') do |f|
|
86
88
|
data = JSON.parse(f.read)
|
87
89
|
end
|
88
|
-
rescue JSON::ParserError =>
|
89
|
-
UI.error
|
90
|
+
rescue JSON::ParserError => e
|
91
|
+
UI.error "Failed to parse cache.json: #{e}"
|
90
92
|
need_update = true
|
91
|
-
rescue SystemCallError =>
|
92
|
-
UI.error
|
93
|
+
rescue SystemCallError => e
|
94
|
+
UI.error "Failed to open cache.json: #{e}"
|
93
95
|
need_update = true
|
94
96
|
else
|
95
97
|
need_update = os_data_need_update?(data, os)
|
96
98
|
data[os.id2name] = nil if need_update
|
97
99
|
end
|
100
|
+
else
|
101
|
+
need_update = true
|
98
102
|
end
|
99
103
|
return need_update, data
|
100
104
|
end
|
@@ -111,7 +115,7 @@ module U3d
|
|
111
115
|
update_cache(os) unless central_cache && fetch_central_cache(os)
|
112
116
|
|
113
117
|
File.delete(file_path) if File.file?(file_path)
|
114
|
-
File.
|
118
|
+
File.write(file_path, @cache.to_json)
|
115
119
|
end
|
116
120
|
|
117
121
|
# Fetches central versions.json. Ignore it if it is too old
|
data/lib/u3d/commands.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
|
#
|
@@ -37,7 +39,7 @@ require 'fileutils'
|
|
37
39
|
|
38
40
|
module U3d
|
39
41
|
# API for U3d, redirecting calls to class they concern
|
40
|
-
# rubocop:disable ClassLength
|
42
|
+
# rubocop:disable Metrics/ClassLength
|
41
43
|
class Commands
|
42
44
|
using ::CoreExtensions::Extractable
|
43
45
|
|
@@ -51,18 +53,18 @@ module U3d
|
|
51
53
|
return
|
52
54
|
end
|
53
55
|
list.each do |u|
|
54
|
-
version_format = "Version %-15
|
56
|
+
version_format = "Version %-15<version>s [%<build_number>s] %<do_not_move>s(%<root_path>s)"
|
55
57
|
do_not_move = u.do_not_move? ? '!'.red.bold : ' '
|
56
58
|
h = { version: u.version, build_number: u.build_number, root_path: u.root_path, do_not_move: do_not_move }
|
57
59
|
UI.message version_format % h
|
58
60
|
packages = u.packages
|
59
61
|
next unless options[:packages] && packages && !packages.empty?
|
62
|
+
|
60
63
|
UI.message 'Packages:'
|
61
64
|
packages.each { |pack| UI.message " - #{pack}" }
|
62
65
|
end
|
63
66
|
end
|
64
67
|
|
65
|
-
# rubocop:disable Style/FormatStringToken
|
66
68
|
def console
|
67
69
|
require 'irb'
|
68
70
|
ARGV.clear
|
@@ -81,7 +83,6 @@ module U3d
|
|
81
83
|
|
82
84
|
catch(:IRB_EXIT) { @irb.eval_input }
|
83
85
|
end
|
84
|
-
# rubocop:enable Style/FormatStringToken
|
85
86
|
|
86
87
|
def move(args: {}, options: {})
|
87
88
|
long_name = options[:long]
|
@@ -131,6 +132,7 @@ module U3d
|
|
131
132
|
v = cache_versions[k]
|
132
133
|
UI.message "Version #{k}: " + v.to_s.cyan.underline
|
133
134
|
next unless show_packages
|
135
|
+
|
134
136
|
version_packages = packages[k]
|
135
137
|
UI.message 'Packages:'
|
136
138
|
version_packages.each { |package| UI.message " - #{package.id.capitalize}" }
|
@@ -166,6 +168,7 @@ module U3d
|
|
166
168
|
files = Downloader.fetch_modules(definition, packages: packages, download: options[:download])
|
167
169
|
|
168
170
|
return unless options[:install]
|
171
|
+
|
169
172
|
Installer.install_modules(files, definition.version, installation_path: options[:installation_path])
|
170
173
|
end
|
171
174
|
|
@@ -222,12 +225,14 @@ module U3d
|
|
222
225
|
action = args[0]
|
223
226
|
raise "Please specify an action to perform, one of #{credentials_actions.join(',')}" unless action
|
224
227
|
raise "Unknown action '#{action}'. Use one of #{credentials_actions.join(',')}" unless credentials_actions.include? action
|
225
|
-
|
228
|
+
|
229
|
+
case action
|
230
|
+
when 'add'
|
226
231
|
U3dCore::Globals.use_keychain = true
|
227
232
|
# credentials = U3dCore::Credentials.new(user: ENV['USER'])
|
228
233
|
# credentials.login # ask password
|
229
234
|
UI.error 'Invalid credentials' unless U3dCore::CommandExecutor.has_admin_privileges?
|
230
|
-
|
235
|
+
when 'remove'
|
231
236
|
U3dCore::Globals.use_keychain = true
|
232
237
|
U3dCore::Credentials.new(user: ENV['USER']).forget_credentials(force: true)
|
233
238
|
else
|
@@ -269,8 +274,7 @@ module U3d
|
|
269
274
|
def cache_versions(os, offline: false, force_refresh: false, central_cache: true)
|
270
275
|
cache = Cache.new(force_os: os, offline: offline, force_refresh: force_refresh, central_cache: central_cache)
|
271
276
|
cache_os = cache[os.id2name] || {}
|
272
|
-
|
273
|
-
cache_versions
|
277
|
+
cache_os['versions'] || {}
|
274
278
|
end
|
275
279
|
|
276
280
|
def verify_package_names(packages, definition)
|
@@ -418,6 +422,7 @@ module U3d
|
|
418
422
|
package = definition[package_name]
|
419
423
|
return true unless package.depends_on
|
420
424
|
return true if unity.package_installed?(package.depends_on)
|
425
|
+
|
421
426
|
installing.map { |other| definition[other] }.any? do |other|
|
422
427
|
other.id == package.depends_on || other.name == package.depends_on
|
423
428
|
end
|
@@ -430,7 +435,7 @@ module U3d
|
|
430
435
|
end
|
431
436
|
end
|
432
437
|
end
|
433
|
-
# rubocop:enable ClassLength
|
438
|
+
# rubocop:enable Metrics/ClassLength
|
434
439
|
end
|
435
440
|
|
436
441
|
class InstallationSetupError < StandardError
|
@@ -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
|
#
|
@@ -28,12 +30,12 @@ HighLine.track_eof = false
|
|
28
30
|
|
29
31
|
module U3d
|
30
32
|
# CLI using commander gem for u3d
|
31
|
-
# rubocop:disable ClassLength
|
33
|
+
# rubocop:disable Metrics/ClassLength
|
32
34
|
class CommandsGenerator
|
33
35
|
include Commander::Methods
|
34
36
|
UI = U3dCore::UI
|
35
37
|
|
36
|
-
UNICODE_FILE = File.expand_path('
|
38
|
+
UNICODE_FILE = File.expand_path('../assets/utf8.txt', __dir__)
|
37
39
|
|
38
40
|
def self.start
|
39
41
|
U3dCore::UpdateChecker.start_looking_for_update('u3d')
|
@@ -97,7 +99,7 @@ Fore more information about how the rules work, see https://github.com/DragonBox
|
|
97
99
|
c.option '-u', '--unity_version STRING', String, 'Version of Unity to run with. If not specified, it runs with the version of the project (either specified as -projectPath or current)'
|
98
100
|
c.option '-r', '--raw_logs', 'Raw Unity output, not filtered by u3d\'s log prettifier'
|
99
101
|
c.action do |args, options|
|
100
|
-
UI.user_error! "Run doesn't take arguments. Did you forget '--' or did you mistake your command? (#{args})" if args.count
|
102
|
+
UI.user_error! "Run doesn't take arguments. Did you forget '--' or did you mistake your command? (#{args})" if args.count.positive?
|
101
103
|
U3dCore::Globals.log_timestamps = true
|
102
104
|
Commands.run(options: convert_options(options), run_args: run_args)
|
103
105
|
end
|
@@ -263,5 +265,5 @@ More on that: https://forum.unity3d.com/threads/unity-on-linux-release-notes-and
|
|
263
265
|
run!
|
264
266
|
end
|
265
267
|
end
|
266
|
-
# rubocop:enable ClassLength
|
268
|
+
# rubocop:enable Metrics/ClassLength
|
267
269
|
end
|
data/lib/u3d/compatibility.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
|
#
|
@@ -51,7 +53,8 @@ module U3d
|
|
51
53
|
|
52
54
|
class LinuxValidator < DownloadValidator
|
53
55
|
def validate(package, file, definition)
|
54
|
-
return size_validation(expected: definition[package].download_size, actual: File.size(file)) if definition[package]
|
56
|
+
return size_validation(expected: definition[package].download_size, actual: File.size(file)) if definition[package]&.download_size
|
57
|
+
|
55
58
|
UI.important "No file validation available, #{file} is assumed to be correct"
|
56
59
|
true
|
57
60
|
end
|
@@ -59,7 +62,7 @@ module U3d
|
|
59
62
|
|
60
63
|
class MacValidator < DownloadValidator
|
61
64
|
def validate(package, file, definition)
|
62
|
-
if definition[package].download_size % 1000 && definition[package].checksum.nil?
|
65
|
+
if (definition[package].download_size % 1000) && definition[package].checksum.nil?
|
63
66
|
UI.verbose "File '#{definition[package].name}' seems external. Validation skipped"
|
64
67
|
return true
|
65
68
|
end
|
@@ -71,7 +74,7 @@ module U3d
|
|
71
74
|
class WindowsValidator < DownloadValidator
|
72
75
|
def validate(package, file, definition)
|
73
76
|
# External packages have no md5 and a false size value
|
74
|
-
if definition[package].download_size % 1000 && definition[package].checksum.nil?
|
77
|
+
if (definition[package].download_size % 1000) && definition[package].checksum.nil?
|
75
78
|
UI.verbose "File '#{definition[package].name}' seems external. Validation skipped"
|
76
79
|
return true
|
77
80
|
end
|
data/lib/u3d/downloader.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,13 +29,13 @@ module U3d
|
|
27
29
|
# Take care of downloading files and packages
|
28
30
|
module Downloader
|
29
31
|
# Name of the directory for the package downloading
|
30
|
-
DOWNLOAD_DIRECTORY = 'Unity_Packages'
|
32
|
+
DOWNLOAD_DIRECTORY = 'Unity_Packages'
|
31
33
|
# Path to the directory for the package downloading
|
32
|
-
DOWNLOAD_PATH = "#{ENV['HOME']}/Downloads"
|
34
|
+
DOWNLOAD_PATH = "#{ENV['HOME']}/Downloads"
|
33
35
|
# Regex to get the name of a localization asset
|
34
|
-
UNITY_LANGUAGE_FILE_REGEX = %r{
|
36
|
+
UNITY_LANGUAGE_FILE_REGEX = %r{/\d+/[0-9.]+/([\w-]+)$}.freeze
|
35
37
|
# Regex to get the name of a package out of its file name
|
36
|
-
UNITY_MODULE_FILE_REGEX = %r{
|
38
|
+
UNITY_MODULE_FILE_REGEX = %r{/([\w\-_.+]+\.(?:pkg|dmg|exe|zip|sh|deb|msi|xz))[^/]*$}.freeze
|
37
39
|
|
38
40
|
class << self
|
39
41
|
def download_directory
|
@@ -112,15 +114,15 @@ module U3d
|
|
112
114
|
return
|
113
115
|
else
|
114
116
|
extension = File.extname(path)
|
115
|
-
new_path = File.join(File.dirname(path), File.basename(path, extension)
|
117
|
+
new_path = File.join(File.dirname(path), "#{File.basename(path, extension)}_CORRUPTED#{extension}")
|
116
118
|
UI.important "File present at #{path} is not correct, it has been renamed to #{new_path}"
|
117
119
|
File.rename(path, new_path)
|
118
120
|
end
|
119
121
|
end
|
120
122
|
|
121
123
|
UI.header "Downloading #{package_info.name} version #{definition.version}"
|
122
|
-
UI.message
|
123
|
-
UI.message
|
124
|
+
UI.message "Downloading from #{url.to_s.cyan.underline}"
|
125
|
+
UI.message "Download will be found at #{path}"
|
124
126
|
download_package(path, url, size: package_info.download_size)
|
125
127
|
|
126
128
|
if validator.validate(package, path, definition)
|
@@ -153,7 +155,7 @@ module U3d
|
|
153
155
|
Utils.ensure_dir(dir)
|
154
156
|
|
155
157
|
file_name = if (language_match = UNITY_LANGUAGE_FILE_REGEX.match(final_url))
|
156
|
-
language_match[1]
|
158
|
+
"#{language_match[1]}.po" # Unity uses PO (Portable object files) for localization
|
157
159
|
elsif (module_match = UNITY_MODULE_FILE_REGEX.match(final_url))
|
158
160
|
module_match[1]
|
159
161
|
else
|
@@ -182,8 +184,10 @@ module U3d
|
|
182
184
|
# for backward compatibility
|
183
185
|
class MacDownloader < StandardPackageDownloader
|
184
186
|
end
|
187
|
+
|
185
188
|
class LinuxDownloader < StandardPackageDownloader
|
186
189
|
end
|
190
|
+
|
187
191
|
class WindowsDownloader < StandardPackageDownloader
|
188
192
|
end
|
189
193
|
end
|
data/lib/u3d/failure_reporter.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'date'
|
2
4
|
require 'fileutils'
|
3
5
|
require 'json'
|
@@ -9,6 +11,7 @@ module U3d
|
|
9
11
|
class << self
|
10
12
|
def report(failure_type: "DEFAULT", failure_message: "", data: {})
|
11
13
|
return unless ENV['U3D_REPORT_FAILURES']
|
14
|
+
|
12
15
|
report = {
|
13
16
|
type: failure_type,
|
14
17
|
message: failure_message,
|
@@ -21,9 +24,7 @@ module U3d
|
|
21
24
|
"#{failure_type}.#{Date.now.strftime('%Y%m%dT%H%M')}.failure.json"
|
22
25
|
)
|
23
26
|
|
24
|
-
File.
|
25
|
-
file.write JSON.pretty_generate(report)
|
26
|
-
end
|
27
|
+
File.write(report_file, JSON.pretty_generate(report))
|
27
28
|
rescue StandardError => e
|
28
29
|
UI.important "Unable to report a #{failure_type} failure. Please use --verbose to get more information about the failure"
|
29
30
|
UI.verbose "Unable to report failure: #{e}"
|
@@ -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
|
#
|
@@ -28,19 +30,34 @@ require 'u3d_core/helper'
|
|
28
30
|
module U3d
|
29
31
|
module HubModulesParser
|
30
32
|
class << self
|
31
|
-
HUB_MODULES_NAME = '%<version>s-%<os>s-modules.json'
|
33
|
+
HUB_MODULES_NAME = '%<version>s-%<os>s-modules.json'
|
32
34
|
|
33
35
|
def load_modules(version, os: U3dCore::Helper.operating_system, offline: false)
|
34
36
|
path = modules_path(version, os)
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
# force download if no hub file present
|
39
|
+
download_modules(os: os) if !File.file?(path) && File.size(path).positive? && !offline
|
40
|
+
|
41
|
+
unless File.file?(path) && File.size(path).positive?
|
42
|
+
UI.verbose "No modules registered for UnityHub for version #{version}"
|
43
|
+
# cached_versions.keys.map{|s| UnityVersionNumber.new(s)}
|
44
|
+
# searching for closest version
|
45
|
+
files = Dir.glob("#{default_modules_path}/*-#{os}-modules.json")
|
46
|
+
|
47
|
+
vn = UnityVersionNumber.new(version)
|
48
|
+
|
49
|
+
versions_and_paths = files.map do |p|
|
50
|
+
v = File.basename(p).split('-')[0]
|
51
|
+
[UnityVersionNumber.new(v), p]
|
52
|
+
end
|
53
|
+
# filtered by version major.minor.patch (same major & minor and patch higher or equal)
|
54
|
+
versions_and_paths = versions_and_paths.select { |a| a[0].parts[0] == vn.parts[0] && a[0].parts[1] == vn.parts[1] && a[0].parts[2] >= vn.parts[2] }
|
39
55
|
|
40
|
-
|
41
|
-
UI.
|
56
|
+
if versions_and_paths.empty?
|
57
|
+
UI.info "No closest version from UnityHub found for version #{version}"
|
42
58
|
return []
|
43
59
|
end
|
60
|
+
path = versions_and_paths.first[1]
|
44
61
|
end
|
45
62
|
|
46
63
|
return JSON.parse(File.read(path))
|
@@ -81,7 +98,7 @@ module U3d
|
|
81
98
|
path = modules_path(build['version'], os)
|
82
99
|
Utils.ensure_dir(File.dirname(path))
|
83
100
|
|
84
|
-
File.
|
101
|
+
File.write(path, build['modules'].to_json)
|
85
102
|
end
|
86
103
|
end
|
87
104
|
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
|
#
|
@@ -30,7 +32,7 @@ module U3d
|
|
30
32
|
#####################################################
|
31
33
|
# @!group INI parameters to load and save ini files
|
32
34
|
#####################################################
|
33
|
-
INI_NAME = 'unity-%<version>s-%<os>s.ini'
|
35
|
+
INI_NAME = 'unity-%<version>s-%<os>s.ini'
|
34
36
|
|
35
37
|
class << self
|
36
38
|
def load_ini(version, cached_versions, os: U3dCore::Helper.operating_system, offline: false)
|
@@ -42,8 +44,9 @@ module U3d
|
|
42
44
|
ini_name = format(INI_NAME, version: version, os: os)
|
43
45
|
Utils.ensure_dir(default_ini_path)
|
44
46
|
ini_path = File.expand_path(ini_name, default_ini_path)
|
45
|
-
unless File.file?(ini_path) && File.size(ini_path)
|
47
|
+
unless File.file?(ini_path) && File.size(ini_path).positive?
|
46
48
|
raise "INI file does not exist at #{ini_path}" if offline
|
49
|
+
|
47
50
|
download_ini(version, cached_versions, os, ini_name, ini_path)
|
48
51
|
end
|
49
52
|
begin
|
@@ -58,7 +61,8 @@ module U3d
|
|
58
61
|
ini_name = format(INI_NAME, version: version, os: 'linux')
|
59
62
|
Utils.ensure_dir(default_ini_path)
|
60
63
|
ini_path = File.expand_path(ini_name, default_ini_path)
|
61
|
-
return if File.file?(ini_path) && File.size(ini_path)
|
64
|
+
return if File.file?(ini_path) && File.size(ini_path).positive?
|
65
|
+
|
62
66
|
data = %([Unity]
|
63
67
|
; -- NOTE --
|
64
68
|
; This is not an official Unity file
|
@@ -90,16 +94,14 @@ url=#{url}
|
|
90
94
|
UI.verbose("Searching for ini file at #{uri}")
|
91
95
|
|
92
96
|
data = Net::HTTP.get(uri)
|
93
|
-
data.tr
|
94
|
-
data.gsub
|
97
|
+
data = data.tr("\"", '')
|
98
|
+
data = data.gsub(/Note:.+\n/, '')
|
95
99
|
|
96
100
|
write_ini_file(ini_path, data)
|
97
101
|
end
|
98
102
|
|
99
103
|
def write_ini_file(ini_path, data)
|
100
|
-
File.
|
101
|
-
f.write(data)
|
102
|
-
end
|
104
|
+
File.binwrite(ini_path, data)
|
103
105
|
end
|
104
106
|
|
105
107
|
def default_ini_path
|
data/lib/u3d/installation.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
|
#
|
@@ -25,9 +27,12 @@ require 'u3d_core/admin_tools'
|
|
25
27
|
require 'fileutils'
|
26
28
|
|
27
29
|
module U3d
|
28
|
-
UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d
|
29
|
-
UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z
|
30
|
-
|
30
|
+
UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/.freeze
|
31
|
+
UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/.freeze
|
32
|
+
# Linux unity_builtin_extra seek position for version
|
33
|
+
UNITY_VERSION_LINUX_POS_LE_2019 = 20
|
34
|
+
UNITY_VERSION_LINUX_POS_GT_2019 = 48
|
35
|
+
U3D_DO_NOT_MOVE = ".u3d_do_not_move"
|
31
36
|
|
32
37
|
class Installation
|
33
38
|
attr_accessor :root_path
|
@@ -114,6 +119,7 @@ module U3d
|
|
114
119
|
require 'rexml/document'
|
115
120
|
UI.verbose("reading #{config_path}")
|
116
121
|
raise "File not found at #{config_path}" unless File.exist? config_path
|
122
|
+
|
117
123
|
doc = REXML::Document.new(File.read(config_path))
|
118
124
|
REXML::XPath.first(doc, node_name).value
|
119
125
|
end
|
@@ -142,10 +148,19 @@ module U3d
|
|
142
148
|
class InstallationUtils
|
143
149
|
def self.read_version_from_unity_builtin_extra(file)
|
144
150
|
File.open(file, "rb") do |f|
|
145
|
-
|
151
|
+
# Check if it is version lower or equal to 2019
|
152
|
+
seek_pos = UNITY_VERSION_LINUX_POS_LE_2019
|
153
|
+
f.seek(seek_pos)
|
154
|
+
z = f.read(1)
|
155
|
+
if z == "\x00"
|
156
|
+
# Version is greater than 2019
|
157
|
+
seek_pos = UNITY_VERSION_LINUX_POS_GT_2019
|
158
|
+
end
|
159
|
+
f.seek(seek_pos)
|
146
160
|
s = ""
|
147
161
|
while (c = f.read(1))
|
148
162
|
break if c == "\x00"
|
163
|
+
|
149
164
|
s += c
|
150
165
|
end
|
151
166
|
s
|
@@ -175,6 +190,7 @@ module U3d
|
|
175
190
|
def path
|
176
191
|
UI.deprecated("path is deprecated. Use root_path instead")
|
177
192
|
return @path if @path
|
193
|
+
|
178
194
|
"#{@root_path}/Unity.app"
|
179
195
|
end
|
180
196
|
|
@@ -217,13 +233,14 @@ module U3d
|
|
217
233
|
begin
|
218
234
|
fpath = "#{root_path}/Unity.app/Contents/Info.plist"
|
219
235
|
raise "#{fpath} doesn't exist" unless File.exist? fpath
|
236
|
+
|
220
237
|
Plist.parse_xml(fpath)
|
221
238
|
end
|
222
239
|
end
|
223
240
|
end
|
224
241
|
|
225
242
|
class LinuxInstallationHelper
|
226
|
-
STRINGS_FULL_VERSION_MATCHER = /^[0-9
|
243
|
+
STRINGS_FULL_VERSION_MATCHER = /^[0-9.abfp]+_[0-9a-f]{12}/.freeze
|
227
244
|
|
228
245
|
def find_build_number(root)
|
229
246
|
known_rev_locations.each do |p|
|
@@ -236,10 +253,10 @@ module U3d
|
|
236
253
|
private
|
237
254
|
|
238
255
|
def strings(path)
|
239
|
-
if `which strings`
|
240
|
-
binutils_strings(path)
|
241
|
-
else
|
256
|
+
if `which strings` == ''
|
242
257
|
Utils.strings(path).to_a
|
258
|
+
else
|
259
|
+
binutils_strings(path)
|
243
260
|
end
|
244
261
|
end
|
245
262
|
|
@@ -258,8 +275,9 @@ module U3d
|
|
258
275
|
|
259
276
|
def find_build_number_in(path = nil)
|
260
277
|
return nil unless File.exist? path
|
278
|
+
|
261
279
|
str = strings(path)
|
262
|
-
lines = str.
|
280
|
+
lines = str.grep(STRINGS_FULL_VERSION_MATCHER)
|
263
281
|
lines.empty? ? nil : lines[0].split('_')[1]
|
264
282
|
end
|
265
283
|
end
|
@@ -347,44 +365,7 @@ module U3d
|
|
347
365
|
private
|
348
366
|
|
349
367
|
def unity_version_info
|
350
|
-
@
|
351
|
-
end
|
352
|
-
|
353
|
-
def string_file_info(info, path)
|
354
|
-
require "Win32API"
|
355
|
-
get_file_version_info_size = Win32API.new('version.dll', 'GetFileVersionInfoSize', 'PP', 'L')
|
356
|
-
get_file_version_info = Win32API.new('version.dll', 'GetFileVersionInfo', 'PIIP', 'I')
|
357
|
-
ver_query_value = Win32API.new('version.dll', 'VerQueryValue', 'PPPP', 'I')
|
358
|
-
rtl_move_memory = Win32API.new('kernel32.dll', 'RtlMoveMemory', 'PLL', 'I')
|
359
|
-
|
360
|
-
file = path.tr("/", "\\")
|
361
|
-
|
362
|
-
buf = [0].pack('L')
|
363
|
-
version_size = get_file_version_info_size.call(file + "\0", buf)
|
364
|
-
raise Exception if version_size.zero? # TODO: use GetLastError
|
365
|
-
|
366
|
-
version_info = 0.chr * version_size
|
367
|
-
version_ok = get_file_version_info.call(file, 0, version_size, version_info)
|
368
|
-
raise Exception if version_ok.zero? # TODO: use GetLastError
|
369
|
-
|
370
|
-
# hardcoding lang codepage
|
371
|
-
struct_path = "\\StringFileInfo\\040904b0\\#{info}"
|
372
|
-
|
373
|
-
addr = [0].pack('L')
|
374
|
-
size = [0].pack('L')
|
375
|
-
query_ok = ver_query_value.call(version_info, struct_path + "\0", addr, size)
|
376
|
-
raise Exception if query_ok.zero?
|
377
|
-
|
378
|
-
raddr = addr.unpack('L')[0]
|
379
|
-
rsize = size.unpack('L')[0]
|
380
|
-
|
381
|
-
info = Array.new(rsize, 0).pack('L*')
|
382
|
-
rtl_move_memory.call(info, raddr, info.length)
|
383
|
-
info.strip
|
384
|
-
rescue StandardError => e
|
385
|
-
UI.verbose("Failure to find '#{info}' under '#{path}': #{e}")
|
386
|
-
UI.verbose(e.backtrace)
|
387
|
-
nil
|
368
|
+
@unity_version_info ||= U3d::Utils.windows_fileversion('Unity Version', @exe_path)
|
388
369
|
end
|
389
370
|
end
|
390
371
|
|
@@ -396,6 +377,7 @@ module U3d
|
|
396
377
|
path = "#{root_path}/Editor/Data/"
|
397
378
|
package = IvyPlaybackEngineUtils.list_module_configs(path).first
|
398
379
|
raise "Couldn't find a module under #{path}" unless package
|
380
|
+
|
399
381
|
IvyPlaybackEngineUtils.unity_version(package)
|
400
382
|
end
|
401
383
|
|
@@ -410,8 +392,8 @@ module U3d
|
|
410
392
|
log_dir = File.expand_path('Unity/Editor/', loc_appdata)
|
411
393
|
UI.important "Log directory (#{log_dir}) does not exist" unless Dir.exist? log_dir
|
412
394
|
@logfile = File.expand_path('Editor.log', log_dir)
|
413
|
-
rescue RuntimeError =>
|
414
|
-
UI.error "Unable to retrieve the editor logfile: #{
|
395
|
+
rescue RuntimeError => e
|
396
|
+
UI.error "Unable to retrieve the editor logfile: #{e}"
|
415
397
|
end
|
416
398
|
end
|
417
399
|
@logfile
|