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"
gem "appraisal"
gem "fog"
gem "bundler"
gem "cocaine"
......@@ -9,6 +9,7 @@ GEM
mime-types
xml-simple
builder (3.0.0)
cocaine (0.0.2)
columnize (0.3.2)
excon (0.5.2)
fog (0.5.2)
......@@ -46,6 +47,7 @@ DEPENDENCIES
appraisal
aws-s3
bundler
cocaine
fog
mocha
rake
......
......@@ -5,6 +5,7 @@ gem "ruby-debug"
gem "rails", "~>2.3.0"
gem "rake"
gem "sqlite3-ruby", "~>1.3.0"
gem "cocaine"
gem "shoulda"
gem "mocha"
gem "bundler"
......
......@@ -19,6 +19,7 @@ GEM
mime-types
xml-simple
builder (3.0.0)
cocaine (0.0.2)
columnize (0.3.2)
excon (0.5.7)
fog (0.7.1)
......@@ -64,6 +65,7 @@ DEPENDENCIES
appraisal
aws-s3
bundler
cocaine
fog
mocha
rails (~> 2.3.0)
......
......@@ -5,6 +5,7 @@ gem "ruby-debug"
gem "rails", "~>3.0.0"
gem "rake"
gem "sqlite3-ruby", "~>1.3.0"
gem "cocaine"
gem "shoulda"
gem "mocha"
gem "bundler"
......
......@@ -37,6 +37,7 @@ GEM
mime-types
xml-simple
builder (2.1.2)
cocaine (0.0.2)
columnize (0.3.2)
erubis (2.6.6)
abstract (>= 1.0.0)
......@@ -105,6 +106,7 @@ DEPENDENCIES
appraisal
aws-s3
bundler
cocaine
fog
mocha
rails (~> 3.0.0)
......
......@@ -39,8 +39,8 @@ require 'paperclip/style'
require 'paperclip/attachment'
require 'paperclip/storage'
require 'paperclip/callback_compatability'
require 'paperclip/command_line'
require 'paperclip/railtie'
require 'cocaine'
if defined?(Rails.root) && Rails.root
Dir.glob(File.join(File.expand_path(Rails.root), "lib", "paperclip_processors", "*.rb")).each do |processor|
require processor
......@@ -87,7 +87,7 @@ module Paperclip
# symlink them so they are all in the same directory.
#
# 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.
# These codes should be passed as a hash as the last argument, like so:
#
......@@ -100,8 +100,8 @@ module Paperclip
if options[:image_magick_path]
Paperclip.log("[DEPRECATION] :image_magick_path is deprecated and will be removed. Use :command_path instead")
end
CommandLine.path = options[:command_path] || options[:image_magick_path]
CommandLine.new(cmd, *params).run
Cocaine::CommandLine.path = options[:command_path] || options[:image_magick_path]
Cocaine::CommandLine.new(cmd, *params).run
end
def processor name #:nodoc:
......@@ -143,14 +143,6 @@ module Paperclip
class PaperclipError < StandardError #:nodoc:
end
class PaperclipCommandLineError < PaperclipError #:nodoc:
attr_accessor :output
def initialize(msg = nil, output = nil)
super(msg)
@output = output
end
end
class StorageMethodNotFound < PaperclipError
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
file = file.path if file.respond_to? "path"
geometry = begin
Paperclip.run("identify", "-format %wx%h :file", :file => "#{file}[0]")
rescue PaperclipCommandLineError
rescue Cocaine::CommandLineError
""
end
parse(geometry) ||
......
......@@ -59,7 +59,7 @@ module Paperclip
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))
rescue PaperclipCommandLineError => e
rescue Cocaine::CommandLineError => e
raise PaperclipError, "There was an error processing the thumbnail for #{@basename}" if @whiny
end
......
......@@ -26,6 +26,7 @@ spec = Gem::Specification.new do |s|
s.requirements << "ImageMagick"
s.add_dependency 'activerecord', '>=2.3.0'
s.add_dependency 'activesupport', '>=2.3.2'
s.add_dependency 'cocaine', '>=0.0.2'
s.add_development_dependency 'shoulda'
s.add_development_dependency 'appraisal'
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'
class PaperclipTest < Test::Unit::TestCase
context "Calling Paperclip.run" do
setup do
Paperclip.options[:image_magick_path] = nil
Paperclip.options[:command_path] = nil
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
should "run the command with Cocaine" do
Cocaine::CommandLine.expects(:new).with("convert", "stuff").returns(stub(:run))
Paperclip.run("convert", "stuff")
end
end
......
......@@ -91,8 +91,10 @@ class ThumbnailTest < Test::Unit::TestCase
end
should "send the right command to convert when sent #make" do
Paperclip::CommandLine.expects(:"`").with do |arg|
arg.match %r{convert ["']#{File.expand_path(@thumb.file.path)}\[0\]["'] -resize ["']x50["'] -crop ["']100x50\+114\+0["'] \+repage ["'].*?["']}
Paperclip.expects(:run).with do |arg|
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
@thumb.make
end
......@@ -115,8 +117,10 @@ class ThumbnailTest < Test::Unit::TestCase
end
should "send the right command to convert when sent #make" do
Paperclip::CommandLine.expects(:"`").with do |arg|
arg.match %r{convert -strip ["']#{File.expand_path(@thumb.file.path)}\[0\]["'] -resize ["']x50["'] -crop ["']100x50\+114\+0["'] \+repage ["'].*?["']}
Paperclip.expects(:run).with do |arg|
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
@thumb.make
end
......@@ -153,8 +157,10 @@ class ThumbnailTest < Test::Unit::TestCase
end
should "send the right command to convert when sent #make" do
Paperclip::CommandLine.expects(:"`").with do |arg|
arg.match %r{convert ["']#{File.expand_path(@thumb.file.path)}\[0\]["'] -resize ["']x50["'] -crop ["']100x50\+114\+0["'] \+repage -strip -depth 8 ["'].*?["']}
Paperclip.expects(:run).with do |arg|
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
@thumb.make
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