wordmove 5.1.0 → 6.0.0.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +37 -0
  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/README.mdown +1 -1
  8. data/Rakefile +4 -3
  9. data/exe/wordmove +2 -1
  10. data/lib/wordmove/actions/adapt_local_db.rb +95 -0
  11. data/lib/wordmove/actions/adapt_remote_db.rb +87 -0
  12. data/lib/wordmove/actions/backup_local_db.rb +54 -0
  13. data/lib/wordmove/actions/delete_local_file.rb +34 -0
  14. data/lib/wordmove/actions/delete_remote_file.rb +43 -0
  15. data/lib/wordmove/actions/filter_and_setup_tasks_to_run.rb +42 -0
  16. data/lib/wordmove/actions/ftp/backup_remote_db.rb +54 -0
  17. data/lib/wordmove/actions/ftp/cleanup_after_adapt.rb +70 -0
  18. data/lib/wordmove/actions/ftp/download_remote_db.rb +69 -0
  19. data/lib/wordmove/actions/ftp/get_directory.rb +67 -0
  20. data/lib/wordmove/actions/ftp/helpers.rb +91 -0
  21. data/lib/wordmove/actions/ftp/pull_wordpress.rb +56 -0
  22. data/lib/wordmove/actions/ftp/push_wordpress.rb +54 -0
  23. data/lib/wordmove/actions/ftp/put_and_import_dump_remotely.rb +74 -0
  24. data/lib/wordmove/actions/ftp/put_directory.rb +67 -0
  25. data/lib/wordmove/actions/get_file.rb +38 -0
  26. data/lib/wordmove/actions/helpers.rb +142 -0
  27. data/lib/wordmove/actions/put_file.rb +48 -0
  28. data/lib/wordmove/actions/run_after_pull_hook.rb +26 -0
  29. data/lib/wordmove/actions/run_after_push_hook.rb +26 -0
  30. data/lib/wordmove/actions/run_before_pull_hook.rb +26 -0
  31. data/lib/wordmove/actions/run_before_push_hook.rb +26 -0
  32. data/lib/wordmove/actions/run_local_command.rb +34 -0
  33. data/lib/wordmove/actions/setup_context_for_db.rb +79 -0
  34. data/lib/wordmove/actions/ssh/backup_remote_db.rb +49 -0
  35. data/lib/wordmove/actions/ssh/cleanup_after_adapt.rb +42 -0
  36. data/lib/wordmove/actions/ssh/download_remote_db.rb +76 -0
  37. data/lib/wordmove/actions/ssh/get_directory.rb +76 -0
  38. data/lib/wordmove/actions/ssh/helpers.rb +128 -0
  39. data/lib/wordmove/actions/ssh/pull_wordpress.rb +56 -0
  40. data/lib/wordmove/actions/ssh/push_wordpress.rb +54 -0
  41. data/lib/wordmove/actions/ssh/put_and_import_dump_remotely.rb +70 -0
  42. data/lib/wordmove/actions/ssh/put_directory.rb +76 -0
  43. data/lib/wordmove/actions/ssh/run_remote_command.rb +39 -0
  44. data/lib/wordmove/assets/dump.php.erb +6 -6
  45. data/lib/wordmove/assets/import.php.erb +7 -7
  46. data/lib/wordmove/assets/wordmove_schema_global.yml +2 -0
  47. data/lib/wordmove/assets/wordmove_schema_remote.yml +2 -2
  48. data/lib/wordmove/cli.rb +152 -91
  49. data/lib/wordmove/db_paths_config.rb +44 -0
  50. data/lib/wordmove/doctor/movefile.rb +8 -8
  51. data/lib/wordmove/doctor/mysql.rb +18 -15
  52. data/lib/wordmove/doctor/rsync.rb +2 -2
  53. data/lib/wordmove/doctor/ssh.rb +3 -3
  54. data/lib/wordmove/doctor/wpcli.rb +4 -4
  55. data/lib/wordmove/environments_list.rb +4 -4
  56. data/lib/wordmove/exceptions.rb +13 -0
  57. data/lib/wordmove/generators/movefile.rb +7 -5
  58. data/lib/wordmove/generators/movefile_adapter.rb +11 -5
  59. data/lib/wordmove/guardian.rb +5 -5
  60. data/lib/wordmove/hook.rb +15 -16
  61. data/lib/wordmove/logger.rb +11 -10
  62. data/lib/wordmove/movefile.rb +63 -59
  63. data/lib/wordmove/organizers/ftp/pull.rb +52 -0
  64. data/lib/wordmove/organizers/ftp/push.rb +53 -0
  65. data/lib/wordmove/organizers/ssh/pull.rb +52 -0
  66. data/lib/wordmove/organizers/ssh/push.rb +53 -0
  67. data/lib/wordmove/version.rb +1 -1
  68. data/lib/wordmove/wordpress_directory.rb +76 -8
  69. data/lib/wordmove/wpcli.rb +85 -0
  70. data/lib/wordmove.rb +33 -11
  71. data/wordmove.gemspec +37 -30
  72. metadata +143 -45
  73. data/.travis.yml +0 -20
  74. data/lib/wordmove/deployer/base.rb +0 -193
  75. data/lib/wordmove/deployer/ftp.rb +0 -160
  76. data/lib/wordmove/deployer/ssh/default_sql_adapter.rb +0 -47
  77. data/lib/wordmove/deployer/ssh/wpcli_sql_adapter.rb +0 -55
  78. data/lib/wordmove/deployer/ssh.rb +0 -169
  79. data/lib/wordmove/sql_adapter/default.rb +0 -68
  80. data/lib/wordmove/sql_adapter/wpcli.rb +0 -54
  81. data/lib/wordmove/wordpress_directory/path.rb +0 -11
