u3d 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,167 @@
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
+ require 'u3d/utils'
24
+
25
+ module U3d
26
+ UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/
27
+ UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/
28
+
29
+ class Installation
30
+ def self.create(path: nil)
31
+ if Helper.mac?
32
+ MacInstallation.new path
33
+ elsif Helper.linux?
34
+ LinuxInstallation.new path
35
+ else
36
+ WindowsInstallation.new path
37
+ end
38
+ end
39
+ end
40
+
41
+ class MacInstallation < Installation
42
+ attr_reader :path
43
+
44
+ require 'plist'
45
+
46
+ def initialize(path: nil)
47
+ @path = path
48
+ end
49
+
50
+ def version
51
+ plist['CFBundleVersion']
52
+ end
53
+
54
+ def default_log_file
55
+ "#{ENV['HOME']}/Library/Logs/Unity/Editor.log"
56
+ end
57
+
58
+ def exe_path
59
+ "#{path}/Contents/MacOS/Unity"
60
+ end
61
+
62
+ def packages
63
+ if Utils.parse_unity_version(version)[0].to_i <= 4
64
+ # Unity < 5 doesn't have packages
65
+ return []
66
+ end
67
+ fpath = File.expand_path('../PlaybackEngines', path)
68
+ return [] unless Dir.exist? fpath # install without package
69
+ Dir.entries(fpath).select { |e| File.directory?(File.join(fpath, e)) && !(e == '.' || e == '..') }
70
+ end
71
+
72
+ def clean_install?
73
+ path =~ UNITY_DIR_CHECK
74
+ end
75
+
76
+ private
77
+
78
+ def plist
79
+ @plist ||= Plist.parse_xml("#{@path}/Contents/Info.plist")
80
+ end
81
+ end
82
+
83
+ class LinuxInstallation < Installation
84
+ attr_reader :path
85
+
86
+ def initialize(path: nil)
87
+ @path = path
88
+ end
89
+
90
+ def version
91
+ # I don't find an easy way to extract the version on Linux
92
+ require 'rexml/document'
93
+ fpath = "#{path}/Editor/Data/PlaybackEngines/LinuxStandaloneSupport/ivy.xml"
94
+ raise "Couldn't find file #{fpath}" unless File.exist? fpath
95
+ doc = REXML::Document.new(File.read(fpath))
96
+ version = REXML::XPath.first(doc, 'ivy-module/info/@e:unityVersion').value
97
+ if (m = version.match(/^(.*)x(.*)Linux$/))
98
+ version = "#{m[1]}#{m[2]}"
99
+ end
100
+ version
101
+ end
102
+
103
+ def default_log_file
104
+ "#{ENV['HOME']}/.config/unity3d/Editor.log"
105
+ end
106
+
107
+ def exe_path
108
+ "#{path}/Editor/Unity"
109
+ end
110
+
111
+ def packages
112
+ false
113
+ end
114
+
115
+ def clean_install?
116
+ path =~ UNITY_DIR_CHECK_LINUX
117
+ end
118
+ end
119
+
120
+ class WindowsInstallation < Installation
121
+ attr_reader :path
122
+
123
+ def initialize(path: nil)
124
+ @path = path
125
+ end
126
+
127
+ def version
128
+ require 'rexml/document'
129
+ fpath = "#{path}/Editor/Data/PlaybackEngines/windowsstandalonesupport/ivy.xml"
130
+ raise "Couldn't find file #{fpath}" unless File.exist? fpath
131
+ doc = REXML::Document.new(File.read(fpath))
132
+ version = REXML::XPath.first(doc, 'ivy-module/info/@e:unityVersion').value
133
+
134
+ version
135
+ end
136
+
137
+ def default_log_file
138
+ if @logfile.nil?
139
+ begin
140
+ loc_appdata = Utils.windows_local_appdata
141
+ log_dir = File.expand_path('Unity/Editor/', loc_appdata)
142
+ UI.important "Log directory (#{log_dir}) does not exist" unless Dir.exist? log_dir
143
+ @logfile = File.expand_path('Editor.log', log_dir)
144
+ rescue RuntimeError => ex
145
+ UI.error "Unable to retrieve the editor logfile: #{ex}"
146
+ end
147
+ end
148
+ @logfile
149
+ end
150
+
151
+ def exe_path
152
+ File.join(@path, 'Editor', 'Unity.exe')
153
+ end
154
+
155
+ def packages
156
+ # Unity prior to Unity5 did not have package
157
+ return [] if Utils.parse_unity_version(version)[0].to_i <= 4
158
+ fpath = "#{path}/Editor/Data/PlaybackEngines/"
159
+ return [] unless Dir.exist? fpath # install without package
160
+ Dir.entries(fpath).select { |e| File.directory?(File.join(fpath, e)) && !(e == '.' || e == '..') }
161
+ end
162
+
163
+ def clean_install?
164
+ path =~ UNITY_DIR_CHECK
165
+ end
166
+ end
167
+ end
@@ -21,157 +21,16 @@
21
21
  ## --- END LICENSE BLOCK ---
