wordmove 6.0.0.alpha.5 → 6.0.0.alpha.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1ea52bea7c72c65b2b9a55a425d54bfd586b2c8c71e998517d489f4f55fd1616
4
- data.tar.gz: 90430c49a99da9c6ded3519a103066b26c13ee6771d89114ed85b46dad39860f
3
+ metadata.gz: 1e1645bb92c5ec1ef2f74eb99eb0ad62eb42648af628104c23c6286e3bf1505b
4
+ data.tar.gz: 5b44c223013a491f2fbca11da41d063597363f8a28b07cf14f556d48b79c4aac
5
5
  SHA512:
6
- metadata.gz: 95dd8ab8d22c5f8ec4faa15deb9b95792ecce5e2826d43266cbfdebac551e3f1ee6d646a86b2248ae5a16696849dc6e403ccd1a01d3cbadaa629ae0d62148ea4
7
- data.tar.gz: e2413aaf068bd8993a1d4701504eddcdd3259b713f1bd1de92e1b10d7523234862c5e398e367277b8ddc80fb4ab00c717575ad6ac50cb6cb01fdfd6f53e4136f
6
+ metadata.gz: 1039454681f0c345713c3cb3777429197deac2a50f1f2bddf781fe2145e2ba099365a5600edad49272d680ddaa1b8f4be3a82d7a0f9f9929dbf3eb38c28f5999
7
+ data.tar.gz: 4215958770c983f0d156162e943eaefe06d55c7e4a9cc1d085e7ec87e7130cca7a43daf9881602350b01c65a5f576f38d1c85b12522bbd6964be84beadf5f59b
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.7.1
2
+ TargetRubyVersion: 3.1.0
3
3
  DisplayCopNames: true
4
4
  DisplayStyleGuide: true
5
5
  NewCops: enable
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.7.1
1
+ 3.1.0
@@ -9,7 +9,7 @@ module Wordmove
9
9
  class AdaptLocalDb
10
10
  extend ::LightService::Action
11
11
  include Wordmove::Actions::Helpers
12
- include Wordmove::Wpcli
12
+ include Wordmove::WpcliHelpers
13
13
 
14
14
  expects :local_options,
15
15
  :remote_options,
@@ -38,63 +38,104 @@ module Wordmove
38
38
 
39
39
  next context if simulate?(cli_options: context.cli_options)
40
40
 
41
- result = Wordmove::Actions::RunLocalCommand.execute(
42
- cli_options: context.cli_options,
43
- logger: context.logger,
44
- command: mysql_dump_command(
45
- env_db_options: context.local_options[:database],
46
- save_to_path: context.db_paths.local.path
47
- )
48
- )
49
- context.fail_and_return!(result.message) if result.failure?
41
+ context.logger.task_step true, dump_command(context)
42
+ begin
43
+ system(dump_command(context), exception: true)
44
+ rescue RuntimeError, SystemExit => e
45
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
46
+ end
50
47
 
51
48
  if context.cli_options[:no_adapt]
52
49
  context.logger.warn 'Skipping DB adapt'
53
50
  else
54
- result = Wordmove::Actions::RunLocalCommand.execute(
55
- cli_options: context.cli_options,
56
- logger: context.logger,
57
- command: wpcli_search_replace_command(context, :vhost)
58
- )
59
- context.fail_and_return!(result.message) if result.failure?
60
-
61
- result = Wordmove::Actions::RunLocalCommand.execute(
62
- cli_options: context.cli_options,
63
- logger: context.logger,
64
- command: wpcli_search_replace_command(context, :wordpress_path)
65
- )
66
- context.fail_and_return!(result.message) if result.failure?
67
- end
51
+ %i[vhost wordpress_path].each do |key|
52
+ command = search_replace_command(context, key)
53
+ context.logger.task_step true, command
68
54
 
69
- result = Wordmove::Actions::RunLocalCommand.execute(
70
- cli_options: context.cli_options,
55
+ begin
56
+ system(command, exception: true)
57
+ rescue RuntimeError, SystemExit => e
58
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
59
+ end
60
+ end
61
+ end
71
62
 
72
- logger: context.logger,
73
- command: mysql_dump_command(
74
- env_db_options: context.local_options[:database],
75
- save_to_path: context.db_paths.local.adapted_path
76
- )
77
- )
78
- context.fail_and_return!(result.message) if result.failure?
63
+ context.logger.task_step true, dump_adapted_command(context)
64
+ begin
65
+ system(dump_adapted_command(context), exception: true)
66
+ rescue RuntimeError, SystemExit => e
67
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
68
+ end
79
69
 
80
70
  if context.photocopier.is_a? Photocopier::SSH