@@ -0,0 +1,48 @@
1
+ module Wordmove
2
+ module Actions
3
+ # Upload a single file to the remote server.
4
+ #
5
+ # @note The remote server is already configured inside the Photocopier object
6
+ # @note This action is *not* meant to be organized, but as a standalone one.
7
+ class PutFile
8
+ extend LightService::Action
9
+ include Wordmove::Actions::Helpers
10
+
11
+ expects :photocopier,
12
+ :logger,
13
+ :command_args,
14
+ :cli_options
15
+
16
+ # @!method execute
17
+ # @param photocopier [Photocopier]
18
+ # @param logger [Wordmove::Logger]
19
+ # @param command_args ((String) local file path, (String) remote file path)
20
+ # @return [LightService::Context] Action's context
21
+ executed do |context|
22
+ command = 'put'
23
+
24
+ # First argument could be a file or a content string. Do not log if the latter
25
+ message = if File.exist?(context.command_args.first)
26
+ context.command_args.join(' ')
27
+ else
28
+ context.command_args.second
29
+ end
30
+
31
+ context.logger.task_step false, "#{command}: #{message}"
32
+
33
+ result = if simulate?(cli_options: context.cli_options)
34
+ true
35
+ else
36
+ context.photocopier.send(command, *context.command_args)
37
+ end
38
+
39
+ next context if result == true
40
+ # We can't trust the return from the fotocopier method when using FTP. Keep on
41
+ # and have faith.
42
+ next context if context.photocopier.is_a? Photocopier::FTP
43
+
44
+ context.fail! "Failed to upload file: #{context.command_args.first}"
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+ module Wordmove
2
+ module Actions
3
+ # Runs before push hooks by invoking the external service
4
+ # Wordmove::Hook
5
+ class RunAfterPullHook
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+
9
+ expects :movefile,
10
+ :cli_options
11
+
12
+ # @!method execute
13
+ # @param movefile [Wordmove::Movefile]
14
+ # @param cli_options [Hash]
15
+ # @return [LightService::Context] Action's context
16
+ executed do |context|
17
+ Wordmove::Hook.run(
18
+ :pull,
19
+ :after,
20
+ movefile: context.movefile,
21
+ simulate: simulate?(cli_options: context.cli_options)
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Wordmove
2
+ module Actions
3
+ # Runs after push hooks by invoking the external service
4
+ # Wordmove::Hook
5
+ class RunAfterPushHook
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+
9
+ expects :movefile,
10
+ :cli_options
11
+
12
+ # @!method execute
13
+ # @param movefile [Wordmove::Movefile]
14
+ # @param cli_options [Hash]
15
+ # @return [LightService::Context] Action's context
16
+ executed do |context|
17
+ Wordmove::Hook.run(
18
+ :push,
19
+ :after,
20
+ movefile: context.movefile,
21
+ simulate: simulate?(cli_options: context.cli_options)
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Wordmove
2
+ module Actions
3
+ # Runs before pull hooks by invoking the external service
4
+ # Wordmove::Hook
5
+ class RunBeforePullHook
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+
9
+ expects :movefile,
10
+ :cli_options
11
+
12
+ # @!method execute
13
+ # @param movefile [Wordmove::Movefile]
14
+ # @param cli_options [Hash]
15
+ # @return [LightService::Context] Action's context
16
+ executed do |context|
17
+ Wordmove::Hook.run(
18
+ :pull,
19
+ :before,
20
+ movefile: context.movefile,
21
+ simulate: simulate?(cli_options: context.cli_options)
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Wordmove
2
+ module Actions
3
+ # Runs before push hooks by invoking the external service
4
+ # Wordmove::Hook
5
+ class RunBeforePushHook
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+
9
+ expects :movefile,
10
+ :cli_options
11
+
12
+ # @!method execute
13
+ # @param movefile [Wordmove::Movefile]
14
+ # @param cli_options [Hash]
15
+ # @return [LightService::Context] Action's context
16
+ executed do |context|
17
+ Wordmove::Hook.run(
18
+ :push,
19
+ :before,
20
+ movefile: context.movefile,
21
+ simulate: simulate?(cli_options: context.cli_options)
22
+ )
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ require 'English'
2
+
3
+ module Wordmove
4
+ module Actions
5
+ # Run a command on the local system.
6
+ # Command won't be run if +--simulate+ flag is present on CLI.
7
+ # @note This action is *not* meant to be organized, but as a standalone one.
8
+ class RunLocalCommand
9
+ extend LightService::Action
10
+ include Wordmove::Actions::Helpers
11
+
12
+ expects :command,
13
+ :cli_options,
14
+ :logger
15
+
16
+ # @!method execute
17
+ # @param command [String] The command to run
18
+ # @param cli_options [Hash]
19
+ # @param logger [Wordmove::Logger]
20
+ # @return [LightService::Context] Action's context
21
+ executed do |context|
22
+ context.logger.task_step true, context.command
23
+
24
+ next context if simulate?(cli_options: context.cli_options)
25
+
26
+ begin
27
+ system(context.command, exception: true)
28
+ rescue RuntimeError, SystemExit => e
29
+ context.fail!("Local command status reports an error: #{e.message}")
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,79 @@
1
+ module Wordmove
2
+ module Actions
3
+ class SetupContextForDb
4
+ extend ::LightService::Action
5
+ include Wordmove::Actions::Helpers
6
+ include Wordmove::Actions::Ftp::Helpers
7
+ include WordpressDirectory::LocalHelperMethods
8
+ include WordpressDirectory::RemoteHelperMethods
9
+
10
+ expects :cli_options,
11
+ :local_options,
12
+ :remote_options,
13
+ :logger,
14
+ :movefile,
15
+ :database_task
16
+ promises :db_paths
17
+
18
+ executed do |context| # rubocop:disable Metrics/BlockLength
19
+ if context.database_task == false
20
+ context.skip_remaining!
21
+ context.db_paths = false
22
+ next context
23
+ end
24
+
25
+ next context if simulate?(cli_options: context.cli_options)
26
+
27
+ content_dir = local_wp_content_dir(local_options: context.local_options)
28
+
29
+ token = remote_php_scripts_token
30
+
31
+ DbPathsConfig.local.path = content_dir.path('dump.sql')
32
+ DbPathsConfig.local.gzipped_path = "#{DbPathsConfig.local.path}.gz"
33
+ DbPathsConfig.remote.path = remote_wp_content_dir(
34
+ remote_options: context.remote_options
35
+ ).path('dump.sql')
36
+ DbPathsConfig.remote.gzipped_path = "#{DbPathsConfig.remote.path}.gz"
37
+ DbPathsConfig.local.adapted_path = content_dir.path('search_replace_dump.sql')
38
+ DbPathsConfig.local.gzipped_adapted_path = "#{DbPathsConfig.local.adapted_path}.gz"
39
+ DbPathsConfig.backup.local.path = content_dir.path("local-backup-#{Time.now.to_i}.sql")
40
+ DbPathsConfig.backup.local.gzipped_path = "#{DbPathsConfig.backup.local.path}.gz"
41
+ DbPathsConfig.backup.remote.path =
42
+ content_dir.path("#{context.movefile.environment}-backup-#{Time.now.to_i}.sql")
43
+ DbPathsConfig.backup.remote.gzipped_path = "#{DbPathsConfig.backup.remote.path}.gz"
44
+
45
+ DbPathsConfig.ftp.remote.dump_script_path = remote_wp_content_dir(
46
+ remote_options: context.remote_options
47
+ ).path('dump.php')
48
+ DbPathsConfig.ftp.remote.dumped_path = remote_wp_content_dir(
49
+ remote_options: context.remote_options
50
+ ).path('dump.mysql')
51
+ DbPathsConfig.ftp.remote.dump_script_url = remote_wp_content_dir(
52
+ remote_options: context.remote_options
53
+ ).url('dump.php')
54
+ DbPathsConfig.ftp.remote.import_script_path = remote_wp_content_dir(
55
+ remote_options: context.remote_options
56
+ ).path('import.php')
57
+ DbPathsConfig.ftp.remote.import_script_url = remote_wp_content_dir(
58
+ remote_options: context.remote_options
59
+ ).url('import.php')
60
+ DbPathsConfig.ftp.local.generated_dump_script_path = generate_dump_script(
61
+ remote_db_options: context.remote_options[:database],
62
+ token: token
63
+ )
64
+ DbPathsConfig.ftp.local.generated_import_script_path = generate_import_script(
65
+ remote_db_options: context.remote_options[:database],
66
+ token: token
67
+ )
68
+ DbPathsConfig.ftp.local.temp_path = local_wp_content_dir(
69
+ local_options: context.local_options
70
+ ).path('log.html')
71
+ # I know this is not a path, but it's used to generate
72
+ # a URL to dump the DB, so it's somewhat in context
73
+ DbPathsConfig.ftp.token = token
74
+
75
+ context.db_paths = DbPathsConfig
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,49 @@
1
+ module Wordmove
2
+ module Actions
3
+ module Ssh
4
+ # Bakups an alrady downloaded remote dump
5
+ class BackupRemoteDb
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+
9
+ expects :cli_options,
10
+ :logger,
11
+ :db_paths
12
+
13
+ # @!method execute
14
+ # @param cli_options [Hash] Command line options (with symbolized keys)
15
+ # @param logger [Wordmove::Logger]
16
+ # @param db_paths [BbPathsConfig] Configuration object for database
17
+ # @!scope class
18
+ # @return [LightService::Context] Action's context
19
+ executed do |context|
20
+ context.logger.task 'Backup remote DB'
21
+
22
+ if simulate?(cli_options: context.cli_options)
23
+ context.logger.info 'A backup of the remote DB would have been saved into ' \
24
+ "#{context.db_paths.backup.remote.gzipped_path}, " \
25
+ 'but you\'re simulating'
26
+ next context
27
+ end
28
+
29
+ # Most of the expectations are needed to be proxied to `DownloadRemoteDb`
30
+ # Wordmove::Actions::Ssh::DownloadRemoteDb.execute(context)
31
+ # DownloadRemoteDB will save the file in `db_paths.local.gzipped_path`
32
+
33
+ begin
34
+ FileUtils.mv(
35
+ context.db_paths.local.gzipped_path,
36
+ context.db_paths.backup.remote.gzipped_path
37
+ )
38
+
39
+ context.logger.success(
40
+ "Backup saved at #{context.db_paths.backup.remote.gzipped_path}"
41
+ )
42
+ rescue Errno::ENOENT => e
43
+ context.fail_and_return!("Remote DB backup failed with: #{e.message}. Aborting.")
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ module Wordmove
2
+ module Actions
3
+ module Ssh
4
+ # Cleanup file created during DB push/pull operations
5
+ class CleanupAfterAdapt
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+
9
+ expects :db_paths,
10
+ :cli_options,
11
+ :logger
12
+
13
+ # @!method execute
14
+ # @param db_paths [BbPathsConfig] Configuration object for database
15
+ # @param cli_options [Hash] Command line options (with symbolized keys)
16
+ # @param logger [Wordmove::Logger]
17
+ # @!scope class
18
+ # @return [LightService::Context] Action's context
19
+ executed do |context|
20
+ context.logger.task 'Cleanup'
21
+
22
+ if simulate?(cli_options: context.cli_options)
23
+ context.logger.info 'No cleanup during simulation'
24
+ next context
25
+ end
26
+
27
+ Wordmove::Actions::DeleteLocalFile.execute(
28
+ logger: context.logger,
29
+ cli_options: context.cli_options,
30
+ file_path: context.db_paths.local.path
31
+ )
32
+
33
+ Wordmove::Actions::DeleteLocalFile.execute(
34
+ cli_options: context.cli_options,
35
+ logger: context.logger,
36
+ file_path: context.db_paths.local.gzipped_adapted_path
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,76 @@
1
+ module Wordmove
2
+ module Actions
3
+ module Ssh
4
+ # Downloads the remote DB over SSH protocol
5
+ class DownloadRemoteDb
6
+ extend ::LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+ include WordpressDirectory::LocalHelperMethods
9
+ include WordpressDirectory::RemoteHelperMethods
10
+
11
+ expects :remote_options,
12
+ :cli_options,
13
+ :logger,
14
+ :photocopier,
15
+ :db_paths
16
+
17
+ # @!method execute
18
+ # @param remote_options [Hash] Remote host options fetched from
19
+ # movefile (with symbolized keys)
20
+ # @param cli_options [Hash] Command line options (with symbolized keys)
21
+ # @param logger [Wordmove::Logger]
22
+ # @param photocopier [Photocopier::SSH]
23
+ # @param db_paths [BbPathsConfig] Configuration object for database
24
+ # @!scope class
25
+ # @return [LightService::Context] Action's context
26
+ executed do |context| # rubocop:disable Metrics/BlockLength
27
+ context.logger.task 'Download remote DB'
28
+
29
+ next context if simulate?(cli_options: context.cli_options)
30
+
31
+ result = Wordmove::Actions::Ssh::RunRemoteCommand.execute(
32
+ cli_options: context.cli_options,
33
+ photocopier: context.photocopier,
34
+ logger: context.logger,
35
+ command: mysql_dump_command(
36
+ env_db_options: context.remote_options[:database],
37
+ save_to_path: context.db_paths.remote.path
38
+ )
39
+ )
40
+ context.fail_and_return!(result.message) if result.failure?
41
+
42
+ result = Wordmove::Actions::Ssh::RunRemoteCommand.execute(
43
+ cli_options: context.cli_options,
44
+ photocopier: context.photocopier,
45
+ logger: context.logger,
46
+ command: compress_command(file_path: context.db_paths.remote.path)
47
+ )
48
+ context.fail_and_return!(result.message) if result.failure?
49
+
50
+ result = Wordmove::Actions::GetFile.execute(
51
+ photocopier: context.photocopier,
52
+ logger: context.logger,
53
+ cli_options: context.cli_options,
54
+ command_args: [
55
+ context.db_paths.remote.gzipped_path,
56
+ context.db_paths.local.gzipped_path
57
+ ]
58
+ )
59
+ context.fail_and_return!(result.message) if result.failure?
60
+
61
+ result = Wordmove::Actions::DeleteRemoteFile.execute(
62
+ photocopier: context.photocopier,
63
+ logger: context.logger,
64
+ cli_options: context.cli_options,
65
+ remote_file: context.db_paths.remote.gzipped_path
66
+ )
67
+ context.fail_and_return!(result.message) if result.failure?
68
+
69
+ context.logger.success(
70
+ "Remote DB dump downloaded in #{context.db_paths.local.gzipped_path}"
71
+ )
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,76 @@
1
+ module Wordmove
2
+ module Actions
3
+ module Ssh
4
+ # Syncs a whole directory over SSH protocol from the remote server to local host
5
+ class GetDirectory
6
+ extend LightService::Action
7
+ include Wordmove::Actions::Helpers
8
+ include Wordmove::Actions::Ssh::Helpers
9
+ include WordpressDirectory::RemoteHelperMethods
10
+
11
+ # :folder_task is expected to be one symbol from Wordmove::CLI.wordpress_options array
12
+ expects :logger,
13
+ :local_options,
14
+ :remote_options,
15
+ :cli_options,
16
+ :photocopier,
17
+ :folder_task
18
+
19
+ # @!method execute
20
+ # @param logger [Wordmove::Logger]
21
+ # @param local_options [Hash] Local host options fetched from
22
+ # movefile (with symbolized keys)
23
+ # @param remote_options [Hash] Remote host options fetched from
24
+ # movefile (with symbolized keys)
25
+ # @param cli_options [Hash] Command line options (with symbolized keys)
26
+ # @param photocopier [Photocopier::SSH]
27
+ # @param folder_task [Symbol] Symbolazied folder name
28
+ # @!scope class
29
+ # @return [LightService::Context] Action's context
30
+ executed do |context|
31
+ context.logger.task "Pulling #{context.folder_task}"
32
+
33
+ next context if simulate?(cli_options: context.cli_options)
34
+
35
+ command = 'get_directory'
36
+ # For this action `local_path` and `remote_path` will always be
37
+ # `:wordpress_path`; specific folder for `context.folder_task` will be included by
38
+ # `pull_include_paths`
39
+ local_path = context.local_options[:wordpress_path]
40
+ remote_path = context.remote_options[:wordpress_path]
41
+
42
+ # This action can generate `command_args` by itself,
43
+ # but it gives the context the chance to ovveride it.
44
+ # By the way this variable is not `expects`ed.
45
+ # Note that we do not use the second argument to `fetch`
46
+ # to express a default value, because it would be greedly interpreted
47
+ # but if `command_args` is already defined by context, then it's
48
+ # possible that `"remote_#{context.folder_task}_dir"` could
49
+ # not be defined.
50
+ command_args = context.fetch(:command_args) || [
51
+ remote_path,
52
+ local_path,
53
+ pull_exclude_paths(
54
+ remote_task_dir: send(
55
+ "remote_#{context.folder_task}_dir",
56
+ remote_options: context.remote_options
57
+ ),
58
+ paths_to_exclude: paths_to_exclude(remote_options: context.remote_options)
59
+ ),
60
+ pull_include_paths(remote_task_dir: send(
61
+ "remote_#{context.folder_task}_dir",
62
+ remote_options: context.remote_options
63
+ ))
64
+ ]
65
+
66
+ context.logger.task_step false, "#{command}: #{command_args.join(' ')}"
67
+ result = context.photocopier.send(command, *command_args)
68
+
69
+ next context if result == true
70
+
71
+ context.fail!("Failed to push #{context.folder_task}")
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,128 @@
1
+ require 'pathname'
2
+
3
+ # rubocop:disable Metrics/BlockLength
4
+ module Wordmove
5
+ module Actions
6
+ module Ssh
7
+ module Helpers
8
+ extend ActiveSupport::Concern
9
+
10
+ class_methods do
11
+ #
12
+ # Utility method to retrieve and augment ssh options from the superset of remote options.
13
+ # This is useful most because it appends +--dy-run+ rsync's flag to ssh options based
14
+ # on +--simulate+ flag presence
15
+ #
16
+ # @param [Hash] remote_options Remote host options fetcehd from movefile
17
+ # @param [Bool] simulate Tell the moethod if you're in a simulated operation
18
+ #
19
+ # @return [Hash] Ssh options
20
+ #
21
+ def ssh_options(remote_options:, simulate: false)
22
+ ssh_options = remote_options[:ssh]
23
+
24
+ if simulate == true && ssh_options[:rsync_options]
25
+ ssh_options[:rsync_options].concat(' --dry-run')
26
+ elsif simulate == true
27
+ ssh_options[:rsync_options] = '--dry-run'
28
+ end
29
+
30
+ ssh_options
31
+ end
32
+
33
+ #
34
+ # Given the directory you're pushing/pulling, generates an array of path to be included
35
+ # by rsync while pushing. Note that by design include paths are always required but are
36
+ # only programmatically deduced and never user configured.
37
+ #
38
+ # @note The business logic behind how these paths are produced should be deepened
39
+ #
40
+ # @param [WordpressDirectory] local_task_dir An object representing a wordpress folder
41
+ #
42
+ # @return [Array<String>] The array of path to be included by rsync
43
+ #
44
+ def push_include_paths(local_task_dir:)
45
+ Pathname.new(local_task_dir.relative_path)
46
+ .ascend
47
+ .each_with_object([]) do |directory, array|
48
+ path = directory.to_path
49
+ path.prepend('/') unless path.match? %r{^/}
50
+ path.concat('/') unless path.match? %r{/$}
51
+ array << path
52
+ end
53
+ end
54
+
55
+ #
56
+ # Given the directory you're pushing/pulling and the user configured exclude list,
57
+ # generates an array of path to be excluded
58
+ # by rsync while pushing. Note that by design exclude some paths are always required
59
+ # even when the user does not confiure any exclusion.
60
+ #
61
+ # @note The business logic behind how these paths are produced should be deepened
62
+ #
63
+ # @param [WordpressDirectory] local_task_dir An object representing a wordpress folder
64
+ # @param [Array<String>] pats_to_exclude An array of paths
65
+ #
66
+ # @return [Array<String>] The array of path to be included by rsync
67
+ #
68
+ def push_exclude_paths(local_task_dir:, paths_to_exclude:)
69
+ Pathname.new(local_task_dir.relative_path)
70
+ .dirname
71
+ .ascend
72
+ .each_with_object([]) do |directory, array|
73
+ path = directory.to_path
74
+ path.prepend('/') unless path.match? %r{^/}
75
+ path.concat('/') unless path.match? %r{/$}
76
+ path.concat('*')
77
+ array << path
78
+ end
79
+ .concat(paths_to_exclude)
80
+ .concat(['/*'])
81
+ end
82
+
83
+ #
84
+ # Same as Wordmove::Actions::Ssh::Helpers.push_include_path but for pull actions
85
+ #
86
+ # @param [WordpressDirectory] local_task_dir An object representing a wordpress folder
87
+ #
88
+ # @return [Array<String>] An array of paths
89
+ #
90
+ def pull_include_paths(remote_task_dir:)
91
+ Pathname.new(remote_task_dir.relative_path)
92
+ .ascend
93
+ .each_with_object([]) do |directory, array|
94
+ path = directory.to_path
95
+ path.prepend('/') unless path.match? %r{^/}
96
+ path.concat('/') unless path.match? %r{/$}
97
+ array << path
98
+ end
99
+ end
100
+
101
+ #
102
+ # Same as Wordmove::Actions::Ssh::Helpers.push_exclude_path but for pull actions
103
+ #
104
+ # @param [WordpressDirectory] local_task_dir An object representing a wordpress folder
105
+ # @param [Array<String>] paths_to_exclude User configured array of paths to exclude
106
+ #
107
+ # @return [Array<String>] Array of paths to be excluded
108
+ #
109
+ def pull_exclude_paths(remote_task_dir:, paths_to_exclude:)
110
+ Pathname.new(remote_task_dir.relative_path)
111
+ .dirname
112
+ .ascend
113
+ .each_with_object([]) do |directory, array|
114
+ path = directory.to_path
115
+ path.prepend('/') unless path.match? %r{^/}
116
+ path.concat('/') unless path.match? %r{/$}
117
+ path.concat('*')
118
+ array << path
119
+ end
120
+ .concat(paths_to_exclude)
121
+ .concat(['/*'])
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ # rubocop:enable Metrics/BlockLength