u3d 1.0.20 → 1.0.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab0e4249d0406f5fb52fdbec3de6d5da617e749d
4
- data.tar.gz: bb2dca8350752bf2eea3ca212b838661fd8b4762
3
+ metadata.gz: 10b2431e2eb35059d86094081ce7c219c568f935
4
+ data.tar.gz: e826f09214bc27778063015107f8509473c58ee3
5
5
  SHA512:
6
- metadata.gz: d2250d5b8c92617ac32e8108abff60d6dc93fbab21d5ce8007a0639e832444635f8c68c596c5cc7cefdfbfab2420aa269da4bd91ff3b1518630d8cf319533807
7
- data.tar.gz: 04d154f9e8c7bdb6f7cac0f3a47711c5e2fe1b8cd4efa5a086fb6984e67fa7d9776498983cb3167e6c98ad302cd19fea4081a8afc0dec6b146f078fb733a10e3
6
+ metadata.gz: 193be5dd907f183a023cf64d6e88b0cd483b0bac27e37b0735c0cf560707467d765208a1c9643f2f0c9a80e6745d2232ce83d170a18cb464b791d375d6efcb9d
7
+ data.tar.gz: 064ef5072d1bd047109874b91662fc589125892e90e5c4fcb3c9fec759b5f375a28bdbe9b273f110f7ee30fd0179f7a9cb6c0787b1e02e1294f54d850411763c
@@ -1,4 +1,4 @@
1
- future-release=v1.0.20
1
+ future-release=v1.0.21
2
2
  since-tag=v0.9
3
3
  exclude_tags_regex=v0\.[0-8]\..*
4
4
  exclude-labels=nochangelog,question
data/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Change Log
2
2
 
