migr8 0.4.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.
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 kuwata-lab.com
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,356 @@
1
+ Migr8.rb
2
+ ========
3
+
4
+ Migr8.rb is a database schema version management tool.
5
+
6
+ * Easy to install, easy to setup, and easy to start
7
+ * No configuration file; instead, only two environment variables
8
+ * Designed carefully to suit Git or Mercurial
9
+ * Supports SQLite3, PostgreSQL, and MySQL
10
+ * Written in Ruby (>= 1.8)
11
+
12
+
13
+ Quick Start
14
+ -----------
15
+
16
+ 1. Donwload migr8.rb.
17
+
18
+ $ curl -Lo migr8.rb http://bit.ly/migr8_rb
19
+ $ chmod a+x migr8.rb
20
+ ### or
21
+ $ gem install migr8
22
+
23
+ 2. Set environment variables: $MIGR8_COMMAND and $MIGR8_EDITOR.
24
+
25
+ $ export MIGR8_COMMAND="sqlite3 dbfile1" # for SQLite3
26
+ $ export MIGR8_COMMAND="psql -q -U user1 dbname1" # for PostgreSQL
27
+ $ export MIGR8_COMMAND="mysql -s -u user1 dbname1" # for MySQL
28
+
29
+ $ export MIGR8_EDITOR="open -a TextMate" # for TextMate (MacOSX)
30
+ $ export MIGR8_EDITOR="emacsclient" # for Emacs
31
+ $ export MIGR8_EDITOR="vim" # for Vim
32
+
33
+ 3. Create managiment files and table.
34
+
35
+ $ ./migr8.rb init # create files in current directory,
36
+ # and create a table in DB.
37
+
38
+ 4. Now you can manage DB schema versions.
39
+
40
+ $ ./migr8.rb # show current status
41
+ $ ./migr8.rb new -m "create 'users' table" # create a migration
42
+ # or ./migr8.rb new --table=users
43
+ $ ./migr8.rb # show status again
44
+ $ ./migr8.rb up # apply migration
45
+ $ ./migr8.rb # show status again
46
+ $ ./migr8.rb hist # list history
47
+
48
+ 5. You may got confliction error when `git rebase` or `git pull`.
49
+ In this case, you must resolve it by hand.
50
+ (This is intended design.)
51
+
52
+ $ git rebase master # confliction!
53
+ $ ./migr8.rb hist -o # open 'migr8/history.txt', and
54
+ # resolve confliction manually
55
+ $ ./migr8.rb hist # check whether history file is valid
56
+ $ git add migr8/history.txt
57
+ $ git rebase --continue
58
+
59
+
60
+ Templating
61
+ ----------
62
+
63
+ (!!Attention!! this is experimental feature and may be changed in the future.)
64
+
65
+ It is possible to embed eRuby code into `up` and `down` scripts.
66
+
67
+ Syntax:
68
+
69
+ * `<% ... %>` : Ruby statement
70
+ * `<%= ... %>` : Ruby expression, escaping `'` into `''` (or `\'` on MySQL)
71
+ * `<%== ... %>` : Ruby expression, no escaping
72
+
73
+ For example:
74
+
75
+ vars:
76
+ - table: users
77
+
78
+ up: |
79
+ insert into ${table}(name) values
80
+ <% comma = " " %>
81
+ <% for name in ["Haruhi", "Mikuru", "Yuki"] %>
82
+ <%= comma %>('<%= name %>')
83
+ <% comma = ", " %>
84
+ <% end %>
85
+ ;
86
+
87
+ down: |
88
+ <% for name in ["Haruhi", "Mikuru", "Yuki"] %>
89
+ delete from ${table} where name = '<%= name %>';
90
+ <% end %>
91
+
92
+ The above is the same as the following:
93
+
94
+ up: |
95
+ insert into users(name) values
96
+ ('Haruhi')
97
+ , ('Mikuru')
98
+ , ('Yuki')
99
+ ;
100
+
101
+ down: |
102
+ delete from users where name = 'Haruhi';
103
+ delete from users where name = 'Mikuru';
104
+ delete from users where name = 'Yuki';
105
+
106
+ In eRuby code, values in `vars` are available as instance variables.
107
+ For example:
108
+
109
+ version: uhtu4853
110
+ desc: register members
111
+ author: kyon
112
+ vars:
113
+ - table: users
114
+ - members: [Haruhi, Mikuru, Yuki]
115
+
116
+ up: |
117
+ <% for member in @members %>
118
+ insert into ${table}(name) values ('<%= member %>');
119
+ <% end %>
120
+
121
+ down: |
122
+ <% for member in @members %>
123
+ delete from ${table} where name = '<%= member %>';
124
+ <% end %>
125
+
126
+ If you want to see up and down scripts rendered, run `migr8.rb show` action.
127
+ For example:
128
+
129
+ $ ./migr8.rb show uhtu4853
130
+ version: uhtu4853
131
+ desc: register members
132
+ author: kyon
133
+ vars:
134
+ - table: "users"
135
+ - members: ["Haruhi", "Mikuru", "Yuki"]
136
+
137
+ up: |
138
+ insert into users(name) values ('Haruhi');
139
+ insert into users(name) values ('Mikuru');
140
+ insert into users(name) values ('Yuki');
141
+
142
+ down: |
143
+ delete from users where name = 'Haruhi';
144
+ delete from users where name = 'Mikuru';
145
+ delete from users where name = 'Yuki';
146
+
147
+
148
+ Notice that migration file using eRuby code is not compatible with other
149
+ Migr8 implemtation.
150
+
151
+
152
+ Tips
153
+ ----
154
+
155
+ * `migr8.rb up -a` applys all migrations, while `migr8.rb up` applys a
156
+ migration.
157
+
158
+ * `migr8.rb -D up` saves SQL executed into `migr8/history.txt` file.
159
+
160
+ * `migr8.rb redo` is equivarent to `migr8.rb down; migr8.rb up`.
161
+
162
+ * `migr8.rb new -p` generates migration file with plain skeleton, and
163
+ `migr8.rb new --table=name` generates with table name.
164
+
165
+ * `migr8.rb unapply -x` unapplies migration which is applied in DB but
166
+ corresponding migration file doesn't exist.
167
+ (Describing in detail, `migr8.rb unapply -x abcd1234` runs `down` script
168
+ in `_migr_history` table, while `migr8.rb unapply abcd1234` runs `down`
169
+ script in `migr8/migrations/abcd1234.yaml` file.)
170
+ This may help you when switching Git/Hg branch.
171
+
172
+ * `migr8.rb` generates sql file and run it with sql command such as `psql`
173
+ (PostgreSQL), `sqlite3` (SQLite3) or `mysql` (MySQL). Therefore you can
174
+ use non-sql command in migration file.
175
+ For example:
176
+
177
+ up: |
178
+ -- read data from CSV file and insert into DB (PostgreSQL)
179
+ \copy table1 from 'file1.csv' with csv;
180
+
181
+ * **MySQL doesn't support transactional DDL**.
182
+ It will cause troubles when you have errors in migration script
183
+ (See https://www.google.com/search?q=transactional+DDL for details).
184
+ On the other hand, SQLite3 and PostgreSQL support transactional DDL,
185
+ and DDL will be rollbacked when error occurred in migration script.
186
+ Very good.
187
+
188
+
189
+ <!--
190
+
191
+ Trouble Shooting
192
+ ----------------
193
+
194
+ * Command `migr8.rb unapply -x` unapplies migration which is applied in DB
195
+ but it's migration file doesn't exist in 'migr8/migrations' directory.
196
+ You may face this case when switching Git branch.
197
+
198
+ There can be migrations which are applied in DB but migration file does
199
+ not exit in 'migr8/migrations' directory. You my face this case when
200
+ switching Git/Hg branch.
201
+
202
+ For example, the following shows that migration 'uhtu4853' is applied
203
+ in DB, but file 'migr8/migrations/uhtu4853.yaml' does not exist.
204
+
205
+ $ ./migr8.rb
206
+ ## Status: all applied
207
+ ## Recent history:
208
+ ssgc3376 2013-11-18 10:04:40 # [kwatch] create 'groups' table
209
+ ## !!! The following migrations are applied to DB, but files are not found.
210
+ ## !!! (Try `migr8.rb unapply -x abcd1234` to unapply them.)
211
+ uhtu4853 2013-11-18 10:04:46 # [kwatch] create 'users' table
212
+
213
+ You may try to unapply 'uhtu4853', but will be refused because migration
214
+ file does not exist.
215
+
216
+ $ ./migr8.rb unapply uhtu4853
217
+ ERROR[migr8.rb] unapply: uhtu4853: no such version in history file.
218
+
219
+ In this case, `migr8.rb new -x` is the answer.
220
+
221
+ $ ./migr8.rb unapply -x uhtu4853
222
+ ## unapplying uhtu4853 # [kwatch] create 'users' table
223
+ $ ./migr8.rb
224
+ ## Status: all applied
225
+ ## Recent history:
226
+ ssgc3376 2013-11-20 10:04:46 # [kwatch] create 'groups' table
227
+
228
+ -->
229
+
230
+
231
+ Usage and Actions
232
+ -----------------
233
+
234
+ Usage: migr8.rb [global-options] [action [options] [...]]
235
+ -h, --help : show help
236
+ -v, --version : show version
237
+ -D, --debug : not remove sql file ('migr8/tmp.sql') for debug
238
+
239
+ Actions: (default: status)
240
+ readme : !!READ ME AT FIRST!!
241
+ help [action] : show help message of action, or list action names
242
+ init : create necessary files and a table
243
+ hist : list history of versions
244
+ -o : open history file with $MIGR8_EDITOR
245
+ -b : rebuild history file from migration files
246
+ new : create new migration file and open it by $MIGR8_EDITOR
247
+ -m text : description message (mandatory)
248
+ -u user : author name (default: current user)
249
+ -v version : specify version number instead of random string
250
+ -p : plain skeleton
251
+ -e editor : editr command (such as 'emacsclient', 'open', ...)
252
+ --table=table : skeleton to create table
253
+ --column=tbl.col : skeleton to add column
254
+ --index=tbl.col : skeleton to create index
255
+ --unique=tbl.col : skeleton to add unique constraint
256
+ show [version] : show migration file with expanding variables
257
+ -x : load values of migration from history table in DB
258
+ edit [version] : open migration file by $MIGR8_EDITOR
259
+ -r N : edit N-th file from latest version
260
+ -e editor : editr command (such as 'emacsclient', 'open', ...)
261
+ status : show status
262
+ up : apply next migration
263
+ -n N : apply N migrations
264
+ -a : apply all migrations
265
+ down : unapply current migration
266
+ -n N : unapply N migrations
267
+ --ALL : unapply all migrations
268
+ redo : do migration down, and up it again
269
+ -n N : redo N migrations
270
+ --ALL : redo all migrations
271
+ apply version ... : apply specified migrations
272
+ unapply version ... : unapply specified migrations
273
+ -x : unapply versions with down-script in DB, not in file
274
+ delete version ... : delete unapplied migration file
275
+ --Imsure : you must specify this option to delete migration
276
+
277
+
278
+ TODO
279
+ ----
280
+
281
+ * [_] write more tests
282
+ * [_] test on windows
283
+ * [_] implement in Python
284
+ * [_] implement in JavaScript
285
+
286
+
287
+ Changes
288
+ -------
289
+
290
+ ### Release 0.4.0 (2013-11-28) ###
291
+
292
+ * [enhance] RubyGems package available.
293
+ You can install migr8.rb by `gem install migr8`.
294
+ * [enhance] eRuby templating `up` and `down` script.
295
+ See 'Templating' section of README file for details.
296
+ * [enhance] Add new action 'show' which shows migration attributes
297
+ with expanding variables (ex: `${table}`) and renderting template.
298
+ * [enhance] Add new action 'delete' which deletes unapplied migration file.
299
+ Note: this action can't delete migration which is already applied.
300
+ * [enhance] Add new option 'new -v version' in order to specify version
301
+ number by yourself instead of auto-generated random string.
302
+ * [bufix] Action 'edit version' now can open migration file even when
303
+ version number in migration file is wrong.
304
+
305
+
306
+ ### Release 0.3.1 (2013-11-24) ###
307
+
308
+ * [bugfix] Fix 'hist' action not to raise error.
309
+
310
+
311
+ ### Release 0.3.0 (2013-11-22) ###
312
+
313
+ * [enhance] Add `-x` option to `unapply` action which unapplies migrations
314
+ by down-script in DB, not in migration file.
315
+ You can unapply migrations which files are missing in some reason.
316
+ * [change] Eliminate indentation from output of 'readme' action.
317
+
318
+
319
+ ### Release 0.2.1 (2013-11-20) ###
320
+
321
+ * [bugfix] Fix `new --table=name` action to set table name correctly
322
+
323
+
324
+ ### Release 0.2.0 (2013-11-14) ###
325
+
326
+ * [enhance] Add new options to `new` action for some skeletons
327
+ * `new --table=table` : create table
328
+ * `new --column=tbl.col` : add column to table
329
+ * `new --index=tbl.col` : create index on column
330
+ * `new --unique=tbl.col` : add unique constraint on column
331
+ * [enhance] Add new option `hist -b` action which re-generate history file.
332
+ * [change] Change several error messages
333
+ * [change] Tweak SQL generated on SQLite3
334
+
335
+
336
+ ### Release 0.1.1 (2013-11-12) ###
337
+
338
+ * [IMPORTANT] Change history table schema: SORRY, YOU MUST RE-CREATE HISTORY TABLE.
339
+ * [enhance] Fix 'up' action to save both up and down script into history table.
340
+
341
+
342
+ ### Release 0.1.0 (2013-11-11) ###
343
+
344
+ * Public release
345
+
346
+
347
+ License
348
+ -------
349
+
350
+ $License: MIT License $
351
+
352
+
353
+ Copyright
354
+ ---------
355
+
356
+ $Copyright: copyright(c) 2013 kuwata-lab.com all rights reserved $
@@ -0,0 +1,133 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ project = "migr8"
4
+ release = ENV['RELEASE'] || "0.4.0"
5
+ copyright = "copyright(c) 2013 kuwata-lab.com all rights reserved"
6
+ license = "MIT License"
7
+
8
+ require 'fileutils'
9
+ include FileUtils
10
+
11
+ require 'rake/clean'
12
+ CLEAN.include("build/#{project}-#{release}")
13
+ CLOBBER.include("build")
14
+
15
+
16
+ task :default => :test
17
+
18
+ def _do_test
19
+ Dir.glob('test/*_test.rb').each do |fname|
20
+ sh "ruby #{fname} -sp"
21
+ end
22
+ end
23
+
24
+ desc "do test"
25
+ task :test do
26
+ _do_test()
27
+ end
28
+
29
+ desc "do test for 1.8.6, 1.8.7, and 1.9.2"
30
+ task :test_all do
31
+ orig_path = ENV['PATH']
32
+ %w[1.8.6-p369 1.8.7-p334 1.9.2-p180].each do |ruby_ver|
33
+ ruby_path = "/usr/local/ruby/#{ruby_ver}/bin"
34
+ ENV['PATH'] = ruby_path + ':' + orig_path
35
+ puts "*** ruby_path=#{ruby_path}"
36
+ sh "ruby -v"
37
+ _do_test()
38
+ end
39
+ end
40
+
41
+
42
+ desc "embed 'README.md' into 'lib/migr8.rb'"
43
+ task :readme do
44
+ content = File.read('README.md')
45
+ content.gsub!(/^ /, '')
46
+ content.gsub!(/\n\n<!--.*\n-->\n/m, '')
47
+ File.open('lib/migr8.rb', 'r+') do |f|
48
+ text = f.read()
49
+ text.sub!(/('README_DOCUMENT'\n)(.*)(^README_DOCUMENT\n)/m) {
50
+ "'README_DOCUMENT'\n#{content}README_DOCUMENT\n"
51
+ }
52
+ f.rewind()
53
+ f.truncate(0)
54
+ f.write(text)
55
+ end
56
+ end
57
+
58
+
59
+ def edit_files(*filenames, &block)
60
+ filenames.flatten.each do |fname|
61
+ Dir.glob(fname).each do |fpath|
62
+ next unless File.file?(fpath)
63
+ s = File.open(fpath, 'rb') {|f| f.read() }
64
+ s = block.arity == 2 ? yield(s, fpath) : yield(s)
65
+ File.open(fpath, 'wb') {|f| f.write(s) }
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+ desc "update '$Release$', '$License$', and '$Copyright$'"
72
+ task :edit do
73
+ files = ['README.md', 'MIT-LICENSE', 'lib/*.rb', 'bin/*.rb', 'test/*.rb', 'migr8.gemspec']
74
+ edit_files(files) do |s, filename|
75
+ next s if filename == 'test/oktest.rb'
76
+ next s if filename == 'Rakefile'
77
+ s.gsub!(/\$Release:.*\$/, "$Release: #{release} $")
78
+ s.gsub!(/\$License:.*\$/, "$License: #{license} $")
79
+ s.gsub!(/\$Copyright:.*\$/, "$Copyright: #{copyright} $")
80
+ s.gsub!(/\$Release\$/, release)
81
+ s.gsub!(/\$License\$/, license)
82
+ s.gsub!(/\$Copyright\$/, copyright)
83
+ s
84
+ end
85
+ end
86
+
87
+
88
+ desc "copy 'oktest.rb' into 'test/'"
89
+ task :oktest => "test/oktest.rb"
90
+
91
+
92
+ file "test/oktest.rb" => File.expand_path("~/src/oktest/ruby/lib/oktest.rb") do |t|
93
+ cp t.prerequisites, "test"
94
+ end
95
+
96
+ #task "availables" do |t|
97
+ # methods = t.methods.sort - Object.new.methods
98
+ # $stderr.puts "\033[0;31m*** debug: methods=#{methods.inspect}\033[0m"
99
+ #end
100
+
101
+
102
+ desc "generates rubygems package"
103
+ task :gem => :dist do
104
+ dir = "dist/#{project}-#{release}"
105
+ Dir.chdir dir do
106
+ sh "gem build migr8.gemspec"
107
+ end
108
+ mv Dir.glob("#{dir}/migr8-#{release}.gem"), "dist"
109
+ puts "**"
110
+ puts "** created: dist/migr8-#{release}.gem"
111
+ puts "**"
112
+ end
113
+
114
+
115
+ desc "create 'dist' directory and copy files to it"
116
+ task :dist do
117
+ dir = "dist/#{project}-#{release}"
118
+ files = %w[README.md MIT-LICENSE migr8.gemspec Rakefile setup.rb]
119
+ rm_rf dir
120
+ mkdir_p dir
121
+ mkdir_p "#{dir}/bin"
122
+ mkdir_p "#{dir}/lib"
123
+ mkdir_p "#{dir}/test"
124
+ cp files, dir
125
+ cp Dir.glob("lib/*"), "#{dir}/lib"
126
+ cp Dir.glob("bin/*"), "#{dir}/bin"
127
+ cp Dir.glob("test/*"), "#{dir}/test"
128
+ chmod 0644, *Dir.glob("#{dir}/lib/*")
129
+ chmod 0755, *Dir.glob("#{dir}/bin/*")
130
+ Dir.chdir dir do
131
+ sh "rake edit"
132
+ end
133
+ end