squasher 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +8 -0
- data/lib/squasher.rb +28 -13
- data/lib/squasher/cleaner.rb +1 -1
- data/lib/squasher/config.rb +70 -5
- data/lib/squasher/messages.yml +30 -0
- data/lib/squasher/worker.rb +6 -11
- data/spec/lib/squasher_spec.rb +1 -1
- data/spec/lib/worker_spec.rb +23 -15
- data/spec/spec_helper.rb +3 -3
- data/squasher.gemspec +1 -1
- metadata +4 -5
- data/lib/squasher/messages.json +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cc559f05a448e4588dbc9bad9e58d638ae7b00ce
|
4
|
+
data.tar.gz: a68a4350108a577fc3e245ce1d6e3b800b4ebef1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ac40501ddb62f825bbea4c776218bfacfc50d35dc80bc6181b8ced3324a7b6f1a3952c8dff0a99e165505ab4146e139362f885e48298f935ab334cc50532b64
|
7
|
+
data.tar.gz: 9d184455efd6c40609c8cd11374f02ed250a616d7f667761c760dfa6e44fb470461abb5448ff37752f1641d5c684616b5077b5cb93597898117b1e892d59faa7
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -50,12 +50,20 @@ process breaks in a migration from 2014. In this situation you squash till 2014,
|
|
50
50
|
database at the end, make a patch in the broken migration and run again the suite with `-r` option. As the result
|
51
51
|
squasher will not need to create the db schema and all data from the previous migrations will be there.
|
52
52
|
|
53
|
+
`-e` - tell squasher that you are squashing a Rails engine. To squash migrations you need to configure a dummy app. If your dummy app located outside the engine's folder provide path to it as the next argument `squasher -e ../my-engine-app 2016`
|
54
|
+
|
53
55
|
## Requirements
|
54
56
|
|
55
57
|
It works and was tested on Ruby 2.0+ and Rails 3.1+. It also requires a valid development configuration in `config/database.yml` and using Ruby format in `db/schema.rb` (default Rails use-case).
|
56
58
|
If an old migration inserted data (created ActiveRecord model records) you will lose this code in the squashed migration, **BUT** `squasher` will ask you to leave a tmp database which will have all data that was inserted while migrating. Using this database you could add that data as another migration, or into `config/seed.rb` (the expected place for this stuff).
|
57
59
|
|
58
60
|
## Changelog
|
61
|
+
- 0.3.0
|
62
|
+
- **rails engines support** ([@JakeTheSnake3p0](https://github.com/JakeTheSnake3p0))
|
63
|
+
- move messages from JSON file to YAML
|
64
|
+
- allow to use a db config with a "soft" parsing errors
|
65
|
+
- 0.2.2
|
66
|
+
- strip white spaces in init migrations
|
59
67
|
- 0.2.1
|
60
68
|
- support rails 5
|
61
69
|
- 0.2.0
|
data/lib/squasher.rb
CHANGED
@@ -6,19 +6,32 @@ module Squasher
|
|
6
6
|
autoload :Render, 'squasher/render'
|
7
7
|
autoload :Worker, 'squasher/worker'
|
8
8
|
|
9
|
-
|
9
|
+
attr_reader :config
|
10
|
+
|
11
|
+
@config = Config.new
|
12
|
+
|
13
|
+
def squash(raw_date, options)
|
10
14
|
parts = raw_date.to_s.split('/').map(&:to_i)
|
11
15
|
date = Time.new(*parts)
|
12
16
|
|
13
|
-
options
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
options.reduce([]) do |acc, arg|
|
18
|
+
if arg.index('-') == 0
|
19
|
+
arg = arg.gsub('-', '').to_sym
|
20
|
+
unless Config::OPTIONS.include?(arg)
|
21
|
+
tell(:wrong_option, arg: arg)
|
22
|
+
error(:usage)
|
23
|
+
end
|
24
|
+
acc.push([arg])
|
25
|
+
elsif acc.empty?
|
26
|
+
tell(:invalid_param, arg: arg)
|
17
27
|
error(:usage)
|
28
|
+
else
|
29
|
+
acc.last[1] = arg
|
18
30
|
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
31
|
+
acc
|
32
|
+
end.each { |(k, v)| config.set(k, v) }
|
33
|
+
|
34
|
+
Worker.process(date)
|
22
35
|
end
|
23
36
|
|
24
37
|
def clean
|
@@ -27,7 +40,9 @@ module Squasher
|
|
27
40
|
|
28
41
|
def rake(command, description = nil)
|
29
42
|
tell(description) if description
|
30
|
-
|
43
|
+
config.in_app_root do
|
44
|
+
system("RAILS_ENV=development DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake #{ command }")
|
45
|
+
end
|
31
46
|
end
|
32
47
|
|
33
48
|
def ask(*args)
|
@@ -44,7 +59,7 @@ module Squasher
|
|
44
59
|
|
45
60
|
def error(*args)
|
46
61
|
tell(*args)
|
47
|
-
|
62
|
+
abort
|
48
63
|
end
|
49
64
|
|
50
65
|
private
|
@@ -52,9 +67,9 @@ module Squasher
|
|
52
67
|
def messages
|
53
68
|
return @messages if @messages
|
54
69
|
|
55
|
-
require '
|
56
|
-
path = File.join(File.dirname(__FILE__), 'squasher/messages.
|
57
|
-
@messages =
|
70
|
+
require 'yaml'
|
71
|
+
path = File.join(File.dirname(__FILE__), 'squasher/messages.yml')
|
72
|
+
@messages = YAML.load(File.open(path))
|
58
73
|
end
|
59
74
|
|
60
75
|
COLORS = ['red', 'green', 'yellow', 'blue'].each_with_index.inject({}) { |r, (k, i)| r.merge!(k => "03#{ i + 1 }") }
|
data/lib/squasher/cleaner.rb
CHANGED
data/lib/squasher/config.rb
CHANGED
@@ -4,14 +4,65 @@ require 'erb'
|
|
4
4
|
|
5
5
|
module Squasher
|
6
6
|
class Config
|
7
|
+
OPTIONS = [:d, :r, :e].freeze
|
8
|
+
|
9
|
+
module Render
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def process(path)
|
13
|
+
@error = false
|
14
|
+
|
15
|
+
str = YAML.load(ERB.new(File.read(path)).result(binding))
|
16
|
+
[str, @error]
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(*args)
|
20
|
+
@error = true
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def const_missing(*args)
|
25
|
+
@error = true
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
''
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
''
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
7
38
|
attr_reader :schema_file
|
8
39
|
|
9
40
|
def initialize
|
10
|
-
root_path = Dir.pwd
|
41
|
+
@root_path = Dir.pwd.freeze
|
42
|
+
@migrations_folder = File.join(@root_path, 'db', 'migrate')
|
43
|
+
@flags = []
|
44
|
+
set_app_path(@root_path)
|
45
|
+
end
|
46
|
+
|
47
|
+
def set(key, value)
|
48
|
+
if key == :e
|
49
|
+
base = value.nil? ? @root_path : File.expand_path(value, @root_path)
|
50
|
+
list = Dir.glob(File.join(base, '**', '*', 'config', 'application.rb'))
|
51
|
+
case list.size
|
52
|
+
when 1
|
53
|
+
set_app_path(File.expand_path('../..', list.first))
|
54
|
+
when 0
|
55
|
+
Squasher.error(:cannot_find_dummy, base: base)
|
56
|
+
else
|
57
|
+
Squasher.error(:multi_dummy_case, base: base)
|
58
|
+
end
|
59
|
+
else
|
60
|
+
@flags << key
|
61
|
+
end
|
62
|
+
end
|
11
63
|
|
12
|
-
|
13
|
-
@
|
14
|
-
@dbconfig_file = File.join(root_path, 'config', 'database.yml')
|
64
|
+
def with?(k)
|
65
|
+
@flags.include?(k)
|
15
66
|
end
|
16
67
|
|
17
68
|
def migration_files
|
@@ -50,6 +101,10 @@ module Squasher
|
|
50
101
|
end
|
51
102
|
end
|
52
103
|
|
104
|
+
def in_app_root(&block)
|
105
|
+
Dir.chdir(@app_path, &block)
|
106
|
+
end
|
107
|
+
|
53
108
|
private
|
54
109
|
|
55
110
|
attr_reader :migrations_folder, :dbconfig_file
|
@@ -61,13 +116,23 @@ module Squasher
|
|
61
116
|
@dbconfig = nil
|
62
117
|
|
63
118
|
begin
|
64
|
-
content =
|
119
|
+
content, soft_error = Render.process(dbconfig_file)
|
65
120
|
if content.has_key?('development')
|
66
121
|
@dbconfig = { 'development' => content['development'].merge('database' => 'squasher') }
|
67
122
|
end
|
68
123
|
rescue
|
69
124
|
end
|
125
|
+
|
126
|
+
if soft_error && @dbconfig
|
127
|
+
exit unless Squasher.ask(:use_dbconfig, config: @dbconfig.fetch('development'))
|
128
|
+
end
|
70
129
|
@dbconfig
|
71
130
|
end
|
131
|
+
|
132
|
+
def set_app_path(path)
|
133
|
+
@app_path = path
|
134
|
+
@schema_file = File.join(path, 'db', 'schema.rb')
|
135
|
+
@dbconfig_file = File.join(path, 'config', 'database.yml')
|
136
|
+
end
|
72
137
|
end
|
73
138
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
keep_database:
|
2
|
+
- "Squasher's created the `:green<squasher>` database for its needs."
|
3
|
+
- It might be useful to keep it if any of your deleted migrations inserts data or
|
4
|
+
- you squash migrations in a few steps (look at -r option).
|
5
|
+
- "Keep it (:green<yes> / :red<no>)?"
|
6
|
+
apply_clean: "Do you want to clean your database from the old schema migration records(:red<yes>/:green<no>)?"
|
7
|
+
migration_folder_missing:
|
8
|
+
- The folder with migrations is missing.
|
9
|
+
- "Are you sure that you're in the :red<root of a rails> application?"
|
10
|
+
no_migrations: "There are no migrations in the folder prior to :red<%{date}>"
|
11
|
+
use_dbconfig: "There were problems in parsing `:green<database.yml>`. Do you want to use the config below (:green<yes>/:red<no>)?\n\n%{config}\n"
|
12
|
+
dbconfig_invalid: "Squasher couldn't load `:green<database.yml>`. Please, make sure that it's present and doesn't include any ruby code."
|
13
|
+
db_create: Squasher is creating a tmp database
|
14
|
+
db_migrate: Squasher is applying migrations on a tmp database
|
15
|
+
db_cleaning: Squasher is applying the clean migration
|
16
|
+
db_reuse: Squasher is reusing the database from the previous squashing
|
17
|
+
usage:
|
18
|
+
- "Example usage:"
|
19
|
+
- " :green<squasher> [options] :yellow<year[/month][/day]> => squash migrations prior to a specified date"
|
20
|
+
- " :green<squasher> :yellow<clean> => generate or update a cleaning migration and apply it"
|
21
|
+
- " :green<squasher> :yellow<info> => show the message\n"
|
22
|
+
- "Options:"
|
23
|
+
- " :yellow<-d> => execute in :blue<`dry`> mode - test a squashing process without removing old migrations"
|
24
|
+
- " :yellow<-r> => reuse a database from the previous squashing"
|
25
|
+
- " :yellow<-e> [dummy-root] => execute in :blue<`engine`> mode - requires a dummy app"
|
26
|
+
wrong_option: "You provided a wrong option :red<%{arg}>\n\n"
|
27
|
+
invalid_param: "You provided a wrong param :red<%{arg}>\n\n"
|
28
|
+
dry_mode_finished: "The `dry` mode is finished. Below the init schema's content:"
|
29
|
+
cannot_find_dummy: "Squasher can't find a dummy app inside :yellow<%{base}>"
|
30
|
+
multi_dummy_case: "Squasher found a few config/application.rb inside :yellow<%{base}>. Please specify the path more precisely"
|
data/lib/squasher/worker.rb
CHANGED
@@ -2,24 +2,21 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
module Squasher
|
4
4
|
class Worker
|
5
|
-
|
6
|
-
|
7
|
-
attr_reader :date, :options
|
5
|
+
attr_reader :date
|
8
6
|
|
9
7
|
def self.process(*args)
|
10
8
|
new(*args).process
|
11
9
|
end
|
12
10
|
|
13
|
-
def initialize(date
|
11
|
+
def initialize(date)
|
14
12
|
@date = date
|
15
|
-
@options = options
|
16
13
|
end
|
17
14
|
|
18
15
|
def process
|
19
16
|
check!
|
20
17
|
|
21
18
|
result = under_squash_env do
|
22
|
-
if
|
19
|
+
if Squasher.config.with?(:d)
|
23
20
|
Squasher.tell(:dry_mode_finished)
|
24
21
|
puts Render.render(:init_schema, config)
|
25
22
|
else
|
@@ -37,7 +34,7 @@ module Squasher
|
|
37
34
|
private
|
38
35
|
|
39
36
|
def config
|
40
|
-
|
37
|
+
Squasher.config
|
41
38
|
end
|
42
39
|
|
43
40
|
def check!
|
@@ -50,9 +47,7 @@ module Squasher
|
|
50
47
|
end
|
51
48
|
|
52
49
|
def migrations
|
53
|
-
|
54
|
-
|
55
|
-
@migrations = config.migration_files.select { |file| before_date?(get_timestamp(file)) }.sort
|
50
|
+
@migrations ||= config.migration_files.select { |file| before_date?(get_timestamp(file)) }.sort
|
56
51
|
end
|
57
52
|
|
58
53
|
def get_timestamp(file)
|
@@ -71,7 +66,7 @@ module Squasher
|
|
71
66
|
|
72
67
|
def under_squash_env
|
73
68
|
config.stub_dbconfig do
|
74
|
-
if
|
69
|
+
if Squasher.config.with?(:r)
|
75
70
|
Squasher.tell(:db_reuse)
|
76
71
|
else
|
77
72
|
return unless Squasher.rake("db:drop db:create", :db_create)
|
data/spec/lib/squasher_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Squasher do
|
|
6
6
|
specify { expected_covert("2013", Time.new(2013, 1, 1)) }
|
7
7
|
|
8
8
|
def expected_covert(input, expected)
|
9
|
-
expect(Squasher::Worker).to receive(:process).with(expected
|
9
|
+
expect(Squasher::Worker).to receive(:process).with(expected)
|
10
10
|
Squasher.squash(input, [])
|
11
11
|
end
|
12
12
|
end
|
data/spec/lib/worker_spec.rb
CHANGED
@@ -50,21 +50,29 @@ describe Squasher::Worker do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
expect(Squasher).to receive(:ask).with(:keep_database).and_return(false)
|
58
|
-
expect(Squasher).to receive(:rake).with("db:drop")
|
59
|
-
expect(Squasher).to receive(:ask).with(:apply_clean).and_return(false)
|
60
|
-
worker.process
|
61
|
-
end
|
53
|
+
context 'with flags' do
|
54
|
+
before do
|
55
|
+
Squasher.instance_variable_set(:@config, Squasher::Config.new)
|
56
|
+
end
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
58
|
+
specify 'the dry mode' do
|
59
|
+
Squasher.config.set(:d, nil)
|
60
|
+
worker = described_class.new(Time.new(2014))
|
61
|
+
allow(worker).to receive(:under_squash_env).and_yield.and_return(true)
|
62
|
+
expect(Squasher).to receive(:tell).with(:dry_mode_finished).and_call_original
|
63
|
+
expect(Squasher).to receive(:ask).with(:keep_database).and_return(false)
|
64
|
+
expect(Squasher).to receive(:rake).with("db:drop")
|
65
|
+
expect(Squasher).to receive(:ask).with(:apply_clean).and_return(false)
|
66
|
+
worker.process
|
67
|
+
end
|
68
|
+
|
69
|
+
specify 'reuse of an existing database' do
|
70
|
+
Squasher.config.set(:r, nil)
|
71
|
+
worker = described_class.new(Time.new(2014))
|
72
|
+
expect(Squasher).to receive(:tell).with(:db_reuse).and_call_original
|
73
|
+
expect(Squasher).not_to receive(:rake).with("db:drop db:create", :db_create)
|
74
|
+
allow(Squasher).to receive(:rake).with("db:migrate VERSION=20131213090719", :db_migrate).and_return(false)
|
75
|
+
worker.process
|
76
|
+
end
|
69
77
|
end
|
70
78
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'bundler/setup'
|
2
|
-
Bundler.require
|
3
|
-
|
4
1
|
module SpecHelpers
|
5
2
|
def fake_root
|
6
3
|
File.join(File.dirname(__FILE__), 'fake_app')
|
@@ -15,6 +12,9 @@ module Squasher
|
|
15
12
|
end
|
16
13
|
end
|
17
14
|
|
15
|
+
require 'bundler/setup'
|
16
|
+
Bundler.require
|
17
|
+
|
18
18
|
RSpec.configure do |config|
|
19
19
|
config.order = 'random'
|
20
20
|
config.include SpecHelpers
|
data/squasher.gemspec
CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "squasher"
|
8
|
-
spec.version = "0.
|
8
|
+
spec.version = "0.3.0"
|
9
9
|
spec.authors = ["Sergey Pchelintsev"]
|
10
10
|
spec.email = ["mail@sergeyp.me"]
|
11
11
|
spec.description = %q{Squash your old migrations}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: squasher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergey Pchelintsev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -70,7 +70,7 @@ files:
|
|
70
70
|
- lib/squasher.rb
|
71
71
|
- lib/squasher/cleaner.rb
|
72
72
|
- lib/squasher/config.rb
|
73
|
-
- lib/squasher/messages.
|
73
|
+
- lib/squasher/messages.yml
|
74
74
|
- lib/squasher/render.rb
|
75
75
|
- lib/squasher/templates/init_schema.rb.erb
|
76
76
|
- lib/squasher/templates/squasher_clean.rb.erb
|
@@ -108,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
108
|
version: '0'
|
109
109
|
requirements: []
|
110
110
|
rubyforge_project:
|
111
|
-
rubygems_version: 2.
|
111
|
+
rubygems_version: 2.6.11
|
112
112
|
signing_key:
|
113
113
|
specification_version: 4
|
114
114
|
summary: Squash your old migrations
|
@@ -125,4 +125,3 @@ test_files:
|
|
125
125
|
- spec/lib/squasher_spec.rb
|
126
126
|
- spec/lib/worker_spec.rb
|
127
127
|
- spec/spec_helper.rb
|
128
|
-
has_rdoc:
|
data/lib/squasher/messages.json
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"keep_database" : [
|
3
|
-
"Squasher's created the `:green<squasher>` database for its needs.",
|
4
|
-
"It might be useful to keep it if any of your deleted migrations inserts data or",
|
5
|
-
"you squash migrations in few steps (look at -r option).",
|
6
|
-
"Keep it (:green<yes> / :red<no>)?"
|
7
|
-
],
|
8
|
-
|
9
|
-
"apply_clean": "Do you want to clean your database from the old schema migration records(:red<yes>/:green<no>)?",
|
10
|
-
|
11
|
-
"migration_folder_missing" : [
|
12
|
-
"The folder with migrations is missing.",
|
13
|
-
"Are you sure that you're in the :red<root of a rails> application?"
|
14
|
-
],
|
15
|
-
|
16
|
-
"no_migrations" : "There are no migrations in the folder prior to :red<%{date}>",
|
17
|
-
|
18
|
-
"dbconfig_invalid" : "Squasher couldn't load `:green<database.yml>`. Please, make sure that it's present and doesn't include any ruby code.",
|
19
|
-
|
20
|
-
"db_create": "Squasher is creating a tmp database",
|
21
|
-
|
22
|
-
"db_migrate": "Squasher is applying migrations on a tmp database",
|
23
|
-
|
24
|
-
"db_cleaning": "Squasher is applying the clean migration",
|
25
|
-
|
26
|
-
"db_reuse": "Squasher is reusing the database from the previous squashing",
|
27
|
-
|
28
|
-
"usage": [
|
29
|
-
"Example usage:",
|
30
|
-
" :green<squasher> [options] :yellow<year[/month][/day]> => squash migrations prior to a specified date",
|
31
|
-
" :green<squasher> :yellow<clean> => generate or update a cleaning migration and apply it",
|
32
|
-
" :green<squasher> :yellow<info> => show the message",
|
33
|
-
"",
|
34
|
-
"Options:",
|
35
|
-
" :yellow<-d> => execute in :blue<`dry`> mode - test a squashing process without removing old migrations",
|
36
|
-
" :yellow<-r> => reuse a database from the previous squashing"
|
37
|
-
],
|
38
|
-
|
39
|
-
"wrong_option": "You provided a wrong option :red<%{o}>",
|
40
|
-
|
41
|
-
"dry_mode_finished": "The `dry` mode is finished. Below the init schema's content:"
|
42
|
-
}
|