wordmove 5.2.2 → 6.0.0.alpha.1

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.
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