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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12116f56ac7b71bdd918cd878a4954efa0a9ef46
4
- data.tar.gz: 0cc5ba3d421e63497336b8e71ed79a25fa00d279
3
+ metadata.gz: cc559f05a448e4588dbc9bad9e58d638ae7b00ce
4
+ data.tar.gz: a68a4350108a577fc3e245ce1d6e3b800b4ebef1
5
5
  SHA512:
6
- metadata.gz: 151aa2462ff4415923bcb36cc85d601c48deb7271d44d0702e3095551e75b9e859ccaf62ba2885ae3c3921ad6aab6420f2645125adf2feee5b7767a9bec02647
7
- data.tar.gz: 353e4d710717f72cbd2e7a9ebc0d434d0864ae497d7f49e9a0fd609df3e86949eedc032175fa55a7df56503a5f4b9a81152a11817e073274ffbcec0e215d6fb1
6
+ metadata.gz: 6ac40501ddb62f825bbea4c776218bfacfc50d35dc80bc6181b8ced3324a7b6f1a3952c8dff0a99e165505ab4146e139362f885e48298f935ab334cc50532b64
7
+ data.tar.gz: 9d184455efd6c40609c8cd11374f02ed250a616d7f667761c760dfa6e44fb470461abb5448ff37752f1641d5c684616b5077b5cb93597898117b1e892d59faa7
data/.gitignore CHANGED
@@ -3,6 +3,7 @@
3
3
  /.bundle
4
4
  /.config
5
5
  /.rspec
6
+ /dummy
6
7
  Gemfile.custom
7
8
  Gemfile.lock
8
9
  InstalledFiles
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
@@ -6,19 +6,32 @@ module Squasher
6
6
  autoload :Render, 'squasher/render'
7
7
  autoload :Worker, 'squasher/worker'
8
8
 
9
- def squash(raw_date, raw_options)
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 = raw_options.map do |o|
14
- o = o.gsub('-', '').to_sym
15
- unless Worker::OPTIONS.include?(o)
16
- tell(:wrong_option, o: o)
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
- o
20
- end
21
- Worker.process(date, options)
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
- system("RAILS_ENV=development DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake #{ command }")
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
- exit
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 'json'
56
- path = File.join(File.dirname(__FILE__), 'squasher/messages.json')
57
- @messages = JSON.load(File.open(path))
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 }") }
@@ -25,7 +25,7 @@ module Squasher
25
25
  private
26
26
 
27
27
  def config
28
- @config ||= Squasher::Config.new
28
+ Squasher.config
29
29
  end
30
30
 
31
31
  def prev_migration
@@ -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
- @schema_file = File.join(root_path, 'db', 'schema.rb')
13
- @migrations_folder = File.join(root_path, 'db', 'migrate')
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 = YAML.load(ERB.new(File.read(dbconfig_file)).result(binding))
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"
@@ -2,24 +2,21 @@ require 'fileutils'
2
2
 
3
3
  module Squasher
4
4
  class Worker
5
- OPTIONS = [:d, :r]
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, options = [])
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 options.include?(:d)
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
- @config ||= ::Squasher::Config.new
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
- return @migrations if @migrations
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 options.include?(:r)
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)
@@ -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
@@ -50,21 +50,29 @@ describe Squasher::Worker do
50
50
  end
51
51
  end
52
52
 
53
- specify 'the dry mode' do
54
- worker = described_class.new(Time.new(2014), [:d])
55
- allow(worker).to receive(:under_squash_env).and_yield.and_return(true)
56
- expect(Squasher).to receive(:tell).with(:dry_mode_finished).and_call_original
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
- specify 'reuse of an existing database' do
64
- worker = described_class.new(Time.new(2014), [:r])
65
- expect(Squasher).to receive(:tell).with(:db_reuse).and_call_original
66
- expect(Squasher).not_to receive(:rake).with("db:drop db:create", :db_create)
67
- allow(Squasher).to receive(:rake).with("db:migrate VERSION=20131213090719", :db_migrate).and_return(false)
68
- worker.process
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
@@ -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
@@ -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.2.2"
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.2.2
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-09 00:00:00.000000000 Z
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.json
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.4.5
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:
@@ -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
- }