image_optim 0.27.1 → 0.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.appveyor.yml +2 -0
- data/.github/workflows/check.yml +59 -0
- data/.pre-commit-hooks.yaml +9 -0
- data/.rubocop.yml +6 -3
- data/CHANGELOG.markdown +22 -0
- data/CONTRIBUTING.markdown +5 -2
- data/Gemfile +1 -7
- data/LICENSE.txt +1 -1
- data/README.markdown +21 -10
- data/Vagrantfile +1 -1
- data/image_optim.gemspec +7 -4
- data/lib/image_optim/bin_resolver/bin.rb +10 -9
- data/lib/image_optim/cache.rb +6 -0
- data/lib/image_optim/cmd.rb +45 -6
- data/lib/image_optim/config.rb +14 -8
- 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 +24 -18
- 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 +13 -11
- data/lib/image_optim/worker/jpegrecompress.rb +17 -2
- 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 +10 -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 +2 -2
- 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 +8 -8
- 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 +32 -0
- 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 +18 -17
- metadata +36 -15
- data/.travis.yml +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e80e82d67e3434476f0bdf332b14b6369601010aaeef7ab7b901515d0c03565c
|
4
|
+
data.tar.gz: 16f304385c879cf1afc0073d7d037fb548d6c260f57e2b94cdcdd974f3cd4b4e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0395980a804453e3273f779c1217d5dd5b9b7c522e74964070b43f2b3ac433f9f39d5f997a3e9c6594f22d244752910eea1697ac2e570de34e6b0641555b9e8
|
7
|
+
data.tar.gz: 9de0bebe89071d3aa7bd506b02dc684b53d998dcfccab1debad72bdc244e6fbae6eb0ac2d5871359fe2ffa5cb9e7c5ae8a7dc98829e00e8abef49c017ac3b00c
|
data/.appveyor.yml
CHANGED
@@ -0,0 +1,59 @@
|
|
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
|
+
coverage:
|
36
|
+
runs-on: ubuntu-latest
|
37
|
+
env:
|
38
|
+
CC_TEST_REPORTER_ID: b433c6540d220a2da0663670c9b260806bafdb3a43c6f22b2e81bfb1f87b12fe
|
39
|
+
steps:
|
40
|
+
- uses: actions/checkout@v2
|
41
|
+
- uses: ruby/setup-ruby@v1
|
42
|
+
with:
|
43
|
+
ruby-version: '3.0'
|
44
|
+
bundler-cache: true
|
45
|
+
- run: sudo npm install -g svgo
|
46
|
+
- 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'
|
47
|
+
- 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'
|
48
|
+
- uses: paambaati/codeclimate-action@v2.7.5
|
49
|
+
with:
|
50
|
+
coverageCommand: bundle exec rspec
|
51
|
+
rubocop:
|
52
|
+
runs-on: ubuntu-latest
|
53
|
+
steps:
|
54
|
+
- uses: actions/checkout@v2
|
55
|
+
- uses: ruby/setup-ruby@v1
|
56
|
+
with:
|
57
|
+
ruby-version: '3.0'
|
58
|
+
bundler-cache: true
|
59
|
+
- 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,28 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v0.31.0 (2021-10-03)
|
6
|
+
|
7
|
+
* 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)
|
8
|
+
* 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)
|
9
|
+
|
10
|
+
## v0.30.0 (2021-05-11)
|
11
|
+
|
12
|
+
* 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)
|
13
|
+
|
14
|
+
## v0.29.0 (2021-04-28)
|
15
|
+
|
16
|
+
* Require at least ruby 1.9.3 [@toy](https://github.com/toy)
|
17
|
+
* 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)
|
18
|
+
* 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)
|
19
|
+
* More precise regular expression for capturing svgo version [@toy](https://github.com/toy)
|
20
|
+
|
21
|
+
## v0.28.0 (2020-12-18)
|
22
|
+
|
23
|
+
* 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)
|
24
|
+
* Add `--skip-if-larger` flag to pngquant worker. The pngquant worker already does this, but this will make it fail faster. [#125](https://github.com/toy/image_optim/pull/125) [#181](https://github.com/toy/image_optim/pull/181) [@iggant](https://github.com/iggant) [@oblakeerickson](https://github.com/oblakeerickson)
|
25
|
+
* Add `method` option for jpegrecompress, default to `ssim` [#102](https://github.com/toy/image_optim/issues/102) [#103](https://github.com/toy/image_optim/pull/103) [#182](https://github.com/toy/image_optim/pull/182) [@ramiroaraujo](https://github.com/ramiroaraujo) [@oblakeerickson](https://github.com/oblakeerickson)
|
26
|
+
|
5
27
|
## v0.27.1 (2020-09-30)
|
6
28
|
|
7
29
|
* Fixed atomic replacement for case when equal `File::Stat#dev` doesn't mean that file can be linked [#180](https://github.com/toy/image_optim/issues/180) [@toy](https://github.com/toy)
|
data/CONTRIBUTING.markdown
CHANGED
@@ -2,10 +2,13 @@
|
|
2
2
|
|
3
3
|
* Create topic/feature branch: `git checkout -b awesome-changes`
|
4
4
|
* Commit…
|
5
|
-
* Add entry at the top of [ChangeLog](CHANGELOG.markdown)
|
5
|
+
* Add an entry at the top (after ## unreleased) of [ChangeLog](CHANGELOG.markdown), include:
|
6
|
+
* Issues (`[#123](https://github.com/toy/image_optim/issues/123)`)
|
7
|
+
* Pull requests (`[#123](https://github.com/toy/image_optim/pull/123)`)
|
8
|
+
* Authors (`[@octocat](https://github.com/octocat)`)
|
6
9
|
* Run tests: `bundle exec rspec`
|
7
10
|
* Check code style: `bundle exec rubocop`
|
8
11
|
* Rebase on master and squash commits to logical units
|
9
12
|
* Push your branch: `git push origin awesome-changes`
|
10
13
|
* Create pull request
|
11
|
-
* 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,10 @@
|
|
1
|
-
[![Gem Version](https://img.shields.io/gem/v/image_optim
|
2
|
-
[![Build Status](https://img.shields.io/
|
3
|
-
[![AppVeyor Status](https://img.shields.io/appveyor/
|
4
|
-
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim
|
5
|
-
[![Code Climate Coverage](https://img.shields.io/codeclimate/
|
6
|
-
[![Depfu](https://
|
7
|
-
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master
|
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
|
+
[![AppVeyor Status](https://img.shields.io/appveyor/build/toy/image-optim/master?label=windows&logo=appveyor)](https://ci.appveyor.com/project/toy/image-optim)
|
4
|
+
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
|
5
|
+
[![Code Climate Coverage](https://img.shields.io/codeclimate/coverage/toy/image_optim?logo=codeclimate)](https://codeclimate.com/github/toy/image_optim)
|
6
|
+
[![Depfu](https://img.shields.io/depfu/toy/image_optim)](https://depfu.com/github/toy/image_optim)
|
7
|
+
[![Inch CI](https://inch-ci.org/github/toy/image_optim.svg?branch=master)](https://inch-ci.org/github/toy/image_optim)
|
8
8
|
|
9
9
|
# image_optim
|
10
10
|
|
@@ -18,6 +18,7 @@ Command line tool and ruby interface to optimize (lossless compress, optionally
|
|
18
18
|
* [jpeg-recompress](https://github.com/danielgtaylor/jpeg-archive#jpeg-recompress)
|
19
19
|
* jpegtran from [Independent JPEG Group's JPEG library](http://www.ijg.org/)
|
20
20
|
* [optipng](http://optipng.sourceforge.net/)
|
21
|
+
* [oxipng](https://github.com/shssoichiro/oxipng)
|
21
22
|
* [pngcrush](http://pmt.sourceforge.net/pngcrush/)
|
22
23
|
* [pngout](http://www.advsys.net/ken/util/pngout.htm)
|
23
24
|
* [pngquant](http://pngquant.org/)
|
@@ -60,7 +61,7 @@ With version:
|
|
60
61
|
|
61
62
|
<!---<update-version>-->
|
62
63
|
```ruby
|
63
|
-
gem 'image_optim', '~> 0.
|
64
|
+
gem 'image_optim', '~> 0.31'
|
64
65
|
```
|
65
66
|
<!---</update-version>-->
|
66
67
|
|
@@ -166,6 +167,14 @@ sudo port install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush png
|
|
166
167
|
brew install advancecomp gifsicle jhead jpegoptim jpeg optipng pngcrush pngquant jonof/kenutils/pngout
|
167
168
|
```
|
168
169
|
|
170
|
+
### oxipng installation (optional)
|
171
|
+
|
172
|
+
Unless it is available in your chosen package manager, can be installed using cargo:
|
173
|
+
|
174
|
+
```bash
|
175
|
+
cargo install oxipng
|
176
|
+
```
|
177
|
+
|
169
178
|
### pngout installation (optional)
|
170
179
|
|
171
180
|
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 +300,7 @@ optipng:
|
|
291
300
|
* `:allow_lossy` — Allow lossy workers and optimizations *(defaults to `false`)*
|
292
301
|
* `:cache_dir` — Configure cache directory
|
293
302
|
* `:cache_worker_digests` - Also cache worker digests along with original file digest and worker options: updating workers invalidates cache
|
303
|
+
* `:timeout` — Maximum time in seconds to spend on one image, note multithreading and cache *(defaults to unlimited)*
|
294
304
|
|
295
305
|
Worker can be disabled by passing `false` instead of options hash or by setting option `:disable` to `true`.
|
296
306
|
|
@@ -310,12 +320,13 @@ Worker has no options
|
|
310
320
|
|
311
321
|
### jpegoptim:
|
312
322
|
* `:allow_lossy` — Allow limiting maximum quality *(defaults to `false`)*
|
313
|
-
* `:strip` — List of
|
323
|
+
* `:strip` — List of markers to strip: `:com`, `:exif`, `:iptc`, `:icc`, `:xmp`, `:none` or `:all` *(defaults to `:all`)*
|
314
324
|
* `:max_quality` — Maximum image quality factor `0`..`100`, ignored in default/lossless mode *(defaults to `100`)*
|
315
325
|
|
316
326
|
### jpegrecompress:
|
317
327
|
* `:allow_lossy` — Allow worker, it is always lossy *(defaults to `false`)*
|
318
328
|
* `:quality` — JPEG quality preset: `0` - low, `1` - medium, `2` - high, `3` - veryhigh *(defaults to `3`)*
|
329
|
+
* `:method` — Comparison Metric: `mpe` - Mean pixel error, `ssim` - Structural similarity, `ms-ssim` - Multi-scale structural similarity (slow!), `smallfry` - Linear-weighted BBCQ-like (may be patented) *(defaults to ssim)*
|
319
330
|
|
320
331
|
### jpegtran:
|
321
332
|
* `:copy_chunks` — Copy all chunks *(defaults to `false`)*
|
@@ -361,4 +372,4 @@ In separate file [CHANGELOG.markdown](CHANGELOG.markdown).
|
|
361
372
|
|
362
373
|
## Copyright
|
363
374
|
|
364
|
-
Copyright (c) 2012-
|
375
|
+
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.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, 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",
|
@@ -33,7 +35,8 @@ EOF
|
|
33
35
|
|
34
36
|
s.add_development_dependency 'image_optim_pack', '~> 0.2', '>= 0.2.2'
|
35
37
|
s.add_development_dependency 'rspec', '~> 3.0'
|
36
|
-
if RUBY_VERSION >= '2.
|
37
|
-
s.add_development_dependency 'rubocop', '~>
|
38
|
+
if RUBY_VERSION >= '2.4' && !Gem.win_platform? && !defined?(JRUBY_VERSION)
|
39
|
+
s.add_development_dependency 'rubocop', '~> 1.0'
|
40
|
+
s.add_development_dependency 'rubocop-rspec', '~> 2.0'
|
38
41
|
end
|
39
42
|
end
|
@@ -14,6 +14,7 @@ class ImageOptim
|
|
14
14
|
# Holds bin name and path, gets version
|
15
15
|
class Bin
|
16
16
|
class UnknownVersion < Error; end
|
17
|
+
|
17
18
|
class BadVersion < Error; end
|
18
19
|
|
19
20
|
attr_reader :name, :path, :version
|
@@ -37,30 +38,30 @@ class ImageOptim
|
|
37
38
|
is = ComparableCondition.is
|
38
39
|
|
39
40
|
FAIL_CHECKS = {
|
40
|
-
:
|
41
|
+
pngcrush: [
|
41
42
|
[is.between?('1.7.60', '1.7.65'), 'is known to produce broken pngs'],
|
42
43
|
[is == '1.7.80', 'loses one color in indexed images'],
|
43
44
|
],
|
44
|
-
:
|
45
|
+
pngquant: [
|
45
46
|
[is < '2.0', 'is not supported'],
|
46
47
|
],
|
47
48
|
}.freeze
|
48
49
|
|
49
50
|
WARN_CHECKS = {
|
50
|
-
:
|
51
|
+
advpng: [
|
51
52
|
[is == 'none', 'is of unknown version'],
|
52
53
|
[is < '1.17', 'does not use zopfli'],
|
53
54
|
],
|
54
|
-
:
|
55
|
+
gifsicle: [
|
55
56
|
[is < '1.85', 'does not support removing extension blocks'],
|
56
57
|
],
|
57
|
-
:
|
58
|
+
pngcrush: [
|
58
59
|
[is < '1.7.38', 'does not have blacken flag'],
|
59
60
|
],
|
60
|
-
:
|
61
|
+
pngquant: [
|
61
62
|
[is < '2.1', 'may be lossy even with quality `100-`'],
|
62
63
|
],
|
63
|
-
:
|
64
|
+
optipng: [
|
64
65
|
[is < '0.7', 'does not support -strip option'],
|
65
66
|
],
|
66
67
|
}.freeze
|
@@ -108,10 +109,10 @@ class ImageOptim
|
|
108
109
|
case name
|
109
110
|
when :advpng
|
110
111
|
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\bv(\d+(\.\d+)+|none)/, 1]
|
111
|
-
when :gifsicle, :jpegoptim, :optipng
|
112
|
+
when :gifsicle, :jpegoptim, :optipng, :oxipng
|
112
113
|
capture("#{escaped_path} --version 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
113
114
|
when :svgo, :pngquant
|
114
|
-
capture("#{escaped_path} --version 2>&1")[/\d+(\.\d+)+/]
|
115
|
+
capture("#{escaped_path} --version 2>&1")[/\A\d+(\.\d+)+/]
|
115
116
|
when :jhead, :'jpeg-recompress'
|
116
117
|
capture("#{escaped_path} -V 2> #{Path::NULL}")[/\d+(\.\d+)+/]
|
117
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
|
|
@@ -197,10 +203,10 @@ class ImageOptim
|
|
197
203
|
when /darwin9/
|
198
204
|
Cmd.capture 'hwprefs cpu_count'
|
199
205
|
when /darwin/
|
200
|
-
if (Cmd.capture 'which hwprefs')
|
201
|
-
Cmd.capture 'hwprefs thread_count'
|
202
|
-
else
|
206
|
+
if (Cmd.capture 'which hwprefs') == ''
|
203
207
|
Cmd.capture 'sysctl -n hw.ncpu'
|
208
|
+
else
|
209
|
+
Cmd.capture 'hwprefs thread_count'
|
204
210
|
end
|
205
211
|
when /linux/
|
206
212
|
Cmd.capture 'grep -c processor /proc/cpuinfo'
|
@@ -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