81
- result = Wordmove::Actions::RunLocalCommand.execute(
82
- cli_options: context.cli_options,
83
- logger: context.logger,
84
- command: compress_command(file_path: context.db_paths.local.adapted_path)
85
- )
86
- context.fail_and_return!(result.message) if result.failure?
71
+ context.logger.task_step true, compress_command(context)
72
+ begin
73
+ system(compress_command(context), exception: true)
74
+ rescue RuntimeError, SystemExit => e
75
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
76
+ end
77
+ end
78
+
79
+ context.logger.task_step true, import_original_db_command(context)
80
+ begin
81
+ system(import_original_db_command(context), exception: true)
82
+ rescue RuntimeError, SystemExit => e
83
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
84
+ end
85
+ end
86
+
87
+ def self.dump_command(context)
88
+ "wp db export #{context.db_paths.local.path} --allow-root --quiet " \
89
+ "--path=#{wpcli_config_path(context)}"
90
+ end
91
+
92
+ def self.dump_adapted_command(context)
93
+ "wp db export #{context.db_paths.local.adapted_path} --allow-root --quiet " \
94
+ "--path=#{wpcli_config_path(context)}"
95
+ end
96
+
97
+ def self.import_original_db_command(context)
98
+ "wp db import #{context.db_paths.local.path} --allow-root --quiet " \
99
+ "--path=#{wpcli_config_path(context)}"
100
+ end
101
+
102
+ def self.compress_command(context)
103
+ command = ['nice']
104
+ command << '-n'
105
+ command << '0'
106
+ command << 'gzip'
107
+ command << '-9'
108
+ command << '-f'
109
+ command << "\"#{context.db_paths.local.adapted_path}\""
110
+ command.join(' ')
111
+ end
112
+
113
+ # Compose and returns the search-replace command. It's intended to be
114
+ # used from a +LightService::Action+
115
+ #
116
+ # @param context [LightService::Context] The context of an action
117
+ # @param config_key [:vhost, :wordpress_path] Determines what will be replaced in DB
118
+ # @return [String]
119
+ # @!scope class
120
+ def self.search_replace_command(context, config_key)
121
+ unless %i[vhost wordpress_path].include?(config_key)
122
+ raise ArgumentError, "Unexpected `config_key` #{config_key}.:vhost" \
123
+ 'or :wordpress_path expected'
87
124
  end
88
125
 
89
- result = Wordmove::Actions::RunLocalCommand.execute(
90
- cli_options: context.cli_options,
91
- logger: context.logger,
92
- command: mysql_import_command(
93
- dump_path: context.db_paths.local.path,
94
- env_db_options: context.local_options[:database]
95
- )
96
- )
97
- context.fail_and_return!(result.message) if result.failure?
126
+ [
127
+ 'wp search-replace',
128
+ "--path=#{wpcli_config_path(context)}",
129
+ '"\A' + context.dig(:local_options, config_key) + '\Z"', # rubocop:disable Style/StringConcatenation
130
+ '"' + context.dig(:remote_options, config_key) + '"', # rubocop:disable Style/StringConcatenation
131
+ '--regex-delimiter="|"',
132
+ '--regex',
133
+ '--precise',
134
+ '--quiet',
135
+ '--skip-columns=guid',
136
+ '--all-tables',
137
+ '--allow-root'
138
+ ].join(' ')
98
139
  end
99
140
  end
100
141
  end
@@ -14,7 +14,7 @@ module Wordmove
14
14
  class AdaptRemoteDb
15
15
  extend ::LightService::Action
16
16
  include Wordmove::Actions::Helpers
17
- include Wordmove::Wpcli
17
+ include Wordmove::WpcliHelpers
18
18
 
19
19
  expects :local_options,
20
20
  :cli_options,
@@ -39,11 +39,12 @@ module Wordmove
39
39
  next context if simulate?(cli_options: context.cli_options)
40
40
 
41
41
  if File.exist?(context.db_paths.local.gzipped_path)
42
- Wordmove::Actions::RunLocalCommand.execute(
43
- cli_options: context.cli_options,
44
- logger: context.logger,
45
- command: uncompress_command(file_path: context.db_paths.local.gzipped_path)
46
- )
42
+ context.logger.task_step true, uncompress_command(context)
43
+ begin
44
+ system(uncompress_command(context), exception: true)
45
+ rescue RuntimeError, SystemExit => e
46
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
47
+ end
47
48
  end
48
49
 
49
50
  unless File.exist?(context.db_paths.local.path)
@@ -52,37 +53,76 @@ module Wordmove
52
53
  )
53
54
  end
54
55
 
55
- result = Wordmove::Actions::RunLocalCommand.execute(
56
- cli_options: context.cli_options,
57
- logger: context.logger,
58
- command: mysql_import_command(
59
- dump_path: context.db_paths.local.path,
60
- env_db_options: context.local_options[:database]
61
- )
62
- )
63
- context.fail_and_return!(result.message) if result.failure?
56
+ context.logger.task_step true, import_db_command(context)
57
+ begin
58
+ system(import_db_command(context), exception: true)
59
+ rescue RuntimeError, SystemExit => e
60
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
61
+ end
64
62
 
65
63
  if context.cli_options[:no_adapt]
66
64
  context.logger.warn 'Skipping DB adapt'
67
65
  next context
68
66
  end
69
67
 
70
- result = Wordmove::Actions::RunLocalCommand.execute(
71
- cli_options: context.cli_options,
72
- logger: context.logger,
73
- command: wpcli_search_replace_command(context, :vhost)
74
- )
75
- context.fail_and_return!(result.message) if result.failure?
76
-
77
- result = Wordmove::Actions::RunLocalCommand.execute(
78
- cli_options: context.cli_options,
79
- logger: context.logger,
80
- command: wpcli_search_replace_command(context, :wordpress_path)
81
- )
82
- context.fail_and_return!(result.message) if result.failure?
68
+ %i[vhost wordpress_path].each do |key|
69
+ command = search_replace_command(context, key)
70
+ context.logger.task_step true, command
71
+ begin
72
+ system(command, exception: true)
73
+ rescue RuntimeError, SystemExit => e
74
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
75
+ end
76
+ end
83
77
 
