u3d 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
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