module Prick module SubCommand def self.create_migration(username, from_version, force: false, file: nil) constrain from_version, PrickVersion Git.clean? or raise "Won't migrate: Repository is dirty" Git.synchronized? or raise "Won't migrate: Repository is not synchronized" from_version != PrickVersion.zero or raise Prick::Error, "Can't migrate from release 0.0.0" to_version = Prick.state.version migration_dir = "#{MIGRATION_DIR}/#{from_version}" migration_exist = File.directory? migration_dir force || file || !migration_exist or raise Prick::Fail, "Migration #{from_version} exists" $quiet = true if file if file && migration_exist File.open(file, "w") { |file| for diff_file in DIFF_FILES file.write File.read("#{migration_dir}/#{diff_file}") end } else from_version != to_version or raise Prick::Fail, "Can't migrate to same release" from_version < to_version or raise Prick::Fail, "Can't migrate backwards (why not?)" diff = nil if force || !migration_exist from_db = "#{Prick.state.name}-#{from_version}" to_db = "#{Prick.state.name}-#{to_version}" mesg "Migrating from #{from_version} to #{to_version}" begin origin = Git.origin # Local repos are supported to ease testing if File.directory?(origin) origin = File.expand_path(origin) end diff = Dir.mktmpdir { |tmpdir| Dir.chdir(tmpdir) { mesg " Building #{from_db}" Git.clone(origin, from_version, branch: from_version) Dir.chdir(from_version.to_s) { build(from_db, username, nil) } } mesg " Building #{to_db}" build(to_db, username, nil) mesg " Creating diff" Diff.new(from_db, to_db) } !diff.same? or raise Prick::Fail, "No changes" ensure drop_all(from_db) drop_all(to_db) end end diff.write(file) if file end if file File.open(file, "a") { |f| f.puts "-- UPDATE VERSION" f.puts File.readlines(SCHEMA_VERSION_PATH).grep_v(/^--/) } else FileUtils.rm_rf migration_dir if force FileUtils.mkdir_p migration_dir Command.command "cp -a #{SHARE_PATH}/migrate/migration/. #{migration_dir}" Dir.chdir(migration_dir) { diff.write(*DIFF_FILES, mark: true) } end end end end