3
+ ## [v1.0.21](https://github.com/DragonBox/u3d/tree/v1.0.21) (2018-04-27)
4
+ [Full Changelog](https://github.com/DragonBox/u3d/compare/v1.0.20...v1.0.21)
5
+
6
+ **Implemented enhancements:**
7
+
8
+ - u3d/install: do not ask for password when user is root on Linux [\#303](https://github.com/DragonBox/u3d/issues/303)
9
+ - u3d/prettify: report failures to parse logs automatically [\#146](https://github.com/DragonBox/u3d/issues/146)
10
+ - u3d/install do not ask for root password [\#304](https://github.com/DragonBox/u3d/pull/304) ([lacostej](https://github.com/lacostej))
11
+ - u3d/\* automatically retry admin privilege elevation \#236 [\#297](https://github.com/DragonBox/u3d/pull/297) ([lacostej](https://github.com/lacostej))
12
+ - u3d/sanitize: support dot\_not\_move [\#293](https://github.com/DragonBox/u3d/pull/293) ([lacostej](https://github.com/lacostej))
13
+ - u3d/ui: adjust a message that is use for more than just downloading unity [\#292](https://github.com/DragonBox/u3d/pull/292) ([lacostej](https://github.com/lacostej))
14
+ - u3d/sanitize: ensure Installation instance's root\_path is updated post move [\#291](https://github.com/DragonBox/u3d/pull/291) ([lacostej](https://github.com/lacostej))
15
+ - u3d/move command, renaming install dirs. Support long version names. Fixes \#274 [\#289](https://github.com/DragonBox/u3d/pull/289) ([lacostej](https://github.com/lacostej))
16
+ - u3d/console: an interactive version of u3d \(Fixes \#265\) [\#283](https://github.com/DragonBox/u3d/pull/283) ([lacostej](https://github.com/lacostej))
17
+
18
+ **Fixed bugs:**
19
+
20
+ - Unity Installations fail on Windows with space in path [\#302](https://github.com/DragonBox/u3d/issues/302)
21
+ - u3d/internals: grant\_admin wasn't using has\_admin\_privileges? to get the privileges on non windows platforms [\#301](https://github.com/DragonBox/u3d/pull/301) ([lacostej](https://github.com/lacostej))
22
+
23
+ **Closed issues:**
24
+
25
+ - Include build number when renaming hotfix releases of Unity [\#274](https://github.com/DragonBox/u3d/issues/274)
26
+ - u3d should ask again for password if wrong password is given in interactive mode [\#236](https://github.com/DragonBox/u3d/issues/236)
27
+ - u3d: non UTF-8 environments can cause issues. [\#147](https://github.com/DragonBox/u3d/issues/147)
28
+
29
+ **Merged pull requests:**
30
+
31
+ - u3d/console: remove require on pry [\#307](https://github.com/DragonBox/u3d/pull/307) ([lacostej](https://github.com/lacostej))
32
+ - Allow spaces in installation paths on Windows \#302 [\#306](https://github.com/DragonBox/u3d/pull/306) ([lacostej](https://github.com/lacostej))
33
+ - u3d/install: support full pkg for Linux [\#305](https://github.com/DragonBox/u3d/pull/305) ([lacostej](https://github.com/lacostej))
34
+ - u3d/internals: fallback on admin move of creating u3d\_do\_not\_move if needed [\#300](https://github.com/DragonBox/u3d/pull/300) ([lacostej](https://github.com/lacostej))
35
+ - u3d/list: identify versions that can't be moved with a ! [\#298](https://github.com/DragonBox/u3d/pull/298) ([lacostej](https://github.com/lacostej))
36
+ - u3d/internals: move windows\_path from U3d::Utils to U3dCore::Helper and reuse it in AdminTools [\#296](https://github.com/DragonBox/u3d/pull/296) ([lacostej](https://github.com/lacostej))
37
+ - u3d/internals: extract the move\_file into U3dCore::AdminTools [\#295](https://github.com/DragonBox/u3d/pull/295) ([lacostej](https://github.com/lacostej))
38
+ - u3d/sanitize: sanitize on list only + cleanups and refactors [\#294](https://github.com/DragonBox/u3d/pull/294) ([lacostej](https://github.com/lacostej))
39
+ - u3d/list: properly identify the build number [\#288](https://github.com/DragonBox/u3d/pull/288) ([lacostej](https://github.com/lacostej))
40
+ - u3d/examples: support Unity 2017.3+, identified while investigating \#3 [\#286](https://github.com/DragonBox/u3d/pull/286) ([lacostej](https://github.com/lacostej))
41
+ - u3d/\* Detect incorrect locale \(Fixes \#147\) [\#285](https://github.com/DragonBox/u3d/pull/285) ([lacostej](https://github.com/lacostej))
42
+ - u3d/list: introduce format and make sure the list\_installed return an array of versions [\#284](https://github.com/DragonBox/u3d/pull/284) ([lacostej](https://github.com/lacostej))
43
+
3
44
  ## [v1.0.20](https://github.com/DragonBox/u3d/tree/v1.0.20) (2018-04-19)
4
45
  [Full Changelog](https://github.com/DragonBox/u3d/compare/v1.0.19...v1.0.20)
5
46
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- u3d (1.0.20)
4
+ u3d (1.0.21)
5
5
  colored (>= 1.2, < 2.0.0)
6
6
  commander (>= 4.4.0, < 5.0.0)
7
7
  file-tail (>= 1.2.0)
@@ -22,7 +22,8 @@ GEM
22
22
  public_suffix (~> 2.0, >= 2.0.2)
23
23
  ast (2.3.0)
24
24
  builder (3.2.3)
25
- coderay (1.1.1)
25
+ byebug (10.0.2)
26
+ coderay (1.1.2)
26
27
  colored (1.2)
27
28
  commander (4.4.4)
28
29
  highline (~> 1.7.2)
@@ -54,7 +55,7 @@ GEM
54
55
  i18n (0.8.6)
55
56
  inifile (3.0.0)
56
57
  json (2.1.0)
57
- method_source (0.8.2)
58
+ method_source (0.9.0)
58
59
  minitest (5.10.3)
59
60
  multi_json (1.12.1)
60
61
  multipart-post (2.0.0)
@@ -65,10 +66,12 @@ GEM
65
66
  ast (~> 2.3)
66
67
  plist (3.4.0)
67
68
  powerpack (0.1.1)
68
- pry (0.10.4)
69
+ pry (0.11.3)
69
70
  coderay (~> 1.1.0)
70
- method_source (~> 0.8.1)
71
- slop (~> 3.4)
71
+ method_source (~> 0.9.0)
72
+ pry-byebug (3.6.0)
73
+ byebug (~> 10.0)
74
+ pry (~> 0.10)
72
75
  public_suffix (2.0.5)
73
76
  rainbow (3.0.0)
74
77
  rake (10.5.0)
@@ -105,7 +108,6 @@ GEM
105
108
  json (>= 1.8, < 3)
106
109
  simplecov-html (~> 0.10.0)
107
110
  simplecov-html (0.10.1)
108
- slop (3.6.0)
109
111
  term-ansicolor (1.6.0)
110
112
  tins (~> 1.0)
111
113
  thor (0.19.4)
@@ -124,7 +126,7 @@ DEPENDENCIES
124
126
  bundler (~> 1.13)
125
127
  coveralls
126
128
  github_changelog_generator
127
- pry
129
+ pry-byebug
128
130
  rake (~> 10.0)
129
131
  rspec (~> 3.1.0)
130
132
  rspec_junit_formatter (~> 0.2.3)
data/README.md CHANGED
@@ -55,6 +55,10 @@ The prettifyer is on by default but can be turned off to get Unity's raw output.
55
55
 
56
56
  ![u3d list](https://github.com/DragonBox/u3d/raw/master/docs/assets/u3d_licenses.png)
57
57
 
58
+ * `u3d console`: Run u3d in interactive mode, accessing its API
59
+
60
+ ![u3d console](https://github.com/DragonBox/u3d/raw/master/docs/assets/u3d_console.png)
61
+
58
62
  ## Installation
59
63
 
60
64
  ```shell
@@ -82,7 +86,7 @@ Unity uses the following version formatting: 0.0.0x0. The \'x\' can takes differ
82
86
 
83
87
  Some versions are known to have a different numbering, e.g. Linux 2017.1.0f3 is named 2017.1.0xf3Linux. Its `ProjectSettings/ProjectVersion.txt` will contain the Linux specific version.
84
88
 
85
- When referencing to a version on the CLI, u3d sanitizes these weird versions. For example, if you ask u3d to launch unity 2017.1.0f3 on Linux, you can use `u3d -u 2017.1.0f3` and it will find "2017.1.0xf3Linux".
89
+ When referencing to a version on the CLI, u3d normalizes these weird versions. For example, if you ask u3d to launch unity 2017.1.0f3 on Linux, you can use `u3d -u 2017.1.0f3` and it will find "2017.1.0xf3Linux".
86
90
 
87
91
  ### Unity build numbers
88
92
 
@@ -114,10 +118,14 @@ Right now u3d has light support for build numbers. The build number can be found
114
118
 
115
119
  ## Sanitize / standardize Unity installation paths
116
120
 
117
- If you have installed Unity in different locations, u3d might discover them and propose you to move them to its standard location. The procedure should be self described and easily revertible (manually). This sanitization operation is only proposed in interactive mode (i.e. if you are not using u3d unattended, e.g. in a build script on a CI server).
121
+ If you have installed Unity in different locations, u3d might discover them and propose you to move them to its standard location. The procedure should be self described and easily revertible (manually). This sanitization operation is only proposed in interactive mode (i.e. if you are not using u3d unattended, e.g. in a build script on a CI server) when running the `list` command.
118
122
 
119
123
  ![u3d sanitize](https://github.com/DragonBox/u3d/raw/master/docs/assets/u3d_sanitize.png)
120
124
 
125
+ If you wish a particular Unity installation to be ignored by the sanitization feature, create a `.u3d_do_not_move` file inside it.
126
+
127
+ If you wish to have your pre-installed unities directory name to automatically contain the full version (unity version + build number), you can call `u3d move --long <version>`.
128
+
121
129
  ## Security
122
130
 
123
131
  When you install Unity with this tool, you will have to grant it higher privileges so it can perform the installation. It means that under MacOS and Linux, you will be asked for your `sudo` password.
data/WIP ADDED
@@ -0,0 +1,5 @@
1
+ * merge other PRs
2
+
3
+ * note: matcher in sanitization is partial on full path and doesn't ask you to move things like Unity_Version_XXX as Version matches it
4
+ * optim: only move with super admin rights if necessary
5
+
Binary file
Binary file
@@ -10,7 +10,14 @@ namespace U3d {
10
10
  static void Build() {
11
11
  Debug.Log("Building Example2");
12
12
 
13
- BuildPlayer(EditorBuildSettings.scenes, "target/Example2.app", BuildTarget.StandaloneOSXIntel64, BuildOptions.None);
13
+ BuildTarget Target;
14
+ #if UNITY_2017_3_OR_NEWER
15
+ Target = BuildTarget.StandaloneOSX;
16
+ #else
17
+ Target = BuildTarget.StandaloneOSXIntel64;
18
+ #endif
19
+
20
+ BuildPlayer(EditorBuildSettings.scenes, "target/Example2.app", Target, BuildOptions.None);
14
21
  }
15
22
 
16
23
  private static void BuildPlayer(EditorBuildSettingsScene[] scenes, string target_dir, BuildTarget build_target, BuildOptions build_options) {
@@ -0,0 +1,2 @@
1
+
2
+
data/lib/u3d/commands.rb CHANGED
@@ -43,21 +43,18 @@ module U3d
43
43
 
44
44
  class << self
45
45
  def list_installed(options: {})
46
- list = Installer.create.installed
46
+ installer = Installer.create
47
+ installer.sanitize_installs
48
+ list = installer.installed_sorted_by_versions
47
49
  if list.empty?
48
50
  UI.important 'No Unity version installed'
49
51
  return
50
52
  end
51
- # version -> installations
52
- arraym = list.map { |a| [a.version, a] }
53
- map = Hash[*arraym.flatten]
54
- # sorted versions
55
- vcomparators = map.keys.map { |k| UnityVersionComparator.new(k) }
56
- sorted_keys = vcomparators.sort.map { |v| v.version.to_s }
57
- sorted_keys.each do |k|
58
- u = map[k]
59
- version = "#{u.version.ljust(13)} [#{u.build_number}]".ljust(30)
60
- UI.message "Version #{version}(#{u.root_path})"
53
+ list.each do |u|
54
+ version_format = "Version %-15{version} [%<build_number>s] %<do_not_move>s(%<root_path>s)"
55
+ do_not_move = u.do_not_move? ? '!'.red.bold : ' '
56
+ h = { version: u.version, build_number: u.build_number, root_path: u.root_path, do_not_move: do_not_move }
57
+ UI.message version_format % h
61
58
  packages = u.packages
62
59
  next unless options[:packages] && packages && !packages.empty?
63
60
  UI.message 'Packages:'
@@ -65,6 +62,47 @@ module U3d
65
62
  end
66
63
  end
67
64
 
65
+ # rubocop:disable Style/FormatStringToken
66
+ def console
67
+ require 'irb'
68
+ ARGV.clear
69
+ IRB.setup(nil)
70
+ @irb = IRB::Irb.new(nil)
71
+ IRB.conf[:MAIN_CONTEXT] = @irb.context
72
+ IRB.conf[:PROMPT][:U3D] = IRB.conf[:PROMPT][:SIMPLE].dup
73
+ IRB.conf[:PROMPT][:U3D][:RETURN] = "%s\n"
74
+ @irb.context.prompt_mode = :U3D
75
+ @irb.context.workspace = IRB::WorkSpace.new(binding)
76
+ trap 'INT' do
77
+ @irb.signal_handle
78
+ end
79
+
80
+ UI.message('Welcome to u3d interactive!')
81
+
82
+ catch(:IRB_EXIT) { @irb.eval_input }
83
+ end
84
+ # rubocop:enable Style/FormatStringToken
85
+
86
+ def move(args: {}, options: {})
87
+ long_name = options[:long]
88
+ UI.user_error! "move only supports long version name for now" unless long_name
89
+
90
+ version = args[0]
91
+ UI.user_error! "Please specify a Unity version" unless version
92
+ unity = check_unity_presence(version: version)
93
+ if unity.nil?
94
+ UI.message "Specified version '#{version}' not found."
95
+ return
96
+ end
97
+ if unity.do_not_move?
98
+ UI.error "Specified version is specicically marked as _do not move_."
99
+ return
100
+ end
101
+ Installer.create.sanitize_install(unity, long: true, dry_run: options[:dry_run])
102
+
103
+ unity.do_not_move!(dry_run: options[:dry_run]) # this may fail because of admin rights
104
+ end
105
+
68
106
  def list_available(options: {})
69
107
  ver = options[:unity_version]
70
108
  os = valid_os_or_current(options[:operating_system])
@@ -246,7 +284,7 @@ module U3d
246
284
  up = UnityProject.new(Dir.pwd)
247
285
  version = up.editor_version if up.exist?
248
286
  end
249
- UI.user_error!('Please specify a Unity version to download') unless version
287
+ UI.user_error!('Please specify a Unity version') unless version
250
288
  version
251
289
  end
252
290
 
@@ -33,10 +33,20 @@ module U3d
33
33
  include Commander::Methods
34
34
  UI = U3dCore::UI
35
35
 
36
+ UNICODE_FILE = File.expand_path('../../assets/utf8.txt', __FILE__)
37
+
36
38
  def self.start
39
+ check_locale
37
40
  new.run
38
41
  end
39
42
 
43
+ def self.check_locale
44
+ File.read(UNICODE_FILE).split("\n")
45
+ rescue ArgumentError => _e
46
+ UI.important "WARNING! Your Locale system appears to be incompatible with Unicode. Set you LOCALE appropriately"
47
+ UI.important "See https://github.com/DragonBox/u3d#setup"
48
+ end
49
+
40
50
  def extract_run_args(args = ARGV)
41
51
  both_args = [[], []]
42
52
  idx = 0
@@ -212,6 +222,32 @@ More on that: https://forum.unity3d.com/threads/unity-on-linux-release-notes-and
212
222
  end
213
223
  end
214
224
 
225
+ command :console do |c|
226
+ c.syntax = 'u3d console'
227
+ c.summary = "Run an interactive console"
228
+ c.action do |_args, _options|
229
+ Commands.console
230
+ end
231
+ end
232
+
233
+ command :move do |c|
234
+ c.syntax = 'u3d move [--dry_run] --long <version>'
235
+ # c.option '-f', '--force', Array, 'Specifies which packages to download/install. Overriden by --all'
236
+ c.option '-l', '--long', "Rename the installation dir into its long name pattern, namely #{U3d::UNITY_DIR_LONG} on Windows/Mac and #{U3d::UNITY_DIR_LINUX_LONG} on Linux"
237
+ c.option '--dry_run', "show what would have happened"
238
+ c.summary = "Move an existing Unity install to an optionally specified new folder, marking it as non moveable later on"
239
+ c.description = %(
240
+ #{c.summary}
241
+ Sometimes you want to move Unity to a different folder/path and let u3d stop modifying trying to move it around.
242
+
243
+ The current command only supports 'long' installation dir names, containing not only the version but also the build number.
244
+ See https://github.com/DragonBox/u3d#unity-build-numbers for more information.
245
+ )
246
+ c.action do |args, options|
247
+ Commands.move(args: args, options: convert_options(options))
248
+ end
249
+ end
250
+
215
251
  default_command :run
216
252
 
217
253
  run!
data/lib/u3d/iniparser.rb CHANGED
@@ -48,7 +48,6 @@ module U3d
48
48
  end
49
49
  begin
50
50
  result = IniFile.load(ini_path).to_h
51
- result = filter_broken_linux(result) if os == 'linux'
52
51
  rescue StandardError => e
53
52
  raise "Could not parse INI data (#{e})"
54
53
  end
@@ -98,10 +97,6 @@ url=#{url}
98
97
  end
99
98
  end
100
99
 
101
- def filter_broken_linux(ini_hash)
102
- ini_hash.select { |_k, v| v['url'] && !v['url'].end_with?('.pkg') }
103
- end
104
-
105
100
  def default_ini_path
106
101
  File.join(U3dCore::Helper.data_path, 'ini_files')
107
102
  end
@@ -21,13 +21,16 @@
21
21
  ## --- END LICENSE BLOCK ---
22
22
 
23
23
  require 'u3d/utils'
24
+ require 'u3d_core/admin_tools'
25
+ require 'fileutils'
24
26
 
25
27
  module U3d
26
28
  UNITY_DIR_CHECK = /Unity_\d+\.\d+\.\d+[a-z]\d+/
27
29
  UNITY_DIR_CHECK_LINUX = /unity-editor-\d+\.\d+\.\d+[a-z]\d+\z/
30
+ U3D_DO_NOT_MOVE = ".u3d_do_not_move".freeze
28
31
 
29
32
  class Installation
30
- attr_reader :root_path
33
+ attr_accessor :root_path
31
34
 
32
35
  NOT_PLAYBACKENGINE_PACKAGES = %w[Documentation StandardAssets MonoDevelop].freeze
33
36
  PACKAGE_ALIASES =
@@ -67,6 +70,22 @@ module U3d
67
70
  false
68
71
  end
69
72
 
73
+ def do_not_move?
74
+ File.exist?(@root_path) && File.exist?(do_not_move_file_path)
75
+ end
76
+
77
+ def do_not_move!(dry_run: false)
78
+ if dry_run
79
+ UI.message "Would create '#{do_not_move_file_path}'"
80
+ else
81
+ begin
82
+ FileUtils.touch do_not_move_file_path
83
+ rescue Errno::EACCES => _e
84
+ U3dCore::AdminTools.create_file(Helper.operating_system, do_not_move_file_path)
85
+ end
86
+ end
87
+ end
88
+
70
89
  def package_installed?(package)
71
90
  return true if (packages || []).include?(package)
72
91
 
@@ -78,6 +97,12 @@ module U3d
78
97
 
79
98
  return !(aliases & packages).empty?
80
99
  end
100
+
101
+ private
102
+
103
+ def do_not_move_file_path
104
+ File.join(@root_path, U3D_DO_NOT_MOVE)
105
+ end
81
106
  end
82
107
 
83
108
  class PlaybackEngineUtils
@@ -152,7 +177,7 @@ module U3d
152
177
  end
153
178
 
154
179
  def clean_install?
155
- !(root_path =~ UNITY_DIR_CHECK).nil?
180
+ do_not_move? || !(root_path =~ UNITY_DIR_CHECK).nil?
156
181
  end
157
182
 
158
183
  private
@@ -175,6 +200,7 @@ module U3d
175
200
  rev = find_build_number_in("#{root}#{p}")
176
201
  return rev if rev
177
202
  end
203
+ nil
178
204
  end
179
205
 
180
206
  private
@@ -257,7 +283,7 @@ module U3d
257
283
  end
258
284
 
259
285
  def clean_install?
260
- !(root_path =~ UNITY_DIR_CHECK_LINUX).nil?
286
+ do_not_move? || !(root_path =~ UNITY_DIR_CHECK_LINUX).nil?
261
287
  end
262
288
  end
263
289
 
@@ -372,7 +398,7 @@ module U3d
372
398
  end
373
399
 
374
400
  def clean_install?
375
- !(root_path =~ UNITY_DIR_CHECK).nil?
401
+ do_not_move? || !(root_path =~ UNITY_DIR_CHECK).nil?
376
402
  end
377
403
  end
378
404
  end
data/lib/u3d/installer.rb CHANGED
@@ -21,6 +21,7 @@
21
21
  ## --- END LICENSE BLOCK ---
22
22
 
23
23
  require 'u3d/utils'
24
+ require 'u3d_core/admin_tools'
24
25
  require 'u3d_core/core_ext/string'
25
26
  require 'u3d/installation'
26
27
  require 'fileutils'
@@ -32,32 +33,23 @@ module U3d
32
33
  DEFAULT_MAC_INSTALL = '/'.freeze
33
34
  DEFAULT_WINDOWS_INSTALL = 'C:/Program Files/'.freeze
34
35
  UNITY_DIR = "Unity_%<version>s".freeze
36
+ UNITY_DIR_LONG = "Unity_%<version>s_%<build_number>s".freeze
35
37
  UNITY_DIR_LINUX = "unity-editor-%<version>s".freeze
38
+ UNITY_DIR_LINUX_LONG = "unity-editor-%<version>s_%<build_number>s".freeze
36
39
 
37
40
  class Installer
38
41
  def self.create
39
- installer = if Helper.mac?
40
- MacInstaller.new
41
- elsif Helper.linux?
42
- LinuxInstaller.new
43
- else
44
- WindowsInstaller.new
45
- end
46
- sanitize_installs(installer)
47
- installer
42
+ if Helper.mac?
43
+ MacInstaller.new
44
+ elsif Helper.linux?
45
+ LinuxInstaller.new
46
+ else
47
+ WindowsInstaller.new
48
+ end
48
49
  end
49
50
 
50
51
  def self.sanitize_installs(installer)
51
- return unless UI.interactive? || Helper.test?
52
- unclean = []
53
- installer.installed.each { |unity| unclean << unity unless unity.clean_install? }
54
- return if unclean.empty?
55
- UI.important("u3d can optionally standardize the existing Unity installation names and locations.")
56
- UI.important("Check the documentation for more information:")
57
- UI.important("** https://github.com/DragonBox/u3d/blob/master/README.md#default-installation-paths **")
58
- unclean.each { |unity| installer.sanitize_install(unity, dry_run: true) }
59
- return unless UI.confirm("#{unclean.count} Unity installation(s) will be moved. Proceed??")
60
- unclean.each { |unity| installer.sanitize_install(unity) }
52
+ installer.sanitize_installs
61
53
  end
62
54
 
63
55
  def self.install_modules(files, version, installation_path: nil)
@@ -75,34 +67,51 @@ module U3d
75
67
  end
76
68
  end
77
69
 
70
+ class BaseInstaller
71
+ def sanitize_installs
72
+ return unless UI.interactive? || Helper.test?
73
+ unclean = []
74
+ installed.each { |unity| unclean << unity unless unity.clean_install? }
75
+ return if unclean.empty?
76
+ UI.important("u3d can optionally standardize the existing Unity installation names and locations.")
77
+ UI.important("Check the documentation for more information:")
78
+ UI.important("** https://github.com/DragonBox/u3d/blob/master/README.md#default-installation-paths **")
79
+ unclean.each { |unity| sanitize_install(unity, dry_run: true) }
80
+ return unless UI.confirm("#{unclean.count} Unity installation(s) will be moved. Proceed??")
81
+ unclean.each { |unity| sanitize_install(unity) }
82
+ end
83
+
84
+ def installed_sorted_by_versions
85
+ list = installed
86
+ return [] if list.empty?
87
+ # version -> installations
88
+ arraym = list.map { |a| [a.version, a] }
89
+ map = Hash[*arraym.flatten]
90
+ # sorted versions
91
+ vcomparators = map.keys.map { |k| UnityVersionComparator.new(k) }
92
+ sorted_keys = vcomparators.sort.map { |v| v.version.to_s }
93
+ sorted_keys.map { |k| map[k] }
94
+ end
95
+ end
96
+
97
+ # deprecated
78
98
  class CommonInstaller
79
99
  def self.sanitize_install(source_path, new_path, command, dry_run: false)
80
- if source_path == new_path
81
- UI.important "sanitize_install does nothing if the path won't change (#{source_path})"
82
- return
83
- end
84
-
85
- if dry_run
86
- UI.message "'#{source_path}' would move to '#{new_path}'"
87
- else
88
- UI.important "Moving '#{source_path}' to '#{new_path}'..."
89
- U3dCore::CommandExecutor.execute(command: command, admin: true)
90
- UI.success "Successfully moved '#{source_path}' to '#{new_path}'"
91
- end
92
- rescue StandardError => e
93
- UI.error "Unable to move '#{source_path}' to '#{new_path}': #{e}"
100
+ UI.deprecated("Use U3dCore::AdminTools.move_files")
101
+ U3dCore::AdminTools.move_file(source_path, new_path, command, dry_run: dry_run)
94
102
  end
95
103
  end
96
104
 
97
- class MacInstaller
98
- def sanitize_install(unity, dry_run: false)
105
+ class MacInstaller < BaseInstaller
106
+ def sanitize_install(unity, long: false, dry_run: false)
99
107
  source_path = unity.root_path
100
108
  parent = File.expand_path('..', source_path)
101
- new_path = File.join(parent, format(UNITY_DIR, version: unity.version))
109
+ dir_name = format(long ? UNITY_DIR_LONG : UNITY_DIR,
110
+ version: unity.version, build_number: unity.build_number)
111
+ new_path = File.join(parent, dir_name)
102
112
 
103
- command = "mv #{source_path.shellescape} #{new_path.shellescape}"
104
-
105
- CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
113
+ moved = U3dCore::AdminTools.move_os_file(:mac, source_path, new_path, dry_run: dry_run)
114
+ unity.root_path = new_path if moved && !dry_run
106
115
  end
107
116
 
108
117
  def installed
@@ -192,15 +201,17 @@ module U3d
192
201
  end
193
202
  end
194
203
 
195
- class LinuxInstaller
196
- def sanitize_install(unity, dry_run: false)
204
+ # rubocop:disable ClassLength
205
+ class LinuxInstaller < BaseInstaller
206
+ def sanitize_install(unity, long: false, dry_run: false)
197
207
  source_path = File.expand_path(unity.root_path)
198
208
  parent = File.expand_path('..', source_path)
199
- new_path = File.join(parent, format(UNITY_DIR_LINUX, version: unity.version))
200
-
201
- command = "mv #{source_path.shellescape} #{new_path.shellescape}"
209
+ dir_name = format(long ? UNITY_DIR_LINUX_LONG : UNITY_DIR_LINUX,
210
+ version: unity.version, build_number: unity.build_number)
211
+ new_path = File.join(parent, dir_name)
202
212
 
203
- CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
213
+ moved = U3dCore::AdminTools.move_os_file(:linux, source_path, new_path, dry_run: dry_run)
214
+ unity.root_path = new_path if moved && !dry_run
204
215
  end
205
216
 
206
217
  def installed
@@ -208,12 +219,12 @@ module U3d
208
219
  paths.map { |path| LinuxInstallation.new(root_path: path) }
209
220
  end
210
221
 
211
- # rubocop:disable UnusedMethodArgument
222
+ # rubocop:disable UnusedMethodArgument, PerceivedComplexity
212
223
  def install(file_path, version, installation_path: nil, info: {})
213
- # rubocop:enable UnusedMethodArgument
224
+ # rubocop:enable UnusedMethodArgument, PerceivedComplexity
214
225
  extension = File.extname(file_path)
215
226
 
216
- raise "Installation of #{extension} files is not supported on Linux" unless ['.sh', '.xz'].include? extension
227
+ raise "Installation of #{extension} files is not supported on Linux" unless ['.sh', '.xz', '.pkg'].include? extension
217
228
  if extension == '.sh'
218
229
  path = installation_path || DEFAULT_LINUX_INSTALL
219
230
  install_sh(file_path, installation_path: path)
@@ -221,6 +232,10 @@ module U3d
221
232
  new_path = File.join(DEFAULT_LINUX_INSTALL, format(UNITY_DIR_LINUX, version: version))
222
233
  path = installation_path || new_path
223
234
  install_xz(file_path, installation_path: path)
235
+ elsif extension == '.pkg'
236
+ new_path = File.join(DEFAULT_LINUX_INSTALL, format(UNITY_DIR_LINUX, version: version))
237
+ path = installation_path || new_path
238
+ install_pkg(file_path, installation_path: path)
224
239
  end
225
240
 
226
241
  # Forces sanitation for installation of 'weird' versions eg 5.6.1xf1Linux
@@ -262,6 +277,33 @@ module U3d
262
277
  UI.success 'Installation successful'
263
278
  end
264
279
 
280
+ def install_pkg(file, installation_path: nil)
281
+ raise 'Missing installation_path' unless installation_path
282
+ raise 'Only able to install pkg on top of existing Unity installs' unless File.exist? installation_path
283
+ raise 'Missing 7z' if `which 7z`.empty?
284
+
285
+ Dir.mktmpdir do |tmp_dir|
286
+ UI.verbose "Working in tmp dir #{tmp_dir}"
287
+
288
+ command = "7z -aos -o#{tmp_dir.shellescape} e #{file.shellescape}"
289
+ U3dCore::CommandExecutor.execute(command: command)
290
+
291
+ target_location = pkg_install_path(installation_path, "#{tmp_dir}/PackageInfo")
292
+
293
+ # raise "Path for #{target_location} already exists" if path File.exist? target_location
294
+
295
+ command = "cd #{target_location.shellescape}; gzip -dc #{tmp_dir}/Payload | cpio -i '*' -"
296
+ command = "mkdir -p #{target_location.shellescape}; #{command}" # unless File.directory? installation_path
297
+
298
+ U3dCore::CommandExecutor.execute(command: command, admin: true)
299
+ end
300
+ rescue StandardError => e
301
+ UI.verbose(e.backtrace.join("\n"))
302
+ UI.error "Failed to install pkg file #{file} at #{installation_path}: #{e}"
303
+ else
304
+ UI.success 'Installation successful'
305
+ end
306
+
265
307
  def uninstall(unity: nil)
266
308
  UI.verbose("Uninstalling Unity at '#{unity.root_path}'...")
267
309
  command = "rm -r #{unity.root_path}"
@@ -274,6 +316,27 @@ module U3d
274
316
 
275
317
  private
276
318
 
319
+ def pkg_install_path(unity_root_path, pinfo_path)
320
+ raise "PackageInfo not found under #{pinfo_path}" unless File.exist? pinfo_path
321
+ pinfo = File.read(pinfo_path)
322
+ require 'rexml/document'
323
+ d = REXML::Document.new(pinfo)
324
+ identifier = d.root.attributes['identifier']
325
+
326
+ case identifier
327
+ when 'com.unity3d.Documentation'
328
+ "#{unity_root_path}/Editor/Data/"
329
+ when 'com.unity3d.StandardAssets'
330
+ "#{unity_root_path}/Editor/Standard Assets/"
331
+ when 'com.unity3d.ExampleProject'
332
+ unity_root_path
333
+ else
334
+ install_location = d.root.attributes['install-location']
335
+ raise "Not sure how to install this module with identifier #{identifier} install-location: #{install_location}" unless install_location.start_with? '/Applications/Unity/'
336
+ install_location.gsub(%(\/Applications\/Unity), "#{unity_root_path}/Editor/Data")
337
+ end
338
+ end
339
+
277
340
  def list_installed_paths
278
341
  find = File.join(DEFAULT_LINUX_INSTALL, 'unity-editor-*', 'Editor')
279
342
  paths = Dir[find]
@@ -290,19 +353,18 @@ module U3d
290
353
  paths
291
354
  end
292
355
  end
356
+ # rubocop:enable ClassLength
293
357
 
294
- class WindowsInstaller
295
- def sanitize_install(unity, dry_run: false)
358
+ class WindowsInstaller < BaseInstaller
359
+ def sanitize_install(unity, long: false, dry_run: false)
296
360
  source_path = File.expand_path(unity.root_path)
297
361
  parent = File.expand_path('..', source_path)
298
- new_path = File.join(parent, format(UNITY_DIR, version: unity.version))
299
-
300
- source_path.tr!('/', '\\')
301
- new_path.tr!('/', '\\')
302
-
303
- command = "move #{source_path.argescape} #{new_path.argescape}"
362
+ dir_name = format(long ? UNITY_DIR_LONG : UNITY_DIR,
363
+ version: unity.version, build_number: unity.build_number)
364
+ new_path = File.join(parent, dir_name)
304
365
 
305
- CommonInstaller.sanitize_install(source_path, new_path, command, dry_run: dry_run)
366
+ moved = U3dCore::AdminTools.move_os_file(:win, source_path, new_path, dry_run: dry_run)
367
+ unity.root_path = new_path if moved && !dry_run
306
368
  end
307
369
 
308
370
  def installed
@@ -323,23 +385,23 @@ module U3d
323
385
 
324
386
  def install_exe(file_path, installation_path: nil, info: {})
325
387
  installation_path ||= DEFAULT_WINDOWS_INSTALL
326
- final_path = Utils.windows_path(installation_path)
388
+ final_path = U3dCore::Helper.windows_path(installation_path)
327
389
  Utils.ensure_dir(final_path)
328
390
  begin
329
391
  command = nil
330
392
  if info['cmd']
331
393
  command = info['cmd']
332
394
  if /msiexec/ =~ command
333
- command.sub!(/{FILENAME}/, '"' + Utils.windows_path(file_path) + '"')
395
+ command.sub!(/{FILENAME}/, '"' + U3dCore::Helper.windows_path(file_path) + '"')
334
396
  else
335
- command.sub!(/{FILENAME}/, file_path)
397
+ command.sub!(/{FILENAME}/, file_path.argescape)
336
398
  end
337
399
  command.sub!(/{INSTDIR}/, final_path)
338
400
  command.sub!(/{DOCDIR}/, final_path)
339
401
  command.sub!(/{MODULEDIR}/, final_path)
340
402
  command.sub!(%r{\/D=}, '/S /D=') unless %r{\/S} =~ command
341
403
  end
342
- command ||= file_path.to_s
404
+ command ||= file_path.argescape
343
405
  U3dCore::CommandExecutor.execute(command: command, admin: true)
344
406
  rescue StandardError => e
345
407
  UI.error "Failed to install package at #{file_path}: #{e}"
data/lib/u3d/utils.rb CHANGED
@@ -202,7 +202,8 @@ module U3d
202
202
  end
203
203
 
204
204
  def windows_path(path)
205
- path.gsub(%r{\/(\d)}, '/\\\\\1').tr('/', '\\')
205
+ UI.deprecated("Use U3dCore::Helper.windows_path")
206
+ U3dCore::Helper.windows_path(path)
206
207
  end
207
208
 
208
209
  private
data/lib/u3d/version.rb CHANGED
@@ -21,7 +21,7 @@
21
21
  ## --- END LICENSE BLOCK ---
22
22
 
23
23
  module U3d
24
- VERSION = '1.0.20'.freeze
24
+ VERSION = '1.0.21'.freeze
25
25
  DESCRIPTION = 'Provides numerous tools for installing, managing and running the Unity game engine from command line.'.freeze
26
26
  UNITY_VERSIONS_NOTE = "Unity uses the following version formatting: 0.0.0x0. The \'x\' can takes different values:\n"\
27
27
  "\t. 'f' are the main release candidates for Unity\n"\
@@ -0,0 +1,72 @@
1
+ ## --- BEGIN LICENSE BLOCK ---
2
+ # Original work Copyright (c) 2015-present the fastlane authors
3
+ # Modified work Copyright 2016-present WeWantToKnow AS
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in all
13
+ # copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ # SOFTWARE.
22
+ ## --- END LICENSE BLOCK ---
23
+ module U3dCore
24
+ class AdminTools
25
+ def self.move_os_file(os, source_path, new_path, dry_run:)
26
+ if os == :win
27
+ source_path = U3dCore::Helper.windows_path(source_path)
28
+ new_path = U3dCore::Helper.windows_path(new_path)
29
+ command = "move #{source_path.argescape} #{new_path.argescape}"
30
+ else
31
+ command = "mv #{source_path.shellescape} #{new_path.shellescape}"
32
+ end
33
+ move_file(source_path, new_path, command, dry_run: dry_run)
34
+ end
35
+
36
+ def self.create_file(os, path, dry_run: false)
37
+ if dry_run
38
+ UI.message "'#{source_path}' would create file at '#{path}'"
39
+ return
40
+ end
41
+
42
+ if os == :win
43
+ path = U3dCore::Helper.windows_path(path)
44
+ command = "fsutil file createnew #{path.argescape} 0"
45
+ else
46
+ command = "touch #{path.shellescape}"
47
+ end
48
+ U3dCore::CommandExecutor.execute(command: command, admin: true)
49
+ true
50
+ end
51
+
52
+ # move one path to a new path
53
+ def self.move_file(source_path, new_path, command, dry_run: false)
54
+ if source_path == new_path
55
+ UI.verbose "move_file does nothing if the path won't change (#{source_path})"
56
+ return false
57
+ end
58
+
59
+ if dry_run
60
+ UI.message "'#{source_path}' would move to '#{new_path}'"
61
+ else
62
+ UI.important "Moving '#{source_path}' to '#{new_path}'..."
63
+ U3dCore::CommandExecutor.execute(command: command, admin: true)
64
+ UI.success "Successfully moved '#{source_path}' to '#{new_path}'"
65
+ end
66
+ true
67
+ rescue StandardError => e
68
+ UI.error "Unable to move '#{source_path}' to '#{new_path}': #{e}"
69
+ false
70
+ end
71
+ end
72
+ end
@@ -115,42 +115,55 @@ module U3dCore
115
115
  return output.join("\n")
116
116
  end
117
117
 
118
- # rubocop:disable PredicateName
119
- def has_admin_privileges?
120
- # rubocop:enable PredicateName
118
+ # rubocop:disable PredicateName,PerceivedComplexity
119
+ def has_admin_privileges?(retry_count: 2)
120
+ # rubocop:enable PredicateName,PerceivedComplexity
121
121
  if Helper.windows?
122
122
  begin
123
- result = system('reg query HKU\\S-1-5-19', out: File::NULL, err: File::NULL)
123
+ result = system_no_output('reg query HKU\\S-1-5-19')
124
124
  rescue StandardError
125
125
  result = false
126
126
  end
127
127
  else
128
- credentials = U3dCore::Credentials.new(user: ENV['USER'])
129
- begin
130
- result = system("sudo -k && echo #{credentials.password.shellescape} | sudo -S /usr/bin/whoami",
131
- out: File::NULL,
132
- err: File::NULL)
133
- rescue StandardError
134
- result = false
128
+ env_username = ENV['USER']
129
+ if env_username == "root"
130
+ result = true
131
+ else
132
+ credentials = U3dCore::Credentials.new(user: env_username)
133
+ begin
134
+ result = system_no_output("sudo -k && echo #{credentials.password.shellescape} | sudo -S /usr/bin/whoami")
135
+ rescue StandardError
136
+ result = false
137
+ end
138
+ credentials.forget_credentials unless result # FIXME: why?
135
139
  end
136
- credentials.forget_credentials unless result # FIXME: why?
137
140
  end
138
141
  # returns false if result is nil (command execution fail)
139
- return (result ? true : false)
142
+ result = result ? true : false
143
+ result = has_admin_privileges?(retry_count: retry_count - 1) unless retry_count <= 0 || result
144
+ result
140
145
  end
141
146
 
142
147
  def grant_admin_privileges(command)
143
- cred = U3dCore::Credentials.new(user: ENV['USER'])
144
148
  if Helper.windows?
145
149
  raise CredentialsError, "The command \'#{command}\' must be run in administrative shell" unless has_admin_privileges?
146
150
  else
147
- command = "sudo -k && echo #{cred.password.shellescape} | sudo -S bash -c \"#{command}\""
151
+ env_username = ENV['USER']
152
+ unless env_username == "root"
153
+ cred = U3dCore::Credentials.new(user: env_username)
154
+ raise CredentialsError, "The command \'#{command}\' must be run with admin privileges" unless has_admin_privileges?
155
+ command = "sudo -k && echo #{cred.password.shellescape} | sudo -S bash -c \"#{command}\""
156
+ end
148
157
  end
149
158
  UI.verbose 'Admin privileges granted for command execution'
150
159
  command
151
160
  end
161
+
162
+ def system_no_output(command)
163
+ system(command, out: File::NULL, err: File::NULL)
164
+ end
152
165
  end
153
166
 
154
- private_class_method :execute_command_low
167
+ private_class_method :execute_command_low, :system_no_output
155
168
  end
156
169
  end
@@ -41,6 +41,10 @@ module U3dCore
41
41
  end
42
42
  end
43
43
 
44
+ def self.windows_path(path)
45
+ path.gsub(%r{\/(\d)}, '/\\\\\1').tr('/', '\\')
46
+ end
47
+
44
48
  # Runs a given command using backticks (`)
45
49
  # and prints them out using the UI.command method
46
50
  def self.backticks(command, print: true)
data/u3d.gemspec CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency "bundler", "~> 1.13"
35
35
  spec.add_development_dependency "coveralls"
36
36
  spec.add_development_dependency "github_changelog_generator"
37
- spec.add_development_dependency "pry"
37
+ spec.add_development_dependency "pry-byebug"
38
38
  spec.add_development_dependency "rake", "~> 10.0"
39
39
  spec.add_development_dependency "rspec", "~> 3.1.0"
40
40
  spec.add_development_dependency 'rspec_junit_formatter', '~> 0.2.3'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: u3d
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.20
4
+ version: 1.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerome Lacoste
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-04-19 00:00:00.000000000 Z
12
+ date: 2018-04-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colored
@@ -176,7 +176,7 @@ dependencies:
176
176
  - !ruby/object:Gem::Version
177
177
  version: '0'
178
178
  - !ruby/object:Gem::Dependency
179
- name: pry
179
+ name: pry-byebug
180
180
  requirement: !ruby/object:Gem::Requirement
181
181
  requirements:
182
182
  - - ">="
@@ -271,6 +271,7 @@ files:
271
271
  - LOG_RULES.md
272
272
  - README.md
273
273
  - Rakefile
274
+ - WIP
274
275
  - appveyor.yml
275
276
  - build.sh
276
277
  - config/log_rules.json
@@ -281,6 +282,7 @@ files:
281
282
  - docs/assets/ci_jenkins_version_node.png
282
283
  - docs/assets/ci_jenkins_version_param.png
283
284
  - docs/assets/u3d_available.png
285
+ - docs/assets/u3d_console.png
284
286
  - docs/assets/u3d_install.png
285
287
  - docs/assets/u3d_licenses.png
286
288
  - docs/assets/u3d_list.png
@@ -372,6 +374,7 @@ files:
372
374
  - fastlane-plugin-u3d/lib/fastlane/plugin/u3d/helper/u3d_helper.rb
373
375
  - fastlane-plugin-u3d/lib/fastlane/plugin/u3d/version.rb
374
376
  - fastlane-plugin-u3d/spec/spec_helper.rb
377
+ - lib/assets/utf8.txt
375
378
  - lib/u3d.rb
376
379
  - lib/u3d/cache.rb
377
380
  - lib/u3d/commands.rb
@@ -393,6 +396,7 @@ files:
393
396
  - lib/u3d/utils.rb
394
397
  - lib/u3d/version.rb
395
398
  - lib/u3d_core.rb
399
+ - lib/u3d_core/admin_tools.rb
396
400
  - lib/u3d_core/command_executor.rb
397
401
  - lib/u3d_core/command_runner.rb
398
402
  - lib/u3d_core/core_ext/hash.rb