22
22
 
23
23
  require 'u3d/utils'
24
+ require 'u3d/installation'
24
25
  require 'fileutils'
25
26
  require 'file-tail'
26
27
 
27
- # Mac specific only right now
28
28
  module U3d
29
29
  DEFAULT_LINUX_INSTALL = '/opt/'.freeze
30
30
  DEFAULT_MAC_INSTALL = '/'.freeze
31
31
  DEFAULT_WINDOWS_INSTALL = 'C:/Program Files/'.freeze
32
32
  UNITY_DIR = "Unity_%s".freeze
33
33
  UNITY_DIR_LINUX = "unity-editor-%s".freeze
34
- UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/
35
- UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/
36
-
37
- class Installation
38
- def self.create(path: nil)
39
- if Helper.mac?
40
- MacInstallation.new path
41
- elsif Helper.linux?
42
- LinuxInstallation.new path
43
- else
44
- WindowsInstallation.new path
45
- end
46
- end
47
- end
48
-
49
- class MacInstallation < Installation
50
- attr_reader :path
51
-
52
- require 'plist'
53
-
54
- def initialize(path: nil)
55
- @path = path
56
- end
57
-
58
- def version
59
- plist['CFBundleVersion']
60
- end
61
-
62
- def default_log_file
63
- "#{ENV['HOME']}/Library/Logs/Unity/Editor.log"
64
- end
65
-
66
- def exe_path
67
- "#{path}/Contents/MacOS/Unity"
68
- end
69
-
70
- def packages
71
- if Utils.parse_unity_version(version)[0].to_i <= 4
72
- # Unity < 5 doesn't have packages
73
- return []
74
- end
75
- fpath = File.expand_path('../PlaybackEngines', path)
76
- raise "Unity installation does not seem correct. Couldn't locate PlaybackEngines." unless Dir.exist? fpath
77
- Dir.entries(fpath).select { |e| File.directory?(File.join(fpath, e)) && !(e == '.' || e == '..') }
78
- end
79
-
80
- def clean_install?
81
- path =~ UNITY_DIR_CHECK
82
- end
83
-
84
- private
85
-
86
- def plist
87
- @plist ||= Plist.parse_xml("#{@path}/Contents/Info.plist")
88
- end
89
- end
90
-
91
- class LinuxInstallation < Installation
92
- attr_reader :path
93
-
94
- def initialize(path: nil)
95
- @path = path
96
- end
97
-
98
- def version
99
- # I don't find an easy way to extract the version on Linux
100
- require 'rexml/document'
101
- fpath = "#{path}/Editor/Data/PlaybackEngines/LinuxStandaloneSupport/ivy.xml"
102
- raise "Couldn't find file #{fpath}" unless File.exist? fpath
103
- doc = REXML::Document.new(File.read(fpath))
104
- version = REXML::XPath.first(doc, 'ivy-module/info/@e:unityVersion').value
105
- if m = version.match(/^(.*)x(.*)Linux$/)
106
- version = "#{m[1]}#{m[2]}"
107
- end
108
- version
109
- end
110
-
111
- def default_log_file
112
- "#{ENV['HOME']}/.config/unity3d/Editor.log"
113
- end
114
-
115
- def exe_path
116
- "#{path}/Editor/Unity"
117
- end
118
-
119
- def packages
120
- false
121
- end
122
-
123
- def clean_install?
124
- path =~ UNITY_DIR_CHECK_LINUX
125
- end
126
- end
127
-
128
- class WindowsInstallation < Installation
129
- attr_reader :path
130
-
131
- def initialize(path: nil)
132
- @path = path
133
- end
134
-
135
- def version
136
- require 'rexml/document'
137
- fpath = "#{path}/Editor/Data/PlaybackEngines/windowsstandalonesupport/ivy.xml"
138
- raise "Couldn't find file #{fpath}" unless File.exist? fpath
139
- doc = REXML::Document.new(File.read(fpath))
140
- version = REXML::XPath.first(doc, 'ivy-module/info/@e:unityVersion').value
141
-
142
- version
143
- end
144
-
145
- def default_log_file
146
- if @logfile.nil?
147
- begin
148
- loc_appdata = Utils.windows_local_appdata
149
- log_dir = File.expand_path('Unity/Editor/', loc_appdata)
150
- UI.important "Log directory (#{log_dir}) does not exist" unless Dir.exist? log_dir
151
- @logfile = File.expand_path('Editor.log', log_dir)
152
- rescue RuntimeError => ex
153
- UI.error "Unable to retrieve the editor logfile: #{ex}"
154
- end
155
- end
156
- @logfile
157
- end
158
-
159
- def exe_path
160
- File.join(@path, 'Editor', 'Unity.exe')
161
- end
162
-
163
- def packages
164
- # Unity prior to Unity5 did not have package
165
- return [] if Utils.parse_unity_version(version)[0].to_i <= 4
166
- fpath = "#{path}/Editor/Data/PlaybackEngines/"
167
- raise "Unity installation does not seem correct. Couldn't locate PlaybackEngines." unless Dir.exist? fpath
168
- Dir.entries(fpath).select { |e| File.directory?(File.join(fpath, e)) && !(e == '.' || e == '..') }
169
- end
170
-
171
- def clean_install?
172
- path =~ UNITY_DIR_CHECK
173
- end
174
- end
175
34
 
