callisto 0.9

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.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *#
19
+ .#*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in callisto.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Daniel Mircea
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Callisto
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'callisto'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install callisto
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rake/testtask"
4
+
5
+ task :default => :test
6
+
7
+ Rake::TestTask.new do |t|
8
+ t.pattern = "spec/**/*_spec.rb"
9
+ end
data/callisto.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/callisto/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Daniel Mircea"]
6
+ gem.email = ["daniel@thegeek.ro"]
7
+ gem.description = "Image thumbnails on the fly"
8
+ gem.summary = "Callisto"
9
+ gem.homepage = "https://github.com/viseztrance/callisto"
10
+
11
+ gem.add_development_dependency "minitest"
12
+
13
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ gem.name = "callisto"
17
+ gem.require_paths = ["lib"]
18
+ gem.version = Callisto::VERSION
19
+ end
data/lib/callisto.rb ADDED
@@ -0,0 +1,19 @@
1
+ $LOAD_PATH << File.dirname(__FILE__)
2
+
3
+ require "callisto/version"
4
+ require "callisto/configuration"
5
+ require "callisto/shell"
6
+ require "callisto/pool"
7
+ require "callisto/thumbnail"
8
+
9
+ module Callisto
10
+
11
+ def self.configuration
12
+ @configuration ||= Configuration.new
13
+ end
14
+
15
+ def self.configure
16
+ yield configuration
17
+ end
18
+
19
+ end
@@ -0,0 +1,44 @@
1
+ module Callisto
2
+
3
+ class Configuration
4
+
5
+ module Defaults
6
+
7
+ POOL = {
8
+ :identifier => proc { |task| task.command },
9
+ :callback => proc { |task| task.run },
10
+ :max_workers => 4
11
+ }
12
+
13
+ end
14
+
15
+ attr_accessor :thumbnail_defaults
16
+
17
+ def initialize
18
+ self.thumbnail_defaults = {}
19
+ load_defaults
20
+ end
21
+
22
+ def load_defaults
23
+ Pool.settings = Defaults::POOL
24
+ end
25
+
26
+ def max_workers=(val)
27
+ Pool.settings.max_workers = val
28
+ end
29
+
30
+ def method_missing(method, *args, &block)
31
+ if /^thumbnail_(?<name>[a-z\_]+)(?<setter>=)?/ =~ method
32
+ if setter
33
+ self.thumbnail_defaults[name] = args.first
34
+ else
35
+ thumbnail_defaults[name]
36
+ end
37
+ else
38
+ super
39
+ end
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,65 @@
1
+ require "singleton"
2
+ require "ostruct"
3
+
4
+ module Callisto
5
+
6
+ class Pool
7
+
8
+ include Singleton
9
+
10
+ attr_accessor :queue, :running, :pending, :workers
11
+
12
+ class << self
13
+
14
+ def settings=(options)
15
+ defaults = {
16
+ :max_workers => 10,
17
+ :identifier => proc { |entry| entry.object_id },
18
+ :callback => proc { |entry| entry.call }
19
+ }
20
+ @@settings = OpenStruct.new(defaults.merge(options))
21
+ end
22
+
23
+ def settings
24
+ @@settings
25
+ end
26
+
27
+ end
28
+
29
+ def initialize
30
+ self.pending, self.running, self.workers = [], [], []
31
+ self.queue = Queue.new
32
+ 1.upto(self.class.settings.max_workers) do
33
+ worker = Thread.new do
34
+ loop do
35
+ task = self.queue.pop
36
+ self.pending.delete self.class.settings.identifier.call(task)
37
+ self.running << self.class.settings.identifier.call(task)
38
+ self.class.settings.callback.call(task)
39
+ self.running.delete self.class.settings.identifier.call(task)
40
+ end
41
+ end
42
+ self.workers << worker
43
+ end
44
+ end
45
+
46
+ def wait(id = nil)
47
+ sleep(0.1) while (id ? processes.include?(id) : processes.any?)
48
+ end
49
+
50
+ def <<(task)
51
+ identifier = self.class.settings.identifier.call(task)
52
+ if !processes.include?(identifier)
53
+ self.pending << identifier
54
+ self.queue << task
55
+ end
56
+ identifier
57
+ end
58
+
59
+ def processes
60
+ pending + running
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -0,0 +1,31 @@
1
+ module Callisto
2
+
3
+ class Shell
4
+
5
+ attr_accessor :executable, :arguments
6
+
7
+ def self.bin_path=(path)
8
+ @@bin_path = path
9
+ end
10
+
11
+ def initialize(executable, arguments)
12
+ self.executable = executable
13
+ self.arguments = arguments
14
+ end
15
+
16
+ def command
17
+ prefix = if defined?(@@bin_path)
18
+ File.join(@@bin_path, executable)
19
+ else
20
+ executable
21
+ end
22
+ "#{prefix} #{arguments}"
23
+ end
24
+
25
+ def run
26
+ `#{command}`.chomp
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,80 @@
1
+ require "digest"
2
+ require "fileutils"
3
+
4
+ module Callisto
5
+
6
+ class Thumbnail
7
+
8
+ attr_accessor :file_path, :args, :flag
9
+ attr_reader :name, :crop
10
+ attr_writer :extension, :root_path, :prefix, :public_path, :size, :quality
11
+
12
+ def initialize(args = {})
13
+ args.each do |name, value|
14
+ self.send("#{name}=", value)
15
+ end
16
+ self.name = args
17
+ end
18
+
19
+ def name=(value)
20
+ token = Digest::MD5.hexdigest(file_path.gsub(root_path.to_s, "") + value.to_s)
21
+ @name = token + extension
22
+ end
23
+
24
+ def save
25
+ location = File.join(root_path, prefix)
26
+ if !File.exist?(save_path)
27
+ FileUtils.mkdir_p(location) unless File.directory?(location)
28
+ task = Shell.new("convert", "#{file_path} -strip -quality #{quality || 90} -resize #{size}#{flag} #{crop} #{save_path}")
29
+ pid = Callisto::Pool.instance << task
30
+ Callisto::Pool.instance.wait(pid)
31
+ end
32
+ public_path
33
+ end
34
+
35
+ def save_path
36
+ File.join(root_path, prefix, name)
37
+ end
38
+
39
+ def public_path
40
+ File.join((@public_path || Callisto.configuration.thumbnail_public_path).to_s, name)
41
+ end
42
+
43
+ def crop=(value)
44
+ @crop = "-gravity Center -crop #{size}+0+0 +repage" if value
45
+ end
46
+
47
+ def extension
48
+ @extension || Callisto.configuration.thumbnail_extension || File.extname(file_path)
49
+ end
50
+
51
+ %w(root_path prefix size quality).each do |attr|
52
+ define_method attr do
53
+ instance_variable_get("@#{attr}") || Callisto.configuration.send("thumbnail_#{attr}")
54
+ end
55
+ end
56
+
57
+ def fixed_size=(val)
58
+ self.min_size = val
59
+ self.crop = true
60
+ end
61
+
62
+ def min_size=(val)
63
+ self.flag = "^"
64
+ self.size = val
65
+ end
66
+
67
+ def max_size=(val)
68
+ self.size = val
69
+ self.flag = "\\>"
70
+ self.crop = true
71
+ end
72
+
73
+ def geometry
74
+ task = Shell.new("identify", "-format \"%wx%h\" #{save_path}")
75
+ task.run
76
+ end
77
+
78
+ end
79
+
80
+ end
@@ -0,0 +1,3 @@
1
+ module Callisto
2
+ VERSION = "0.9"
3
+ end
@@ -0,0 +1,20 @@
1
+ require "minitest/autorun"
2
+ require File.expand_path("../minitest_helper", __FILE__)
3
+
4
+ describe "Callisto" do
5
+
6
+ it "should have a configuration" do
7
+ Callisto.configuration.must_be_instance_of Callisto::Configuration
8
+ end
9
+
10
+ it "must cache configuration" do
11
+ Callisto.configuration.object_id.must_equal Callisto.configuration.object_id
12
+ end
13
+
14
+ it "yields the current configuration" do
15
+ Callisto.configure do |config|
16
+ config.must_equal Callisto.configuration
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,23 @@
1
+ require "minitest/autorun"
2
+ require File.expand_path("../minitest_helper", __FILE__)
3
+
4
+ describe "Configuration" do
5
+
6
+ it "should assign max workers to pool" do
7
+ Callisto.configure do |config|
8
+ config.max_workers = 13
9
+ end
10
+ Callisto::Pool.settings.max_workers.must_equal 13
11
+ end
12
+
13
+ it "should assign thumbnail defaults" do
14
+ Callisto.configure do |config|
15
+ config.thumbnail_size = "20x45"
16
+ config.thumbnail_quality = 75
17
+ end
18
+
19
+ Callisto.configuration.thumbnail_size.must_equal "20x45"
20
+ Callisto.configuration.thumbnail_quality.must_equal 75
21
+ end
22
+
23
+ end
Binary file
@@ -0,0 +1,8 @@
1
+ require File.expand_path("../support/file_creator", __FILE__)
2
+ require File.expand_path("../support/singleton", __FILE__)
3
+ require File.expand_path("../lib/callisto", File.dirname(__FILE__))
4
+
5
+ def reset_pool
6
+ Callisto::Pool.settings = {}
7
+ Callisto::Pool.reset_instance
8
+ end
data/spec/pool_spec.rb ADDED
@@ -0,0 +1,157 @@
1
+ require "minitest/autorun"
2
+ require File.expand_path("../minitest_helper", __FILE__)
3
+
4
+ describe "Pool" do
5
+
6
+ before do
7
+ reset_pool
8
+ end
9
+
10
+ describe "when assigning a task" do
11
+
12
+ before do
13
+ Callisto::Pool.settings = {
14
+ :max_workers => 10,
15
+ :identifier => proc { |task| task.path },
16
+ :callback => proc { |task| task.save }
17
+ }
18
+ end
19
+
20
+ it "should run a task" do
21
+ file = FileCreator.new("callback.txt")
22
+ Callisto::Pool.instance << file
23
+ Callisto::Pool.instance.wait
24
+ File.exist?(file.path).must_equal true
25
+ File.unlink(file.path)
26
+ end
27
+
28
+ it "should run tasks in parallel" do
29
+ file1 = FileCreator.new("file1.txt")
30
+ file2 = FileCreator.new("file2.txt")
31
+ file3 = FileCreator.new("file3.txt")
32
+ Callisto::Pool.settings.callback = proc { |task| task.save(1.0) }
33
+ start_time = Time.now
34
+ Callisto::Pool.instance << file1
35
+ Callisto::Pool.instance << file2
36
+ Callisto::Pool.instance << file3
37
+ Callisto::Pool.instance.wait
38
+ end_time = Time.now
39
+ (end_time - start_time).must_be :<, 2
40
+ File.exist?(file1.path).must_equal true
41
+ File.exist?(file2.path).must_equal true
42
+ File.exist?(file3.path).must_equal true
43
+ File.unlink(file1.path, file2.path, file3.path)
44
+ end
45
+
46
+ end
47
+
48
+ describe "when running the same (identical) task more than once" do
49
+
50
+ before do
51
+ Callisto::Pool.settings = {
52
+ :identifier => proc { |task| task[:id] },
53
+ :callback => proc { |task| task[:data].call }
54
+ }
55
+ end
56
+
57
+ it "adding a task should return the id" do
58
+ id1 = Callisto::Pool.instance << { :id => 1, :data => proc { sleep 1 } }
59
+ id2 = Callisto::Pool.instance << { :id => 1, :data => proc { sleep 1 } }
60
+ id3 = Callisto::Pool.instance << { :id => 2, :data => proc { sleep 1 } }
61
+ sleep 0.1
62
+ id1.must_equal id2
63
+ id1.wont_equal id3
64
+ end
65
+
66
+ it "should not run the task" do
67
+ Callisto::Pool.instance << { :id => 1, :data => proc { sleep 1 } }
68
+ 4.times {
69
+ Callisto::Pool.instance << { :id => 2, :data => proc { sleep 1 } }
70
+ }
71
+ sleep 0.1
72
+ Callisto::Pool.instance.running.count.must_equal 2
73
+ end
74
+
75
+ it "should not stack duplicates" do
76
+ Callisto::Pool.instance << { :id => 1, :data => proc { sleep 1 } }
77
+ 4.times {
78
+ Callisto::Pool.instance << { :id => 2, :data => proc { sleep 1 } }
79
+ }
80
+ Callisto::Pool.instance << { :id => 3, :data => proc { sleep 1 } }
81
+ Callisto::Pool.instance.processes.count.must_equal 3
82
+ end
83
+
84
+ end
85
+
86
+ describe "when max tasks reached" do
87
+
88
+ before do
89
+ Callisto::Pool.settings.max_workers = 2
90
+ end
91
+
92
+ it "should not run more than the max allowed processes at the same time" do
93
+ 3.times {
94
+ Callisto::Pool.instance << proc { sleep 1 }
95
+ }
96
+ sleep 0.1
97
+ Callisto::Pool.instance.running.count.must_equal 2
98
+ end
99
+
100
+ it "should stack incoming tasks" do
101
+ 5.times {
102
+ Callisto::Pool.instance << proc { sleep 1 }
103
+ }
104
+ sleep 0.1
105
+ Callisto::Pool.instance.pending.count.must_equal 3
106
+ end
107
+
108
+ end
109
+
110
+ describe "when task is finished" do
111
+
112
+ it "should be removed from the running list" do
113
+ 3.times {
114
+ Callisto::Pool.instance << proc { sleep 1 }
115
+ }
116
+ sleep 0.1
117
+ Callisto::Pool.instance.running.count.must_equal 3
118
+ Callisto::Pool.instance.wait
119
+ Callisto::Pool.instance.running.count.must_equal 0
120
+ end
121
+
122
+ it "should run the first pending task" do
123
+ Callisto::Pool.settings = {
124
+ :max_workers => 1,
125
+ :callback => proc { |task| task.save(0.5) }
126
+ }
127
+ file1 = FileCreator.new("file1.txt")
128
+ file2 = FileCreator.new("file2.txt")
129
+ Callisto::Pool.instance << file1
130
+ Callisto::Pool.instance << file2
131
+ sleep 0.1
132
+ Callisto::Pool.instance.running.count.must_equal 1
133
+ Callisto::Pool.instance.wait
134
+ File.exist?(file1.path).must_equal true
135
+ File.exist?(file2.path).must_equal true
136
+ File.unlink(file1.path, file2.path)
137
+ end
138
+
139
+ it "should remove pending task from the stack" do
140
+ Callisto::Pool.settings = {
141
+ :max_workers => 1,
142
+ :identifier => proc { |task| task[:id] },
143
+ :callback => proc { |task| task[:data].call }
144
+ }
145
+ id1 = Callisto::Pool.instance << { :id => 1, :data => proc { sleep 0.4 } }
146
+ id2 = Callisto::Pool.instance << { :id => 2, :data => proc { sleep 0.4 } }
147
+ sleep 0.1
148
+ Callisto::Pool.instance.pending.must_equal([id2])
149
+ Callisto::Pool.instance.wait(id1)
150
+ Callisto::Pool.instance.running.must_equal([id2])
151
+ Callisto::Pool.instance.wait(id2)
152
+ Callisto::Pool.instance.running.must_equal([])
153
+ end
154
+
155
+ end
156
+
157
+ end
@@ -0,0 +1,21 @@
1
+ require "tmpdir"
2
+ require "fileutils"
3
+
4
+ class FileCreator
5
+
6
+ attr_accessor :file_name
7
+
8
+ def initialize(value)
9
+ self.file_name = value
10
+ end
11
+
12
+ def save(wait = 0)
13
+ sleep wait
14
+ FileUtils.touch path
15
+ end
16
+
17
+ def path
18
+ File.join(Dir.tmpdir, file_name)
19
+ end
20
+
21
+ end
@@ -0,0 +1,27 @@
1
+ # Reset singleton
2
+ # http://blog.ardes.com/2006/12/11/testing-singletons-with-ruby
3
+
4
+ require "singleton"
5
+
6
+ class << Singleton
7
+
8
+ def included_with_reset(klass)
9
+
10
+ included_without_reset(klass)
11
+
12
+ class << klass
13
+
14
+ def reset_instance
15
+ Singleton.send :__init__, self
16
+ self
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+ alias_method :included_without_reset, :included
24
+
25
+ alias_method :included, :included_with_reset
26
+
27
+ end
@@ -0,0 +1,108 @@
1
+ require "minitest/autorun"
2
+ require File.expand_path("../minitest_helper", __FILE__)
3
+
4
+ def cleanup(path)
5
+ matcher = File.join(path, "*.*")
6
+ Dir[matcher].each { |entry| File.unlink(entry) }
7
+ end
8
+
9
+ describe "Thumbnail" do
10
+
11
+ before do
12
+ reset_pool
13
+ Callisto.configuration.load_defaults
14
+ end
15
+
16
+ describe "when saving" do
17
+
18
+ before do
19
+ @options = {
20
+ :file_path => File.expand_path("fixtures/normal-photo.png", File.dirname(__FILE__)),
21
+ :root_path => File.expand_path("../tmp", File.dirname(__FILE__)),
22
+ :prefix => "images",
23
+ :size => "50x50",
24
+ :extension => ".jpg"
25
+ }
26
+ end
27
+
28
+ after do
29
+ cleanup(File.join(@options[:root_path], @options[:prefix]))
30
+ end
31
+
32
+ it "should write the file at the specified location" do
33
+ thumbnail = Callisto::Thumbnail.new(@options)
34
+ File.exist?(thumbnail.save_path).must_equal false
35
+ thumbnail.save
36
+ File.exist?(thumbnail.save_path).must_equal true
37
+ end
38
+
39
+ it "should change file extension to the new value" do
40
+ @options.merge!(:extension => ".gif")
41
+ thumbnail = Callisto::Thumbnail.new(@options)
42
+ File.extname(thumbnail.save_path).must_equal ".gif"
43
+ end
44
+
45
+ it "should preserve file extension" do
46
+ @options.delete(:extension)
47
+ thumbnail = Callisto::Thumbnail.new(@options)
48
+ thumbnail.save
49
+ File.extname(thumbnail.save_path).must_equal ".png"
50
+ File.exist?(thumbnail.save_path).must_equal true
51
+ end
52
+
53
+ it "should return the public file path" do
54
+ @options.merge!({ :public_path => "http://localhost:3000/images" })
55
+ thumbnail = Callisto::Thumbnail.new(@options)
56
+ thumbnail.save.must_equal "http://localhost:3000/images/#{thumbnail.name}"
57
+ end
58
+
59
+ end
60
+
61
+ describe "resizing the image" do
62
+
63
+ before do
64
+ @options = {
65
+ :file_path => File.expand_path("fixtures/normal-photo.png", File.dirname(__FILE__)),
66
+ :root_path => File.expand_path("../tmp", File.dirname(__FILE__)),
67
+ :prefix => "images"
68
+ }
69
+ end
70
+
71
+ after do
72
+ cleanup(File.join(@options[:root_path], @options[:prefix]))
73
+ end
74
+
75
+ it "should scale image to the specified size" do
76
+ @options.merge!({ :fixed_size => "50x50" })
77
+ thumbnail = Callisto::Thumbnail.new(@options)
78
+ thumbnail.save
79
+ thumbnail.geometry.must_equal "50x50"
80
+ end
81
+
82
+ it "should scale image within the specified size" do
83
+ @options.merge!({ :max_size => "50x50" })
84
+ thumbnail = Callisto::Thumbnail.new(@options)
85
+ thumbnail.save
86
+ thumbnail.geometry.must_equal "50x31"
87
+ end
88
+
89
+ it "should scale image larger then specified size" do
90
+ @options.merge!({ :min_size => "50x50" })
91
+ thumbnail = Callisto::Thumbnail.new(@options)
92
+ thumbnail.save
93
+ thumbnail.geometry.must_equal "80x50"
94
+ end
95
+
96
+ end
97
+
98
+ it "should inherit and fallback configuration" do
99
+ Callisto.configure do |config|
100
+ config.thumbnail_root_path = "some/path"
101
+ config.thumbnail_prefix = "img"
102
+ end
103
+ thumbnail = Callisto::Thumbnail.new(:fixed_size => "125x125", :file_path => "some_file.txt")
104
+ thumbnail.root_path.must_equal "some/path"
105
+ thumbnail.prefix.must_equal "img"
106
+ end
107
+
108
+ end
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: callisto
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.9'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniel Mircea
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: &25241560 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: *25241560
25
+ description: Image thumbnails on the fly
26
+ email:
27
+ - daniel@thegeek.ro
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - Gemfile
34
+ - LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - callisto.gemspec
38
+ - lib/callisto.rb
39
+ - lib/callisto/configuration.rb
40
+ - lib/callisto/pool.rb
41
+ - lib/callisto/shell.rb
42
+ - lib/callisto/thumbnail.rb
43
+ - lib/callisto/version.rb
44
+ - spec/callisto_spec.rb
45
+ - spec/configuration_spec.rb
46
+ - spec/fixtures/normal-photo.png
47
+ - spec/minitest_helper.rb
48
+ - spec/pool_spec.rb
49
+ - spec/support/file_creator.rb
50
+ - spec/support/singleton.rb
51
+ - spec/thumbnail_spec.rb
52
+ homepage: https://github.com/viseztrance/callisto
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubyforge_project:
72
+ rubygems_version: 1.8.10
73
+ signing_key:
74
+ specification_version: 3
75
+ summary: Callisto
76
+ test_files:
77
+ - spec/callisto_spec.rb
78
+ - spec/configuration_spec.rb
79
+ - spec/fixtures/normal-photo.png
80
+ - spec/minitest_helper.rb
81
+ - spec/pool_spec.rb
82
+ - spec/support/file_creator.rb
83
+ - spec/support/singleton.rb
84
+ - spec/thumbnail_spec.rb
85
+ has_rdoc: