u3d 0.9.3 → 0.9.4

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.
data/Rakefile CHANGED
@@ -22,7 +22,31 @@
22
22
 
23
23
  require "bundler/gem_tasks"
24
24
  require "rspec/core/rake_task"
25
+ require 'rubocop/rake_task'
26
+ # doesn't yet support dot file
27
+ # https://github.com/skywinder/github-changelog-generator/issues/473
28
+ # require 'github_changelog_generator/task'
25
29
 
26
30
  RSpec::Core::RakeTask.new(:spec)
31
+ RuboCop::RakeTask.new
27
32
 
28
- task default: :spec
33
+ task :changelog do
34
+ puts "Updating changelog #{ENV['CHANGELOG_GITHUB_TOKEN']}"
35
+ sh "github_changelog_generator" if ENV['CHANGELOG_GITHUB_TOKEN']
36
+ end
37
+
38
+ task :test_all do
39
+ formatter = "--format progress"
40
+ if ENV["CIRCLECI"]
41
+ Dir.mkdir("/tmp/rspec/")
42
+ formatter += " -r rspec_junit_formatter --format RspecJunitFormatter -o /tmp/rspec/rspec.xml"
43
+ TEST_FILES = `(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)`.tr!("\n", ' ')
44
+ rspec_args = "#{formatter} #{TEST_FILES}"
45
+ else
46
+ formatter += ' --pattern "./spec/**/*_spec.rb"'
47
+ rspec_args = formatter
48
+ end
49
+ sh "rspec #{rspec_args}"
50
+ end
51
+
52
+ task default: %i[rubocop test_all]
Binary file
@@ -5,4 +5,6 @@ REPO_ROOT = File.expand_path(File.join('..', '..'))
5
5
  gem 'u3d', path: REPO_ROOT
6
6
 
7
7
  plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
8
+ # rubocop:disable Eval
8
9
  eval(File.read(plugins_path), binding) if File.exist?(plugins_path)
10
+ # rubocop:enable Eval
@@ -5,4 +5,6 @@ REPO_ROOT = File.expand_path(File.join('..', '..'))
5
5
  gem 'u3d', path: REPO_ROOT
6
6
 
7
7
  plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
8
+ # rubocop:disable Eval
8
9
  eval(File.read(plugins_path), binding) if File.exist?(plugins_path)
10
+ # rubocop:enable Eval
@@ -21,8 +21,10 @@
21
21
  ## --- END LICENSE BLOCK ---
22
22
 
23
23
  require 'u3d/unity_versions'
24
+ require 'u3d/unity_version_definition'
24
25
  require 'u3d/downloader'
25
26
  require 'u3d/installer'
27
+ require 'u3d/unity_project'
26
28
  require 'u3d/cache'
27
29
  require 'u3d/utils'
28
30
  require 'u3d/log_analyzer'
@@ -33,6 +35,7 @@ require 'fileutils'
33
35
 
34
36
  module U3d
35
37
  # API for U3d, redirecting calls to class they concern
38
+ # rubocop:disable ClassLength
36
39
  class Commands
37
40
  class << self
38
41
  def list_installed(options: {})
@@ -49,7 +52,7 @@ module U3d
49
52
  sorted_keys = vcomparators.sort.map { |v| v.version.to_s }
50
53
  sorted_keys.each do |k|
51
54
  u = map[k]
52
- UI.message "%-*s%s" % [30, "Version #{u.version}", " (#{u.path})"]
55
+ UI.message "Version #{u.version.ljust(30)}(#{u.path})"
53
56
  packages = u.packages
54
57
  next unless options[:packages] && packages && !packages.empty?
55
58
  UI.message 'Packages:'
@@ -59,17 +62,9 @@ module U3d
59
62
 
60
63
  def list_available(options: {})
61
64
  ver = options[:unity_version]
62
- os = options[:operating_system]
65
+ os = valid_os_or_current(options[:operating_system])
63
66
  rl = options[:release_level]