176
35
  class Installer
177
36
  def self.create
@@ -182,16 +41,23 @@ module U3d
182
41
  else
183
42
  WindowsInstaller.new
184
43
  end
185
- if UI.interactive?
186
- unclean = []
187
- installer.installed.each { |unity| unclean << unity unless unity.clean_install? }
188
- if !unclean.empty? && UI.confirm("#{unclean.count} Unity installation should be moved. Proceed?")
189
- unclean.each { |unity| installer.sanitize_install(unity) }
190
- end
191
- end
44
+ sanitize_installs(installer)
192
45
  installer
193
46
  end
194
47
 
48
+ def self.sanitize_installs(installer)
49
+ return unless UI.interactive? || Helper.test?
50
+ unclean = []
51
+ installer.installed.each { |unity| unclean << unity unless unity.clean_install? }
52
+ return if unclean.empty?
53
+ UI.important("u3d can optionally standardize the existing Unity3d installation names and locations.")
54
+ UI.important("Check the documentation for more information:")
55
+ UI.important("** https://github.com/DragonBox/u3d/blob/master/README.md#default-installation-paths **")
56
+ unclean.each { |unity| installer.sanitize_install(unity, dry_run: true) }
57
+ return unless UI.confirm("#{unclean.count} Unity installation(s) will be moved. Proceed??")
58
+ unclean.each { |unity| installer.sanitize_install(unity) }
59
+ end
60
+
195
61
  def self.install_modules(files, version, installation_path: nil)
196
62
  installer = Installer.create
