database_patcher 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/database_patcher.rb +2 -3
- data/lib/database_patcher/action.rb +11 -0
- data/lib/database_patcher/action/initializer.rb +49 -0
- data/lib/database_patcher/{patch_applier.rb → action/patch_applier.rb} +6 -4
- data/lib/database_patcher/{patch_creator.rb → action/patch_creator.rb} +3 -2
- data/lib/database_patcher/command/create_patch.rb +2 -1
- data/lib/database_patcher/command/down.rb +3 -2
- data/lib/database_patcher/command/init.rb +2 -1
- data/lib/database_patcher/command/rollback.rb +3 -2
- data/lib/database_patcher/command/up.rb +3 -2
- data/lib/database_patcher/db.rb +1 -2
- data/lib/database_patcher/fetcher.rb +16 -10
- data/lib/database_patcher/interface.rb +9 -0
- data/lib/database_patcher/interface/null.rb +6 -0
- data/lib/database_patcher/interface/std.rb +24 -0
- data/lib/database_patcher/patch_entity.rb +29 -13
- data/lib/database_patcher/rake_task.rb +12 -14
- data/lib/database_patcher/version.rb +1 -1
- metadata +9 -6
- data/.rspec +0 -2
- data/lib/database_patcher/initializer.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4dd4e79091a8bbff51742008dbe13648634ec1e9
|
4
|
+
data.tar.gz: 0a105b04e9c13b5abe5bff2cd9e8a6e139ed9ddd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79d02146d5dc66f9ce04d29cdeb580fe110dde9946c8e691dbb75494e7d9314c94c0d50960fc2953d8b785f9ff56d743987b7397a4e8cfab315129149834e3e3
|
7
|
+
data.tar.gz: 1ff2bce215c6020902fbb6eab6a33a9a5369f07bee0bc25335596a5387f562ed8d145745593f3efa795994110d8502b13858fe65ee3b144d9a958ce129aac6dc
|
data/lib/database_patcher.rb
CHANGED
@@ -2,12 +2,11 @@ require 'fileutils'
|
|
2
2
|
module DatabasePatcher
|
3
3
|
require 'database_patcher/db'
|
4
4
|
require 'database_patcher/cli'
|
5
|
+
require 'database_patcher/action'
|
5
6
|
require 'database_patcher/fetcher'
|
6
7
|
require 'database_patcher/version'
|
7
8
|
require 'database_patcher/command'
|
9
|
+
require 'database_patcher/interface'
|
8
10
|
require 'database_patcher/environment'
|
9
|
-
require 'database_patcher/initializer'
|
10
11
|
require 'database_patcher/patch_entity'
|
11
|
-
require 'database_patcher/patch_creator'
|
12
|
-
require 'database_patcher/patch_applier'
|
13
12
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'database_patcher'
|
2
|
+
class DatabasePatcher::Action
|
3
|
+
require 'database_patcher/action/initializer'
|
4
|
+
require 'database_patcher/action/patch_applier'
|
5
|
+
require 'database_patcher/action/patch_creator'
|
6
|
+
|
7
|
+
attr_reader :interface
|
8
|
+
def initialize(interface=DatabasePatcher::Interface::Null.new)
|
9
|
+
@interface = interface
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'database_patcher'
|
2
|
+
class DatabasePatcher::Action::Initializer < DatabasePatcher::Action
|
3
|
+
def init
|
4
|
+
create_patch_folder
|
5
|
+
check_table_exists
|
6
|
+
check_required_columns
|
7
|
+
rescue Sequel::DatabaseError => explanation
|
8
|
+
connection.create_table(:installed_patches) do
|
9
|
+
Integer :timestamp
|
10
|
+
String :uuid, size: 36
|
11
|
+
String :md5_down, size: 32
|
12
|
+
String :md5_up, size: 32
|
13
|
+
String :comment
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def check_required_columns
|
20
|
+
test_column(:timestamp, Integer)
|
21
|
+
test_column(:uuid, String, size: 36, default: "")
|
22
|
+
test_column(:md5_down, String, size: 32)
|
23
|
+
test_column(:md5_up, String, size: 32)
|
24
|
+
test_column(:md5_up, String, size: 32)
|
25
|
+
test_column(:comment, String)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_column(name, type, opts = {})
|
29
|
+
connection.transaction do
|
30
|
+
unless connection[:installed_patches].columns.include?(name)
|
31
|
+
connection.alter_table(:installed_patches) do
|
32
|
+
add_column(name, type, opts)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_table_exists
|
39
|
+
connection[:installed_patches].first
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_patch_folder
|
43
|
+
FileUtils.mkpath(DatabasePatcher::Environment.patch_folder_path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def connection
|
47
|
+
@connection ||= DatabasePatcher::DB.create_connection
|
48
|
+
end
|
49
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'database_patcher'
|
2
|
-
class DatabasePatcher::PatchApplier
|
2
|
+
class DatabasePatcher::Action::PatchApplier < DatabasePatcher::Action
|
3
3
|
def up
|
4
4
|
connection = DatabasePatcher::DB.create_connection
|
5
5
|
connection.transaction do
|
6
|
-
fetcher = DatabasePatcher::Fetcher.new(connection)
|
6
|
+
fetcher = DatabasePatcher::Fetcher.new(connection, interface)
|
7
7
|
fetcher.get_pending_patches.each do |pending_patch|
|
8
8
|
pending_patch.up(connection)
|
9
9
|
end
|
@@ -11,9 +11,10 @@ class DatabasePatcher::PatchApplier
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def down
|
14
|
+
return unless interface.ask('This will execute all the down patches! Are you sure?')
|
14
15
|
connection = DatabasePatcher::DB.create_connection
|
15
16
|
connection.transaction do
|
16
|
-
fetcher = DatabasePatcher::Fetcher.new(connection)
|
17
|
+
fetcher = DatabasePatcher::Fetcher.new(connection, interface)
|
17
18
|
fetcher.get_intalled_patches.each do |installed_patche|
|
18
19
|
installed_patche.down(connection)
|
19
20
|
end
|
@@ -21,9 +22,10 @@ class DatabasePatcher::PatchApplier
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def rollback
|
25
|
+
return unless interface.ask('This will execute the last patch down part! Are you sure?')
|
24
26
|
connection = DatabasePatcher::DB.create_connection
|
25
27
|
connection.transaction do
|
26
|
-
fetcher = DatabasePatcher::Fetcher.new(connection)
|
28
|
+
fetcher = DatabasePatcher::Fetcher.new(connection, interface)
|
27
29
|
fetcher.get_intalled_patches.each do |patch|
|
28
30
|
patch.down(connection)
|
29
31
|
break
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'database_patcher'
|
3
|
-
class DatabasePatcher::PatchCreator
|
4
|
-
def initialize(type, idenpotent, file_name_description)
|
3
|
+
class DatabasePatcher::Action::PatchCreator < DatabasePatcher::Action
|
4
|
+
def initialize(type, idenpotent, file_name_description, interface = DatabasePatcher::Interface::Null)
|
5
|
+
super(interface)
|
5
6
|
@type = type
|
6
7
|
@idenpotent = !!idenpotent
|
7
8
|
@file_name_description = file_name_description
|
@@ -15,6 +15,7 @@ class DatabasePatcher::Command::CreatePatch < DatabasePatcher::Command
|
|
15
15
|
end
|
16
16
|
|
17
17
|
on_call do |args|
|
18
|
-
DatabasePatcher::
|
18
|
+
std = DatabasePatcher::Interface::STD.new
|
19
|
+
DatabasePatcher::Action::PatchCreator.new(options[:type], options[:idempotent],args.join('_'), std).make
|
19
20
|
end
|
20
21
|
end
|
@@ -4,7 +4,8 @@ class DatabasePatcher::Command::Down < DatabasePatcher::Command
|
|
4
4
|
desc 'execute the down patches and remove all db patch'
|
5
5
|
|
6
6
|
on_call do |*_|
|
7
|
-
DatabasePatcher::
|
8
|
-
DatabasePatcher::
|
7
|
+
std = DatabasePatcher::Interface::STD.new
|
8
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
9
|
+
DatabasePatcher::Action::PatchApplier.new(std).down
|
9
10
|
end
|
10
11
|
end
|
@@ -4,6 +4,7 @@ class DatabasePatcher::Command::Init < DatabasePatcher::Command
|
|
4
4
|
desc 'this will create initial directory and the default installed_patches table in the database'
|
5
5
|
|
6
6
|
on_call do |*_|
|
7
|
-
DatabasePatcher::
|
7
|
+
std = DatabasePatcher::Interface::STD.new
|
8
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
8
9
|
end
|
9
10
|
end
|
@@ -4,7 +4,8 @@ class DatabasePatcher::Command::RollBack < DatabasePatcher::Command
|
|
4
4
|
desc 'execute the last patch down part, and remove the db patch registration'
|
5
5
|
|
6
6
|
on_call do |*_|
|
7
|
-
DatabasePatcher::
|
8
|
-
DatabasePatcher::
|
7
|
+
std = DatabasePatcher::Interface::STD.new
|
8
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
9
|
+
DatabasePatcher::Action::PatchApplier.new(std).rollback
|
9
10
|
end
|
10
11
|
end
|
@@ -4,7 +4,8 @@ class DatabasePatcher::Command::Up < DatabasePatcher::Command
|
|
4
4
|
desc 'apply all pending db patch'
|
5
5
|
|
6
6
|
on_call do |*_|
|
7
|
-
DatabasePatcher::
|
8
|
-
DatabasePatcher::
|
7
|
+
std = DatabasePatcher::Interface::STD.new
|
8
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
9
|
+
DatabasePatcher::Action::PatchApplier.new(std).up
|
9
10
|
end
|
10
11
|
end
|
data/lib/database_patcher/db.rb
CHANGED
@@ -7,14 +7,13 @@ module DatabasePatcher::DB
|
|
7
7
|
|
8
8
|
def create_connection
|
9
9
|
new_connection = Sequel.connect(DatabasePatcher::Environment.database_url)
|
10
|
-
new_connection.sql_log_level = :info
|
11
10
|
new_connection.loggers << new_logger
|
12
11
|
new_connection
|
13
12
|
end
|
14
13
|
|
15
14
|
def new_logger
|
16
15
|
logger = Logger.new($stdout)
|
17
|
-
logger.level = Logger::Severity::
|
16
|
+
logger.level = Logger::Severity::UNKNOWN
|
18
17
|
logger
|
19
18
|
end
|
20
19
|
|
@@ -1,29 +1,30 @@
|
|
1
1
|
require 'database_patcher'
|
2
2
|
class DatabasePatcher::Fetcher
|
3
|
-
def initialize(connection)
|
3
|
+
def initialize(connection, interface)
|
4
4
|
@connection = connection
|
5
|
+
@interface = interface
|
5
6
|
end
|
6
7
|
|
7
8
|
def get_intalled_patches
|
8
|
-
patches = get_patches
|
9
|
+
patches = get_patches
|
9
10
|
installed_patches = []
|
10
|
-
|
11
|
+
uniq_indentifiers = get_already_applied_patch_uniq_indentifiers
|
11
12
|
|
12
13
|
patches.each do |patch|
|
13
|
-
break unless
|
14
|
+
break unless uniq_indentifiers.include?(patch.uniq_indentifier)
|
14
15
|
installed_patches.push(patch)
|
15
16
|
end
|
16
17
|
|
17
|
-
installed_patches
|
18
|
+
installed_patches.reverse
|
18
19
|
end
|
19
20
|
|
20
21
|
def get_pending_patches
|
21
22
|
patches = get_patches
|
22
23
|
pending_patches = []
|
23
|
-
|
24
|
+
uniq_indentifiers = get_already_applied_patch_uniq_indentifiers
|
24
25
|
|
25
26
|
patches.each do |patch|
|
26
|
-
break if
|
27
|
+
break if uniq_indentifiers.include?(patch.uniq_indentifier)
|
27
28
|
pending_patches.push(patch)
|
28
29
|
end
|
29
30
|
|
@@ -36,7 +37,7 @@ class DatabasePatcher::Fetcher
|
|
36
37
|
|
37
38
|
def get_patches
|
38
39
|
Dir.glob(File.join(DatabasePatcher::Environment.patch_folder_path, '*')).reduce([]) do |patches, current_path|
|
39
|
-
patches << DatabasePatcher::PatchEntity.factory(current_path)
|
40
|
+
patches << DatabasePatcher::PatchEntity.factory(current_path, @interface)
|
40
41
|
patches
|
41
42
|
end.sort_by(&:timestamp)
|
42
43
|
end
|
@@ -45,7 +46,12 @@ class DatabasePatcher::Fetcher
|
|
45
46
|
connection[:installed_patches].all
|
46
47
|
end
|
47
48
|
|
48
|
-
def
|
49
|
-
installed_patches.map
|
49
|
+
def get_already_applied_patch_uniq_indentifiers
|
50
|
+
installed_patches.map do |record|
|
51
|
+
{
|
52
|
+
timestamp: record[:timestamp],
|
53
|
+
uuid: record[:uuid]
|
54
|
+
}
|
55
|
+
end.sort_by{|r| r[:timestamp].to_i }
|
50
56
|
end
|
51
57
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'database_patcher'
|
3
|
+
class DatabasePatcher::Interface::STD < DatabasePatcher::Interface
|
4
|
+
def initialize(options = {})
|
5
|
+
@force = !!options[:force]
|
6
|
+
end
|
7
|
+
|
8
|
+
def ask(question)
|
9
|
+
return true if @force
|
10
|
+
Timeout.timeout(15) do
|
11
|
+
loop do
|
12
|
+
$stdout.puts(question.to_s + ' ([y]es/[n]o)')
|
13
|
+
case $stdin.gets.chomp.strip.downcase
|
14
|
+
when 'y', 'yes'
|
15
|
+
return true
|
16
|
+
when 'n', 'no'
|
17
|
+
return false
|
18
|
+
else
|
19
|
+
$stdout.puts('invalid answer, please try again')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -4,23 +4,30 @@ class DatabasePatcher::PatchEntity
|
|
4
4
|
require 'database_patcher/patch_entity/file'
|
5
5
|
require 'database_patcher/patch_entity/folder'
|
6
6
|
|
7
|
-
def self.factory(path)
|
7
|
+
def self.factory(path, interface)
|
8
8
|
if ::File.directory?(path)
|
9
|
-
self::Folder.new(path)
|
9
|
+
self::Folder.new(path, interface)
|
10
10
|
else
|
11
|
-
self::File.new(path)
|
11
|
+
self::File.new(path, interface)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
attr_reader :path, :interface
|
16
|
+
def initialize(path, interface)
|
16
17
|
@path = path
|
18
|
+
@interface = interface
|
17
19
|
end
|
18
20
|
|
19
21
|
def timestamp
|
20
|
-
basename = ::File.basename(@path, '.*')
|
21
22
|
basename.scan(/^\d+/).flatten.first.to_i
|
22
23
|
end
|
23
24
|
|
25
|
+
UUID_MATCHER = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'.freeze
|
26
|
+
def uuid
|
27
|
+
basename = ::File.basename(@path, '.*')
|
28
|
+
basename.scan(/^\d+_(#{UUID_MATCHER})_/).flatten.first.to_s
|
29
|
+
end
|
30
|
+
|
24
31
|
def up(_connection)
|
25
32
|
raise
|
26
33
|
end
|
@@ -29,6 +36,15 @@ class DatabasePatcher::PatchEntity
|
|
29
36
|
raise
|
30
37
|
end
|
31
38
|
|
39
|
+
def uniq_indentifier
|
40
|
+
{
|
41
|
+
timestamp: timestamp,
|
42
|
+
uuid: uuid
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
32
48
|
def execute_file(connection, path)
|
33
49
|
case ::File.extname(path)
|
34
50
|
|
@@ -54,16 +70,12 @@ class DatabasePatcher::PatchEntity
|
|
54
70
|
$stdout.puts("Patch removed: #{uniq_indentifier[:timestamp]}")
|
55
71
|
end
|
56
72
|
|
57
|
-
def
|
73
|
+
def patch_record
|
58
74
|
{
|
59
|
-
timestamp: timestamp,
|
60
75
|
md5_down: md5_down,
|
61
|
-
md5_up: md5_up
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
def patch_record
|
66
|
-
uniq_indentifier.merge(comment: comment)
|
76
|
+
md5_up: md5_up,
|
77
|
+
comment: comment
|
78
|
+
}.merge(uniq_indentifier)
|
67
79
|
end
|
68
80
|
|
69
81
|
def md5(string)
|
@@ -95,4 +107,8 @@ class DatabasePatcher::PatchEntity
|
|
95
107
|
def raise_unknown_extension_for(path)
|
96
108
|
raise("unknown patch file extension: #{::File.extname(path)} (#{path})")
|
97
109
|
end
|
110
|
+
|
111
|
+
def basename
|
112
|
+
::File.basename(@path, '.*')
|
113
|
+
end
|
98
114
|
end
|
@@ -1,31 +1,29 @@
|
|
1
1
|
require "database_patcher"
|
2
|
-
|
2
|
+
std = DatabasePatcher::Interface::STD.new
|
3
|
+
namespace :dp do
|
3
4
|
|
4
5
|
desc 'apply pending schema migrations'
|
5
|
-
task :
|
6
|
-
DatabasePatcher::Initializer.new.init
|
7
|
-
DatabasePatcher::PatchApplier.new.up
|
6
|
+
task :up do
|
7
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
8
|
+
DatabasePatcher::Action::PatchApplier.new(std).up
|
8
9
|
end
|
9
10
|
|
10
|
-
desc "Alias task for apply_pending_patches"
|
11
|
-
task :migrate => :apply_pending_patches
|
12
|
-
|
13
11
|
desc 'apply pending schema migrations'
|
14
|
-
task :
|
15
|
-
DatabasePatcher::Initializer.new.init
|
16
|
-
DatabasePatcher::PatchApplier.new.down
|
12
|
+
task :down do
|
13
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
14
|
+
DatabasePatcher::Action::PatchApplier.new(std).down
|
17
15
|
end
|
18
16
|
|
19
17
|
desc 'rollback one patch'
|
20
18
|
task :rollback do
|
21
|
-
DatabasePatcher::Initializer.new.init
|
22
|
-
DatabasePatcher::PatchApplier.new.rollback
|
19
|
+
DatabasePatcher::Action::Initializer.new(std).init
|
20
|
+
DatabasePatcher::Action::PatchApplier.new(std).rollback
|
23
21
|
end
|
24
22
|
|
25
23
|
desc 'create a new migration patch'
|
26
|
-
task :
|
24
|
+
task :add, :type, :idempotent, :description do |t, args|
|
27
25
|
args.with_defaults(:type => 'ruby', :idempotent => false, :description => '')
|
28
|
-
DatabasePatcher::PatchCreator.new(args[:type], args[:idempotent],args[:description]).make
|
26
|
+
DatabasePatcher::Action::PatchCreator.new(args[:type], args[:idempotent],args[:description],std).make
|
29
27
|
end
|
30
28
|
|
31
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: database_patcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Luzsi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -104,7 +104,6 @@ extra_rdoc_files: []
|
|
104
104
|
files:
|
105
105
|
- ".env"
|
106
106
|
- ".gitignore"
|
107
|
-
- ".rspec"
|
108
107
|
- ".travis.yml"
|
109
108
|
- CODE_OF_CONDUCT.md
|
110
109
|
- Gemfile
|
@@ -115,6 +114,10 @@ files:
|
|
115
114
|
- database_patcher.gemspec
|
116
115
|
- exe/database_patcher
|
117
116
|
- lib/database_patcher.rb
|
117
|
+
- lib/database_patcher/action.rb
|
118
|
+
- lib/database_patcher/action/initializer.rb
|
119
|
+
- lib/database_patcher/action/patch_applier.rb
|
120
|
+
- lib/database_patcher/action/patch_creator.rb
|
118
121
|
- lib/database_patcher/cli.rb
|
119
122
|
- lib/database_patcher/command.rb
|
120
123
|
- lib/database_patcher/command/create_patch.rb
|
@@ -126,9 +129,9 @@ files:
|
|
126
129
|
- lib/database_patcher/db.rb
|
127
130
|
- lib/database_patcher/environment.rb
|
128
131
|
- lib/database_patcher/fetcher.rb
|
129
|
-
- lib/database_patcher/
|
130
|
-
- lib/database_patcher/
|
131
|
-
- lib/database_patcher/
|
132
|
+
- lib/database_patcher/interface.rb
|
133
|
+
- lib/database_patcher/interface/null.rb
|
134
|
+
- lib/database_patcher/interface/std.rb
|
132
135
|
- lib/database_patcher/patch_entity.rb
|
133
136
|
- lib/database_patcher/patch_entity/file.rb
|
134
137
|
- lib/database_patcher/patch_entity/folder.rb
|
data/.rspec
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
require 'database_patcher'
|
2
|
-
class DatabasePatcher::Initializer
|
3
|
-
def init
|
4
|
-
create_patch_folder
|
5
|
-
check_table_exists
|
6
|
-
rescue Sequel::DatabaseError
|
7
|
-
connection.create_table(:installed_patches) do
|
8
|
-
Integer :timestamp
|
9
|
-
String :md5_down, size: 32
|
10
|
-
String :md5_up, size: 32
|
11
|
-
String :comment
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
protected
|
16
|
-
|
17
|
-
def check_table_exists
|
18
|
-
connection[:installed_patches].first
|
19
|
-
end
|
20
|
-
|
21
|
-
def create_patch_folder
|
22
|
-
FileUtils.mkpath(DatabasePatcher::Environment.patch_folder_path)
|
23
|
-
end
|
24
|
-
|
25
|
-
def connection
|
26
|
-
@connection ||= DatabasePatcher::DB.create_connection
|
27
|
-
end
|
28
|
-
end
|