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.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.licenses.json +19 -0
- data/.rspec +1 -0
- data/.rubocop.yml +43 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +98 -0
- data/LICENSE +21 -0
- data/LICENSE.fastlane +22 -0
- data/LOG_RULES.md +170 -0
- data/README.md +72 -0
- data/Rakefile +28 -0
- data/TODO.md +15 -0
- data/build.sh +5 -0
- data/config/log_rules.json +230 -0
- data/examples/Example1/.gitignore +19 -0
- data/examples/Example1/Assets/Editor.meta +9 -0
- data/examples/Example1/Assets/Editor/EditorRun.cs +23 -0
- data/examples/Example1/Assets/Editor/EditorRun.cs.meta +12 -0
- data/examples/Example1/Assets/Editor/FileSystemUtil.cs +26 -0
- data/examples/Example1/Assets/Editor/FileSystemUtil.cs.meta +12 -0
- data/examples/Example1/Assets/Scene1.unity +264 -0
- data/examples/Example1/Assets/Scene1.unity.meta +8 -0
- data/examples/Example1/Gemfile +8 -0
- data/examples/Example1/Gemfile.lock +165 -0
- data/examples/Example1/ProjectSettings/AudioManager.asset +16 -0
- data/examples/Example1/ProjectSettings/ClusterInputManager.asset +6 -0
- data/examples/Example1/ProjectSettings/DynamicsManager.asset +18 -0
- data/examples/Example1/ProjectSettings/EditorBuildSettings.asset +7 -0
- data/examples/Example1/ProjectSettings/EditorSettings.asset +14 -0
- data/examples/Example1/ProjectSettings/GraphicsSettings.asset +61 -0
- data/examples/Example1/ProjectSettings/InputManager.asset +295 -0
- data/examples/Example1/ProjectSettings/NavMeshAreas.asset +89 -0
- data/examples/Example1/ProjectSettings/NetworkManager.asset +8 -0
- data/examples/Example1/ProjectSettings/Physics2DSettings.asset +35 -0
- data/examples/Example1/ProjectSettings/ProjectSettings.asset +591 -0
- data/examples/Example1/ProjectSettings/ProjectVersion.txt +1 -0
- data/examples/Example1/ProjectSettings/QualitySettings.asset +180 -0
- data/examples/Example1/ProjectSettings/TagManager.asset +43 -0
- data/examples/Example1/ProjectSettings/TimeManager.asset +9 -0
- data/examples/Example1/ProjectSettings/UnityConnectSettings.asset +32 -0
- data/examples/Example1/README.md +5 -0
- data/examples/Example1/Rakefile +5 -0
- data/examples/Example1/fastlane/Fastfile +4 -0
- data/examples/Example1/fastlane/Pluginfile +1 -0
- data/examples/Example1/run.sh +1 -0
- data/examples/Example2/.gitignore +20 -0
- data/examples/Example2/Assets/Editor.meta +9 -0
- data/examples/Example2/Assets/Editor/EditorRun.cs +33 -0
- data/examples/Example2/Assets/Editor/EditorRun.cs.meta +12 -0
- data/examples/Example2/Assets/Editor/PostprocessBuildPlayer.cs +92 -0
- data/examples/Example2/Assets/Editor/PostprocessBuildPlayer.cs.meta +8 -0
- data/examples/Example2/Assets/Editor/PostprocessBuildPlayer_log.sh +31 -0
- data/examples/Example2/Assets/Editor/PostprocessBuildPlayer_log.sh.meta +8 -0
- data/examples/Example2/Assets/Editor/SimpleBuildSetup.cs +20 -0
- data/examples/Example2/Assets/Editor/SimpleBuildSetup.cs.meta +12 -0
- data/examples/Example2/Assets/Scene.unity +278 -0
- data/examples/Example2/Assets/Scene.unity.meta +8 -0
- data/examples/Example2/Gemfile +8 -0
- data/examples/Example2/Gemfile.lock +165 -0
- data/examples/Example2/ProjectSettings/AudioManager.asset +17 -0
- data/examples/Example2/ProjectSettings/ClusterInputManager.asset +6 -0
- data/examples/Example2/ProjectSettings/DynamicsManager.asset +19 -0
- data/examples/Example2/ProjectSettings/EditorBuildSettings.asset +10 -0
- data/examples/Example2/ProjectSettings/EditorSettings.asset +14 -0
- data/examples/Example2/ProjectSettings/GraphicsSettings.asset +63 -0
- data/examples/Example2/ProjectSettings/InputManager.asset +295 -0
- data/examples/Example2/ProjectSettings/NavMeshAreas.asset +89 -0
- data/examples/Example2/ProjectSettings/NetworkManager.asset +8 -0
- data/examples/Example2/ProjectSettings/Physics2DSettings.asset +36 -0
- data/examples/Example2/ProjectSettings/ProjectSettings.asset +591 -0
- data/examples/Example2/ProjectSettings/ProjectVersion.txt +1 -0
- data/examples/Example2/ProjectSettings/QualitySettings.asset +193 -0
- data/examples/Example2/ProjectSettings/TagManager.asset +43 -0
- data/examples/Example2/ProjectSettings/TimeManager.asset +9 -0
- data/examples/Example2/ProjectSettings/UnityConnectSettings.asset +34 -0
- data/examples/Example2/README.md +10 -0
- data/examples/Example2/fastlane/Fastfile +4 -0
- data/examples/Example2/fastlane/Pluginfile +1 -0
- data/exe/u3d +7 -0
- data/fastlane-plugin-u3d/.gitignore +10 -0
- data/fastlane-plugin-u3d/.licenses.json +9 -0
- data/fastlane-plugin-u3d/.rspec +3 -0
- data/fastlane-plugin-u3d/.rubocop.yml +253 -0
- data/fastlane-plugin-u3d/.travis.yml +4 -0
- data/fastlane-plugin-u3d/Gemfile +6 -0
- data/fastlane-plugin-u3d/LICENSE +21 -0
- data/fastlane-plugin-u3d/README.md +52 -0
- data/fastlane-plugin-u3d/Rakefile +9 -0
- data/fastlane-plugin-u3d/circle.yml +9 -0
- data/fastlane-plugin-u3d/fastlane-plugin-u3d.gemspec +31 -0
- data/fastlane-plugin-u3d/fastlane/Fastfile +3 -0
- data/fastlane-plugin-u3d/fastlane/Pluginfile +1 -0
- data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d.rb +38 -0
- data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d/actions/u3d_action.rb +80 -0
- data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d/helper/u3d_helper.rb +34 -0
- data/fastlane-plugin-u3d/lib/fastlane/plugin/u3d/version.rb +27 -0
- data/fastlane-plugin-u3d/spec/spec_helper.rb +32 -0
- data/lib/u3d.rb +33 -0
- data/lib/u3d/cache.rb +120 -0
- data/lib/u3d/commands.rb +307 -0
- data/lib/u3d/commands_generator.rb +163 -0
- data/lib/u3d/downloader.rb +363 -0
- data/lib/u3d/iniparser.rb +83 -0
- data/lib/u3d/installer.rb +445 -0
- data/lib/u3d/log_analyzer.rb +221 -0
- data/lib/u3d/unity_version_number.rb +71 -0
- data/lib/u3d/unity_versions.rb +207 -0
- data/lib/u3d/utils.rb +121 -0
- data/lib/u3d/version.rb +31 -0
- data/lib/u3d_core.rb +30 -0
- data/lib/u3d_core/command_executor.rb +134 -0
- data/lib/u3d_core/command_runner.rb +93 -0
- data/lib/u3d_core/credentials.rb +116 -0
- data/lib/u3d_core/globals.rb +84 -0
- data/lib/u3d_core/helper.rb +149 -0
- data/lib/u3d_core/ui/disable_colors.rb +40 -0
- data/lib/u3d_core/ui/implementations/shell.rb +157 -0
- data/lib/u3d_core/ui/interface.rb +182 -0
- data/lib/u3d_core/ui/ui.rb +49 -0
- data/local_gem_install.sh +6 -0
- data/scripts/be +14 -0
- data/u3d.gemspec +41 -0
- metadata +388 -0
data/lib/u3d/utils.rb
ADDED
@@ -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
|
data/lib/u3d/version.rb
ADDED
@@ -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
|
data/lib/u3d_core.rb
ADDED
@@ -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
|