197
63
  files.each do |name, file, info|
@@ -201,19 +67,36 @@ module U3d
201
67
  end
202
68
  end
203
69
 
70
+ class CommonInstaller
71
+ def self.sanitize_install(source_path, new_path, command, dry_run: false)
72
+ if source_path == new_path
73
+ UI.important "sanitize_install does nothing if the path won't change (#{source_path})"
74
+ return
75
+ end
76
+
77
+ if dry_run
78
+ UI.message "'#{source_path}' would move to '#{new_path}'"
79
+ else
80
+ UI.important "Moving '#{source_path}' to '#{new_path}'..."
81
+ U3dCore::CommandExecutor.execute(command: command, admin: true)
82
+ UI.success "Successfully moved '#{source_path}' to '#{new_path}'"
83
+ end
84
+ rescue => e
85
+ UI.error "Unable to move '#{source_path}' to '#{new_path}': #{e}"
86
+ end
87
+ end
88
+
204
89
  class MacInstaller
205
- def sanitize_install(unity)
90
+ def sanitize_install(unity, dry_run: false)
206
91
  source_path = File.expand_path('..', unity.path)
207
92
  parent = File.expand_path('..', source_path)
208
93
  new_path = File.join(parent, UNITY_DIR % unity.version)
209
- UI.important "Moving #{source_path} to #{new_path}..."
210
- source_path = "\"#{source_path}\"" if source_path =~ / /
211
- new_path = "\"#{new_path}\"" if new_path =~ / /
212
- U3dCore::CommandExecutor.execute(command: "mv #{source_path} #{new_path}", admin: true)
213
- rescue => e
214
- UI.error "Unable to move #{source_path} to #{new_path}: #{e}"
215
- else
216
- UI.success "Successfully moved #{source_path} to #{new_path}"
94
+ source_path = source_path.shellescape
95
+ new_path = new_path.shellescape
96
+
97
+ command = "mv #{source_path} #{new_path}"
98
+
99
+ CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
217
100
  end
218
101
 
219
102
  def installed
@@ -234,7 +117,9 @@ module U3d
234
117
  versions.sort! { |x, y| x.version <=> y.version }
235
118
  end
236
119
 
120
+ # rubocop:disable UnusedMethodArgument
237
121
  def install(file_path, version, installation_path: nil, info: {})
122
+ # rubocop:enable UnusedMethodArgument
238
123
  extension = File.extname(file_path)
239
124
  raise "Installation of #{extension} files is not supported on Mac" if extension != '.pkg'
240
125
  path = installation_path || DEFAULT_MAC_INSTALL
@@ -249,13 +134,15 @@ module U3d
249
134
  target_path ||= DEFAULT_MAC_INSTALL
250
135
  command = "installer -pkg #{file_path.shellescape} -target #{target_path.shellescape}"
251
136
  unity = installed.find { |u| u.version == version }
137
+ temp_path = File.join(target_path, 'Applications', 'Unity')
252
138
  if unity.nil?
253
139
  UI.verbose "No Unity install for version #{version} was found"
254
140
  U3dCore::CommandExecutor.execute(command: command, admin: true)
141
+ destination_path = File.join(target_path, 'Applications', UNITY_DIR % version)
142
+ FileUtils.mv temp_path, destination_path
255
143
  else
256
144
  begin
257
145
  path = File.expand_path('..', unity.path)
258
- temp_path = File.join(target_path, 'Applications', 'Unity')
259
146
  move_to_temp = (temp_path != path)
260
147
  if move_to_temp
261
148
  UI.verbose "Temporary switching location of #{path} to #{temp_path} for installation purpose"
@@ -274,18 +161,16 @@ module U3d
274
161
  end
275
162
 
276
163
  class LinuxInstaller
277
- def sanitize_install(unity)
164
+ def sanitize_install(unity, dry_run: false)
278
165
  source_path = File.expand_path(unity.path)
279
166
  parent = File.expand_path('..', source_path)
