wordmove 0.1.0.alpha → 0.1.0.beta

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/README.mdown CHANGED
@@ -1,6 +1,8 @@
1
1
  # Wordmove
2
2
 
3
- Wordmove is a nice little gem that lets you automatically mirror local Wordpress installations and DB data back and forth from your local development machine to the remote staging server.
3
+ Wordmove is a nice little gem that lets you automatically mirror local Wordpress
4
+ installations and DB data back and forth from your local development machine to
5
+ the remote staging server. SSH and FTP connections are both supported.
4
6
 
5
7
  Think of it like Capistrano for Wordpress, complete with push/pull capabilities.
6
8
 
@@ -9,7 +11,7 @@ Think of it like Capistrano for Wordpress, complete with push/pull capabilities.
9
11
  That's easy:
10
12
 
11
13
  ```
12
- gem install wordmove
14
+ gem install wordmove --pre
13
15
  ```
14
16
 
15
17
  ## Usage
@@ -33,7 +35,7 @@ local:
33
35
  wordpress_path: "~/dev/sites/your_site"
34
36
  database:
35
37
  name: "database_name"
36
- username: "username"
38
+ user: "user"
37
39
  password: "password"
38
40
  host: "host"
39
41
  remote:
@@ -46,34 +48,30 @@ remote:
46
48
  - Movefile
47
49
  database:
48
50
  name: "database_name"
49
- username: "username"
51
+ user: "user"
50
52
  password: "password"
51
53
  host: "host"
52
54
  ssh:
53
- username: "username"
55
+ user: "user"
54
56
  password: "password" # optional, will use SSH public key if available
55
57
  host: "host"
56
58
  port: 2202 # optional
57
59
  ```
58
- ## About SSH authentication
59
-
60
60
  ### If you have your local SSH public key already installed on the remote machine.. (recommended)
61
- Just drop the `remote.ssh.password` file on your `Movefile`.
62
-
63
- ### Else..
64
- You need to have [`sshpass`](http://sourceforge.net/projects/sshpass/) on your machine. On Linux, install it with your standard package manager. On Mac, you can have it via [`brew`](https://github.com/mxcl/homebrew):
61
+ Just not use the `remote.ssh.password` field on your `Movefile`. Easy peasy.
65
62
 
66
- ```
67
- sudo brew install https://raw.github.com/gist/1513663/3e98bf9e03feb7e31eeddcd08f89ca86163a376d/sshpass.rb
68
- ```
63
+ ### If you want to specify SSH password on the Movefile
64
+ Please take a look at the various gotchas of the underlying [`photocopier` gem](https://github.com/stefanoverna/photocopier#password-gotchas).
69
65
 
70
- **Please note that on Ubuntu 11.10 `sshpass` is at version 1.04, which has a [bug](https://bugs.launchpad.net/ubuntu/+source/sshpass/+bug/774882) that prevents it from working. Install version 1.03 or 1.05.**
66
+ ### How the heck you are able to sync the DB via FTP?
67
+ Thanks for asking. We basically upload via FTP a PHP script that performs the various
68
+ import/export operations. This script then gets executed via HTTP. Don't worry
69
+ too much about security though: the script is deleted just after the usage,
70
+ and can only be executed by `wordmove`, as each time it requires a pre-shared
71
+ one-time-password to be run.
71
72
 
72
- ## Requirements
73
- * Wordmove requires an SSH connection to the remote host;
74
- * Wordmove requires `mysqldump` and `mysql` to be present in the remote host and executable by the SSH user;
75
- * Wordmove requires `rsync` to be present and executable in your machine;
76
- * As said above, you may also need `sshpass` on your machine;
73
+ * The dump script is the [`MYSQL-dump` PHP package](https://github.com/dg/MySQL-dump) by David Grudl;
74
+ * The import script used is the [BigDump](http://www.ozerov.de/bigdump/) library;
77
75
 
78
76
  ## License
79
77
 
@@ -10,7 +10,7 @@ if ($_GET['shared_key'] != $shared_key) {
10
10
  // Database configuration
11
11
 
12
12
  $db_server = '<%= escape_php db[:host] %>';
13
- $db_username = '<%= escape_php db[:user] %>';
13
+ $db_username = '<%= escape_php db[:username] %>';
14
14
  $db_password = '<%= escape_php db[:password] %>';
15
15
  $db_name = '<%= escape_php db[:name] %>';
16
16
 
@@ -48,7 +48,7 @@ $comment[]='/*!'; // Or add your own string to leave out oth
48
48
  // See http://dev.mysql.com/doc/refman/5.0/en/charset-charsets.html for the full list
49
49
  // Change this if you have problems with non-latin letters
50
50
 
51
- $db_connection_charset = '<%= db[:charset] || utf8';
51
+ $db_connection_charset = '<%= db[:charset] || 'utf8' %>';
52
52
 
53
53
  // Default query delimiter: this character at the line end tells Bigdump where a SQL statement ends
54
54
  // Can be changed by DELIMITER statement in the dump file (normally used when defining procedures/functions)
@@ -1,5 +1,6 @@
1
1
  require 'active_support/core_ext'
2
2
  require 'wordmove/logger'
3
+ require 'wordmove/sql_mover'
3
4
  require 'escape'
4
5
 
5
6
  module Wordmove
@@ -51,17 +52,21 @@ module Wordmove
51
52
  %w(uploads themes plugins).each do |task|
52
53
  define_method "push_#{task}" do
53
54
  logger.task "Pushing #{task.titleize}"
54
- remote_put_directory(local_wpcontent_path(task), remote_wpcontent_path(task))
55
+ remote_put_directory(local_wpcontent_path(task), remote_wpcontent_path(task), paths_to_exclude)
55
56
  end
56
57
 
57
58
  define_method "pull_#{task}" do
58
59
  logger.task "Pulling #{task.titleize}"
59
- remote_get_directory(remote_wpcontent_path(task), local_wpcontent_path(task))
60
+ remote_get_directory(remote_wpcontent_path(task), local_wpcontent_path(task), paths_to_exclude)
60
61
  end
61
62
  end
62
63
 
63
64
  protected
64
65
 
66
+ def paths_to_exclude
67
+ options[:remote][:exclude] || Array.new
68
+ end
69
+
65
70
  def run(command)
66
71
  logger.task_step true, command
67
72
  unless simulate?
@@ -97,16 +102,14 @@ module Wordmove
97
102
  def adapt_sql(save_to_path, local, remote)
98
103
  logger.task_step true, "adapt dump"
99
104
  unless simulate?
100
- File.open(save_to_path, 'a') do |file|
101
- file.write "UPDATE wp_options SET option_value=\"#{remote[:vhost]}\" WHERE option_name=\"siteurl\" OR option_name=\"home\";\n"
102
- end
105
+ SqlMover.new(save_to_path, local, remote).move!
103
106
  end
104
107
  end
105
108
 
106
109
  def mysql_dump_command(options, save_to_path)
107
110
  arguments = [ "mysqldump" ]
108
111
  arguments << "--host=#{options[:host]}" if options[:host].present?
109
- arguments << "--user=#{options[:user]}" if options[:user].present?
112
+ arguments << "--user=#{options[:username]}" if options[:username].present?
110
113
  arguments << "--password=#{options[:password]}" if options[:password].present?
111
114
  arguments << "--default-character-set=#{options[:charset]}" if options[:charset].present?
112
115
  arguments << options[:name]
@@ -116,7 +119,7 @@ module Wordmove
116
119
  def mysql_import_command(dump_path, options)
117
120
  arguments = [ "mysql" ]
118
121
  arguments << "--host=#{options[:host]}" if options[:host].present?
119
- arguments << "--user=#{options[:user]}" if options[:user].present?
122
+ arguments << "--user=#{options[:username]}" if options[:username].present?
120
123
  arguments << "--password=#{options[:password]}" if options[:password].present?
121
124
  arguments << "--database=#{options[:name]}"
122
125
  Escape.shell_command(arguments) + " < #{dump_path}"
@@ -10,7 +10,8 @@ module Wordmove
10
10
  def initialize(options)
11
11
  super
12
12
  ftp_options = options[:remote][:ftp]
13
- @copier = Photocopier::FTP.new(ftp_options.merge(logger: logger))
13
+ @copier = Photocopier::FTP.new(ftp_options)
14
+ @copier.logger = logger
14
15
  end
15
16
 
16
17
  def push_db
@@ -7,7 +7,8 @@ module Wordmove
7
7
  def initialize(options)
8
8
  super
9
9
  ssh_options = options[:remote][:ssh]
10
- @copier = Photocopier::SSH.new(ssh_options.merge(logger: logger))
10
+ @copier = Photocopier::SSH.new(ssh_options)
11
+ @copier.logger = logger
11
12
  end
12
13
 
13
14
  def push_db
@@ -3,30 +3,25 @@ local:
3
3
  wordpress_path: "~/dev/sites/your_site"
4
4
  database:
5
5
  name: "database_name"
6
- username: "username"
6
+ username: "user"
7
7
  password: "password"
8
- host: "host"
8
+ host: "127.0.0.1"
9
9
  remote:
10
10
  vhost: "http://remote.com"
11
11
  wordpress_path: "/var/www/your_site"
12
- exclude:
13
- - .git
14
- - .DS_Store
15
- - .sass-cache
16
- - Movefile
17
12
  database:
18
13
  name: "database_name"
19
- username: "username"
14
+ username: "user"
20
15
  password: "password"
21
16
  host: "host"
22
- ssh:
17
+ ssh: # also ftp is allowed
23
18
  host: "host"
24
- username: "username"
19
+ user: "user"
25
20
  password: "password" # password is optional, will use public keys if available.
26
21
  # port: 22 # Port is optional
27
22
  #
28
23
  # gateway:
29
24
  # host: "host"
30
- # username: "username"
25
+ # user: "user"
31
26
  # password: "password" # password is optional, will use public keys if available.
32
27
 
@@ -0,0 +1,59 @@
1
+ module Wordmove
2
+
3
+ class SqlMover
4
+
5
+ attr_accessor :sql_content
6
+ attr_reader :sql_path, :source_config, :dest_config
7
+
8
+ def initialize(sql_path, source_config, dest_config)
9
+ @sql_path = sql_path
10
+ @source_config = source_config
11
+ @dest_config = dest_config
12
+ end
13
+
14
+ def sql_content
15
+ @sql_content ||= File.open(sql_path).read
16
+ end
17
+
18
+ def move!
19
+ replace_vhost!
20
+ replace_wordpress_path!
21
+ write_sql!
22
+ end
23
+
24
+ def replace_vhost!
25
+ replace_field!(:vhost)
26
+ end
27
+
28
+ def replace_wordpress_path!
29
+ replace_field!(:wordpress_path)
30
+ end
31
+
32
+ def replace_field!(field_sym)
33
+ source_field = source_config[field_sym]
34
+ dest_field = dest_config[field_sym]
35
+ if source_field && dest_field
36
+ serialized_replace!(source_field, dest_field)
37
+ simple_replace!(source_field, dest_field)
38
+ end
39
+ end
40
+
41
+ def serialized_replace!(source_field, dest_field)
42
+ length_delta = source_field.length - dest_field.length
43
+
44
+ sql_content.gsub!(/s:(\d+):"#{Regexp.escape(source_field)}/) do |match|
45
+ source_length = $1.to_i
46
+ dest_length = source_length - length_delta
47
+ "s:#{dest_length}:\"#{dest_field}"
48
+ end
49
+ end
50
+
51
+ def simple_replace!(source_field, dest_field)
52
+ sql_content.gsub!(source_field, dest_field)
53
+ end
54
+
55
+ def write_sql!
56
+ File.open(sql_path, 'w') {|f| f.write(sql_content) }
57
+ end
58
+ end
59
+ end
@@ -1,3 +1,3 @@
1
1
  module Wordmove
2
- VERSION = "0.1.0.alpha"
2
+ VERSION = "0.1.0.beta"
3
3
  end
@@ -3,24 +3,19 @@ local:
3
3
  wordpress_path: "~/dev/sites/your_site"
4
4
  database:
5
5
  name: "database_name"
6
- username: "username"
6
+ user: "user"
7
7
  password: "password"
8
8
  host: "host"
9
9
  remote:
10
10
  vhost: "http://remote.com"
11
11
  wordpress_path: "/var/www/your_site"
12
- exclude:
13
- - .git
14
- - .DS_Store
15
- - .sass-cache
16
- - Movefile
17
12
  database:
18
13
  name: "database_name"
19
- username: "username"
14
+ user: "user"
20
15
  password: "password"
21
16
  host: "host"
22
17
  ssh:
23
- username: "username"
18
+ user: "user"
24
19
  password: "password"
25
20
  host: "host"
26
21
  port: 30000
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: 0.1.0.alpha
4
+ version: 0.1.0.beta
5
5
  prerelease: 6
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-10-26 00:00:00.000000000 Z
12
+ date: 2012-11-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colored
@@ -183,9 +183,8 @@ files:
183
183
  - lib/wordmove/deployer/ssh.rb
184
184
  - lib/wordmove/generators/Movefile
185
185
  - lib/wordmove/generators/movefile.rb
186
- - lib/wordmove/hosts/local_host.rb
187
- - lib/wordmove/hosts/remote_host.rb
188
186
  - lib/wordmove/logger.rb
187
+ - lib/wordmove/sql_mover.rb
189
188
  - lib/wordmove/version.rb
190
189
  - pkg/wordmove-0.0.1.gem
191
190
  - pkg/wordmove-0.0.2.gem
@@ -1,41 +0,0 @@
1
- require 'escape'
2
-
3
- module Wordmove
4
- class LocalHost
5
-
6
- attr_reader :options
7
- attr_reader :logger
8
- attr_reader :ssh_extras
9
-
10
- def initialize(options = {})
11
- @options = Hashie::Mash.new(options)
12
- @logger = @options[:logger]
13
- end
14
-
15
- def run(*args)
16
- command = shell_command(*args)
17
- logger.verbose "Executing locally #{command}"
18
- unless system(command)
19
- raise Thor::Error, "Error executing \"#{command}\""
20
- end
21
- end
22
-
23
- def close
24
- end
25
-
26
- protected
27
-
28
- def shell_command(*args)
29
- options = args.extract_options!
30
- command = Escape.shell_command(args)
31
- if options[:stdin]
32
- command += " < #{options[:stdin]}"
33
- end
34
- if options[:stdout]
35
- command += " > #{options[:stdout]}"
36
- end
37
- command
38
- end
39
-
40
- end
41
- end
@@ -1,135 +0,0 @@
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 rsync(source_dir, destination_dir)
90
-
91
- exclude_file = Tempfile.new('exclude')
92
- exclude_file.write(options.exclude.join("\n"))
93
- exclude_file.close
94
-
95
- arguments = [ "-azLKO" ]
96
-
97
- if options.ssh && (options.ssh.port || options.ssh.password || options.ssh.gateway)
98
-
99
- remote_shell_arguments = []
100
-
101
- if options.ssh.gateway
102
- host = options.ssh.gateway.host
103
- host = "#{options.ssh.gateway.username}@#{host}" if options.ssh.gateway.username
104
- remote_shell_arguments << [ "ssh", host ]
105
- if options.ssh.gateway.port
106
- remote_shell_arguments << [ "-p", options.ssh.gateway.port ]
107
- end
108
- end
109
-
110
- remote_shell_arguments << [ "ssh" ]
111
-
112
- if options.ssh.port
113
- remote_shell_arguments << [ "-p", options.ssh.port ]
114
- end
115
-
116
- if options.ssh.password
117
- remote_shell_arguments = [ "sshpass", "-p", options.ssh.password ] + remote_shell_arguments
118
- end
119
-
120
- host = options.ssh.host
121
- host = "#{options.ssh.username}@#{host}" if options.ssh.username
122
- remote_shell_arguments << host
123
-
124
- arguments << [ "-e", remote_shell_arguments.join(" ") ]
125
- end
126
-
127
- arguments << [ "--exclude-from=#{exclude_file.path}", "--delete", source_dir, destination_dir ]
128
- arguments.flatten!
129
- locally_run "rsync", *arguments
130
-
131
- exclude_file.unlink
132
- end
133
-
134
- end
135
- end