squasher 0.1.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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +37 -0
- data/Rakefile +1 -0
- data/bin/squasher +9 -0
- data/lib/squasher.rb +57 -0
- data/lib/squasher/cleaner.rb +43 -0
- data/lib/squasher/config.rb +82 -0
- data/lib/squasher/messages.json +19 -0
- data/lib/squasher/render.rb +46 -0
- data/lib/squasher/templates/init_schema.rb.erb +11 -0
- data/lib/squasher/templates/squasher_clean.rb.erb +13 -0
- data/lib/squasher/version.rb +3 -0
- data/lib/squasher/worker.rb +74 -0
- data/spec/fake_app/config/database.yml +8 -0
- data/spec/fake_app/config/invalid_database.yml +4 -0
- data/spec/fake_app/db/migrate/201312090000_first_migration.rb +0 -0
- data/spec/fake_app/db/migrate/2013122900_second_migration.rb +0 -0
- data/spec/fake_app/db/migrate/20140101010101_squasher_clean.rb +0 -0
- data/spec/fake_app/db/migrate/20140110_third_migration.rb +0 -0
- data/spec/fake_app/db/schema.rb +41 -0
- data/spec/lib/squasher/cleaner_spec.rb +39 -0
- data/spec/lib/squasher/config_spec.rb +57 -0
- data/spec/lib/squasher/worker_spec.rb +52 -0
- data/spec/lib/squasher_spec.rb +13 -0
- data/spec/spec_helper.rb +13 -0
- data/squasher.gemspec +24 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 03bf510487b316ab7771766ef9605f8a8269bfed
|
4
|
+
data.tar.gz: e01e6ba2390d5dabcc0a7fd24d7cbafb4c0f4549
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 399e73be169b440d181fd4ab2283bb11fd75226e5a8d3b3ecba6b4c4b1b3808b7908c993f5a5ec44d5e258920a70c568db8773823bff7aef49fe7979f250167c
|
7
|
+
data.tar.gz: 092b138e42c74d278a97247e1fbf679ea5c2bba65e0379aaa1ac555205d2e9ac4937a53608f010764f47be788fbbff895acb1656e0b358822728d7d59ac827fa
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Sergey Pchelincev
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Squasher
|
2
|
+
|
3
|
+
Squasher is a compressor of the old migrations in rails application. If you works on big project with lots of migrations
|
4
|
+
every `rake db:migrate` takes a few seconds, creating of a new database might takes a few minutes. It's just because rails load
|
5
|
+
all this files. Squasher instead remove all this migrations and create one single migration with a final state of a database.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
You should not add this to Gemfile. Just standalone installation:
|
10
|
+
|
11
|
+
$ gem install squasher
|
12
|
+
|
13
|
+
@Note if you use Rbenv don't forget to run `rbenv rehash`.
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
Once you install gem you will get `squasher` command.
|
18
|
+
|
19
|
+
$ squasher 2014 #compress all migrations which were created prior to 2014 year
|
20
|
+
|
21
|
+
You can tell `squasher` a more detailed date, for example:
|
22
|
+
|
23
|
+
$ squasher 2013/12 #prior December 2013
|
24
|
+
$ squasher 2013/12/19 #prior 19 December 2013
|
25
|
+
|
26
|
+
## Requirements
|
27
|
+
|
28
|
+
It works and was tested on Ruby 1.9.3+ and Rails 3.2+. Also it requires a valid configuration in `config/database.yml` and using Ruby format in `db/schema.rb`(default rails usecase).
|
29
|
+
If some migration insert data(create a ActiveRecord model records) you will lost this code in a new created migration, but `squasher` will ask you to leave tmp database which will have all inserted information. Using this database you could again add this inserting into a new migration or create/update `config/seed.rb` file(expected place for this stuff).
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
1. Fork it
|
34
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
35
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
36
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
37
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/squasher
ADDED
data/lib/squasher.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Squasher
|
2
|
+
extend self
|
3
|
+
|
4
|
+
autoload :Cleaner, 'squasher/cleaner'
|
5
|
+
autoload :Config, 'squasher/config'
|
6
|
+
autoload :Render, 'squasher/render'
|
7
|
+
autoload :Worker, 'squasher/worker'
|
8
|
+
|
9
|
+
def squash(raw_date)
|
10
|
+
parts = raw_date.to_s.split('/').map(&:to_i)
|
11
|
+
date = Time.new(*parts)
|
12
|
+
Worker.process(date)
|
13
|
+
end
|
14
|
+
|
15
|
+
def clean
|
16
|
+
Cleaner.process
|
17
|
+
end
|
18
|
+
|
19
|
+
def rake(command, description = nil)
|
20
|
+
tell(description) if description
|
21
|
+
system("bundle exec rake #{ command }")
|
22
|
+
end
|
23
|
+
|
24
|
+
def ask(*args)
|
25
|
+
tell(*args)
|
26
|
+
$stdin.gets[0].downcase == 'y'
|
27
|
+
end
|
28
|
+
|
29
|
+
def tell(key, options = {})
|
30
|
+
message = messages.fetch(key.to_s)
|
31
|
+
message = colorize(message)
|
32
|
+
options.each { |key, value| message.gsub!(":#{ key }", value) }
|
33
|
+
puts message
|
34
|
+
end
|
35
|
+
|
36
|
+
def error(*args)
|
37
|
+
tell(*args)
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def messages
|
44
|
+
return @messages if @messages
|
45
|
+
|
46
|
+
require 'json'
|
47
|
+
path = File.join(File.dirname(__FILE__), 'squasher/messages.json')
|
48
|
+
@messages = JSON.load(File.open(path))
|
49
|
+
end
|
50
|
+
|
51
|
+
def colorize(message)
|
52
|
+
message.gsub(/\:(\w+)\{([^}]+)\}/) do |match|
|
53
|
+
color_code = { "red" => "031", "green" => "032", "yellow" => "033" }[$1]
|
54
|
+
"\033[#{ color_code }m#{ $2 }\033[039m"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Squasher
|
4
|
+
class Cleaner
|
5
|
+
MIGRATION_NAME = 'squasher_clean'
|
6
|
+
|
7
|
+
def self.process(*args)
|
8
|
+
new(*args).process
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
Squasher.error(:migration_folder_missing) unless config.migrations_folder?
|
13
|
+
|
14
|
+
migration_file = config.migration_file(now_timestamp, MIGRATION_NAME)
|
15
|
+
if prev_migration
|
16
|
+
FileUtils.mv(prev_migration, migration_file)
|
17
|
+
else
|
18
|
+
File.open(migration_file, 'wb') do |stream|
|
19
|
+
stream << ::Squasher::Render.render(MIGRATION_NAME, config)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
Squasher.rake("db:migrate", :db_cleaning)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def config
|
28
|
+
@config ||= Squasher::Config.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def prev_migration
|
32
|
+
return @prev_migration if defined?(@prev_migration)
|
33
|
+
|
34
|
+
@prev_migration = config.migration_files.detect do |file|
|
35
|
+
File.basename(file).include?(MIGRATION_NAME)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def now_timestamp
|
40
|
+
Time.now.strftime("%Y%m%d%H%M%S")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Squasher
|
5
|
+
class Config
|
6
|
+
def initialize
|
7
|
+
@root_path = Dir.pwd
|
8
|
+
end
|
9
|
+
|
10
|
+
def schema_file
|
11
|
+
@schema_file ||= from_root('db', 'schema.rb')
|
12
|
+
end
|
13
|
+
|
14
|
+
def migration_files
|
15
|
+
Dir.glob(File.join(migrations_folder, '**.rb'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def migration_file(timestamp, migration_name)
|
19
|
+
File.join(migrations_folder, "#{ timestamp }_#{ migration_name }.rb")
|
20
|
+
end
|
21
|
+
|
22
|
+
def migrations_folder?
|
23
|
+
Dir.exists?(migrations_folder)
|
24
|
+
end
|
25
|
+
|
26
|
+
def dbconfig?
|
27
|
+
!dbconfig.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
def stub_dbconfig
|
31
|
+
return unless dbconfig?
|
32
|
+
|
33
|
+
list = [dbconfig_file, schema_file]
|
34
|
+
list.each do |file|
|
35
|
+
next unless File.exists?(file)
|
36
|
+
FileUtils.mv file, "#{ file }.sbackup"
|
37
|
+
end
|
38
|
+
update_dbconfig_file
|
39
|
+
|
40
|
+
yield
|
41
|
+
|
42
|
+
ensure
|
43
|
+
list.each do |file|
|
44
|
+
next unless File.exists?("#{ file }.sbackup")
|
45
|
+
FileUtils.mv "#{ file }.sbackup", file
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
attr_reader :root_path
|
52
|
+
|
53
|
+
def from_root(*subfolders)
|
54
|
+
File.join(root_path, *subfolders)
|
55
|
+
end
|
56
|
+
|
57
|
+
def migrations_folder
|
58
|
+
@migrations_folder ||= from_root('db', 'migrate')
|
59
|
+
end
|
60
|
+
|
61
|
+
def dbconfig_file
|
62
|
+
@dbconfig_file ||= from_root('config', 'database.yml')
|
63
|
+
end
|
64
|
+
|
65
|
+
def dbconfig
|
66
|
+
return @dbconfig if defined?(@dbconfig)
|
67
|
+
return @dbconfig = nil unless File.exists?(dbconfig_file)
|
68
|
+
|
69
|
+
@dbconfig = YAML.load_file(dbconfig_file)['development']
|
70
|
+
if @dbconfig && !@dbconfig.empty?
|
71
|
+
@dbconfig['database'] = 'squasher'
|
72
|
+
@dbconfig = { 'development' => @dbconfig }
|
73
|
+
else
|
74
|
+
@dbconfig = nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def update_dbconfig_file
|
79
|
+
File.open(dbconfig_file, 'wb') { |stream| stream.write dbconfig.to_yaml }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"keep_database" : "Squasher created `:green{squasher}` database for it needs.\nIt might be useful if some deleted migration insert data into a database.\nLeft it(:green{yes} / :red{no})?",
|
3
|
+
|
4
|
+
"apply_clean": "Do you want to clean your database from an old schema migrations records(:red{yes}/:green{no})?",
|
5
|
+
|
6
|
+
"migration_folder_missing" : "The folder with migrations is missing.\nAre you sure in the :red{root of a rails} application?",
|
7
|
+
|
8
|
+
"no_migrations" : "There are no migrations in the folder prior :red{:date}",
|
9
|
+
|
10
|
+
"dbconfig_invalid" : "Squasher could not find `:green{database.yml}` with working development environment",
|
11
|
+
|
12
|
+
"db_create": "Squasher is creating a tmp database",
|
13
|
+
|
14
|
+
"db_migrate": "Squasher is appling a migrations on a tmp database",
|
15
|
+
|
16
|
+
"db_cleaning": "Squasher is appling a clean migration",
|
17
|
+
|
18
|
+
"usage": "Example usage:\n :green{squasher} :yellow{year[/month][/day]} #squash migrations prior to a specified date\n :green{squasher} :yellow{clean} #generate or update a cleaning migration and apply it\n :green{squasher} :yellow{info} #show this message"
|
19
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Squasher
|
4
|
+
class Render
|
5
|
+
def self.render(*args)
|
6
|
+
new(*args).render
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :name, :config
|
10
|
+
|
11
|
+
def initialize(name, config)
|
12
|
+
@name = name
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def render
|
17
|
+
ERB.new(template("#{ name }.rb"), nil, '-').result(binding)
|
18
|
+
end
|
19
|
+
|
20
|
+
def each_schema_line
|
21
|
+
File.open(config.schema_file, 'r') do |stream|
|
22
|
+
inside_schema = false
|
23
|
+
stream.each_line do |line|
|
24
|
+
if inside_schema
|
25
|
+
next if line.empty?
|
26
|
+
# reach eand of schema
|
27
|
+
break if line.index("end") == 0
|
28
|
+
yield line[2...-1]
|
29
|
+
else
|
30
|
+
inside_schema = true if line.include?("ActiveRecord::Schema")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def template(name)
|
39
|
+
path = File.join(File.dirname(__FILE__), "templates/#{ name }.erb")
|
40
|
+
template = File.open(path, "rb")
|
41
|
+
content = template.read
|
42
|
+
template.close
|
43
|
+
content
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class SquasherClean < ActiveRecord::Migration
|
2
|
+
class SchemaMigration < ActiveRecord::Base
|
3
|
+
end
|
4
|
+
|
5
|
+
def up
|
6
|
+
migrations = Dir.glob(File.join(File.dirname(__FILE__), '**.rb'))
|
7
|
+
versions = migrations.map { |file| file.split('/').last[/\A\d+/] }
|
8
|
+
SchemaMigration.where("version NOT IN (?)", versions).delete_all
|
9
|
+
end
|
10
|
+
|
11
|
+
def down
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Squasher
|
4
|
+
class Worker
|
5
|
+
attr_reader :date
|
6
|
+
|
7
|
+
def self.process(*args)
|
8
|
+
new(*args).process
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(date)
|
12
|
+
@date = date
|
13
|
+
end
|
14
|
+
|
15
|
+
def process
|
16
|
+
check!
|
17
|
+
|
18
|
+
result = under_squash_env do
|
19
|
+
File.open(config.migration_file(finish_timestamp, :init_schema), 'wb') do |stream|
|
20
|
+
stream << ::Squasher::Render.render(:init_schema, config)
|
21
|
+
end
|
22
|
+
|
23
|
+
migrations.each { |file| FileUtils.rm(file) }
|
24
|
+
|
25
|
+
Squasher.rake("db:drop") unless Squasher.ask(:keep_database)
|
26
|
+
end
|
27
|
+
Squasher.clean if result && Squasher.ask(:apply_clean)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def config
|
33
|
+
@config ||= ::Squasher::Config.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def check!
|
37
|
+
Squasher.error(:migration_folder_missing) unless config.migrations_folder?
|
38
|
+
Squasher.error(:dbconfig_invalid) unless config.dbconfig?
|
39
|
+
if migrations.empty?
|
40
|
+
print_date = date.strftime("%Y/%m/%d")
|
41
|
+
Squasher.error(:no_migrations, :date => print_date)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def migrations
|
46
|
+
return @migrations if @migrations
|
47
|
+
|
48
|
+
@migrations = config.migration_files.select { |file| before_date?(get_timestamp(file)) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_timestamp(file)
|
52
|
+
File.basename(file)[/\A\d+/]
|
53
|
+
end
|
54
|
+
|
55
|
+
def before_date?(timestamp)
|
56
|
+
@point ||= date.strftime("%Y%m%d").to_i
|
57
|
+
return unless timestamp
|
58
|
+
timestamp[0...8].to_i < @point
|
59
|
+
end
|
60
|
+
|
61
|
+
def finish_timestamp
|
62
|
+
@finish_timestamp ||= get_timestamp(migrations.last)
|
63
|
+
end
|
64
|
+
|
65
|
+
def under_squash_env
|
66
|
+
config.stub_dbconfig do
|
67
|
+
if Squasher.rake("db:drop db:create", :db_create) &&
|
68
|
+
Squasher.rake("db:migrate VERSION=#{ finish_timestamp }", :db_migrate)
|
69
|
+
yield
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
# This file is auto-generated from the current state of the database. Instead
|
3
|
+
# of editing this file, please use the migrations feature of Active Record to
|
4
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
5
|
+
#
|
6
|
+
# Note that this schema.rb definition is the authoritative source for your
|
7
|
+
# database schema. If you need to create the application database on another
|
8
|
+
# system, you should be using db:schema:load, not running all the migrations
|
9
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
10
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
11
|
+
#
|
12
|
+
# It's strongly recommended to check this file into your version control system.
|
13
|
+
|
14
|
+
ActiveRecord::Schema.define(:version => 20130613090053) do
|
15
|
+
|
16
|
+
create_table "cities", :force => true do |t|
|
17
|
+
t.string "name"
|
18
|
+
t.datetime "created_at", :null => false
|
19
|
+
t.datetime "updated_at", :null => false
|
20
|
+
end
|
21
|
+
|
22
|
+
create_table "managers", :force => true do |t|
|
23
|
+
t.string "email"
|
24
|
+
t.string "password_digest"
|
25
|
+
t.datetime "created_at", :null => false
|
26
|
+
t.datetime "updated_at", :null => false
|
27
|
+
end
|
28
|
+
|
29
|
+
create_table "offices", :force => true do |t|
|
30
|
+
t.string "name"
|
31
|
+
t.string "address"
|
32
|
+
t.string "phone"
|
33
|
+
t.text "description"
|
34
|
+
t.integer "capacity"
|
35
|
+
t.datetime "created_at", :null => false
|
36
|
+
t.datetime "updated_at", :null => false
|
37
|
+
t.integer "manager_id"
|
38
|
+
t.integer "city_id"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe Squasher::Cleaner do
|
5
|
+
let(:expected_file) { File.join(fake_root, 'db', 'migrate', '20140102030405_squasher_clean.rb') }
|
6
|
+
|
7
|
+
before do
|
8
|
+
Time.stub(:now => Time.new(2014, 1, 2, 3, 4, 5))
|
9
|
+
Squasher.stub(:rake).with("db:migrate", :db_cleaning)
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
FileUtils.rm(expected_file)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'create a new migration' do
|
17
|
+
Squasher::Cleaner.any_instance.stub(:prev_migration => nil)
|
18
|
+
Squasher.clean
|
19
|
+
|
20
|
+
expect(clean_migrations).to include(expected_file)
|
21
|
+
File.open(expected_file) do |stream|
|
22
|
+
content = stream.read
|
23
|
+
expect(content).to include("SquasherClean")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'update an existing migration' do
|
28
|
+
Squasher.clean
|
29
|
+
|
30
|
+
expect(clean_migrations.size).to be(1)
|
31
|
+
expect(clean_migrations.first).to eq(expected_file)
|
32
|
+
|
33
|
+
FileUtils.touch(File.join(fake_root, 'db/migrate/20140101010101_squasher_clean.rb'))
|
34
|
+
end
|
35
|
+
|
36
|
+
def clean_migrations
|
37
|
+
Dir.glob(File.join(fake_root, '**/*_squasher_clean.rb'))
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Squasher::Config do
|
4
|
+
let(:config) { described_class.new }
|
5
|
+
|
6
|
+
context '.dbconfig?' do
|
7
|
+
subject(:result) { config.dbconfig? }
|
8
|
+
|
9
|
+
it 'a file is exists and it has a valid content' do
|
10
|
+
expect(result).to be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'a file is exists but doesnt have a valid content' do
|
14
|
+
config.stub(:dbconfig_file => File.join(fake_root, 'config', 'invalid_database.yml'))
|
15
|
+
|
16
|
+
expect(result).to be_false
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'a file is not exists' do
|
20
|
+
config.stub(:dbconfig_file => File.join(fake_root, 'config', 'not_existed.yml'))
|
21
|
+
|
22
|
+
expect(result).to be_false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context '#stub_dbconfig' do
|
27
|
+
it 'add required db config file' do
|
28
|
+
config.stub_dbconfig do
|
29
|
+
File.open(File.join(fake_root, 'config', 'database.yml')) do |stream|
|
30
|
+
content = stream.read
|
31
|
+
expect(content).to include ("database: squasher")
|
32
|
+
expect(content).to include("development:")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'recover original schema and db config files if some error raised' do
|
38
|
+
begin
|
39
|
+
config.stub_dbconfig do
|
40
|
+
expect(file_exists?('config', 'database.yml')).to be_true
|
41
|
+
expect(file_exists?('config', 'database.yml.sbackup')).to be_true
|
42
|
+
|
43
|
+
raise RuntimeError, "Unexpected system error"
|
44
|
+
end
|
45
|
+
rescue RuntimeError
|
46
|
+
expect(file_exists?('config', 'database.yml')).to be_true
|
47
|
+
expect(file_exists?('config', 'database.yml.sbackup')).to be_false
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_exists?(*parts)
|
52
|
+
File.exists?(File.join(fake_root, *parts))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
specify { expect(config.migration_file(1230, :sample)).to eq(File.join(fake_root, 'db', 'migrate', '1230_sample.rb')) }
|
57
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe Squasher::Worker do
|
5
|
+
context 'failed on #check!' do
|
6
|
+
let(:worker) { described_class.new(Time.new(2012, 6, 20)) }
|
7
|
+
|
8
|
+
it 'command was run not in application root' do
|
9
|
+
Squasher::Config.any_instance.stub(:migrations_folder? => false)
|
10
|
+
|
11
|
+
expect_exit_with(:migration_folder_missing)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'db configuration is invalid' do
|
15
|
+
Squasher::Config.any_instance.stub(:dbconfig? => false)
|
16
|
+
|
17
|
+
expect_exit_with(:dbconfig_invalid)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'matched migrations was not found' do
|
21
|
+
expect_exit_with(:no_migrations, :date => "2012/06/20")
|
22
|
+
end
|
23
|
+
|
24
|
+
def expect_exit_with(*args)
|
25
|
+
expect(Squasher).to receive(:error).with(*args).and_call_original
|
26
|
+
expect { worker.process }.to raise_error(SystemExit)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'create a new squashed migration & remove selected migrations' do
|
31
|
+
worker = described_class.new(Time.new(2014))
|
32
|
+
worker.stub(:under_squash_env).and_yield.and_return(true)
|
33
|
+
new_migration_path = File.join(Dir.tmpdir, 'init_schema.rb')
|
34
|
+
Squasher::Config.any_instance.stub(:migration_file).with('2013122900', :init_schema).and_return(new_migration_path)
|
35
|
+
|
36
|
+
FileUtils.should_receive(:rm).with(File.join(fake_root, 'db', 'migrate', '201312090000_first_migration.rb'))
|
37
|
+
FileUtils.should_receive(:rm).with(File.join(fake_root, 'db', 'migrate', '2013122900_second_migration.rb'))
|
38
|
+
Squasher.should_receive(:ask).with(:keep_database).and_return(false)
|
39
|
+
Squasher.should_receive(:rake).with("db:drop")
|
40
|
+
Squasher.should_receive(:ask).with(:apply_clean).and_return(true)
|
41
|
+
Squasher.should_receive(:clean)
|
42
|
+
|
43
|
+
worker.process
|
44
|
+
|
45
|
+
expect(File.exists?(new_migration_path)).to be_true
|
46
|
+
File.open(new_migration_path) do |stream|
|
47
|
+
content = stream.read
|
48
|
+
expect(content).to include("InitSchema")
|
49
|
+
expect(content).to include('create_table "managers", :force => true do |t|')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Squasher do
|
4
|
+
context '.squash' do
|
5
|
+
specify { expected_covert("2013/12/23", Time.new(2013, 12, 23)) }
|
6
|
+
specify { expected_covert("2013", Time.new(2013, 1, 1)) }
|
7
|
+
|
8
|
+
def expected_covert(input, expected)
|
9
|
+
expect(Squasher::Worker).to receive(:process).with(expected)
|
10
|
+
Squasher.squash(input)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.require
|
3
|
+
|
4
|
+
def fake_root
|
5
|
+
@fake_root ||= File.join(File.dirname(__FILE__), 'fake_app')
|
6
|
+
end
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.order = 'random'
|
10
|
+
config.before do
|
11
|
+
Squasher::Config.any_instance.stub(:root_path => fake_root)
|
12
|
+
end
|
13
|
+
end
|
data/squasher.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'squasher/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "squasher"
|
8
|
+
spec.version = Squasher::VERSION
|
9
|
+
spec.authors = ["Sergey Pchelincev"]
|
10
|
+
spec.email = ["mail@sergeyp.me"]
|
11
|
+
spec.description = %q{Squash your old migrations}
|
12
|
+
spec.summary = %q{Squash your old migrations}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", ">= 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec", ">= 2.14"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: squasher
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sergey Pchelincev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '2.14'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '2.14'
|
55
|
+
description: Squash your old migrations
|
56
|
+
email:
|
57
|
+
- mail@sergeyp.me
|
58
|
+
executables:
|
59
|
+
- squasher
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- .gitignore
|
64
|
+
- .rspec
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE.txt
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- bin/squasher
|
70
|
+
- lib/squasher.rb
|
71
|
+
- lib/squasher/cleaner.rb
|
72
|
+
- lib/squasher/config.rb
|
73
|
+
- lib/squasher/messages.json
|
74
|
+
- lib/squasher/render.rb
|
75
|
+
- lib/squasher/templates/init_schema.rb.erb
|
76
|
+
- lib/squasher/templates/squasher_clean.rb.erb
|
77
|
+
- lib/squasher/version.rb
|
78
|
+
- lib/squasher/worker.rb
|
79
|
+
- spec/fake_app/config/database.yml
|
80
|
+
- spec/fake_app/config/invalid_database.yml
|
81
|
+
- spec/fake_app/db/migrate/201312090000_first_migration.rb
|
82
|
+
- spec/fake_app/db/migrate/2013122900_second_migration.rb
|
83
|
+
- spec/fake_app/db/migrate/20140101010101_squasher_clean.rb
|
84
|
+
- spec/fake_app/db/migrate/20140110_third_migration.rb
|
85
|
+
- spec/fake_app/db/schema.rb
|
86
|
+
- spec/lib/squasher/cleaner_spec.rb
|
87
|
+
- spec/lib/squasher/config_spec.rb
|
88
|
+
- spec/lib/squasher/worker_spec.rb
|
89
|
+
- spec/lib/squasher_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
- squasher.gemspec
|
92
|
+
homepage: ''
|
93
|
+
licenses:
|
94
|
+
- MIT
|
95
|
+
metadata: {}
|
96
|
+
post_install_message:
|
97
|
+
rdoc_options: []
|
98
|
+
require_paths:
|
99
|
+
- lib
|
100
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 2.0.14
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: Squash your old migrations
|
116
|
+
test_files:
|
117
|
+
- spec/fake_app/config/database.yml
|
118
|
+
- spec/fake_app/config/invalid_database.yml
|
119
|
+
- spec/fake_app/db/migrate/201312090000_first_migration.rb
|
120
|
+
- spec/fake_app/db/migrate/2013122900_second_migration.rb
|
121
|
+
- spec/fake_app/db/migrate/20140101010101_squasher_clean.rb
|
122
|
+
- spec/fake_app/db/migrate/20140110_third_migration.rb
|
123
|
+
- spec/fake_app/db/schema.rb
|
124
|
+
- spec/lib/squasher/cleaner_spec.rb
|
125
|
+
- spec/lib/squasher/config_spec.rb
|
126
|
+
- spec/lib/squasher/worker_spec.rb
|
127
|
+
- spec/lib/squasher_spec.rb
|
128
|
+
- spec/spec_helper.rb
|
129
|
+
has_rdoc:
|