Class: Aspera::Environment
- Inherits:
-
Object
- Object
- Aspera::Environment
- Includes:
- Singleton
- Defined in:
- lib/aspera/environment.rb
Overview
detect OS, architecture, and specific stuff
Constant Summary collapse
- USER_INTERFACES =
%i[text graphical].freeze
- OS_WINDOWS =
:windows
- OS_MACOS =
:osx
- OS_LINUX =
:linux
- OS_AIX =
:aix
- OS_LIST =
[OS_WINDOWS, OS_MACOS, OS_LINUX, OS_AIX].freeze
- CPU_X86_64 =
:x86_64
- CPU_ARM64 =
:arm64
- CPU_PPC64 =
:ppc64
- CPU_PPC64LE =
:ppc64le
- CPU_S390 =
:s390
- CPU_LIST =
[CPU_X86_64, CPU_ARM64, CPU_PPC64, CPU_PPC64LE, CPU_S390].freeze
- BITS_PER_BYTE =
8
- MEBI =
1024 * 1024
- BYTES_PER_MEBIBIT =
MEBI / BITS_PER_BYTE
Instance Attribute Summary collapse
-
#url_method ⇒ Object
Returns the value of attribute url_method.
Class Method Summary collapse
-
.architecture ⇒ Object
normalized architecture name see constants: OS_* and CPU_*.
- .cpu ⇒ Object
-
.default_gui_mode ⇒ Object
:text or :graphical depending on the environment.
-
.empty_binding ⇒ Object
empty variable binding for secure eval.
-
.exe_file(name = '') ⇒ Object
executable file extension for current OS.
-
.fix_home ⇒ Object
on Windows, the env var %USERPROFILE% provides the path to user’s home more reliably than %HOMEDRIVE%%HOMEPATH% so, tell Ruby the right way.
-
.log_spawn(exec:, args: nil, env: nil) ⇒ String
Generate log line for external program with arguments.
-
.open_editor(file_path) ⇒ Object
open a file in an editor.
-
.open_uri_graphical(uri) ⇒ Object
open a URI in a graphical browser command must be non blocking.
- .os ⇒ Object
-
.restrict_file_access(path, mode: nil) ⇒ Object
restrict access to a file or folder to user only.
- .ruby_version ⇒ Object
-
.secure_capture(exec:, args: [], **opts) ⇒ Object
Execute process and capture stdout.
-
.secure_eval(code, file, line) ⇒ Object
secure execution of Ruby code.
-
.secure_execute(exec:, args: nil, env: nil, **system_args) ⇒ String
start process and wait for completion.
-
.secure_spawn(exec:, args: nil, env: nil, **options) ⇒ String
Start process in background caller can call Process.wait on returned value.
-
.terminal? ⇒ Boolean
True if we are in a terminal.
-
.write_file_restricted(path, force: false, mode: nil) ⇒ Object
Write content to a file, with restricted access.
Instance Method Summary collapse
-
#initialize ⇒ Environment
constructor
A new instance of Environment.
-
#open_uri(the_url) ⇒ Object
Allows a user to open a Url if method is “text”, then URL is displayed on terminal if method is “graphical”, then the URL will be opened with the default browser.
- #terminal_supports_unicode? ⇒ Boolean
Constructor Details
#initialize ⇒ Environment
Returns a new instance of Environment.
250 251 252 253 |
# File 'lib/aspera/environment.rb', line 250 def initialize @url_method = self.class.default_gui_mode @terminal_supports_unicode = nil end |
Instance Attribute Details
#url_method ⇒ Object
Returns the value of attribute url_method.
248 249 250 |
# File 'lib/aspera/environment.rb', line 248 def url_method @url_method end |
Class Method Details
.architecture ⇒ Object
normalized architecture name see constants: OS_* and CPU_*
70 71 72 |
# File 'lib/aspera/environment.rb', line 70 def architecture return "#{os}-#{cpu}" end |
.cpu ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/aspera/environment.rb', line 53 def cpu case RbConfig::CONFIG['host_cpu'] when /x86_64/, /x64/ return CPU_X86_64 when /powerpc/, /ppc64/ return CPU_PPC64LE if os.eql?(OS_LINUX) return CPU_PPC64 when /s390/ return CPU_S390 when /arm/, /aarch64/ return CPU_ARM64 else Aspera.error_unexpected_value(RbConfig::CONFIG['host_cpu']){'host_cpu'} end end |
.default_gui_mode ⇒ Object
Returns :text or :graphical depending on the environment.
217 218 219 220 221 222 223 |
# File 'lib/aspera/environment.rb', line 217 def default_gui_mode # assume not remotely connected on macos and windows return :graphical if [Environment::OS_WINDOWS, Environment::OS_MACOS].include?(Environment.os) # unix family return :graphical if ENV.key?('DISPLAY') && !ENV['DISPLAY'].empty? return :text end |
.empty_binding ⇒ Object
empty variable binding for secure eval
89 90 91 |
# File 'lib/aspera/environment.rb', line 89 def empty_binding return Kernel.binding end |
.exe_file(name = '') ⇒ Object
executable file extension for current OS
75 76 77 78 |
# File 'lib/aspera/environment.rb', line 75 def exe_file(name='') return "#{name}.exe" if os.eql?(OS_WINDOWS) return name end |
.fix_home ⇒ Object
on Windows, the env var %USERPROFILE% provides the path to user’s home more reliably than %HOMEDRIVE%%HOMEPATH% so, tell Ruby the right way
82 83 84 85 86 |
# File 'lib/aspera/environment.rb', line 82 def fix_home return unless os.eql?(OS_WINDOWS) && ENV.key?('USERPROFILE') && Dir.exist?(ENV.fetch('USERPROFILE', nil)) ENV['HOME'] = ENV.fetch('USERPROFILE', nil) Log.log.debug{"Windows: set HOME to USERPROFILE: #{Dir.home}"} end |
.log_spawn(exec:, args: nil, env: nil) ⇒ String
Generate log line for external program with arguments
103 104 105 106 107 108 109 110 |
# File 'lib/aspera/environment.rb', line 103 def log_spawn(exec:, args: nil, env: nil) [ 'execute:'.red, env&.map{|k, v| "#{k}=#{Shellwords.shellescape(v)}"}, Shellwords.shellescape(exec), args&.map{|a|Shellwords.shellescape(a)} ].compact.flatten.join(' ') end |
.open_editor(file_path) ⇒ Object
open a file in an editor
238 239 240 241 242 243 244 245 246 |
# File 'lib/aspera/environment.rb', line 238 def open_editor(file_path) if ENV.key?('EDITOR') system(ENV['EDITOR'], file_path.to_s) elsif Environment.os.eql?(Environment::OS_WINDOWS) system('notepad.exe', %Q{"#{file_path}"}) else open_uri_graphical(file_path.to_s) end end |
.open_uri_graphical(uri) ⇒ Object
open a URI in a graphical browser command must be non blocking
227 228 229 230 231 232 233 234 235 |
# File 'lib/aspera/environment.rb', line 227 def open_uri_graphical(uri) case Environment.os when Environment::OS_MACOS then return system('open', uri.to_s) when Environment::OS_WINDOWS then return system('start', 'explorer', %Q{"#{uri}"}) when Environment::OS_LINUX then return system('xdg-open', uri.to_s) else raise "no graphical open method for #{Environment.os}" end end |
.os ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/aspera/environment.rb', line 39 def os case RbConfig::CONFIG['host_os'] when /mswin/, /msys/, /mingw/, /cygwin/, /bccwin/, /wince/, /emc/ return OS_WINDOWS when /darwin/, /mac os/ return OS_MACOS when /linux/ return OS_LINUX when /aix/ return OS_AIX else Aspera.error_unexpected_value(RbConfig::CONFIG['host_os']){'host_os'} end end |
.restrict_file_access(path, mode: nil) ⇒ Object
restrict access to a file or folder to user only
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/aspera/environment.rb', line 195 def restrict_file_access(path, mode: nil) if mode.nil? # or FileUtils ? if File.file?(path) mode = 0o600 elsif File.directory?(path) mode = 0o700 else Log.log.debug{"No restriction can be set for #{path}"} end end File.chmod(mode, path) unless mode.nil? rescue => e Log.log.warn(e.) end |
.ruby_version ⇒ Object
35 36 37 |
# File 'lib/aspera/environment.rb', line 35 def ruby_version return RbConfig::CONFIG['RUBY_PROGRAM_VERSION'] end |
.secure_capture(exec:, args: [], **opts) ⇒ Object
Execute process and capture stdout
165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/aspera/environment.rb', line 165 def secure_capture(exec:, args: [], **opts) Aspera.assert_type(exec, String) Aspera.assert_type(args, Array) Aspera.assert_type(opts, Hash) Log.log.debug {log_spawn(exec: exec, args: args)} stdout, stderr, status = Open3.capture3(exec, *args, **opts) Log.log.debug{"status=#{status}, stderr=#{stderr}"} Log.log.trace1{"stdout=#{stdout}"} raise "process failed: #{status.exitstatus} : #{stderr}" unless status.success? return stdout end |
.secure_eval(code, file, line) ⇒ Object
secure execution of Ruby code
94 95 96 |
# File 'lib/aspera/environment.rb', line 94 def secure_eval(code, file, line) Kernel.send('lave'.reverse, code, empty_binding, file, line) end |
.secure_execute(exec:, args: nil, env: nil, **system_args) ⇒ String
start process and wait for completion
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/aspera/environment.rb', line 143 def secure_execute(exec:, args: nil, env: nil, **system_args) Aspera.assert_type(exec, String) Aspera.assert_type(args, Array) unless args.nil? Aspera.assert_type(env, Hash) unless env.nil? Log.log.debug {log_spawn(exec: exec, args: args, env: env)} # start in separate process spawn_args = [] spawn_args.push(env) unless env.nil? # ensure no shell expansion spawn_args.push([exec, exec]) spawn_args.concat(args) unless args.nil? kwargs = {exception: true} kwargs.merge!(system_args) Kernel.system(*spawn_args, **kwargs) nil end |
.secure_spawn(exec:, args: nil, env: nil, **options) ⇒ String
Start process in background caller can call Process.wait on returned value
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/aspera/environment.rb', line 120 def secure_spawn(exec:, args: nil, env: nil, **) Aspera.assert_type(exec, String) Aspera.assert_type(args, Array) unless args.nil? Aspera.assert_type(env, Hash) unless env.nil? Aspera.assert_type(, Hash) unless .nil? Log.log.debug {log_spawn(exec: exec, args: args, env: env)} # start ascp in separate process spawn_args = [] spawn_args.push(env) unless env.nil? spawn_args.push([exec, exec]) spawn_args.concat(args) unless args.nil? opts = {close_others: true} opts.merge!() unless .nil? ascp_pid = Process.spawn(*spawn_args, **opts) Log.log.debug{"pid: #{ascp_pid}"} return ascp_pid end |
.terminal? ⇒ Boolean
Returns true if we are in a terminal.
212 213 214 |
# File 'lib/aspera/environment.rb', line 212 def terminal? $stdout.tty? end |
.write_file_restricted(path, force: false, mode: nil) ⇒ Object
Write content to a file, with restricted access
182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/aspera/environment.rb', line 182 def write_file_restricted(path, force: false, mode: nil) Aspera.assert(block_given?, exception_class: Aspera::InternalError) if force || !File.exist?(path) # Windows may give error File.unlink(path) rescue nil # content provided by block File.write(path, yield) restrict_file_access(path, mode: mode) end return path end |
Instance Method Details
#open_uri(the_url) ⇒ Object
Allows a user to open a Url if method is “text”, then URL is displayed on terminal if method is “graphical”, then the URL will be opened with the default browser. this is non blocking
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 |
# File 'lib/aspera/environment.rb', line 267 def open_uri(the_url) case @url_method when :graphical self.class.open_uri_graphical(the_url) when :text case the_url.to_s when /^http/ puts "USER ACTION: please enter this url in a browser:\n#{the_url.to_s.red}\n" else puts "USER ACTION: open this:\n#{the_url.to_s.red}\n" end else raise StandardError, "unsupported url open method: #{@url_method}" end end |
#terminal_supports_unicode? ⇒ Boolean
258 259 260 261 |
# File 'lib/aspera/environment.rb', line 258 def terminal_supports_unicode? @terminal_supports_unicode = self.class.terminal? && %w(LC_ALL LC_CTYPE LANG).any?{|var|ENV[var]&.include?('UTF-8')} if @terminal_supports_unicode.nil? return @terminal_supports_unicode end |