diff --git a/src/backends.cr b/src/backends.cr new file mode 100644 index 0000000..3e9911d --- /dev/null +++ b/src/backends.cr @@ -0,0 +1,20 @@ + +abstract class Package::Backend::Packaging + getter name : String + + def initialize(@name) + end + + abstract def package(context : Context, package : Package) : Bool +end + +class Package::Backend::Splitter + def initialize(&block : Proc(Recipe, Package)) + @callback = block + end + + def create_split(recipe : Recipe) : Package + @callback.call recipe + end +end + diff --git a/src/backends/apk.cr b/src/backends/apk.cr new file mode 100644 index 0000000..32da54d --- /dev/null +++ b/src/backends/apk.cr @@ -0,0 +1,58 @@ +require "../backends.cr" + +# FIXME: Where should this go? We can’t just leave it here. :( +def pkginfo(package) + du = `du -sk #{package.fake_root_directory}` + size = du.sub(/[ \t].*/, "").to_i * 1024 + + 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" # This’ll need to be imported from Context. + lines << "builddate = #{Time.utc.to_unix}" + + package.dependencies.each do |atom| + lines << "depend = #{atom.to_s}" + end + + package.provides.each do |atom| + lines << "provides = #{atom.to_s}" + end + + package.conflicts.each do |atom| + lines << "conflicts = #{atom.to_s}" + end + + lines.join("\n") + "\n" +end + +class ApkBackend < Package::Backend::Packaging + def initialize + @name = "apk" + end + + def package(context : Package::Context, package : Package::Package) + # FIXME: This needs to have access to architecture (from Context?) + # to work properly. + old_cwd = Dir.current + + File.write "#{package.fake_root_directory}/.PKGINFO", pkginfo package + + # Create data.tar.gz here. + package_target = "#{context.packages_directory}/#{context.architecture}/#{package.name}-#{package.version}-r#{package.release}.apk" + Dir.mkdir_p File.dirname package_target + + # FIXME: This shouldn’t have to be in users’ PATH. libexec? + r = context.run package.fake_root_directory, "#{OWN_LIBEXEC_DIR}/assemble-apk.sh", [ + package_target + ] + + r.exit_status == 0 + end +end + diff --git a/src/backends/pkgutils.cr b/src/backends/pkgutils.cr new file mode 100644 index 0000000..91fec47 --- /dev/null +++ b/src/backends/pkgutils.cr @@ -0,0 +1,15 @@ +require "../backends.cr" + +class PkgutilsBackend < Package::Backend::Packaging + def initialize + @name = "pkgutils" + end + + def package(context : Package::Context, package : Package::Package) + puts "#{package.fake_root_directory} -> #{context.packages_directory}/#{package.name}##{package.version}-#{package.release}.pkg.tar.xz" + pp! r = context.run package.fake_root_directory, "tar", ["cJf", "#{context.packages_directory}/#{package.name}##{package.version}.pkg.tar.xz", "."] + + r.exit_status == 0 + end +end + diff --git a/src/backends/weird.cr b/src/backends/weird.cr new file mode 100644 index 0000000..66c662f --- /dev/null +++ b/src/backends/weird.cr @@ -0,0 +1,50 @@ +require "../backends.cr" + + +class WeirdBackend < Package::Backend::Packaging + def initialize + @name = "weird" + end + + def package(context : Package::Context, package : Package::Package) + destination_package_file = "#{context.packages_directory}/#{package.name}-#{package.version}-#{package.release}.weird" + + tmpdir = package.recipe.working_directory + fake_root = package.fake_root_directory + + context.detail "Archiving package content" + context.run fake_root, "tar", ["cJf", "#{tmpdir}/data.tar.xz", "."] + + context.detail "Generating control.spec" + generate_spec package, "#{tmpdir}/control.spec" + + context.detail "Assembling '#{destination_package_file}'" + + r = context.run tmpdir, "tar", [ + "cf", destination_package_file, + "control.spec", "data.tar.xz" + ] + + r.exit_status == 0 + end + + def generate_spec(package : Package::Package, file_name : String) + file = File.open file_name, "w" + + file.puts "name: #{package.name}" + file.puts "version: #{package.version}" + file.puts "release: #{package.release}" + file.puts + file.puts "url: #{package.url}" + file.puts "description: #{package.description}" + file.puts + file.puts "slot: #{package.prefix}" + file.puts + file.puts "dependencies: #{package.dependencies.join ", "}" + file.puts "conflicts: #{package.conflicts.join ", "}" + file.puts "provides: #{package.provides.join ", "}" + + file.close + end +end + diff --git a/src/context.cr b/src/context.cr index 2a4c83b..475b9aa 100644 --- a/src/context.cr +++ b/src/context.cr @@ -6,6 +6,11 @@ require "./exception.cr" require "./config.cr" +require "./backends/weird.cr" +require "./backends/apk.cr" +require "./backends/pkgutils.cr" +require "./backends.cr" + # FIXME: Where should this go? We can’t just leave it here. :( def pkginfo(package) du = `du -sk #{package.fake_root_directory}` @@ -37,28 +42,6 @@ def pkginfo(package) lines.join("\n") + "\n" end -class Package::Backend::Packaging - getter name : String - - def initialize(@name, &block : Proc(Context, Package, Bool)) - @callback = block - end - - def package(context : Context, package : Package) - @callback.call context, package - end -end - -class Package::Backend::Splitter - def initialize(&block : Proc(Recipe, Package)) - @callback = block - end - - def create_split(recipe : Recipe) : Package - @callback.call recipe - end -end - class Package::Context property working_directory = "/tmp/package" property sources_directory = Dir.current @@ -81,31 +64,9 @@ class Package::Context property verbosity = 0 def initialize - @packaging_backends << Backend::Packaging.new "pkgutils" do |context, package| - puts "#{package.fake_root_directory} -> #{packages_directory}/#{package.name}##{package.version}-#{package.release}.pkg.tar.xz" - pp! r = run package.fake_root_directory, "tar", ["cJf", "#{packages_directory}/#{package.name}##{package.version}.pkg.tar.xz", "."] - - r.exit_status == 0 - end - - @packaging_backends << Backend::Packaging.new "apk" do |context, package| - # FIXME: This needs to have access to architecture (from Context?) - # to work properly. - old_cwd = Dir.current - - File.write "#{package.fake_root_directory}/.PKGINFO", pkginfo package - - # Create data.tar.gz here. - package_target = "#{packages_directory}/#{context.architecture}/#{package.name}-#{package.version}-r#{package.release}.apk" - Dir.mkdir_p File.dirname package_target - - # FIXME: This shouldn’t have to be in users’ PATH. libexec? - r = run package.fake_root_directory, "#{OWN_LIBEXEC_DIR}/assemble-apk.sh", [ - package_target - ] - - r.exit_status == 0 - end + @packaging_backends << ApkBackend.new + @packaging_backends << WeirdBackend.new + @packaging_backends << PkgutilsBackend.new @selected_packaging_backend = @packaging_backends[0] @@ -309,6 +270,8 @@ class Package::Context key, value = match @environment[key] = value end + when "package-manager" + self.packaging_backend = value.as_s end end end diff --git a/src/main.cr b/src/main.cr index 164058b..f073b6a 100644 --- a/src/main.cr +++ b/src/main.cr @@ -8,7 +8,6 @@ require "./recipe.cr" extend Package context = Context.new() -context.packaging_backend = "apk" context.repositories << "." configuration_file = "#{SYSCONF_DIR}/package.cfg" diff --git a/src/package.cr b/src/package.cr index 26a9c65..d663240 100644 --- a/src/package.cr +++ b/src/package.cr @@ -65,6 +65,8 @@ class Package::Package property files : Array(String)? property file_patterns : Array(Regex)? + inherit prefix : String + @fake_root_directory : String? def dependencies