64
- if os
65
- os = os.to_sym
66
- oses = U3dCore::Helper.operating_systems
67
- raise "Specified OS (#{os}) isn't valid [#{oses.join(', ')}]" unless oses.include?(os)
68
- else
69
- os = U3dCore::Helper.operating_system
70
- end
71
67
  cache = Cache.new(force_os: os, force_refresh: options[:force])
72
- versions = {}
73
68
 
74
69
  return UI.error "Version #{ver} is not in cache" if ver && cache[os.id2name]['versions'][ver].nil?
75
70
 
@@ -103,93 +98,43 @@ module U3d
103
98
  end
104
99
  end
105
100
 
106
- def download(args: [], options: {})
107
- version = args[0]
108
- UI.user_error!('Please specify a Unity version to download') unless version
109
-
110
- packages = packages_with_unity_first(options)
101
+ def install(args: [], options: {})
102
+ version = specified_or_current_project_version(args[0])
111
103
 
112
104
  os = U3dCore::Helper.operating_system
105
+
106
+ packages = packages_with_unity_first(os, options)
107
+
113
108
  cache = Cache.new(force_os: os)
114
- versions = cache[os.id2name]['versions']
115
- version = interpret_latest(version, versions)
109
+ cache_versions = cache[os.id2name]['versions']
110
+ version = interpret_latest(version, cache_versions)
111
+ unless cache_versions[version]
112
+ UI.error "No version '#{version}' was found in cache. Either it doesn't exist or u3d doesn't know about it yet. Try refreshing with 'u3d available -f'"
113
+ return
114
+ end
116
115
 
116
+ definition = UnityVersionDefinition.new(version, os, cache_versions)
117
117
  unity = check_unity_presence(version: version)
118
- return unless enforce_setup_coherence(packages, options, unity)
119
-
120
- U3d::Globals.use_keychain = true if options[:keychain] && Helper.mac?
118
+ return unless enforce_setup_coherence(packages, options, unity, definition)
121
119
 
122
- unless options[:no_install]
120
+ if options[:install]
121
+ U3d::Globals.use_keychain = true if options[:keychain] && Helper.mac?
123
122
  UI.important 'Root privileges are required'
124
123
  raise 'Could not get administrative privileges' unless U3dCore::CommandExecutor.has_admin_privileges?
125
124
  end
126
125
 
127
- files = []
128
- if os == :linux
129
- UI.important 'Option -a | --all not available for Linux' if options[:all]
130
- UI.important 'Option -p | --packages not available for Linux' if options[:packages]
131
- downloader = Downloader::LinuxDownloader
132
- files << ["Unity #{version}", downloader.download(version, versions), {}]
133
- else
134
- downloader = Downloader::MacDownloader if os == :mac
135
- downloader = Downloader::WindowsDownloader if os == :win
136
- if options[:all]
137
- files = downloader.download_all(version, versions)
138
- else
139
- packages.each do |package|
140
- result = downloader.download_specific(package, version, versions)
141
- files << [package, result[0], result[1]] unless result.nil?
142
- end
143
- end
144
- end
126
+ files = Downloader.fetch_modules(definition, packages: packages, download: options[:download])
145
127
 
