wordmove 5.2.2 → 6.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +12 -5
  3. data/.rubocop.yml +2 -5
  4. data/.ruby-version +1 -1
  5. data/.yardopts +1 -0
  6. data/CONTRIBUTING.md +15 -0
  7. data/Rakefile +4 -3
  8. data/exe/wordmove +2 -1
  9. data/lib/wordmove/actions/adapt_local_db.rb +95 -0
  10. data/lib/wordmove/actions/adapt_remote_db.rb +87 -0
  11. data/lib/wordmove/actions/backup_local_db.rb +54 -0
  12. data/lib/wordmove/actions/delete_local_file.rb +34 -0
  13. data/lib/wordmove/actions/delete_remote_file.rb +43 -0
  14. data/lib/wordmove/actions/filter_and_setup_tasks_to_run.rb +42 -0
  15. data/lib/wordmove/actions/ftp/backup_remote_db.rb +54 -0
  16. data/lib/wordmove/actions/ftp/cleanup_after_adapt.rb +70 -0
  17. data/lib/wordmove/actions/ftp/download_remote_db.rb +69 -0
  18. data/lib/wordmove/actions/ftp/get_directory.rb +67 -0
  19. data/lib/wordmove/actions/ftp/helpers.rb +91 -0
  20. data/lib/wordmove/actions/ftp/pull_wordpress.rb +56 -0
  21. data/lib/wordmove/actions/ftp/push_wordpress.rb +54 -0
  22. data/lib/wordmove/actions/ftp/put_and_import_dump_remotely.rb +74 -0
  23. data/lib/wordmove/actions/ftp/put_directory.rb +67 -0
  24. data/lib/wordmove/actions/get_file.rb +38 -0
  25. data/lib/wordmove/actions/helpers.rb +142 -0
  26. data/lib/wordmove/actions/put_file.rb +48 -0
  27. data/lib/wordmove/actions/run_after_pull_hook.rb +26 -0
  28. data/lib/wordmove/actions/run_after_push_hook.rb +26 -0
  29. data/lib/wordmove/actions/run_before_pull_hook.rb +26 -0
  30. data/lib/wordmove/actions/run_before_push_hook.rb +26 -0
  31. data/lib/wordmove/actions/run_local_command.rb +34 -0
  32. data/lib/wordmove/actions/setup_context_for_db.rb +79 -0
  33. data/lib/wordmove/actions/ssh/backup_remote_db.rb +49 -0
  34. data/lib/wordmove/actions/ssh/cleanup_after_adapt.rb +42 -0
  35. data/lib/wordmove/actions/ssh/download_remote_db.rb +76 -0
  36. data/lib/wordmove/actions/ssh/get_directory.rb +76 -0
  37. data/lib/wordmove/actions/ssh/helpers.rb +128 -0
  38. data/lib/wordmove/actions/ssh/pull_wordpress.rb +56 -0
  39. data/lib/wordmove/actions/ssh/push_wordpress.rb +54 -0
  40. data/lib/wordmove/actions/ssh/put_and_import_dump_remotely.rb +70 -0
  41. data/lib/wordmove/actions/ssh/put_directory.rb +76 -0
  42. data/lib/wordmove/actions/ssh/run_remote_command.rb +39 -0
  43. data/lib/wordmove/assets/dump.php.erb +6 -6
  44. data/lib/wordmove/assets/import.php.erb +7 -7
  45. data/lib/wordmove/assets/wordmove_schema_global.yml +2 -0
  46. data/lib/wordmove/cli.rb +152 -91
  47. data/lib/wordmove/db_paths_config.rb +44 -0
  48. data/lib/wordmove/doctor/movefile.rb +8 -8
  49. data/lib/wordmove/doctor/mysql.rb +18 -15
  50. data/lib/wordmove/doctor/rsync.rb +2 -2
  51. data/lib/wordmove/doctor/ssh.rb +3 -3
  52. data/lib/wordmove/doctor/wpcli.rb +4 -4
  53. data/lib/wordmove/environments_list.rb +4 -4
  54. data/lib/wordmove/exceptions.rb +13 -0
  55. data/lib/wordmove/generators/movefile.rb +7 -5
  56. data/lib/wordmove/generators/movefile_adapter.rb +11 -5
  57. data/lib/wordmove/guardian.rb +5 -5
  58. data/lib/wordmove/hook.rb +13 -14
  59. data/lib/wordmove/logger.rb +11 -10
  60. data/lib/wordmove/movefile.rb +63 -59
  61. data/lib/wordmove/organizers/ftp/pull.rb +52 -0
  62. data/lib/wordmove/organizers/ftp/push.rb +53 -0
  63. data/lib/wordmove/organizers/ssh/pull.rb +52 -0
  64. data/lib/wordmove/organizers/ssh/push.rb +53 -0
  65. data/lib/wordmove/version.rb +1 -1
  66. data/lib/wordmove/wordpress_directory.rb +76 -8
  67. data/lib/wordmove/wpcli.rb +85 -0
  68. data/lib/wordmove.rb +33 -11
  69. data/wordmove.gemspec +37 -30
  70. metadata +139 -35
  71. data/lib/wordmove/deployer/base.rb +0 -193
  72. data/lib/wordmove/deployer/ftp.rb +0 -160
  73. data/lib/wordmove/deployer/ssh/default_sql_adapter.rb +0 -47
  74. data/lib/wordmove/deployer/ssh/wpcli_sql_adapter.rb +0 -55
  75. data/lib/wordmove/deployer/ssh.rb +0 -169
  76. data/lib/wordmove/sql_adapter/default.rb +0 -68
  77. data/lib/wordmove/sql_adapter/wpcli.rb +0 -54
  78. data/lib/wordmove/wordpress_directory/path.rb +0 -11
