require "colorize" require "specparser" require "./exception.cr" require "./config.cr" require "./backends.cr" class Package::Context property working_directory = "/tmp/packaging" property sources_directory = Dir.current property packages_directory = Dir.current getter packaging_backends = [] of Backend::Packaging getter building_backends = [] of Backend::Building getter splitter_backends = [] of Backend::Splitter # Directories where ports can be found. getter repositories = [] of String # Well, this will need configuration, auto-detection and conversion, # but it’ll be kind of enough for now. property architecture = "x86_64" # prefixes for `packaging` running environment and child processes # = where to search for binaries and libraries for the build property prefixes = ["/usr/baguette", "/usr", "/"] # By default, building a package only uses one core property build_cores = 1 # list of environment variables we want to have when building #property environment = {} of String => String property recipe : Recipe? = nil def initialize # Add package backends: baguette (package-tools) and apk. # They implement the Backend::Packaging abstract class: # init (@name) + package (context, package) method @packaging_backends << Backend::Packaging::Baguette.new @packaging_backends << Backend::Packaging::APK.new @packaging_backends << Backend::Packaging::Pkgutils.new @selected_packaging_backend = @packaging_backends[0] # Add building backends: configuration, build and install. @building_backends << Backend::Configure.autotools @building_backends << Backend::Configure.cmake @building_backends << Backend::Build.make @building_backends << Backend::Install.make # Split = new package from a recipe, each one with different files being included. @splitter_backends << Backend::Splitter.man @prefixes @splitter_backends << Backend::Splitter.dev @prefixes @splitter_backends << Backend::Splitter.src @prefixes end def packaging_backend=(name : String) @selected_packaging_backend = @packaging_backends.find(&.name.==(name)).not_nil! end def packaging_backend=(backend : Backend::Packaging) @selected_packaging_backend = backend end def package(package : Package) : Bool @selected_packaging_backend.package @packages_directory, @architecture, package end def read_recipe(filename : String) @recipe = Recipe.new self, filename @recipe.not_nil! end def find_recipe(name : String) : Recipe? recipe_file_name = "" repo = @repositories.find do |repo| repo_dir_name = "#{repo}/#{name}" recipe_file_name = "#{repo_dir_name}/recipe.spec" if Dir.exists?(repo_dir_name) && File.exists?(recipe_file_name) next true end end read_recipe recipe_file_name if repo end def read_configuration(filename : String) specs = SpecParser.parse(File.read(filename)) specs.assignments.each do |key, value| case key when "packages-directory" @packages_directory = value.as_s when "sources-directory" @sources_directory = value.as_s when "working-directory" @working_directory = value.as_s when "prefixes" # Prefixes during the build process. @prefixes = value.as_a_or_s when "build-cores" # NB of cores used to compile applications. @build_cores = value.as_s.to_i when "environment" # Environment variables during the build process. value.as_a_or_s.each do |entry| match = entry.split(':').map( &.gsub(/^[ \t]*/, "").gsub(/[ \t]*$/, "")) if match.size != 2 STDERR.puts "WARNING: misformed environment definition: #{entry}" next end key, value = match Do.environment[key] = value if Baguette::Context.verbosity > 2 STDOUT.puts "environment: #{key} => #{value}" end end when "package-manager" # Targeted package manager (default: package, for BaguetteOS). begin self.packaging_backend = value.as_s rescue e STDERR.puts "Error during selecting packaging backend: #{e}" STDERR.puts "#{value.as_s} seems not to be a valid backend" STDERR.puts "valid backends:" @packaging_backends.each do |backend| STDERR.puts "- #{backend.name}" end exit 1 end end end end def install(packages : Array(String)) @selected_packaging_backend.install packages end end