image_optim 0.15.0 → 0.16.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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODA5N2IyMjgwM2FjYTU3OGM4NjE2OTU0NzM5NGRhOTRiNGExNDM5Mw==
4
+ MDE1MjA4Yzc2MDkwZWM5YjgwNmJhZDVmMzM5MzI5NTU2ZjY3YWViZA==
5
5
  data.tar.gz: !binary |-
6
- YTNiZmYwOTk0OWY5NmE0OGM3OTliNzRmNTE5NDIwMGQ4OWM4NmMyMQ==
6
+ NTMxMjc5YTI1ZmEzYzA1YTYwMWYwNWU4YzM3ODA0YTMwNDAyZDc3MQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- YzI4NWY2MmU5Y2Y3YjJjMmExNzQ1NDk4NmE5NjhmOWFjMjVlZmY1NmQyMmM3
10
- M2RmZTAzZWI1Mzg2MTQ3ZDQ4YzkyZjM5MGYxYjcwM2NiMTE3Mzg1ZmMwY2Vl
11
- MmQwODgxMDkwYmVlOTE2ZjY1MTA2YzY4ODgxMzJmODFiN2FmMmU=
9
+ YWM3ZmNmMzk0NWE4YTI0NTQxNDI1YzEyM2YxNzM3ZjlhMmM3NWIwMTQwYjE5
10
+ NGIwYzJiZDk3MzhlMGJkOWQ5Y2NkYzc3OWEyMGMyZGQ5YzEyNzJkOGRhODgy
11
+ NmRkNzBkMTQ0N2M3YTc3YWU2OTI0MzAxM2MyMDZmMzliMjljNDM=
12
12
  data.tar.gz: !binary |-
13
- NzViMzQ4Yjc0Y2MyYjdlNDBiNjM1N2U5ZmIzYTkzYzZlZjNkNjZlMzMxMDVk
14
- NWEwYjk0MzEzMTU3NDdlNmZiZjlmMjMzYWM2ZjRjNGNlNjRmY2I2MTY2MjRm
15
- YmFjNmE0ZTc2M2I1MGVlM2RiOTg1OTJmOGFhZjEwYzkxMjNiNTY=
13
+ MjEyYWRhNDA3OTZkMTM2NWNiYTc5MzI2MDEyYzQ4ZDBlYzcyNzU4MjkxODY0
14
+ MTVjZjdjYjIyMWRhYTIzY2ZiMTA0ZDM3N2U2YzAyZDllM2M5Y2NkNWI5YWQw
15
+ OGRhYmFmZGU5ZWVlNWIzZjYzMmJkNDI3ODM1NTg0NWY3NDdhODM=
data/.rubocop.yml CHANGED
@@ -5,18 +5,24 @@ AllCops:
5
5
  Lint/EndAlignment:
6
6
  AlignWith: variable
7
7
 
8
+ Metrics/ClassLength:
9
+ Max: 150
10
+
11
+ Metrics/CyclomaticComplexity:
12
+ Max: 10
13
+
14
+ Metrics/MethodLength:
15
+ Max: 20
16
+
17
+ Metrics/PerceivedComplexity:
18
+ Max: 8
19
+
8
20
  Style/AccessModifierIndentation:
9
21
  EnforcedStyle: outdent
10
22
 
11
23
  Style/CaseIndentation:
12
24
  IndentWhenRelativeTo: end
13
25
 
14
- Style/ClassLength:
15
- Max: 120
16
-
17
- Style/CyclomaticComplexity:
18
- Max: 8
19
-
20
26
  Style/DotPosition:
21
27
  EnforcedStyle: trailing
22
28
 
@@ -35,9 +41,6 @@ Style/IfUnlessModifier:
35
41
  Style/IndentHash:
36
42
  EnforcedStyle: consistent
37
43
 
38
- Style/MethodLength:
39
- Max: 20
40
-
41
44
  Style/PercentLiteralDelimiters:
42
45
  PreferredDelimiters:
43
46
  '%w': '[]'
data/.travis.yml CHANGED
@@ -16,17 +16,27 @@ script:
16
16
  - '! bundle show rubocop || bundle exec rubocop' # run rubocop only if it is bundled
17
17
  before_install:
18
18
  - sudo apt-get update -qq
19
- - sudo apt-get install -qq advancecomp gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush
19
+ - sudo apt-get install -qq gifsicle jhead jpegoptim libjpeg-progs optipng pngcrush
20
20
  - npm install -g svgo
21
21
  - mkdir ~/bin
22
- # pngquant:
22
+
23
+ - echo 'Installing advancecomp(advpng):'
24
+ - ADVANCECOMP_VERSION=1.19
25
+ - wget http://downloads.sourceforge.net/project/advancemame/advancecomp/$ADVANCECOMP_VERSION/advancecomp-$ADVANCECOMP_VERSION.tar.gz
26
+ - tar -xzf advancecomp-$ADVANCECOMP_VERSION.tar.gz
27
+ - (cd advancecomp-$ADVANCECOMP_VERSION && ./configure && make)
28
+ - mv advancecomp-$ADVANCECOMP_VERSION/advpng ~/bin
29
+
30
+ - echo 'Installing pngquant:'
23
31
  - git clone git://github.com/pornel/pngquant.git
24
- - pushd pngquant && git checkout $(git describe --tags --abbrev=0) && make && popd
32
+ - (cd pngquant && git checkout $(git describe --tags --abbrev=0) && make)
25
33
  - mv pngquant/pngquant ~/bin
26
- # pngout:
27
- - wget http://static.jonof.id.au/dl/kenutils/pngout-20130221-linux.tar.gz
28
- - tar -xzf pngout-*-linux.tar.gz
29
- - mv pngout-*-linux/x86_64/pngout ~/bin
34
+
35
+ - echo 'Installing pngout:'
36
+ - PNGOUT_VERSION=20130221
37
+ - wget http://static.jonof.id.au/dl/kenutils/pngout-$PNGOUT_VERSION-linux.tar.gz
38
+ - tar -xzf pngout-$PNGOUT_VERSION-linux.tar.gz
39
+ - mv pngout-$PNGOUT_VERSION-linux/x86_64/pngout ~/bin
30
40
  env:
31
41
  - PATH=~/bin:$PATH
32
42
  matrix:
