diff --git a/assemble-apk.sh b/assemble-apk.sh new file mode 100755 index 0000000..f676bd6 --- /dev/null +++ b/assemble-apk.sh @@ -0,0 +1,35 @@ +#!/bin/zsh + +# This script transforms the current directory into a full-blown apk package. +# It still requires a .PKGINFO file though. + +set -e + +# Output package name. +apk="$1" + +# data.tar.gz +echo "Compressing data..." +set -- * + +tar --xattrs -f - -c * | \ + abuild-tar --hash | \ + gzip -9 > data.tar.gz + +echo "Create checksum..." +# append the hash for data.tar.gz +local sha256=$(sha256sum data.tar.gz | cut -f1 -d' ') +echo "datahash = $sha256" >> .PKGINFO + +# control.tar.gz +cd "$dir" +metafiles=.PKGINFO +[ -f .metafiles ] && metafiles=$(cat .metafiles) + +tar -f - -c ${metafiles[@]} | abuild-tar --cut \ + | gzip -9 > control.tar.gz +#abuild-sign -q control.tar.gz || exit 1 + +echo "Create $apk" +cat control.tar.gz data.tar.gz > $apk + diff --git a/src/context.cr b/src/context.cr index 314cf9f..29eac71 100644 --- a/src/context.cr +++ b/src/context.cr @@ -1,4 +1,20 @@ +# 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 + + %{ # Generated by `package`. + pkgname = #{package.name} + pkgver = #{package.version}-r#{package.release} + url = #{package.url || ""} + size = #{size} + origin = #{package.recipe.name} + buildtype = host + builddate = #{Time.utc.to_unix} + }.gsub /^ */m, "" +end + class Package::Backend::Packaging getter name : String @@ -19,14 +35,40 @@ class Package::Context getter packaging_backends = [] of Backend::Packaging getter building_backends = [] of Backend::Building + # Well, this will need configuration, auto-detection and conversion, + # but it’ll be kind of enough for now. + property architecture = "x86_64" + def initialize @packaging_backends << Backend::Packaging.new "pkgutils" do |package| - puts "#{package.fake_root_directory} -> #{packages_directory}/#{package.name}##{package.version}.pkg.tar.xz" + 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 |package| + # FIXME: This needs to have access to architecture (from Context?) + # to work properly. + old_cwd = Dir.current + + puts "#{package.fake_root_directory} -> #{packages_directory}/#{package.name}-#{package.version}-r#{package.release}.apk" + + run package.fake_root_directory, "find", [".."] + + puts pkginfo package + File.write "#{package.fake_root_directory}/.PKGINFO", pkginfo package + + # Create data.tar.gz here. + package_target = "#{packages_directory}/#{package.name}-#{package.version}-r#{package.release}.apk" + # FIXME: This shouldn’t have to be in users’ PATH. libexec? + r = run package.fake_root_directory, "assemble-apk.sh", [ + package_target + ] + + r.exit_status == 0 + end + @selected_packaging_backend = @packaging_backends[0] @building_backends << Backend::Building.new "configure", "autotools" do |context, recipe| @@ -60,6 +102,22 @@ class Package::Context BuildStatus::Failed end end + + @building_backends << Backend::Building.new "install", "make" do |context, recipe| + Dir.cd recipe.dirname + + unless File.exists? "Makefile" + next BuildStatus::Pass + end + + child = context.run "make", ["install", "DESTDIR=#{recipe.fake_root_directory}"] + + if child.exit_status == 0 + BuildStatus::Success + else + BuildStatus::Failed + end + end end def packaging_backend=(name : String) diff --git a/src/main.cr b/src/main.cr index 31df186..4755e88 100644 --- a/src/main.cr +++ b/src/main.cr @@ -6,15 +6,20 @@ extend Package # FIXME: recipe.clean? context autoclean? Context.new().tap do |context| - context.packaging_backend = "pkgutils" + context.packaging_backend = "apk" # FIXME: context.new_recipe? context.recipe? Recipe.new(context, "hello", "2.10").tap do |recipe| recipe.sources << "https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz" - #recipe.instructions.configure << "cd hello-#{recipe.version} && ./configure" + # This is a voluntary mix of automatic and manual build + # instructions. + # Also, installing in /package makes testing with a real-life + # package manager trivial and reduces the damage done in case + # of… containment failure. ]:-> + recipe.instructions.configure << "cd hello-#{recipe.version} && ./configure --prefix=/package" #recipe.instructions.build << "cd hello-#{recipe.version} && make" - recipe.instructions.install << "cd hello-#{recipe.version} && make DESTDIR='${PKG}' install" + #recipe.instructions.install << "cd hello-#{recipe.version} && make DESTDIR='${PKG}' install" recipe.url = "https://www.gnu.org/software/hello/" recipe.description = "The GNU Hello program produces a familiar, friendly greeting." diff --git a/src/package.cr b/src/package.cr index 802b885..d765b4a 100644 --- a/src/package.cr +++ b/src/package.cr @@ -1,6 +1,6 @@ class Package::Package - @recipe : Recipe + getter recipe : Recipe def initialize(@recipe) end diff --git a/src/recipe.cr b/src/recipe.cr index 7fc2f3b..642cf8c 100644 --- a/src/recipe.cr +++ b/src/recipe.cr @@ -60,7 +60,7 @@ class Package::Recipe end def working_directory - @context.working_directory + "#{@context.working_directory}/#{@working_uuid}" end def building_directory