From fe8749e4c3b81d7075535600dacae706405adfe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81bastien=20Gruhier?= Date: Sun, 9 Feb 2014 09:30:01 +0100 Subject: [PATCH] Capistrano 3 support PR #23 from @sauliusgrigaitis --- README.markdown | 2 +- capistrano-db-tasks.gemspec | 2 +- lib/capistrano-db-tasks/asset.rb | 22 ++-- lib/capistrano-db-tasks/database.rb | 27 ++--- lib/capistrano-db-tasks/dbtasks.rb | 168 +++++++++++++--------------- lib/capistrano-db-tasks/util.rb | 8 +- lib/capistrano-db-tasks/version.rb | 2 +- 7 files changed, 108 insertions(+), 123 deletions(-) diff --git a/README.markdown b/README.markdown index 2bcabcf..5dc893a 100644 --- a/README.markdown +++ b/README.markdown @@ -2,7 +2,7 @@ CapistranoDbTasks ================= Add database AND assets tasks to capistrano to a Rails project. -It only works with capistrano 2. Any pull requests for capistrano 3 support are welcome :) +It only works with capistrano 3. Older versions until 0.3 works with capistrano 2. Currently diff --git a/capistrano-db-tasks.gemspec b/capistrano-db-tasks.gemspec index 9b14ba1..bac8c56 100644 --- a/capistrano-db-tasks.gemspec +++ b/capistrano-db-tasks.gemspec @@ -18,5 +18,5 @@ Gem::Specification.new do |s| s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] - s.add_development_dependency "capistrano", "> 2.0.0" + s.add_runtime_dependency "capistrano", ">= 3.0.0" end diff --git a/lib/capistrano-db-tasks/asset.rb b/lib/capistrano-db-tasks/asset.rb index fbaeb3c..d40b3b9 100644 --- a/lib/capistrano-db-tasks/asset.rb +++ b/lib/capistrano-db-tasks/asset.rb @@ -2,22 +2,26 @@ module Asset extend self def remote_to_local(cap) - servers = cap.find_servers :roles => :app - port = cap.port rescue 22 - [cap.assets_dir].flatten.each do |dir| - system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' #{cap.user}@#{servers.first}:#{cap.current_path}/#{dir} #{cap.local_assets_dir}") + servers = Capistrano::Configuration.env.send(:servers) + server = servers.detect { |s| s.roles.include?(:app) } + port = server.netssh_options[:port] || 22 + user = server.netssh_options[:user] + [cap.fetch(:assets_dir)].flatten.each do |dir| + system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' #{user}@#{server}:#{cap.current_path}/#{dir} #{cap.fetch(:local_assets_dir)}") end end def local_to_remote(cap) - servers = cap.find_servers :roles => :app - port = cap.port rescue 22 - [cap.assets_dir].flatten.each do |dir| - system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' ./#{dir} #{cap.user}@#{servers.first}:#{cap.current_path}/#{cap.local_assets_dir}") + servers = Capistrano::Configuration.env.send(:servers) + server = servers.detect { |s| s.roles.include?(:app) } + port = server.netssh_options[:port] || 22 + user = server.netssh_options[:user] + [cap.fetch(:assets_dir)].flatten.each do |dir| + system("rsync -a --del -L -K -vv --progress --rsh='ssh -p #{port}' ./#{dir} #{user}@#{server}:#{cap.current_path}/#{cap.fetch(:local_assets_dir)}") end end def to_string(cap) - [cap.assets_dir].flatten.join(" ") + [cap.fetch(:assets_dir)].flatten.join(" ") end end diff --git a/lib/capistrano-db-tasks/database.rb b/lib/capistrano-db-tasks/database.rb index c3088c6..2ec10cd 100644 --- a/lib/capistrano-db-tasks/database.rb +++ b/lib/capistrano-db-tasks/database.rb @@ -61,36 +61,33 @@ def import_cmd(file) class Remote < Base def initialize(cap_instance) super(cap_instance) - @config = "" - @cap.run("cat #{@cap.current_path}/config/database.yml") do |c, s, d| - @config += d - end - @config = YAML.load(ERB.new(@config).result)[@cap.rails_env.to_s] + @config = @cap.capture("cat #{@cap.current_path}/config/database.yml") + @config = YAML.load(ERB.new(@config).result)[@cap.fetch(:rails_env).to_s] end def dump - @cap.run "cd #{@cap.current_path} && #{dump_cmd} | bzip2 - - > #{output_file}" + @cap.execute "cd #{@cap.current_path} && #{dump_cmd} | bzip2 - - > #{output_file}" self end def download(local_file = "#{output_file}") remote_file = "#{@cap.current_path}/#{output_file}" - @cap.get remote_file, local_file + @cap.download! remote_file, local_file end # cleanup = true removes the mysqldump file after loading, false leaves it in db/ def load(file, cleanup) unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2')) # @cap.run "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} bundle exec rake db:drop db:create && #{import_cmd(unzip_file)}" - @cap.run "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.rails_env} && #{import_cmd(unzip_file)}" - @cap.run("cd #{@cap.current_path} && rm #{unzip_file}") if cleanup + @cap.execute "cd #{@cap.current_path} && bunzip2 -f #{file} && RAILS_ENV=#{@cap.fetch(:rails_env)} && #{import_cmd(unzip_file)}" + @cap.execute("cd #{@cap.current_path} && rm #{unzip_file}") if cleanup end end class Local < Base def initialize(cap_instance) super(cap_instance) - @config = YAML.load(ERB.new(File.read(File.join('config', 'database.yml'))).result)[@cap.local_rails_env.to_s] + @config = YAML.load(ERB.new(File.read(File.join('config', 'database.yml'))).result)[fetch(:local_rails_env).to_s] puts "local #{@config}" end @@ -98,15 +95,15 @@ def initialize(cap_instance) def load(file, cleanup) unzip_file = File.join(File.dirname(file), File.basename(file, '.bz2')) # system("bunzip2 -f #{file} && bundle exec rake db:drop db:create && #{import_cmd(unzip_file)} && bundle exec rake db:migrate") - @cap.logger.info("executing local: bunzip2 -f #{file} && #{import_cmd(unzip_file)}") + @cap.info "executing local: bunzip2 -f #{file} && #{import_cmd(unzip_file)}" system("bunzip2 -f #{file} && #{import_cmd(unzip_file)}") if cleanup - @cap.logger.info("removing #{unzip_file}") + @cap.info "removing #{unzip_file}" File.unlink(unzip_file) else - @cap.logger.info("leaving #{unzip_file} (specify :db_local_clean in deploy.rb to remove)") + @cap.info "leaving #{unzip_file} (specify :db_local_clean in deploy.rb to remove)" end - @cap.logger.info("Completed database import") + @cap.info "Completed database import" end def dump @@ -116,7 +113,7 @@ def dump def upload remote_file = "#{@cap.current_path}/#{output_file}" - @cap.upload output_file, remote_file + @cap.upload! output_file, remote_file end end diff --git a/lib/capistrano-db-tasks/dbtasks.rb b/lib/capistrano-db-tasks/dbtasks.rb index 9e1e58a..3928b85 100644 --- a/lib/capistrano-db-tasks/dbtasks.rb +++ b/lib/capistrano-db-tasks/dbtasks.rb @@ -1,114 +1,102 @@ -if Capistrano::Configuration.instance(false) - - Capistrano::Configuration.instance(true).load do |instance| - - require File.expand_path("#{File.dirname(__FILE__)}/util") - require File.expand_path("#{File.dirname(__FILE__)}/database") - require File.expand_path("#{File.dirname(__FILE__)}/asset") - - instance.set :local_rails_env, ENV['RAILS_ENV'] || 'development' unless exists?(:local_rails_env) - instance.set :rails_env, 'production' unless exists?(:rails_env) - instance.set :db_local_clean, false unless exists?(:db_local_clean) - instance.set :assets_dir, 'system' unless exists?(:assets_dir) - instance.set :local_assets_dir, 'public' unless exists?(:local_assets_dir) - - namespace :db do - namespace :remote do - desc 'Synchronize your remote database using local database data' - task :sync, :roles => :db do - if Util.prompt 'Are you sure you want to REPLACE THE REMOTE DATABASE with local database' - Database.local_to_remote(instance) - end +require File.expand_path("#{File.dirname(__FILE__)}/util") +require File.expand_path("#{File.dirname(__FILE__)}/database") +require File.expand_path("#{File.dirname(__FILE__)}/asset") + +set :local_rails_env, ENV['RAILS_ENV'] || 'development' unless fetch(:local_rails_env) +set :rails_env, 'production' unless fetch(:rails_env) +set :db_local_clean, false unless fetch(:db_local_clean) +set :assets_dir, 'system' unless fetch(:assets_dir) +set :local_assets_dir, 'public' unless fetch(:local_assets_dir) + +namespace :db do + namespace :remote do + desc 'Synchronize your remote database using local database data' + task :sync do + on roles(:db) do + if Util.prompt 'Are you sure you want to REPLACE THE REMOTE DATABASE with local database' + Database.local_to_remote(self) end end + end + end - namespace :local do - desc 'Synchronize your local database using remote database data' - task :sync, :roles => :db do - puts "Local database: #{Database::Local.new(instance).database}" - if Util.prompt 'Are you sure you want to erase your local database with server database' - Database.remote_to_local(instance) - end + namespace :local do + desc 'Synchronize your local database using remote database data' + task :sync do + on roles(:db) do + puts "Local database: #{Database::Local.new(self).database}" + if Util.prompt 'Are you sure you want to erase your local database with server database' + Database.remote_to_local(self) end end + end + end - desc 'Synchronize your local database using remote database data' - task :pull do - db.local.sync - end + desc 'Synchronize your local database using remote database data' + task :pull => "db:local:sync" - desc 'Synchronize your remote database using local database data' - task :push do - db.remote.sync - end - end + desc 'Synchronize your remote database using local database data' + task :push => "db:remote:sync" +end - namespace :assets do - namespace :remote do - desc 'Synchronize your remote assets using local assets' - task :sync, :roles => :app do - puts "Assets directories: #{assets_dir}" - if Util.prompt "Are you sure you want to erase your server assets with local assets" - Asset.local_to_remote(instance) - end +namespace :assets do + namespace :remote do + desc 'Synchronize your remote assets using local assets' + task :sync do + on roles(:app) do + puts "Assets directories: #{fetch(:assets_dir)}" + if Util.prompt "Are you sure you want to erase your server assets with local assets" + Asset.local_to_remote(self) end end + end + end - namespace :local do - desc 'Synchronize your local assets using remote assets' - task :sync, :roles => :app do - puts "Assets directories: #{local_assets_dir}" - if Util.prompt "Are you sure you want to erase your local assets with server assets" - Asset.remote_to_local(instance) - end + namespace :local do + desc 'Synchronize your local assets using remote assets' + task :sync do + on roles(:app) do + puts "Assets directories: #{fetch(:local_assets_dir)}" + if Util.prompt "Are you sure you want to erase your local assets with server assets" + Asset.remote_to_local(self) end end - - desc 'Synchronize your local assets using remote assets' - task :pull do - assets.local.sync - end - - desc 'Synchronize your remote assets using local assets' - task :push do - assets.remote.sync - end end + end - namespace :app do - namespace :remote do - desc 'Synchronize your remote assets AND database using local assets and database' - task :sync do - if Util.prompt "Are you sure you want to REPLACE THE REMOTE DATABASE AND your remote assets with local database and assets(#{assets_dir})" - Database.local_to_remote(instance) - Asset.local_to_remote(instance) - end - end - end + desc 'Synchronize your local assets using remote assets' + task :pull => "assets:local:sync" - namespace :local do - desc 'Synchronize your local assets AND database using remote assets and database' - task :sync do - puts "Local database : #{Database::Local.new(instance).database}" - puts "Assets directories : #{local_assets_dir}" - if Util.prompt "Are you sure you want to erase your local database AND your local assets with server database and assets(#{assets_dir})" - Database.remote_to_local(instance) - Asset.remote_to_local(instance) - end - end - end + desc 'Synchronize your remote assets using local assets' + task :push => "assets:remote:sync" +end - desc 'Synchronize your local assets AND database using remote assets and database' - task :pull do - app.local.sync +namespace :app do + namespace :remote do + desc 'Synchronize your remote assets AND database using local assets and database' + task :sync do + if Util.prompt "Are you sure you want to REPLACE THE REMOTE DATABASE AND your remote assets with local database and assets(#{assets_dir})" + Database.local_to_remote(self) + Asset.local_to_remote(self) end + end + end - desc 'Synchronize your remote assets AND database using local assets and database' - task :push do - app.remote.sync + namespace :local do + desc 'Synchronize your local assets AND database using remote assets and database' + task :sync do + puts "Local database : #{Database::Local.new(self).database}" + puts "Assets directories : #{fetch(:local_assets_dir)}" + if Util.prompt "Are you sure you want to erase your local database AND your local assets with server database and assets(#{assets_dir})" + Database.remote_to_local(self) + Asset.remote_to_local(self) end - end end + desc 'Synchronize your local assets AND database using remote assets and database' + task :pull => "app:local:sync" + + desc 'Synchronize your remote assets AND database using local assets and database' + task :push => "app:remote:sync" end diff --git a/lib/capistrano-db-tasks/util.rb b/lib/capistrano-db-tasks/util.rb index 276c70b..a84610e 100644 --- a/lib/capistrano-db-tasks/util.rb +++ b/lib/capistrano-db-tasks/util.rb @@ -1,10 +1,6 @@ module Util def self.prompt(msg, prompt = "(y)es, (n)o ") - answer = Capistrano::CLI.ui.ask("#{msg} #{prompt} ? ") do |q| - q.overwrite = false - q.validate = /^y$|^yes$|^n$|^no$/i - q.responses[:not_valid] = prompt - end - (answer =~ /^y$|^yes$/i) == 0 + ask(:answer, "#{msg} #{prompt} ? ") + (fetch(:answer) =~ /^y$|^yes$/i) == 0 end end diff --git a/lib/capistrano-db-tasks/version.rb b/lib/capistrano-db-tasks/version.rb index 28bb1ac..e99f421 100644 --- a/lib/capistrano-db-tasks/version.rb +++ b/lib/capistrano-db-tasks/version.rb @@ -1,3 +1,3 @@ module CapistranoDbTasks - VERSION = "0.2.1" + VERSION = "0.3" end