146
- return if options[:no_install]
147
- Installer.install_modules(files, version, installation_path: options[:installation_path])
148
- end
149
-
150
- def local_install(args: [], options: {})
151
- UI.user_error!('Please specify a version') if args.empty?
152
- version = args[0]
153
-
154
- packages = packages_with_unity_first(options)
155
-
156
- os = U3dCore::Helper.operating_system
157
-
158
- unity = check_unity_presence(version: version)
159
- return unless enforce_setup_coherence(packages, options, unity)
160
-
161
- U3d::Globals.use_keychain = true if options[:keychain] && Helper.mac?
162
-
163
- UI.important 'Root privileges are required'
164
- raise 'Could not get administrative privileges' unless U3dCore::CommandExecutor.has_admin_privileges?
165
-
166
- files = []
167
- if os == :linux
168
- UI.important 'Option -a | --all not available for Linux' if options[:all]
169
- UI.important 'Option -p | --packages not available for Linux' if options[:packages]
170
- downloader = Downloader::LinuxDownloader
171
- files << ["Unity #{version}", downloader.local_file(version), {}]
172
- else
173
- downloader = Downloader::MacDownloader if os == :mac
174
- downloader = Downloader::WindowsDownloader if os == :win
175
- if options[:all]
176
- files = downloader.all_local_files(version)
177
- else
178
- packages.each do |package|
179
- result = downloader.local_file(package, version)
180
- files << [package, result[0], result[1]] unless result.nil?
181
- end
182
- end
183
- end
184
-
185
- Installer.install_modules(files, version, installation_path: options[:installation_path])
128
+ return unless options[:install]
129
+ Installer.install_modules(files, definition.version, installation_path: options[:installation_path])
186
130
  end
187
131
 
188
132
  def run(options: {}, run_args: [])
189
133
  version = options[:unity_version]
190
134
 
191
135
  runner = Runner.new
192
- pp = runner.find_projectpath_in_args(run_args)
136
+ args_pp = Runner.find_projectpath_in_args(run_args)
137
+ pp = args_pp
193
138
  pp = Dir.pwd unless pp
194
139
  up = UnityProject.new(pp)
195
140
 
@@ -200,17 +145,19 @@ module U3d
200
145
  end
201
146
  end
202
147
 
203
- run_args = ['-projectpath', up.path] if run_args.empty? && up.exist?
148
+ if up.exist? && args_pp.nil?
149
+ extra_run_args = ['-projectpath', up.path]
150
+ run_args = [extra_run_args, run_args].flatten
151
+ end
204
152
 
205
- # we could
206
- # * support matching 5.3.6p3 if passed 5.3.6
153
+ # we could support matching 5.3.6p3 if passed 5.3.6
207
154
  unity = Installer.create.installed.find { |u| u.version == version }
208
155
  UI.user_error! "Unity version '#{version}' not found" unless unity
209
156
  runner.run(unity, run_args, raw_logs: options[:raw_logs])
210
157
  end
211
158
 
212
159
  def credentials_actions
213
- %w(add remove check)
160
+ %w[add remove check]
214
161
  end
215
162
 
216
163
  def credentials(args: [], _options: {})
@@ -226,20 +173,7 @@ module U3d
226
173
  U3dCore::Globals.use_keychain = true
227
174
  U3dCore::Credentials.new(user: ENV['USER']).forget_credentials(force: true)
228
175
  else
229
- U3dCore::Globals.use_keychain = true
230
- credentials = U3dCore::Credentials.new(user: ENV['USER'])
231
- U3dCore::Globals.with_do_not_login(true) do
232
- if credentials.password.to_s.empty?
233
- UI.message "No credentials stored"
234
- else
235
- if U3dCore::CommandExecutor.has_admin_privileges?
236
- UI.success "Stored credentials are valid"
237
- else
238
- UI.error "Stored credentials are not valid"
239
- end
240
- end
241
- end
242
- # FIXME: return value
176
+ credentials_check
243
177
  end
244
178
  end
245
179
 
@@ -254,7 +188,7 @@ module U3d
254
188
  end
255
189
 
256
190
  def release_levels
257
- [:stable, :beta, :patch]
191
+ %i[stable beta patch]
258
192
  end
259
193
 
260
194
  def release_letter_mapping
@@ -268,6 +202,45 @@ module U3d
268
202
 
269
203
  private
270
204
 
