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.
Files changed (61) hide show
  1. checksums.yaml +5 -5
  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 +62 -11
  8. data/Gemfile.lock +147 -87
  9. data/Rakefile +12 -7
  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 +14 -9
  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 -8
  29. data/lib/u3d/installation.rb +31 -49
  30. data/lib/u3d/installer.rb +44 -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 +82 -15
  40. data/lib/u3d/version.rb +8 -6
  41. data/lib/u3d.rb +2 -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 -30
data/lib/u3d/installer.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
  #
@@ -30,13 +32,13 @@ require 'pathname'
30
32
  require 'zip'
31
33
 
32
34
  module U3d
33
- DEFAULT_LINUX_INSTALL = '/opt/'.freeze
34
- DEFAULT_MAC_INSTALL = '/'.freeze
35
- DEFAULT_WINDOWS_INSTALL = 'C:/Program Files/'.freeze
36
- UNITY_DIR = "Unity_%<version>s".freeze
37
- UNITY_DIR_LONG = "Unity_%<version>s_%<build_number>s".freeze
38
- UNITY_DIR_LINUX = "unity-editor-%<version>s".freeze
39
- UNITY_DIR_LINUX_LONG = "unity-editor-%<version>s_%<build_number>s".freeze
35
+ DEFAULT_LINUX_INSTALL = '/opt/'
36
+ DEFAULT_MAC_INSTALL = '/'
37
+ DEFAULT_WINDOWS_INSTALL = 'C:/Program Files/'
38
+ UNITY_DIR = "Unity_%<version>s"
39
+ UNITY_DIR_LONG = "Unity_%<version>s_%<build_number>s"
40
+ UNITY_DIR_LINUX = "unity-editor-%<version>s"
41
+ UNITY_DIR_LINUX_LONG = "unity-editor-%<version>s_%<build_number>s"
40
42
 
41
43
  class Installer
42
44
  def self.create
@@ -57,7 +59,7 @@ module U3d
57
59
  installer = Installer.create
58
60
  files.each do |name, file, info|
59
61
  UI.header "Installing #{info.name} (#{name})"
60
- UI.message 'Installing with ' + file
62
+ UI.message "Installing with #{file}"
61
63
  installer.install(file, version, installation_path: installation_path, info: info)
62
64
  end
63
65
  end
@@ -71,20 +73,24 @@ module U3d
71
73
  class BaseInstaller
72
74
  def sanitize_installs
73
75
  return unless UI.interactive? || Helper.test?
76
+
74
77
  unclean = []
75
78
  installed.each { |unity| unclean << unity unless unity.clean_install? }
76
79
  return if unclean.empty?
80
+
77
81
  UI.important("u3d can optionally standardize the existing Unity installation names and locations.")
78
82
  UI.important("Check the documentation for more information:")
79
83
  UI.important("** https://github.com/DragonBox/u3d/blob/master/README.md#default-installation-paths **")
80
84
  unclean.each { |unity| sanitize_install(unity, dry_run: true) }
81
85
  return unless UI.confirm("#{unclean.count} Unity installation(s) will be moved. Proceed??")
86
+
82
87
  unclean.each { |unity| sanitize_install(unity) }
83
88
  end
84
89
 
85
90
  def installed_sorted_by_versions
86
91
  list = installed
87
92
  return [] if list.empty?
93
+
88
94
  list.sort { |a, b| UnityVersionComparator.new(a.version) <=> UnityVersionComparator.new(b.version) }
89
95
  end
90
96
 
@@ -123,7 +129,7 @@ module U3d
123
129
  end
124
130
  end
125
131
 
126
- if info && info.rename_from && info.rename_to
132
+ if info&.rename_from && info&.rename_to
127
133
  rename_from = info.rename_from.gsub(/{UNITY_PATH}/, unity.root_path)
128
134
  rename_to = info.rename_to.gsub(/{UNITY_PATH}/, unity.root_path)
