image_optim 0.31.3 → 0.32.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: edffa5fea26babe4654e681a829753b7df3d5d80a158a7b3d2974e97b46a49a5
4
- data.tar.gz: 467cdc261c726ac97b5252b6b93507e4fac6e5d3804bd7fc17636ba32a6f565a
3
+ metadata.gz: ef1f30c74ae2a4479ec6d68f006313ae236cd92e3f8338a15619a74d5fbb2dc7
4
+ data.tar.gz: 3db0340fc04da059048f162c4b4e35870213f3ce40a6f8af896059ffd2703cbe
5
5
  SHA512:
6
- metadata.gz: '0379e12d0d4ef8dd0af9e047a728bc9acf0177136b83b9b4aced834238067d0ab3248350bc1813cc76b33eaa3fc5751032a72c14f03a81d3dad9eed61abb0b99'
7
- data.tar.gz: 68489aa06564d6f8555adf409c23454fb4b9d57fa74117cd9b1174787ad65bc56a101a8cce9e455ba0e3474f1a1b7e8c8b9707549768be1bb3a94a063c200721
6
+ metadata.gz: 2fdbf6c9cb715760ce38200157ddaa9142e5ec83611813572b475893c24c50f18983207bf268cd9f73d98689d7fb28e3703a8ab9633d5c28bad2c9e003a9f667
7
+ data.tar.gz: d9826620e1554b8cac570b79995636c8abd652f66318bf8f1bf498156756250919bd48374038c0db99554c9e2ce1ba1f2af194715c73c41ff9afea97e4cc33eb
@@ -0,0 +1,8 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: daily
7
+ cooldown:
8
+ default-days: 7
@@ -0,0 +1,60 @@
1
+ name: build-test-containers
2
+ on:
3
+ workflow_dispatch:
4
+ schedule:
5
+ - cron: 11 2 13 * *
6
+ jobs:
7
+ base:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v6
11
+ - uses: docker/login-action@v4
12
+ with:
13
+ registry: ghcr.io
14
+ username: ${{ github.actor }}
15
+ password: ${{ secrets.GITHUB_TOKEN }}
16
+ - run:
17
+ docker build
18
+ -f Dockerfile.test
19
+ --target ruby-build
20
+ -t ghcr.io/toy/image_optim.test:ruby-build
21
+ --push
22
+ .
23
+
24
+ test-images:
25
+ needs: base
26
+ runs-on: ubuntu-latest
27
+ strategy:
28
+ matrix:
29
+ ruby:
30
+ - '1.9'
31
+ - '2.0'
32
+ - '2.1'
33
+ - '2.2'
34
+ - '2.3'
35
+ - '2.4'
36
+ - '2.5'
37
+ - '2.6'
38
+ - '2.7'
39
+ - '3.0'
40
+ - '3.1'
41
+ - '3.2'
42
+ - '3.3'
43
+ - '3.4'
44
+ - '4.0'
45
+ fail-fast: false
46
+ steps:
47
+ - uses: actions/checkout@v6
48
+ - uses: docker/login-action@v4
49
+ with:
50
+ registry: ghcr.io
51
+ username: ${{ github.actor }}
52
+ password: ${{ secrets.GITHUB_TOKEN }}
53
+ - run:
54
+ docker build
55
+ -f Dockerfile.test
56
+ --target test
57
+ --build-arg "RUBY_VERSION=${{ matrix.ruby }}"
58
+ -t "ghcr.io/toy/image_optim.test:${{ matrix.ruby }}"
59
+ --push
60
+ .
@@ -6,53 +6,76 @@ on:
6
6
  - cron: 45 4 * * 2
7
7
  jobs:
8
8
  check:
9
- runs-on: ubuntu-latest
9
+ runs-on: ubuntu-22.04
10
10
  strategy:
11
11
  matrix:
12
12
  ruby:
13
- - '2.0'
14
- - '2.1'
15
- - '2.2'
16
- - '2.3'
17
- - '2.4'
18
- - '2.5'
19
- - '2.6'
20
13
  - '2.7'