205
+ def specified_or_current_project_version(version)
206
+ unless version # no version specified, use the one from the current unity project if any
207
+ UI.message "No unity version specified. If the current directory is a Unity project, we try to install the one it requires"
208
+ up = UnityProject.new(Dir.pwd)
209
+ version = up.editor_version if up.exist?
210
+ end
211
+ UI.user_error!('Please specify a Unity version to download') unless version
212
+ version
213
+ end
214
+
215
+ def credentials_check
216
+ U3dCore::Globals.use_keychain = true
217
+ credentials = U3dCore::Credentials.new(user: ENV['USER'])
218
+ U3dCore::Globals.with_do_not_login(true) do
219
+ if credentials.password.to_s.empty?
220
+ UI.message "No credentials stored"
221
+ elsif U3dCore::CommandExecutor.has_admin_privileges?
222
+ UI.success "Stored credentials are valid"
223
+ else
224
+ UI.error "Stored credentials are not valid"
225
+ end
226
+ end
227
+ # FIXME: return value
228
+ end
229
+
230
+ # if the specified string representatio of `os` is non nil
231
+ # convert the it to a symbol and checks it against the valid ones
232
+ # or return the current OS
233
+ def valid_os_or_current(os)
234
+ if os
235
+ os = os.to_sym
236
+ oses = U3dCore::Helper.operating_systems
237
+ raise "Specified OS (#{os}) isn't valid [#{oses.join(', ')}]" unless oses.include?(os)
238
+ else
239
+ os = U3dCore::Helper.operating_system
240
+ end
241
+ os
242
+ end
243
+
271
244
  def interpret_latest(version, versions)
272
245
  return version unless release_letter_mapping.keys.include? version.to_sym
273
246
 
@@ -282,7 +255,11 @@ module U3d
282
255
  iversion
283
256
  end
284
257
 
285
- def packages_with_unity_first(options)
258
+ def packages_with_unity_first(os, options)
259
+ if os == :linux
260
+ UI.important 'Option -a | --all not available for Linux' if options[:all]
261
+ UI.important 'Option -p | --packages not available for Linux' if options[:packages]
262
+ end
286
263
  temp = options[:packages] || ['Unity']
287
264
  temp.insert(0, 'Unity') if temp.delete('Unity')
288
265
  temp
@@ -300,23 +277,28 @@ module U3d
300
277
  nil
301
278
  end
302
279
 
303
- def enforce_setup_coherence(packages, options, unity)
280
+ def enforce_setup_coherence(packages, options, unity, definition)
281
+ packages = definition.available_packages if options[:all]
304
282
  if unity
305
283
  UI.important "Unity #{unity.version} is already installed"
306
- return false if Helper.linux?
284
+ # Not needed since Linux custom u3d files contain only one entry wich is Unity
285
+ # return false if definition.os == :linux
307
286
  if packages.include?('Unity')
308
287
  UI.important 'Ignoring Unity module, it is already installed'
309
288
  packages.delete('Unity')
310
- options[:installation_path] ||= unity.path if Helper.windows?
289
+
290
+ # FIXME: Move me to the WindowsInstaller
291
+ options[:installation_path] ||= unity.path if definition.os == :win
311
292
  end
312
293
  if unity.packages
313
294
  unity.packages.each do |pack|
314
295
  UI.important "Ignoring #{pack} module, it is already installed" if packages.delete(pack)
315
296
  end
316
297
  end
298
+ return false if packages.empty?
317
299
  else
318
300
  unless packages.include?('Unity')
319
- UI.error "Please install Unity #{unity.version} before any of its packages"
301
+ UI.error 'Please install Unity before any of its packages'
320
302
  return false
321
303
  end
322
304
  end
@@ -324,4 +306,5 @@ module U3d
324
306
  end
325
307
  end
326
308
  end
309
+ # rubocop:enable ClassLength
327
310
  end
@@ -28,6 +28,7 @@ HighLine.track_eof = false
28
28
 
29
29
  module U3d
30
30
  # CLI using commander gem for u3d
31
+ # rubocop:disable ClassLength
31
32
  class CommandsGenerator
32
33
  include Commander::Methods