280
167
  new_path = File.join(parent, UNITY_DIR_LINUX % unity.version)
281
- UI.important "Moving #{source_path} to #{new_path}..."
282
- source_path = "\"#{source_path}\"" if source_path =~ / /
283
- new_path = "\"#{new_path}\"" if new_path =~ / /
284
- U3dCore::CommandExecutor.execute(command: "mv #{source_path} #{new_path}", admin: true)
285
- rescue => e
286
- UI.error "Unable to move #{source_path} to #{new_path}: #{e}"
287
- else
288
- UI.success "Successfully moved #{source_path} to #{new_path}"
168
+ source_path = source_path.shellescape
169
+ new_path = new_path.shellescape
170
+
171
+ command = "mv #{source_path} #{new_path}"
172
+
173
+ CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
289
174
  end
290
175
 
291
176
  def installed
@@ -296,7 +181,9 @@ module U3d
296
181
  versions.sort! { |x, y| x.version <=> y.version }
297
182
  end
298
183
 
184
+ # rubocop:disable UnusedMethodArgument
299
185
  def install(file_path, version, installation_path: nil, info: {})
186
+ # rubocop:enable UnusedMethodArgument
300
187
  extension = File.extname(file_path)
301
188
  raise "Installation of #{extension} files is not supported on Linux" if extension != '.sh'
302
189
  path = installation_path || DEFAULT_LINUX_INSTALL
@@ -327,20 +214,19 @@ module U3d
327
214
  end
328
215
 
329
216
  class WindowsInstaller
330
- def sanitize_install(unity)
217
+ def sanitize_install(unity, dry_run: false)
331
218
  source_path = File.expand_path(unity.path)
332
219
  parent = File.expand_path('..', source_path)
333
220
  new_path = File.join(parent, UNITY_DIR % unity.version)
334
- UI.important "Moving #{source_path} to #{new_path}..."
221
+
335
222
  source_path.tr!('/', '\\')
336
223
  new_path.tr!('/', '\\')
337
224
  source_path = "\"" + source_path + "\"" if source_path =~ / /
338
225
  new_path = "\"" + new_path + "\"" if new_path =~ / /
339
- U3dCore::CommandExecutor.execute(command: "move #{source_path} #{new_path}", admin: true)
340
- rescue => e
341
- UI.error "Unable to move #{source_path} to #{new_path}: #{e}"
342
- else
343
- UI.success "Successfully moved #{source_path} to #{new_path}"
226
+
227
+ command = "move #{source_path} #{new_path}"
228
+
229
+ CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
344
230
  end
345
231
 
346
232
  def installed
@@ -374,7 +260,7 @@ module U3d
374
260
  command.sub!(/{INSTDIR}/, final_path)
375
261
  command.sub!(/{DOCDIR}/, final_path)
376
262
  command.sub!(/{MODULEDIR}/, final_path)
377
- command.sub!(/\/D=/, '/S /D=') unless /\/S/ =~ command
263
+ command.sub!(%r{\/D=}, '/S /D=') unless %r{\/S} =~ command
378
264
  end
379
265
  command ||= file_path.to_s
380
266
  U3dCore::CommandExecutor.execute(command: command, admin: true)
@@ -385,24 +271,4 @@ module U3d
385
271
  end
386
272
  end
387
273
  end
388
-
389
- class UnityProject
390
- attr_reader :path
391
-
392
- def initialize(path)
393
- @path = path
394
- end
395
-
396
- def exist?
397
- Dir.exist?("#{@path}/Assets") && Dir.exist?("#{@path}/ProjectSettings")
398
- end
399
-
400
- def editor_version
401
- require 'yaml'
402
- yaml = YAML.load(File.read("#{@path}/ProjectSettings/ProjectVersion.txt"))
403
- version = yaml['m_EditorVersion']
404
- version.gsub!(/(\d+\.\d+\.\d+)(?:x)?(\w\d+)(?:Linux)?/, '\1\2') if Helper.linux?
405
- version
406
- end
407
- end
408
274
  end