db-migrate 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9d20012ab53ae15b7b98fec15bb8eae3abd9914e
4
+ data.tar.gz: e02941b8c31643efaa71774d67b22aba0c4f2bc8
5
+ SHA512:
6
+ metadata.gz: 6d316f5e858dcdfad7e16449cd78abf3a8a44e51111cb26411467d89bdbaf2cf8900728abebe1f697d05b6553e1dd8839400957ba310d9bb4e4b6066625c13ce
7
+ data.tar.gz: 8538758ab5dc8d23e9b1923b777187cbb7321d58e7efbe97bd26aa3fca37f32a033bfe795bb6d56f2830e46d9141fc3ee85572cf1a42ade898fe19dd5cc822a6
@@ -0,0 +1,3 @@
1
+ *.conf
2
+ *.config
3
+ spec/lib/fixtures/v*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1
6
+ - 2.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gemspec
5
+
6
+ gem "rspec"
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ migrate (0.0.1)
5
+ colorize (= 0.7.7)
6
+ highline (= 1.7.8)
7
+ json (= 1.8.3)
8
+ mysql2 (= 0.4.2)
9
+ parseconfig (= 1.0.6)
10
+ pg (= 0.18.4)
11
+ thor (= 0.19.1)
12
+
13
+ GEM
14
+ remote: https://rubygems.org/
15
+ specs:
16
+ colorize (0.7.7)
17
+ diff-lcs (1.2.5)
18
+ highline (1.7.8)
19
+ json (1.8.3)
20
+ mysql2 (0.4.2)
21
+ parseconfig (1.0.6)
22
+ pg (0.18.4)
23
+ rspec (3.4.0)
24
+ rspec-core (~> 3.4.0)
25
+ rspec-expectations (~> 3.4.0)
26
+ rspec-mocks (~> 3.4.0)
27
+ rspec-core (3.4.1)
28
+ rspec-support (~> 3.4.0)
29
+ rspec-expectations (3.4.0)
30
+ diff-lcs (>= 1.2.0, < 2.0)
31
+ rspec-support (~> 3.4.0)
32
+ rspec-mocks (3.4.0)
33
+ diff-lcs (>= 1.2.0, < 2.0)
34
+ rspec-support (~> 3.4.0)
35
+ rspec-support (3.4.1)
36
+ thor (0.19.1)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ migrate!
43
+ rspec
44
+
45
+ BUNDLED WITH
46
+ 1.10.6
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Ivan Pusic
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,60 @@
1
+ # migrate
2
+
3
+ Tool for managing and executing your database migrations.
4
+
5
+ ### How it works?
6
+ It saves metadata about your migrations to database. It uses that metadata for executing and creating new migrations.
7
+
8
+ It supports multiple databases and multiple languages for executing migrations.
9
+
10
+ #### Supported databases
11
+ - PostgreSQL
12
+ - MySQL
13
+
14
+ #### Supported languages
15
+ - SQL
16
+ - Ruby
17
+ - Python
18
+ - Javascript (Node.js)
19
+ - Go
20
+
21
+ ### What I can do with it?
22
+ ```
23
+ Commands:
24
+ migrate init # make configuration file
25
+ migrate new [DESCRIPTION] # generate files for new migration
26
+ migrate up # Upgrade database schema
27
+ migrate down # Downgrade database schema
28
+ migrate list # Show list of all migrations
29
+ migrate delete [VERSION] # Will delete migration data
30
+ migrate version # Show current version
31
+ migrate help [COMMAND] # Describe available commands or one specific
32
+ Options:
33
+ -r, [--root=ROOT] # Sepcify migration root directory, where config file is located
34
+ # Default: .
35
+ -c, [--config=CONFIG] # Specify custom configuration file name
36
+ # Default: migrate.conf
37
+ ```
38
+
39
+ ### How to use it?
40
+
41
+ First thing you have to do is to make initial configuration with **migrate init** command.
42
+ After that you can start generating migrations by using **migrate new** command. This will generate migration script for you based on your prefered language.
43
+
44
+ When you are done with writing your `up` and `down` migration script, you can execute **migrate up** to run up migration script for new version. You can also execute multiple migrations in single call by providing `--to n` argument, where `n` is highest version where you want to navigate.
45
+
46
+ You can also use **migrate down** to go one version back. `down` comand also accepts `--to n` argument, but in this case `n` is lowest version where you want to navigate.
47
+
48
+ If you are asking yourself about current version, use **migrate version** to find out current version.
49
+
50
+ If you don't need some migration, use **migrate delete n** to remove version `n`.
51
+
52
+ You can see list of your migrations by running **migrate list**. This command also provides some additional options for filtering results.
53
+
54
+ ## Contributing
55
+ - do ruby magic
56
+ - write tests!
57
+ - send pull request
58
+
59
+ ## License
60
+ *MIT*
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "thor"
4
+ require "json"
5
+ require "highline"
6
+ require_relative "../lib/migrate"
7
+
8
+ include Migrate
9
+ $asker = HighLine.new
10
+
11
+ class CLI < Thor
12
+ method_option :root, {
13
+ :aliases => "-r",
14
+ :default => ".",
15
+ :desc => "Sepcify migration root directory, where config file is located"
16
+ }
17
+ method_option :config, {
18
+ :aliases => "-c",
19
+ :default => "migrate.conf",
20
+ :desc => "Specify custom configuration file name"
21
+ }
22
+ def initialize(*args)
23
+ super
24
+ @config = Config.new(options["root"], options["config"])
25
+
26
+ init_invoked = ARGV.length > 0 && ARGV[0] == "init"
27
+ if not init_invoked and @config.exists?
28
+ @config.load!
29
+ @migrator = Migrator.new(@config)
30
+ elsif not init_invoked
31
+ Log.error("Configuration not found in `#{Pathname.new(@config.root).expand_path}`. " \
32
+ "Make sure you are in right directory or " \
33
+ "run `migrate init` to create configuration.")
34
+ exit
35
+ end
36
+ end
37
+
38
+ desc "init", "make configuration file"
39
+ def init
40
+ Log.info("Creating configuration...")
41
+
42
+ storage = nil
43
+ $asker.choose do |menu|
44
+ menu.prompt = "Which database do you prefer?"
45
+
46
+ menu.choice(:mysql) { storage = "mysql" }
47
+ menu.choices(:pg) { storage = "pg" }
48
+ end
49
+
50
+ db_defaults = case storage
51
+ when "mysql"
52
+ { :port => "3306", :user => "root" }
53
+ when "pg"
54
+ { :port => "5432", :user => "postgres" }
55
+ end
56
+
57
+ lang = nil
58
+ $asker.choose do |menu|
59
+ menu.prompt = "What language would you like use for your migration scripts?"
60
+
61
+ menu.choice(:sql) { lang = "sql" }
62
+ menu.choices(:ruby) { lang = "ruby" }
63
+ menu.choice(:javascript) { lang = "javascript" }
64
+ menu.choice(:go) { lang = "go" }
65
+ menu.choice(:python) { lang = "python" }
66
+ end
67
+
68
+ config = {
69
+ storage: storage,
70
+ lang: lang,
71
+ host: $asker.ask("Host: ") {|q| q.default = "localhost"},
72
+ port: ($asker.ask("Port: ") {|q| q.default = db_defaults[:port]}).to_i,
73
+ database: $asker.ask("Database Name: ") {|q| q.default = "mydb"},
74
+ user: $asker.ask("User: ") {|q| q.default = db_defaults[:user]},
75
+ password: $asker.ask("Password: ") {|q| q.default = nil},
76
+ version_info: $asker.ask("Version info table: ") {|q| q.default = "version_info"},
77
+ version_number: $asker.ask("Version number table: ") {|q| q.default = "version_number"}
78
+ }
79
+
80
+ @config.init(config)
81
+ @config.load!
82
+ Migrator.new(@config).init
83
+ rescue Exception => e
84
+ Log.error("Error while initialization.", e)
85
+ @config.remove
86
+ exit
87
+ end
88
+
89
+ desc "new [DESCRIPTION]", "generate files for new migration"
90
+ def new(description="")
91
+ @migrator.new(description)
92
+ end
93
+
94
+ desc "up", "Upgrade database schema"
95
+ option :to, :aliases => "-t", :desc => "Upgrade to the version"
96
+ def up
97
+ @migrator.up(options[:to])
98
+ rescue VersionNotFound => e
99
+ Log.error("Next version not found.")
100
+ rescue Exception => e
101
+ Log.error("Error while migrating up.", e)
102
+ end
103
+
104
+ desc "down [TO_VERSION]", "Downgrade database schema"
105
+ option :to, :aliases => "-t", :desc => "Downgrade back to the version"
106
+ def down
107
+ @migrator.down(options[:to])
108
+ rescue VersionNotFound => e
109
+ Log.error("Previous version not found.")
110
+ rescue Exception => e
111
+ Log.error("Error while migrating down.", e)
112
+ end
113
+
114
+ desc "list", "Show list of all migrations"
115
+ option :limit, :aliases => "-l", :desc => "Limit results"
116
+ option :select, :aliases => "-s", :desc => "Columns to select"
117
+ def list()
118
+ @migrator.list(options[:select], options[:limit])
119
+ end
120
+
121
+ desc "delete [VERSION]", "Will delete migration data"
122
+ def delete(version)
123
+ @migrator.delete(version.to_i)
124
+ rescue VersionNotFound
125
+ Log.error("Version not found.")
126
+ rescue Exception => e
127
+ Log.error("Error while removing migration.", e)
128
+ end
129
+
130
+ desc "version", "Show current version"
131
+ def version()
132
+ Log.version(@migrator.current_version())
133
+ end
134
+ end
135
+
136
+ CLI.start
@@ -0,0 +1,9 @@
1
+ require_relative "./migrate/logger"
2
+ require_relative "./migrate/config"
3
+ require_relative "./migrate/storage"
4
+ require_relative "./migrate/lang"
5
+ require_relative "./migrate/migrator"
6
+ require_relative "./migrate/errors"
7
+
8
+ module Migrate
9
+ end
@@ -0,0 +1,104 @@
1
+ require "parseconfig"
2
+
3
+ module Migrate
4
+ class Config
5
+ attr_reader :root
6
+
7
+ def initialize(root, file)
8
+ @root = root
9
+ @file=file
10
+ @file_path = "#{root}/#{file}"
11
+ @loaded = false
12
+ end
13
+
14
+ def exists?
15
+ File.exist? @file_path
16
+ end
17
+
18
+ def init(config)
19
+ if not Dir.exist? @root
20
+ Dir.mkdir @root
21
+ end
22
+
23
+ File.open(@file_path, "w") do |f|
24
+ config.map do |key, value|
25
+ f.puts "#{key}=#{value}\n"
26
+ end
27
+ end
28
+
29
+ Log.success("Configuration file created. Location: `#{@file_path}`")
30
+ end
31
+
32
+ def load!
33
+ Log.info("Loading configuration...")
34
+ config = ParseConfig.new(@file_path)
35
+
36
+ config.get_params.map do |param|
37
+ self.class.send(:attr_reader, param)
38
+ instance_variable_set("@#{param}", config[param])
39
+ end
40
+
41
+ @loaded = true
42
+ Log.success("Configuration loaded.")
43
+ end
44
+
45
+ def delete
46
+ File.delete @file_path
47
+ rescue Exception => e
48
+ Log.error("Error while removing configuration file.", e)
49
+ exit
50
+ end
51
+
52
+ def get_db
53
+ case @storage
54
+ when "pg"
55
+ if @pg == nil
56
+ @pg = Storage::Postgres.new(self)
57
+ end
58
+
59
+ @pg
60
+ when "mysql"
61
+ if @mysql == nil
62
+ @mysql = Storage::Mysql.new(self)
63
+ end
64
+
65
+ @mysql
66
+ end
67
+ end
68
+
69
+ def get_lang
70
+ case @lang
71
+ when "sql"
72
+ if @sql == nil
73
+ @sql = Lang::Sql.new(get_db)
74
+ end
75
+
76
+ @sql
77
+ when "javascript"
78
+ if @javascript == nil
79
+ @javascript = Lang::Javascript.new
80
+ end
81
+
82
+ @javascript
83
+ when "ruby"
84
+ if @ruby == nil
85
+ @ruby = Lang::Ruby.new
86
+ end
87
+
88
+ @ruby
89
+ when "go"
90
+ if @go == nil
91
+ @go = Lang::Go.new
92
+ end
93
+
94
+ @go
95
+ when "python"
96
+ if @python == nil
97
+ @python = Lang::Python.new
98
+ end
99
+
100
+ @python
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,4 @@
1
+ module Migrate
2
+ class VersionNotFound < StandardError
3
+ end
4
+ end
@@ -0,0 +1,10 @@
1
+ module Migrate
2
+ module Lang
3
+ require_relative "./lang/lang"
4
+ require_relative "./lang/sql"
5
+ require_relative "./lang/javascript"
6
+ require_relative "./lang/ruby"
7
+ require_relative "./lang/go"
8
+ require_relative "./lang/python"
9
+ end
10
+ end
@@ -0,0 +1,37 @@
1
+ module Migrate
2
+ module Lang
3
+ class Go < Lang
4
+ def initialize
5
+ @ext = "go"
6
+ end
7
+
8
+ def create_migration(dir)
9
+ File.open("#{dir}/up.#{@ext}", "w") do |f|
10
+ f.puts <<-eot
11
+ package main
12
+
13
+ func main() {
14
+ // Here goes your Go migration forward
15
+ }
16
+ eot
17
+ end
18
+
19
+ File.open("#{dir}/down.#{@ext}", "w") do |f|
20
+ f.puts <<-eot
21
+ package main
22
+
23
+ func main() {
24
+ // Here goes your Go migration backward
25
+ }
26
+ eot
27
+ end
28
+ end
29
+
30
+ def exec_migration(dir, is_up)
31
+ script = "#{dir}/#{is_up ? "up" : "down"}.#{@ext}"
32
+ Log.info("Executing #{script}...")
33
+ `go run #{script}`
34
+ end
35
+ end
36
+ end
37
+ end