wordmove 2.3.1 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b44325c0d09d56d3a59080721d52ef65d301116
4
- data.tar.gz: 5fbb645e7df0d2ec0b66773c0c52c5523ec25131
3
+ metadata.gz: 2b51293554be6d33b634aa494f0db0e88ea2326a
4
+ data.tar.gz: 2fcf92909bd0a02c28f2a2f641be9f0e03c585be
5
5
  SHA512:
6
- metadata.gz: 8112d61e266fb7b83227463dcd70e6160a006bbfa19cbf1405502783a7a0ddcb4ee8b4d8a28df9ee2d88cd9f93c7bdc962926e2da1296444fb7dff83b770f464
7
- data.tar.gz: 0f07783014805087b720a9b11b48fc7fda2a79e3b6ab0f8eca31ad75ac3d82f7b6d07c9434f393ab94b4b8924c16bfc38e324e3e550625afa09f24981a4bcec6
6
+ metadata.gz: 9a9d599400d09b8b0424eb1b88c01e1f68c80a4f280c304d6522d9e275aaf2ad6716eef0dd0c679a490f05490bd6e2b2daf6b09089ee02fab88445b2de4cb6a9
7
+ data.tar.gz: 450caed451d3c875f977a6aad2407e88d5cd895a8b7c3916a8e8d744f4a9cd0da2ddd775a606e96f0e49f705bdd57d5d76a5a4942bd0e82576781bf57e2bd394
data/README.mdown CHANGED
@@ -6,11 +6,14 @@ Wordmove is a gem that lets you automatically mirror local Wordpress
6
6
  installations and DB data back and forth from your local development machine to
7
7
  the remote server.
8
8
 
9
- **SSH** connections are fully supported, while [FTP support is planned to be discontinued](https://github.com/welaika/wordmove/wiki/FTP-support-disclaimer) when new features will be introduced.
9
+ Wordmove has also a neat hook system which enables you to run arbitrary commands
10
+ before and after push/pull actions. Local and remote commands are both supported, but remote
11
+ ones will be run only if using SSH protocol. Read the [dedicated wiki page](https://github.com/welaika/wordmove/wiki/Hooks) for more info.
10
12
 
11
- Think of it like Capistrano for Wordpress, complete with push/pull capabilities.
13
+ [FTP support has been discontinued](https://github.com/welaika/wordmove/wiki/FTP-support-disclaimer), thus most recent features won't work,
14
+ while base functionalities are granted.
12
15
 
13
- [![Build Status](https://travis-ci.org/welaika/wordmove.png?branch=master)](https://travis-ci.org/welaika/wordmove)
16
+ [![Build Status](https://travis-ci.org/welaika/wordmove.svg?branch=master)](https://travis-ci.org/welaika/wordmove)
14
17
  [![Slack channel](https://img.shields.io/badge/Slack-WP--Hub-blue.svg)](https://wphub-auto-invitation.herokuapp.com/)
15
18
  [![Gem Version](https://badge.fury.io/rb/wordmove.svg)](https://rubygems.org/gems/wordmove)
16
19
 
@@ -18,11 +21,11 @@ Think of it like Capistrano for Wordpress, complete with push/pull capabilities.
18
21
 
19
22
  That's easy:
20
23
 
21
- ```
22
- gem install wordmove
23
- ```
24
+ gem install wordmove
24
25
 
26
+ And to update:
25
27
 
28
+ gem update wordmove
26
29
 
27
30
  ## Peer dependencies
28
31
 
@@ -32,7 +35,7 @@ Wordmove just acts as automation glue bewtween tools you already have and love.
32
35
  | ------- | ---------------------------- | ------------------------------- |
33
36
  | rsync | Push and pull files and dirs | Yes for SSH connections |
34
37
  | mysql | Import and dump database | Yes |
35
- | wp-cli | DB adapt | Nope: experimental and optional |
38
+ | wp-cli | DB adapt | Nope (but soon will be) |
36
39
  | lftp | all | Yes, for FTP connections |
37
40
  | ssh | all | Yes, for SSH connections |
38
41
 
@@ -61,7 +64,7 @@ Move inside the Wordpress folder and use `wordmove init` to generate a new `move
61
64
 
62
65
  ## movefile.yml
63
66
 
64
- You can configure Wordmove creating a `movefile.yml`. That's just a YAML file with local and remote host infos:
67
+ You can configure Wordmove creating a `movefile.yml`. That's a YAML file with local and remote host(s) infos:
65
68
 
66
69
  ```yaml
67
70
  global:
@@ -113,11 +116,49 @@ production:
113
116
  ssh:
114
117
  host: host
115
118
  user: user
119
+
120
+ # hooks: # Remote hooks won't work with FTP
121
+ # push:
122
+ # before:
123
+ # local:
124
+ # - 'echo "Do something locally before push"'
125
+ # remote:
126
+ # - 'echo "Do something remotely before push"'
127
+ # after:
128
+ # local:
129
+ # - 'echo "Do something locally after push"'
130
+ # remote:
131
+ # - 'echo "Do something remotely after push"'
132
+ # pull:
133
+ # before:
134
+ # local:
135
+ # - 'echo "Do something locally before pull"'
136
+ # remote:
137
+ # - 'echo "Do something remotely before pull"'
138
+ # after:
139
+ # local:
140
+ # - 'echo "Do something locally after pull"'
141
+ # remote:
142
+ # - 'echo "Do something remotely after pull"'
116
143
  ```
117
144
 
118
145
  **We warmly recommend to read the wiki article [Multiple environments explained
119
146
  ](https://github.com/welaika/wordmove/wiki/Multiple-environments-explained) if you need multi-stage support, and the wiki article [Movefile configurations explained](https://github.com/welaika/wordmove/wiki/movefile.yml-configurations-explained) to understand about the supported configurations.**
120
147
 
148
+ ## Multistage
149
+
150
+ You can define multiple environments in your `movefile.yml`, such as production, staging, etc.
151
+ Use `-e` with `pull` or `push` to run the command on the specified environment.
152
+
153
+ For example:
154
+
155
+ wordmove push -e staging -d
156
+
157
+ will push your local database to the staging environment only.
158
+
159
+ We warmly **recommend** to read the wiki article: [Multiple environments explained
160
+ ](https://github.com/welaika/wordmove/wiki/Multiple-environments-explained)
161
+
121
162
  ## Supports
122
163
 
123
164
  ### OS
@@ -141,21 +182,17 @@ See the [Windows (un)support disclaimer](https://github.com/welaika/wordmove/wik
141
182
 
142
183
  FTP support is [planned to be discontinued](https://github.com/welaika/wordmove/wiki/FTP-support-disclaimer) at some point of future development.
143
184
 
144
- ### Multistage
185
+ ## Notes
145
186
 
146
- You can define multiple environments in your `movefile.yml`, such as production, staging, etc.
147
- Use `-e` with `pull` or `push` to run the command on the specified environment.
187
+ ### Mirroring
148
188
 
149
- For example:
150
- ```
151
- wordmove push -e staging -d
152
- ```
153
- will push your local database to the staging environment only.
154
-
155
- We warmly **recommend** to read the wiki article: [Multiple environments explained
156
- ](https://github.com/welaika/wordmove/wiki/Multiple-environments-explained)
189
+ Push and pull actions on files will perform a **mirror** operation. Please, keep
190
+ in mind that to mirror means to transfer new/updated files **and remove files**
191
+ from destination if not present in source.
157
192
 
158
- ## Notes
193
+ This means that if you have files/directories on your remotes which you must
194
+ preserve, you **must exclude those in your movefile.yml**, or they will be
195
+ deleted.
159
196
 
160
197
  ### How the heck you are able to sync the DB via FTP?
161
198
 
data/lib/wordmove.rb CHANGED
@@ -22,6 +22,7 @@ require 'wordmove/doctor/mysql'
22
22
  require 'wordmove/doctor/wpcli'
23
23
  require 'wordmove/doctor/rsync'
24
24
  require 'wordmove/doctor/ssh'
25
+ require 'wordmove/hook'
25
26
  require 'wordmove/logger'
26
27
  require 'wordmove/movefile'
27
28
  require 'wordmove/sql_adapter/default'
@@ -76,3 +76,56 @@ mapping:
76
76
  passive:
77
77
  type: bool
78
78
  scheme:
79
+ hooks:
80
+ type: map
81
+ mapping:
82
+ push:
83
+ type: map
84
+ mapping:
85
+ before:
86
+ type: map
87
+ mapping:
88
+ local:
89
+ type: seq
90
+ sequence:
91
+ - type: str
92
+ remote:
93
+ type: seq
94
+ sequence:
95
+ - type: str
96
+ after:
97
+ type: map
98
+ mapping:
99
+ local:
100
+ type: seq
101
+ sequence:
102
+ - type: str
103
+ remote:
104
+ type: seq
105
+ sequence:
106
+ - type: str
107
+ pull:
108
+ type: map
109
+ mapping:
110
+ before:
111
+ type: map
112
+ mapping:
113
+ local:
114
+ type: seq
115
+ sequence:
116
+ - type: str
117
+ remote:
118
+ type: seq
119
+ sequence:
120
+ - type: str
121
+ after:
122
+ type: map
123
+ mapping:
124
+ local:
125
+ type: seq
126
+ sequence:
127
+ - type: str
128
+ remote:
129
+ type: seq
130
+ sequence:
131
+ - type: str
data/lib/wordmove/cli.rb CHANGED
@@ -65,14 +65,19 @@ module Wordmove
65
65
  def pull
66
66
  ensure_wordpress_options_presence!(options)
67
67
  begin
68
- deployer = Wordmove::Deployer::Base.deployer_for(options)
68
+ deployer = Wordmove::Deployer::Base.deployer_for(options.deep_symbolize_keys)
69
69
  rescue MovefileNotFound => e
70
70
  logger.error(e.message)
71
71
  exit 1
72
72
  end
73
+
74
+ Wordmove::Hook.run(:pull, :before, options)
75
+
73
76
  handle_options(options) do |task|
74
77
  deployer.send("pull_#{task}")
75
78
  end
79
+
80
+ Wordmove::Hook.run(:pull, :after, options)
76
81
  end
77
82
 
78
83
  desc "push", "Pushes WP data from local machine to remote host"
@@ -87,9 +92,14 @@ module Wordmove
87
92
  logger.error(e.message)
88
93
  exit 1
89
94
  end
95
+
96
+ Wordmove::Hook.run(:push, :before, options)
97
+
90
98
  handle_options(options) do |task|
91
99
  deployer.send("push_#{task}")
92
100
  end
101
+
102
+ Wordmove::Hook.run(:push, :after, options)
93
103
  end
94
104
  end
95
105
  end
@@ -7,17 +7,9 @@ module Wordmove
7
7
 
8
8
  class << self
9
9
  def deployer_for(cli_options)
10
- options = fetch_movefile(cli_options[:config])
11
- available_enviroments = extract_available_envs(options)
12
- options.merge!(cli_options).deep_symbolize_keys!
13
-
14
- if available_enviroments.size > 1 && options[:environment].nil?
15
- raise(
16
- UndefinedEnvironment,
17
- "You need to specify an environment with --environment parameter"
18
- )
19
- end
20
- environment = (options[:environment] || available_enviroments.first).to_sym
10
+ movefile = Wordmove::Movefile.new(cli_options[:config])
11
+ options = movefile.fetch.merge! cli_options
12
+ environment = movefile.environment(cli_options)
21
13
 
22
14
  return FTP.new(environment, options) if options[environment][:ftp]
23
15
 
@@ -32,15 +24,6 @@ module Wordmove
32
24
  raise NoAdapterFound, "No valid adapter found."
33
25
  end
34
26
 
35
- def extract_available_envs(options)
36
- options.keys.map(&:to_sym) - %i[local global]
37
- end
38
-
39
- def fetch_movefile(name = nil, start_dir = current_dir)
40
- movefile = Wordmove::Movefile.new
41
- movefile.fetch name, start_dir
42
- end
43
-
44
27
  def current_dir
45
28
  '.'
46
29
  end
@@ -10,6 +10,8 @@ module Wordmove
10
10
  def push_db
11
11
  super
12
12
 
13
+ return true if simulate?
14
+
13
15
  local_dump_path = local_wp_content_dir.path("dump.sql")
14
16
  remote_dump_path = remote_wp_content_dir.path("dump.sql")
15
17
  local_backup_path = local_wp_content_dir.path("remote-backup-#{Time.now.to_i}.sql")
@@ -32,6 +34,9 @@ module Wordmove
32
34
 
33
35
  def pull_db
34
36
  super
37
+
38
+ return true if simulate?
39
+
35
40
  local_dump_path = local_wp_content_dir.path("dump.sql")
36
41
  local_backup_path = local_wp_content_dir.path("local-backup-#{Time.now.to_i}.sql")
37
42
 
@@ -9,6 +9,13 @@ module Wordmove
9
9
  def initialize(environment, options)
10
10
  super
11
11
  ssh_options = remote_options[:ssh]
12
+
13
+ if simulate? && ssh_options[:rsync_options]
14
+ ssh_options[:rsync_options].concat(" --dry-run")
15
+ elsif simulate?
16
+ ssh_options[:rsync_options] = "--dry-run"
17
+ end
18
+
12
19
  @copier = Photocopier::SSH.new(ssh_options).tap { |c| c.logger = logger }
13
20
 
14
21
  @local_dump_path = local_wp_content_dir.path("dump.sql")
@@ -23,6 +30,8 @@ module Wordmove
23
30
  def push_db
24
31
  super
25
32
 
33
+ return true if simulate?
34
+
26
35
  backup_remote_db!
27
36
  adapt_local_db!
28
37
  after_push_cleanup!
@@ -31,15 +40,20 @@ module Wordmove
31
40
  def pull_db
32
41
  super
33
42
 
43
+ return true if simulate?
44
+
34
45
  backup_local_db!
35
46
  adapt_remote_db!
36
47
  after_pull_cleanup!
37
48
  end
38
49
 
50
+ # In following commands, we do not guard for simulate?
51
+ # because it is handled through --dry-run rsync option.
52
+ # @see initialize
39
53
  %w[get put get_directory put_directory delete].each do |command|
40
54
  define_method "remote_#{command}" do |*args|
41
55
  logger.task_step false, "#{command}: #{args.join(' ')}"
42
- @copier.send(command, *args) unless simulate?
56
+ @copier.send(command, *args)
43
57
  end
44
58
  end
45
59
 
@@ -1,14 +1,14 @@
1
1
  module Wordmove
2
2
  class Doctor
3
3
  class Movefile
4
- MANDATORY_SECTIONS = %w[global local].freeze
4
+ MANDATORY_SECTIONS = %i[global local].freeze
5
5
  attr_reader :movefile, :contents, :root_keys
6
6
 
7
7
  def initialize(name = nil, dir = '.')
8
- @movefile = Wordmove::Movefile.new
8
+ @movefile = Wordmove::Movefile.new(name, dir)
9
9
 
10
10
  begin
11
- @contents = movefile.fetch(name, dir)
11
+ @contents = movefile.fetch
12
12
  @root_keys = contents.keys
13
13
  rescue Psych::SyntaxError
14
14
  movefile.logger.error "Your movefile is not parsable due to a syntax error"\
@@ -37,7 +37,7 @@ module Wordmove
37
37
  def validate_section(key)
38
38
  validator = validator_for(key)
39
39
 
40
- errors = validator.validate(contents[key])
40
+ errors = validator.validate(contents[key].deep_stringify_keys)
41
41
 
42
42
  if errors&.empty?
43
43
  movefile.logger.success "Formal validation passed"
@@ -67,7 +67,7 @@ module Wordmove
67
67
  end
68
68
 
69
69
  def validate_protocol_presence(keys)
70
- return true if keys.include?('ssh') || keys.include?('ftp')
70
+ return true if keys.include?(:ssh) || keys.include?(:ftp)
71
71
 
72
72
  movefile.logger.error "This remote has not ssh nor ftp protocol defined"
73
73
 
@@ -6,7 +6,7 @@ module Wordmove
6
6
  def initialize(movefile_name = nil, movefile_dir = '.')
7
7
  @logger = Logger.new(STDOUT).tap { |l| l.level = Logger::INFO }
8
8
  begin
9
- @config = Wordmove::Movefile.new.fetch(movefile_name, movefile_dir)["local"]["database"]
9
+ @config = Wordmove::Movefile.new(movefile_name, movefile_dir).fetch[:local][:database]
10
10
  rescue Psych::SyntaxError
11
11
  return
12
12
  end
@@ -24,19 +24,20 @@ production:
24
24
  # mysqldump_options: --max_allowed_packet=1G # Only available if using SSH
25
25
 
26
26
  exclude:
27
- - .git/
28
- - .gitignore
29
- - .sass-cache/
30
- - node_modules/
31
- - bin/
32
- - tmp/*
33
- - Gemfile*
34
- - Movefile
35
- - movefile
36
- - movefile.yml
37
- - movefile.yaml
38
- - wp-config.php
39
- - wp-content/*.sql.gz
27
+ - '.git/'
28
+ - '.gitignore'
29
+ - '.sass-cache/'
30
+ - 'node_modules/'
31
+ - 'bin/'
32
+ - 'tmp/*'
33
+ - 'Gemfile*'
34
+ - 'Movefile'
35
+ - 'movefile'
36
+ - 'movefile.yml'
37
+ - 'movefile.yaml'
38
+ - 'wp-config.php'
39
+ - 'wp-content/*.sql.gz'
40
+ - '*.orig'
40
41
 
41
42
  # paths: # you can customize wordpress internal paths
42
43
  # wp_content: wp-content
@@ -51,7 +52,7 @@ production:
51
52
  # user: user
52
53
  # password: password # password is optional, will use public keys if available.
53
54
  # port: 22 # Port is optional
54
- # rsync_options: --verbose # Additional rsync options, optional
55
+ # rsync_options: --verbose --itemize-changes# Additional rsync options, optional
55
56
  # gateway: # Gateway is optional
56
57
  # host: host
57
58
  # user: user
@@ -64,5 +65,29 @@ production:
64
65
  # passive: true
65
66
  # scheme: ftps # default ftp
66
67
 
68
+ # hooks: # Remote hooks won't work with FTP
69
+ # push:
70
+ # before:
71
+ # local:
72
+ # - 'echo "Do something locally before push"'
73
+ # remote:
74
+ # - 'echo "Do something remotely before push"'
75
+ # after:
76
+ # local:
77
+ # - 'echo "Do something locally after push"'
78
+ # remote:
79
+ # - 'echo "Do something remotely after push"'
80
+ # pull:
81
+ # before:
82
+ # local:
83
+ # - 'echo "Do something locally before pull"'
84
+ # remote:
85
+ # - 'echo "Do something remotely before pull"'
86
+ # after:
87
+ # local:
88
+ # - 'echo "Do something locally after pull"'
89
+ # remote:
90
+ # - 'echo "Do something remotely after pull"'
91
+
67
92
  # staging: # multiple environments can be specified
68
93
  # [...]
@@ -0,0 +1,114 @@
1
+ module Wordmove
2
+ class Hook
3
+ def self.logger
4
+ Logger.new(STDOUT).tap { |l| l.level = Logger::DEBUG }
5
+ end
6
+
7
+ def self.run(action, step, cli_options)
8
+ movefile = Wordmove::Movefile.new(cli_options[:config])
9
+ options = movefile.fetch(false)
10
+ environment = movefile.environment(cli_options)
11
+
12
+ hooks = Wordmove::Hook::Config.new(
13
+ options[environment][:hooks],
14
+ action,
15
+ step
16
+ )
17
+
18
+ unless hooks.local_hooks.empty?
19
+ Wordmove::Hook::Local.run(hooks.local_hooks, cli_options[:simulate])
20
+ end
21
+
22
+ return if hooks.remote_hooks.empty?
23
+
24
+ if options[environment][:ftp]
25
+ logger.debug "You have configured remote hooks to run over "\
26
+ "an FTP connections, but this is not possible. Skipping."
27
+
28
+ return
29
+ end
30
+
31
+ Wordmove::Hook::Remote.run(
32
+ hooks.remote_hooks, options[environment][:ssh], cli_options[:simulate]
33
+ )
34
+ end
35
+
36
+ Config = Struct.new(:options, :action, :step) do
37
+ def empty?
38
+ (local_hooks + remote_hooks).empty?
39
+ end
40
+
41
+ def local_hooks
42
+ return [] if empty_step?
43
+
44
+ options[action][step][:local] || []
45
+ end
46
+
47
+ def remote_hooks
48
+ return [] if empty_step?
49
+
50
+ options[action][step][:remote] || []
51
+ end
52
+
53
+ private
54
+
55
+ def empty_step?
56
+ return true unless options
57
+ return true if options[action].nil?
58
+ return true if options[action][step].nil?
59
+
60
+ false
61
+ end
62
+ end
63
+
64
+ class Local
65
+ def self.logger
66
+ parent.logger
67
+ end
68
+
69
+ def self.run(commands, simulate = false)
70
+ logger.task "Running local hooks"
71
+
72
+ commands.each do |command|
73
+ logger.task_step true, "Exec command: #{command}"
74
+ return true if simulate
75
+
76
+ stdout_return = `#{command} 2>&1`
77
+ logger.task_step true, "Output: #{stdout_return}"
78
+
79
+ if $CHILD_STATUS.exitstatus.zero?
80
+ logger.success ""
81
+ else
82
+ logger.error "Error code: #{$CHILD_STATUS.exitstatus}"
83
+ end
84
+ end
85
+ end
86
+ end
87
+
88
+ class Remote
89
+ def self.logger
90
+ parent.logger
91
+ end
92
+
93
+ def self.run(commands, ssh_options, simulate = false)
94
+ logger.task "Running remote hooks"
95
+
96
+ copier = Photocopier::SSH.new(ssh_options).tap { |c| c.logger = logger }
97
+ commands.each do |command|
98
+ logger.task_step false, "Exec command: #{command}"
99
+ return true if simulate
100
+
101
+ stdout, stderr, exit_code = copier.exec! command
102
+
103
+ if exit_code.zero?
104
+ logger.task_step false, "Output: #{stdout}"
105
+ logger.success ""
106
+ else
107
+ logger.task_step false, "Output: #{stderr}"
108
+ logger.error "Error code #{exit_code}"
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,12 +1,14 @@
1
1
  module Wordmove
2
2
  class Movefile
3
- attr_reader :logger
3
+ attr_reader :logger, :name, :start_dir
4
4
 
5
- def initialize
5
+ def initialize(name = nil, start_dir = current_dir)
6
6
  @logger = Logger.new(STDOUT).tap { |l| l.level = Logger::DEBUG }
7
+ @name = name
8
+ @start_dir = start_dir
7
9
  end
8
10
 
9
- def fetch(name = nil, start_dir = current_dir)
11
+ def fetch(verbose = true)
10
12
  entries = if name.nil?
11
13
  Dir["#{File.join(start_dir, '{M,m}ovefile')}{,.yml,.yaml}"]
12
14
  else
@@ -15,16 +17,36 @@ module Wordmove
15
17
 
16
18
  if entries.empty?
17
19
  raise MovefileNotFound, "Could not find a valid Movefile" if last_dir?(start_dir)
18
- return fetch(name, upper_dir(start_dir))
20
+ @start_dir = upper_dir(start_dir)
21
+ return fetch
19
22
  end
20
23
 
21
24
  found = entries.first
22
- logger.task("Using Movefile: #{found}")
23
- YAML.safe_load(ERB.new(File.read(found)).result, [], [], true)
25
+ logger.task("Using Movefile: #{found}") if verbose == true
26
+ YAML.safe_load(ERB.new(File.read(found)).result, [], [], true).deep_symbolize_keys!
27
+ end
28
+
29
+ def environment(cli_options = {})
30
+ options = fetch(false)
31
+ available_enviroments = extract_available_envs(options)
32
+ options.merge!(cli_options).deep_symbolize_keys!
33
+
34
+ if available_enviroments.size > 1 && options[:environment].nil?
35
+ raise(
36
+ UndefinedEnvironment,
37
+ "You need to specify an environment with --environment parameter"
38
+ )
39
+ end
40
+
41
+ (options[:environment] || available_enviroments.first).to_sym
24
42
  end
25
43
 
26
44
  private
27
45
 
46
+ def extract_available_envs(options)
47
+ options.keys.map(&:to_sym) - %i[local global]
48
+ end
49
+
28
50
  def last_dir?(directory)
29
51
  directory == "/" || File.exist?(File.join(directory, 'wp-config.php'))
30
52
  end
@@ -1,3 +1,3 @@
1
1
  module Wordmove
2
- VERSION = "2.3.1".freeze
2
+ VERSION = "2.4.0".freeze
3
3
  end
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: 2.3.1
4
+ version: 2.4.0
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: 2017-12-23 00:00:00.000000000 Z
15
+ date: 2017-12-28 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: activesupport
@@ -264,6 +264,7 @@ files:
264
264
  - lib/wordmove/generators/movefile.rb
265
265
  - lib/wordmove/generators/movefile.yml
266
266
  - lib/wordmove/generators/movefile_adapter.rb
267
+ - lib/wordmove/hook.rb
267
268
  - lib/wordmove/logger.rb
268
269
  - lib/wordmove/movefile.rb
269
270
  - lib/wordmove/sql_adapter/default.rb