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/backends/baguette.cr

103 lines
2.9 KiB
Crystal

require "openssl"
require "../backends.cr"
class BaguetteBackend < Package::Backend::Packaging
def initialize
@name = "package"
end
# TODO: checksums + security
def package(context : Package::Context, package : Package::Package) : Bool
# Fake root example: /tmp/packages/<uuid>/root-xz-dev
fake_root = package.fake_root_directory
data_archive_path = "#{fake_root}/data.tar"
compressed_data_archive_path = "#{fake_root}/data.tar.zst"
control_spec_file_path = "#{fake_root}/control.spec"
manifest_file_path = "#{fake_root}/manifest"
package_target = "#{context.packages_directory}/#{package.name}-#{package.version}-#{package.release}.baguette"
context.detail "Archiving package content"
context.run fake_root, "tar", ["cvf", data_archive_path, "."]
context.detail "Compressing the archive"
# produces data.tar.zst
context.run fake_root, "zstd", ["--ultra", data_archive_path]
context.detail "Generating control.spec"
generate_spec package, control_spec_file_path
context.detail "Generating manifest"
generate_manifest context, package, manifest_file_path
context.detail "Assembling '#{package_target}'"
r = context.run fake_root, "tar", [
"cf", package_target,
# WARNING: relative paths are necessary.
"control.spec", "manifest", "data.tar.zst"
]
r.exit_status == 0
end
def generate_spec(package : Package::Package, file_name : String)
du = `du -sk #{package.fake_root_directory}`
size = du.sub(/[ \t].*/, "").to_u64 * 1024_u64
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 "size: #{size}"
file.puts "origin: #{package.recipe.name}"
file.puts "slot: #{package.prefix}"
file.puts
file.puts "url: #{package.url}"
file.puts "description: #{package.description}"
file.puts
file.puts "dependencies: #{package.dependencies.join ", "}"
file.puts "conflicts: #{package.conflicts.join ", "}"
file.puts "provides: #{package.provides.join ", "}"
file.close
end
def generate_manifest(context : Package::Context, package : Package::Package, file_name : String)
old_pwd = Dir.current
manifest = File.open(file_name, "w").not_nil!
Dir.cd package.fake_root_directory
FileUtils.find "." do |path|
file = path.lchop
if File.symlink? path
manifest.puts [file, "symlink", File.readlink(path)].join ':'
elsif File.directory? path
manifest.puts [file, "directory"].join ':'
elsif File.info?(path).try &.file?
digest = OpenSSL::Digest.new("sha256").file(path).final.hexstring
manifest.puts [file, "file", digest].join ':'
else
manifest.puts [file, "other"].join ':'
end
end
manifest.close
ensure
Dir.cd old_pwd.not_nil!
end
def self.install(packages : Array(String))
# TODO: install packages through package-install
raise "call to package-install not implemented, yet"
end
end