21
14
  - '3.0'
22
15
  - '3.1'
23
16
  - '3.2'
24
- - jruby-9.3
17
+ - '3.3'
18
+ - '3.4'
19
+ - '4.0'
25
20
  - jruby-9.4
21
+ - jruby-10.1
26
22
  fail-fast: false
27
23
  steps:
28
- - uses: actions/checkout@v3
24
+ - uses: actions/checkout@v6
29
25
  - uses: ruby/setup-ruby@v1
30
26
  with:
31
27
  ruby-version: "${{ matrix.ruby }}"
32
28
  bundler-cache: true
33
- - run: sudo npm install -g svgo
34
- - run: curl -L "https://github.com/shssoichiro/oxipng/releases/download/v4.0.3/oxipng-4.0.3-x86_64-unknown-linux-musl.tar.gz" | tar -xz -C /usr/local/bin --strip-components 1 --wildcards '*oxipng'
29
+ - run: npm install -g svgo
35
30
  - run: bundle exec image_optim --info
36
31
  - run: bundle exec rspec
32
+ containers:
33
+ runs-on: ubuntu-latest
34
+ container: ${{ matrix.container }}
35
+ strategy:
36
+ matrix:
37
+ container:
38
+ - debian:bullseye
39
+ - debian:bookworm
40
+ # - alpine
41
+ fail-fast: false
42
+ steps:
43
+ - uses: actions/checkout@v6
44
+ - run: |
45
+ if command -v apt-get &> /dev/null; then
46
+ apt-get update
47
+ apt-get -y install make gcc git curl imagemagick ruby ruby-dev rubygems
48
+ fi
49
+ - run: |
50
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
51
+ . ~/.nvm/nvm.sh
52
+ nvm install 20
53
+ echo "PATH=$PATH" >> $GITHUB_ENV
54
+ - run: npm install -g svgo
55
+ - run: gem install bundler || gem install bundler --version '< 2.4'
56
+ - run: bundle install
57
+ - run: bundle exec bin/image_optim --info
58
+ - run: bundle exec rspec
37
59
  windows:
38
60
  runs-on: windows-latest
39
61
  strategy:
40
62
  matrix:
41
63
  ruby:
42
- - '2.6'
43
64
  - '2.7'
44
65
  - '3.0'
45
66
  - '3.1'
46
67
  - '3.2'
68
+ - '3.3'
69
+ - '3.4'
70
+ - '4.0'
47
71
  fail-fast: false
48
- continue-on-error: ${{ matrix.ruby == '3.2' }}
49
72
  steps:
50
- - uses: actions/checkout@v3
73
+ - uses: actions/checkout@v6
51
74
  - uses: ruby/setup-ruby@v1
52
75
  with:
53
76
  ruby-version: "${{ matrix.ruby }}"
54
77
  bundler-cache: true
55
- - uses: actions/cache@v2
78
+ - uses: actions/cache@v5
56
79
  with:
57
80
  path: "$HOME/bin"
58
81
  key: ${{ runner.os }}
@@ -67,18 +90,12 @@ jobs:
67
90
  - run: npm install -g svgo
68
91
  - run: bundle exec image_optim --info
69
92
  - run: bundle exec rspec
70
- coverage:
93
+ update_worker_options_in_readme:
71
94
  runs-on: ubuntu-latest
72
- env:
73
- CC_TEST_REPORTER_ID: b433c6540d220a2da0663670c9b260806bafdb3a43c6f22b2e81bfb1f87b12fe
74
95
  steps:
75
- - uses: actions/checkout@v3
96
+ - uses: actions/checkout@v6
76
97
  - uses: ruby/setup-ruby@v1
77
98
  with:
78
- ruby-version: '3'
99
+ ruby-version: '4'
79
100
  bundler-cache: true
