squasher 0.2.2 → 0.3.0
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 +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
|
-
}
|