Skip to content

Instantly share code, notes, and snippets.

@arika
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save arika/750e1c0e25625124a3e6 to your computer and use it in GitHub Desktop.

Select an option

Save arika/750e1c0e25625124a3e6 to your computer and use it in GitHub Desktop.
# usage:
# ruby manual_import_migrations.rb ../path/to/project/db/migrate/**/*.rb
require 'optparse'
require 'fileutils'
require 'ripper'
def omit_pos(token)
if token.size == 3 &&
token[-1].is_a?(Array) && token[-1].size == 2 &&
token[-1][0].is_a?(Integer) && token[-1][1].is_a?(Integer)
token[-1] = nil
end
token.each do |t|
next unless t.is_a?(Array)
omit_pos(t)
end
end
def sexp(str)
s = Ripper.sexp(str)
omit_pos(s)
s
end
def get_migrations(dir)
migrations = {}
Dir[File.join(dir, '**/*')].each do |fname|
next unless FileTest.file?(fname)
s = sexp(File.read(fname))
sf = s.flatten
migrations[fname] = [s, sf, sf.size]
end
migrations
end
def find_migration(fname, migrations)
s = sexp(File.read(fname))
found = nil
migrations.each do |fn, x|
if s == x[0]
found = fn
break
end
end
unless found
sf = s.flatten
sf_size = sf.size
sims = migrations.map do |fn, x|
d1 = sf - x[1]
d2 = x[1] - sf
[(sf_size + x[2])/(d1.size + d2.size), fn]
end.sort_by {|ratio, fn| ratio }
if sims.last[0] > 20
sim = sims.last[1]
end
end
[found, sim]
end
def copy_migration(src, migrate_dir, opts)
n = File.basename(src)
to = File.join(migrate_dir, n).sub(/\.rb\z/, '.manual_import.rb')
if File.exists?(to)
warn "already exists `#{to}' for `#{src}'"
else
FileUtils.cp(src, to,
noop: opts[:dryrun],
verbose: opts[:verbose])
end
end
opts = {
list: true,
copy: false,
dryrun: false,
verbose: true,
}
OptionParser.new do |o|
o.on('-l', '--[no-]list', 'suppress list') do |v|
opts[:list] = v
end
o.on('-c', '--copy', 'copy missing migrations') do
opts[:copy] = true
end
o.on('-n', '--dry-run', 'show copy instructions') do
opts[:dryrun] = true
end
o.on('-q', '--quiet', 'suppress output') do
opts[:verbose] = false
end
o.on_tail('-h', '--help') do
puts o
exit
end
end.parse!
migrate_dir = 'db/migrate'
migrations = get_migrations(migrate_dir)
copy = []
ARGV.each do |fname|
found, sim = find_migration(fname, migrations)
if found
puts "#{fname} == #{found}" if opts[:list]
elsif sim
puts "#{fname} =~ #{sim}" if opts[:list]
else
puts "#{fname}: --" if opts[:list]
copy << fname if opts[:copy]
end
end
copy.each do |src|
copy_migration(src, migrate_dir, opts)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment