u3d 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/.licenses.json +19 -0
  4. data/.rspec +1 -0
  5. data/.rubocop.yml +43 -0
  6. data/Gemfile +5 -0
  7. data/Gemfile.lock +98 -0
  8. data/LICENSE +21 -0
  9. data/LICENSE.fastlane +22 -0
  10. data/LOG_RULES.md +170 -0
  11. data/README.md +72 -0
  12. data/Rakefile +28 -0
  13. data/TODO.md +15 -0
  14. data/build.sh +5 -0
  15. data/config/log_rules.json +230 -0
  16. data/examples/Example1/.gitignore +19 -0
  17. data/examples/Example1/Assets/Editor.meta +9 -0
  18. data/examples/Example1/Assets/Editor/EditorRun.cs +23 -0
  19. data/examples/Example1/Assets/Editor/EditorRun.cs.meta +12 -0
  20. data/examples/Example1/Assets/Editor/FileSystemUtil.cs +26 -0
  21. data/examples/Example1/Assets/Editor/FileSystemUtil.cs.meta +12 -0
  22. data/examples/Example1/Assets/Scene1.unity +264 -0
  23. data/examples/Example1/Assets/Scene1.unity.meta +8 -0
  24. data/examples/Example1/Gemfile +8 -0
  25. data/examples/Example1/Gemfile.lock +165 -0
  26. data/examples/Example1/ProjectSettings/AudioManager.asset +16 -0
  27. data/examples/Example1/ProjectSettings/ClusterInputManager.asset +6 -0
  28. data/examples/Example1/ProjectSettings/DynamicsManager.asset +18 -0
  29. data/examples/Example1/ProjectSettings/EditorBuildSettings.asset +7 -0
  30. data/examples/Example1/ProjectSettings/EditorSettings.asset +14 -0
  31. data/examples/Example1/ProjectSettings/GraphicsSettings.asset +61 -0
  32. data/examples/Example1/ProjectSettings/InputManager.asset +295 -0
  33. data/examples/Example1/ProjectSettings/NavMeshAreas.asset +89 -0
  34. data/examples/Example1/ProjectSettings/NetworkManager.asset +8 -0
  35. data/examples/Example1/ProjectSettings/Physics2DSettings.asset +35 -0
  36. data/examples/Example1/ProjectSettings/ProjectSettings.asset +591 -0
  37. data/examples/Example1/ProjectSettings/ProjectVersion.txt +1 -0
  38. data/examples/Example1/ProjectSettings/QualitySettings.asset +180 -0
  39. data/examples/Example1/ProjectSettings/TagManager.asset +43 -0
  40. data/examples/Example1/ProjectSettings/TimeManager.asset +9 -0
  41. data/examples/Example1/ProjectSettings/UnityConnectSettings.asset +32 -0
  42. data/examples/Example1/README.md +5 -0
  43. data/examples/Example1/Rakefile +5 -0
  44. data/examples/Example1/fastlane/Fastfile +4 -0
  45. data/examples/Example1/fastlane/Pluginfile +1 -0
  46. data/examples/Example1/run.sh +1 -0
  47. data/examples/Example2/.gitignore +20 -0
  48. data/examples/Example2/Assets/Editor.meta +9 -0
  49. data/examples/Example2/Assets/Editor/EditorRun.cs +33 -0
  50. data/examples/Example2/Assets/Editor/EditorRun.cs.meta +12 -0
  51. data/examples/Example2/Assets/Editor/PostprocessBuildPlayer.cs +92 -0
  52. data/examples/Example2/Assets/Editor/PostprocessBuildPlayer.cs.meta +8 -0
  53. data/examples/Example2/Assets/Editor/PostprocessBuildPlayer_log.sh +31 -0
  54. data/examples/Example2/Assets/Editor/PostprocessBuildPlayer_log.sh.meta +8 -0
  55. data/examples/Example2/Assets/Editor/SimpleBuildSetup.cs +20 -0
  56. data/examples/Example2/Assets/Editor/SimpleBuildSetup.cs.meta +12 -0
  57. data/examples/Example2/Assets/Scene.unity +278 -0
  58. data/examples/Example2/Assets/Scene.unity.meta +8 -0
  59. data/examples/Example2/Gemfile +8 -0
  60. data/examples/Example2/Gemfile.lock +165 -0
  61. data/examples/Example2/ProjectSettings/AudioManager.asset +17 -0
  62. data/examples/Example2/ProjectSettings/ClusterInputManager.asset +6 -0
  63. data/examples/Example2/ProjectSettings/DynamicsManager.asset +19 -0
  64. data/examples/Example2/ProjectSettings/EditorBuildSettings.asset +10 -0
  65. data/examples/Example2/ProjectSettings/EditorSettings.asset +14 -0
  66. data/examples/Example2/ProjectSettings/GraphicsSettings.asset +63 -0
  67. data/examples/Example2/ProjectSettings/InputManager.asset +295 -0
  68. data/examples/Example2/ProjectSettings/NavMeshAreas.asset +89 -0
  69. data/examples/Example2/ProjectSettings/NetworkManager.asset +8 -0
  70. data/examples/Example2/ProjectSettings/Physics2DSettings.asset +36 -0
  71. data/examples/Example2/ProjectSettings/ProjectSettings.asset +591 -0
  72. data/examples/Example2/ProjectSettings/ProjectVersion.txt +1 -0
  73. data/examples/Example2/ProjectSettings/QualitySettings.asset +193 -0
  74. data/examples/Example2/ProjectSettings/TagManager.asset +43 -0
  75. data/examples/Example2/ProjectSettings/TimeManager.asset +9 -0
  76. data/examples/Example2/ProjectSettings/UnityConnectSettings.asset +34 -0
  77. data/examples/Example2/README.md +10 -0
  78. data/examples/Example2/fastlane/Fastfile +4 -0
  79. data/examples/Example2/fastlane/Pluginfile +1 -0
  80. data/exe/u3d +7 -0
  81. data/fastlane-plugin-u3d/.gitignore +10 -0
  82. data/fastlane-plugin-u3d/.licenses.json +9 -0
  83. data/fastlane-plugin-u3d/.rspec +3 -0
  84. data/fastlane-plugin-u3d/.rubocop.yml +253 -0
  85. data/fastlane-plugin-u3d/.travis.yml +4 -0
  86. data/fastlane-plugin-u3d/Gemfile +6 -0
  87. data/fastlane-plugin-u3d/LICENSE +21 -0
  88. data/fastlane-plugin-u3d/README.md +52 -0
  89. data/fastlane-plugin-u3d/Rakefile +9 -0
  90. data/fastlane-plugin-u3d/circle.yml +9 -0
  91. data/fastlane-plugin-u3d/fastlane-plugin-u3d.gemspec +31 -0
  92. data/fastlane-plugin-u3d/fastlane/Fastfile +3 -0
  93. data/fastlane-plugin-u3d/fastlane/Pluginfile +1 -0
  94. data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d.rb +38 -0
  95. data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d/actions/u3d_action.rb +80 -0
  96. data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d/helper/u3d_helper.rb +34 -0
  97. data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d/version.rb +27 -0
  98. data/fastlane-plugin-u3d/spec/spec_helper.rb +32 -0
  99. data/lib/u3d.rb +33 -0
  100. data/lib/u3d/cache.rb +120 -0
  101. data/lib/u3d/commands.rb +307 -0
  102. data/lib/u3d/commands_generator.rb +163 -0
  103. data/lib/u3d/downloader.rb +363 -0
  104. data/lib/u3d/iniparser.rb +83 -0
  105. data/lib/u3d/installer.rb +445 -0
  106. data/lib/u3d/log_analyzer.rb +221 -0
  107. data/lib/u3d/unity_version_number.rb +71 -0
  108. data/lib/u3d/unity_versions.rb +207 -0
  109. data/lib/u3d/utils.rb +121 -0
  110. data/lib/u3d/version.rb +31 -0
  111. data/lib/u3d_core.rb +30 -0
  112. data/lib/u3d_core/command_executor.rb +134 -0
  113. data/lib/u3d_core/command_runner.rb +93 -0
  114. data/lib/u3d_core/credentials.rb +116 -0
  115. data/lib/u3d_core/globals.rb +84 -0
  116. data/lib/u3d_core/helper.rb +149 -0
  117. data/lib/u3d_core/ui/disable_colors.rb +40 -0
  118. data/lib/u3d_core/ui/implementations/shell.rb +157 -0
  119. data/lib/u3d_core/ui/interface.rb +182 -0
  120. data/lib/u3d_core/ui/ui.rb +49 -0
  121. data/local_gem_install.sh +6 -0
  122. data/scripts/be +14 -0
  123. data/u3d.gemspec +41 -0
  124. metadata +388 -0