@@ -1,47 +0,0 @@
1
- module Wordmove
2
- module Deployer
3
- module Ssh
4
- class DefaultSqlAdapter < SSH
5
- private
6
-
7
- def backup_remote_db!
8
- download_remote_db(local_gzipped_backup_path)
9
- end
10
-
11
- def adapt_local_db!
12
- save_local_db(local_dump_path)
13
- adapt_sql(local_dump_path, local_options, remote_options)
14
- run compress_command(local_dump_path)
15
- import_remote_dump(local_gzipped_dump_path)
16
- end
17
-
18
- def after_push_cleanup!
19
- local_delete(local_gzipped_dump_path)
20
- end
21
-
22
- def backup_local_db!
23
- save_local_db(local_backup_path)
24
- run compress_command(local_backup_path)
25
- end
26
-
27
- def adapt_remote_db!
28
- download_remote_db(local_gzipped_dump_path)
29
- run uncompress_command(local_gzipped_dump_path)
30
- adapt_sql(local_dump_path, remote_options, local_options)
31
- run mysql_import_command(local_dump_path, local_options[:database])
32
- end
33
-
34
- def after_pull_cleanup!
35
- local_delete(local_dump_path)
36
- end
37
-
38
- def adapt_sql(save_to_path, local, remote)
39
- return if options[:no_adapt]
40
-
41
- logger.task_step true, "Adapt dump"
42
- SqlAdapter::Default.new(save_to_path, local, remote).adapt! unless simulate?
43
- end
44
- end
45
- end
46
- end
47
- end
@@ -1,55 +0,0 @@
1
- module Wordmove
2
- module Deployer
3
- module Ssh
4
- class WpcliSqlAdapter < SSH
5
- def backup_remote_db!
6
- download_remote_db(local_gzipped_backup_path)
7
- end
8
-
9
- def adapt_local_db!
10
- save_local_db(local_dump_path)
11
- run wpcli_search_replace(local_options, remote_options, :vhost)
12
- run wpcli_search_replace(local_options, remote_options, :wordpress_path)
13
-
14
- local_search_replace_dump_path = local_wp_content_dir.path("search_replace_dump.sql")
15
- local_gzipped_search_replace_dump_path = local_search_replace_dump_path + '.gz'
16
-
17
- save_local_db(local_search_replace_dump_path)
18
- run compress_command(local_search_replace_dump_path)
19
- import_remote_dump(local_gzipped_search_replace_dump_path)
20
- local_delete(local_gzipped_search_replace_dump_path)
21
- run mysql_import_command(local_dump_path, local_options[:database])
22
- end
23
-
24
- def after_push_cleanup!
25
- local_delete(local_dump_path)
26
- end
27
-
28
- def backup_local_db!
29
- save_local_db(local_backup_path)
30
- run compress_command(local_backup_path)
31
- end
32
-
33
- def adapt_remote_db!
34
- download_remote_db(local_gzipped_dump_path)
35
- run uncompress_command(local_gzipped_dump_path)
36
- run mysql_import_command(local_dump_path, local_options[:database])
37
- run wpcli_search_replace(remote_options, local_options, :vhost)
38
- run wpcli_search_replace(remote_options, local_options, :wordpress_path)
39
- end
40
-
41
- def after_pull_cleanup!
42
- local_delete(local_dump_path)
43
- end
44
-
45
- def wpcli_search_replace(local, remote, config_key)
46
- return if options[:no_adapt]
47
-
48
- logger.task_step true, "adapt dump for #{config_key}"
49
- path = local_options[:wordpress_path]
50
- SqlAdapter::Wpcli.new(local, remote, config_key, path).command unless simulate?
51
- end
52
- end
53
- end
54
- end
55
- end
@@ -1,169 +0,0 @@
1
- require 'pathname'
2
-
3
- module Wordmove
4
- module Deployer
5
- class SSH < Base
6
- attr_reader :local_dump_path,
7
- :local_backup_path,
8
- :local_gzipped_dump_path,
9
- :local_gzipped_backup_path
10
-
11
- def initialize(environment, options)
12
- super(environment, options)
13
- ssh_options = remote_options[:ssh]
14
-
15
- if simulate? && ssh_options[:rsync_options]
16
- ssh_options[:rsync_options].concat(" --dry-run")
17
- elsif simulate?
18
- ssh_options[:rsync_options] = "--dry-run"
19
- end
20
-
21
- @copier = Photocopier::SSH.new(ssh_options).tap { |c| c.logger = logger }
22
-
23
- @local_dump_path = local_wp_content_dir.path("dump.sql")
24
- @local_backup_path = local_wp_content_dir.path("local-backup-#{Time.now.to_i}.sql")
25
- @local_gzipped_dump_path = local_dump_path + '.gz'
26
- @local_gzipped_backup_path = local_wp_content_dir
27
- .path("#{environment}-backup-#{Time.now.to_i}.sql.gz")
28
- end
29
-
30
- private
31
-
32
- def push_db
33
- super
34
-
35
- return true if simulate?
36
-
37
- backup_remote_db!
38
- adapt_local_db!
39
- after_push_cleanup!
40
- end
41
-
42
- def pull_db
43
- super
44
-
45
- return true if simulate?
46
-
47
- backup_local_db!
48
- adapt_remote_db!
49
- after_pull_cleanup!
50
- end
51
-
52
- # In following commands, we do not guard for simulate?
53
- # because it is handled through --dry-run rsync option.
54
- # @see initialize
55
- %w[get put get_directory put_directory delete].each do |command|
56
- define_method "remote_#{command}" do |*args|
57
- logger.task_step false, "#{command}: #{args.join(' ')}"
58
- @copier.send(command, *args)
59
- end
60
- end
61
-
62
- def remote_run(command)
63
- logger.task_step false, command
64
- return true if simulate?
65
-
66
- _stdout, stderr, exit_code = @copier.exec! command
67
-
68
- return true if exit_code.zero?
69
-
70
- raise(
71
- ShellCommandError,
72
- "Error code #{exit_code} returned by command \"#{command}\": #{stderr}"
73
- )
74
- end
75
-
76
- def download_remote_db(local_gizipped_dump_path)
77
- remote_dump_path = remote_wp_content_dir.path("dump.sql")
78
- # dump remote db into file
79
- remote_run mysql_dump_command(remote_options[:database], remote_dump_path)
80
- remote_run compress_command(remote_dump_path)
81
- remote_dump_path += '.gz'
82
- # download remote dump
83
- remote_get(remote_dump_path, local_gizipped_dump_path)
84
- remote_delete(remote_dump_path)
85
- end
86
-
87
- def import_remote_dump(local_gizipped_dump_path)
88
- remote_dump_path = remote_wp_content_dir.path("dump.sql")
89
- remote_gizipped_dump_path = remote_dump_path + '.gz'
90
-
91
- remote_put(local_gizipped_dump_path, remote_gizipped_dump_path)
92
- remote_run uncompress_command(remote_gizipped_dump_path)
93
- remote_run mysql_import_command(remote_dump_path, remote_options[:database])
94
- remote_delete(remote_dump_path)
95
- end
96
-
97
- %w[uploads themes plugins mu_plugins languages].each do |task|
98
- define_method "push_#{task}" do
99
- logger.task "Pushing #{task.titleize}"
100
- local_path = local_options[:wordpress_path]
101
- remote_path = remote_options[:wordpress_path]
102
-
103
- remote_put_directory(local_path, remote_path,
104
- push_exclude_paths(task), push_inlcude_paths(task))
105
- end
106
-
107
- define_method "pull_#{task}" do
108
- logger.task "Pulling #{task.titleize}"
109
- local_path = local_options[:wordpress_path]
110
- remote_path = remote_options[:wordpress_path]
111
- remote_get_directory(remote_path, local_path,
112
- pull_exclude_paths(task), pull_include_paths(task))
113
- end
114
- end
115
-
116
- def push_inlcude_paths(task)
117
- Pathname.new(send(:"local_#{task}_dir").relative_path)
118
- .ascend
119
- .each_with_object([]) do |directory, array|
120
- path = directory.to_path
121
- path.prepend('/') unless path.match? %r{^/}
122
- path.concat('/') unless path.match? %r{/$}
123
- array << path
124
- end
125
- end
126
-
127
- def push_exclude_paths(task)
128
- Pathname.new(send(:"local_#{task}_dir").relative_path)
129
- .dirname
130
- .ascend
131
- .each_with_object([]) do |directory, array|
132
- path = directory.to_path
133
- path.prepend('/') unless path.match? %r{^/}
134
- path.concat('/') unless path.match? %r{/$}
135
- path.concat('*')
136
- array << path
137
- end
138
- .concat(paths_to_exclude)
139
- .concat(['/*'])
140
- end
141
-
142
- def pull_include_paths(task)
143
- Pathname.new(send(:"remote_#{task}_dir").relative_path)
144
- .ascend
145
- .each_with_object([]) do |directory, array|
146
- path = directory.to_path
147
- path.prepend('/') unless path.match? %r{^/}
148
- path.concat('/') unless path.match? %r{/$}
149
- array << path
150
- end
151
- end
152
-
153
- def pull_exclude_paths(task)
154
- Pathname.new(send(:"remote_#{task}_dir").relative_path)
155
- .dirname
156
- .ascend
157
- .each_with_object([]) do |directory, array|
158
- path = directory.to_path
159
- path.prepend('/') unless path.match? %r{^/}
160
- path.concat('/') unless path.match? %r{/$}
161
- path.concat('*')
162
- array << path
163
- end
164
- .concat(paths_to_exclude)
165
- .concat(['/*'])
166
- end
167
- end
168
- end
169
- end
@@ -1,68 +0,0 @@
1
- module Wordmove
2
- module SqlAdapter
3
- class Default
4
- attr_writer :sql_content
5
- attr_reader :sql_path, :source_config, :dest_config
6
-
7
- def initialize(sql_path, source_config, dest_config)
8
- @sql_path = sql_path
9
- @source_config = source_config
10
- @dest_config = dest_config
11
- end
12
-
13
- def sql_content
14
- @sql_content ||= File.open(sql_path).read
15
- end
16
-
17
- def adapt!
18
- replace_vhost!
19
- replace_wordpress_path!
20
- write_sql!
21
- end
22
-
23
- def replace_vhost!
24
- source_vhost = source_config[:vhost]
25
- dest_vhost = dest_config[:vhost]
26
- replace_field!(source_vhost, dest_vhost)
27
- end
28
-
29
- def replace_wordpress_path!
30
- source_path = source_config[:wordpress_absolute_path] || source_config[:wordpress_path]
31
- dest_path = dest_config[:wordpress_absolute_path] || dest_config[:wordpress_path]
32
- replace_field!(source_path, dest_path)
33
- end
34
-
35
- def replace_field!(source_field, dest_field)
36
- return false unless source_field && dest_field
37
-
38
- serialized_replace!(source_field, dest_field)
39
- simple_replace!(source_field, dest_field)
40
- end
41
-
42
- def serialized_replace!(source_field, dest_field)
43
- length_delta = source_field.length - dest_field.length
44
-
45
- sql_content.gsub!(/s:(\d+):([\\]*['"])(.*?)\2;/) do |_|
46
- length = Regexp.last_match(1).to_i
47
- delimiter = Regexp.last_match(2)
48
- string = Regexp.last_match(3)
49
-
50
- string.gsub!(/#{Regexp.escape(source_field)}/) do |_|
51
- length -= length_delta
52
- dest_field
53
- end
54
-
55
- %(s:#{length}:#{delimiter}#{string}#{delimiter};)
56
- end
57
- end
58
-
59
- def simple_replace!(source_field, dest_field)
60
- sql_content.gsub!(source_field, dest_field)
61
- end
62
-
63
- def write_sql!
64
- File.open(sql_path, 'w') { |f| f.write(sql_content) }
65
- end
66
- end
67
- end
68
- end
@@ -1,54 +0,0 @@
1
- module Wordmove
2
- module SqlAdapter
3
- class Wpcli
4
- attr_accessor :sql_content
5
- attr_reader :from, :to, :local_path
6
-
7
- def initialize(source_config, dest_config, config_key, local_path)
8
- @from = source_config[config_key]
9
- @to = dest_config[config_key]
10
- @local_path = local_path
11
- end
12
-
13
- def command
14
- unless wp_in_path?
15
- raise UnmetPeerDependencyError, "WP-CLI is not installed or not in your $PATH"
16
- end
17
-
18
- opts = [
19
- "--path=#{cli_config_path}",
20
- from,
21
- to,
22
- "--quiet",
23
- "--skip-columns=guid",
24
- "--all-tables",
25
- "--allow-root"
26
- ]
27
-
28
- "wp search-replace #{opts.join(' ')}"
29
- end
30
-
31
- private
32
-
33
- def wp_in_path?
34
- system('which wp > /dev/null 2>&1')
35
- end
36
-
37
- def cli_config_path
38
- load_from_yml || load_from_cli || local_path
39
- end
40
-
41
- def load_from_yml
42
- cli_config_path = File.join(local_path, "wp-cli.yml")
43
- return unless File.exist?(cli_config_path)
44
-
45
- YAML.load_file(cli_config_path).with_indifferent_access["path"]
46
- end
47
-
48
- def load_from_cli
49
- cli_config = JSON.parse(`wp cli param-dump --with-values`, symbolize_names: true)
50
- cli_config.dig(:path, :current)
51
- end
52
- end
53
- end
54
- end
@@ -1,11 +0,0 @@
1
- class WordpressDirectory
2
- module Path
3
- WP_CONTENT = :wp_content
4
- WP_CONFIG = :wp_config
5
- PLUGINS = :plugins
6
- MU_PLUGINS = :mu_plugins
7
- THEMES = :themes
8
- UPLOADS = :uploads
9
- LANGUAGES = :languages
10
- end
11
- end