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

# SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
# SPDX-FileCopyrightText: 2021 Harald Sitter <sitter@kde.org>

require 'open3'

# Lists versioned kernel packages (skips over ones marked not auto)
class ManualVersionedKernels
  # Apt comes with an expression list in APT::VersionedKernelPackages but for what we want to do it is hot garbage
  # because we need to have realtively constrained expressions whereas APT has incredibly generic ones, leading to
  # packages getting matched that aren't anywhere near related to the kernel e.g. .*-modules matches samba-vfs-modules.
  # Instead we have this bespoke list here.
  ANY_VERSION = '([-_]?(\d[\-+\.:\~\da-zA-Z]*))'
  VERSIONED_EXPRESSIONS = [
    "^linux-image#{ANY_VERSION}-.*$",
    "^linux-.*headers#{ANY_VERSION}$",
    "^linux-modules-.*#{ANY_VERSION}$",
    "^linux-.*tools#{ANY_VERSION}$",
    "^linux-.*cloud-tools#{ANY_VERSION}-.*$"
  ].freeze

  def list
    matches = []
    VERSIONED_EXPRESSIONS.each do |expression|
      all_packages.each do |package|
        next unless package =~ Regexp.new(expression)

        # apt has a guard to not ever autoremove the most relevant versions, so we are safe to list and mark
        # everything auto. the safe-guard will prevent autoremove from removing too much.

        matches << package
      end
    end
    matches.uniq.compact
  end

  def mark(list)
    return if list.empty?

    puts 'Marking versioned kernel packages auto...'
    puts list.join(', ')
    system(*%w[apt-mark auto], *list) || raise
  end

  private

  def all_packages
    @all_packages ||= begin
      all_packages, status = Open3.capture2(*%w[apt-mark showmanual])
      raise unless status.success?

      all_packages.split("\n").uniq.compact
    end
  end
end

if $PROGRAM_NAME == __FILE__
  marker = ManualVersionedKernels.new
  marker.mark(marker.list)
end
