From afaf5c2fda67c65f07944752d664fae0ac3d6b98 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Tue, 2 Mar 2021 10:33:54 +0100 Subject: [PATCH] baguette backend overflow bugfix, baguette package tool --- shard.yml | 16 ++--- src/backends/baguette.cr | 2 +- src/context.cr | 54 +++++++-------- src/main.cr | 4 -- src/package.cr | 2 +- src/recipe.cr | 9 ++- src/tools/baguette.cr | 145 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 184 insertions(+), 48 deletions(-) create mode 100644 src/tools/baguette.cr diff --git a/shard.yml b/shard.yml index 13be699..efa86bc 100644 --- a/shard.yml +++ b/shard.yml @@ -10,14 +10,14 @@ description: | dependencies: specparser: git: https://git.baguette.netlib.re/Baguette/recipes-parser + baguette-crystal-base: + git: https://git.baguette.netlib.re/Baguette/baguette-crystal-base + branch: master -# dependencies: -# pg: -# github: will/crystal-pg -# version: "~> 0.5" - -# development_dependencies: -# webmock: -# github: manastech/webmock.cr +targets: + package-create: + main: src/main.cr + baguette: + main: src/tools/baguette.cr license: ISC diff --git a/src/backends/baguette.cr b/src/backends/baguette.cr index e2b7fd3..23d08bb 100644 --- a/src/backends/baguette.cr +++ b/src/backends/baguette.cr @@ -45,7 +45,7 @@ class BaguetteBackend < Package::Backend::Packaging def generate_spec(package : Package::Package, file_name : String) du = `du -sk #{package.fake_root_directory}` - size = du.sub(/[ \t].*/, "").to_i * 1024 + size = du.sub(/[ \t].*/, "").to_u64 * 1024_u64 file = File.open file_name, "w" diff --git a/src/context.cr b/src/context.cr index 09ac051..f14fe3a 100644 --- a/src/context.cr +++ b/src/context.cr @@ -11,37 +11,6 @@ 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}` - size = du.sub(/[ \t].*/, "").to_i * 1024 - - lines = [] of String - - lines << "# Generated by `packaging`." - 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 Package::Context property working_directory = "/tmp/packaging" property sources_directory = Dir.current @@ -161,6 +130,7 @@ class Package::Context # new name = split name (-man, -src, ...) # split files + # Man-pages and documentation @splitter_backends << Backend::Splitter.new do |recipe| Package.new(recipe, true).tap do |split| prefixes = (@prefixes + [recipe.prefix]).uniq @@ -169,9 +139,11 @@ class Package::Context split.files = prefixes.map do |prefix| "#{prefix}/share/man" end + split.recipe.require_stripping = false end end + # Developer's files: headers, pkgconfig files, *.a. @splitter_backends << Backend::Splitter.new do |recipe| Package.new(recipe, true).tap do |split| prefixes = (@prefixes + [recipe.prefix]).uniq @@ -186,6 +158,26 @@ class Package::Context split.file_patterns = prefixes.map do |prefix| Regex.new("^" + prefix + ".*\\.a$") end + # Any prefix containing "/include/" + split.file_patterns.not_nil! << Regex.new(".*/include/.*/") + end + end + + # Source files: prefix containing "src". + @splitter_backends << Backend::Splitter.new do |recipe| + Package.new(recipe, true).tap do |split| + prefixes = (@prefixes + [recipe.prefix]).uniq + + split.name = "#{recipe.name}-src" + split.files = prefixes.map do |prefix| + [ + "#{prefix}/lib/share/src", + "#{prefix}/src", + "#{prefix}/usr/src", + "#{prefix}/usr/local/src" + ] + end.flatten + split.recipe.require_stripping = false end end end diff --git a/src/main.cr b/src/main.cr index 669123c..8829342 100644 --- a/src/main.cr +++ b/src/main.cr @@ -149,10 +149,6 @@ if CLIOpts.watch_only exit 0 end -# TODO: verify package-create dependencies: -# - rsync -# - tar (bsdtar) - begin latest_build_dir = "" diff --git a/src/package.cr b/src/package.cr index 0d5c243..d52bfa7 100644 --- a/src/package.cr +++ b/src/package.cr @@ -67,7 +67,7 @@ class Package::Package inherit prefix : String - @fake_root_directory : String? + property fake_root_directory : String? def dependencies @dependencies || @recipe.run_dependencies diff --git a/src/recipe.cr b/src/recipe.cr index b4b3df5..a465a3f 100644 --- a/src/recipe.cr +++ b/src/recipe.cr @@ -74,7 +74,11 @@ class Package::Recipe property recipe_directory = "." - getter working_uuid : UUID = UUID.random + property working_uuid : UUID = UUID.random + + # Does this package requires running `strip` on its content? + # Man-page and source packages don't, for example. + property require_stripping = true def initialize(@context, @name, @version) end @@ -302,12 +306,11 @@ class Package::Recipe raise BuildError.new self, "No file was installed in the fake root." end - do_strip + do_strip if @require_stripping do_splits end - # TODO: do not search within source files. private def do_strip @context.info "Stripping binaries" diff --git a/src/tools/baguette.cr b/src/tools/baguette.cr new file mode 100644 index 0000000..2cff477 --- /dev/null +++ b/src/tools/baguette.cr @@ -0,0 +1,145 @@ +require "../context.cr" +require "../recipe.cr" +require "../package.cr" +require "../backends/baguette.cr" + +require "option_parser" + +require "baguette-crystal-base" + +class Context + class_property command = "not-implemented" + class_property configuration_file = "#{SYSCONF_DIR}/packaging.cfg" + class_property args = Array(String).new +end + +class Action + property the_call = {} of String => Proc(Nil) + property context : Package::Context + + def initialize(@context) + @the_call["package"] = ->package + end + + def package + pkg, uuid = Context.args[0..1] + Baguette::Log.info "package #{pkg} uuid #{uuid}" + + recipe = context.find_recipe(pkg) + unless recipe + Baguette::Log.error "Error: no recipes" + exit 1 + end + + begin + # Change working UUID. + old_uuid = recipe.working_uuid + new_uuid = UUID.new(uuid) + recipe.working_uuid = new_uuid + recipe.packages.each do |pkg| + if frd = pkg.fake_root_directory + pkg.fake_root_directory = frd.gsub old_uuid.to_s, new_uuid.to_s + end + end + + latest_build_dir = recipe.building_directory + + context.title recipe.name + + # recipe.download + # recipe.extract + # recipe.build + recipe.package + + # recipe.clean unless Context.do_not_clean + rescue e : Package::Exception + Baguette::Log.error "#{e.message}" + Baguette::Log.error "You may want to inspect the build directory at #{latest_build_dir}" + exit 1 + rescue e + Baguette::Log.error "An unexpected error occured:" + Baguette::Log.error e + exit 1 + end + end +end + + +def main + + opt_help = -> (parser : OptionParser) { + parser.on "help", "Prints this help message." do + puts parser + exit 0 + end + } + + # Unrecognized parameters are used to create commands with multiple arguments. + # Example: user add _login email phone_ + # Here, login, email and phone are unrecognized arguments. + # Still, the "user add" command expect them. + unrecognized_args_to_context_args = -> (parser : OptionParser, n_expected_args : Int32) { + # With the right args, these will be interpreted as serialized data. + parser.unknown_args do |args| + if args.size != n_expected_args + Baguette::Log.error "expected number of arguments: #{n_expected_args}, received: #{args.size}" + Baguette::Log.error "args: #{args}" + Baguette::Log.error "#{parser}" + exit 1 + end + args.each do |arg| + Baguette::Log.debug "Unrecognized argument: #{arg} (adding to Context.args)" + Context.args << arg + end + end + } + + OptionParser.parse do |parser| + parser.banner = "usage: baguette [options] command [parameters]" + + parser.on "package", "Create a package." do + parser.banner = "Usage: baguette [opt] package package-name uuid" + Baguette::Log.info "Create a Baguette package." + Context.command = "package" + opt_help.call parser + # package name, uuid + unrecognized_args_to_context_args.call parser, 2 + end + + parser.on "-c configuration-file", "--config configuration-file", "Configuration file." do |f| + Baguette::Log.info "configuration file is: #{f}" + Context.configuration_file = f + end + + parser.on "-h", "--help", "Show this help" do + puts parser + exit 0 + end + end + + + context = Package::Context.new() + context.repositories << "." + + context.read_configuration Context.configuration_file + + actions = Action.new context + + # Now we did read the intent, we should proceed doing what was asked. + begin + actions.the_call[Context.command].call + rescue e + Baguette::Log.info "The command is not recognized (or implemented)." + end + +rescue e : OptionParser::Exception + Baguette::Log.error e.message +rescue e + Baguette::Log.error "exception raised: #{e.message}" + e.backtrace.try &.each do |line| + STDERR << " - " << line << '\n' + end +end + + +main