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.
251 252 253 254 |
# File 'lib/aspera/environment.rb', line 251 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.
249 250 251 |
# File 'lib/aspera/environment.rb', line 249 def url_method @url_method end |
Class Method Details
.architecture ⇒ Object
normalized architecture name see constants: OS_* and CPU_*
71 72 73 |
# File 'lib/aspera/environment.rb', line 71 def architecture return "#{os}-#{cpu}" end |
.cpu ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/aspera/environment.rb', line 54 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.
218 219 220 221 222 223 224 |
# File 'lib/aspera/environment.rb', line 218 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
90 91 92 |
# File 'lib/aspera/environment.rb', line 90 def empty_binding return Kernel.binding end |
.exe_file(name = '') ⇒ Object
executable file extension for current OS
76 77 78 79 |
# File 'lib/aspera/environment.rb', line 76 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
83 84 85 86 87 |
# File 'lib/aspera/environment.rb', line 83 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
104 105 106 107 108 109 110 111 |
# File 'lib/aspera/environment.rb', line 104 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
239 240 241 242 243 244 245 246 247 |
# File 'lib/aspera/environment.rb', line 239 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
228 229 230 231 232 233 234 235 236 |
# File 'lib/aspera/environment.rb', line 228 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
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/aspera/environment.rb', line 40 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
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/aspera/environment.rb', line 196 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
36 37 38 |
# File 'lib/aspera/environment.rb', line 36 def ruby_version return RbConfig::CONFIG['RUBY_PROGRAM_VERSION'] end |
.secure_capture(exec:, args: [], **opts) ⇒ Object
Execute process and capture stdout
166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/aspera/environment.rb', line 166 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
95 96 97 |
# File 'lib/aspera/environment.rb', line 95 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
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/aspera/environment.rb', line 144 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
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/aspera/environment.rb', line 121 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.
213 214 215 |
# File 'lib/aspera/environment.rb', line 213 def terminal? $stdout.tty? end |
.write_file_restricted(path, force: false, mode: nil) ⇒ Object
Write content to a file, with restricted access
183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/aspera/environment.rb', line 183 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
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/aspera/environment.rb', line 268 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
259 260 261 262 |
# File 'lib/aspera/environment.rb', line 259 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 |