84
78
  context.logger.success 'Local DB adapted'
85
79
  end
80
+
81
+ # Construct the command to deflate a compressed file as a string.
82
+ #
83
+ # @param file_path [String] The path where the file to be deflated is located
84
+ # @return [String] the command
85
+ # @!scope class
86
+ def self.uncompress_command(context)
87
+ command = ['gzip']
88
+ command << '-d'
89
+ command << '-f'
90
+ command << "\"#{context.db_paths.local.gzipped_path}\""
91
+ command.join(' ')
92
+ end
93
+
94
+ def self.import_db_command(context)
95
+ "wp db import #{context.db_paths.local.path} --allow-root --quiet " \
96
+ "--path=#{wpcli_config_path(context)}"
97
+ end
98
+
99
+ # Compose and returns the search-replace command. It's intended to be
100
+ # used from a +LightService::Action+
101
+ #
102
+ # @param context [LightService::Context] The context of an action
103
+ # @param config_key [:vhost, :wordpress_path] Determines what will be replaced in DB
104
+ # @return [String]
105
+ # @!scope class
106
+ def self.search_replace_command(context, config_key)
107
+ unless %i[vhost wordpress_path].include?(config_key)
108
+ raise ArgumentError, "Unexpected `config_key` #{config_key}.:vhost" \
109
+ 'or :wordpress_path expected'
110
+ end
111
+
112
+ [
113
+ 'wp search-replace',
114
+ "--path=#{wpcli_config_path(context)}",
115
+ '"\A' + context.dig(:remote_options, config_key) + '\Z"', # rubocop:disable Style/StringConcatenation
116
+ '"' + context.dig(:local_options, config_key) + '"', # rubocop:disable Style/StringConcatenation
117
+ '--regex-delimiter="|"',
118
+ '--regex',
119
+ '--precise',
120
+ '--quiet',
121
+ '--skip-columns=guid',
122
+ '--all-tables',
123
+ '--allow-root'
124
+ ].join(' ')
125
+ end
86
126
  end
87
127
  end
88
128
  end
@@ -30,27 +30,41 @@ module Wordmove
30
30
  next context
31
31
  end
32
32
 
33
- result = Wordmove::Actions::RunLocalCommand.execute(
34
- cli_options: context.cli_options,
35
- logger: context.logger,
36
- command: mysql_dump_command(
37
- env_db_options: context.local_options[:database],
38
- save_to_path: context.db_paths.backup.local.path
39
- )
40
- )
41
- context.fail_and_return!(result.message) if result.failure?
33
+ context.logger.task_step true, dump_command(context)
42
34
 
43
- result = Wordmove::Actions::RunLocalCommand.execute(
44
- cli_options: context.cli_options,
45
- logger: context.logger,
46
- command: compress_command(file_path: context.db_paths.backup.local.path)
47
- )
48
- context.fail_and_return!(result.message) if result.failure?
35
+ begin
36
+ system(dump_command(context), exception: true)
37
+ rescue RuntimeError, SystemExit => e
38
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
39
+ end
40
+
41
+ context.logger.task_step true, compress_command(context)
42
+
43
+ begin
44
+ system(compress_command(context), exception: true)
45
+ rescue RuntimeError, SystemExit => e
46
+ context.fail_and_return!("Local command status reports an error: #{e.message}")
47
+ end
49
48
 
50
49
  context.logger.success(
51
50
  "Backup saved at #{context.db_paths.backup.local.gzipped_path}"
52
51
  )
53
52
  end
53
+
54
+ def self.dump_command(context)
55
+ "wp db export #{context.db_paths.backup.local.path} --allow-root --quiet"
56
+ end
57
+
58
+ def self.compress_command(context)
59
+ command = ['nice']
60
+ command << '-n'
61
+ command << '0'
62
+ command << 'gzip'
63
+ command << '-9'
64
+ command << '-f'
65
+ command << "\"#{context.db_paths.backup.local.path}\""
66
+ command.join(' ')
67
+ end
54
68
  end
55
69
  end
56
70
  end
@@ -52,12 +52,10 @@ module Wordmove
52
52
  remote_options: context.remote_options
53
53
  ).url('import.php')
54
54
  DbPathsConfig.ftp.local.generated_dump_script_path = generate_dump_script(
55
- remote_db_options: context.remote_options[:database],
56
- token: token
55
+ remote_db_options: context.remote_options[:database], token:
57
56
  )
58
57
  DbPathsConfig.ftp.local.generated_import_script_path = generate_import_script(
59
- remote_db_options: context.remote_options[:database],
60
- token: token
58
+ remote_db_options: context.remote_options[:database], token:
61
59
  )
62
60
  DbPathsConfig.ftp.local.temp_path = local_wp_content_dir(
63
61
  local_options: context.local_options
@@ -3,6 +3,7 @@ mapping:
3
3
  vhost:
4
4
  pattern: /^https?:\/\//
5
5
  wordpress_path:
6
+ required: true
6
7
  database:
7
8
  type: map
8
9
  required: true
@@ -15,9 +16,6 @@ mapping:
15
16
  required: true
16
17
  host:
17
18
  required: true
18
- mysqldump_options:
19
- port:
20
- charset:
21
19
  paths:
22
20
  type: map
23
21
  mapping:
data/lib/wordmove/cli.rb CHANGED
@@ -32,23 +32,16 @@ module Wordmove
32
32
  exit 1
33
33
  end
34
34
 
35
- def initial_context(cli_options)
36
- cli_options.deep_symbolize_keys!
37
- movefile = Wordmove::Movefile.new(cli_options)
38
-
39
- [cli_options, movefile]
40
- end
41
-
42
- def movefile_from(**cli_options)
35
+ def movefile_from(cli_options)
43
36
  ensure_wordpress_options_presence!(cli_options)
44
- Wordmove::Movefile.new(cli_options)
37
+ Wordmove::Movefile.new(cli_options, nil, true)
45
38
  rescue MovefileNotFound => e
46
39
  Logger.new($stdout).error(e.message)
47
40
  exit 1
48
41
  end
49
42
 
50
- def call_organizer_with(klass:, movefile:, **cli_options)
51
- result = klass.call(cli_options: cli_options, movefile: movefile)
43
+ def call_organizer_with(klass:, movefile:, cli_options:)
44
+ result = klass.call(cli_options, movefile)
52
45
 
53
46
  exit 0 if result.success?
54
47
 
@@ -114,22 +107,22 @@ module Wordmove
114
107
  private
115
108
 
116
109
  def call_pull_organizer_with(**cli_options)
117
- movefile = movefile_from(**cli_options)
110
+ movefile = movefile_from(cli_options)
118
111
 
119
112
  if movefile.options.dig(movefile.environment, :ssh)
120
113
  call_organizer_with(
121
114
  klass: Wordmove::Organizers::Ssh::Pull,
122
- movefile: movefile,
123
- **cli_options
115
+ movefile:, cli_options:
124
116
  )
125
117
  elsif movefile.options.dig(movefile.environment, :ftp)
126
118
  call_organizer_with(
127
119
  klass: Wordmove::Organizers::Ftp::Pull,
128
- movefile: movefile,
129
- **cli_options
120
+ movefile:, cli_options:
130
121
  )
131
122
  else
132
- raise NoAdapterFound, 'No valid adapter found.'
123
+ raise NoAdapterFound, 'No valid adapter found. It seems like your movefile.yml lacks ' \
124
+ 'an ssh or ftp section for the current environment. ' \
125
+ 'Run `wordmove doctor` for more info'
133
126
  end
134
127
  rescue NoAdapterFound => e
135
128
  Logger.new($stdout).error(e.message)
@@ -149,22 +142,22 @@ module Wordmove
149
142
  private
150
143
 
151
144
  def call_push_organizer_with(**cli_options)
152
- movefile = movefile_from(**cli_options)
145
+ movefile = movefile_from(cli_options)
153
146
 
154
147
  if movefile.options.dig(movefile.environment, :ssh)
155
148
  call_organizer_with(
156
149
  klass: Wordmove::Organizers::Ssh::Push,
157
- movefile: movefile,
158
- **cli_options
150
+ movefile:, cli_options:
159
151
  )
160
152
  elsif movefile.options.dig(movefile.environment, :ftp)
161
153
  call_organizer_with(
162
154
  klass: Wordmove::Organizers::Ftp::Push,
163
- movefile: movefile,
164
- **cli_options
155
+ movefile:, cli_options:
165
156
  )
166
157
  else
167
- raise NoAdapterFound, 'No valid adapter found.'
158
+ raise NoAdapterFound, 'No valid adapter found. It seems like your movefile.yml lacks ' \
159
+ 'an ssh or ftp section for the current environment. ' \
160
+ 'Run `wordmove doctor` for more info'
168
161
  end
169
162
  rescue NoAdapterFound => e
170
163
  Logger.new($stdout).error(e.message)
@@ -5,7 +5,7 @@ module Wordmove
5
5
  attr_reader :movefile, :contents, :root_keys
6
6
 
7
7
  def initialize(cli_options = {}, dir = '.')
8
- @movefile = Wordmove::Movefile.new(cli_options, dir)
8
+ @movefile = Wordmove::Movefile.new(cli_options, dir, false)
9
9
 
10
10
  begin
11
11
  @contents = movefile.options
@@ -7,7 +7,7 @@ module Wordmove
7
7
  @logger = Logger.new($stdout).tap { |l| l.level = Logger::INFO }
8
8
  begin
9
9
  @config = Wordmove::Movefile
10
- .new({ config: movefile_name }, movefile_dir)
10
+ .new({ config: movefile_name }, movefile_dir, false)
11
11
  .options[:local][:database]
12
12
  rescue Psych::SyntaxError => e
13
13
  logger.error e.message
@@ -16,8 +16,8 @@ module Wordmove
16
16
  end
17
17
 
18
18
  def print
19
- contents = parse_movefile(movefile: movefile)
20
- generate_vhost_list(contents: contents)
19
+ contents = parse_movefile(movefile:)
20
+ generate_vhost_list(contents:)
21
21
  output
22
22
  end
23
23
 
@@ -55,7 +55,7 @@ module Wordmove
55
55
  #
56
56
  def generate_vhost_list(contents:)
57
57
  # select object which has 'vhost' only
58
- vhosts = select_vhost(contents: contents)
58
+ vhosts = select_vhost(contents:)
59
59
  vhosts.each do |list|
60
60
  if list[:env] == :local
61
61
  @local_vhost << list
@@ -1,16 +1,15 @@
1
1
  module Wordmove
2
2
  module Generators
3
3
  class Movefile
4
- include MovefileAdapter
5
-
6
4
  def self.generate
7
- new.copy_movefile
5
+ copy_movefile
8
6
  end
9
7
 
10
- def copy_movefile
8
+ def self.copy_movefile
9
+ wordpress_path = File.expand_path(Dir.pwd)
11
10
  content = ERB.new(File.read(File.join(__dir__, 'movefile.yml'))).result(binding)
12
- files = Dry::Files.new
13
11
 
12
+ files = Dry::Files.new
14
13
  files.write('movefile.yml', content)
15
14
  end
16
15
  end
@@ -2,14 +2,15 @@ global:
2
2
  sql_adapter: wpcli
3
3
 
4
4
  local:
5
- vhost: http://vhost.local
6
5
  wordpress_path: <%= wordpress_path %> # use an absolute path here
7
6
 
8
- database:
9
- name: <%= database.name %>
10
- user: <%= database.user %>
11
- password: "<%= database.password %>" # could be blank, so always use quotes around
12
- host: <%= database.host %>
7
+ # paths: # you can customize wordpress internal paths
8
+ # wp_content: wp-content
9
+ # uploads: wp-content/uploads
10
+ # plugins: wp-content/plugins
11
+ # mu_plugins: wp-content/mu-plugins
12
+ # themes: wp-content/themes
13
+ # languages: wp-content/languages
13
14
 
14
15
  production:
15
16
  vhost: http://example.com
@@ -40,6 +41,7 @@ production:
40
41
  - 'wp-config.php'
41
42
  - 'wp-content/*.sql.gz'
42
43
  - '*.orig'
44
+ - 'wp-cli.yml'
43
45
 
44
46
  # paths: # you can customize wordpress internal paths
45
47
  # wp_content: wp-content
@@ -56,8 +56,6 @@ module Wordmove
56
56
  private
57
57
 
58
58
  def fetch(verbose = true) # rubocop:disable Style/OptionalBooleanParameter
59
- load_dotenv
60
-
61
59
  entries = if config_file_name.nil?
62
60
  Dir["#{File.join(start_dir, '{M,m}ovefile')}{,.yml,.yaml}"]
63
61
  else
@@ -75,18 +73,40 @@ module Wordmove
75
73
  end
76
74
 
77
75
  found = entries.first
76
+
78
77
  logger.task("Using Movefile: #{found}") if verbose == true
79
- YAML.safe_load(ERB.new(File.read(found)).result, [], [], true).deep_symbolize_keys!
78
+ load_dotenv(verbose)
79
+
80
+ options = YAML.safe_load(ERB.new(File.read(found)).result, symbolize_names: true)
81
+
82
+ merge_local_options_from_wpcli(options)
83
+ end
84
+
85
+ def merge_local_options_from_wpcli(options)
86
+ config_path = options.dig(:local, :wordpress_path)
87
+
88
+ options.merge(
89
+ local: {
90
+ database: {
91
+ password: Wordmove::WpcliHelpers.get_config('DB_PASSWORD', config_path:),
92
+ host: Wordmove::WpcliHelpers.get_config('DB_HOST', config_path:),
93
+ name: Wordmove::WpcliHelpers.get_config('DB_NAME', config_path:),
94
+ user: Wordmove::WpcliHelpers.get_config('DB_USER', config_path:)
95
+ },
96
+ vhost: Wordmove::WpcliHelpers.get_option('siteurl', config_path:),
97
+ wordpress_path: config_path
98
+ }
99
+ )
80
100
  end
81
101
 
82
- def load_dotenv
102
+ def load_dotenv(verbose)
83
103
  env_files = Dir[File.join(start_dir, '.env')]
84
104
 
85
105
  found_env = env_files.first
86
106
 
87
107
  return false unless found_env.present?
88
108
 
89
- logger.info("Using .env file: #{found_env}")
109
+ logger.info("Using .env file: #{found_env}") if verbose
90
110
  Dotenv.load(found_env)
91
111
  end
92
112
 
@@ -6,21 +6,23 @@ module Wordmove
6
6
  include Wordmove::Actions::Helpers
7
7
  include Wordmove::Actions::Ftp::Helpers
8
8
 
9
- def self.call(cli_options:, movefile:)
9
+ # Can't use keyword arguments since LightService still has some problems with modern
10
+ # ruby syntax: https://github.com/adomokos/light-service/pull/224
11
+ def self.call(cli_options, movefile)
10
12
  logger = Logger.new($stdout, movefile.secrets).tap { |l| l.level = Logger::DEBUG }
11
13
  remote_options = movefile.options[movefile.environment]
12
- ftp_opts = ftp_options(remote_options: remote_options)
14
+ ftp_opts = ftp_options(remote_options:)
13
15
 
14
16
  LightService::Configuration.logger = ::Logger.new($stdout) if cli_options[:debug]
15
17
 
16
18
  with(
17
- cli_options: cli_options,
19
+ cli_options:,
18
20
  global_options: movefile.options[:global],
19
21
  local_options: movefile.options[:local],
20
- remote_options: remote_options,
21
- movefile: movefile,
22
- guardian: Wordmove::Guardian.new(cli_options: cli_options, action: :pull),
23
- logger: logger,
22
+ remote_options:,
23
+ movefile:,
24
+ guardian: Wordmove::Guardian.new(cli_options:, action: :pull),
25
+ logger:,
24
26
  photocopier: Photocopier::FTP
25
27
  .new(ftp_opts)
26
28
  .tap { |c| c.logger = logger }
@@ -6,21 +6,23 @@ module Wordmove
6
6
  include Wordmove::Actions::Helpers
7
7
  include Wordmove::Actions::Ftp::Helpers
8
8
 
9
- def self.call(cli_options:, movefile:)
9
+ # Can't use keyword arguments since LightService still has some problems with modern
10
+ # ruby syntax: https://github.com/adomokos/light-service/pull/224
11
+ def self.call(cli_options, movefile)
10
12
  logger = Logger.new($stdout, movefile.secrets).tap { |l| l.level = Logger::DEBUG }
11
13
  remote_options = movefile.options[movefile.environment]
12
- ftp_opts = ftp_options(remote_options: remote_options)
14
+ ftp_opts = ftp_options(remote_options:)
13
15
 
14
16
  LightService::Configuration.logger = ::Logger.new($stdout) if cli_options[:debug]
15
17
 
16
18
  with(
17
- cli_options: cli_options,
19
+ cli_options:,
18
20
  global_options: movefile.options[:global],
19
21
  local_options: movefile.options[:local],
20
- remote_options: remote_options,
21
- movefile: movefile,
22
- guardian: Wordmove::Guardian.new(cli_options: cli_options, action: :push),
23
- logger: logger,
22
+ remote_options:,
23
+ movefile:,
24
+ guardian: Wordmove::Guardian.new(cli_options:, action: :push),
25
+ logger:,
24
26
  photocopier: Photocopier::FTP
25
27
  .new(ftp_opts)
26
28
  .tap { |c| c.logger = logger }
@@ -6,21 +6,23 @@ module Wordmove
6
6
  include Wordmove::Actions::Helpers
7
7
  include Wordmove::Actions::Ssh::Helpers
8
8
 
9
- def self.call(cli_options:, movefile:)
9
+ # Can't use keyword arguments since LightService still has some problems with modern
10
+ # ruby syntax: https://github.com/adomokos/light-service/pull/224
11
+ def self.call(cli_options, movefile)
10
12
  logger = Logger.new($stdout, movefile.secrets).tap { |l| l.level = Logger::DEBUG }
11
13
  remote_options = movefile.options[movefile.environment]
12
- ssh_opts = ssh_options(remote_options: remote_options, simulate: cli_options[:simulate])
14
+ ssh_opts = ssh_options(remote_options:, simulate: cli_options[:simulate])
13
15
 
14
16
  LightService::Configuration.logger = ::Logger.new($stdout) if cli_options[:debug]
15
17
 
16
18
  with(
17
- cli_options: cli_options,
19
+ cli_options:,
18
20
  global_options: movefile.options[:global],
19
21
  local_options: movefile.options[:local],
20
- remote_options: remote_options,
21
- movefile: movefile,
22
- guardian: Wordmove::Guardian.new(cli_options: cli_options, action: :pull),
23
- logger: logger,
22
+ remote_options:,
23
+ movefile:,
24
+ guardian: Wordmove::Guardian.new(cli_options:, action: :pull),
25
+ logger:,
24
26
  photocopier: Photocopier::SSH
25
27
  .new(ssh_opts)
26
28
  .tap { |c| c.logger = logger }
@@ -6,21 +6,23 @@ module Wordmove
6
6
  include Wordmove::Actions::Helpers
7
7
  include Wordmove::Actions::Ssh::Helpers
8
8
 
9
- def self.call(cli_options:, movefile:)
9
+ # Can't use keyword arguments since LightService still has some problems with modern
10
+ # ruby syntax: https://github.com/adomokos/light-service/pull/224
11
+ def self.call(cli_options, movefile)
10
12
  logger = Logger.new($stdout, movefile.secrets).tap { |l| l.level = Logger::DEBUG }
11
13
  remote_options = movefile.options[movefile.environment]
12
- ssh_opts = ssh_options(remote_options: remote_options, simulate: cli_options[:simulate])
14
+ ssh_opts = ssh_options(remote_options:, simulate: cli_options[:simulate])
13
15
 
14
16
  LightService::Configuration.logger = ::Logger.new($stdout) if cli_options[:debug]
15
17
 
16
18
  with(
17
- cli_options: cli_options,
19
+ cli_options:,
18
20
  global_options: movefile.options[:global],
19
21
  local_options: movefile.options[:local],
20
- remote_options: remote_options,
21
- movefile: movefile,
22
- guardian: Wordmove::Guardian.new(cli_options: cli_options, action: :push),
23
- logger: logger,
22
+ remote_options:,
23
+ movefile:,
24
+ guardian: Wordmove::Guardian.new(cli_options:, action: :push),
25
+ logger:,
24
26
  photocopier: Photocopier::SSH
25
27
  .new(ssh_opts)
26
28
  .tap { |c| c.logger = logger }
@@ -1,3 +1,3 @@
1
1
  module Wordmove
2
- VERSION = '6.0.0.alpha.5'.freeze
2
+ VERSION = '6.0.0.alpha.6'.freeze
3
3
  end
@@ -1,7 +1,7 @@
1
1
  module Wordmove
2
2
  # This class is a sort of mini-wrapper around the wp-cli executable.
3
3
  # It's responsible to run or produce wp-cli commands.
4
- module Wpcli
4
+ module WpcliHelpers
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  included do
@@ -17,42 +17,27 @@ module Wordmove
17
17
  system('which wp > /dev/null 2>&1')
18
18
  end
19
19
 
20
- # Compose and returns the search-replace command. It's intended to be
21
- # used from a +LightService::Action+
22
- #
23
- # @param context [LightService::Context] The context of an action
24
- # @param config_key [:vhost, :wordpress_path] Determines what will be replaced in DB
25
- # @return [String]
26
- # @!scope class
27
- def wpcli_search_replace_command(context, config_key)
28
- unless %i[vhost wordpress_path].include?(config_key)
29
- raise ArgumentError, "Unexpected `config_key` #{config_key}.:vhost" \
30
- 'or :wordpress_path expected'
31
- end
32
-
33
- [
34
- 'wp search-replace',
35
- "--path=#{wpcli_config_path(context)}",
36
- '"\A' + context.dig(:remote_options, config_key) + '\Z"', # rubocop:disable Style/StringConcatenation
37
- '"' + context.dig(:local_options, config_key) + '"', # rubocop:disable Style/StringConcatenation
38
- '--regex-delimiter="|"',
39
- '--regex',
40
- '--precise',
41
- '--quiet',
42
- '--skip-columns=guid',
43
- '--all-tables',
44
- '--allow-root'
45
- ].join(' ')
46
- end
47
-
48
20
  # Returns the wordpress path from wp-cli (with precedence) or from movefile
49
21
  #
50
- # It's intended to be used from a +LightService::Action+
22
+ # It's intended to be used from a +LightService::Action+, but it also supports
23
+ # to receive a path as argument. If the argument is not a LightService::Context
24
+ # then it will be treated as a path.
25
+ # The path passed as argument should be the wordpress installation path, but it's
26
+ # not strictly mandatory: the method will try to load a wpcli's YAML config
27
+ # from that path, so you can potentially use it with any path
51
28
  #
52
- # @param context [LightService::Context] The context of an action
29
+ # @param context [LightService::Context|String] The context of an action or a path as string
53
30
  # @return [String]
54
31
  # @!scope class
55
- def wpcli_config_path(context)
32
+ def wpcli_config_path(context_or_path)
33
+ context = if context_or_path.is_a? LightService::Context
34
+ context_or_path
35
+ else
36
+ # We need to make it quack like a duck in order to be
37
+ # backward compatible with previous code
38
+ { local_options: { wordpress_path: context_or_path } }
39
+ end
40
+
56
41
  load_from_yml(context) || load_from_wpcli || context.dig(:local_options, :wordpress_path)
57
42
  end
58
43
 
@@ -63,7 +48,8 @@ module Wordmove
63
48
  # @!scope class
64
49
  # @!visibility private
65
50
  def load_from_yml(context)
66
- yml_path = File.join(context.dig(:local_options, :wordpress_path), 'wp-cli.yml')
51
+ config_path = context.dig(:local_options, :wordpress_path) || '.'
52
+ yml_path = File.join(config_path, 'wp-cli.yml')
67
53
 
68
54
  return unless File.exist?(yml_path)
69
55
 
@@ -87,5 +73,13 @@ module Wordmove
87
73
  nil
88
74
  end
89
75
  end
76
+
77
+ def self.get_option(option, config_path:)
78
+ `wp option get #{option} --allow-root --path=#{config_path}`.chomp
79
+ end
80
+
81
+ def self.get_config(config, config_path:)
82
+ `wp config get #{config} --allow-root --path=#{config_path}`.chomp
83
+ end
90
84
  end
91
85
  end
data/lib/wordmove.rb CHANGED
@@ -17,6 +17,8 @@ require 'yaml'
17
17
 
18
18
  require 'photocopier'
19
19
 
20
+ require 'wordmove/wpcli'
21
+
20
22
  require 'wordmove/cli'
21
23
  require 'wordmove/doctor'
22
24
  require 'wordmove/doctor/movefile'
@@ -32,9 +34,7 @@ require 'wordmove/movefile'
32
34
  require 'wordmove/wordpress_directory'
33
35
  require 'wordmove/version'
34
36
  require 'wordmove/environments_list'
35
- require 'wordmove/wpcli'
36
37
 
37
- require 'wordmove/generators/movefile_adapter'
38
38
  require 'wordmove/generators/movefile'
39
39
 
40
40
  require 'wordmove/db_paths_config'
@@ -42,8 +42,8 @@ require 'wordmove/db_paths_config'
42
42
  require 'wordmove/actions/helpers'
43
43
  require 'wordmove/actions/ssh/helpers'
44
44
  require 'wordmove/actions/ftp/helpers'
45
- Dir[File.join(__dir__, 'wordmove/actions/**/*.rb')].sort.each { |file| require file }
46
- Dir[File.join(__dir__, 'wordmove/organizers/**/*.rb')].sort.each { |file| require file }
45
+ Dir[File.join(__dir__, 'wordmove/actions/**/*.rb')].each { |file| require file }
46
+ Dir[File.join(__dir__, 'wordmove/organizers/**/*.rb')].each { |file| require file }
47
47
 
48
48
  module Wordmove
49
49
  # Interactors' namespce. Interactors are called "Actions", following the LightService convention.
data/wordmove.gemspec CHANGED
@@ -36,12 +36,12 @@ Gem::Specification.new do |spec|
36
36
  spec.add_runtime_dependency 'dry-configurable', '~> 0.13.0'
37
37
  spec.add_runtime_dependency 'kwalify', '~> 0.7.2'
38
38
  spec.add_runtime_dependency 'light-service', '~> 0.17.0'
39
- spec.add_runtime_dependency 'photocopier', '~> 1.4', '>= 1.4.0'
39
+ spec.add_runtime_dependency 'photocopier', '~> 1.4', '>= 1.4.1'
40
40
  # spec.add_runtime_dependency 'thor', '~> 0.20.3'
41
41
  spec.add_runtime_dependency 'dry-cli', '~> 0.7.0'
42
42
  spec.add_runtime_dependency 'dry-files', '~> 0.1.0'
43
43
 
44
- spec.required_ruby_version = '>= 2.6.0' # rubocop:disable Gemspec/RequiredRubyVersion
44
+ spec.required_ruby_version = '>= 3.1.0'
45
45
 
46
46
  spec.add_development_dependency 'bundler', '~> 2.3.3'
47
47
  spec.add_development_dependency 'pry-byebug', '~> 3.1'
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: 6.0.0.alpha.5
4
+ version: 6.0.0.alpha.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefano Verna
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: exe
14
14
  cert_chain: []
15
- date: 2021-12-30 00:00:00.000000000 Z
15
+ date: 2022-01-04 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -107,7 +107,7 @@ dependencies:
107
107
  version: '1.4'
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: 1.4.0
110
+ version: 1.4.1
111
111
  type: :runtime
112
112
  prerelease: false
113
113
  version_requirements: !ruby/object:Gem::Requirement
@@ -117,7 +117,7 @@ dependencies:
117
117
  version: '1.4'
118
118
  - - ">="
119
119
  - !ruby/object:Gem::Version
120
- version: 1.4.0
120
+ version: 1.4.1
121
121
  - !ruby/object:Gem::Dependency
122
122
  name: dry-cli
123
123
  requirement: !ruby/object:Gem::Requirement
@@ -375,7 +375,6 @@ files:
375
375
  - lib/wordmove/exceptions.rb
376
376
  - lib/wordmove/generators/movefile.rb
377
377
  - lib/wordmove/generators/movefile.yml
378
- - lib/wordmove/generators/movefile_adapter.rb
379
378
  - lib/wordmove/guardian.rb
380
379
  - lib/wordmove/hook.rb
381
380
  - lib/wordmove/logger.rb
@@ -410,14 +409,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
410
409
  requirements:
411
410
  - - ">="
412
411
  - !ruby/object:Gem::Version
413
- version: 2.6.0
412
+ version: 3.1.0
414
413
  required_rubygems_version: !ruby/object:Gem::Requirement
415
414
  requirements:
416
415
  - - ">"
417
416
  - !ruby/object:Gem::Version
418
417
  version: 1.3.1
419
418
  requirements: []
420
- rubygems_version: 3.1.2
419
+ rubygems_version: 3.3.3
421
420
  signing_key:
422
421
  specification_version: 4
423
422
  summary: Wordmove, Capistrano for Wordpress
@@ -1,89 +0,0 @@
1
- module Wordmove
2
- module Generators
3
- module MovefileAdapter
4
- def wordpress_path
5
- File.expand_path(Dir.pwd)
6
- end
7
-
8
- def database
9
- DBConfigReader.config
10
- end
11
- end
12
-
13
- class DBConfigReader
14
- def self.config
15
- new.config
16
- end
17
-
18
- def config
19
- Struct.new(
20
- :name,
21
- :user,
22
- :password,
23
- :host,
24
- keyword_init: true
25
- ).new(database_config)
26
- end
27
-
28
- def database_config
29
- if wp_config_exists?
30
- WordpressDBConfig.config
31
- else
32
- DefaultDBConfig.config
33
- end
34
- end
35
-
36
- def wp_config_exists?
37
- File.exist?(WordpressDirectory.default_path_for(:wp_config))
38
- end
39
- end
40
-
41
- class DefaultDBConfig
42
- def self.config
43
- {
44
- name: 'database_name',
45
- user: 'user',
46
- password: 'password',
47
- host: '127.0.0.1'
48
- }
49
- end
50
- end
51
-
52
- class WordpressDBConfig
53
- def self.config
54
- new.config
55
- end
56
-
57
- def wp_config
58
- @wp_config ||= File.read(
59
- WordpressDirectory.default_path_for(:wp_config)
60
- ).encode('utf-8', invalid: :replace)
61
- end
62
-
63
- def wp_definitions
64
- {
65
- name: 'DB_NAME',
66
- user: 'DB_USER',
67
- password: 'DB_PASSWORD',
68
- host: 'DB_HOST'
69
- }
70
- end
71
-
72
- def wp_definition_regex(definition)
73
- /['"]#{definition}['"],\s*["'](?<value>.*)['"]/
74
- end
75
-
76
- def defaults
77
- DefaultDBConfig.config.clone
78
- end
79
-
80
- def config
81
- wp_definitions.each_with_object(defaults) do |(key, definition), result|
82
- wp_config.match(wp_definition_regex(definition)) do |match|
83
- result[key] = match[:value]
84
- end
85
- end
86
- end
87
- end
88
- end
89
- end