image_optim 0.28.0 → 0.31.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Gem Version](https://img.shields.io/gem/v/image_optim
|
2
|
-
[![Build Status](https://img.shields.io/
|
3
|
-
[![
|
4
|
-
[![Code Climate](https://img.shields.io/codeclimate/
|
5
|
-
[![
|
6
|
-
[![
|
7
|
-
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master&style=flat)](https://inch-ci.org/github/toy/image_optim)
|
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/workflow/status/toy/image_optim/check/master?logo=github)](https://github.com/toy/image_optim/actions/workflows/check.yml)
|
3
|
+
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
|
4
|
+
[![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
|
5
|
+
[![Depfu](https://img.shields.io/depfu/toy/image_optim)](https://depfu.com/github/toy/image_optim)
|
6
|
+
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master)](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
|
|