33
34
  UI = U3dCore::UI
@@ -71,7 +72,7 @@ module U3d
71
72
 
72
73
  c.syntax = 'u3d run [-u | --unity_version <version>] [-r | --raw_logs] [ -- <run_args>]'
73
74
  c.description = 'Run unity, and parses its output through u3d\'s log prettifier'
74
- c.option '-u', '--unity_version STRING', String, 'Version of Unity to run with'
75
+ 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)'
75
76
  c.option '-r', '--raw_logs', 'Raw Unity output, not filtered by u3d\'s log prettifier'
76
77
  c.action do |args, options|
77
78
  UI.user_error! "Run doesn't take arguments. Did you forget '--' or did you mistake your command? (#{args})" if args.count > 0
@@ -95,7 +96,7 @@ module U3d
95
96
  c.syntax = 'u3d available [-r | --release_level <level>] [-o | --operating_system <OS>] [-u | --unity_version <version>] [-p | --packages] [-f | --force]'
96
97
  levels = Commands.release_levels
97
98
  c.option '-f', '--force', 'Force refresh list of available versions'
98
- c.option '-r', '--release_level STRING', String, "Checks for availability on specific release level [#{levels.join(',')}]"
99
+ c.option '-r', '--release_level STRING', String, "Checks for availability on specific release level [#{levels.join(', ')}]"
99
100
  c.option '-o', '--operating_system STRING', String, "Checks for availability on specific OS [#{oses.join(', ')}]"
100
101
  c.option '-u', '--unity_version STRING', String, 'Checks if specified version is available'
101
102
  c.option '-p', '--packages', 'Lists available packages as well'
@@ -111,31 +112,29 @@ module U3d
111
112
  end
112
113
 
113
114
  command :install do |c|
114
- c.syntax = 'u3d install <version> [ [-p | --packages <package> ...] | [-a | --all] ] [ [-n | --no_install] [-i | --installation_path <path>] ]'
115
- c.description = "Download (and install) Unity3D packages."
116
- c.option '-p', '--packages PACKAGES', Array, 'Specifies which packages to download. Overriden by --all'
117
- c.option '-i', '--installation_path PATH', String, 'Specifies where package(s) will be installed. Overriden by --no_install'
118
- c.option '-a', '--all', 'Download all available packages'
119
- c.option '-n', '--no_install', 'No installation after download success'
115
+ c.syntax = 'u3d install [<version>] [ [-p | --packages <package> ...] | [-a | --all] ] [ [-n | --no_install] [-i | --installation_path <path>] ]'
116
+ c.summary = "Download (and/or) install Unity3D packages."
117
+ c.description = %(
118
+ #{c.summary}
119
+
120
+ This command allows you to either:
121
+ * download and install packages
122
+ * download packages but not install them
123
+ * install already downloaded packages
124
+ )
125
+ c.option '--[no-]download', 'Perform or not downloading before installation. Downloads by default'
126
+ c.option '--[no-]install', 'Perform or not installation after downloading. Installs by default'
127
+ c.option '-p', '--packages PACKAGES', Array, 'Specifies which packages to download/install. Overriden by --all'
128
+ c.option '-a', '--all', 'Download all available packages. Overrides -p'
129
+ c.option '-X', '--installation_path PATH', String, 'Specifies where package(s) will be downloaded/installed. Conflicts with --no-install'
120
130
  c.option '-k', '--keychain', 'Gain privileges right through the keychain. [OSX only]'
121
131
  c.example 'Download and install Unity, its Documentation and the Android build support and install them for version 5.1.2f1', 'u3d install 5.1.2f1 -p Unity,Documentation,Android'
122
- c.example "The 'version' argument can be a specific version number, such as 5.6.1f1, or an alias in [#{Commands.release_letter_mapping.keys.join(',')}]", 'u3d install latest'
132
+ c.example "The 'version' argument can be a specific version number, such as 5.6.1f1, or an alias in [#{Commands.release_letter_mapping.keys.join(', ')}]. If not specified, u3d will download the unity version for the current project", 'u3d install latest'
123
133
  c.action do |args, options|
