Commit f0d15d91 by Jon Yurek

Extracted the CommandLine class into the Cocaine gem.

parent 13d51e31
...@@ -8,3 +8,4 @@ gem "sqlite3-ruby", "~>1.3.0" ...@@ -8,3 +8,4 @@ gem "sqlite3-ruby", "~>1.3.0"
gem "appraisal" gem "appraisal"
gem "fog" gem "fog"
gem "bundler" gem "bundler"
gem "cocaine"
...@@ -9,6 +9,7 @@ GEM ...@@ -9,6 +9,7 @@ GEM
mime-types mime-types
xml-simple xml-simple
builder (3.0.0) builder (3.0.0)
cocaine (0.0.2)
columnize (0.3.2) columnize (0.3.2)
excon (0.5.2) excon (0.5.2)
fog (0.5.2) fog (0.5.2)
...@@ -46,6 +47,7 @@ DEPENDENCIES ...@@ -46,6 +47,7 @@ DEPENDENCIES
appraisal appraisal
aws-s3 aws-s3
bundler bundler
cocaine
fog fog
mocha mocha
rake rake
......
...@@ -5,6 +5,7 @@ gem "ruby-debug" ...@@ -5,6 +5,7 @@ gem "ruby-debug"
gem "rails", "~>2.3.0" gem "rails", "~>2.3.0"
gem "rake" gem "rake"
gem "sqlite3-ruby", "~>1.3.0" gem "sqlite3-ruby", "~>1.3.0"
gem "cocaine"
gem "shoulda" gem "shoulda"
gem "mocha" gem "mocha"
gem "bundler" gem "bundler"
......
...@@ -19,6 +19,7 @@ GEM ...@@ -19,6 +19,7 @@ GEM
mime-types mime-types
xml-simple xml-simple
builder (3.0.0) builder (3.0.0)
cocaine (0.0.2)
columnize (0.3.2) columnize (0.3.2)
excon (0.5.7) excon (0.5.7)
fog (0.7.1) fog (0.7.1)
...@@ -64,6 +65,7 @@ DEPENDENCIES ...@@ -64,6 +65,7 @@ DEPENDENCIES
appraisal appraisal
aws-s3 aws-s3
bundler bundler
cocaine
fog fog
mocha mocha
rails (~> 2.3.0) rails (~> 2.3.0)
......
...@@ -5,6 +5,7 @@ gem "ruby-debug" ...@@ -5,6 +5,7 @@ gem "ruby-debug"
gem "rails", "~>3.0.0" gem "rails", "~>3.0.0"
gem "rake" gem "rake"
gem "sqlite3-ruby", "~>1.3.0" gem "sqlite3-ruby", "~>1.3.0"
gem "cocaine"
gem "shoulda" gem "shoulda"
gem "mocha" gem "mocha"
gem "bundler" gem "bundler"
......
...@@ -37,6 +37,7 @@ GEM ...@@ -37,6 +37,7 @@ GEM
mime-types mime-types
xml-simple xml-simple
builder (2.1.2) builder (2.1.2)
cocaine (0.0.2)
columnize (0.3.2) columnize (0.3.2)
erubis (2.6.6) erubis (2.6.6)
abstract (>= 1.0.0) abstract (>= 1.0.0)
...@@ -105,6 +106,7 @@ DEPENDENCIES ...@@ -105,6 +106,7 @@ DEPENDENCIES
appraisal appraisal
aws-s3 aws-s3
bundler bundler
cocaine
fog fog
mocha mocha
rails (~> 3.0.0) rails (~> 3.0.0)
......
...@@ -39,8 +39,8 @@ require 'paperclip/style' ...@@ -39,8 +39,8 @@ require 'paperclip/style'
require 'paperclip/attachment' require 'paperclip/attachment'
require 'paperclip/storage' require 'paperclip/storage'
require 'paperclip/callback_compatability' require 'paperclip/callback_compatability'
require 'paperclip/command_line'
require 'paperclip/railtie' require 'paperclip/railtie'
require 'cocaine'
if defined?(Rails.root) && Rails.root if defined?(Rails.root) && Rails.root
Dir.glob(File.join(File.expand_path(Rails.root), "lib", "paperclip_processors", "*.rb")).each do |processor| Dir.glob(File.join(File.expand_path(Rails.root), "lib", "paperclip_processors", "*.rb")).each do |processor|
require processor require processor
...@@ -87,7 +87,7 @@ module Paperclip ...@@ -87,7 +87,7 @@ module Paperclip
# symlink them so they are all in the same directory. # symlink them so they are all in the same directory.
# #
# If the command returns with a result code that is not one of the # If the command returns with a result code that is not one of the
# expected_outcodes, a PaperclipCommandLineError will be raised. Generally # expected_outcodes, a Cocaine::CommandLineError will be raised. Generally
# a code of 0 is expected, but a list of codes may be passed if necessary. # a code of 0 is expected, but a list of codes may be passed if necessary.
# These codes should be passed as a hash as the last argument, like so: # These codes should be passed as a hash as the last argument, like so:
# #
...@@ -100,8 +100,8 @@ module Paperclip ...@@ -100,8 +100,8 @@ module Paperclip
if options[:image_magick_path] if options[:image_magick_path]
Paperclip.log("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead") Paperclip.log("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
end end
CommandLine.path = options[:command_path] || options[:image_magick_path] Cocaine::CommandLine.path = options[:command_path] || options[:image_magick_path]
CommandLine.new(cmd, *params).run Cocaine::CommandLine.new(cmd, *params).run
end end
def processor name #:nodoc: def processor name #:nodoc:
...@@ -143,14 +143,6 @@ module Paperclip ...@@ -143,14 +143,6 @@ module Paperclip
class PaperclipError < StandardError #:nodoc: class PaperclipError < StandardError #:nodoc:
end end
class PaperclipCommandLineError < PaperclipError #:nodoc:
attr_accessor :output
def initialize(msg = nil, output = nil)
super(msg)
@output = output
end
end
class StorageMethodNotFound < PaperclipError class StorageMethodNotFound < PaperclipError
end end
......
module Paperclip
class CommandLine
class << self
attr_accessor :path
end
def initialize(binary, params = "", options = {})
@binary = binary.dup
@params = params.dup
@options = options.dup
@swallow_stderr = @options.has_key?(:swallow_stderr) ? @options.delete(:swallow_stderr) : Paperclip.options[:swallow_stderr]
@expected_outcodes = @options.delete(:expected_outcodes)
@expected_outcodes ||= [0]
end
def command
cmd = []
cmd << full_path(@binary)
cmd << interpolate(@params, @options)
cmd << bit_bucket if @swallow_stderr
cmd.join(" ")
end
def run
Paperclip.log(command)
begin
output = self.class.send(:'`', command)
rescue Errno::ENOENT
raise Paperclip::CommandNotFoundError
end
if $?.exitstatus == 127
raise Paperclip::CommandNotFoundError
end
unless @expected_outcodes.include?($?.exitstatus)
raise Paperclip::PaperclipCommandLineError, "Command '#{command}' returned #{$?.exitstatus}. Expected #{@expected_outcodes.join(", ")}"
end
output
end
private
def full_path(binary)
[self.class.path, binary].compact.join("/")
end
def interpolate(pattern, vars)
# interpolates :variables and :{variables}
pattern.gsub(%r#:(?:\w+|\{\w+\})#) do |match|
key = match[1..-1]
key = key[1..-2] if key[0,1] == '{'
if invalid_variables.include?(key)
raise PaperclipCommandLineError,
"Interpolation of #{key} isn't allowed."
end
interpolation(vars, key) || match
end
end
def invalid_variables
%w(expected_outcodes swallow_stderr)
end
def interpolation(vars, key)
if vars.key?(key.to_sym)
shell_quote(vars[key.to_sym])
end
end
def shell_quote(string)
return "" if string.nil? or string.blank?
if self.class.unix?
string.split("'").map{|m| "'#{m}'" }.join("\\'")
else
%{"#{string}"}
end
end
def bit_bucket
self.class.unix? ? "2>/dev/null" : "2>NUL"
end
def self.unix?
File.exist?("/dev/null")
end
end
end
...@@ -17,7 +17,7 @@ module Paperclip ...@@ -17,7 +17,7 @@ module Paperclip
file = file.path if file.respond_to? "path" file = file.path if file.respond_to? "path"
geometry = begin geometry = begin
Paperclip.run("identify", "-format %wx%h :file", :file => "#{file}[0]") Paperclip.run("identify", "-format %wx%h :file", :file => "#{file}[0]")
rescue PaperclipCommandLineError rescue Cocaine::CommandLineError
"" ""
end end
parse(geometry) || parse(geometry) ||
......
...@@ -59,7 +59,7 @@ module Paperclip ...@@ -59,7 +59,7 @@ module Paperclip
parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ") parameters = parameters.flatten.compact.join(" ").strip.squeeze(" ")
success = Paperclip.run("convert", parameters, :source => "#{File.expand_path(src.path)}[0]", :dest => File.expand_path(dst.path)) success = Paperclip.run("convert", parameters, :source => "#{File.expand_path(src.path)}[0]", :dest => File.expand_path(dst.path))
rescue PaperclipCommandLineError => e rescue Cocaine::CommandLineError => e
raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny
end end
......
...@@ -26,6 +26,7 @@ spec = Gem::Specification.new do |s| ...@@ -26,6 +26,7 @@ spec = Gem::Specification.new do |s|
s.requirements << "ImageMagick" s.requirements << "ImageMagick"
s.add_dependency 'activerecord', '>=2.3.0' s.add_dependency 'activerecord', '>=2.3.0'
s.add_dependency 'activesupport', '>=2.3.2' s.add_dependency 'activesupport', '>=2.3.2'
s.add_dependency 'cocaine', '>=0.0.2'
s.add_development_dependency 'shoulda' s.add_development_dependency 'shoulda'
s.add_development_dependency 'appraisal' s.add_development_dependency 'appraisal'
s.add_development_dependency 'mocha' s.add_development_dependency 'mocha'
......
require './test/helper'
class CommandLineTest < Test::Unit::TestCase
def setup
Paperclip::CommandLine.path = nil
File.stubs(:exist?).with("/dev/null").returns(true)
end
should "allow colons in parameters" do
cmd = Paperclip::CommandLine.new("convert", "'a.jpg' -resize 175x220> -size 175x220 xc:black +swap -gravity center -composite 'b.jpg'", :swallow_stderr => false)
assert_equal "convert 'a.jpg' -resize 175x220> -size 175x220 xc:black +swap -gravity center -composite 'b.jpg'", cmd.command
end
should "take a command and parameters and produce a shell command for bash" do
cmd = Paperclip::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
assert_equal "convert a.jpg b.png", cmd.command
end
should "be able to set a path and produce commands with that path" do
Paperclip::CommandLine.path = "/opt/bin"
cmd = Paperclip::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
assert_equal "/opt/bin/convert a.jpg b.png", cmd.command
end
should "be able to interpolate quoted variables into the parameters" do
cmd = Paperclip::CommandLine.new("convert",
":one :{two}",
:one => "a.jpg",
:two => "b.png",
:swallow_stderr => false)
assert_equal "convert 'a.jpg' 'b.png'", cmd.command
end
should "quote command line options differently if we're on windows" do
File.stubs(:exist?).with("/dev/null").returns(false)
cmd = Paperclip::CommandLine.new("convert",
":one :{two}",
:one => "a.jpg",
:two => "b.png",
:swallow_stderr => false)
assert_equal 'convert "a.jpg" "b.png"', cmd.command
end
should "be able to quote and interpolate dangerous variables" do
cmd = Paperclip::CommandLine.new("convert",
":one :two",
:one => "`rm -rf`.jpg",
:two => "ha'ha.png",
:swallow_stderr => false)
assert_equal "convert '`rm -rf`.jpg' 'ha'\\''ha.png'", cmd.command
end
should "be able to quote and interpolate dangerous variables even on windows" do
File.stubs(:exist?).with("/dev/null").returns(false)
cmd = Paperclip::CommandLine.new("convert",
":one :two",
:one => "`rm -rf`.jpg",
:two => "ha'ha.png",
:swallow_stderr => false)
assert_equal %{convert "`rm -rf`.jpg" "ha'ha.png"}, cmd.command
end
should "add redirection to get rid of stderr in bash" do
File.stubs(:exist?).with("/dev/null").returns(true)
cmd = Paperclip::CommandLine.new("convert",
"a.jpg b.png",
:swallow_stderr => true)
assert_equal "convert a.jpg b.png 2>/dev/null", cmd.command
end
should "add redirection to get rid of stderr in cmd.exe" do
File.stubs(:exist?).with("/dev/null").returns(false)
cmd = Paperclip::CommandLine.new("convert",
"a.jpg b.png",
:swallow_stderr => true)
assert_equal "convert a.jpg b.png 2>NUL", cmd.command
end
should "raise if trying to interpolate :swallow_stderr or :expected_outcodes" do
cmd = Paperclip::CommandLine.new("convert",
":swallow_stderr :expected_outcodes",
:swallow_stderr => false,
:expected_outcodes => [0, 1])
assert_raise(Paperclip::PaperclipCommandLineError) do
cmd.command
end
end
should "run the #command it's given and return the output" do
cmd = Paperclip::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
cmd.class.stubs(:"`").with("convert a.jpg b.png").returns(:correct_value)
with_exitstatus_returning(0) do
assert_equal :correct_value, cmd.run
end
end
should "raise a PaperclipCommandLineError if the result code isn't expected" do
cmd = Paperclip::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
cmd.class.stubs(:"`").with("convert a.jpg b.png").returns(:correct_value)
with_exitstatus_returning(1) do
assert_raises(Paperclip::PaperclipCommandLineError) do
cmd.run
end
end
end
should "not raise a PaperclipCommandLineError if the result code is expected" do
cmd = Paperclip::CommandLine.new("convert",
"a.jpg b.png",
:expected_outcodes => [0, 1],
:swallow_stderr => false)
cmd.class.stubs(:"`").with("convert a.jpg b.png").returns(:correct_value)
with_exitstatus_returning(1) do
assert_nothing_raised do
cmd.run
end
end
end
should "log the command" do
cmd = Paperclip::CommandLine.new("convert", "a.jpg b.png", :swallow_stderr => false)
cmd.class.stubs(:'`')
Paperclip.expects(:log).with("convert a.jpg b.png")
cmd.run
end
should "detect that the system is unix or windows based on presence of /dev/null" do
File.stubs(:exist?).returns(true)
assert Paperclip::CommandLine.unix?
end
should "detect that the system is not unix or windows based on absence of /dev/null" do
File.stubs(:exist?).returns(false)
assert ! Paperclip::CommandLine.unix?
end
end
...@@ -2,44 +2,9 @@ require './test/helper' ...@@ -2,44 +2,9 @@ require './test/helper'
class PaperclipTest < Test::Unit::TestCase class PaperclipTest < Test::Unit::TestCase
context "Calling Paperclip.run" do context "Calling Paperclip.run" do
setup do should "run the command with Cocaine" do
Paperclip.options[:image_magick_path] = nil Cocaine::CommandLine.expects(:new).with("convert", "stuff").returns(stub(:run))
Paperclip.options[:command_path] = nil Paperclip.run("convert", "stuff")
Paperclip::CommandLine.stubs(:'`')
end
should "execute the right command with :image_magick_path" do
Paperclip.options[:image_magick_path] = "/usr/bin"
Paperclip.expects(:log).with(includes('[DEPRECATION]'))
Paperclip.expects(:log).with(regexp_matches(%r{/usr/bin/convert ['"]one.jpg['"] ['"]two.jpg['"]}))
Paperclip::CommandLine.expects(:"`").with(regexp_matches(%r{/usr/bin/convert ['"]one.jpg['"] ['"]two.jpg['"]}))
Paperclip.run("convert", ":one :two", :one => "one.jpg", :two => "two.jpg")
end
should "execute the right command with :command_path" do
Paperclip.options[:command_path] = "/usr/bin"
Paperclip::CommandLine.expects(:"`").with(regexp_matches(%r{/usr/bin/convert ['"]one.jpg['"] ['"]two.jpg['"]}))
Paperclip.run("convert", ":one :two", :one => "one.jpg", :two => "two.jpg")
end
should "execute the right command with no path" do
Paperclip::CommandLine.expects(:"`").with(regexp_matches(%r{convert ['"]one.jpg['"] ['"]two.jpg['"]}))
Paperclip.run("convert", ":one :two", :one => "one.jpg", :two => "two.jpg")
end
should "tell you the command isn't there if the shell returns 127" do
with_exitstatus_returning(127) do
assert_raises(Paperclip::CommandNotFoundError) do
Paperclip.run("command")
end
end
end
should "tell you the command isn't there if an ENOENT is raised" do
assert_raises(Paperclip::CommandNotFoundError) do
Paperclip::CommandLine.stubs(:"`").raises(Errno::ENOENT)
Paperclip.run("command")
end
end end
end end
......
...@@ -91,8 +91,10 @@ class ThumbnailTest < Test::Unit::TestCase ...@@ -91,8 +91,10 @@ class ThumbnailTest < Test::Unit::TestCase
end end
should "send the right command to convert when sent #make" do should "send the right command to convert when sent #make" do
Paperclip::CommandLine.expects(:"`").with do |arg| Paperclip.expects(:run).with do |arg|
arg.match %r{convert ["']#{File.expand_path(@thumb.file.path)}\[0\]["'] -resize ["']x50["'] -crop ["']100x50\+114\+0["'] \+repage ["'].*?["']} arg[0] == 'convert' &&
arg[1] == ':source -resize "x50" -crop "100x50+114+0" +repage :dest' &&
arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
end end
@thumb.make @thumb.make
end end
...@@ -115,8 +117,10 @@ class ThumbnailTest < Test::Unit::TestCase ...@@ -115,8 +117,10 @@ class ThumbnailTest < Test::Unit::TestCase
end end
should "send the right command to convert when sent #make" do should "send the right command to convert when sent #make" do
Paperclip::CommandLine.expects(:"`").with do |arg| Paperclip.expects(:run).with do |arg|
arg.match %r{convert -strip ["']#{File.expand_path(@thumb.file.path)}\[0\]["'] -resize ["']x50["'] -crop ["']100x50\+114\+0["'] \+repage ["'].*?["']} arg[0] == 'convert' &&
arg[1] == '-strip :source -resize "x50" -crop "100x50+114+0" +repage :dest' &&
arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
end end
@thumb.make @thumb.make
end end
...@@ -153,8 +157,10 @@ class ThumbnailTest < Test::Unit::TestCase ...@@ -153,8 +157,10 @@ class ThumbnailTest < Test::Unit::TestCase
end end
should "send the right command to convert when sent #make" do should "send the right command to convert when sent #make" do
Paperclip::CommandLine.expects(:"`").with do |arg| Paperclip.expects(:run).with do |arg|
arg.match %r{convert ["']#{File.expand_path(@thumb.file.path)}\[0\]["'] -resize ["']x50["'] -crop ["']100x50\+114\+0["'] \+repage -strip -depth 8 ["'].*?["']} arg[0] == 'convert' &&
arg[1] == ':source -resize "x50" -crop "100x50+114+0" +repage -strip -depth 8 :dest' &&
arg[2][:source] == "#{File.expand_path(@thumb.file.path)}[0]"
end end
@thumb.make @thumb.make
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment