wordmove 0.1.0.alpha → 0.1.0.beta

Sign up to get free protection for your applications and to get access to all the features.
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