This repository has been archived on 2022-01-17. You can view files and clone it, but cannot push or open issues/pull-requests.
packaging/src/context.cr

283 lines
6.7 KiB
Crystal
Raw Normal View History

require "colorize"
require "specparser"
2019-08-29 00:20:15 +02:00
2019-08-16 14:55:25 +02:00
require "./exception.cr"
2019-07-02 03:50:50 +02:00
2019-08-03 13:12:23 +02:00
require "./config.cr"
2019-09-06 00:39:11 +02:00
require "./backends/weird.cr"
require "./backends/apk.cr"
require "./backends/pkgutils.cr"
require "./backends.cr"
2019-07-03 05:23:48 +02:00
# FIXME: Where should this go? We cant just leave it here. :(
def pkginfo(package)
du = `du -sk #{package.fake_root_directory}`
size = du.sub(/[ \t].*/, "").to_i * 1024
2019-08-03 13:01:29 +02:00
lines = [] of String
lines << "# Generated by `package`."
lines << "pkgname = #{package.name}"
lines << "pkgver = #{package.version}-r#{package.release}"
lines << "url = #{package.url || ""} "
lines << "size = #{size}"
lines << "origin = #{package.recipe.name}"
lines << "buildtype = host" # Thisll need to be imported from Context.
lines << "builddate = #{Time.utc.to_unix}"
package.dependencies.each do |atom|
2019-09-04 19:49:47 +02:00
lines << "depend = #{atom.to_s}"
2019-08-03 13:01:29 +02:00
end
package.provides.each do |atom|
lines << "provides = #{atom.to_s}"
end
package.conflicts.each do |atom|
lines << "conflicts = #{atom.to_s}"
end
2019-09-01 17:29:44 +02:00
lines.join("\n") + "\n"
2019-07-03 05:23:48 +02:00
end
2019-07-02 03:50:50 +02:00
class Package::Context
property working_directory = "/tmp/package"
property sources_directory = Dir.current
property packages_directory = Dir.current
2019-07-03 03:48:31 +02:00
getter packaging_backends = [] of Backend::Packaging
getter building_backends = [] of Backend::Building
2019-07-04 23:18:54 +02:00
getter splitter_backends = [] of Backend::Splitter
2019-07-03 03:35:35 +02:00
2019-08-03 12:55:47 +02:00
# Directories where ports can be found.
getter repositories = [] of String
2019-07-03 05:23:48 +02:00
# Well, this will need configuration, auto-detection and conversion,
# but itll be kind of enough for now.
property architecture = "x86_64"
property prefixes = ["/usr", "/", "/usr/weirdos"]
property environment = {} of String => String
property verbosity = 0
2019-07-02 03:50:50 +02:00
def initialize
2019-09-06 00:39:11 +02:00
@packaging_backends << ApkBackend.new
@packaging_backends << WeirdBackend.new
@packaging_backends << PkgutilsBackend.new
2019-07-03 05:23:48 +02:00
2019-07-03 03:35:35 +02:00
@selected_packaging_backend = @packaging_backends[0]
2019-07-03 03:48:31 +02:00
@building_backends << Backend::Building.new "configure", "autotools" do |context, recipe|
2019-08-29 01:18:32 +02:00
next BuildStatus::Pass unless Dir.exists? recipe.dirname
2019-07-03 03:48:31 +02:00
Dir.cd recipe.dirname
unless File.exists? "configure"
next BuildStatus::Pass
end
child = context.sh "./configure --prefix=#{recipe.prefix} #{recipe.options["configure"]? || ""}"
2019-07-03 03:48:31 +02:00
if child.exit_status == 0
BuildStatus::Success
else
BuildStatus::Failed
end
end
2019-08-29 01:18:32 +02:00
@building_backends << Backend::Building.new "configure", "cmake" do |context, recipe|
next BuildStatus::Pass unless Dir.exists? recipe.dirname
Dir.cd recipe.dirname
next BuildStatus::Pass unless File.exists? "CMakeLists.txt"
options = [
"-DCMAKE_INSTALL_PREFIX='#{recipe.prefix}'",
"-DCMAKE_BUILD_TYPE=Release #{recipe.options["cmake"]}"
]
child = context.sh "cmake . #{options.join " "}"
if child.exit_status == 0
BuildStatus::Success
else
BuildStatus::Failed
end
end
2019-07-03 03:48:31 +02:00
@building_backends << Backend::Building.new "build", "make" do |context, recipe|
2019-08-29 01:18:32 +02:00
next BuildStatus::Pass unless Dir.exists? recipe.dirname
2019-07-03 03:48:31 +02:00
Dir.cd recipe.dirname
unless File.exists? "Makefile"
next BuildStatus::Pass
end
2019-07-23 16:41:34 +02:00
child = context.sh "make #{recipe.options["make"]? || ""}"
2019-07-03 03:48:31 +02:00
if child.exit_status == 0
BuildStatus::Success
else
BuildStatus::Failed
end
end
2019-07-03 05:23:48 +02:00
@building_backends << Backend::Building.new "install", "make" do |context, recipe|
2019-08-29 01:18:32 +02:00
next BuildStatus::Pass unless Dir.exists? recipe.dirname
2019-07-03 05:23:48 +02:00
Dir.cd recipe.dirname
unless File.exists? "Makefile"
next BuildStatus::Pass
end
2019-07-23 16:41:34 +02:00
child = context.sh "make install 'DESTDIR=#{recipe.fake_root_directory}' #{recipe.options["make install"]? || ""}"
2019-07-03 05:23:48 +02:00
if child.exit_status == 0
BuildStatus::Success
else
BuildStatus::Failed
end
end
2019-07-04 23:18:54 +02:00
@splitter_backends << Backend::Splitter.new do |recipe|
Package.new(recipe, true).tap do |split|
prefixes = (@prefixes + [recipe.prefix]).uniq
2019-07-04 23:18:54 +02:00
split.name = "#{recipe.name}-man"
split.files = prefixes.map do |prefix|
"#{prefix}/share/man"
end
2019-07-04 23:18:54 +02:00
end
end
@splitter_backends << Backend::Splitter.new do |recipe|
Package.new(recipe, true).tap do |split|
prefixes = (@prefixes + [recipe.prefix]).uniq
2019-07-04 23:18:54 +02:00
split.name = "#{recipe.name}-dev"
split.files = prefixes.map do |prefix|
[
"#{prefix}/include",
"#{prefix}/lib/pkgconfig"
]
end.flatten
split.file_patterns = prefixes.map do |prefix|
Regex.new("^" + prefix + ".*\\.a$")
end
2019-07-04 23:18:54 +02:00
end
end
2019-07-03 03:35:35 +02:00
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
2019-07-02 03:50:50 +02:00
end
2019-07-02 19:45:33 +02:00
def run(chdir, command, args)
output = Process::Redirect::Inherit
if @verbosity < -1
output = Process::Redirect::Close
end
Process.run command, args, chdir: chdir, output: output, error: output, env: @environment
2019-07-02 19:45:33 +02:00
end
def run(command, args)
run nil, command, args
end
def run(command)
run nil, command, nil
end
2019-07-23 16:41:34 +02:00
def sh(command)
run nil, "sh", ["-x", "-e", "-c", command]
end
def captured_sh(command)
output = IO::Memory.new
child = Process.run "sh", ["-x", "-e", "-c", command], output: output
{child, output}
end
# Output functions.
def title(s)
return if @verbosity < -3
puts ">> ".colorize(:green).mode(:bright).to_s +
s.colorize(:white).mode(:bright).to_s
2019-09-19 18:16:24 +02:00
STDOUT.flush
end
def info(s)
return if @verbosity < -2
puts ":: ".colorize(:green).to_s + s.colorize(:white).to_s
2019-09-19 18:16:24 +02:00
STDOUT.flush
end
def detail(s)
return if @verbosity < -1
puts ("+ " + s).colorize(:cyan)
2019-09-19 18:16:24 +02:00
STDOUT.flush
end
def package(package : Package) : Bool
@selected_packaging_backend.package self, package
end
2019-08-02 17:43:09 +02:00
def read_recipe(filename : String)
2019-08-02 23:58:42 +02:00
Recipe.new self, filename
2019-08-02 17:43:09 +02:00
end
2019-08-03 12:55:47 +02:00
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
2019-08-29 00:20:15 +02:00
def read_configuration(filename : String)
specs = SpecParser.parse(filename)
2019-08-29 00:20:15 +02:00
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 "prefixes"
@prefixes = value.as_a_or_s
when "environment"
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
@environment[key] = value
end
2019-09-06 00:39:11 +02:00
when "package-manager"
self.packaging_backend = value.as_s
2019-08-29 00:20:15 +02:00
end
end
end
2019-07-02 03:50:50 +02:00
end