├── .gitignore ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── CHANGELOG.md ├── Gemfile ├── Gemfile.lock ├── Guardfile ├── LICENSE ├── README.md ├── Rakefile ├── lib └── os.rb ├── os.gemspec └── spec ├── config └── rspec │ └── rspec_core.rb ├── linux_spec.rb ├── os_spec.rb ├── osx_spec.rb └── spec_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | ## MAC OS 2 | .DS_Store 3 | 4 | ## TEXTMATE 5 | *.tmproj 6 | tmtags 7 | 8 | ## EMACS 9 | *~ 10 | \#* 11 | .\#* 12 | 13 | ## VIM 14 | *.swp 15 | 16 | ## PROJECT::GENERAL 17 | coverage 18 | rdoc 19 | pkg 20 | 21 | ## PROJECT::SPECIFIC 22 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --format documentation 2 | --require spec_helper 3 | --color 4 | --order random 5 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: .rubocop_todo.yml 2 | 3 | inherit_gem: 4 | rubocop-lts: rubocop-lts1_8.yml 5 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2022-12-11 23:40:03 +0700 using RuboCop version 0.41.2. 4 | # The point is for the user to remove these configuration records 5 | # one by one as the offenses are removed from the code base. 6 | # Note that changes in the inspected code, or installation of new 7 | # versions of RuboCop, may require this file to be generated again. 8 | 9 | # Offense count: 1 10 | Lint/ParenthesesAsGroupedExpression: 11 | Exclude: 12 | - 'spec/os_spec.rb' 13 | 14 | # Offense count: 2 15 | Metrics/AbcSize: 16 | Max: 31 17 | 18 | # Offense count: 1 19 | # Configuration parameters: CountComments. 20 | Metrics/ClassLength: 21 | Max: 234 22 | 23 | # Offense count: 2 24 | Metrics/CyclomaticComplexity: 25 | Max: 9 26 | 27 | # Offense count: 22 28 | # Configuration parameters: AllowHeredoc, AllowURI, URISchemes. 29 | # URISchemes: http, https 30 | Metrics/LineLength: 31 | Max: 144 32 | 33 | # Offense count: 6 34 | # Configuration parameters: CountComments. 35 | Metrics/MethodLength: 36 | Max: 26 37 | 38 | # Offense count: 3 39 | Metrics/PerceivedComplexity: 40 | Max: 10 41 | 42 | # Offense count: 1 43 | # Cop supports --auto-correct. 44 | # Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. 45 | # SupportedStyles: ruby19, ruby19_no_mixed_keys, hash_rockets 46 | Style/HashSyntax: 47 | Exclude: 48 | - 'Rakefile' 49 | 50 | # Offense count: 2 51 | Style/IfInsideElse: 52 | Exclude: 53 | - 'lib/os.rb' 54 | - 'spec/os_spec.rb' 55 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file, starting with versions >= 0.9.5. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) starting with versions >= 1.0.0. 6 | 7 | ## [Unreleased] 8 | ### Added 9 | - [#53](https://github.com/rdp/os/pull/53) - Add cygwin support to `open_file_command` 10 | - [#54](https://github.com/rdp/os/pull/54) - Add `host_cpu` to documentation 11 | ### Changed 12 | - [#68](https://github.com/rdp/os/pull/68) - Upgrade RSpec to latest (including syntax) 13 | - [#71](https://github.com/rdp/os/pull/71) - Migrate `autotest` => `guard-rspec` 14 | - [#72](https://github.com/rdp/os/pull/72) - Rakefile Best Practices (& RuboCop) 15 | - [#74](https://github.com/rdp/os/pull/74) - Modernize CHANGELOG; adopt Keep a Changelog format 16 | ### Fixed 17 | - [#52](https://github.com/rdp/os/pull/52) - http => https typo 18 | - [#59](https://github.com/rdp/os/pull/59) - 🚑️ Remove circular dependency, fixes #55, #60 19 | - 20 | ### Removed 21 | 22 | ## [1.1.4] - 2021-11-07 ([tag][1.1.4t]) 23 | ### Fixed 24 | - Attempt to fix circular dependency 25 | 26 | ## [1.1.2] - 2021-11-07 ([tag][1.1.2t]) 27 | ### Fixed 28 | - Make `rss_bytes` return bytes in linux/OS X, like it always should have 29 | 30 | ## 1.1.1 - 2020-08-02 31 | ### Fixed 32 | - Fix skip blank lines in `OS#parse_os_release` 33 | 34 | ## [1.1.0] - 2020-03-31 ([tag][1.1.0t]) 35 | ### Added 36 | - Add app_config_path method 37 | - Detect underlying Docker containers method 38 | - Add Linux-specific OS#parse_os_release method 39 | ### Changed 40 | - Cleans up dev dependency specs 41 | 42 | ## 1.0.1 - 2019-04-26 43 | ### Added 44 | - `docker?` method 45 | 46 | ## [1.0.0] - 2017-02-20 ([tag][1.0.0t]) 47 | ### Added 48 | - `freebsd?` method 49 | ### Changed 50 | - other cleanup 51 | - use same version number in VERSION and os.gemspec 52 | 53 | ## 0.9.6 - 2012-02-17 54 | ### Added 55 | - add changelog, license 56 | 57 | ## 0.9.5 - 2011-12-07 58 | ### Fixed 59 | - don't count hyper thread by default windows 60 | 61 | ## 0.9.4 - 2011-08-11 62 | ## 0.9.3 - 2011-06-27 63 | ## 0.9.2 - 2011-06-08 64 | ## 0.9.1 - 2011-06-06 65 | ## 0.9.0 - 2011-06-01 66 | ## 0.8.0 - 2011-05-20 67 | ## 0.7.4 - 2011-02-25 68 | ## 0.7.2 - 2010-05-18 69 | ## 0.7.1 - 2010-01-19 - yanked 70 | ## 0.6.3 - 2010-01-16 71 | ## 0.6.1 - 2010-01-15 72 | ## 0.6.0 - 2010-01-15 73 | ## 0.5.0 - 2010-01-14 74 | ## 0.4.0 - 2010-01-13 75 | ## 0.3.3 - 2009-12-30 76 | ## 0.3.2 - 2009-12-29 77 | ## 0.3.1 - 2009-12-21 78 | ## 0.3.0 - 2009-12-17 79 | ## 0.2.0 - 2009-12-17 80 | ## 0.1.0 - 2009-12-17 81 | ## 0.0.0 - 2009-12-17 82 | 83 | [Unreleased]: https://github.com/rdp/os/compare/v1.1.4...HEAD 84 | [1.1.4]: https://github.com/rdp/os/compare/v1.1.2...v1.1.4 85 | [1.1.4t]: https://github.com/rdp/os/releases/tag/v1.1.4 86 | [1.1.2]: https://github.com/rdp/os/compare/v1.1.0...v1.1.2 87 | [1.1.2t]: https://github.com/rdp/os/releases/tag/v1.1.2 88 | [1.1.0]: https://github.com/rdp/os/compare/v1.0.0...v1.1.0 89 | [1.1.0t]: https://github.com/rdp/os/releases/tag/v1.1.0 90 | [1.0.0]: https://github.com/rdp/os/compare/5cf86de08aae24eb7a3c2f86cab5e8fa0a901a15...v1.0.0 91 | [1.0.0t]: https://github.com/rdp/os/releases/tag/v1.0.0 92 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | source 'http://rubygems.org' 3 | 4 | gemspec 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | os (1.1.4) 5 | 6 | GEM 7 | remote: http://rubygems.org/ 8 | specs: 9 | ast (2.4.2) 10 | coderay (1.1.3) 11 | diff-lcs (1.5.0) 12 | ffi (1.15.5) 13 | formatador (1.1.0) 14 | guard (2.18.0) 15 | formatador (>= 0.2.4) 16 | listen (>= 2.7, < 4.0) 17 | lumberjack (>= 1.0.12, < 2.0) 18 | nenv (~> 0.1) 19 | notiffany (~> 0.0) 20 | pry (>= 0.13.0) 21 | shellany (~> 0.0) 22 | thor (>= 0.18.1) 23 | guard-compat (1.2.1) 24 | guard-rspec (4.7.3) 25 | guard (~> 2.1) 26 | guard-compat (~> 1.1) 27 | rspec (>= 2.99.0, < 4.0) 28 | listen (3.7.1) 29 | rb-fsevent (~> 0.10, >= 0.10.3) 30 | rb-inotify (~> 0.9, >= 0.9.10) 31 | lumberjack (1.2.8) 32 | method_source (1.0.0) 33 | nenv (0.3.0) 34 | notiffany (0.1.3) 35 | nenv (~> 0.1) 36 | shellany (~> 0.0) 37 | parser (2.4.0.2) 38 | ast (~> 2.3) 39 | power_assert (2.0.2) 40 | powerpack (0.1.3) 41 | pry (0.14.1) 42 | coderay (~> 1.1) 43 | method_source (~> 1.0) 44 | rainbow (2.2.2) 45 | rake 46 | rake (10.5.0) 47 | rb-fsevent (0.11.2) 48 | rb-inotify (0.10.1) 49 | ffi (~> 1.0) 50 | rspec (3.12.0) 51 | rspec-core (~> 3.12.0) 52 | rspec-expectations (~> 3.12.0) 53 | rspec-mocks (~> 3.12.0) 54 | rspec-core (3.12.0) 55 | rspec-support (~> 3.12.0) 56 | rspec-expectations (3.12.0) 57 | diff-lcs (>= 1.2.0, < 2.0) 58 | rspec-support (~> 3.12.0) 59 | rspec-mocks (3.12.1) 60 | diff-lcs (>= 1.2.0, < 2.0) 61 | rspec-support (~> 3.12.0) 62 | rspec-support (3.12.0) 63 | rubocop (0.41.2) 64 | parser (>= 2.3.1.1, < 3.0) 65 | powerpack (~> 0.1) 66 | rainbow (>= 1.99.1, < 3.0) 67 | ruby-progressbar (~> 1.7) 68 | unicode-display_width (~> 1.0, >= 1.0.1) 69 | rubocop-lts (2.0.5) 70 | rubocop-ruby1_9 (~> 1.0.5) 71 | rubocop-ruby1_9 (1.0.5) 72 | parser (= 2.4.0.2) 73 | rubocop (= 0.41.2) 74 | ruby-progressbar (1.11.0) 75 | shellany (0.0.1) 76 | test-unit (3.5.5) 77 | power_assert 78 | thor (1.2.1) 79 | unicode-display_width (1.8.0) 80 | 81 | PLATFORMS 82 | x86_64-darwin-19 83 | 84 | DEPENDENCIES 85 | guard-rspec (~> 4.7) 86 | os! 87 | rake (~> 10.5) 88 | rspec (~> 3.12) 89 | rubocop-lts (~> 2.0) 90 | test-unit (~> 3.5) 91 | 92 | BUNDLED WITH 93 | 2.3.26 94 | -------------------------------------------------------------------------------- /Guardfile: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # More info at https://github.com/guard/guard#readme 3 | 4 | guard :rspec, :cmd => 'bundle exec rspec' do 5 | require 'guard/rspec/dsl' 6 | dsl = Guard::RSpec::Dsl.new(self) 7 | 8 | # Feel free to open issues for suggestions and improvements 9 | 10 | # RSpec files 11 | rspec = dsl.rspec 12 | watch(rspec.spec_helper) { rspec.spec_dir } 13 | watch(rspec.spec_support) { "#{rspec.spec_dir}/config" } 14 | watch(rspec.spec_files) 15 | 16 | # Ruby files 17 | ruby = dsl.ruby 18 | dsl.watch_spec_files_for(ruby.lib_files) 19 | end 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2012 Roger Pack 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The OS gem allows for some easy telling if you're on windows or not. 2 | 3 | ## Install 4 | 5 | ```shell 6 | bundle add os 7 | ``` 8 | 9 | ## Usage 10 | 11 | ```ruby 12 | require 'os' 13 | 14 | >> OS.windows? 15 | => true # or OS.doze? 16 | 17 | >> OS.bits 18 | => 32 19 | 20 | >> OS.java? 21 | => true # if you're running in jruby. Also OS.jruby? 22 | 23 | >> OS.ruby_bin 24 | => "c:\ruby18\bin\ruby.exe" # or "/usr/local/bin/ruby" or what not 25 | 26 | >> OS.posix? 27 | => false # true for linux, os x, cygwin 28 | 29 | >> OS.mac? # or OS.osx? or OS.x? 30 | => false 31 | 32 | >> OS.dev_null 33 | => "NUL" # or "/dev/null" depending on which platform 34 | 35 | >> OS.rss_bytes 36 | => 12300033 # number of rss bytes this process is using currently. Basically "total in memory footprint" (doesn't include RAM used by the process that's in swap/page file) 37 | 38 | >> OS.host_cpu 39 | => "x86_64" 40 | 41 | >> puts OS.report 42 | ==> # a yaml report of helpful values 43 | --- 44 | arch: x86_64-darwin10.6.0 45 | target_os: darwin10.6.0 46 | target_vendor: apple 47 | target_cpu: x86_64 48 | target: x86_64-apple-darwin10.6.0 49 | host_os: darwin10.6.0 50 | host_vendor: apple 51 | host_cpu: i386 52 | host: i386-apple-darwin10.6.0 53 | RUBY_PLATFORM: x86_64-darwin10.6.0 54 | 55 | >> OS.cpu_count 56 | => 2 # number of cores, doesn't include hyper-threaded cores. 57 | 58 | >> OS.open_file_command 59 | => "start" # or open on mac, or xdg-open on linux (all designed to open a file) 60 | 61 | >> OS::Underlying.windows? 62 | => true # true for cygwin or MRI, whereas OS.windows? is false for cygwin 63 | 64 | >> OS::Underlying.bsd? 65 | => true # true for OS X 66 | 67 | >> OS::Underlying.docker? 68 | => false # true if running inside a Docker container 69 | 70 | >> pp OS.parse_os_release 71 | ==> # A hash of details on the current Linux distro (or an exception if not Linux) 72 | {:NAME=>"Ubuntu", 73 | :VERSION=>"18.04.4 LTS (Bionic Beaver)", 74 | :ID=>"ubuntu", 75 | :ID_LIKE=>"debian", 76 | :PRETTY_NAME=>"Ubuntu 18.04.4 LTS", 77 | :VERSION_ID=>"18.04", 78 | :HOME_URL=>"https://www.ubuntu.com/", 79 | :SUPPORT_URL=>"https://help.ubuntu.com/", 80 | :BUG_REPORT_URL=>"https://bugs.launchpad.net/ubuntu/", 81 | :PRIVACY_POLICY_URL=> 82 | "https://www.ubuntu.com/legal/terms-and-policies/privacy-policy", 83 | :VERSION_CODENAME=>"bionic", 84 | :UBUNTU_CODENAME=>"bionic"} 85 | ``` 86 | 87 | If there are any other features you'd like, let me know, I'll do what I can to add them :) 88 | 89 | http://github.com/rdp/os for feedback et al 90 | 91 | ## Alternatives 92 | 93 | rubygems: 94 | 95 | ```ruby 96 | Gem::Platform.local 97 | Gem.ruby 98 | ``` 99 | 100 | The reason Gem::Platform.local felt wrong to me is that it treated cygwin as windows--which for most build environments, is wrong. Hence the creation of this gem. 101 | 102 | the facets gem (has a class similar to rubygems, above) 103 | 104 | ```ruby 105 | require 'facets/platform' 106 | Platform.local 107 | ``` 108 | 109 | the ["platform" gem](http://rubydoc.info/github/ffi/ffi/master/FFI/Platform), itself (a different gem) 110 | 111 | ```ruby 112 | FFI::Platform::OS 113 | ``` 114 | 115 | ## Contributing 116 | 117 | Develop locally: 118 | 119 | ```shell 120 | bundle install 121 | bundle exec guard 122 | ``` 123 | 124 | ## License 125 | 126 | License: MIT (see LICENSE file) 127 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # frozen_string_literal: true 3 | 4 | # !/usr/bin/env rake 5 | 6 | require 'bundler/gem_tasks' 7 | 8 | begin 9 | require 'rspec/core/rake_task' 10 | RSpec::Core::RakeTask.new(:spec) 11 | rescue LoadError 12 | desc 'spec task stub' 13 | task :spec do 14 | warn 'rspec is disabled' 15 | end 16 | end 17 | desc 'alias test task to spec' 18 | task :test => :spec 19 | 20 | begin 21 | require 'rubocop/rake_task' 22 | RuboCop::RakeTask.new do |task| 23 | task.options = ['-D'] # Display the name of the failing cops 24 | end 25 | rescue LoadError 26 | desc 'rubocop task stub' 27 | task :rubocop do 28 | warn 'RuboCop is disabled' 29 | end 30 | end 31 | 32 | task default: %i[test rubocop] 33 | -------------------------------------------------------------------------------- /lib/os.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'rbconfig' 3 | 4 | # a set of friendly files for determining your Ruby runtime 5 | # treats cygwin as linux 6 | # also treats IronRuby on mono as...linux 7 | class OS 8 | attr_reader :config 9 | 10 | def self.config 11 | @config ||= RbConfig::CONFIG 12 | end 13 | 14 | # true if on windows [and/or jruby] 15 | # false if on linux or cygwin on windows 16 | 17 | def self.windows? 18 | @windows ||= begin 19 | if RUBY_PLATFORM =~ /cygwin/ # i386-cygwin 20 | false 21 | elsif ENV['OS'] == 'Windows_NT' 22 | true 23 | else 24 | false 25 | end 26 | end 27 | end 28 | 29 | # true for linux, os x, cygwin 30 | def self.posix? 31 | @posix ||= 32 | begin 33 | if OS.windows? 34 | begin 35 | begin 36 | # what if we're on interix... 37 | # untested, of course 38 | Process.wait fork {} 39 | true 40 | rescue NotImplementedError, NoMethodError 41 | false 42 | end 43 | end 44 | else 45 | # assume non windows is posix 46 | true 47 | end 48 | end 49 | end 50 | 51 | # true for linux, false for windows, os x, cygwin 52 | def self.linux? 53 | if host_os =~ /linux/ 54 | true 55 | else 56 | false 57 | end 58 | end 59 | 60 | def self.freebsd? 61 | if host_os =~ /freebsd/ 62 | true 63 | else 64 | false 65 | end 66 | end 67 | 68 | def self.iron_ruby? 69 | @iron_ruby ||= begin 70 | if defined?(RUBY_ENGINE) && (RUBY_ENGINE == 'ironruby') 71 | true 72 | else 73 | false 74 | end 75 | end 76 | end 77 | 78 | def self.bits 79 | @bits ||= begin 80 | if host_cpu =~ /_64$/ || RUBY_PLATFORM =~ /x86_64/ 81 | 64 82 | elsif RUBY_PLATFORM == 'java' && ENV_JAVA['sun.arch.data.model'] # "32" or "64":http://www.ruby-forum.com/topic/202173#880613 83 | ENV_JAVA['sun.arch.data.model'].to_i 84 | elsif host_cpu == 'i386' 85 | 32 86 | elsif host_os =~ /32$/ # mingw32, mswin32 87 | 32 88 | else # cygwin only...I think 89 | if 1.size == 8 90 | 64 91 | else 92 | 32 93 | end 94 | end 95 | end 96 | end 97 | 98 | def self.java? 99 | @java ||= begin 100 | if RUBY_PLATFORM =~ /java/ 101 | true 102 | else 103 | false 104 | end 105 | end 106 | end 107 | 108 | def self.ruby_bin 109 | @ruby_exe ||= begin 110 | File.join(config['bindir'], config['ruby_install_name']) + config['EXEEXT'] 111 | end 112 | end 113 | 114 | def self.mac? 115 | @mac = begin 116 | if host_os =~ /darwin/ 117 | true 118 | else 119 | false 120 | end 121 | end 122 | end 123 | 124 | def self.osx? 125 | mac? 126 | end 127 | 128 | def self.x? 129 | mac? 130 | end 131 | 132 | # amount of memory the current process "is using", in RAM 133 | # (doesn't include any swap memory that it may be using, just that in actual RAM) 134 | # raises 'unknown' on jruby currently 135 | def self.rss_bytes 136 | # attempt to do this in a jruby friendly way 137 | if OS::Underlying.windows? 138 | # MRI, Java, IronRuby, Cygwin 139 | if OS.java? 140 | # no win32ole on 1.5.x, so leave here for compatibility...maybe for awhile :P 141 | require 'java' 142 | mem_bean = java.lang.management.ManagementFactory.getMemoryMXBean 143 | mem_bean.heap_memory_usage.used + mem_bean.non_heap_memory_usage.used 144 | else 145 | wmi = nil 146 | begin 147 | require 'win32ole' 148 | wmi = WIN32OLE.connect('winmgmts://') 149 | rescue LoadError, NoMethodError => e # NoMethod for IronRuby currently [sigh] 150 | raise 'rss unknown for this platform ' + e.to_s 151 | end 152 | processes = wmi.ExecQuery("select * from win32_process where ProcessId = #{Process.pid}") 153 | memory_used = nil 154 | # only allow for one process... 155 | processes.each do |process| 156 | raise 'multiple processes same pid?' if memory_used 157 | memory_used = process.WorkingSetSize.to_i 158 | end 159 | memory_used 160 | end 161 | elsif OS.posix? # linux [though I've heard it works in OS X] 162 | `ps -o rss= -p #{Process.pid}`.to_i * 1024 # in kiloBytes 163 | else 164 | raise 'unknown rss for this platform' 165 | end 166 | end 167 | 168 | class Underlying 169 | def self.bsd? 170 | OS.osx? 171 | end 172 | 173 | def self.windows? 174 | ENV['OS'] == 'Windows_NT' 175 | end 176 | 177 | def self.linux? 178 | OS.host_os =~ /linux/ ? true : false 179 | end 180 | 181 | def self.docker? 182 | system('grep -q docker /proc/self/cgroup') if OS.linux? 183 | end 184 | end 185 | 186 | def self.cygwin? 187 | @cygwin = begin 188 | if RUBY_PLATFORM =~ /-cygwin/ 189 | true 190 | else 191 | false 192 | end 193 | end 194 | end 195 | 196 | def self.dev_null # File::NULL in 1.9.3+ 197 | @dev_null ||= begin 198 | if OS.windows? 199 | 'NUL' 200 | else 201 | '/dev/null' 202 | end 203 | end 204 | end 205 | 206 | # provides easy way to see the relevant config entries 207 | def self.report 208 | require 'yaml' 209 | relevant_keys = [ 210 | 'arch', 211 | 'host', 212 | 'host_cpu', 213 | 'host_os', 214 | 'host_vendor', 215 | 'target', 216 | 'target_cpu', 217 | 'target_os', 218 | 'target_vendor' 219 | ] 220 | RbConfig::CONFIG.reject { |key, _val| !relevant_keys.include? key }.merge('RUBY_PLATFORM' => RUBY_PLATFORM).to_yaml 221 | end 222 | 223 | def self.cpu_count 224 | @cpu_count ||= 225 | case RUBY_PLATFORM 226 | when /darwin9/ 227 | `hwprefs cpu_count`.to_i 228 | when /darwin10/ 229 | (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i 230 | when /linux/ 231 | `cat /proc/cpuinfo | grep processor | wc -l`.to_i 232 | when /freebsd/ 233 | `sysctl -n hw.ncpu`.to_i 234 | else 235 | if RbConfig::CONFIG['host_os'] =~ /darwin/ 236 | (hwprefs_available? ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i 237 | elsif windows? 238 | # ENV counts hyper threaded...not good. 239 | # out = ENV['NUMBER_OF_PROCESSORS'].to_i 240 | require 'win32ole' 241 | wmi = WIN32OLE.connect('winmgmts://') 242 | cpu = wmi.ExecQuery('select NumberOfCores from Win32_Processor') # don't count hyper-threaded in this 243 | cpu.to_enum.first.NumberOfCores 244 | else 245 | raise 'unknown platform processor_count' 246 | end 247 | end 248 | end 249 | 250 | def self.open_file_command 251 | if OS.cygwin? 252 | 'cygstart' 253 | elsif OS.doze? 254 | 'start' 255 | elsif OS.mac? 256 | 'open' 257 | else 258 | 'xdg-open' 259 | end 260 | end 261 | 262 | def self.app_config_path(name) 263 | if OS.doze? 264 | return File.join(ENV['LOCALAPPDATA'], name) if ENV['LOCALAPPDATA'] 265 | 266 | File.join ENV['USERPROFILE'], 'Local Settings', 'Application Data', name 267 | elsif OS.mac? 268 | File.join ENV['HOME'], 'Library', 'Application Support', name 269 | else 270 | return File.join(ENV['XDG_CONFIG_HOME'], name) if ENV['XDG_CONFIG_HOME'] 271 | 272 | File.join ENV['HOME'], '.config', name 273 | end 274 | end 275 | 276 | def self.parse_os_release 277 | raise "File /etc/os-release doesn't exists or not Linux" unless OS.linux? && File.exist?('/etc/os-release') 278 | 279 | output = {} 280 | File.read('/etc/os-release').each_line do |line| 281 | parsed_line = line.chomp.tr('"', '').split('=') 282 | next if parsed_line.empty? 283 | output[parsed_line[0].to_sym] = parsed_line[1] 284 | end 285 | output 286 | end 287 | 288 | class << self 289 | alias doze? windows? # a joke name but I use it and like it :P 290 | alias jruby? java? 291 | 292 | # delegators for relevant config values 293 | ['host', 'host_cpu', 'host_os'].each do |method_name| 294 | define_method(method_name) { config[method_name] } 295 | end 296 | 297 | private 298 | 299 | def hwprefs_available? 300 | `which hwprefs` != '' 301 | end 302 | end 303 | end 304 | -------------------------------------------------------------------------------- /os.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Generated by jeweler 3 | # DO NOT EDIT THIS FILE DIRECTLY 4 | # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' 5 | # -*- encoding: utf-8 -*- 6 | # stub: os 1.1.4 ruby lib 7 | 8 | Gem::Specification.new do |s| 9 | s.name = 'os'.freeze 10 | s.version = '1.1.4' 11 | 12 | s.required_rubygems_version = Gem::Requirement.new('>= 0'.freeze) if s.respond_to? :required_rubygems_version= 13 | s.require_paths = ['lib'.freeze] 14 | s.authors = ['rdp'.freeze, 'David McCullars'.freeze] 15 | s.date = '2021-11-07' 16 | s.description = 'The OS gem allows for some useful and easy functions, like OS.windows? (=> true or false) OS.bits ( => 32 or 64) etc"'.freeze 17 | s.email = 'rogerpack2005@gmail.com'.freeze 18 | s.files = [ 19 | 'CHANGELOG.md', 20 | 'Gemfile', 21 | 'LICENSE', 22 | 'README.md', 23 | 'Rakefile', 24 | 'lib/os.rb', 25 | 'os.gemspec' 26 | ] 27 | s.homepage = 'https://github.com/rdp/os'.freeze 28 | s.licenses = ['MIT'.freeze] 29 | s.rubygems_version = '2.7.6'.freeze 30 | s.summary = "Simple and easy way to know if you're on windows or not (reliably), as well as how many bits the OS is, etc.".freeze 31 | 32 | s.add_development_dependency('guard-rspec'.freeze, ['~> 4.7']) 33 | s.add_development_dependency('rake'.freeze, ['~> 10.5']) 34 | s.add_development_dependency('rspec'.freeze, ['~> 3.12']) 35 | s.add_development_dependency('rubocop-lts'.freeze, ['~> 2.0']) # For Ruby 1.8.7 compat 36 | s.add_development_dependency('test-unit'.freeze, ['~> 3.5']) 37 | end 38 | -------------------------------------------------------------------------------- /spec/config/rspec/rspec_core.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # frozen_string_literal: true 3 | 4 | RSpec.configure do |config| 5 | # RSpec v3+ 6 | # Enable flags like --only-failures and --next-failure 7 | # config.example_status_persistence_file_path = '.rspec_status' 8 | 9 | # RSpec v3+ 10 | # Disable RSpec exposing methods globally on `Module` and `main` 11 | # config.disable_monkey_patching! 12 | 13 | config.expect_with :rspec do |c| 14 | c.syntax = :expect 15 | end 16 | 17 | config.expect_with :test_unit 18 | end 19 | -------------------------------------------------------------------------------- /spec/linux_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | describe 'For Linux, (Ubuntu, Ubuntu 10.04 LTS) ' do 3 | before(:each) do 4 | allow(ENV).to receive(:[]).with('OS') 5 | ## Having difficulties finding a stub for RUBY_PLATFORM 6 | # Looking into something like: http://stackoverflow.com/questions/1698335/can-i-use-rspec-mocks-to-stub-out-version-constants 7 | # For now, simply using RbConfig::CONFIG 8 | # Kernel.stub!(:const_get).with('RUBY_PLATFORM').and_return("i686-linux") 9 | allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('linux_gnu') 10 | allow(RbConfig::CONFIG).to receive(:[]).with('host_cpu').and_return('i686') 11 | end 12 | 13 | describe OS do 14 | subject { OS } # class, not instance 15 | 16 | it { is_expected.to be_linux } 17 | it { is_expected.to be_posix } 18 | 19 | it { is_expected.not_to be_mac } 20 | it { is_expected.not_to be_osx } 21 | it { is_expected.not_to be_windows } 22 | end 23 | 24 | describe OS::Underlying do 25 | subject { OS::Underlying } # class, not instance 26 | 27 | it { is_expected.to be_linux } 28 | 29 | it { is_expected.not_to be_bsd } 30 | it { is_expected.not_to be_windows } 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /spec/os_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | describe 'OS' do 3 | it 'identifies whether windows? or posix?' do 4 | if ENV['OS'] == 'Windows_NT' 5 | if RUBY_PLATFORM =~ /cygwin/ 6 | assert OS::Underlying.windows? 7 | assert OS.windows? == false 8 | assert OS.posix? == true 9 | else 10 | assert OS.windows? == true 11 | assert OS.doze? == true 12 | assert OS.posix? == false # can fail in error at times...I guess because some other spec has reset ENV on us... 13 | end 14 | assert OS::Underlying.windows? 15 | elsif [/linux/, /darwin/].any? { |posix_pattern| (RbConfig::CONFIG['host_os'] =~ posix_pattern) || RUBY_PLATFORM =~ posix_pattern } 16 | assert OS.windows? == false 17 | assert OS.posix? == true 18 | assert !OS::Underlying.windows? 19 | else 20 | skip 'create test' 21 | end 22 | end 23 | 24 | it 'has a bits method' do 25 | if RUBY_PLATFORM =~ /mingw32/ 26 | assert OS.bits == 32 27 | elsif RUBY_PLATFORM =~ /64/ # linux... 28 | assert OS.bits == 64 29 | elsif RUBY_PLATFORM =~ /i686/ 30 | assert OS.bits == 32 31 | elsif RUBY_PLATFORM =~ /java/ && RbConfig::CONFIG['host_os'] =~ /32$/ 32 | assert OS.bits == 32 33 | elsif RUBY_PLATFORM =~ /java/ && RbConfig::CONFIG['host_cpu'] =~ /i386/ 34 | assert OS.bits == 32 35 | elsif RUBY_PLATFORM =~ /i386/ 36 | assert OS.bits == 32 37 | else 38 | skip 'os bits not tested!' + RUBY_PLATFORM + ' ' + RbConfig::CONFIG['host_os'] 39 | end 40 | end 41 | 42 | it 'should have an iron_ruby method' do 43 | if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'ironruby' 44 | assert OS.iron_ruby? == true 45 | else 46 | assert OS.iron_ruby? == false 47 | end 48 | end 49 | 50 | it "should know if you're on java" do 51 | if RUBY_PLATFORM == 'java' 52 | assert OS.java? == true # must be [true | false] 53 | else 54 | assert OS.java? == false 55 | end 56 | end 57 | 58 | it 'should have a ruby_bin method' do 59 | if OS.windows? 60 | assert OS.ruby_bin.include?('.exe') 61 | if OS.iron_ruby? 62 | assert OS.ruby_bin.include?('ir.exe') 63 | else 64 | assert OS.ruby_bin.include?('ruby.exe') 65 | end 66 | else 67 | assert OS.ruby_bin.include?('ruby') && OS.ruby_bin.include?('/') 68 | end 69 | 70 | if OS.java? 71 | assert OS.ruby_bin.include?('jruby') # I think 72 | end 73 | end 74 | 75 | it 'should have a cygwin? method' do 76 | if RUBY_PLATFORM =~ /cygwin/ 77 | assert OS.cygwin? == true 78 | else 79 | assert OS.cygwin? == false 80 | end 81 | end 82 | 83 | it 'should have a functional mac? method' do 84 | if RUBY_PLATFORM =~ /darwin/ 85 | assert OS.mac? == true 86 | else 87 | if OS.host_os == 'darwin' 88 | assert OS.mac? == true 89 | else 90 | assert OS.mac? == false 91 | end 92 | end 93 | end 94 | 95 | it 'should have a way to get rss_bytes on each platform' do 96 | bytes = OS.rss_bytes 97 | assert bytes > 0 # should always be true 98 | assert bytes.is_a?(Numeric) # don't want strings from any platform... 99 | end 100 | 101 | it 'should tell you what the right /dev/null is' do 102 | if OS.windows? 103 | expect(OS.dev_null).to eq('NUL') 104 | else 105 | expect(OS.dev_null).to eq('/dev/null') 106 | end 107 | end 108 | 109 | it 'should have a jruby method' do 110 | if defined?(RUBY_DESCRIPTION) && RUBY_DESCRIPTION =~ /^(jruby|java)/ 111 | assert OS.jruby? 112 | else 113 | assert !OS.jruby? 114 | end 115 | end 116 | 117 | it 'has working cpu count method' do 118 | cpu_count = OS.cpu_count 119 | assert cpu_count >= 1 120 | # CPU count is usually either a power of 2 or an even number. 121 | assert ((cpu_count & (cpu_count - 1)) == 0) || cpu_count.even? 122 | end 123 | 124 | it 'has working cpu count method with no env. variable' do 125 | OS.instance_variable_set(:@cpu_count, nil) # reset it 126 | if OS.windows? 127 | ENV.delete('NUMBER_OF_PROCESSORS') 128 | assert OS.cpu_count >= 1 129 | end 130 | end 131 | 132 | it 'should have a start/open command helper' do 133 | if OS.doze? 134 | assert OS.open_file_command == 'start' 135 | elsif OS.mac? 136 | assert OS.open_file_command == 'open' 137 | else 138 | assert OS.open_file_command == 'xdg-open' 139 | end 140 | end 141 | 142 | it 'should provide a path to directory for application config' do 143 | allow(ENV).to receive(:[]) 144 | home = '/home/user' 145 | 146 | if OS.mac? 147 | allow(ENV).to receive(:[]).with('HOME').and_return(home) 148 | assert OS.app_config_path('appname') == "#{home}/Library/Application Support/appname" 149 | elsif OS.doze? 150 | # TODO 151 | else 152 | allow(ENV).to receive(:[]).with('HOME').and_return(home) 153 | assert OS.app_config_path('appname') == "#{home}/.config/appname" 154 | 155 | allow(ENV).to receive(:[]).with('XDG_CONFIG_HOME').and_return("#{home}/.config") 156 | assert OS.app_config_path('appname') == "#{home}/.config/appname" 157 | end 158 | end 159 | 160 | it 'should have a freebsd? method' do 161 | if OS.host_os =~ /freebsd/ 162 | assert OS.freebsd? == true 163 | else 164 | assert OS.freebsd? == false 165 | end 166 | end 167 | end 168 | 169 | describe OS, 'provides access to to underlying config values' do 170 | describe '#config, supplys the CONFIG hash' do 171 | subject { OS.config } 172 | 173 | specify { expect(subject).to be_a(Hash) } 174 | 175 | it "should supply 'host_cpu'" do 176 | expect(subject['host_cpu']).to eq(RbConfig::CONFIG['host_cpu']) 177 | end 178 | 179 | it "should supply 'host_os'" do 180 | expect(subject['host_os']).to eq(RbConfig::CONFIG['host_os']) 181 | end 182 | end 183 | 184 | describe 'by providing a delegate method for relevant keys in RbConfig::CONFIG' do 185 | ['host', 'host_cpu', 'host_os'].sort.each do |config_key| 186 | it "should delegate '#{config_key}'" do 187 | expected = "TEST #{config_key}" 188 | expect(RbConfig::CONFIG).to receive(:[]).with(config_key).and_return(expected) 189 | 190 | expect(OS.send(config_key)).to eq(expected) 191 | end 192 | end 193 | end 194 | end 195 | -------------------------------------------------------------------------------- /spec/osx_spec.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | describe 'For OSX (Snow Leopard, 10.6),' do 3 | before(:each) do 4 | allow(ENV).to receive(:[]).with('OS').and_return(nil) 5 | # Issues stubbing RUBY_PLATFORM, using RbConfig instead. 6 | # Kernel.stub!(:RUBY_PLATFORM => "x86_64-darwin10.6") 7 | allow(RbConfig::CONFIG).to receive(:[]).with('host_os').and_return('darwin10.6.0') 8 | allow(RbConfig::CONFIG).to receive(:[]).with('host_cpu').and_return('i386') 9 | end 10 | 11 | describe OS do 12 | subject { OS } # class, not instance 13 | 14 | it { is_expected.to be_mac } 15 | it { is_expected.to be_x } # OS.x? 16 | it { is_expected.to be_osx } 17 | it { is_expected.to be_posix } 18 | 19 | it { is_expected.not_to be_windows } 20 | end 21 | 22 | describe OS::Underlying do 23 | subject { OS::Underlying } # class, not instance 24 | 25 | it { is_expected.to be_bsd } 26 | it { is_expected.not_to be_windows } 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # Third Party Libraries 3 | require 'rspec' 4 | 5 | # This gem 6 | require 'os' 7 | 8 | # Library Configs 9 | 10 | # RSpec Configs 11 | require 'config/rspec/rspec_core' 12 | --------------------------------------------------------------------------------