#!/usr/bin/env ruby
# coding: utf-8
#
# Syd: rock-solid application kernel
# dev/cave-hide.rb: Cave subcommand to generate stat rules using package contents.
# Copyright (c) 2024 Ali Polatel <alip@chesswob.org>
# SPDX-License-Identifier: GPL-3.0

require 'Paludis'

require 'set'
require 'getoptlong'

include Paludis

NAME = File::basename($0, '.rb')
Log.instance.log_level = LogLevel::Warning
Log.instance.program_name = NAME

version = "0.1.0"

opts = GetoptLong.new(
  [ '--help',         '-h', GetoptLong::NO_ARGUMENT ],
  [ '--version',      '-V', GetoptLong::NO_ARGUMENT ],
  [ '--log-level',          GetoptLong::REQUIRED_ARGUMENT ],
  [ '--environment',  '-E', GetoptLong::REQUIRED_ARGUMENT ],
  [ '--syd',          '-s', GetoptLong::NO_ARGUMENT ])

$envspec = ""
$sprefix = false

opts.each do | opt, arg |
  case opt
  when '--help'
    puts <<HELP
Usage: #{NAME} [options] spec...

Options:
  --help, -h             Display a help message
  --version, -V          Display program version
  --log-level            Set log level (debug, qa, warning, silent)
  --environment, -E      Environment specification (class:suffix, both parts
                         optional, class must be 'paludis' if specified)
  --syd, -s              Prefix rules with /dev/syd/

Queries installed files by the given specs.
Writes a syd profile that allows these paths for stat sandboxing.
HELP
    exit 0
  when '--version'
    puts NAME + " " + version + " (Paludis Version: " + Version + ")"
    exit 0
  when '--log-level'
    case arg
    when 'debug'
      Log.instance.log_level = LogLevel::Debug
    when 'qa'
      Log.instance.log_level = LogLevel::Qa
    when 'warning'
      Log.instance.log_level = LogLevel::Warning
    when 'silent'
      Log.instance.log_level = LogLevel::Silent
    else
      $stderr.puts "Bad --log-level value " + arg
      exit 1
    end
  when '--environment'
    $envspec = arg
  when '--syd'
    $sprefix = true
  end
end

$env = EnvironmentFactory.instance.create($envspec)
if ARGV.empty?
  $stderr.puts "No specs supplied"
  exit 1
end

prefix = '/dev/syd/' if $sprefix
entries = Set.new
ARGV.each do |spec|
  ids = $env[Selection::AllVersionsSorted.new(
        Generator::Matches.new(Paludis::parse_user_package_dep_spec(spec, $env, [:allow_wildcards]), nil, []) |
        Filter::InstalledAtRoot.new("/"))]
  ids.each do |id|
    contents = id.contents
    next unless contents
    contents.each do |content|
      if content.kind_of?(ContentsDirEntry) || content.kind_of?(ContentsFileEntry) || content.kind_of?(ContentsSymEntry)
        value = content.location_key.parse_value
        unless entries.include?(value)
          puts "#{prefix}allow/stat+#{value}"
          entries.add(value)
        end
      end
    end
  end
end
