Skip to content

Instantly share code, notes, and snippets.

@bf4
Forked from matthewd/db-switch.rb
Created August 30, 2021 18:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bf4/b2ac2f77b2bf7144e84775c6151258e3 to your computer and use it in GitHub Desktop.
Save bf4/b2ac2f77b2bf7144e84775c6151258e3 to your computer and use it in GitHub Desktop.
bin/db-switch
#!/usr/bin/env ruby
require(Dir.pwd + "/config/environment")
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
ActiveRecord::Base.establish_connection(db_config.config)
context = ActiveRecord::Base.connection.migration_context
missing_migrations = []
context.migrations_status.each do |status, version, name|
# We're only interested in migrations that are currently applied
next unless status == "up"
# We're only interested in migrations being displayed as "***** NO FILE *****"
next unless name.start_with?("*")
raise "Unexpected version format: #{version.inspect} is not numeric" unless version =~ /\A[0-9]+\z/
missing_migrations << version
end
next if missing_migrations.empty?
puts
puts "Missing migrations in #{db_config.spec_name}:"
puts missing_migrations.map { |s| " #{s}" }
puts
migration_sha = {}
missing_migrations.each do |version|
migration_sha[version] = nil
end
puts "% git rev-list --walk-reflogs HEAD"
IO.popen("git rev-list --walk-reflogs HEAD") do |sha_list|
until migration_sha.values.all?
sha = sha_list.gets.chomp
newly_found = []
paths = Shellwords.join([*context.migrations_paths].map { |path| "#{path}/" })
puts %(% git ls-tree --name-only #{sha} -- #{paths})
migrate_files = %x(git ls-tree --name-only #{sha} -- #{paths}).lines.map(&:chomp)
migrate_files.each do |filename|
version = File.basename(filename).split("_", 2).first
if migration_sha.key?(version) && migration_sha[version].nil?
migration_sha[version] = [sha, filename]
newly_found << version
end
end
puts " found #{newly_found.sort.join(", ")}" unless newly_found.empty?
end
end
migration_files = []
missing_migrations.each do |version|
next unless migration_sha[version]
sha, filename = migration_sha[version]
puts %(% git cat-file blob #{sha}:#{Shellwords.escape filename})
migration_script = %x(git cat-file blob #{sha}:#{Shellwords.escape filename})
eval migration_script, nil, filename, 1
$LOADED_FEATURES << File.expand_path(filename)
migration_files << filename
end
puts
dummy_context = ActiveRecord::MigrationContext.new(nil, ActiveRecord::Base.connection.migration_context.schema_migration)
class << dummy_context
attr_accessor :migration_files
end
dummy_context.migration_files = migration_files
dummy_context.down
if ActiveRecord::Base.dump_schema_after_migration
ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment