wordmove 0.1.0.rc → 1.0.0
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/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile.lock +40 -35
- data/README.mdown +14 -3
- data/lib/wordmove/deployer.rb +166 -0
- data/lib/wordmove/hosts/remote_host.rb +137 -0
- data/lib/wordmove/version.rb +1 -1
- data/spec/spec_helper.rb +0 -4
- data/spec/sql_mover_spec.rb +107 -0
- data/wordmove.gemspec +2 -0
- metadata +14 -8
- data/spec/remote_host_spec.rb +0 -62
    
        data/.rspec
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            --color
         | 
    
        data/.rvmrc
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            rvm use 1.9.2@wordmove
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,58 +1,63 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                wordmove (0.0. | 
| 5 | 
            -
                  activesupport | 
| 4 | 
            +
                wordmove (0.1.0.rc)
         | 
| 5 | 
            +
                  activesupport
         | 
| 6 6 | 
             
                  colored
         | 
| 7 | 
            -
                  escape
         | 
| 8 | 
            -
                  hashie
         | 
| 9 7 | 
             
                  i18n
         | 
| 10 | 
            -
                   | 
| 11 | 
            -
                  net-ssh
         | 
| 8 | 
            +
                  photocopier
         | 
| 12 9 | 
             
                  rake
         | 
| 13 10 | 
             
                  thor
         | 
| 14 11 |  | 
| 15 12 | 
             
            GEM
         | 
| 16 13 | 
             
              remote: http://rubygems.org/
         | 
| 17 14 | 
             
              specs:
         | 
| 18 | 
            -
                activesupport (3. | 
| 19 | 
            -
             | 
| 20 | 
            -
                   | 
| 15 | 
            +
                activesupport (3.2.9)
         | 
| 16 | 
            +
                  i18n (~> 0.6)
         | 
| 17 | 
            +
                  multi_json (~> 1.0)
         | 
| 18 | 
            +
                aruba (0.5.1)
         | 
| 19 | 
            +
                  childprocess (~> 0.3.6)
         | 
| 21 20 | 
             
                  cucumber (>= 1.1.1)
         | 
| 22 | 
            -
                   | 
| 23 | 
            -
             | 
| 24 | 
            -
                 | 
| 25 | 
            -
             | 
| 26 | 
            -
                  ffi (~> 1.0.6)
         | 
| 21 | 
            +
                  rspec-expectations (>= 2.7.0)
         | 
| 22 | 
            +
                builder (3.1.4)
         | 
| 23 | 
            +
                childprocess (0.3.6)
         | 
| 24 | 
            +
                  ffi (~> 1.0, >= 1.0.6)
         | 
| 27 25 | 
             
                colored (1.2)
         | 
| 28 | 
            -
                cucumber (1.1 | 
| 26 | 
            +
                cucumber (1.2.1)
         | 
| 29 27 | 
             
                  builder (>= 2.1.2)
         | 
| 30 | 
            -
                  diff-lcs (>= 1.1. | 
| 31 | 
            -
                  gherkin (~> 2. | 
| 28 | 
            +
                  diff-lcs (>= 1.1.3)
         | 
| 29 | 
            +
                  gherkin (~> 2.11.0)
         | 
| 32 30 | 
             
                  json (>= 1.4.6)
         | 
| 33 | 
            -
                  term-ansicolor (>= 1.0.6)
         | 
| 34 31 | 
             
                diff-lcs (1.1.3)
         | 
| 35 32 | 
             
                escape (0.0.4)
         | 
| 36 | 
            -
                ffi (1.0 | 
| 37 | 
            -
                gherkin (2. | 
| 33 | 
            +
                ffi (1.2.0)
         | 
| 34 | 
            +
                gherkin (2.11.5)
         | 
| 38 35 | 
             
                  json (>= 1.4.6)
         | 
| 39 | 
            -
                 | 
| 40 | 
            -
                 | 
| 41 | 
            -
                 | 
| 36 | 
            +
                i18n (0.6.1)
         | 
| 37 | 
            +
                json (1.7.5)
         | 
| 38 | 
            +
                multi_json (1.4.0)
         | 
| 42 39 | 
             
                net-scp (1.0.4)
         | 
| 43 40 | 
             
                  net-ssh (>= 1.99.1)
         | 
| 44 | 
            -
                net-ssh (2.2 | 
| 45 | 
            -
                 | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
                   | 
| 49 | 
            -
                   | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
                   | 
| 53 | 
            -
             | 
| 54 | 
            -
                 | 
| 55 | 
            -
                 | 
| 41 | 
            +
                net-ssh (2.6.2)
         | 
| 42 | 
            +
                net-ssh-gateway (1.1.0)
         | 
| 43 | 
            +
                  net-ssh (>= 1.99.1)
         | 
| 44 | 
            +
                photocopier (0.0.4)
         | 
| 45 | 
            +
                  activesupport
         | 
| 46 | 
            +
                  escape
         | 
| 47 | 
            +
                  i18n
         | 
| 48 | 
            +
                  net-scp
         | 
| 49 | 
            +
                  net-ssh
         | 
| 50 | 
            +
                  net-ssh-gateway
         | 
| 51 | 
            +
                rake (10.0.2)
         | 
| 52 | 
            +
                rspec (2.12.0)
         | 
| 53 | 
            +
                  rspec-core (~> 2.12.0)
         | 
| 54 | 
            +
                  rspec-expectations (~> 2.12.0)
         | 
| 55 | 
            +
                  rspec-mocks (~> 2.12.0)
         | 
| 56 | 
            +
                rspec-core (2.12.1)
         | 
| 57 | 
            +
                rspec-expectations (2.12.0)
         | 
| 58 | 
            +
                  diff-lcs (~> 1.1.3)
         | 
| 59 | 
            +
                rspec-mocks (2.12.0)
         | 
| 60 | 
            +
                thor (0.16.0)
         | 
| 56 61 |  | 
| 57 62 | 
             
            PLATFORMS
         | 
| 58 63 | 
             
              ruby
         | 
    
        data/README.mdown
    CHANGED
    
    | @@ -11,9 +11,20 @@ Think of it like Capistrano for Wordpress, complete with push/pull capabilities. | |
| 11 11 | 
             
            That's easy:
         | 
| 12 12 |  | 
| 13 13 | 
             
            ```
         | 
| 14 | 
            -
            gem install wordmove | 
| 14 | 
            +
            gem install wordmove
         | 
| 15 15 | 
             
            ```
         | 
| 16 16 |  | 
| 17 | 
            +
            ## Upgrading?
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            Beware!
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            From version 1.0 we have decided to change wordmove flags' behaviour: they used to tell
         | 
| 22 | 
            +
            wordmove which options to **skip**, now they tell instead which options to **include**.
         | 
| 23 | 
            +
            In the Movefile, we have also changed in the ssh subsection the "username" field to be
         | 
| 24 | 
            +
            just "user".
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            So please, be very careful when upgrading :heart:
         | 
| 27 | 
            +
             | 
| 17 28 | 
             
            ## Usage
         | 
| 18 29 |  | 
| 19 30 | 
             
            ```
         | 
| @@ -64,7 +75,7 @@ Just not use the `remote.ssh.password` field on your `Movefile`. Easy peasy. | |
| 64 75 | 
             
            Please take a look at the various gotchas of the underlying [`photocopier` gem](https://github.com/stefanoverna/photocopier#password-gotchas).
         | 
| 65 76 |  | 
| 66 77 | 
             
            ### How the heck you are able to sync the DB via FTP?
         | 
| 67 | 
            -
             | 
| 78 | 
            +
            We're glad you asked! We basically upload via FTP a PHP script that performs the various
         | 
| 68 79 | 
             
            import/export operations. This script then gets executed via HTTP. Don't worry
         | 
| 69 80 | 
             
            too much about security though: the script is deleted just after the usage,
         | 
| 70 81 | 
             
            and can only be executed by `wordmove`, as each time it requires a pre-shared
         | 
| @@ -77,7 +88,7 @@ one-time-password to be run. | |
| 77 88 |  | 
| 78 89 | 
             
            (The MIT License)
         | 
| 79 90 |  | 
| 80 | 
            -
            Copyright ©  | 
| 91 | 
            +
            Copyright © 2012 weLaika
         | 
| 81 92 |  | 
| 82 93 | 
             
            Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
         | 
| 83 94 |  | 
| @@ -0,0 +1,166 @@ | |
| 1 | 
            +
            require 'active_support/core_ext'
         | 
| 2 | 
            +
            require 'hashie'
         | 
| 3 | 
            +
            require 'wordmove/hosts/local_host'
         | 
| 4 | 
            +
            require 'wordmove/hosts/remote_host'
         | 
| 5 | 
            +
            require 'wordmove/logger'
         | 
| 6 | 
            +
            require 'wordmove/sql_mover'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            module Wordmove
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              class Deployer
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                attr_reader :options
         | 
| 13 | 
            +
                attr_reader :logger
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def initialize(options = {})
         | 
| 16 | 
            +
                  @options = Hashie::Mash.new(options)
         | 
| 17 | 
            +
                  @logger = Logger.new
         | 
| 18 | 
            +
                  @logger.level = options.verbose ? Logger::VERBOSE : Logger::INFO
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def push
         | 
| 22 | 
            +
                  informative_errors do
         | 
| 23 | 
            +
                    unless options.skip_db
         | 
| 24 | 
            +
                      logger.info "Pushing the DB..."
         | 
| 25 | 
            +
                      push_db
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    remotely do |host|
         | 
| 29 | 
            +
                      %w(uploads themes plugins).each do |step|
         | 
| 30 | 
            +
                        unless options.send("skip_#{step}")
         | 
| 31 | 
            +
                          logger.info "Pushing wp-content/#{step}..."
         | 
| 32 | 
            +
                          host.download_dir local_wpcontent_path(step), remote_wpcontent_path(step)
         | 
| 33 | 
            +
                        end
         | 
| 34 | 
            +
                      end
         | 
| 35 | 
            +
                    end
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def pull
         | 
| 40 | 
            +
                  informative_errors do
         | 
| 41 | 
            +
                    unless options.skip_db
         | 
| 42 | 
            +
                      logger.info "Pulling the DB..."
         | 
| 43 | 
            +
                      pull_db
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    remotely do |host|
         | 
| 47 | 
            +
                      %w(uploads themes plugins).each do |step|
         | 
| 48 | 
            +
                        unless options.send("skip_#{step}")
         | 
| 49 | 
            +
                          logger.info "Pulling wp-content/#{step}..."
         | 
| 50 | 
            +
                          host.upload_dir remote_wpcontent_path(step), local_wpcontent_path(step)
         | 
| 51 | 
            +
                        end
         | 
| 52 | 
            +
                      end
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                private
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def push_db
         | 
| 60 | 
            +
                  local_mysql_dump_path = local_wpcontent_path("database_dump.sql")
         | 
| 61 | 
            +
                  remote_mysql_dump_path = remote_wpcontent_path("database_dump.sql")
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                  locally do |host|
         | 
| 64 | 
            +
                    host.run "mysqldump", "--host=#{config.local.database.host}", "--user=#{config.local.database.username}", "--password=#{config.local.database.password}", config.local.database.name, :stdout => local_mysql_dump_path
         | 
| 65 | 
            +
                    if options.adapt_sql
         | 
| 66 | 
            +
                      Wordmove::SqlMover.new(local_mysql_dump_path, config.local, config.remote).move!
         | 
| 67 | 
            +
                    else
         | 
| 68 | 
            +
                      File.open(local_mysql_dump_path, 'a') do |file|
         | 
| 69 | 
            +
                        file.write "UPDATE #{options_table} SET option_value=\"#{config.remote.vhost}\" WHERE option_name=\"siteurl\" OR option_name=\"home\";\n"
         | 
| 70 | 
            +
                      end
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  remotely do |host|
         | 
| 75 | 
            +
                    host.download_file local_mysql_dump_path, remote_mysql_dump_path
         | 
| 76 | 
            +
                    host.run "mysql", "--user=#{config.remote.database.username}", "--password=#{config.remote.database.password}", "--host=#{config.remote.database.host}", "--database=#{config.remote.database.name}", :stdin => remote_mysql_dump_path
         | 
| 77 | 
            +
                    host.run "rm", remote_mysql_dump_path
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                  locally do |host|
         | 
| 81 | 
            +
                    host.run "rm", local_mysql_dump_path
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
             | 
| 86 | 
            +
                def pull_db
         | 
| 87 | 
            +
                  local_mysql_dump_path = local_wpcontent_path("database_dump.sql")
         | 
| 88 | 
            +
                  remote_mysql_dump_path = remote_wpcontent_path("database_dump.sql")
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                  remotely do |host|
         | 
| 91 | 
            +
                    host.run "mysqldump", "--host=#{config.remote.database.host}", "--user=#{config.remote.database.username}", "--password=#{config.remote.database.password}", config.remote.database.name, :stdout => remote_mysql_dump_path
         | 
| 92 | 
            +
                    host.upload_file remote_mysql_dump_path, local_mysql_dump_path
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                  locally do |host|
         | 
| 96 | 
            +
                    if options.adapt_sql
         | 
| 97 | 
            +
                      Wordmove::SqlMover.new(local_mysql_dump_path, config.remote, config.local).move!
         | 
| 98 | 
            +
                    else
         | 
| 99 | 
            +
                      File.open(local_mysql_dump_path, 'a') do |file|
         | 
| 100 | 
            +
                        file.write "UPDATE #{options_table} SET option_value=\"#{config.local.vhost}\" WHERE option_name=\"siteurl\" OR option_name=\"home\";\n"
         | 
| 101 | 
            +
                      end
         | 
| 102 | 
            +
                    end
         | 
| 103 | 
            +
                    host.run "mysql", "--user=#{config.local.database.username}", "--password=#{config.local.database.password}", "--host=#{config.local.database.host}", "--database=#{config.local.database.name}", :stdin => local_mysql_dump_path
         | 
| 104 | 
            +
                    host.run "rm", local_mysql_dump_path
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  remotely do |host|
         | 
| 108 | 
            +
                    host.run "rm", remote_mysql_dump_path
         | 
| 109 | 
            +
                  end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                end
         | 
| 112 | 
            +
             | 
| 113 | 
            +
                def config
         | 
| 114 | 
            +
                  if @config.blank?
         | 
| 115 | 
            +
                    config_path = @options[:config] || "Movefile"
         | 
| 116 | 
            +
                    unless File.exists? config_path
         | 
| 117 | 
            +
                      raise Thor::Error, "Could not find a valid Movefile"
         | 
| 118 | 
            +
                    end
         | 
| 119 | 
            +
                    @config = Hashie::Mash.new(YAML::load(File.open(config_path)))
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                  @config
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                def table_prefix
         | 
| 125 | 
            +
                  config.table_prefix || "wp_"
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                def options_table
         | 
| 129 | 
            +
                  table_prefix + "options"
         | 
| 130 | 
            +
                end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                def local_wpcontent_path(*args)
         | 
| 133 | 
            +
                  File.join(config.local.wordpress_path, "wp-content", *args)
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                def remote_wpcontent_path(*args)
         | 
| 137 | 
            +
                  File.join(config.remote.wordpress_path, "wp-content", *args)
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                def locally
         | 
| 141 | 
            +
                  host = LocalHost.new(config.local.merge(:logger => @logger))
         | 
| 142 | 
            +
                  yield host
         | 
| 143 | 
            +
                  host.close
         | 
| 144 | 
            +
                end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                def remotely
         | 
| 147 | 
            +
                  host = RemoteHost.new(config.remote.merge(:logger => @logger))
         | 
| 148 | 
            +
                  yield host
         | 
| 149 | 
            +
                  host.close
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                def informative_errors
         | 
| 153 | 
            +
                  yield
         | 
| 154 | 
            +
                rescue Timeout::Error
         | 
| 155 | 
            +
                  logger.error "Connection timed out!"
         | 
| 156 | 
            +
                  puts "Timed out"
         | 
| 157 | 
            +
                rescue Errno::EHOSTUNREACH
         | 
| 158 | 
            +
                  logger.error "Host unreachable!"
         | 
| 159 | 
            +
                rescue Errno::ECONNREFUSED
         | 
| 160 | 
            +
                  logger.error "Connection refused!"
         | 
| 161 | 
            +
                rescue Net::SSH::AuthenticationFailed
         | 
| 162 | 
            +
                  logger.error "SSH authentification failure, please double check the SSH credentials on your Movefile!"
         | 
| 163 | 
            +
                end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
              end
         | 
| 166 | 
            +
            end
         | 
| @@ -0,0 +1,137 @@ | |
| 1 | 
            +
            require 'net/ssh'
         | 
| 2 | 
            +
            require 'net/scp'
         | 
| 3 | 
            +
            require 'net/ssh/gateway'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            module Wordmove
         | 
| 6 | 
            +
              class RemoteHost < LocalHost
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                alias :locally_run :run
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                attr_reader :session
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def initialize(options = {})
         | 
| 13 | 
            +
                  super
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def session
         | 
| 17 | 
            +
                  if options.ssh.nil?
         | 
| 18 | 
            +
                    raise Thor::Error, "No SSH credentials provided on Movefile!"
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  ssh_extras = {}
         | 
| 22 | 
            +
                  [ :port, :password ].each do |p|
         | 
| 23 | 
            +
                    ssh_extras.merge!( { p => options.ssh[p] } ) if options.ssh[p]
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  if options.ssh.gateway.nil?
         | 
| 27 | 
            +
                    logger.verbose "Connecting to #{options.ssh.host}..." unless @session.present?
         | 
| 28 | 
            +
                    @session ||= Net::SSH.start(options.ssh.host, options.ssh.username, ssh_extras)
         | 
| 29 | 
            +
                  else
         | 
| 30 | 
            +
                    logger.verbose "Connecting to #{options.ssh.host} through the gateway..." unless @session.present?
         | 
| 31 | 
            +
                    @session ||= gateway.ssh(options.ssh.host, options.ssh.username, ssh_extras)
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  @session
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def gateway
         | 
| 38 | 
            +
                  if options.ssh.gateway.nil?
         | 
| 39 | 
            +
                    raise Thor::Error, "No SSH credentials provided on Movefile!"
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                  ssh_extras = {}
         | 
| 43 | 
            +
                  [ :port, :password ].each do |p|
         | 
| 44 | 
            +
                    ssh_extras.merge!( { p => options.ssh.gateway[p] } ) if options.ssh.gateway[p]
         | 
| 45 | 
            +
                  end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  logger.verbose "Connecting to #{options.ssh.gateway.host}..." unless @gateway.present?
         | 
| 48 | 
            +
                  @gateway ||= Net::SSH::Gateway.new(options.ssh.gateway.host, options.ssh.gateway.username, ssh_extras )
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                  @gateway
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                def close
         | 
| 54 | 
            +
                  session.close
         | 
| 55 | 
            +
                  if options.ssh.gateway.present?
         | 
| 56 | 
            +
                    gateway.close(session.transport.port)
         | 
| 57 | 
            +
                  end
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                def upload_file(source_file, destination_file)
         | 
| 61 | 
            +
                  logger.verbose "Copying remote #{source_file} to #{destination_file}..."
         | 
| 62 | 
            +
                  session.scp.download! source_file, destination_file
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def download_file(source_file, destination_file)
         | 
| 66 | 
            +
                  logger.verbose "Copying local #{source_file} to #{destination_file}..."
         | 
| 67 | 
            +
                  session.scp.upload! source_file, destination_file
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                def download_dir(source_dir, destination_dir)
         | 
| 71 | 
            +
                  destination_dir = ":#{destination_dir}"
         | 
| 72 | 
            +
                  destination_dir = "#{options.ssh.username}@#{destination_dir}" if options.ssh.username
         | 
| 73 | 
            +
                  rsync "#{source_dir}/", destination_dir
         | 
| 74 | 
            +
                end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                def upload_dir(source_dir, destination_dir)
         | 
| 77 | 
            +
                  source_dir = ":#{source_dir}/"
         | 
| 78 | 
            +
                  rsync source_dir, destination_dir
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                def run(*args)
         | 
| 82 | 
            +
                  command = shell_command(*args)
         | 
| 83 | 
            +
                  logger.verbose "Executing remotely #{command}"
         | 
| 84 | 
            +
                  session.exec!(command)
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                private
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                def get_host_for_options(options)
         | 
| 90 | 
            +
                  if options.username
         | 
| 91 | 
            +
                    "#{options.username}@#{options.host}"
         | 
| 92 | 
            +
                  else
         | 
| 93 | 
            +
                    options.host
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def rsync(source_dir, destination_dir)
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                  exclude_file = Tempfile.new('exclude')
         | 
| 100 | 
            +
                  exclude_file.write(options.exclude.join("\n"))
         | 
| 101 | 
            +
                  exclude_file.close
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  arguments = [ "-azLKO" ]
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                  if options.ssh
         | 
| 106 | 
            +
                    remote_shell_arguments = []
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                    if options.ssh.gateway
         | 
| 109 | 
            +
                      remote_shell_arguments.push("ssh", get_host_for_options(options.ssh.gateway))
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                      if options.ssh.gateway.port
         | 
| 112 | 
            +
                        remote_shell_arguments.push("-p", options.ssh.gateway.port)
         | 
| 113 | 
            +
                      end
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                    remote_shell_arguments.push("ssh")
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                    if options.ssh.port
         | 
| 119 | 
            +
                      remote_shell_arguments.push("-p", options.ssh.port)
         | 
| 120 | 
            +
                    end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                    if options.ssh.password
         | 
| 123 | 
            +
                      remote_shell_arguments.unshift("sshpass", "-p", options.ssh.password)
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    remote_shell_arguments.push(get_host_for_options(options.ssh))
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                    arguments.push("-e", remote_shell_arguments.join(" "))
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                  arguments.push("--exclude-from=#{exclude_file.path}", "--delete", source_dir, destination_dir)
         | 
| 132 | 
            +
                  locally_run "rsync", *arguments
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  exclude_file.unlink
         | 
| 135 | 
            +
                end
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
            end
         | 
    
        data/lib/wordmove/version.rb
    CHANGED
    
    
    
        data/spec/spec_helper.rb
    CHANGED
    
    | @@ -2,11 +2,7 @@ require 'rubygems' | |
| 2 2 | 
             
            require 'bundler/setup'
         | 
| 3 3 |  | 
| 4 4 | 
             
            require 'wordmove' # and any other gems you need
         | 
| 5 | 
            -
            require 'hashie'
         | 
| 6 | 
            -
            require 'wordmove/hosts/local_host'
         | 
| 7 | 
            -
            require 'wordmove/hosts/remote_host'
         | 
| 8 5 | 
             
            require 'wordmove/logger'
         | 
| 9 | 
            -
            require 'tempfile'
         | 
| 10 6 | 
             
            require 'active_support/core_ext'
         | 
| 11 7 | 
             
            require 'thor'
         | 
| 12 8 |  | 
| @@ -0,0 +1,107 @@ | |
| 1 | 
            +
            require 'wordmove/sql_mover'
         | 
| 2 | 
            +
            require 'tempfile'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe Wordmove::SqlMover do
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              let(:sql_path) { stub }
         | 
| 7 | 
            +
              let(:source_config) { stub }
         | 
| 8 | 
            +
              let(:dest_config) { stub }
         | 
| 9 | 
            +
              let(:sql_mover) {
         | 
| 10 | 
            +
                Wordmove::SqlMover.new(
         | 
| 11 | 
            +
                  sql_path,
         | 
| 12 | 
            +
                  source_config,
         | 
| 13 | 
            +
                  dest_config
         | 
| 14 | 
            +
                )
         | 
| 15 | 
            +
              }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              context ".initialize" do
         | 
| 18 | 
            +
                it "should assign variables correctly on initialization" do
         | 
| 19 | 
            +
                  sql_mover.sql_path.should == sql_path
         | 
| 20 | 
            +
                  sql_mover.source_config.should == source_config
         | 
| 21 | 
            +
                  sql_mover.dest_config.should == dest_config
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              context ".sql_content" do
         | 
| 26 | 
            +
                let(:sql) do
         | 
| 27 | 
            +
                  Tempfile.new('sql').tap { |d| d.write('DUMP'); d.close }
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
                let(:sql_path) { sql.path }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                it "should read the sql file content" do
         | 
| 32 | 
            +
                  sql_mover.sql_content.should == 'DUMP'
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
              end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              context ".move!" do
         | 
| 37 | 
            +
                it "should replace host, path and write to sql" do
         | 
| 38 | 
            +
                  sql_mover.should_receive(:replace_vhost!).and_return(true)
         | 
| 39 | 
            +
                  sql_mover.should_receive(:replace_wordpress_path!).and_return(true)
         | 
| 40 | 
            +
                  sql_mover.should_receive(:write_sql!).and_return(true)
         | 
| 41 | 
            +
                  sql_mover.move!
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              context ".replace_vhost!" do
         | 
| 46 | 
            +
                it "should replace source vhost with dest vhost" do
         | 
| 47 | 
            +
                  sql_mover.should_receive(:replace_field!).with(:vhost).and_return(true)
         | 
| 48 | 
            +
                  sql_mover.replace_vhost!
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
              end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
              context ".replace_wordpress_path!" do
         | 
| 53 | 
            +
                it "should replace source path with dest path" do
         | 
| 54 | 
            +
                  sql_mover.should_receive(:replace_field!).with(:wordpress_path).and_return(true)
         | 
| 55 | 
            +
                  sql_mover.replace_wordpress_path!
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              context ".replace_field!" do
         | 
| 60 | 
            +
                let(:source_config) { stub("config") }
         | 
| 61 | 
            +
                let(:dest_config) { stub("config") }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                it "should replace source vhost with dest vhost" do
         | 
| 64 | 
            +
                  source_config.stub(:[]).with(:field).and_return("DUMP")
         | 
| 65 | 
            +
                  dest_config.stub(:[]).with(:field).and_return("FUNK")
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  sql_mover.should_receive(:serialized_replace!).ordered.with("DUMP", "FUNK").and_return(true)
         | 
| 68 | 
            +
                  sql_mover.should_receive(:simple_replace!).ordered.with("DUMP", "FUNK").and_return(true)
         | 
| 69 | 
            +
                  sql_mover.replace_field!(:field)
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              context ".serialized_replace!" do
         | 
| 74 | 
            +
                let(:content) { 's:4:"spam";s:20:"http://dump.com/spam";s:6:"foobar";s:22:"http://dump.com/foobar";s:8:"sausages"' }
         | 
| 75 | 
            +
                let(:sql) { Tempfile.new('sql').tap do |d| d.write(content); d.close end }
         | 
| 76 | 
            +
                let(:sql_path) { sql.path }
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                it "should replace source vhost with dest vhost" do
         | 
| 79 | 
            +
                  sql_mover.serialized_replace!('http://dump.com', 'http://shrubbery.com')
         | 
| 80 | 
            +
                  sql_mover.sql_content.should == 's:4:"spam";s:25:"http://shrubbery.com/spam";s:6:"foobar";s:27:"http://shrubbery.com/foobar";s:8:"sausages"'
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
              end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
              context ".simple_replace!" do
         | 
| 85 | 
            +
                let(:content) { "THE DUMP!" }
         | 
| 86 | 
            +
                let(:sql) { Tempfile.new('sql').tap do |d| d.write(content); d.close end }
         | 
| 87 | 
            +
                let(:sql_path) { sql.path }
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                it "should replace source vhost with dest vhost" do
         | 
| 90 | 
            +
                  sql_mover.simple_replace!("DUMP", "FUNK")
         | 
| 91 | 
            +
                  sql_mover.sql_content.should == "THE FUNK!"
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
              end
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              context ".write_sql!" do
         | 
| 96 | 
            +
                let(:content) { "THE DUMP!" }
         | 
| 97 | 
            +
                let(:sql) { Tempfile.new('sql').tap do |d| d.write(content); d.close end }
         | 
| 98 | 
            +
                let(:sql_path) { sql.path }
         | 
| 99 | 
            +
                let(:the_funk) { "THE FUNK THE FUNK THE FUNK" }
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                it "should write content to file" do
         | 
| 102 | 
            +
                  sql_mover.sql_content = the_funk
         | 
| 103 | 
            +
                  sql_mover.write_sql!
         | 
| 104 | 
            +
                  File.open(sql_path).read == the_funk
         | 
| 105 | 
            +
                end
         | 
| 106 | 
            +
              end
         | 
| 107 | 
            +
            end
         | 
    
        data/wordmove.gemspec
    CHANGED
    
    | @@ -25,4 +25,6 @@ Gem::Specification.new do |gem| | |
| 25 25 | 
             
              gem.add_development_dependency "rspec"
         | 
| 26 26 | 
             
              gem.add_development_dependency "cucumber"
         | 
| 27 27 | 
             
              gem.add_development_dependency "aruba"
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              gem.post_install_message = "Beware! We have changed the wordmove flags' behaviour: they used to tell wordmove what to _skip_, now they tell what to _include_. Read `wordmove help` for more info."
         | 
| 28 30 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,15 +1,15 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: wordmove
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 5 | 
            -
              prerelease:  | 
| 4 | 
            +
              version: 1.0.0
         | 
| 5 | 
            +
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| 8 8 | 
             
            - Stefano Verna
         | 
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2012- | 
| 12 | 
            +
            date: 2012-12-07 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: colored
         | 
| @@ -164,6 +164,8 @@ extensions: [] | |
| 164 164 | 
             
            extra_rdoc_files: []
         | 
| 165 165 | 
             
            files:
         | 
| 166 166 | 
             
            - .gitignore
         | 
| 167 | 
            +
            - .rspec
         | 
| 168 | 
            +
            - .rvmrc
         | 
| 167 169 | 
             
            - Gemfile
         | 
| 168 170 | 
             
            - Gemfile.lock
         | 
| 169 171 | 
             
            - README.mdown
         | 
| @@ -178,23 +180,27 @@ files: | |
| 178 180 | 
             
            - lib/wordmove/assets/dump.php.erb
         | 
| 179 181 | 
             
            - lib/wordmove/assets/import.php.erb
         | 
| 180 182 | 
             
            - lib/wordmove/cli.rb
         | 
| 183 | 
            +
            - lib/wordmove/deployer.rb
         | 
| 181 184 | 
             
            - lib/wordmove/deployer/base.rb
         | 
| 182 185 | 
             
            - lib/wordmove/deployer/ftp.rb
         | 
| 183 186 | 
             
            - lib/wordmove/deployer/ssh.rb
         | 
| 184 187 | 
             
            - lib/wordmove/generators/Movefile
         | 
| 185 188 | 
             
            - lib/wordmove/generators/movefile.rb
         | 
| 189 | 
            +
            - lib/wordmove/hosts/remote_host.rb
         | 
| 186 190 | 
             
            - lib/wordmove/logger.rb
         | 
| 187 191 | 
             
            - lib/wordmove/sql_mover.rb
         | 
| 188 192 | 
             
            - lib/wordmove/version.rb
         | 
| 189 193 | 
             
            - pkg/wordmove-0.0.1.gem
         | 
| 190 194 | 
             
            - pkg/wordmove-0.0.2.gem
         | 
| 191 195 | 
             
            - spec/fixtures/Movefile
         | 
| 192 | 
            -
            - spec/remote_host_spec.rb
         | 
| 193 196 | 
             
            - spec/spec_helper.rb
         | 
| 197 | 
            +
            - spec/sql_mover_spec.rb
         | 
| 194 198 | 
             
            - wordmove.gemspec
         | 
| 195 199 | 
             
            homepage: ''
         | 
| 196 200 | 
             
            licenses: []
         | 
| 197 | 
            -
            post_install_message: 
         | 
| 201 | 
            +
            post_install_message: ! 'Beware! We have changed the wordmove flags'' behaviour: they
         | 
| 202 | 
            +
              used to tell wordmove what to _skip_, now they tell what to _include_. Read `wordmove
         | 
| 203 | 
            +
              help` for more info.'
         | 
| 198 204 | 
             
            rdoc_options: []
         | 
| 199 205 | 
             
            require_paths:
         | 
| 200 206 | 
             
            - lib
         | 
| @@ -207,9 +213,9 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 207 213 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 208 214 | 
             
              none: false
         | 
| 209 215 | 
             
              requirements:
         | 
| 210 | 
            -
              - - ! ' | 
| 216 | 
            +
              - - ! '>='
         | 
| 211 217 | 
             
                - !ruby/object:Gem::Version
         | 
| 212 | 
            -
                  version:  | 
| 218 | 
            +
                  version: '0'
         | 
| 213 219 | 
             
            requirements: []
         | 
| 214 220 | 
             
            rubyforge_project: 
         | 
| 215 221 | 
             
            rubygems_version: 1.8.23
         | 
| @@ -223,5 +229,5 @@ test_files: | |
| 223 229 | 
             
            - features/step_definitions/aruba_ext_steps.rb
         | 
| 224 230 | 
             
            - features/support/setup.rb
         | 
| 225 231 | 
             
            - spec/fixtures/Movefile
         | 
| 226 | 
            -
            - spec/remote_host_spec.rb
         | 
| 227 232 | 
             
            - spec/spec_helper.rb
         | 
| 233 | 
            +
            - spec/sql_mover_spec.rb
         | 
    
        data/spec/remote_host_spec.rb
    DELETED
    
    | @@ -1,62 +0,0 @@ | |
| 1 | 
            -
            require 'spec_helper'
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            describe Wordmove::RemoteHost do
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              let!(:config) {
         | 
| 6 | 
            -
                Hashie::Mash.new(YAML::load(File.open(File.join( File.dirname(__FILE__), "fixtures", "Movefile"))))
         | 
| 7 | 
            -
              }
         | 
| 8 | 
            -
             | 
| 9 | 
            -
              let(:host) {
         | 
| 10 | 
            -
                logger = Wordmove::Logger.new
         | 
| 11 | 
            -
                logger.level = Logger::INFO
         | 
| 12 | 
            -
                config.remote[:logger] = @logger
         | 
| 13 | 
            -
                host = Wordmove::RemoteHost.new( config.remote )
         | 
| 14 | 
            -
                host.stub!(:locally_run).and_return( 1 )
         | 
| 15 | 
            -
                host
         | 
| 16 | 
            -
              }
         | 
| 17 | 
            -
             | 
| 18 | 
            -
              context ".upload_dir" do
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                it "should use config ports, username and password properly" do
         | 
| 21 | 
            -
                  host.should_receive(:locally_run).with("rsync", "-azLK", "-e",  "sshpass -p password ssh -p 30000", anything(), "--delete", "username@host:foobar/", "barfoo" )
         | 
| 22 | 
            -
                  host.upload_dir( "foobar", "barfoo" )
         | 
| 23 | 
            -
                end
         | 
| 24 | 
            -
             | 
| 25 | 
            -
                it "should skip port if missing" do
         | 
| 26 | 
            -
                  config.remote!.ssh!.port = nil
         | 
| 27 | 
            -
                  host.should_receive(:locally_run).with("rsync", "-azLK", "-e",  "sshpass -p password ssh", anything(), "--delete", "username@host:foobar/", "barfoo" )
         | 
| 28 | 
            -
                  host.upload_dir( "foobar", "barfoo" )
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                it "should skip username if missing" do
         | 
| 32 | 
            -
                  config.remote!.ssh!.username = nil
         | 
| 33 | 
            -
                  host.should_receive(:locally_run).with("rsync", "-azLK", "-e",  "sshpass -p password ssh -p 30000", anything(), "--delete", "host:foobar/", "barfoo" )
         | 
| 34 | 
            -
                  host.upload_dir( "foobar", "barfoo" )
         | 
| 35 | 
            -
                end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                context "when password is missing" do
         | 
| 38 | 
            -
             | 
| 39 | 
            -
                  before { config.remote!.ssh!.password = nil }
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                  it "should use config ports and username properly" do
         | 
| 42 | 
            -
                    host.should_receive(:locally_run).with("rsync", "-azLK", "-e",  "ssh -p 30000", anything(), "--delete", "username@host:foobar/", "barfoo" )
         | 
| 43 | 
            -
                    host.upload_dir( "foobar", "barfoo" )
         | 
| 44 | 
            -
                  end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
                  it "should skip port if missing" do
         | 
| 47 | 
            -
                    config.remote!.ssh!.port = nil
         | 
| 48 | 
            -
                    host.should_receive(:locally_run).with("rsync", "-azLK", anything(), "--delete", "username@host:foobar/", "barfoo" )
         | 
| 49 | 
            -
                    host.upload_dir( "foobar", "barfoo" )
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  it "should skip username if missing" do
         | 
| 53 | 
            -
                    config.remote!.ssh!.username = nil
         | 
| 54 | 
            -
                    host.should_receive(:locally_run).with("rsync", "-azLK", "-e",  "ssh -p 30000", anything(), "--delete", "host:foobar/", "barfoo" )
         | 
| 55 | 
            -
                    host.upload_dir( "foobar", "barfoo" )
         | 
| 56 | 
            -
                  end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                end
         | 
| 59 | 
            -
             | 
| 60 | 
            -
              end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
            end
         |