lib/airbrake/capistrano.rb in airbrake-3.1.12 vs lib/airbrake/capistrano.rb in airbrake-3.1.13
- old
+ new
@@ -1,10 +1,66 @@
# Defines deploy:notify_airbrake which will send information about the deploy to Airbrake.
require 'capistrano'
module Airbrake
module Capistrano
+ # What follows is a copy-paste backport of the shellescape method
+ # included in Ruby 1.9 and greater. The FSF's guidance on a snippet
+ # of this size indicates that such a small function is not subject
+ # to copyright and as such there is no risk of a license conflict:
+ # See www.gnu.org/prep/maintain/maintain.html#Legally-Significant
+ #
+ # Escapes a string so that it can be safely used in a Bourne shell
+ # command line. +str+ can be a non-string object that responds to
+ # +to_s+.
+ #
+ # Note that a resulted string should be used unquoted and is not
+ # intended for use in double quotes nor in single quotes.
+ #
+ # argv = Shellwords.escape("It's better to give than to receive")
+ # argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
+ #
+ # String#shellescape is a shorthand for this function.
+ #
+ # argv = "It's better to give than to receive".shellescape
+ # argv #=> "It\\'s\\ better\\ to\\ give\\ than\\ to\\ receive"
+ #
+ # # Search files in lib for method definitions
+ # pattern = "^[ \t]*def "
+ # open("| grep -Ern #{pattern.shellescape} lib") { |grep|
+ # grep.each_line { |line|
+ # file, lineno, matched_line = line.split(':', 3)
+ # # ...
+ # }
+ # }
+ #
+ # It is the caller's responsibility to encode the string in the right
+ # encoding for the shell environment where this string is used.
+ #
+ # Multibyte characters are treated as multibyte characters, not bytes.
+ #
+ # Returns an empty quoted String if +str+ has a length of zero.
+ def self.shellescape(str)
+ str = str.to_s
+
+ # An empty argument will be skipped, so return empty quotes.
+ return "''" if str.empty?
+
+ str = str.dup
+
+ # Treat multibyte characters as is. It is caller's responsibility
+ # to encode the string in the right encoding for the shell
+ # environment.
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")
+
+ # A LF cannot be escaped with a backslash because a backslash + LF
+ # combo is regarded as line continuation and simply ignored.
+ str.gsub!(/\n/, "'\n'")
+
+ return str
+ end
+
def self.load_into(configuration)
configuration.load do
after "deploy", "airbrake:deploy"
after "deploy:migrations", "airbrake:deploy"
after "deploy:cold", "airbrake:deploy"
@@ -16,12 +72,12 @@
DESC
task :deploy, :except => { :no_release => true } do
rails_env = fetch(:rails_env, "production")
airbrake_env = fetch(:airbrake_env, fetch(:rails_env, "production"))
local_user = ENV['USER'] || ENV['USERNAME']
- executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'rake')
+ executable = RUBY_PLATFORM.downcase.include?('mswin') ? fetch(:rake, 'rake.bat') : fetch(:rake, 'bundle exec rake ')
directory = configuration.release_path
- notify_command = "cd #{directory}; #{executable} RAILS_ENV=#{rails_env} airbrake:deploy TO=#{airbrake_env} REVISION=#{current_revision} REPO=#{repository} USER=#{local_user}"
+ notify_command = "cd #{directory}; #{executable} RAILS_ENV=#{rails_env} airbrake:deploy TO=#{airbrake_env} REVISION=#{current_revision} REPO=#{repository} USER=#{Airbrake::Capistrano::shellescape(local_user)}"
notify_command << " DRY_RUN=true" if dry_run
notify_command << " API_KEY=#{ENV['API_KEY']}" if ENV['API_KEY']
logger.info "Notifying Airbrake of Deploy (#{notify_command})"
if configuration.dry_run
logger.info "DRY RUN: Notification not actually run."