@@ -0,0 +1,121 @@
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 'net/http'
24
+ require 'fileutils'
25
+ require 'filesize'
26
+ require 'u3d_core/helper'
27
+
28
+ module U3d
29
+ # Several different utility methods
30
+ module Utils
31
+ # Regex to capture each part of a version string (0.0.0x0)
32
+ CSIDL_LOCAL_APPDATA = 0x001c
33
+ UNITY_VERSION_REGEX = /(\d+)(?:\.(\d+)(?:\.(\d+))?)?(?:(\w)(?:(\d+))?)?/
34
+
35
+ class << self
36
+ def get_ssl(url, redirect_limit: 10)
37
+ raise 'Too many redirections' if redirect_limit.zero?
38
+ response = nil
39
+ request = nil
40
+ uri = URI(url)
41
+ begin
42
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
43
+ request = Net::HTTP::Get.new uri
44
+ response = http.request request
45
+ end
46
+ rescue OpenSSL::OpenSSLError => ssl_error
47
+ UI.error 'SSL has faced an error, you may want to check our README to fix it'
48
+ raise ssl_error
49
+ end
50
+
51
+ case response
52
+ when Net::HTTPSuccess then
53
+ response.body
54
+ when Net::HTTPRedirection then
55
+ UI.verbose "Redirected to #{response['location']}"
56
+ get_ssl(response['location'], redirect_limit: redirect_limit - 1)
57
+ else raise "Request failed with status #{response.code}"
58
+ end
59
+ end
60
+
61
+ def hashfile(file_path, blocksize: 65_536)
62
+ require 'digest'
63
+ raise ArgumentError, 'Not a file' unless File.file?(file_path)
64
+ md5 = Digest::MD5.new
65
+ File.open(file_path, 'r') do |f|
66
+ md5 << f.read(blocksize) until f.eof?
67
+ end
68
+ md5.hexdigest
69
+ end
70
+
71
+ def ensure_dir(dir)
72
+ FileUtils.mkpath(dir) unless File.directory?(dir)
73
+ end
74
+
75
+ def print_progress(current, total, started_at)
76
+ ratio = [current.to_f / total, 1.0].min
77
+ percent = (ratio * 100.0).round(1)
78
+ arrow = (ratio * 20.0).floor
79
+ time_spent = Time.now.to_i - started_at
80
+ print("\r[")
81
+ print('=' * [arrow - 1, 0].max)
82
+ print('>')
83
+ print('.' * (20 - arrow))
84
+ print("] #{pretty_filesize(current)}/#{pretty_filesize(total)} (#{percent}% at #{pretty_filesize(current.to_f / time_spent)}/s) ")
85
+ end
86
+
87
+ def print_progress_nosize(current, started_at)
88
+ time_spent = Time.now.to_i - started_at
89
+ print("\r>#{pretty_filesize(current)} downloaded at #{pretty_filesize(current.to_f / time_spent)}/s) ")
90
+ end
91
+
92
+ def parse_unity_version(version)
93
+ ver = UNITY_VERSION_REGEX.match(version)
94
+ if ver.nil?
95
+ raise ArgumentError, "Version (#{version}) does not match the Unity "\
96
+ 'version format 0.0.0x0'
97
+ end
98
+ [ver[1], ver[2], ver[3], ver[4], ver[5]]
99
+ end
100
+
101
+ def windows_local_appdata
102
+ require 'win32api'
103
+
104
+ windir = ' ' * 261
105
+
106
+ getdir = Win32API.new('shell32', 'SHGetFolderPath', 'LLLLP', 'L')
107
+ result = getdir.call(0, CSIDL_LOCAL_APPDATA, 0, 0, windir)
108
+ raise "Unable to get Local Appdata directory, returned with value #{result}" unless result.zero?
109
+ windir.rstrip!
110
+ windir = File.expand_path(windir.rstrip)
111
+
112
+ return windir if Dir.exist? windir
113
+ raise "Local Appdata retrieved (#{windir}) is not correct"
114
+ end
115
+
116
+ def pretty_filesize(filesize)
117
+ Filesize.from(filesize.round.to_s + ' B').pretty
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,31 @@
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
+ VERSION = '0.9'.freeze
25
+ DESCRIPTION = 'Provides numerous tools for installing, managing and running the Unity3D game engine from command line.'.freeze
26
+ UNITY_VERSIONS_NOTE = "Unity3d uses the following version formatting: 0.0.0x0. The \'x\' can takes different values:\n"\
27
+ "\t. 'f' are the main release candidates for Unity3d\n"\
28
+ "\t. 'p' are patches fixing those releases\n"\
29
+ "\t. 'b' are the beta releases\n"\
30
+ "\t. 'a' are the alpha releases (not currently discovered)\n".freeze
31
+ end
@@ -0,0 +1,30 @@
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_core/globals'
24
+ require 'u3d_core/helper'
25
+ require 'u3d_core/credentials'
26
+ require 'u3d_core/ui/ui'
27
+ require 'u3d_core/command_executor'
28
+ require 'u3d_core/command_runner'
29
+ require 'colored'
30
+ require 'commander'
@@ -0,0 +1,134 @@
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
+
24
+ require 'u3d_core/credentials'
25
+
26
+ module U3dCore
27
+ # Executes commands and takes care of error handling and more
28
+ class CommandExecutor
29
+ class << self
30
+ # Cross-platform way of finding an executable in the $PATH. Respects the $PATHEXT, which lists
31
+ # valid file extensions for executables on Windows.
32
+ #
33
+ # which('ruby') #=> /usr/bin/ruby
34
+ #
35
+ # Derived from http://stackoverflow.com/a/5471032/3005
36
+ def which(cmd)
37
+ # PATHEXT contains the list of file extensions that Windows considers executable, semicolon separated.
38
+ # e.g. ".COM;.EXE;.BAT;.CMD"
39
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
40
+
41
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
42
+ exts.each do |ext|
43
+ cmd_path = File.expand_path("#{cmd}#{ext}", path)
44
+ return cmd_path if File.executable?(cmd_path) && !File.directory?(cmd_path)
45
+ end
46
+ end
47
+
48
+ return nil
49
+ end
50
+
51
+ # @param command [String] The command to be executed
52
+ # @param print_all [Boolean] Do we want to print out the command output while running?
53
+ # @param print_command [Boolean] Should we print the command that's being executed
54
+ # @param error [Block] A block that's called if an error occurs
55
+ # @param prefix [Array] An array containg a prefix + block which might get applied to the output
56
+ # @param loading [String] A loading string that is shown before the first output
57
+ # @param admin [Boolean] Do we need admin privilege for this command?
58
+ # @param keychain [Boolean] Should we fetch admin rights from the keychain on OSX
59
+ # @return [String] All the output as string
60
+ def execute(command: nil, print_all: false, print_command: true, error: nil, prefix: nil, loading: nil, admin: false)
61
+ print_all = true if U3dCore::Globals.verbose?
62
+ prefix ||= {}
63
+
64
+ output = []
65
+ command = command.join(' ') if command.is_a?(Array)
66
+ UI.command(command) if print_command
67
+
68
+ # this is only used to show the "Loading text"...
69
+ UI.command_output(loading) if print_all && loading
70
+
71
+ if admin
72
+ cred = U3dCore::Credentials.new(user: ENV['USER'])
73
+ if Helper.windows?
74
+ raise CredentialsError, "The command \'#{command}\' must be run in administrative shell" unless has_admin_privileges?
75
+ else
76
+ command = "sudo -k && echo #{cred.password.shellescape} | sudo -S " + command
77
+ end
78
+ UI.verbose 'Admin privileges granted for command execution'
79
+ end
80
+
81
+ begin
82
+ status = U3dCore::Runner.run(command) do |stdin, _stdout, _pid|
83
+ stdin.each do |l|
84
+ line = l.strip # strip so that \n gets removed
85
+ output << line
86
+
87
+ next unless print_all
88
+
89
+ # Prefix the current line with a string
90
+ prefix.each do |element|
91
+ line = element[:prefix] + line if element[:block] && element[:block].call(line)
92
+ end
93
+
94
+ UI.command_output(line)
95
+ end
96
+ end
97
+ raise "Exit status: #{status}".red if status.nonzero? && !status.nil?
98
+ rescue => ex
99
+ # This could happen
100
+ # * if the status is failed
101
+ # * when the environment is wrong:
102
+ # > invalid byte sequence in US-ASCII (ArgumentError)
103
+ output << ex.to_s
104
+ o = output.join("\n")
105
+ UI.verbose o
106
+ raise ex unless error
107
+ error.call(o, nil)
108
+ end
109
+ return output.join("\n")
110
+ end
111
+
112
+ def has_admin_privileges?
113
+ if Helper.windows?
114
+ begin
115
+ result = system('reg query HKU\\S-1-5-19', out: File::NULL, err: File::NULL)
116
+ rescue
117
+ result = false
118
+ end
119
+ else
120
+ credentials = U3dCore::Credentials.new(user: ENV['USER'])
121
+ begin
122
+ # FIXME: hide / show output
123
+ result = system("sudo -k && echo #{credentials.password.shellescape} | sudo -S /usr/bin/whoami")
124
+ rescue
125
+ result = false
126
+ end
127
+ credentials.forget_credentials unless result # FIXME: why?
128
+ end
129
+ # returns false if result is nil (command execution fail)
130
+ return (result ? true : false)
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,93 @@
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
+
24
+ module U3dCore
25
+ # this module is meant to be private to this lib
26
+ module Runner
27
+ class << self
28
+ def run(command, &block)
29
+ select_runner_impl.call(command, &block)
30
+ end
31
+
32
+ private
33
+
34
+ def select_runner_impl
35
+ # disable PTY by setting env variable
36
+ return U3dCore::SafePopen.method(:spawn) unless ENV['U3D_NO_TTY'].nil?
37
+ begin
38
+ require 'pty'
39
+ return U3dCore::SafePty.method(:spawn)
40
+ rescue LoadError
41
+ UI.important("No pty implementation found. Falling back to popen. Output might be buffered")
42
+ return U3dCore::SafePopen.method(:spawn)
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ # Executes commands using PTY and takes care of error handling and more
49
+ class SafePty
50
+ # Wraps the PTY.spawn() call, wait until the process completes.
51
+ # Also catch exceptions that might be raised
52
+ # See also https://www.omniref.com/ruby/gems/shell_test/0.5.0/files/lib/shell_test/shell_methods/utils.rb
53
+ def self.spawn(command, &_block)
54
+ require 'pty'
55
+ PTY.spawn(command) do |r, w, p|
56
+ begin
57
+ trap('INT') do
58
+ Process.kill("INT", p)
59
+ end
60
+ yield r, w, p
61
+ # if the process has closed, ruby might raise an exception if we try
62
+ # to do I/O on a closed stream. This behavior is platform specific
63
+ rescue Errno::EIO
64
+ ensure
65
+ begin
66
+ Process.wait p
67
+ # The process might have exited.
68
+ # This behavior is also ruby version dependent.
69
+ rescue Errno::ECHILD, PTY::ChildExited
70
+ end
71
+ end
72
+ end
73
+ $?.exitstatus
74
+ end
75
+ end
76
+
77
+ # Executes commands using popen2 and takes care of error handling and more
78
+ # Note that the executed program might buffer the output as it isn't run inside
79
+ # a pseudo terminal.
80
+ class SafePopen
81
+ # Wraps the Open3.popen2e() call, wait until the process completes.
82
+ def self.spawn(command, &_block)
83
+ require 'open3'
84
+ Open3.popen2e(command) do |r, w, p|
85
+ yield w, r, p.value.pid # note the inversion
86
+
87
+ r.close
88
+ w.close
89
+ p.value.exitstatus
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,116 @@
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
+
24
+ require 'u3d_core/helper'
25
+ require 'security'
26
+
27
+ module U3dCore
28
+ class Credentials
29
+ MAC_U3D_SERVER = 'u3d'.freeze
30
+ def initialize(user: nil, password: nil)
31
+ @user = user
32
+ @password = password
33
+ @use_keychain = U3dCore::Globals.use_keychain?
34
+ end
35
+
36
+ def user
37
+ @user ||= ENV['U3D_USER']
38
+
39
+ while @user.to_s.empty?
40
+ UI.verbose 'Username does not exist or is empty'
41
+ raise CredentialsError, 'Username missing and context is not interactive. Please check that the environment variable is correct' unless UI.interactive?
42
+ @user = UI.input 'Username for u3d:'
43
+ end
44
+
45
+ return @user
46
+ end
47
+
48
+ def password
49
+ @password ||= ENV['U3D_PASSWORD']
50
+
51
+ if Helper.mac? && @use_keychain
52
+ unless @password
53
+ UI.message 'Fetching password from keychain'
54
+ password_holder = Security::InternetPassword.find(server: MAC_U3D_SERVER)
55
+ @password = password_holder.password unless password_holder.nil?
56
+ end
57
+ end
58
+
59
+ if @password.to_s.empty?
60
+ UI.verbose 'Could not retrieve password'
61
+ if U3dCore::Globals.do_not_login?
62
+ UI.verbose 'Login disabled'
63
+ else
64
+ login
65
+ end
66
+ end
67
+
68
+ return @password
69
+ end
70
+
71
+ def login
72
+ UI.verbose 'Attempting to login'
73
+
74
+ raise CredentialsError, 'No username specified' unless user
75
+
76
+ while @password.to_s.empty?
77
+ UI.verbose 'Password does not exist or is empty'
78
+ raise CredentialsError, 'Password missing and context is not interactive. Please make sure it is correct' unless UI.interactive?
79
+ @password = UI.password "Password for #{user}:"
80
+ end
81
+
82
+ if remember_credentials
83
+ UI.success 'Credentials have been stored'
84
+ else
85
+ UI.important 'No credentials storage available'
86
+ end
87
+ end
88
+
89
+ def remember_credentials
90
+ ENV['U3D_USER'] = @user
91
+ ENV['U3D_PASSWORD'] = @password
92
+ if Helper.mac? && @use_keychain
93
+ UI.message 'Storing credentials to the keychain'
94
+ return Security::InternetPassword.add(MAC_U3D_SERVER, user, password)
95
+ end
96
+
97
+ return false
98
+ end
99
+
100
+ def forget_credentials(force: false)
101
+ @password = nil
102
+ ENV['U3D_PASSWORD'] = nil
103
+ if force || UI.interactive?
104
+ if Helper.mac? && @use_keychain && (force || UI.confirm('Remove credentials from the keychain?'))
105
+ UI.message 'Deleting credentials from the keychain'
106
+ Security::InternetPassword.delete(server: MAC_U3D_SERVER)
107
+ end
108
+ else
109
+ UI.verbose 'Keychain may store invalid credentials for u3d' if Helper.mac?
110
+ end
111
+ end
112
+ end
113
+
114
+ class CredentialsError < StandardError
115
+ end
116
+ end