wordmove 1.0.4 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,18 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- wordmove (0.1.0.rc)
4
+ wordmove (1.0.5)
5
5
  activesupport
6
6
  colored
7
7
  i18n
8
- photocopier
8
+ photocopier (>= 0.0.6)
9
9
  rake
10
10
  thor
11
11
 
12
12
  GEM
13
13
  remote: http://rubygems.org/
14
14
  specs:
15
- activesupport (3.2.9)
15
+ activesupport (3.2.12)
16
16
  i18n (~> 0.6)
17
17
  multi_json (~> 1.0)
18
18
  aruba (0.5.1)
@@ -33,22 +33,22 @@ GEM
33
33
  ffi (1.2.0)
34
34
  gherkin (2.11.5)
35
35
  json (>= 1.4.6)
36
- i18n (0.6.1)
36
+ i18n (0.6.4)
37
37
  json (1.7.5)
38
- multi_json (1.4.0)
39
- net-scp (1.0.4)
40
- net-ssh (>= 1.99.1)
41
- net-ssh (2.6.2)
42
- net-ssh-gateway (1.1.0)
43
- net-ssh (>= 1.99.1)
44
- photocopier (0.0.4)
38
+ multi_json (1.7.0)
39
+ net-scp (1.1.0)
40
+ net-ssh (>= 2.6.5)
41
+ net-ssh (2.6.6)
42
+ net-ssh-gateway (1.2.0)
43
+ net-ssh (>= 2.6.5)
44
+ photocopier (0.0.6)
45
45
  activesupport
46
46
  escape
47
47
  i18n
48
48
  net-scp
49
49
  net-ssh
50
50
  net-ssh-gateway
51
- rake (10.0.2)
51
+ rake (10.0.3)
52
52
  rspec (2.12.0)
53
53
  rspec-core (~> 2.12.0)
54
54
  rspec-expectations (~> 2.12.0)
@@ -57,7 +57,7 @@ GEM
57
57
  rspec-expectations (2.12.0)
58
58
  diff-lcs (~> 1.1.3)
59
59
  rspec-mocks (2.12.0)
60
- thor (0.16.0)
60
+ thor (0.17.0)
61
61
 
62
62
  PLATFORMS
63
63
  ruby
data/README.mdown CHANGED
@@ -47,25 +47,31 @@ local:
47
47
  name: "database_name"
48
48
  user: "user"
49
49
  password: "password"
50
- host: "host"
51
- remote:
50
+ host: "127.0.0.1"
51
+ staging:
52
52
  vhost: "http://remote.com"
53
53
  wordpress_path: "/var/www/your_site"
54
- exclude:
55
- - .git
56
- - .DS_Store
57
- - .sass-cache
58
- - Movefile
59
54
  database:
60
55
  name: "database_name"
61
56
  user: "user"
62
57
  password: "password"
63
58
  host: "host"
