diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index 3fc69d7af0bdc..a4c09b654a559 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -384,23 +384,32 @@ def method_missing(method, *arguments, &block) end end - def copy(destination, sources) + def copy(destination, sources, options = {}) copied = [] + destination_migrations = ActiveRecord::Migrator.migrations(destination) + last = destination_migrations.last sources.each do |name, path| - destination_migrations = ActiveRecord::Migrator.migrations(destination) source_migrations = ActiveRecord::Migrator.migrations(path) - last = destination_migrations.last source_migrations.each do |migration| - next if destination_migrations.any? { |m| m.name == migration.name } + source = File.read(migration.filename) + source = "# This migration comes from #{name} (originally #{migration.version})\n#{source}" + + if duplicate = destination_migrations.detect { |m| m.name == migration.name } + options[:on_skip].call(name, migration) if File.read(duplicate.filename) != source && options[:on_skip] + next + end migration.version = next_migration_number(last ? last.version + 1 : 0).to_i + new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb") + old_path, migration.filename = migration.filename, new_path last = migration - new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.rb") - FileUtils.cp(migration.filename, new_path) - copied << new_path + FileUtils.cp(old_path, migration.filename) + copied << migration + options[:on_copy].call(name, migration, old_path) if options[:on_copy] + destination_migrations << migration end end @@ -426,6 +435,10 @@ def initialize(name, version, filename) @migration = nil end + def basename + File.basename(filename) + end + delegate :migrate, :announce, :write, :to=>:migration private diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 9635ab25fc9dd..ef949300b08a1 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -1912,7 +1912,7 @@ def test_copying_migrations_without_timestamps copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) assert File.exists?(@migrations_path + "/4_people_have_hobbies.rb") assert File.exists?(@migrations_path + "/5_people_have_descriptions.rb") - assert_equal [@migrations_path + "/4_people_have_hobbies.rb", @migrations_path + "/5_people_have_descriptions.rb"], copied + assert_equal [@migrations_path + "/4_people_have_hobbies.rb", @migrations_path + "/5_people_have_descriptions.rb"], copied.map(&:filename) files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy"}) @@ -1953,7 +1953,7 @@ def test_copying_migrations_with_timestamps assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") expected = [@migrations_path + "/20100726101010_people_have_hobbies.rb", @migrations_path + "/20100726101011_people_have_descriptions.rb"] - assert_equal expected, copied + assert_equal expected, copied.map(&:filename) files_count = Dir[@migrations_path + "/*.rb"].length copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) @@ -2006,6 +2006,24 @@ def test_copying_migrations_with_timestamps_to_destination_with_timestamps_in_fu clear end + def test_skipping_migrations + @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" + @existing_migrations = Dir[@migrations_path + "/*.rb"] + + sources = ActiveSupport::OrderedHash.new + sources[:bukkits] = sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" + + skipped = [] + on_skip = Proc.new { |name, migration| skipped << "#{name} #{migration.name}" } + copied = ActiveRecord::Migration.copy(@migrations_path, sources, :on_skip => on_skip) + assert_equal 2, copied.length + + assert_equal 2, skipped.length + assert_equal ["bukkits PeopleHaveHobbies", "bukkits PeopleHaveDescriptions"], skipped + ensure + clear + end + def test_copying_migrations_to_empty_directory @migrations_path = MIGRATIONS_ROOT + "/empty" @existing_migrations = []