80
- - run: sudo npm install -g svgo
81
- - run: curl -L "https://github.com/shssoichiro/oxipng/releases/download/v4.0.3/oxipng-4.0.3-x86_64-unknown-linux-musl.tar.gz" | tar -xz -C /usr/local/bin --strip-components 1 --wildcards '*oxipng'
82
- - uses: paambaati/codeclimate-action@v2.7.5
83
- with:
84
- coverageCommand: bundle exec rspec
101
+ - run: script/update_worker_options_in_readme -n
@@ -8,9 +8,9 @@ jobs:
8
8
  rubocop:
9
9
  runs-on: ubuntu-latest
10
10
  steps:
11
- - uses: actions/checkout@v3
11
+ - uses: actions/checkout@v6
12
12
  - uses: ruby/setup-ruby@v1
13
13
  with:
14
- ruby-version: '3'
14
+ ruby-version: '4'
15
15
  bundler-cache: true
16
16
  - run: bundle exec rubocop
data/.rubocop.yml CHANGED
@@ -67,6 +67,8 @@ Metrics/BlockLength:
67
67
  - 'spec/**/*.rb'
68
68
 
69
69
  Metrics/ClassLength:
70
+ Exclude:
71
+ - 'lib/image_optim.rb'
70
72
  Max: 150
71
73
 
72
74
  Metrics/CyclomaticComplexity:
@@ -88,6 +90,9 @@ Style/AccessorGrouping:
88
90
  Style/Alias:
89
91
  EnforcedStyle: prefer_alias_method
90
92
 
93
+ Style/ArgumentsForwarding:
94
+ Enabled: false
95
+
91
96
  Style/DoubleNegation:
92
97
  Enabled: false
93
98
 
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  ## unreleased
4
4
 