129
135
  Utils.ensure_dir(rename_to)
@@ -131,7 +137,7 @@ module U3d
131
137
  if File.file? rename_from
132
138
  FileUtils.mv(rename_from, rename_to)
133
139
  else
134
- Dir.glob(rename_from + '/*').each { |path| FileUtils.mv(path, rename_to) }
140
+ Dir.glob("#{rename_from}/*").each { |path| FileUtils.mv(path, rename_to) }
135
141
  end
136
142
  end
137
143
 
@@ -139,7 +145,7 @@ module U3d
139
145
  end
140
146
 
141
147
  def package_destination(info, unity_root_path)
142
- if info && info.destination
148
+ if info&.destination
143
149
  info.destination.gsub(/{UNITY_PATH}/, unity_root_path)
144
150
  else
145
151
  unity_root_path
@@ -151,14 +157,15 @@ module U3d
151
157
  # Returns an array of ruby style paths
152
158
  def extra_installation_paths
153
159
  return [] if ENV['U3D_EXTRA_PATHS'].nil?
160
+
154
161
  ENV['U3D_EXTRA_PATHS'].strip.split(File::PATH_SEPARATOR).map { |p| File.expand_path p }
155
162
  end
156
163
 
157
- def find_installations_with_path(default_root_path: '', postfix: [])
164
+ def find_installations_with_path(default_root_path: '', postfix: [], &block)
158
165
  ([default_root_path] | extra_installation_paths).map do |path|
159
166
  UI.verbose "Looking for installed Unity version under #{path}"
160
167
  pattern = File.join([path] + postfix)
161
- Dir.glob(pattern).map { |found_path| yield found_path }
168
+ Dir.glob(pattern).map(&block)
162
169
  end.flatten
163
170
  end
164
171
  end
@@ -189,15 +196,16 @@ module U3d
189
196
  end
190
197
 
191
198
  def install(file_path, version, installation_path: nil, info: nil)
192
- # rubocop:enable UnusedMethodArgument
193
199
  extension = File.extname(file_path)
194
200
  raise "Installation of #{extension} files is not supported on Mac" unless %w[.zip .po .pkg .dmg].include? extension
201
+
195
202
  path = installation_path || DEFAULT_MAC_INSTALL
196
- if extension == '.po'
203
+ case extension
204
+ when '.po'
197
205
  install_po(file_path, version, info: info)
198
- elsif extension == '.zip'
206
+ when '.zip'
199
207
  install_zip(file_path, version, info: info)
200
- elsif extension == '.dmg'
208
+ when '.dmg'
201
209
  UI.important "Skipping installation of #{file_path} for now"
202
210
  else
203
211
  install_pkg(file_path, version: version, target_path: path)
@@ -278,7 +286,7 @@ module U3d
278
286
  end
279
287
  end
280
288
 
281
- # rubocop:disable ClassLength
289
+ # rubocop:disable Metrics/ClassLength
282
290
  class LinuxInstaller < BaseInstaller
283
291
  def sanitize_install(unity, long: false, dry_run: false)
284
292
  source_path = File.expand_path(unity.root_path)
@@ -296,26 +304,26 @@ module U3d
296
304
  paths.map { |path| LinuxInstallation.new(root_path: path) }
297
305
  end
298
306
 
299
- # rubocop:disable PerceivedComplexity
300
307
  def install(file_path, version, installation_path: nil, info: nil)
301
- # rubocop:enable UnusedMethodArgument, PerceivedComplexity
302
308
  extension = File.extname(file_path)
303
309
 
304
310
  raise "Installation of #{extension} files is not supported on Linux" unless ['.zip', '.po', '.sh', '.xz', '.pkg'].include? extension
305
- if extension == '.sh'
311
+
312
+ case extension
313
+ when '.sh'
306
314
  path = installation_path || DEFAULT_LINUX_INSTALL