@@ -0,0 +1,209 @@
1
+ # ChangeLog
2
+
3
+ ## unreleased
4
+
5
+ ## v0.16.0 (2014-09-12)
6
+
7
+ * Wrote this ChangeLog [#62](https://github.com/toy/image_optim/issues/62) [@toy](https://github.com/toy)
8
+ * Use rubocop ~> 0.26.0 [@toy](https://github.com/toy)
9
+ * Install advancecomp from source in travis script [#61](https://github.com/toy/image_optim/issues/61) [@toy](https://github.com/toy)
10
+ * Move expansion of config path to read method and rescue with warning [#58](https://github.com/toy/image_optim/issues/58) [@toy](https://github.com/toy)
11
+ * Show workers options in verbose mode [#56](https://github.com/toy/image_optim/issues/56) [@toy](https://github.com/toy)
12
+ * Resolve all bins during initialization [#22](https://github.com/toy/image_optim/issues/22) [@toy](https://github.com/toy)
13
+ * Add exclusion glob patterns, `.*` by default [#35](https://github.com/toy/image_optim/issues/35) [#48](https://github.com/toy/image_optim/issues/48) [@toy](https://github.com/toy)
14
+ * Show better warning when running image_optim for a directory without recursive option [@toy](https://github.com/toy)
15
+ * Use stable sort for workers [@toy](https://github.com/toy)
16
+ * Check binary version instead of using which to check if binary is present [#59](https://github.com/toy/image_optim/issues/59) [@toy](https://github.com/toy)
17
+
18
+ ## v0.15.0 (2014-08-19)
19
+
20
+ * Use advpng worker before optipng [@toy](https://github.com/toy)
21
+ * Fix order of results (use progress ~> 3.0.1) [@toy](https://github.com/toy)
22
+ * Change array returned from `optimize_images`, `optimize_images!` and `optimize_images_data` to contain pairs of item and result instead of just result [@toy](https://github.com/toy)
23
+ * Fixed `Space` causing exception with negative numbers [@toy](https://github.com/toy)
24
+ * Added pngquant worker [#14](https://github.com/toy/image_optim/issues/14) [#32](https://github.com/toy/image_optim/issues/32) [#40](https://github.com/toy/image_optim/issues/40) [#52](https://github.com/toy/image_optim/issues/52) [@adammathys](https://github.com/adammathys) [@smasry](https://github.com/smasry) [@toy](https://github.com/toy)
25
+ * Add instructions to errors from bin resolver [@toy](https://github.com/toy)
26
+ * Use in_threads ~> 1.2.2 with fix for silent exceptions [@toy](https://github.com/toy)
27
+ * Fix `LocalJumpError` in railtie initializer block (ruby 2.1.2, rails 4.1.4) [#50](https://github.com/toy/image_optim/issues/50) [@schnittchen](https://github.com/schnittchen)
28
+
29
+ ## v0.14.0 (2014-07-17)
30
+
31
+ * Added Inch CI and Gittip badges to README [@toy](https://github.com/toy)
32
+ * Assign worker options to constants for documentation [@toy](https://github.com/toy)
33
+ * Code style, reorganized, comments, added rubocop [@toy](https://github.com/toy)
34
+ * Switch to rspec 3.0 [@toy](https://github.com/toy)
35
+ * Don't mention versions in instructions for installing jpegoptim and pngcrush [@toy](https://github.com/toy)
36
+
37
+ ## v0.13.3 (2014-05-22)
38
+
39
+ * Added instruction about libjpeg-turbo-utils [#49](https://github.com/toy/image_optim/issues/49) [@toy](https://github.com/toy)
40
+
41
+ ## v0.13.2 (2014-04-24)
42
+
43
+ * Updated versions of `pngcrush` and `jpegoptim` in installation instructions [#46](https://github.com/toy/image_optim/issues/46) [@toy](https://github.com/toy)
44
+ * Script for updating instructions in README [@toy](https://github.com/toy)
45
+ * Typo in README [#45](https://github.com/toy/image_optim/issues/45) [@rawsyntax](https://github.com/rawsyntax)
46
+
47
+ ## v0.13.1 (2014-04-08)
48
+
49
+ * Use image_size ~> 1.3.0 so only `FormatError` exceptions are caught and show warning [#44](https://github.com/toy/image_optim/issues/44) [@lencioni](https://github.com/lencioni)
50
+
51
+ ## v0.13.0 (2014-04-06)
52
+
53
+ * Detect and warn about broken images [#43](https://github.com/toy/image_optim/issues/43) [@toy](https://github.com/toy)
54
+ * Output image_optim version when running in verbose mode [@toy](https://github.com/toy)
55
+ * Show resolved version in version exceptions and warnings [@toy](https://github.com/toy)
56
+ * Warn if advpng version is less than 1.17 as it does not use zopfli [#17](https://github.com/toy/image_optim/issues/17) [#18](https://github.com/toy/image_optim/issues/18) [@toy](https://github.com/toy)
57
+
58
+ ## v0.12.1 (2014-03-10)
59
+
60
+ * Don't try to register preprocessors when sprockets library is not initialized (app.assets is nil) [#41](https://github.com/toy/image_optim/issues/41) [@toy](https://github.com/toy)
61
+ * Output resolved binaries when verbose [@toy](https://github.com/toy)
62
+ * Output nice level and number of threads when verbose [@toy](https://github.com/toy)
63
+ * Output config to stderr when verbose [@toy](https://github.com/toy)
64
+ * Don't limit number of threads [@toy](https://github.com/toy)
65
+
66
+ ## v0.12.0 (2014-03-02)
67
+
68
+ * Checking bin versions [#33](https://github.com/toy/image_optim/issues/33) [@toy](https://github.com/toy)
69
+
70
+ ## v0.11.2 (2014-03-01)
71
+
72
+ * Fixed building PATH environment variable [@toy](https://github.com/toy)
73
+
74
+ ## v0.11.1 (2014-02-20)
75
+
76
+ * Allow `-v` for version if it is the only argument [@toy](https://github.com/toy)
77
+ * Fixed initializing railtie [#37](https://github.com/toy/image_optim/issues/37) [@toy](https://github.com/toy)
78
+
79
+ ## v0.11.0 (2014-02-16)
80
+
81
+ * Use image_size ~> 1.2.0 [@toy](https://github.com/toy)
82
+ * Added `svgo` worker and support for svg files [#27](https://github.com/toy/image_optim/issues/27) [#30](https://github.com/toy/image_optim/issues/30) [@nybblr](https://github.com/nybblr)
83
+ * Properly unlink temporary files [#29](https://github.com/toy/image_optim/issues/29) [@toy](https://github.com/toy)
84
+ * Read options from rails app configuration `app.config.assets.image_optim` in railtie [#31](https://github.com/toy/image_optim/issues/31) [@bencrouse](https://github.com/bencrouse)
85
+ * Updated versions of `pngcrush` and `jpegoptim` in installation instructions [#26](https://github.com/toy/image_optim/issues/26) [@jc00ke](https://github.com/jc00ke)
86
+
87
+ ## v0.10.2 (2014-01-25)
88
+
89
+ * Fixed regression with progress introduced in v0.10.0 [@toy](https://github.com/toy)
90
+
91
+ ## v0.10.1 (2014-01-23)
92
+
93
+ * Ensure binary data (ruby 1.9+) from `optimize_image_data` and `optimize_images_data` [#25](https://github.com/toy/image_optim/issues/25) [@toy](https://github.com/toy)
94
+ * Mention `optimize_image_data` and `optimize_images_data` in README [#25](https://github.com/toy/image_optim/issues/25) [@toy](https://github.com/toy)
95
+
96
+ ## v0.10.0 (2013-12-25)
97
+
98
+ * Fixed bug with inheritance of `DelegateClass` in jruby 1.9 and 2.0 [@toy](https://github.com/toy)
99
+ * Return `ImagePath::Optimized` containing also original path and size from `optimize_image` and `optimize_image!` [#12](https://github.com/toy/image_optim/issues/12) [@toy](https://github.com/toy)
100
+ * Show exception backtrace when verbose [@toy](https://github.com/toy)
101
+ * Fail if there were warnings with paths to optimize [@toy](https://github.com/toy)
102
+ * Rails (sprockets) preprocessor [#2](https://github.com/toy/image_optim/issues/2) [@toy](https://github.com/toy)
103
+ * Use fspath ~> 2.1.0 with fixes for jruby 1.7.8 [@toy](https://github.com/toy)
104
+ * Add `optimize_image_data` and `optimize_images_data` [@toy](https://github.com/toy)
105
+ * Read config from `image_optim.yml` at `XDG_CONFIG_HOME` (`~/.config` by default) and from `.image_optim.yml` in current working directory [#13](https://github.com/toy/image_optim/issues/13) [@toy](https://github.com/toy)
106
+ * Added badges to README [@toy](https://github.com/toy)
107
+ * Big refactoring [@toy](https://github.com/toy)
108
+
109
+ ## v0.9.1 (2013-08-20)
110
+
111
+ * Use progress ~> 3.0.0 and in_threads ~> 1.2.0 [@toy](https://github.com/toy)
112
+
113
+ ## v0.9.0 (2013-07-30)
114
+
115
+ * Use fspath ~> 2.0.5 with bug fix for jruby in 1.8 mode [@toy](https://github.com/toy)
116
+ * Overcome wrong implementation of `Process::Status` in jruby [@toy](https://github.com/toy)
117
+ * Fix for jruby not `File.rename` not accepting non String [@toy](https://github.com/toy)
118
+ * Fix for jruby `File.rename` not accepting non String [@toy](https://github.com/toy)
119
+ * Added `.travis.yml` [@toy](https://github.com/toy)
120
+ * Added `jhead` worker [@toy](https://github.com/toy)
121
+
122
+ ## v0.8.1 (2013-05-27)
123
+
124
+ * Fixed variable name in `jpegoptim` worker [@toy](https://github.com/toy)
125
+ * Added example of using `PATH` with ImageOptim.app bins [#11](https://github.com/toy/image_optim/issues/11) [@toy](https://github.com/toy)
126
+
127
+ ## v0.8.0 (2013-03-27)
128
+
129
+ * Print options if verbose [@toy](https://github.com/toy)
130
+ * Added worker options to README using script [#5](https://github.com/toy/image_optim/issues/5) [@toy](https://github.com/toy)
131
+ * Setting worker options using arguments to image_optim bin [@toy](https://github.com/toy)
132
+ * Option definitions with description, default value and validation instead of attribute reader in options [@toy](https://github.com/toy)
133
+ * Don't change PATH for ruby process [@toy](https://github.com/toy)
134
+ * Vendor `jpegrescan` [@toy](https://github.com/toy)
135
+ * Option to use `jpegrescan` in `jpegtran` worker, off by default [#6](https://github.com/toy/image_optim/issues/6) [@toy](https://github.com/toy)
136
+
137
+ ## v0.7.3 (2013-02-24)
138
+
139
+ * Use image_size ~> 1.1.2 [@toy](https://github.com/toy)
140
+
141
+ ## v0.7.2 (2013-01-18)
142
+
143
+ * Make `apply_threading` accept enum instead of array [@toy](https://github.com/toy)
144
+
145
+ ## v0.7.1 (2013-01-17)
146
+
147
+ * Use more compatible redirect syntax `>&` [#9](https://github.com/toy/image_optim/issues/9) @"Chris Thompson"
148
+
149
+ ## v0.7.0 (2013-01-17)
150
+
151
+ * Use `system` with `env` and `nice` instead of forking [#8](https://github.com/toy/image_optim/issues/8) [@toy](https://github.com/toy)
152
+ * Don't use `-s` of `which` as it is nonstandard [#7](https://github.com/toy/image_optim/issues/7) [@toy](https://github.com/toy)
153
+ * Added bin resolving with ability to specify binary paths using environment variables [@toy](https://github.com/toy)
154
+ * Reorganized workers [@toy](https://github.com/toy)
155
+ * Added links to tool projects [@toy](https://github.com/toy)
156
+
157
+ ## v0.6.0 (2012-11-15)
158
+
159
+ * Warn if directly added files are not images or are not optimizable [@toy](https://github.com/toy)
160
+ * Recursively scan directories for images [#4](https://github.com/toy/image_optim/issues/4) [@toy](https://github.com/toy)
161
+ * Typo in bin/image_optim [#3](https://github.com/toy/image_optim/issues/3) [@fabiomcosta](https://github.com/fabiomcosta)
162
+
163
+ ## v0.5.1 (2012-08-07)
164
+
165
+ * Nice output for configuration and binary resolving errors [@toy](https://github.com/toy)
166
+
167
+ ## v0.5.0 (2012-08-05)
168
+
169
+ * Verbose output [@toy](https://github.com/toy)
170
+
171
+ ## v0.4.2 (2012-02-26)
172
+
173
+ * Use image_size ~> 1.1 [@toy](https://github.com/toy)
174
+
175
+ ## v0.4.1 (2012-02-14)
176
+
177
+ * Added binary installation instructions to README [#1](https://github.com/toy/image_optim/issues/1) [@jingoro](https://github.com/jingoro)
178
+
179
+ ## v0.4.0 (2012-01-13)
180
+
181
+ * Added usage to README [@toy](https://github.com/toy)
182
+ * Allow setting nice level, 10 by default [@toy](https://github.com/toy)
183
+ * Use `fork` instead of `system` [@toy](https://github.com/toy)
184
+
185
+ ## v0.3.2 (2012-01-12)
186
+
187
+ * Fixed setting max thread count [@toy](https://github.com/toy)
188
+
189
+ ## v0.3.1 (2012-01-12)
190
+
191
+ * Fixed parsing thread option [@toy](https://github.com/toy)
192
+
193
+ ## v0.3.0 (2012-01-12)
194
+
195
+ * Output size change per file and total [@toy](https://github.com/toy)
196
+ * Warn about non files [@toy](https://github.com/toy)
197
+
198
+ ## v0.2.1 (2012-01-11)
199
+
200
+ * Simplified determining presence of bin [@toy](https://github.com/toy)
201
+
202
+ ## v0.2.0 (2012-01-10)
203
+
204
+ * Reduce number of created temp files to minimum [@toy](https://github.com/toy)
205
+ * Use fspath ~> 2.0.3 [@toy](https://github.com/toy)
206
+
207
+ ## v0.1.0 (2012-01-09)
208
+
209
+ * Initial release [@toy](https://github.com/toy)
@@ -2,6 +2,7 @@
2
2
 
3
3
  * Create topic/feature branch: `git checkout -b awesome-changes`
4
4
  * Commit…
5
+ * Add entry to [ChangeLog](CHANGELOG.markdown)
5
6
  * Run tests: `bundle exec rspec`
6
7
  * Check code style: `bundle exec rubocop`
7
8
  * Push your branch: `git push origin awesome-changes`
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
data/README.markdown CHANGED
@@ -160,6 +160,8 @@ npm install -g svgo
160
160
  ```sh
161
161
  image_optim *.{jpg,png,gif,svg}
162
162
 
163
+ image_optim -r .
164
+
163
165
  image_optim -h
164
166
  ```
165
167
 
@@ -285,7 +287,11 @@ Worker has no options
285
287
 
286
288
  ## Contributing
287
289
 
288
- If you would like to contribute - that is great and you are very welcome. Please check few notes about [CONTRIBUTING](CONTRIBUTING.markdown).
290
+ If you would like to contribute - that is great and you are very welcome. Please check few notes in file [CONTRIBUTING.markdown](CONTRIBUTING.markdown).
291
+
292
+ ## ChangeLog
293
+
294
+ In separate file [CHANGELOG.markdown](CHANGELOG.markdown).
289
295
 
290
296
  ## Copyright
291
297
 
data/bin/image_optim CHANGED
@@ -23,11 +23,26 @@ option_parser = OptionParser.new do |op|
23
23
  |
24
24
  TEXT
25
25
 
26
- op.on('-r', '-R', '--recursive', 'Recurively scan directories '\
26
+ op.on('-r', '-R', '--recursive', 'Recursively scan directories '\
27
27
  'for images') do |recursive|
28
28
  options[:recursive] = recursive
29
29
  end
30
30
 
31
+ op.on("--exclude-dir 'GLOB'", 'Glob for excluding directories '\
32
+ '(defaults to .*)') do |glob|
33
+ options[:exclude_dir_glob] = glob
34
+ end
35
+
36
+ op.on("--exclude-file 'GLOB'", 'Glob for excluding files '\
37
+ '(defaults to .*)') do |glob|
38
+ options[:exclude_file_glob] = glob
39
+ end
40
+
41
+ op.on("--exclude 'GLOB'", 'Set glob for excluding both directories and '\
42
+ 'files') do |glob|
43
+ options[:exclude_file_glob] = options[:exclude_dir_glob] = glob
44
+ end
45
+
31
46
  op.separator nil
32
47
 
33
48
  op.on('--[no-]threads N', Integer, 'Number of threads or disable '\
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.15.0'
5
+ s.version = '0.16.0'
6
6
  s.summary = %q{Optimize (lossless compress) images (jpeg, png, gif, svg) using external utilities (advpng, gifsicle, jpegoptim, jpegtran, optipng, pngcrush, pngout, pngquant, svgo)}
7
7
  s.homepage = "http://github.com/toy/#{s.name}"
8
8
  s.authors = ['Ivan Kuchin']
@@ -15,13 +15,13 @@ Gem::Specification.new do |s|
15
15
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
16
  s.require_paths = %w[lib]
17
17
 
18
- s.add_dependency 'fspath', '~> 2.1.0'
19
- s.add_dependency 'image_size', '~> 1.3.0'
20
- s.add_dependency 'exifr', '~> 1.1.3'
21
- s.add_dependency 'progress', '~> 3.0.1'
22
- s.add_dependency 'in_threads', '~> 1.2.2'
18
+ s.add_dependency 'fspath', '~> 2.1'
19
+ s.add_dependency 'image_size', '~> 1.3'
20
+ s.add_dependency 'exifr', '~> 1.1', '>= 1.1.3'
21
+ s.add_dependency 'progress', '~> 3.0', '>= 3.0.1'
22
+ s.add_dependency 'in_threads', '~> 1.2', '>= 1.2.2'
23
23
  s.add_development_dependency 'rspec', '~> 3.0'
24
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('1.9.2')
25
- s.add_development_dependency 'rubocop', '~> 0.24.1'
24
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('1.9.3')
25
+ s.add_development_dependency 'rubocop', '~> 0.26.0'
26
26
  end
27
27
  end
data/lib/image_optim.rb CHANGED
@@ -45,8 +45,8 @@ class ImageOptim
45
45
 
46
46
  if verbose
47
47
  $stderr << config
48
- $stderr << "Nice level: #{nice}\n"
49
- $stderr << "Using threads: #{threads}\n"
48
+ $stderr << "nice: #{nice}\n"
49
+ $stderr << "threads: #{threads}\n"
50
50
  end
51
51
 
52
52
  @bin_resolver = BinResolver.new(self)
@@ -55,6 +55,8 @@ class ImageOptim
55
55
  config.for_worker(klass)
56
56
  end
57
57
 
58
+ log_workers_by_format if verbose
59
+
58
60
  config.assert_no_unused_options!
59
61
  end
60
62
 
@@ -164,18 +166,32 @@ class ImageOptim
164
166
 
165
167
  private
166
168
 
169
+ def log_workers_by_format
170
+ $stderr << "Workers by format:\n"
171
+ @workers_by_format.each do |format, workers|
172
+ $stderr << "#{format}:\n"
173
+ workers.each do |worker|
174
+ $stderr << " #{worker.class.bin_sym}:\n"
175
+ worker.options.each do |name, value|
176
+ $stderr << " #{name}: #{value.inspect}\n"
177
+ end
178
+ end
179
+ end
180
+ end
181
+
167
182
  # Create hash with format mapped to list of workers sorted by run order
168
183
  def create_workers_by_format(&options_proc)
169
184
  by_format = {}
170
- Worker.klasses.each do |klass|
171
- next unless (options = options_proc[klass])
172
- worker = klass.new(self, options)
185
+ workers = Worker.create_all(self, &options_proc)
186
+ Worker.resolve_all!(workers)
187
+ sorted = workers.sort_by.with_index{ |worker, i| [worker.run_order, i] }
188
+ sorted.each do |worker|
173
189
  worker.image_formats.each do |format|
174
190
  by_format[format] ||= []
175
191
  by_format[format] << worker
176
192
  end
177
193
  end
178
- by_format.each{ |_format, workers| workers.sort! }
194
+ by_format
179
195
  end
180
196
 
181
197
  # Run method for each item in list
@@ -58,6 +58,19 @@ class ImageOptim
58
58
  [dir, ENV['PATH'], VENDOR_PATH].compact.join(':')
59
59
  end
60
60
 
61
+ # Collect resolving errors when running block over items of enumerable
62
+ def self.collect_errors(enumerable)
63
+ errors = []
64
+ enumerable.each do |item|
65
+ begin
66
+ yield item
67
+ rescue Error => e
68
+ errors << e
69
+ end
70
+ end
71
+ errors
72
+ end
73
+
61
74
  private
62
75
 
63
76
  def resolving(name)
@@ -80,17 +93,17 @@ class ImageOptim
80
93
  end
81
94
 
82
95
  def accessible?(name)
83
- capture_output("which #{name.to_s.shellescape}") != ''
96
+ !!version(name)
84
97
  end
85
98
 
86
99
  def version(name)
87
100
  case name.to_sym
88
101
  when :advpng, :gifsicle, :jpegoptim, :optipng, :pngquant
89
- capture_output("#{name} --version")[/\d+(\.\d+){1,}/]
102
+ capture_output("#{name} --version 2> /dev/null")[/\d+(\.\d+){1,}/]
90
103
  when :svgo
91
104
  capture_output("#{name} --version 2>&1")[/\d+(\.\d+){1,}/]
92
105
  when :jhead
93
- capture_output("#{name} -V")[/\d+(\.\d+){1,}/]
106
+ capture_output("#{name} -V 2> /dev/null")[/\d+(\.\d+){1,}/]
94
107
  when :jpegtran
95
108
  capture_output("#{name} -v - 2>&1")[/version (\d+\S*)/, 1]
96
109
  when :pngcrush
@@ -98,7 +111,12 @@ class ImageOptim
98
111
  when :pngout
99
112
  date_regexp = /[A-Z][a-z]{2} (?: |\d)\d \d{4}/
100
113
  date_str = capture_output("#{name} 2>&1")[date_regexp]
101
- Date.parse(date_str).strftime('%Y%m%d')
114
+ Date.parse(date_str).strftime('%Y%m%d') if date_str
115
+ when :jpegrescan
116
+ # jpegrescan has no version so just check presence
117
+ capture_output("command -v #{name}")['jpegrescan']
118
+ else
119
+ fail "getting `#{name}` version is not defined"
102
120
  end
103
121
  end
104
122
 
@@ -10,7 +10,7 @@ class ImageOptim
10
10
  class Config
11
11
  include OptionHelpers
12
12
 
13
- CONFIG_HOME = File.expand_path(ENV['XDG_CONFIG_HOME'] || '~/.config')
13
+ CONFIG_HOME = ENV['XDG_CONFIG_HOME'] || '~/.config'
14
14
  GLOBAL_CONFIG_PATH = File.join(CONFIG_HOME, 'image_optim.yml')
15
15
  LOCAL_CONFIG_PATH = './.image_optim.yml'
16
16
 
@@ -18,25 +18,32 @@ class ImageOptim
18
18
  # Read config at GLOBAL_CONFIG_PATH if it exists, warn if anything is
19
19
  # wrong
20
20
  def global
21
- File.file?(GLOBAL_CONFIG_PATH) ? read(GLOBAL_CONFIG_PATH) : {}
21
+ read(GLOBAL_CONFIG_PATH)
22
22
  end
23
23
 
24
24
  # Read config at LOCAL_CONFIG_PATH if it exists, warn if anything is
25
25
  # wrong
26
26
  def local
27
- File.file?(LOCAL_CONFIG_PATH) ? read(LOCAL_CONFIG_PATH) : {}
27
+ read(LOCAL_CONFIG_PATH)
28
28
  end
29
29
 
30
30
  private
31
31
 
32
32
  def read(path)
33
- config = YAML.load_file(path)
33
+ begin
34
+ full_path = File.expand_path(path)
35
+ rescue ArgumentError => e
36
+ warn "Can't expand path #{path}: #{e}"
37
+ return {}
38
+ end
39
+ return {} unless File.file?(full_path)
40
+ config = YAML.load_file(full_path)
34
41
  unless config.is_a?(Hash)
35
- fail "excpected hash, got #{config.inspect}"
42
+ fail "expected hash, got #{config.inspect}"
36
43
  end
37
44
  HashHelpers.deep_symbolise_keys(config)
38
45
  rescue => e
39
- warn "exception when reading #{path}: #{e}"
46
+ warn "exception when reading #{full_path}: #{e}"
40
47
  {}
41
48
  end
42
49
  end
@@ -61,8 +68,7 @@ class ImageOptim
61
68
  def assert_no_unused_options!
62
69
  unknown_options = @options.reject{ |key, _value| @used.include?(key) }
63
70
  return if unknown_options.empty?
64
- fail ConfigurationError, "unknown options #{unknown_options.inspect} "\
65
- "for #{self}"
71
+ fail ConfigurationError, "unknown options #{unknown_options.inspect}"
66
72
  end
67
73
 
68
74
  def nice
@@ -1,5 +1,6 @@
1
1
  require 'image_optim'
2
2
  require 'image_optim/hash_helpers'
3
+ require 'image_optim/runner/glob_helpers'
3
4
  require 'image_optim/space'
4
5
  require 'progress'
5
6
  require 'optparse'
@@ -47,6 +48,10 @@ class ImageOptim
47
48
  fail 'specify paths to optimize' if args.empty?
48
49
  options = HashHelpers.deep_symbolise_keys(options)
49
50
  @recursive = options.delete(:recursive)
51
+ @exclude_dir_globs, @exclude_file_globs = %w[dir file].map do |type|
52
+ glob = options.delete(:"exclude_#{type}_glob") || '.*'
53
+ GlobHelpers.expand_braces(glob)
54
+ end
50
55
  @image_optim = ImageOptim.new(options)
51
56
  @to_optimize = find_to_optimize(args)
52
57
  end
@@ -85,14 +90,14 @@ class ImageOptim
85
90
  else
86
91
  warning "#{path} is not an image or there is no optimizer for it"
87
92
  end
88
- elsif @recursive
89
- if File.directory?(path)
93
+ elsif File.directory?(path)
94
+ if @recursive
90
95
  to_optimize += find_to_optimize_recursive(path)
91
96
  else
92
- warning "#{path} is not a file or a directory or does not exist"
97
+ warning "#{path} is a directory, use --recursive option"
93
98
  end
94
99
  else
95
- warning "#{path} is not a file or does not exist"
100
+ warning "#{path} is not a file or a directory or does not exist"
96
101
  end
97
102
  end
98
103
  to_optimize
@@ -101,13 +106,36 @@ class ImageOptim
101
106
  def find_to_optimize_recursive(dir)
102
107
  to_optimize = []
103
108
  Find.find(dir) do |path|
104
- next unless File.file?(path)
105
- next unless @image_optim.optimizable?(path)
106
- to_optimize << path
109
+ if File.file?(path)
110
+ next if exclude_file?(dir, path)
111
+ next unless @image_optim.optimizable?(path)
112
+ to_optimize << path
113
+ elsif File.directory?(path)
114
+ Find.prune if dir != path && exclude_dir?(dir, path)
115
+ end
107
116
  end
108
117
  to_optimize
109
118
  end
110
119
 
120
+ def exclude_dir?(dir, path)
121
+ exclude?(dir, path, @exclude_dir_globs)
122
+ end
123
+
124
+ def exclude_file?(dir, path)
125
+ exclude?(dir, path, @exclude_file_globs)
126
+ end
127
+
128
+ # Check if any of globs matches either part of path relative from dir or
129
+ # just basename
130
+ def exclude?(dir, path, globs)
131
+ relative_path = Pathname(path).relative_path_from(Pathname(dir)).to_s
132
+ basename = File.basename(path)
133
+ globs.any? do |glob|
134
+ File.fnmatch(glob, relative_path, File::FNM_PATHNAME) ||
135
+ File.fnmatch(glob, basename, File::FNM_PATHNAME)
136
+ end
137
+ end
138
+
111
139
  def warning(message)
112
140
  @warnings = true
113
141
  warn message
@@ -0,0 +1,45 @@
1
+ class ImageOptim
2
+ class Runner
3
+ # Helper methods for glob
4
+ module GlobHelpers
5
+ class << self
6
+ # Match inner curly braces in glob
7
+ # Negative lookbehind is not used as is not supported by ruby before 1.9
8
+ BRACE_REGEXP = /
9
+ \A
10
+ (
11
+ (?:.*[^\\]|) # anything ending not with slash or nothing
12
+ (?:\\\\)* # any number of self escaped slashes
13
+ )
14
+ \{ # open brace
15
+ (
16
+ (?:|.*?[^\\]) # nothing or non greedy anything ending not with slash
17
+ (?:\\\\)* # any number of self escaped slashes
18
+ )
19
+ \} # close brace
20
+ (
21
+ .* # what is left
22
+ )
23
+ \z
24
+ /x
25
+
26
+ # Expand curly braces in glob as fnmatch in ruby before 2.0 doesn't
27
+ # support them
28
+ def expand_braces(original_glob)
29
+ expanded = []
30
+ unexpanded = [original_glob]
31
+ while (glob = unexpanded.shift)
32
+ if (m = BRACE_REGEXP.match(glob))
33
+ m[2].split(',', -1).each do |variant|
34
+ unexpanded << "#{m[1]}#{variant}#{m[3]}"
35
+ end
36
+ else
37
+ expanded << glob
38
+ end
39
+ end
40
+ expanded.uniq
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -37,6 +37,24 @@ class ImageOptim
37
37
  option_definitions <<
38
38
  OptionDefinition.new(name, default, type, description, &proc)
39
39
  end
40
+
41
+ # Initialize all workers using options from calling options_proc with
42
+ # klass
43
+ def create_all(image_optim, &options_proc)
44
+ Worker.klasses.map do |klass|
45
+ next unless (options = options_proc[klass])
46
+ klass.new(image_optim, options)
47
+ end.compact
48
+ end
49
+
50
+ # Resolve all bins of all workers failing with one joint exception
51
+ def resolve_all!(workers)
52
+ errors = BinResolver.collect_errors(workers) do |worker|
53
+ worker.resolve_used_bins!
54
+ end
55
+ return if errors.empty?
56
+ fail BinResolver::Error, ['Bin resolving errors:', *errors].join("\n")
57
+ end
40
58
  end
41
59
 
42
60
  # Configure (raises on extra options)
@@ -60,6 +78,13 @@ class ImageOptim
60
78
  assert_no_unknown_options!(options)
61
79
  end
62
80
 
81
+ # Return hash with worker options
82
+ def options
83
+ self.class.option_definitions.each_with_object({}) do |option, h|
84
+ h[option.name] = send(option.name)
85
+ end
86
+ end
87
+
63
88
  # Optimize image at src, output at dst, must be overriden in subclass
64
89
  # return true on success
65
90
  def optimize(_src, _dst)
@@ -80,8 +105,18 @@ class ImageOptim
80
105
  0
81
106
  end
82
107
 
83
- def <=>(other)
84
- run_order <=> other.run_order
108
+ # List of bins used by worker
109
+ def used_bins
110
+ [self.class.bin_sym]
111
+ end
112
+
113
+ # Resolve used bins, raise exception mergin all messages
114
+ def resolve_used_bins!
115
+ errors = BinResolver.collect_errors(used_bins) do |bin|
116
+ @image_optim.resolve_bin!(bin)
117
+ end
118
+ return if errors.empty?
119
+ fail BinResolver::Error, wrap_resolver_error_message(errors.join(', '))
85
120
  end
86
121
 
87
122
  # Check if operation resulted in optimized file
@@ -103,9 +138,14 @@ class ImageOptim
103
138
  def resolve_bin!(bin)
104
139
  @image_optim.resolve_bin!(bin)
105
140
  rescue BinResolver::Error => e
141
+ raise e, wrap_resolver_error_message(e.message), e.backtrace
142
+ end
143
+
144
+ def wrap_resolver_error_message(message)
106
145
  name = self.class.bin_sym
107
- raise e, "#{name} worker: #{e.message}; please provide proper binary or "\
108
- "disable this worker (`:#{name} => false`)", e.backtrace
146
+ "#{name} worker: #{message}; please provide proper binary or "\
147
+ "disable this worker (--no-#{name} argument or "\
148
+ "`:#{name} => false` through options)"
109
149
  end
110
150
 
111
151
  # Run command setting priority and hiding output
@@ -17,6 +17,10 @@ class ImageOptim
17
17
  -10
18
18
  end
19
19
 
20
+ def used_bins
21
+ [:jhead, :jpegtran]
22
+ end
23
+
20
24
  def optimize(src, dst)
21
25
  if (2..8).include?(EXIFR::JPEG.new(src.to_s).orientation.to_i)
22
26
  src.copy(dst)
@@ -17,6 +17,10 @@ class ImageOptim
17
17
  option(:jpegrescan, false, 'Use jpegtran through jpegrescan, '\
18
18
  'ignore progressive option'){ |v| !!v }
19
19
 
20
+ def used_bins
21
+ jpegrescan ? [:jpegtran, :jpegrescan] : [:jpegtran]
22
+ end
23
+
20
24
  def optimize(src, dst)
21
25
  if jpegrescan
22
26
  args = %W[#{src} #{dst}]
@@ -15,6 +15,7 @@ describe ImageOptim::BinResolver do
15
15
 
16
16
  it 'should resolve bin in path' do
17
17
  with_env 'LS_BIN', nil do
18
+ allow(resolver).to receive(:version).with(:ls).and_return('xxx')
18
19
  expect(resolver).to receive(:accessible?).with(:ls).once.and_return(true)
19
20
  expect(FSPath).not_to receive(:temp_dir)
20
21
 
@@ -28,12 +29,29 @@ describe ImageOptim::BinResolver do
28
29
  end
29
30
  end
30
31
 
32
+ it 'should fail to resolve unknown bin' do
33
+ with_env 'LS_BIN', nil do
34
+ expect(FSPath).not_to receive(:temp_dir)
35
+
36
+ 5.times do
37
+ expect do
38
+ resolver.resolve!(:ls)
39
+ end.to raise_error RuntimeError
40
+ end
41
+ expect(resolver.env_path).to eq([
42
+ ENV['PATH'],
43
+ ImageOptim::BinResolver::VENDOR_PATH,
44
+ ].join(':'))
45
+ end
46
+ end
47
+
31
48
  it 'should resolve bin specified in ENV' do
32
49
  path = 'some/path/image_optim2.3.4'
33
50
  with_env 'IMAGE_OPTIM_BIN', path do
34
51
  tmpdir = double(:tmpdir, :to_str => 'tmpdir')
35
52
  symlink = double(:symlink)
36
53
 
54
+ allow(resolver).to receive(:version).with(:image_optim).and_return('xxx')
37
55
  expect(resolver).to receive(:accessible?).
38
56
  with(:image_optim).once.and_return(true)
39
57
  expect(FSPath).to receive(:temp_dir).
@@ -63,20 +81,15 @@ describe ImageOptim::BinResolver do
63
81
  end
64
82
 
65
83
  it 'should raise on failure to resolve bin' do
66
- with_env 'SHOULD_NOT_EXIST_BIN', nil do
67
- expect(resolver).to receive(:accessible?).
68
- with(:should_not_exist).once.and_return(false)
84
+ with_env 'PATH', nil do
69
85
  expect(FSPath).not_to receive(:temp_dir)
70
86
 
71
87
  5.times do
72
88
  expect do
73
- resolver.resolve!(:should_not_exist)
89
+ resolver.resolve!(:jpegtran)
74
90
  end.to raise_error ImageOptim::BinResolver::BinNotFound
75
91
  end
76
- expect(resolver.env_path).to eq([
77
- ENV['PATH'],
78
- ImageOptim::BinResolver::VENDOR_PATH,
79
- ].join(':'))
92
+ expect(resolver.env_path).to eq(ImageOptim::BinResolver::VENDOR_PATH)
80
93
  end
81
94
  end
82
95
 
@@ -118,6 +131,7 @@ describe ImageOptim::BinResolver do
118
131
 
119
132
  it 'should resolve bin only once' do
120
133
  with_env 'LS_BIN', nil do
134
+ allow(resolver).to receive(:version).with(:ls).and_return('xxx')
121
135
  expect(resolver).to receive(:resolve?).once.with(:ls){ sleep 0.1; true }
122
136
 
123
137
  10.times.map do
@@ -60,7 +60,11 @@ describe ImageOptim::Config do
60
60
  end
61
61
 
62
62
  describe 'for_worker' do
63
- Abc = Class.new(ImageOptim::Worker) do
63
+ Abc = Class.new do
64
+ def self.bin_sym
65
+ :abc
66
+ end
67
+
64
68
  def image_formats
65
69
  []
66
70
  end
@@ -96,17 +100,7 @@ describe ImageOptim::Config do
96
100
  end
97
101
 
98
102
  describe 'global' do
99
- it 'should return empty hash for global config if it does not exists' do
100
- expect(File).to receive(:file?).
101
- with(Config::GLOBAL_CONFIG_PATH).and_return(false)
102
- expect(Config).not_to receive(:read)
103
-
104
- expect(Config.global).to eq({})
105
- end
106
-
107
- it 'should read global config if it exists' do
108
- expect(File).to receive(:file?).
109
- with(Config::GLOBAL_CONFIG_PATH).and_return(true)
103
+ it 'should call read with GLOBAL_CONFIG_PATH' do
110
104
  expect(Config).to receive(:read).
111
105
  with(Config::GLOBAL_CONFIG_PATH).and_return(:config => true)
112
106
 
@@ -115,17 +109,7 @@ describe ImageOptim::Config do
115
109
  end
116
110
 
117
111
  describe 'local' do
118
- it 'should return empty hash for local config if it does not exists' do
119
- expect(File).to receive(:file?).
120
- with(Config::LOCAL_CONFIG_PATH).and_return(false)
121
- expect(Config).not_to receive(:read)
122
-
123
- expect(Config.local).to eq({})
124
- end
125
-
126
- it 'should read local config if it exists' do
127
- expect(File).to receive(:file?).
128
- with(Config::LOCAL_CONFIG_PATH).and_return(true)
112
+ it 'should call read with LOCAL_CONFIG_PATH' do
129
113
  expect(Config).to receive(:read).
130
114
  with(Config::LOCAL_CONFIG_PATH).and_return(:config => true)
131
115
 
@@ -134,30 +118,65 @@ describe ImageOptim::Config do
134
118
  end
135
119
 
136
120
  describe 'read' do
121
+ let(:path){ double(:path) }
122
+ let(:full_path){ double(:full_path) }
123
+
124
+ it 'should warn if expand path fails' do
125
+ expect(Config).to receive(:warn)
126
+ expect(File).to receive(:expand_path).
127
+ with(path).and_raise(ArgumentError)
128
+ expect(File).not_to receive(:file?)
129
+
130
+ expect(Config.send(:read, path)).to eq({})
131
+ end
132
+
133
+ it 'should return empty hash if path is not a file' do
134
+ expect(Config).not_to receive(:warn)
135
+ expect(File).to receive(:expand_path).
136
+ with(path).and_return(full_path)
137
+ expect(File).to receive(:file?).
138
+ with(full_path).and_return(false)
139
+
140
+ expect(Config.send(:read, path)).to eq({})
141
+ end
142
+
137
143
  it 'should return hash with deep symbolised keys from reader' do
138
144
  stringified = {'config' => {'this' => true}}
139
145
  symbolized = {:config => {:this => true}}
140
146
 
141
- path = double(:path)
142
- expect(YAML).to receive(:load_file).with(path).and_return(stringified)
147
+ expect(Config).not_to receive(:warn)
148
+ expect(File).to receive(:expand_path).
149
+ with(path).and_return(full_path)
150
+ expect(File).to receive(:file?).
151
+ with(full_path).and_return(true)
152
+ expect(YAML).to receive(:load_file).
153
+ with(full_path).and_return(stringified)
143
154
 
144
- expect(Config.instance_eval{ read(path) }).to eq(symbolized)
155
+ expect(Config.send(:read, path)).to eq(symbolized)
145
156
  end
146
157
 
147
158
  it 'should warn and return an empty hash if reader returns non hash' do
148
- path = double(:path)
149
- expect(YAML).to receive(:load_file).with(path).and_return([:config])
150
159
  expect(Config).to receive(:warn)
160
+ expect(File).to receive(:expand_path).
161
+ with(path).and_return(full_path)
162
+ expect(File).to receive(:file?).
163
+ with(full_path).and_return(true)
164
+ expect(YAML).to receive(:load_file).
165
+ with(full_path).and_return([:config])
151
166
 
152
- expect(Config.instance_eval{ read(path) }).to eq({})
167
+ expect(Config.send(:read, path)).to eq({})
153
168
  end
154
169
 
155
170
  it 'should warn and return an empty hash if reader raises exception' do
156
- path = double(:path)
157
- expect(YAML).to receive(:load_file).with(path).and_raise
158
171
  expect(Config).to receive(:warn)
172
+ expect(File).to receive(:expand_path).
173
+ with(path).and_return(full_path)
174
+ expect(File).to receive(:file?).
175
+ with(full_path).and_return(true)
176
+ expect(YAML).to receive(:load_file).
177
+ with(full_path).and_raise
159
178
 
160
- expect(Config.instance_eval{ read(path) }).to eq({})
179
+ expect(Config.send(:read, path)).to eq({})
161
180
  end
162
181
  end
163
182
  end
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
2
+ require 'rspec'
3
+ require 'image_optim/runner/glob_helpers'
4
+
5
+ describe ImageOptim::Runner::GlobHelpers do
6
+ GH = ImageOptim::Runner::GlobHelpers
7
+
8
+ describe :expand_braces do
9
+ {
10
+ 'hello.world' => %w[hello.world],
11
+ '{hello,.world}' => %w[hello .world],
12
+ 'hello{.,!}world' => %w[hello.world hello!world],
13
+ '{a,b},{c,d}' => %w[a,c b,c a,d b,d],
14
+ '{{a,b},{c,d}}' => %w[a b c d],
15
+ '{a,b,{c,d}}' => %w[a b c d],
16
+ '{\{a,b\},\{c,d\}}' => %w[\\{a b\\} \\{c d\\}],
17
+ 'test{ing,}' => %w[testing test],
18
+ }.each do |glob, expected|
19
+ it "should expand #{glob}" do
20
+ expect(GH.expand_braces(glob)).to match_array(expected)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -6,13 +6,12 @@ describe ImageOptim::Worker do
6
6
  Worker = ImageOptim::Worker
7
7
 
8
8
  describe 'optimize' do
9
- it 'should raise NotImplementedError unless overriden' do
10
- class Abc < ImageOptim::Worker; end
11
-
9
+ it 'should raise NotImplementedError' do
12
10
  image_optim = ImageOptim.new
11
+ worker = Worker.new(image_optim, {})
13
12
 
14
13
  expect do
15
- Abc.new(image_optim, {}).optimize(double, double)
14
+ worker.optimize(double, double)
16
15
  end.to raise_error NotImplementedError
17
16
  end
18
17
  end
@@ -67,7 +67,9 @@ describe ImageOptim do
67
67
  expect(path).to receive(:format).and_return(format)
68
68
 
69
69
  workers = image_optim.workers_for_image(path)
70
- expect(workers).to eq(workers.sort)
70
+ expect(workers).to eq(workers.sort_by.with_index do |worker, i|
71
+ [worker.run_order, i]
72
+ end)
71
73
  end
72
74
  end
73
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: image_optim
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.0
4
+ version: 0.16.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ivan Kuchin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-18 00:00:00.000000000 Z
11
+ date: 2014-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fspath
@@ -16,33 +16,36 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 2.1.0
19
+ version: '2.1'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 2.1.0
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: image_size
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ~>
32
32
  - !ruby/object:Gem::Version
33
- version: 1.3.0
33
+ version: '1.3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ~>
39
39
  - !ruby/object:Gem::Version
40
- version: 1.3.0
40
+ version: '1.3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: exifr
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ - - ! '>='
46
49
  - !ruby/object:Gem::Version
47
50
  version: 1.1.3
48
51
  type: :runtime
@@ -50,6 +53,9 @@ dependencies:
50
53
  version_requirements: !ruby/object:Gem::Requirement
51
54
  requirements:
52
55
  - - ~>
56
+ - !ruby/object:Gem::Version
57
+ version: '1.1'
58
+ - - ! '>='
53
59
  - !ruby/object:Gem::Version
54
60
  version: 1.1.3
55
61
  - !ruby/object:Gem::Dependency
@@ -57,6 +63,9 @@ dependencies:
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
65
  - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ - - ! '>='
60
69
  - !ruby/object:Gem::Version
61
70
  version: 3.0.1
62
71
  type: :runtime
@@ -64,6 +73,9 @@ dependencies:
64
73
  version_requirements: !ruby/object:Gem::Requirement
65
74
  requirements:
66
75
  - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '3.0'
78
+ - - ! '>='
67
79
  - !ruby/object:Gem::Version
68
80
  version: 3.0.1
69
81
  - !ruby/object:Gem::Dependency
@@ -71,6 +83,9 @@ dependencies:
71
83
  requirement: !ruby/object:Gem::Requirement
72
84
  requirements:
73
85
  - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: '1.2'
88
+ - - ! '>='
74
89
  - !ruby/object:Gem::Version
75
90
  version: 1.2.2
76
91
  type: :runtime
@@ -78,6 +93,9 @@ dependencies:
78
93
  version_requirements: !ruby/object:Gem::Requirement
79
94
  requirements:
80
95
  - - ~>
96
+ - !ruby/object:Gem::Version
97
+ version: '1.2'
98
+ - - ! '>='
81
99
  - !ruby/object:Gem::Version
82
100
  version: 1.2.2
83
101
  - !ruby/object:Gem::Dependency
@@ -100,14 +118,14 @@ dependencies:
100
118
  requirements:
101
119
  - - ~>
102
120
  - !ruby/object:Gem::Version
103
- version: 0.24.1
121
+ version: 0.26.0
104
122
  type: :development
105
123
  prerelease: false
106
124
  version_requirements: !ruby/object:Gem::Requirement
107
125
  requirements:
108
126
  - - ~>
109
127
  - !ruby/object:Gem::Version
110
- version: 0.24.1
128
+ version: 0.26.0
111
129
  description:
112
130
  email:
113
131
  executables:
@@ -118,6 +136,7 @@ files:
118
136
  - .gitignore
119
137
  - .rubocop.yml
120
138
  - .travis.yml
139
+ - CHANGELOG.markdown
121
140
  - CONTRIBUTING.markdown
122
141
  - Gemfile
123
142
  - LICENSE.txt
@@ -139,6 +158,7 @@ files:
139
158
  - lib/image_optim/option_helpers.rb
140
159
  - lib/image_optim/railtie.rb
141
160
  - lib/image_optim/runner.rb
161
+ - lib/image_optim/runner/glob_helpers.rb
142
162
  - lib/image_optim/space.rb
143
163
  - lib/image_optim/true_false_nil.rb
144
164
  - lib/image_optim/worker.rb
@@ -160,6 +180,7 @@ files:
160
180
  - spec/image_optim/handler_spec.rb
161
181
  - spec/image_optim/hash_helpers_spec.rb
162
182
  - spec/image_optim/image_path_spec.rb
183
+ - spec/image_optim/runner/glob_helpers_spec.rb
163
184
  - spec/image_optim/space_spec.rb
164
185
  - spec/image_optim/worker_spec.rb
165
186
  - spec/image_optim_spec.rb
@@ -220,6 +241,7 @@ test_files:
220
241
  - spec/image_optim/handler_spec.rb
221
242
  - spec/image_optim/hash_helpers_spec.rb
222
243
  - spec/image_optim/image_path_spec.rb
244
+ - spec/image_optim/runner/glob_helpers_spec.rb
223
245
  - spec/image_optim/space_spec.rb
224
246
  - spec/image_optim/worker_spec.rb
225
247
  - spec/image_optim_spec.rb