5
+ ## v0.32.0 (2026-05-28)
6
+
7
+ * Use `Etc.nprocessors` for default number of threads with fallback to manual way [@toy](https://github.com/toy)
8
+ * Correct environment variable to specify `jpeg-recompress` location [@toy](https://github.com/toy)
9
+ * Added --benchmark, to compare performance of each tool [#217](https://github.com/toy/image_optim/issues/217) [#218](https://github.com/toy/image_optim/pull/218) [@gurgeous](https://github.com/gurgeous)
10
+ * Don't require presence of `git` in gemspec [@toy](https://github.com/toy)
11
+ * Add a basic check for names of enabled and disabled svgo plugins [@toy](https://github.com/toy)
12
+ * Add support for enabling/disabling plugins in svgo 2.x, 3.x, 4.x [#191](https://github.com/toy/image_optim/issues/191) [#224](https://github.com/toy/image_optim/pull/224) [@tomhughes](https://github.com/tomhughes)
13
+
14
+ ## v0.31.4 (2024-11-19)
15
+
16
+ * Added `--svgo-allow-lossy` and `--svgo-precision` options to use svgo in lossy mode. This sets svgo `--precision`, which can result in substantially smaller svgs (see [#211](https://github.com/toy/image_optim/issues/211) for some experiments). Lower values are more lossy. 3 is the default, but many SVGs will work well even with 0 or 1. Like all worker specific lossy flags, this is also enabled with `--allow-lossy`. [#210](https://github.com/toy/image_optim/issues/210) [#211](https://github.com/toy/image_optim/issues/211) [@gurgeous](https://github.com/gurgeous)
17
+
5
18
  ## v0.31.3 (2023-02-17)
6
19
 
7
20
  * Support Psych4/Ruby 3.1 changes to use safe_yaml methods by default [#203](https://github.com/toy/image_optim/issues/203) [#204](https://github.com/toy/image_optim/pull/204) [@oscillot](https://github.com/oscillot) [@toy](https://github.com/toy)
data/Dockerfile.test ADDED
@@ -0,0 +1,46 @@
1
+ FROM node:slim AS ruby-build
2
+
3
+ RUN npm install -g svgo
4
+
5
+ RUN apt-get update \
6
+ && apt-get install -y --no-install-recommends \
7
+ build-essential \
8
+ ca-certificates \
9
+ curl \
10
+ git \
11
+ imagemagick \
12
+ libffi-dev \
13
+ libgmp-dev \
14
+ librsvg2-bin \
15
+ libssl-dev \
16
+ libyaml-dev \
17
+ rustc \
18
+ tini \
19
+ zlib1g-dev \
20
+ && rm -rf /var/lib/apt/lists/*
21
+
22
+ RUN git clone https://github.com/rbenv/ruby-build.git /ruby-build \
23
+ && cd /ruby-build \
24
+ && git checkout $(git describe --tags "$(git rev-list --tags --max-count=1)") \
25
+ && /ruby-build/install.sh \
26
+ && rm -r /ruby-build
27
+
28
+ FROM ghcr.io/toy/image_optim.test:ruby-build AS test
29
+
30
+ ARG RUBY_VERSION
31
+ RUN FULL_VERSION=$(ruby-build --definitions | perl -e '$p=shift; while(<>){$l=$_ if index($_,$p)==0} print $l' "${RUBY_VERSION}.") \
32
+ && RUBY_CONFIGURE_OPTS=--disable-install-doc ruby-build --verbose "$FULL_VERSION" /usr/local
33
+
34
+ ENV BUNDLE_SILENCE_ROOT_WARNING=1
35
+ COPY script/update-rubygems-n-bundler ./script/
36
+ RUN script/update-rubygems-n-bundler
37
+
38
+ WORKDIR /gem
39
+ # silence warnings about not being in git directory
40
+ RUN git init
41
+
42
+ COPY Gemfile *.gemspec ./
43
+ RUN bundle install \
44
+ && rm Gemfile Gemfile.lock *.gemspec
45
+
46
+ ENTRYPOINT ["/usr/bin/tini", "--"]
data/Gemfile CHANGED
@@ -4,6 +4,10 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
+ if RUBY_VERSION >= '4'
8
+ gem 'logger'
9
+ end
10
+
7
11
  if ENV['CC_TEST_REPORTER_ID']
8
12
  group :test do
9
13
  gem 'simplecov'
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2023 Ivan Kuchin
1
+ Copyright (c) 2012-2026 Ivan Kuchin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -1,9 +1,7 @@
1
1
  [![Gem Version](https://img.shields.io/gem/v/image_optim?logo=rubygems)](https://rubygems.org/gems/image_optim)
2
- [![Build Status](https://img.shields.io/github/actions/workflow/status/toy/image_optim/check.yml?logo=github)](https://github.com/toy/image_optim/actions/workflows/check.yml)
2
+ [![Check](https://img.shields.io/github/actions/workflow/status/toy/image_optim/check.yml?label=check&logo=github)](https://github.com/toy/image_optim/actions/workflows/check.yml)
3
3
  [![Rubocop](https://img.shields.io/github/actions/workflow/status/toy/image_optim/rubocop.yml?label=rubocop&logo=rubocop)](https://github.com/toy/image_optim/actions/workflows/rubocop.yml)
4
4
  [![CodeQL](https://img.shields.io/github/actions/workflow/status/toy/image_optim/codeql.yml?label=codeql&logo=github)](https://github.com/toy/image_optim/actions/workflows/codeql.yml)
5
- [![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
6
- [![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
7
5
  [![Depfu](https://img.shields.io/depfu/toy/image_optim)](https://depfu.com/github/toy/image_optim)
8
6
  [![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master)](https://inch-ci.org/github/toy/image_optim)
9
7
 
@@ -62,7 +60,7 @@ With version:
62
60
 
63
61
  <!---<update-version>-->
64
62
  ```ruby
65
- gem 'image_optim', '~> 0.31'
63
+ gem 'image_optim', '~> 0.32'
66
64
  ```
67
65
  <!---</update-version>-->
68
66
 
@@ -90,7 +88,7 @@ Simplest way for `image_optim` to locate binaries is to install them in common l
90
88
 
91
89
  If you cannot install to common location, then install to custom one and add it to `PATH`.
92
90
 
93
- Specify custom bin location using `XXX_BIN` environment variable (`JPEGOPTIM_BIN`, `OPTIPNG_BIN`, …).
91
+ Specify custom bin location using `XXX_BIN` environment variable (`JPEGOPTIM_BIN`, `OPTIPNG_BIN`, `JPEG_RECOMPRESS_BIN`, …).
94
92
 
95
93
  Besides permanently setting environment variables in `~/.profile`, `~/.bash_profile`, `~/.bashrc`, `~/.zshrc`, … they can be set:
96
94
 
@@ -303,6 +301,29 @@ optipng:
303
301
 
304
302
  `image_optim` uses standard ruby library for creating temporary files. Temporary directory can be changed using one of `TMPDIR`, `TMP` or `TEMP` environment variables.
305
303
 
304
+ ### Benchmark
305
+
306
+ Run with `--benchmark` to compare the performance of each individual tool on your images:
307
+
308
+ ```sh
309
+ image_optim --benchmark=isolated -r /tmp/corpus/
310
+ ```
311
+
312
+ ```
313
+ benchmarking: 100.0% (elapsed: 3.9m)
314
+
315
+ BENCHMARK RESULTS
316
+
317
+ name files elapsed kb saved kb/s
318
+ -------- ----- ------- -------- -------
319
+ oxipng 50 8.906 1867.253 209.664
320
+ pngquant 50 1.980 214.597 108.386
321
+ pngcrush 50 22.529 1753.704 77.841
322
+ optipng 50 142.940 1641.101 11.481
323
+ advpng 50 137.753 962.549 6.987
324
+ pngout 50 426.706 444.679 1.042
325
+ ```
326
+
306
327
  ## Options
307
328
 
308
329
  * `:nice` — Nice level, priority of all used tools with higher value meaning lower priority, in range `-20..19`, negative values can be set only if run by root user *(defaults to `10`)*
@@ -375,6 +396,8 @@ Worker has no options
375
396
  ### svgo:
376
397
  * `:disable_plugins` — List of plugins to disable *(defaults to `[]`)*
377
398
  * `:enable_plugins` — List of plugins to enable *(defaults to `[]`)*
399
+ * `:allow_lossy` — Allow precision option *(defaults to `false`)*
400
+ * `:precision` — Number of digits in the fractional part `0`..`20`, ignored in default/lossless mode *(defaults to `3`)*
378
401
 
379
402
  <!---</worker-options>-->
380
403
 
@@ -390,4 +413,4 @@ In separate file [CHANGELOG.markdown](CHANGELOG.markdown).
390
413
 
391
414
  ## Copyright
392
415
 
393
- Copyright (c) 2012-2023 Ivan Kuchin. See [LICENSE.txt](LICENSE.txt) for details.
416
+ Copyright (c) 2012-2026 Ivan Kuchin. See [LICENSE.txt](LICENSE.txt) for details.
data/image_optim.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'image_optim'
5
- s.version = '0.31.3'
5
+ s.version = '0.32.0'
6
6
  s.summary = %q{Command line tool and ruby interface to optimize (lossless compress, optionally lossy) jpeg, png, gif and svg images using external utilities (advpng, gifsicle, jhead, jpeg-recompress, jpegoptim, jpegrescan, jpegtran, optipng, oxipng, pngcrush, pngout, pngquant, svgo)}
7
7
  s.homepage = "https://github.com/toy/#{s.name}"
8
8
  s.authors = ['Ivan Kuchin']
@@ -15,11 +15,21 @@ Gem::Specification.new do |s|
15
15
  'changelog_uri' => "https://github.com/toy/#{s.name}/blob/master/CHANGELOG.markdown",
16
16
  'documentation_uri' => "https://www.rubydoc.info/gems/#{s.name}/#{s.version}",
17
17
  'source_code_uri' => "https://github.com/toy/#{s.name}",
18
- }
18
+ } if s.respond_to?(:metadata=)
19
19
 
20
- s.files = `git ls-files`.split("\n")
21
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.files = Dir[*%w[
21
+ .gitignore
22
+ .pre-commit-hooks.yaml
23
+ .rubocop.yml
24
+ Dockerfile.test
25
+ Gemfile
26
+ LICENSE.txt
27
+ *.markdown
28
+ *.gemspec
29
+ {.github,bin,lib,script,spec,vendor}/**/*
30
+ ]].reject(&File.method(:directory?))
31
+ s.test_files = Dir['spec/**/*'].reject(&File.method(:directory?))
32
+ s.executables = Dir['bin/*'].map(&File.method(:basename))
23
33
  s.require_paths = %w[lib]
24
34
 
25
35
  s.post_install_message = <<-EOF
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ImageOptim
4
+ # Benchmark result for one worker+src
5
+ class BenchmarkResult
6
+ attr_reader :bytes, :elapsed, :worker
7
+
8
+ def initialize(src, dst, elapsed, worker)
9
+ @bytes = bytes_saved(src, dst)
10
+ @elapsed = elapsed
11
+ @worker = worker.class.bin_sym.to_s
12
+ end
13
+
14
+ private
15
+
16
+ def bytes_saved(src, dst)
17
+ src, dst = src.size, dst.size
18
+ return 0 if dst == 0 # failure
19
+ return 0 if dst > src # the file got bigger
20
+
21
+ src - dst
22
+ end
23
+ end
24
+ end
@@ -108,7 +108,7 @@ class ImageOptim
108
108
  # Check path in XXX_BIN to exist, be a file and be executable and symlink to
109
109
  # dir as name
110
110
  def symlink_custom_bin!(name)
111
- env_name = "#{name}_bin".upcase
111
+ env_name = "#{name.to_s.tr('-', '_').upcase}_BIN"
112
112
  path = ENV.fetch(env_name, nil)
113
113
  return unless path
114
114
 
@@ -5,12 +5,13 @@ require 'image_optim/configuration_error'
5
5
  require 'image_optim/hash_helpers'
6
6
  require 'image_optim/worker'
7
7
  require 'image_optim/cmd'
8
+ require 'etc'
8
9
  require 'set'
9
10
  require 'yaml'
10
11
 
11
12
  class ImageOptim
12
13
  # Read, merge and parse configuration
13
- class Config
14
+ class Config # rubocop:disable Metrics/ClassLength
14
15
  include OptionHelpers
15
16
 
16
17
  # Global config path at `$XDG_CONFIG_HOME/image_optim.yml` (by default
@@ -134,7 +135,7 @@ class ImageOptim
134
135
  end
135
136
 
136
137
  # Verbose mode, converted to boolean
137
- def verbose
138
+ def verbose # rubocop:disable Naming/PredicateMethod
138
139
  !!get!(:verbose)
139
140
  end
140
141
 
@@ -164,7 +165,7 @@ class ImageOptim
164
165
  end
165
166
 
166
167
  # Allow lossy workers and optimizations, converted to boolean
167
- def allow_lossy
168
+ def allow_lossy # rubocop:disable Naming/PredicateMethod
168
169
  !!get!(:allow_lossy)
169
170
  end
170
171
 
@@ -173,7 +174,7 @@ class ImageOptim
173
174
  dir unless dir.nil? || dir.empty?
174
175
  end
175
176
 
176
- def cache_worker_digests
177
+ def cache_worker_digests # rubocop:disable Naming/PredicateMethod
177
178
  !!get!(:cache_worker_digests)
178
179
  end
179
180
 
@@ -205,9 +206,17 @@ class ImageOptim
205
206
 
206
207
  private
207
208
 
208
- # http://stackoverflow.com/a/6420817
209
209
  def processor_count
210
- @processor_count ||= case host_os = RbConfig::CONFIG['host_os']
210
+ @processor_count ||= if Etc.respond_to?(:nprocessors)
211
+ Etc.nprocessors
212
+ else
213
+ processor_count_manual
214
+ end
215
+ end
216
+
217
+ # http://stackoverflow.com/a/6420817
218
+ def processor_count_manual
219
+ case host_os = RbConfig::CONFIG['host_os']
211
220
  when /darwin9/
212
221
  Cmd.capture 'hwprefs cpu_count'
213
222
  when /darwin/