image_optim 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
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