307
315
  install_sh(file_path, installation_path: path)
308
- elsif extension == '.xz'
316
+ when '.xz'
309
317
  new_path = File.join(DEFAULT_LINUX_INSTALL, format(UNITY_DIR_LINUX, version: version))
310
318
  path = installation_path || new_path
311
319
  install_xz(file_path, installation_path: path)
312
- elsif extension == '.pkg'
320
+ when '.pkg'
313
321
  new_path = File.join(DEFAULT_LINUX_INSTALL, format(UNITY_DIR_LINUX, version: version))
314
322
  path = installation_path || new_path
315
323
  install_pkg(file_path, installation_path: path)
316
- elsif extension == '.po'
324
+ when '.po'
317
325
  install_po(file_path, version, info: info)
318
- elsif extension == '.zip'
326
+ when '.zip'
319
327
  install_zip(file_path, version, info: info)
320
328
  end
321
329
 
@@ -399,6 +407,7 @@ module U3d
399
407
 
400
408
  def pkg_install_path(unity_root_path, pinfo_path)
401
409
  raise "PackageInfo not found under #{pinfo_path}" unless File.exist? pinfo_path
410
+
402
411
  pinfo = File.read(pinfo_path)
403
412
  require 'rexml/document'
404
413
  d = REXML::Document.new(pinfo)
@@ -414,6 +423,7 @@ module U3d
414
423
  else
415
424
  install_location = d.root.attributes['install-location']
416
425
  raise "Not sure how to install this module with identifier #{identifier} install-location: #{install_location}" unless install_location.start_with? '/Applications/Unity/'
426
+
417
427
  install_location.gsub(%(\/Applications\/Unity), "#{unity_root_path}/Editor/Data")
418
428
  end
419
429
  end
@@ -442,7 +452,7 @@ module U3d
442
452
  paths
443
453
  end
444
454
  end
445
- # rubocop:enable ClassLength
455
+ # rubocop:enable Metrics/ClassLength
446
456
 
447
457
  class WindowsInstaller < BaseInstaller
448
458
  def sanitize_install(unity, long: false, dry_run: false)
@@ -470,10 +480,12 @@ module U3d
470
480
  def install(file_path, version, installation_path: nil, info: nil)
471
481
  extension = File.extname(file_path)
472
482
  raise "Installation of #{extension} files is not supported on Windows" unless %w[.po .zip .exe .msi].include? extension
483
+
473
484
  path = installation_path || File.join(DEFAULT_WINDOWS_INSTALL, format(UNITY_DIR, version: version))
474
- if extension == '.po'
485
+ case extension
486
+ when '.po'
475
487
  install_po(file_path, version, info: info)
476
- elsif extension == '.zip'
488
+ when '.zip'
477
489
  install_zip(file_path, version, info: info)
478
490
  else
479
491
  install_exe(file_path, installation_path: path, info: info)
@@ -489,14 +501,14 @@ module U3d
489
501
  if info.command
490
502
  command = info.command
491
503
  if /msiexec/ =~ command
492
- command.sub!(/{FILENAME}/, '"' + U3dCore::Helper.windows_path(file_path) + '"')
504
+ command.sub!(/{FILENAME}/, "\"#{U3dCore::Helper.windows_path(file_path)}\"")
493
505
  else
494
506
  command.sub!(/{FILENAME}/, file_path.argescape)
495
507
  end
496
508
  command.sub!(/{INSTDIR}/, final_path)
497
509
  command.sub!(/{DOCDIR}/, final_path)
498
510
  command.sub!(/{MODULEDIR}/, final_path)
499
- command.sub!(%r{\/D=}, '/S /D=') unless %r{\/S} =~ command
511
+ command.sub!(%r{/D=}, '/S /D=') unless %r{/S} =~ command
500
512
  end
501
513
  command ||= file_path.argescape
502
514
  U3dCore::CommandExecutor.execute(command: command, admin: true)
