image_optim 0.28.0 → 0.31.1
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 +4 -4
- data/.github/workflows/check.yml +89 -0
- data/.pre-commit-hooks.yaml +9 -0
- data/.rubocop.yml +6 -3
- data/CHANGELOG.markdown +20 -0
- data/CONTRIBUTING.markdown +1 -1
- data/Gemfile +1 -7
- data/LICENSE.txt +1 -1
- data/README.markdown +18 -9
- data/Vagrantfile +1 -1
- data/image_optim.gemspec +6 -3
- data/lib/image_optim/bin_resolver/bin.rb +9 -9
- data/lib/image_optim/cache.rb +6 -0
- data/lib/image_optim/cmd.rb +45 -6
- data/lib/image_optim/config.rb +11 -5
- data/lib/image_optim/elapsed_time.rb +26 -0
- data/lib/image_optim/errors.rb +9 -0
- data/lib/image_optim/path.rb +1 -1
- data/lib/image_optim/runner/option_parser.rb +21 -17
- data/lib/image_optim/runner.rb +1 -1
- data/lib/image_optim/timer.rb +25 -0
- data/lib/image_optim/worker/advpng.rb +7 -7
- data/lib/image_optim/worker/gifsicle.rb +11 -11
- data/lib/image_optim/worker/jhead.rb +2 -2
- data/lib/image_optim/worker/jpegoptim.rb +11 -11
- data/lib/image_optim/worker/jpegrecompress.rb +6 -6
- data/lib/image_optim/worker/jpegtran.rb +4 -4
- data/lib/image_optim/worker/optipng.rb +7 -7
- data/lib/image_optim/worker/oxipng.rb +53 -0
- data/lib/image_optim/worker/pngcrush.rb +6 -6
- data/lib/image_optim/worker/pngout.rb +7 -7
- data/lib/image_optim/worker/pngquant.rb +9 -9
- data/lib/image_optim/worker/svgo.rb +2 -2
- data/lib/image_optim/worker.rb +32 -29
- data/lib/image_optim.rb +16 -10
- data/script/update_worker_options_in_readme +1 -1
- data/script/worker_analysis +16 -18
- data/spec/image_optim/bin_resolver_spec.rb +5 -5
- data/spec/image_optim/cache_path_spec.rb +7 -10
- data/spec/image_optim/cache_spec.rb +7 -7
- data/spec/image_optim/cmd_spec.rb +64 -6
- data/spec/image_optim/config_spec.rb +36 -20
- data/spec/image_optim/elapsed_time_spec.rb +14 -0
- data/spec/image_optim/handler_spec.rb +1 -1
- data/spec/image_optim/hash_helpers_spec.rb +18 -18
- data/spec/image_optim/option_definition_spec.rb +6 -6
- data/spec/image_optim/path_spec.rb +8 -11
- data/spec/image_optim/runner/option_parser_spec.rb +4 -4
- data/spec/image_optim/timer_spec.rb +32 -0
- data/spec/image_optim/worker/jpegrecompress_spec.rb +2 -2
- data/spec/image_optim/worker/optipng_spec.rb +11 -11
- data/spec/image_optim/worker/oxipng_spec.rb +89 -0
- data/spec/image_optim/worker/pngquant_spec.rb +5 -5
- data/spec/image_optim/worker_spec.rb +17 -17
- data/spec/image_optim_spec.rb +47 -10
- data/spec/images/invisiblepixels/generate +1 -1
- data/spec/spec_helper.rb +24 -21
- metadata +35 -11
- data/.appveyor.yml +0 -53
- data/.travis.yml +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 481b027ab78658543ea138ff4d7547a609dca8b31eea02f8cb003318f10c67eb
|
4
|
+
data.tar.gz: e11f9f69a28e6a3e7a0028579cb36e78b5dd1457943a884f8071d6de17e7031e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 961044af3b8ef65acbdc6bbce6a278e8aefe246a1ea53a6eceea5bb025f02c7adeecf457843fd2244a5bc21fa0f303094a16f4947cda41fc9ac7372dbcce5f46
|
7
|
+
data.tar.gz: ea8dcb08f8fffd1aad10506bdb3ab2bdf0043f30d08b68e2cb0d2195562492d6477619e3bdcf830a9bec9ead04adfe36b195b136fba61a1e7d4f96835c61c854
|
@@ -0,0 +1,89 @@
|
|
1
|
+
name: check
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
pull_request:
|
5
|
+
schedule:
|
6
|
+
- cron: 45 4 * * 2
|
7
|
+
jobs:
|
8
|
+
check:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
ruby:
|
13
|
+
- '2.0'
|
14
|
+
- '2.1'
|
15
|
+
- '2.2'
|
16
|
+
- '2.3'
|
17
|
+
- '2.4'
|
18
|
+
- '2.5'
|
19
|
+
- '2.6'
|
20
|
+
- '2.7'
|
21
|
+
- '3.0'
|
22
|
+
- jruby-9.2
|
23
|
+
fail-fast: false
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v2
|
26
|
+
- uses: ruby/setup-ruby@v1
|
27
|
+
with:
|
28
|
+
ruby-version: "${{ matrix.ruby }}"
|
29
|
+
bundler-cache: true
|
30
|
+
- run: sudo npm install -g svgo
|
31
|
+
- run: curl -L "https://www.jonof.id.au/files/kenutils/pngout-20200115-linux.tar.gz" | sudo tar -xz -C /usr/local/bin --strip-components 2 --wildcards '*/amd64/pngout'
|
32
|
+
- 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'
|
33
|
+
- run: bundle exec image_optim --info
|
34
|
+
- run: bundle exec rspec
|
35
|
+
windows:
|
36
|
+
runs-on: windows-latest
|
37
|
+
strategy:
|
38
|
+
matrix:
|
39
|
+
ruby:
|
40
|
+
- '2.6'
|
41
|
+
- '2.7'
|
42
|
+
- '3.0'
|
43
|
+
fail-fast: false
|
44
|
+
steps:
|
45
|
+
- uses: actions/checkout@v2
|
46
|
+
- uses: ruby/setup-ruby@v1
|
47
|
+
with:
|
48
|
+
ruby-version: "${{ matrix.ruby }}"
|
49
|
+
bundler-cache: true
|
50
|
+
- uses: actions/cache@v2
|
51
|
+
with:
|
52
|
+
path: "$HOME/bin"
|
53
|
+
key: ${{ runner.os }}
|
54
|
+
- run: |
|
55
|
+
mkdir "$HOME/bin"
|
56
|
+
git fetch origin windows-binaries
|
57
|
+
git --work-tree="$HOME/bin" checkout origin/windows-binaries -- '*.exe'
|
58
|
+
echo "$HOME/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
59
|
+
- run: |
|
60
|
+
choco install --no-progress imagemagick
|
61
|
+
ls C:\'Program Files'\ImageMagick* | % FullName | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
62
|
+
- run: npm install -g svgo
|
63
|
+
- run: bundle exec image_optim --info
|
64
|
+
- run: bundle exec rspec
|
65
|
+
coverage:
|
66
|
+
runs-on: ubuntu-latest
|
67
|
+
env:
|
68
|
+
CC_TEST_REPORTER_ID: b433c6540d220a2da0663670c9b260806bafdb3a43c6f22b2e81bfb1f87b12fe
|
69
|
+
steps:
|
70
|
+
- uses: actions/checkout@v2
|
71
|
+
- uses: ruby/setup-ruby@v1
|
72
|
+
with:
|
73
|
+
ruby-version: '3.0'
|
74
|
+
bundler-cache: true
|
75
|
+
- run: sudo npm install -g svgo
|
76
|
+
- run: curl -L "https://www.jonof.id.au/files/kenutils/pngout-20200115-linux.tar.gz" | sudo tar -xz -C /usr/local/bin --strip-components 2 --wildcards '*/amd64/pngout'
|
77
|
+
- 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'
|
78
|
+
- uses: paambaati/codeclimate-action@v2.7.5
|
79
|
+
with:
|
80
|
+
coverageCommand: bundle exec rspec
|
81
|
+
rubocop:
|
82
|
+
runs-on: ubuntu-latest
|
83
|
+
steps:
|
84
|
+
- uses: actions/checkout@v2
|
85
|
+
- uses: ruby/setup-ruby@v1
|
86
|
+
with:
|
87
|
+
ruby-version: '3.0'
|
88
|
+
bundler-cache: true
|
89
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -103,12 +103,12 @@ Style/ExpandPathArguments:
|
|
103
103
|
Style/FormatStringToken:
|
104
104
|
Enabled: false
|
105
105
|
|
106
|
+
Style/HashConversion:
|
107
|
+
Enabled: false
|
108
|
+
|
106
109
|
Style/HashEachMethods:
|
107
110
|
Enabled: true
|
108
111
|
|
109
|
-
Style/HashSyntax:
|
110
|
-
EnforcedStyle: hash_rockets
|
111
|
-
|
112
112
|
Style/HashTransformKeys:
|
113
113
|
Enabled: false
|
114
114
|
|
@@ -127,6 +127,9 @@ Style/OptionalBooleanParameter:
|
|
127
127
|
Style/ParallelAssignment:
|
128
128
|
Enabled: false
|
129
129
|
|
130
|
+
Style/RedundantBegin:
|
131
|
+
Enabled: false
|
132
|
+
|
130
133
|
Style/RescueStandardError:
|
131
134
|
EnforcedStyle: implicit
|
132
135
|
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,26 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.31.1 (2021-10-21)
|
6
|
+
|
7
|
+
* Allow image_size 3 [@toy](https://github.com/toy)
|
8
|
+
|
9
|
+
## v0.31.0 (2021-10-03)
|
10
|
+
|
11
|
+
* Add support for Oxipng [#167](https://github.com/toy/image_optim/issues/167) [#190](https://github.com/toy/image_optim/pull/190) [@oblakeerickson](https://github.com/oblakeerickson)
|
12
|
+
* Fix `TypeError: can't convert ImageOptim::Timer into Float` with Ruby 3 [#194](https://github.com/toy/image_optim/pull/194) [@yahonda](https://github.com/yahonda)
|
13
|
+
|
14
|
+
## v0.30.0 (2021-05-11)
|
15
|
+
|
16
|
+
* Add `timeout` option to restrict maximum time spent on every image [#21](https://github.com/toy/image_optim/issues/21) [#148](https://github.com/toy/image_optim/pull/148) [#149](https://github.com/toy/image_optim/pull/149) [#162](https://github.com/toy/image_optim/pull/162) [#184](https://github.com/toy/image_optim/pull/184) [#189](https://github.com/toy/image_optim/pull/189) [@tgxworld](https://github.com/tgxworld) [@oblakeerickson](https://github.com/oblakeerickson) [@toy](https://github.com/toy)
|
17
|
+
|
18
|
+
## v0.29.0 (2021-04-28)
|
19
|
+
|
20
|
+
* Require at least ruby 1.9.3 [@toy](https://github.com/toy)
|
21
|
+
* Add support for use as [pre-commit](https://pre-commit.com/) hook [#192](https://github.com/toy/image_optim/pull/192) [@proinsias](https://github.com/proinsias)
|
22
|
+
* Fix `Path#copy_metadata` by rescuing also `Errno::EACCES` as it is done in `fileutils` [#187](https://github.com/toy/image_optim/issues/187) [@toy](https://github.com/toy)
|
23
|
+
* More precise regular expression for capturing svgo version [@toy](https://github.com/toy)
|
24
|
+
|
5
25
|
## v0.28.0 (2020-12-18)
|
6
26
|
|
7
27
|
* Fix and update list of markers in jpegoptim worker: allow to pass `com` instead of incorrect `comments` and add missing `xmp` and `none` [#188](https://github.com/toy/image_optim/issues/188) [@toy](https://github.com/toy)
|
data/CONTRIBUTING.markdown
CHANGED
@@ -11,4 +11,4 @@
|
|
11
11
|
* Rebase on master and squash commits to logical units
|
12
12
|
* Push your branch: `git push origin awesome-changes`
|
13
13
|
* Create pull request
|
14
|
-
* Check if [
|
14
|
+
* Check if [github actions workflow is happy](https://github.com/toy/image_optim_pack/actions/workflows/check.yml)
|
data/Gemfile
CHANGED
@@ -4,14 +4,8 @@ source 'https://rubygems.org'
|
|
4
4
|
|
5
5
|
gemspec
|
6
6
|
|
7
|
-
if ENV['
|
7
|
+
if ENV['CC_TEST_REPORTER_ID']
|
8
8
|
group :test do
|
9
9
|
gem 'simplecov'
|
10
|
-
|
11
|
-
gem 'codeclimate-test-reporter'
|
12
10
|
end
|
13
11
|
end
|
14
|
-
|
15
|
-
if ENV['CHECK_RUBIES']
|
16
|
-
gem 'travis_check_rubies', '~> 0.2'
|
17
|
-
end
|
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
-
[](https://inch-ci.org/github/toy/image_optim)
|
1
|
+
[](https://rubygems.org/gems/image_optim)
|
2
|
+
[](https://github.com/toy/image_optim/actions/workflows/check.yml)
|
3
|
+
[](https://codeclimate.com/github/toy/image_optim)
|
4
|
+
[](https://codeclimate.com/github/toy/image_optim)
|
5
|
+
[](https://depfu.com/github/toy/image_optim)
|
6
|
+
[](https://inch-ci.org/github/toy/image_optim)
|
8
7
|
|
9
8
|
# image_optim
|
10
9
|
|
@@ -18,6 +17,7 @@ Command line tool and ruby interface to optimize (lossless compress, optionally
|
|
18
17
|
* [jpeg-recompress](https://github.com/danielgtaylor/jpeg-archive#jpeg-recompress)
|
19
18
|
* jpegtran from [Independent JPEG Group's JPEG library](http://www.ijg.org/)
|
20
19
|
* [optipng](http://optipng.sourceforge.net/)
|
20
|
+
* [oxipng](https://github.com/shssoichiro/oxipng)
|
21
21
|
* [pngcrush](http://pmt.sourceforge.net/pngcrush/)
|
22
22
|
* [pngout](http://www.advsys.net/ken/util/pngout.htm)
|
23
23
|
* [pngquant](http://pngquant.org/)
|
@@ -60,7 +60,7 @@ With version:
|
|
60
60
|
|
61
61
|
<!---<update-version>-->
|
62
62
|
```ruby
|
63
|
-
gem 'image_optim', '~> 0.
|
63
|
+
gem 'image_optim', '~> 0.31'
|
64
64
|
```
|
65
65
|
<!---</update-version>-->
|
66
66
|
|
@@ -166,6 +166,14 @@ sudo port install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush png
|
|
166
166
|
brew install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush pngquant jonof/kenutils/pngout
|
167
167
|
```
|
168
168
|
|
169
|
+
### oxipng installation (optional)
|
170
|
+
|
171
|
+
Unless it is available in your chosen package manager, can be installed using cargo:
|
172
|
+
|
173
|
+
```bash
|
174
|
+
cargo install oxipng
|
175
|
+
```
|
176
|
+
|
169
177
|
### pngout installation (optional)
|
170
178
|
|
171
179
|
If you installed the dependencies via brew, pngout should be installed already. Otherwise, you can install `pngout` by downloading and installing the [binary versions](http://www.jonof.id.au/kenutils).
|
@@ -291,6 +299,7 @@ optipng:
|
|
291
299
|
* `:allow_lossy` — Allow lossy workers and optimizations *(defaults to `false`)*
|
292
300
|
* `:cache_dir` — Configure cache directory
|
293
301
|
* `:cache_worker_digests` - Also cache worker digests along with original file digest and worker options: updating workers invalidates cache
|
302
|
+
* `:timeout` — Maximum time in seconds to spend on one image, note multithreading and cache *(defaults to unlimited)*
|
294
303
|
|
295
304
|
Worker can be disabled by passing `false` instead of options hash or by setting option `:disable` to `true`.
|
296
305
|
|
@@ -362,4 +371,4 @@ In separate file [CHANGELOG.markdown](CHANGELOG.markdown).
|
|
362
371
|
|
363
372
|
## Copyright
|
364
373
|
|
365
|
-
Copyright (c) 2012-
|
374
|
+
Copyright (c) 2012-2021 Ivan Kuchin. See [LICENSE.txt](LICENSE.txt) for details.
|
data/Vagrantfile
CHANGED
data/image_optim.gemspec
CHANGED
@@ -2,12 +2,14 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'image_optim'
|
5
|
-
s.version = '0.
|
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, pngcrush, pngout, pngquant, svgo)}
|
5
|
+
s.version = '0.31.1'
|
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']
|
9
9
|
s.license = 'MIT'
|
10
10
|
|
11
|
+
s.required_ruby_version = '>= 1.9.3'
|
12
|
+
|
11
13
|
s.metadata = {
|
12
14
|
'bug_tracker_uri' => "https://github.com/toy/#{s.name}/issues",
|
13
15
|
'changelog_uri' => "https://github.com/toy/#{s.name}/blob/master/CHANGELOG.markdown",
|
@@ -26,7 +28,7 @@ You can safely remove `config.assets.image_optim = false` if you are not going t
|
|
26
28
|
EOF
|
27
29
|
|
28
30
|
s.add_dependency 'fspath', '~> 3.0'
|
29
|
-
s.add_dependency 'image_size', '>= 1.5', '<
|
31
|
+
s.add_dependency 'image_size', '>= 1.5', '< 4'
|
30
32
|
s.add_dependency 'exifr', '~> 1.2', '>= 1.2.2'
|
31
33
|
s.add_dependency 'progress', '~> 3.0', '>= 3.0.1'
|
32
34
|
s.add_dependency 'in_threads', '~> 1.3'
|
@@ -35,5 +37,6 @@ EOF
|
|
35
37
|
s.add_development_dependency 'rspec', '~> 3.0'
|
36
38
|
if RUBY_VERSION >= '2.4' && !Gem.win_platform? && !defined?(JRUBY_VERSION)
|
37
39
|
s.add_development_dependency 'rubocop', '~> 1.0'
|
40
|
+
s.add_development_dependency 'rubocop-rspec', '~> 2.0'
|
38
41
|
end
|
39
42
|
end
|
@@ -38,30 +38,30 @@ class ImageOptim
|
|
38
38
|
is = ComparableCondition.is
|
39
39
|
|
40
40
|
FAIL_CHECKS = {
|
41
|
-
:
|
41
|
+
pngcrush: [
|
42
42
|
[is.between?('1.7.60', '1.7.65'), 'is known to produce broken pngs'],
|
43
43
|
[is == '1.7.80', 'loses one color in indexed images'],
|
44
44
|
],
|
45
|
-
:
|
45
|
+
pngquant: [
|
46
46
|
[is < '2.0', 'is not supported'],
|
47
47
|
],
|
48
48
|
}.freeze
|
49
49
|
|
50
50
|
WARN_CHECKS = {
|
51
|
-
:
|
51
|
+
advpng: [
|
52
52
|
[is == 'none', 'is of unknown version'],
|
53
53
|
[is < '1.17', 'does not use zopfli'],
|
54
54
|
],
|
55
|
-
:
|
55
|
+
gifsicle: [
|
56
56
|
[is < '1.85', 'does not support removing extension blocks'],
|
57
57
|
],
|
58
|
-
:
|
58
|
+
pngcrush: [
|
59
59
|
[is < '1.7.38', 'does not have blacken flag'],
|
60
60
|
],
|
61
|
-
:
|
61
|
+
pngquant: [
|
62
62
|
[is < '2.1', 'may be lossy even with quality `100-`'],
|
63
63
|
],
|
64
|
-
:
|
64
|
+
optipng: [
|
65
65
|
[is < '0.7', 'does not support -strip option'],
|
66
66
|
],
|
67
67
|
}.freeze
|
@@ -109,10 +109,10 @@ class ImageOptim
|
|
109
109
|
case name
|
110
110
|
when :advpng
|
111
111
|
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\bv(\d+(\.\d+)+|none)/, 1]
|
112
|
-
when :gifsicle, :jpegoptim, :optipng
|
112
|
+
when :gifsicle, :jpegoptim, :optipng, :oxipng
|
113
113
|
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
114
114
|
when :svgo, :pngquant
|
115
|
-
capture("#{escaped_path} --version 2>&1")[/\d+(\.\d+)+/]
|
115
|
+
capture("#{escaped_path} --version 2>&1")[/\A\d+(\.\d+)+/]
|
116
116
|
when :jhead, :'jpeg-recompress'
|
117
117
|
capture("#{escaped_path} -V 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
118
118
|
when :jpegtran
|
data/lib/image_optim/cache.rb
CHANGED
@@ -21,6 +21,11 @@ class ImageOptim
|
|
21
21
|
"#{bin.name}[#{bin.digest}]"
|
22
22
|
end.sort!.uniq.join(', ')]
|
23
23
|
end]
|
24
|
+
@global_options = begin
|
25
|
+
options = {}
|
26
|
+
options[:timeout] = image_optim.timeout if image_optim.timeout
|
27
|
+
options.empty? ? '' : options.inspect
|
28
|
+
end
|
24
29
|
end
|
25
30
|
|
26
31
|
def fetch(original)
|
@@ -68,6 +73,7 @@ class ImageOptim
|
|
68
73
|
digest = Digest::SHA1.file(path)
|
69
74
|
digest.update options_by_format(format)
|
70
75
|
digest.update bins_by_format(format) if @cache_worker_digests
|
76
|
+
digest.update @global_options
|
71
77
|
s = digest.hexdigest
|
72
78
|
"#{s[0..1]}/#{s[2..-1]}"
|
73
79
|
end
|
data/lib/image_optim/cmd.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'image_optim/errors'
|
3
4
|
require 'English'
|
4
5
|
|
5
6
|
class ImageOptim
|
@@ -10,11 +11,30 @@ class ImageOptim
|
|
10
11
|
# Return success status
|
11
12
|
# Will raise SignalException if process was interrupted
|
12
13
|
def run(*args)
|
13
|
-
|
14
|
+
if args.last.is_a?(Hash) && (timeout = args.last.delete(:timeout))
|
15
|
+
args.last[Gem.win_platform? ? :new_pgroup : :pgroup] = true
|
14
16
|
|
15
|
-
|
17
|
+
pid = Process.spawn(*args)
|
18
|
+
|
19
|
+
waiter = Process.detach(pid)
|
20
|
+
if waiter.join(timeout.to_f)
|
21
|
+
status = waiter.value
|
22
|
+
|
23
|
+
check_status!(status)
|
24
|
+
|
25
|
+
status.success?
|
26
|
+
else
|
27
|
+
cleanup(pid, waiter)
|
16
28
|
|
17
|
-
|
29
|
+
fail Errors::TimeoutExceeded
|
30
|
+
end
|
31
|
+
else
|
32
|
+
success = system(*args)
|
33
|
+
|
34
|
+
check_status!
|
35
|
+
|
36
|
+
success
|
37
|
+
end
|
18
38
|
end
|
19
39
|
|
20
40
|
# Run using backtick
|
@@ -30,9 +50,7 @@ class ImageOptim
|
|
30
50
|
|
31
51
|
private
|
32
52
|
|
33
|
-
def check_status!
|
34
|
-
status = $CHILD_STATUS
|
35
|
-
|
53
|
+
def check_status!(status = $CHILD_STATUS)
|
36
54
|
return unless status.signaled?
|
37
55
|
|
38
56
|
# jruby incorrectly returns true for `signaled?` if process exits with
|
@@ -46,6 +64,27 @@ class ImageOptim
|
|
46
64
|
|
47
65
|
fail SignalException, status.termsig
|
48
66
|
end
|
67
|
+
|
68
|
+
def cleanup(pid, waiter)
|
69
|
+
if Gem.win_platform?
|
70
|
+
kill('KILL', pid)
|
71
|
+
else
|
72
|
+
kill('-TERM', pid)
|
73
|
+
|
74
|
+
# Allow 10 seconds for the process to exit
|
75
|
+
waiter.join(10)
|
76
|
+
|
77
|
+
kill('-KILL', pid)
|
78
|
+
end
|
79
|
+
|
80
|
+
waiter.join
|
81
|
+
end
|
82
|
+
|
83
|
+
def kill(signal, pid)
|
84
|
+
Process.kill(signal, pid)
|
85
|
+
rescue Errno::ESRCH, Errno::EPERM
|
86
|
+
# expected
|
87
|
+
end
|
49
88
|
end
|
50
89
|
end
|
51
90
|
end
|
data/lib/image_optim/config.rb
CHANGED
@@ -15,9 +15,7 @@ class ImageOptim
|
|
15
15
|
|
16
16
|
# Global config path at `$XDG_CONFIG_HOME/image_optim.yml` (by default
|
17
17
|
# `~/.config/image_optim.yml`)
|
18
|
-
GLOBAL_PATH =
|
19
|
-
File.join(ENV['XDG_CONFIG_HOME'] || '~/.config', 'image_optim.yml')
|
20
|
-
end
|
18
|
+
GLOBAL_PATH = File.join(ENV['XDG_CONFIG_HOME'] || '~/.config', 'image_optim.yml')
|
21
19
|
|
22
20
|
# Local config path at `./.image_optim.yml`
|
23
21
|
LOCAL_PATH = './.image_optim.yml'
|
@@ -119,6 +117,14 @@ class ImageOptim
|
|
119
117
|
end
|
120
118
|
end
|
121
119
|
|
120
|
+
# Timeout in seconds for each image:
|
121
|
+
# * not set by default and for `nil`
|
122
|
+
# * otherwise converted to float
|
123
|
+
def timeout
|
124
|
+
timeout = get!(:timeout)
|
125
|
+
timeout ? timeout.to_f : nil
|
126
|
+
end
|
127
|
+
|
122
128
|
# Verbose mode, converted to boolean
|
123
129
|
def verbose
|
124
130
|
!!get!(:verbose)
|
@@ -177,10 +183,10 @@ class ImageOptim
|
|
177
183
|
when true, nil
|
178
184
|
{}
|
179
185
|
when false
|
180
|
-
{:
|
186
|
+
{disable: true}
|
181
187
|
else
|
182
188
|
fail ConfigurationError, "Got #{worker_options.inspect} for "\
|
183
|
-
|
189
|
+
"#{klass.name} options"
|
184
190
|
end
|
185
191
|
end
|
186
192
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ImageOptim
|
4
|
+
# Use Process.clock_gettime if available to get time more fitting to calculate elapsed time
|
5
|
+
module ElapsedTime
|
6
|
+
CLOCK_NAME = %w[
|
7
|
+
CLOCK_UPTIME_RAW
|
8
|
+
CLOCK_UPTIME
|
9
|
+
CLOCK_MONOTONIC_RAW
|
10
|
+
CLOCK_MONOTONIC
|
11
|
+
CLOCK_REALTIME
|
12
|
+
].find{ |name| Process.const_defined?(name) }
|
13
|
+
|
14
|
+
CLOCK_ID = CLOCK_NAME && Process.const_get(CLOCK_NAME)
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def now
|
19
|
+
if CLOCK_ID
|
20
|
+
Process.clock_gettime(CLOCK_ID)
|
21
|
+
else
|
22
|
+
Time.now.to_f
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/image_optim/path.rb
CHANGED
@@ -38,7 +38,7 @@ class ImageOptim
|
|
38
38
|
columns = terminal_columns - 1
|
39
39
|
# 1 for distance between summary and description
|
40
40
|
# 2 for additional indent
|
41
|
-
wrapped_indent = summary_indent + ' ' * (summary_width + 1 + 2)
|
41
|
+
wrapped_indent = summary_indent + (' ' * (summary_width + 1 + 2))
|
42
42
|
wrapped_width = columns - wrapped_indent.length
|
43
43
|
# don't try to wrap if there is too little space for description
|
44
44
|
return text if wrapped_width < 20
|
@@ -97,29 +97,29 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
97
97
|
TEXT
|
98
98
|
|
99
99
|
op.on('--config-paths PATH1,PATH2', Array, 'Config paths to use instead of '\
|
100
|
-
|
100
|
+
'default ones') do |paths|
|
101
101
|
options[:config_paths] = paths
|
102
102
|
end
|
103
103
|
|
104
104
|
op.separator nil
|
105
105
|
|
106
106
|
op.on('-r', '-R', '--recursive', 'Recursively scan directories '\
|
107
|
-
|
107
|
+
'for images') do |recursive|
|
108
108
|
options[:recursive] = recursive
|
109
109
|
end
|
110
110
|
|
111
111
|
op.on("--exclude-dir 'GLOB'", 'Glob for excluding directories '\
|
112
|
-
|
112
|
+
'(defaults to .*)') do |glob|
|
113
113
|
options[:exclude_dir_glob] = glob
|
114
114
|
end
|
115
115
|
|
116
116
|
op.on("--exclude-file 'GLOB'", 'Glob for excluding files '\
|
117
|
-
|
117
|
+
'(defaults to .*)') do |glob|
|
118
118
|
options[:exclude_file_glob] = glob
|
119
119
|
end
|
120
120
|
|
121
121
|
op.on("--exclude 'GLOB'", 'Set glob for excluding both directories and '\
|
122
|
-
|
122
|
+
'files') do |glob|
|
123
123
|
options[:exclude_file_glob] = options[:exclude_dir_glob] = glob
|
124
124
|
end
|
125
125
|
|
@@ -130,19 +130,19 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
130
130
|
end
|
131
131
|
|
132
132
|
op.on('--[no-]threads N', Integer, 'Number of threads or disable '\
|
133
|
-
|
133
|
+
'(defaults to number of processors)') do |threads|
|
134
134
|
options[:threads] = threads
|
135
135
|
end
|
136
136
|
|
137
137
|
op.on('--[no-]nice N', Integer, 'Nice level, priority of all used tools '\
|
138
|
-
|
139
|
-
|
138
|
+
'with higher value meaning lower priority, in range -20..19, negative '\
|
139
|
+
'values can be set only if run by root user (defaults to 10)') do |nice|
|
140
140
|
options[:nice] = nice
|
141
141
|
end
|
142
142
|
|
143
143
|
op.on('--[no-]pack', 'Require image_optim_pack or disable it, '\
|
144
|
-
|
145
|
-
|
144
|
+
'by default image_optim_pack will be used if available, '\
|
145
|
+
'will turn on skip-missing-workers unless explicitly disabled') do |pack|
|
146
146
|
options[:pack] = pack
|
147
147
|
end
|
148
148
|
|
@@ -150,12 +150,12 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
150
150
|
op.separator ' Caching:'
|
151
151
|
|
152
152
|
op.on('--cache-dir DIR', 'Cache optimized images '\
|
153
|
-
|
153
|
+
'into the specified directory') do |cache_dir|
|
154
154
|
options[:cache_dir] = cache_dir
|
155
155
|
end
|
156
156
|
|
157
157
|
op.on('--cache-worker-digests', 'Cache worker digests '\
|
158
|
-
|
158
|
+
'(updating workers invalidates cache)') do |cache_worker_digests|
|
159
159
|
options[:cache_worker_digests] = cache_worker_digests
|
160
160
|
end
|
161
161
|
|
@@ -163,7 +163,7 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
163
163
|
op.separator ' Disabling workers:'
|
164
164
|
|
165
165
|
op.on('--[no-]skip-missing-workers', 'Skip workers with missing or '\
|
166
|
-
|
166
|
+
'problematic binaries') do |skip|
|
167
167
|
options[:skip_missing_workers] = skip
|
168
168
|
end
|
169
169
|
|
@@ -178,10 +178,14 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
178
178
|
op.separator ' Worker options:'
|
179
179
|
|
180
180
|
op.on('--allow-lossy', 'Allow lossy workers and '\
|
181
|
-
|
181
|
+
'optimizations') do |allow_lossy|
|
182
182
|
options[:allow_lossy] = allow_lossy
|
183
183
|
end
|
184
184
|
|
185
|
+
op.on('--timeout N', Float, 'Maximum time in seconds to spend on one image') do |timeout|
|
186
|
+
options[:timeout] = timeout
|
187
|
+
end
|
188
|
+
|
185
189
|
op.separator nil
|
186
190
|
|
187
191
|
ImageOptim::Worker.klasses.each_with_index do |klass, i|
|
@@ -226,8 +230,8 @@ ImageOptim::Runner::OptionParser::DEFINE = proc do |op, options|
|
|
226
230
|
op.separator ' Common options:'
|
227
231
|
|
228
232
|
op.on_tail('-v', '--verbose', 'Verbose output (show global and worker '\
|
229
|
-
|
230
|
-
|
233
|
+
'config, binary resolution log, information about each tool invocation, '\
|
234
|
+
'backtrace of exception)') do
|
231
235
|
options[:verbose] = true
|
232
236
|
end
|
233
237
|
|