64
- ssh:
65
- user: "user"
66
- password: "password" # optional, will use SSH public key if available
67
- host: "host"
68
- port: 2202 # optional
59
+ # ssh:
60
+ # host: "host"
61
+ # user: "user"
62
+ # password: "password" # password is optional, will use public keys if available.
63
+ # port: 22 # Port is optional
64
+ # gateway: # Gateway is optional
65
+ # host: "host"
66
+ # user: "user"
67
+ # password: "password" # password is optional, will use public keys if available.
68
+ # ftp:
69
+ # user: "user"
70
+ # password: "password"
71
+ # host: "host"
72
+ # passive: true
73
+ # production: # multiple environments can be specified
74
+ # [...]
69
75
  ```
70
76
 
71
77
  ### If you have your local SSH public key already installed on the remote machine.. (recommended)
@@ -81,9 +87,10 @@ too much about security though: the script is deleted just after the usage,
81
87
  and can only be executed by `wordmove`, as each time it requires a pre-shared
82
88
  one-time-password to be run.
83
89
 
84
- ### If you want to specify both relative and absolute wordpress path (FTP paths anyone?)
85
- Just add to the YAML config a `wordpress_absolute_path` field specifying the absolute path,
86
- while using the usual `wordpress_path` for the relative one.
90
+ ### If you want to specify both relative and absolute wordpress path (FTP relative paths anyone?)
91
+ Just add in the remote section of the Movefile a `wordpress_absolute_path` field
92
+ specifying the absolute path (you may need to recover this from the `__FILE__` constant),
93
+ while using `wordpress_path` for the relative folder path.
87
94
 
88
95
  ### If you want to specify a passive FTP connection
89
96
  Add to the YAML config a `passive` flag set to `true`.
@@ -95,7 +102,7 @@ Add to the YAML config a `passive` flag set to `true`.
95
102
 
96
103
  (The MIT License)
97
104
 
98
- Copyright © 2012 weLaika
105
+ Copyright © 2013 weLaika
99
106
 
100
107
  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:
101
108
 
data/lib/wordmove/cli.rb CHANGED
@@ -11,13 +11,15 @@ module Wordmove
11
11
  end
12
12
 
13
13
  desc "pull", "Pulls WP data from remote host to the local machine"
14
- method_option :db, :aliases => "-d", :type => :boolean
15
- method_option :uploads, :aliases => "-u", :type => :boolean
16
- method_option :themes, :aliases => "-t", :type => :boolean
17
- method_option :plugins, :aliases => "-p", :type => :boolean
18
- method_option :verbose, :aliases => "-v", :type => :boolean
19
- method_option :simulate, :aliases => "-s", :type => :boolean
20
- method_option :config, :aliases => "-c"
14
+ method_option :db, :aliases => "-d", :type => :boolean
15
+ method_option :uploads, :aliases => "-u", :type => :boolean
16
+ method_option :themes, :aliases => "-t", :type => :boolean
17
+ method_option :plugins, :aliases => "-p", :type => :boolean
18
+ method_option :verbose, :aliases => "-v", :type => :boolean
19
+ method_option :simulate, :aliases => "-s", :type => :boolean
20
+ method_option :no_adapt, :type => :boolean
21
+ method_option :environment, :aliases => "-e"
22
+ method_option :config, :aliases => "-c"
21
23
  def pull
22
24
  deployer = Wordmove::Deployer::Base.deployer_for(options)
23
25
  %w(db uploads themes plugins).map(&:to_sym).each do |task|
@@ -28,13 +30,15 @@ module Wordmove
28
30
  end
29
31
 
30
32
  desc "push", "Pushes WP data from local machine to remote host"
31
- method_option :db, :aliases => "-d", :type => :boolean
32
- method_option :uploads, :aliases => "-u", :type => :boolean
33
- method_option :themes, :aliases => "-t", :type => :boolean
34
- method_option :plugins, :aliases => "-p", :type => :boolean
35
- method_option :verbose, :aliases => "-v", :type => :boolean
36
- method_option :simulate, :aliases => "-s", :type => :boolean
37
- method_option :config, :aliases => "-c"
33
+ method_option :uploads, :aliases => "-u", :type => :boolean
34
+ method_option :db, :aliases => "-d", :type => :boolean
35
+ method_option :themes, :aliases => "-t", :type => :boolean
36
+ method_option :plugins, :aliases => "-p", :type => :boolean
37
+ method_option :verbose, :aliases => "-v", :type => :boolean
38
+ method_option :simulate, :aliases => "-s", :type => :boolean
39
+ method_option :no_adapt, :type => :boolean
40
+ method_option :environment, :aliases => "-e"
41
+ method_option :config, :aliases => "-c"
38
42
  def push
39
43
  deployer = Wordmove::Deployer::Base.deployer_for(options)
40
44
  %w(db uploads themes plugins).map(&:to_sym).each do |task|
@@ -9,16 +9,26 @@ module Wordmove
9
9
  class Base
10
10
  attr_reader :options
11
11
  attr_reader :logger
12
+ attr_reader :environment
12
13
 
13
- def self.deployer_for(options)
14
- options = fetch_movefile(options[:config]).merge(options)
14
+ def self.deployer_for(cli_options)
15
+ options = fetch_movefile(cli_options[:config])
16
+ available_enviroments = options.keys.map(&:to_sym) - [ :local ]
17
+ options.merge!(cli_options)
15
18
  recursive_symbolize_keys!(options)
16
- if options[:remote][:ftp]
19
+
20
+ if available_enviroments.size > 1 && options[:environment].nil?
21
+ raise "You need to specify an environment with --environment parameter"
22
+ end
23
+
24
+ environment = (options[:environment] || available_enviroments.first).to_sym
25
+
26
+ if options[environment][:ftp]
17
27
  require 'wordmove/deployer/ftp'
18
- FTP.new(options)
19
- elsif options[:remote][:ssh]
28
+ FTP.new(environment, options)
29
+ elsif options[environment][:ssh]
20
30
  require 'wordmove/deployer/ssh'
21
- SSH.new(options)
31
+ SSH.new(environment, options)
22
32
  else
23
33
  raise Thor::Error, "No valid adapter found."
24
34
  end
@@ -32,7 +42,8 @@ module Wordmove
32
42
  YAML::load(File.open(path))
33
43
  end
34
44
 
35
- def initialize(options = {})
45
+ def initialize(environment, options = {})
46
+ @environment = environment.to_sym
36
47
  @options = options
37
48
  @logger = Logger.new(STDOUT)
38
49
  @logger.level = Logger::DEBUG
@@ -64,18 +75,19 @@ module Wordmove
64
75
  protected
65
76
 
66
77
  def paths_to_exclude
67
- options[:remote][:exclude] || Array.new
78
+ remote_options[:exclude] || Array.new
68
79
  end
69
80
 
70
81
  def run(command)
71
82
  logger.task_step true, command
72
83
  unless simulate?
73
84
  system(command)
85
+ raise "Return code reports an error" unless $?.success?
74
86
  end
75
87
  end
76
88
 
77
89
  def download(url, local_path)
78
- logger.task_step true, "download #{url}"
90
+ logger.task_step true, "download #{url} > #{local_path}"
79
91
  unless simulate?
80
92
  open(local_path, 'w') do |file|
81
93
  file << open(url).read
@@ -88,21 +100,23 @@ module Wordmove
88
100
  end
89
101
 
90
102
  def local_wpcontent_path(*args)
91
- File.join(options[:local][:wordpress_path], "wp-content", *args)
103
+ File.join(local_options[:wordpress_path], "wp-content", *args)
92
104
  end
93
105
 
94
106
  def remote_wpcontent_path(*args)
95
- File.join(options[:remote][:wordpress_path], "wp-content", *args)
107
+ File.join(remote_options[:wordpress_path], "wp-content", *args)
96
108
  end
97
109
 
98
110
  def remote_wpcontent_url(*args)
99
- options[:remote][:vhost] + File.join("/wp-content", *args)
111
+ remote_options[:vhost] + File.join("/wp-content", *args)
100
112
  end
101
113
 
102
114
  def adapt_sql(save_to_path, local, remote)
103
- logger.task_step true, "adapt dump"
104
- unless simulate?
105
- SqlMover.new(save_to_path, local, remote).move!
115
+ unless options[:no_adapt]
116
+ logger.task_step true, "adapt dump"
117
+ unless simulate?
118
+ SqlMover.new(save_to_path, local, remote).move!
119
+ end
106
120
  end
107
121
  end
108
122
 
@@ -125,6 +139,19 @@ module Wordmove
125
139
  Escape.shell_command(arguments) + " < #{dump_path}"
126
140
  end
127
141
 
142
+ def save_local_db(local_dump_path)
143
+ # dump local mysql into file
144
+ run mysql_dump_command(local_options[:database], local_dump_path)
145
+ end
146
+
147
+ def remote_options
148
+ options[environment].clone
149
+ end
150
+
151
+ def local_options
152
+ options[:local].clone
153
+ end
154
+
128
155
  private
129
156
 
130
157
  def self.recursive_symbolize_keys! hash
@@ -7,9 +7,9 @@ module Wordmove
7
7
  module Deployer
8
8
  class FTP < Base
9
9
 
10
- def initialize(options)
10
+ def initialize(environment, options)
11
11
  super
12
- ftp_options = options[:remote][:ftp]
12
+ ftp_options = remote_options[:ftp]
13
13
  @copier = Photocopier::FTP.new(ftp_options)
14
14
  @copier.logger = logger
15
15
  end
@@ -17,29 +17,20 @@ module Wordmove
17
17
  def push_db
18
18
  super
19
19
 
20
- remote_import_script_path = remote_wpcontent_path("import.php")
21
20
  local_dump_path = local_wpcontent_path("dump.sql")
22
21
  remote_dump_path = remote_wpcontent_path("dump.sql")
22
+ local_backup_path = local_wpcontent_path("remote-backup-#{Time.now.to_i}.sql")
23
+
24
+ download_remote_db(local_backup_path)
25
+ save_local_db(local_dump_path)
23
26
 
24
- # dump local mysql into file
25
- run mysql_dump_command(options[:local][:database], local_dump_path)
26
27
  # gsub sql
27
- adapt_sql(local_dump_path, options[:local], options[:remote])
28
+ adapt_sql(local_dump_path, local_options, remote_options)
28
29
  # upload it
29
30
  remote_put(local_dump_path, remote_dump_path)
30
31
 
31
- # generate a secure one-time password
32
- one_time_password = SecureRandom.hex(40)
33
- # generate import script
34
- import_script = generate_import_script(options[:remote][:database], one_time_password)
35
- # upload import script
36
- remote_put(import_script, remote_import_script_path)
37
- # run import script
38
- import_url = "#{remote_wpcontent_url("import.php")}?shared_key=#{one_time_password}&start=1&foffset=0&totalqueries=0&fn=dump.sql"
39
- download(import_url, local_dump_path + "_")
32
+ import_remote_dump
40
33
 
41
- # remove script remotely
42
- remote_delete(remote_import_script_path)
43
34
  # remove dump remotely
44
35
  remote_delete(remote_dump_path)
45
36
  # and locally
@@ -48,28 +39,17 @@ module Wordmove
48
39
 
49
40
  def pull_db
50
41
  super
51
-
52
- remote_dump_script = remote_wpcontent_path("dump.php")
53
42
  local_dump_path = local_wpcontent_path("dump.sql")
43
+ local_backup_path = local_wpcontent_path("local-backup-#{Time.now.to_i}.sql")
54
44
 
55
- # generate a secure one-time password
56
- one_time_password = SecureRandom.hex(40)
57
-
58
- # generate dump script
59
- dump_script = generate_dump_script(options[:remote][:database], one_time_password)
60
- # upload the dump script
61
- remote_put(dump_script, remote_dump_script)
62
- # download the resulting dump (using the password)
63
- dump_url = "#{remote_wpcontent_url("dump.php")}?shared_key=#{one_time_password}"
64
- download(dump_url, local_dump_path)
45
+ save_local_db(local_backup_path)
46
+ download_remote_db(local_dump_path)
65
47
 
66
48
  # gsub sql
67
- adapt_sql(local_dump_path, options[:remote], options[:local])
49
+ adapt_sql(local_dump_path, remote_options, local_options)
68
50
  # import locally
69
- run mysql_import_command(local_dump_path, options[:local][:database])
51
+ run mysql_import_command(local_dump_path, local_options[:database])
70
52
 
71
- # remove it remotely
72
- remote_delete(remote_dump_script)
73
53
  # and locally
74
54
  run "rm #{local_dump_path}"
75
55
  end
@@ -112,6 +92,38 @@ module Wordmove
112
92
  template.result(binding)
113
93
  end
114
94
 
95
+ def download_remote_db(local_dump_path)
96
+ remote_dump_script = remote_wpcontent_path("dump.php")
97
+ # generate a secure one-time password
98
+ one_time_password = SecureRandom.hex(40)
99
+ # generate dump script
100
+ dump_script = generate_dump_script(remote_options[:database], one_time_password)
101
+ # upload the dump script
102
+ remote_put(dump_script, remote_dump_script)
103
+ # download the resulting dump (using the password)
104
+ dump_url = "#{remote_wpcontent_url("dump.php")}?shared_key=#{one_time_password}"
105
+ download(dump_url, local_dump_path)
106
+ # remove it remotely
107
+ remote_delete(remote_dump_script)
108
+ end
109
+
110
+ def import_remote_dump
111
+ temp_path = local_wpcontent_path("temp.txt")
112
+ remote_import_script_path = remote_wpcontent_path("import.php")
113
+ # generate a secure one-time password
114
+ one_time_password = SecureRandom.hex(40)
115
+ # generate import script
116
+ import_script = generate_import_script(remote_options[:database], one_time_password)
117
+ # upload import script
118
+ remote_put(import_script, remote_import_script_path)
119
+ # run import script
120
+ import_url = "#{remote_wpcontent_url("import.php")}?shared_key=#{one_time_password}&start=1&foffset=0&totalqueries=0&fn=dump.sql"
121
+ download(import_url, temp_path)
122
+ run "rm #{temp_path}"
123
+ # remove script remotely
124
+ remote_delete(remote_import_script_path)
125
+ end
126
+
115
127
  end
116
128
  end
117
129
  end
@@ -4,9 +4,9 @@ require 'photocopier/ssh'
4
4
  module Wordmove
5
5
  module Deployer
6
6
  class SSH < Base
7
- def initialize(options)
7
+ def initialize(environment, options)
8
8
  super
9
- ssh_options = options[:remote][:ssh]
9
+ ssh_options = remote_options[:ssh]
10
10
  @copier = Photocopier::SSH.new(ssh_options)
11
11
  @copier.logger = logger
12
12
  end
@@ -15,19 +15,12 @@ module Wordmove
15
15
  super
16
16
 
17
17
  local_dump_path = local_wpcontent_path("dump.sql")
18
- remote_dump_path = remote_wpcontent_path("dump.sql")
18
+ local_backup_path = local_wpcontent_path("remote-backup-#{Time.now.to_i}.sql")
19
+ download_remote_db(local_backup_path)
19
20
 
20
- # dump local mysql into file
21
- run mysql_dump_command(options[:local][:database], local_dump_path)
22
- # gsub sql
23
- adapt_sql(local_dump_path, options[:local], options[:remote])
24
- # upload it
25
- remote_put(local_dump_path, remote_dump_path)
26
- # import it remotely
27
- remote_run mysql_import_command(remote_dump_path, options[:remote][:database])
28
- # remove it remotely
29
- remote_delete(remote_dump_path)
30
- # and locally
21
+ save_local_db(local_dump_path)
22
+ adapt_sql(local_dump_path, local_options, remote_options)
23
+ import_remote_dump(local_dump_path)
31
24
  run "rm #{local_dump_path}"
32
25
  end
33
26
 
@@ -36,18 +29,12 @@ module Wordmove
36
29
 
37
30
  local_dump_path = local_wpcontent_path("dump.sql")
38
31
  remote_dump_path = remote_wpcontent_path("dump.sql")
32
+ local_backup_path = local_wpcontent_path("local-backup-#{Time.now.to_i}.sql")
33
+ save_local_db(local_backup_path)
39
34
 
40
- # dump remote db into file
41
- remote_run mysql_dump_command(options[:remote][:database], remote_dump_path)
42
- # download remote dump
43
- remote_get(remote_dump_path, local_dump_path)
44
- # gsub sql
45
- adapt_sql(local_dump_path, options[:remote], options[:local])
46
- # import locally
47
- run mysql_import_command(local_dump_path, options[:local][:database])
48
- # remove it remotely
49
- remote_delete(remote_dump_path)
50
- # and locally
35
+ download_remote_db(local_dump_path)
36
+ adapt_sql(local_dump_path, remote_options, local_options)
37
+ run mysql_import_command(local_dump_path, local_options[:database])
51
38
  run "rm #{local_dump_path}"
52
39
  end
53
40
 
@@ -65,10 +52,27 @@ module Wordmove
65
52
  def remote_run(command)
66
53
  logger.task_step false, command
67
54
  unless simulate?
68
- @copier.session.exec! command
55
+ stdout, stderr, exit_code = @copier.exec! command
56
+ raise "Error code #{exit_code} returned by command \"#{cmd}\": #{stderr}" unless exit_code.zero?
69
57
  end
70
58
  end
71
59
 
60
+ def download_remote_db(local_dump_path)
61
+ remote_dump_path = remote_wpcontent_path("dump.sql")
62
+ # dump remote db into file
63
+ remote_run mysql_dump_command(remote_options[:database], remote_dump_path)
64
+ # download remote dump
65
+ remote_get(remote_dump_path, local_dump_path)
66
+ remote_delete(remote_dump_path)
67
+ end
68
+
69
+ def import_remote_dump(local_dump_path)
70
+ remote_dump_path = remote_wpcontent_path("dump.sql")
71
+ remote_put(local_dump_path, remote_dump_path)
72
+ remote_run mysql_import_command(remote_dump_path, remote_options[:database])
73
+ remote_delete(remote_dump_path)
74
+ end
75
+
72
76
  end
73
77
  end
74
78
  end
@@ -6,7 +6,7 @@ local:
6
6
  user: "user"
7
7
  password: "password"
8
8
  host: "127.0.0.1"
9
- remote:
9
+ staging:
10
10
  vhost: "http://remote.com"
11
11
  wordpress_path: "/var/www/your_site"
12
12
  database:
@@ -14,14 +14,19 @@ remote:
14
14
  user: "user"
15
15
  password: "password"
16
16
  host: "host"
17
- ssh: # also ftp is allowed
18
- host: "host"
19
- user: "user"
20
- password: "password" # password is optional, will use public keys if available.
21
- # port: 22 # Port is optional
22
- #
23
- # gateway:
24
- # host: "host"
25
- # user: "user"
26
- # password: "password" # password is optional, will use public keys if available.
27
-
17
+ # ssh:
18
+ # host: "host"
19
+ # user: "user"
20
+ # password: "password" # password is optional, will use public keys if available.
21
+ # port: 22 # Port is optional
22
+ # gateway: # Gateway is optional
23
+ # host: "host"
24
+ # user: "user"
25
+ # password: "password" # password is optional, will use public keys if available.
26
+ # ftp:
27
+ # user: "user"
28
+ # password: "password"
29
+ # host: "host"
30
+ # passive: true
31
+ # production: # multiple environments can be specified
32
+ # [...]
@@ -43,10 +43,17 @@ module Wordmove
43
43
  def serialized_replace!(source_field, dest_field)
44
44
  length_delta = source_field.length - dest_field.length
45
45
 
46
- sql_content.gsub!(/s:(\d+):([\\'"]+)#{Regexp.escape(source_field)}/) do |match|
47
- source_length = $1.to_i
48
- dest_length = source_length - length_delta
49
- "s:#{dest_length}:#{$2}#{dest_field}"
46
+ sql_content.gsub!(/s:(\d+):([\\'"]+)(.*?)\2;/) do |match|
47
+ length = $1.to_i
48
+ delimiter = $2
49
+ string = $3
50
+
51
+ string.gsub!(/#{Regexp.escape(source_field)}/) do |match|
52
+ length -= length_delta
53
+ dest_field
54
+ end
55
+
56
+ %(s:#{length}:#{delimiter}#{string}#{delimiter};)
50
57
  end
51
58
  end
52
59
 
@@ -1,3 +1,3 @@
1
1
  module Wordmove
2
- VERSION = "1.0.4"
2
+ VERSION = "1.0.6"
3
3
  end
@@ -82,21 +82,30 @@ describe Wordmove::SqlMover do
82
82
  end
83
83
 
84
84
  context ".serialized_replace!" do
85
- let(:content) { 's:4:"spam";s:20:"http://dump.com/spam";s:6:"foobar";s:22:"http://dump.com/foobar";s:8:"sausages"' }
85
+ let(:content) { 'a:3:{i:0;s:20:"http://dump.com/spam";i:1;s:6:"foobar";i:2;s:22:"http://dump.com/foobar";}' }
86
86
  let(:sql) { Tempfile.new('sql').tap do |d| d.write(content); d.close end }
87
87
  let(:sql_path) { sql.path }
88
88
 
89
89
  it "should replace source vhost with dest vhost" do
90
90
  sql_mover.serialized_replace!('http://dump.com', 'http://shrubbery.com')
91
- 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"'
91
+ sql_mover.sql_content.should == 'a:3:{i:0;s:25:"http://shrubbery.com/spam";i:1;s:6:"foobar";i:2;s:27:"http://shrubbery.com/foobar";}'
92
92
  end
93
93
 
94
94
  context "given multiple types of string quoting" do
95
- let(:content) { "s:20:\\\"http://dump.com/spam\\\";s:6:'foobar';s:22:'http://dump.com/foobar';s:8:'sausages'" }
95
+ let(:content) { "a:3:{s:20:\\\"http://dump.com/spam\\\";s:6:'foobar';s:22:'http://dump.com/foobar';s:8:'sausages';}" }
96
96
 
97
- it "handles replacing just as well" do
97
+ it "should handle replacing just as well" do
98
98
  sql_mover.serialized_replace!('http://dump.com', 'http://shrubbery.com')
99
- sql_mover.sql_content.should == "s:25:\\\"http://shrubbery.com/spam\\\";s:6:'foobar';s:27:'http://shrubbery.com/foobar';s:8:'sausages'"
99
+ sql_mover.sql_content.should == "a:3:{s:25:\\\"http://shrubbery.com/spam\\\";s:6:'foobar';s:27:'http://shrubbery.com/foobar';s:8:'sausages';}"
100
+ end
101
+ end
102
+
103
+ context "given multiple occurences in the same string" do
104
+ let(:content) { 'a:1:{i:0;s:52:"ni http://dump.com/spam ni http://dump.com/foobar ni";}' }
105
+
106
+ it "should replace all occurences" do
107
+ sql_mover.serialized_replace!('http://dump.com', 'http://shrubbery.com')
108
+ sql_mover.sql_content.should == 'a:1:{i:0;s:62:"ni http://shrubbery.com/spam ni http://shrubbery.com/foobar ni";}'
100
109
  end
101
110
  end
102
111
  end
data/wordmove.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |gem|
20
20
  gem.add_dependency "thor"
21
21
  gem.add_dependency "activesupport"
22
22
  gem.add_dependency "i18n"
23
- gem.add_dependency "photocopier"
23
+ gem.add_dependency "photocopier", ">= 0.0.6"
24
24
 
25
25
  gem.add_development_dependency "rspec"
26
26
  gem.add_development_dependency "cucumber"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wordmove
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 1.0.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-20 00:00:00.000000000 Z
12
+ date: 2013-03-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colored
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ! '>='
100
100
  - !ruby/object:Gem::Version
101
- version: '0'
101
+ version: 0.0.6
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: 0.0.6
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: rspec
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -180,7 +180,6 @@ files:
180
180
  - lib/wordmove/assets/dump.php.erb
181
181
  - lib/wordmove/assets/import.php.erb
182
182
  - lib/wordmove/cli.rb
183
- - lib/wordmove/deployer.rb
184
183
  - lib/wordmove/deployer/base.rb
185
184
  - lib/wordmove/deployer/ftp.rb
186
185
  - lib/wordmove/deployer/ssh.rb
@@ -230,3 +229,4 @@ test_files:
230
229
  - spec/fixtures/Movefile
231
230
  - spec/spec_helper.rb
232
231
  - spec/sql_mover_spec.rb
232
+ has_rdoc:
@@ -1,166 +0,0 @@
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.user}", "--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.user}", "--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.user}", "--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.user}", "--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