124
134
  options.default all: false
125
- options.default no_install: false
126
- Commands.download(args: args, options: convert_options(options))
127
- end
128
- end
129
-
130
- command :local_install do |c|
131
- c.syntax = 'u3d local_install <version> [ [-p | --packages <package> ...] | [-a | --all] ] [-i | --installation_path <path>]'
132
- c.description = 'Install downloaded version of Unity3d'
133
- c.option '-p', '--packages PACKAGES', Array, 'Specifies which packages to install. Overriden by --all'
134
- c.option '-i', '--installation_path PATH', String, 'Specifies where package(s) will be installed.'
135
- c.option '-a', '--all', 'Install all downloaded packages'
136
- c.option '-k', '--keychain', 'Gain privileges right through the keychain. [OSX only]'
137
- c.action do |args, options|
138
- Commands.local_install(args: args, options: convert_options(options))
135
+ options.default install: true
136
+ options.default download: true
137
+ Commands.install(args: args, options: convert_options(options))
139
138
  end
140
139
  end
141
140
 
@@ -160,4 +159,5 @@ module U3d
160
159
  run!
161
160
  end
162
161
  end
162
+ # rubocop:enable ClassLength
163
163
  end
@@ -0,0 +1,74 @@
1
+ ## --- BEGIN LICENSE BLOCK ---
2
+ # Copyright (c) 2016-present WeWantToKnow AS
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ # of this software and associated documentation files (the "Software"), to deal
6
+ # in the Software without restriction, including without limitation the rights
7
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ # copies of the Software, and to permit persons to whom the Software is
9
+ # furnished to do so, subject to the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be included in all
12
+ # copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ # SOFTWARE.
21
+ ## --- END LICENSE BLOCK ---
22
+
23
+ module U3d
24
+ class DownloadValidator
25
+ def hash_validation(expected: nil, actual: nil)
26
+ if expected
27
+ if expected != actual
28
+ UI.verbose "Expected hash is #{expected}, file hash is #{actual}"
29
+ UI.important 'File looks corrupted (wrong hash)'
30
+ return false
31
+ end
32
+ else
33
+ UI.verbose 'No hash validation available. File is assumed correct but may not be.'
34
+ end
35
+ true
36
+ end
37
+
38
+ def size_validation(expected: nil, actual: nil)
39
+ if expected
40
+ if expected != actual
41
+ UI.verbose "Expected size is #{expected}, file size is #{actual}"
42
+ UI.important 'File looks corrupted (wrong size)'
43
+ return false
44
+ end
45
+ else
46
+ UI.verbose 'No size validation available. File is assumed correct but may not be.'
47
+ end
48
+ true
49
+ end
50
+ end
51
+
52
+ class LinuxValidator < DownloadValidator
53
+ def validate(package, file, definition)
54
+ return size_validation(expected: definition[package]['size'], actual: File.size(file)) if definition.ini && definition[package]['size']
55
+ UI.important "No file validation available, #{file} is assumed to be correct"
56
+ true
57
+ end
58
+ end
59
+
60
+ class MacValidator < DownloadValidator
61
+ def validate(package, file, definition)
62
+ size_validation(expected: definition[package]['size'], actual: File.size(file)) &&
63
+ hash_validation(expected: definition[package]['md5'], actual: Utils.hashfile(file))
64
+ end
65
+ end
66
+
67
+ class WindowsValidator < DownloadValidator
68
+ def validate(package, file, definition)
69
+ rounded_size = (File.size(file).to_f / 1024).floor
70
+ size_validation(expected: definition[package]['size'], actual: rounded_size) &&
71
+ hash_validation(expected: definition[package]['md5'], actual: Utils.hashfile(file))
72
+ end
73
+ end
74
+ end