#!/usr/bin/env ruby
# frozen_string_literal: true

# This script will promote post_migrate files
# which have existed for more than one Discourse
# ESR cycle.
#
# Renames will be staged in git, but not committed
#
# Usage:
#   script/promote_migrations [--dry-run] [--plugins]

require "open3"
require "fileutils"

VERSION_REGEX = %r{\/(\d+)_}

DRY_RUN = !!ARGV.delete("--dry-run")
PLUGINS = false

if i = ARGV.find_index("--plugins-base")
  ARGV.delete_at(i)
  PLUGINS = true
  PLUGINS_BASE = ARGV.delete_at(i)
elsif ARGV.delete("--plugins")
  PLUGINS = true
  PLUGINS_BASE = "plugins"
end

raise "Unknown arguments: #{ARGV.join(", ")}" if ARGV.length > 0

def run(*args, capture: true)
  out, s = Open3.capture2(*args)
  if s.exitstatus != 0
    STDERR.puts "Command failed: '#{args.join(" ")}'"
    exit 1
  end
  out.strip
end

run "git fetch"

current_version = run 'git describe --abbrev=0 --match "v*"'
puts "Current version is #{current_version}"

current_esr_version = run 'git describe --abbrev=0 --match "v*" esr'
puts "Current esr version is #{current_esr_version}"

minor = current_esr_version[/^(v\d+\.\d+)\./, 1]

previous_esr_version = "#{minor}.0"
puts "Previous esr version is #{previous_esr_version}"

esr_post_migrate_filenames =
  run("git", "ls-tree", "--name-only", "-r", previous_esr_version, "db/post_migrate").split("\n")

esr_post_migrate_filenames.sort!
latest_esr_post_migration = esr_post_migrate_filenames.last

puts "The latest core post_migrate file in #{previous_esr_version} is #{latest_esr_post_migration}"
puts "Promoting this, and all earlier post_migrates, to regular migrations"

promote_threshold = latest_esr_post_migration[VERSION_REGEX, 1].to_i
current_post_migrations =
  if PLUGINS
    puts "Looking in plugins..."
    Dir.glob("#{PLUGINS_BASE}/**/db/post_migrate/*")
  else
    Dir.glob("db/post_migrate/*")
  end

puts "No post_migrate files found. All done" if current_post_migrations.length == 0

current_post_migrations.each do |path|
  version = path[VERSION_REGEX, 1].to_i
  file = File.basename(path)
  dir = File.dirname(path)

  if version <= promote_threshold
    print "Promoting #{path}..."
    if DRY_RUN
      puts " (dry run)"
    else
      run "mkdir", "-p", "#{dir}/../migrate"
      run "git", "-C", dir, "mv", file, "../migrate/#{file}"
      puts " (done)"
    end
  end
end

puts "Done! File moves are staged and ready for commit."
puts "Suggested commit message:"
puts "-" * 20
puts <<~TEXT
DEV: Promote historic post_deploy migrations

This commit promotes all post_deploy migrations which existed in Discourse #{previous_esr_version} (timestamp <= #{promote_threshold})
TEXT
puts "-" * 20