@@ -572,9 +584,8 @@ module U3d
572
584
  raise 'Cannot install dependencies on your Linux distribution'
573
585
  end
574
586
 
575
- if UI.interactive?
576
- return unless UI.confirm "Install dependencies? (#{DEPENDENCIES.length} dependency(ies) to install)"
577
- end
587
+ return if UI.interactive? && !(UI.confirm "Install dependencies? (#{DEPENDENCIES.length} dependency(ies) to install)")
588
+
578
589
  U3dCore::CommandExecutor.execute(command: "#{prefix} #{DEPENDENCIES.join(' ')}", admin: true)
579
590
  end
580
591
  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
  #
@@ -25,9 +27,9 @@ require 'u3d/failure_reporter'
25
27
 
26
28
  module U3d
27
29
  # Analyzes log by filtering output along a set of rules
28
- # rubocop:disable ClassLength, PerceivedComplexity, BlockNesting
30
+ # rubocop:disable Metrics/ClassLength, Metrics/PerceivedComplexity, Metrics/BlockNesting
29
31
  class LogAnalyzer
30
- RULES_PATH = File.expand_path('../../../config/log_rules.json', __FILE__)
32
+ RULES_PATH = File.expand_path('../../config/log_rules.json', __dir__)
31
33
  MEMORY_SIZE = 10
32
34
 
33
35
  def initialize
@@ -55,6 +57,7 @@ module U3d
55
57
  # Phase parsing
56
58
  next unless phase['active']
57
59
  next if phase['phase_start_pattern'].nil?
60
+
58
61
  phase['phase_start_pattern'] = Regexp.new phase['phase_start_pattern']
59
62
  phase['phase_end_pattern'] = Regexp.new phase['phase_end_pattern'] if phase['phase_end_pattern']
60
63
  phase.delete('comment')
@@ -79,6 +82,7 @@ module U3d
79
82
  @phases.each do |name, phase|
80
83
  next if name == @active_phase
81
84
  next unless line =~ phase['phase_start_pattern']
85
+
82
86
  finish_phase if @active_phase
83
87
  @active_phase = name
84
88
  UI.verbose("--- Beginning #{name} phase ---")
@@ -116,12 +120,10 @@ module U3d
116
120
  # It's not the end of the rules, should the line be stored?
117
121
  elsif rule['store_lines']
118
122
  match = false
119
- if rule['ignore_lines']
120
- rule['ignore_lines'].each do |pat|
121
- if line =~ pat
122
- match = true
123
- break
124
- end
123
+ rule['ignore_lines']&.each do |pat|
124
+ if line =~ pat
125
+ match = true
126
+ break
125
127
  end
126
128
  end
127
129
  @rule_lines_buffer << line.chomp unless match
@@ -133,6 +135,7 @@ module U3d
133
135
  ruleset.each do |rn, r|
134
136
  pattern = r['start_pattern']
135
137
  next unless line =~ pattern
138
+
136
139
  @active_rule = rn if r['end_pattern']
137
140
  match = line.match(pattern)
138
141
  @context = match.names.map(&:to_sym).zip(match.captures).to_h
@@ -145,10 +148,12 @@ module U3d
145
148
  match = false
146
149
  r['fetch_first_line_not_matching'].each do |pat|
147
150
  next unless l =~ pat
151
+
148
152
  match = true
149
153
  break
150
154
  end
151
155
  next if match
156
+
152
157
  fetched_line = l
153
158
  break
154
159
  end
@@ -196,7 +201,7 @@ module U3d
196
201
  if @active_rule
197
202
  # Active rule should be finished
198
203
  # If it is still active during phase change, it means that something went wrong
199
- context = @lines_memory.map { |l| "> #{l}" }.join('')
204
+ context = @lines_memory.map { |l| "> #{l}" }.join
200
205
  UI.error("[#{@active_phase}] Could not finish active rule '#{@active_rule}'. Aborting it. Context:\n#{context}")
201
206
 
202
207
  U3d::FailureReporter.report(
@@ -237,26 +242,25 @@ module U3d
237
242
  message
238
243
  end
239
244
 
240
- def parse_rule(r)
241
- return false unless r['active']
242
- return false if r['start_pattern'].nil?
243
- r['start_pattern'] = Regexp.new r['start_pattern']
244
- r['end_pattern'] = Regexp.new r['end_pattern'] if r['end_pattern']
245
- if r['fetch_line_at_index']
246
- r.delete('fetch_line_at_index') if r['fetch_line_at_index'] >= MEMORY_SIZE
247
- r.delete('fetch_line_at_index') if r['fetch_line_at_index'] <= 0
248
- elsif r['fetch_first_line_not_matching']
249
- r['fetch_first_line_not_matching'].map! { |pat| Regexp.new pat }
250
- end
251
- if r['fetch_line_at_index'] || r['fetch_first_line_not_matching']
252
- r['fetched_line_pattern'] = Regexp.new r['fetched_line_pattern'] if r['fetched_line_pattern']
245
+ def parse_rule(rule)
246
+ return false unless rule['active']
247
+ return false if rule['start_pattern'].nil?
248
+
249
+ rule['start_pattern'] = Regexp.new rule['start_pattern']
250
+ rule['end_pattern'] = Regexp.new rule['end_pattern'] if rule['end_pattern']
251
+ if rule['fetch_line_at_index']
252
+ rule.delete('fetch_line_at_index') if rule['fetch_line_at_index'] >= MEMORY_SIZE
253
+ rule.delete('fetch_line_at_index') if rule['fetch_line_at_index'] <= 0
254
+ elsif rule['fetch_first_line_not_matching']
255
+ rule['fetch_first_line_not_matching'].map! { |pat| Regexp.new pat }
253
256
  end
254
- r['type'] = 'important' if r['type'] == 'warning'
255
- r['type'] = 'message' if r['type'] && r['type'] != 'error' && r['type'] != 'important' && r['type'] != 'success'
256
- r['type'] ||= 'message'
257
- r['ignore_lines'].map! { |pat| Regexp.new pat } if r['ignore_lines']
257
+ rule['fetched_line_pattern'] = Regexp.new rule['fetched_line_pattern'] if (rule['fetch_line_at_index'] || rule['fetch_first_line_not_matching']) && (rule['fetched_line_pattern'])
258
+ rule['type'] = 'important' if rule['type'] == 'warning'
259
+ rule['type'] = 'message' if rule['type'] && rule['type'] != 'error' && rule['type'] != 'important' && rule['type'] != 'success'
260
+ rule['type'] ||= 'message'
261
+ rule['ignore_lines']&.map! { |pat| Regexp.new pat }
258
262
  true
259
263
  end
260
264
  end
261
- # rubocop:enable ClassLength, PerceivedComplexity, BlockNesting
265
+ # rubocop:enable Metrics/ClassLength, Metrics/PerceivedComplexity, Metrics/BlockNesting
262
266
  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
  #
@@ -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
  #
@@ -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
  #
@@ -46,9 +48,10 @@ module U3d
46
48
  require 'yaml'
47
49
  project_version = File.join(project_settings_path, 'ProjectVersion.txt')
48
50
  return nil unless File.exist? project_version
51
+
49
52
  yaml = YAML.safe_load(File.read(project_version))
50
53
  version = yaml['m_EditorVersion']
51
- version.gsub!(/(\d+\.\d+\.\d+)(?:x)?(\w\d+)(?:Linux)?/, '\1\2') if Helper.linux?
54
+ version = version.gsub(/(\d+\.\d+\.\d+)(?:x)?(\w\d+)(?:Linux)?/, '\1\2') if Helper.linux?
52
55
  version
53
56
  end
54
57
  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
  #
@@ -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