diff --git a/src/backends/baguette.cr b/src/backends/baguette.cr index d862c33..e2b7fd3 100644 --- a/src/backends/baguette.cr +++ b/src/backends/baguette.cr @@ -8,15 +8,15 @@ class BaguetteBackend < Package::Backend::Packaging @name = "package" end + # TODO: checksums + security def package(context : Package::Context, package : Package::Package) : Bool - - tmpdir = package.recipe.working_directory + # Fake root example: /tmp/packages//root-xz-dev fake_root = package.fake_root_directory - data_archive_path = "#{tmpdir}/data.tar" - compressed_data_archive_path = "#{tmpdir}/data.tar.zst" - control_spec_file_path = "#{tmpdir}/control.spec" - manifest_file_path = "#{tmpdir}/manifest" + 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" @@ -34,7 +34,7 @@ class BaguetteBackend < Package::Backend::Packaging generate_manifest context, package, manifest_file_path context.detail "Assembling '#{package_target}'" - r = context.run tmpdir, "tar", [ + r = context.run fake_root, "tar", [ "cf", package_target, # WARNING: relative paths are necessary. "control.spec", "manifest", "data.tar.zst" diff --git a/src/context.cr b/src/context.cr index e6bb44c..09ac051 100644 --- a/src/context.cr +++ b/src/context.cr @@ -153,9 +153,12 @@ class Package::Context end end - # Splitters = creating new packages: + # Package::Backend::Splitter = create new package + # takes (then stores) the given block + # this block takes a recipe as a parameter and create a new package + # the new package: # keep prefixes - # split names (man, src, ...) + # new name = split name (-man, -src, ...) # split files @splitter_backends << Backend::Splitter.new do |recipe| @@ -204,7 +207,8 @@ class Package::Context # log sub-commands outputs logfile_path = "#{@working_directory}/#{@recipe.not_nil!.working_uuid}.log" output = File.open logfile_path, "a" - STDOUT.puts "logging command #{command} #{args}" + STDOUT.puts "logging command " + + "#{command} #{args}".colorize(:light_magenta).to_s STDOUT.puts "in " + logfile_path.colorize(:blue).mode(:bright).to_s output.puts "" @@ -242,6 +246,16 @@ class Package::Context {child, output} end + # Log file moves during splits. + def mv(f1 : String, f2 : String) + run "mv", [ f1, f2 ] + end + + # Log directory creations during splits. + def mkdir_p(dir : String) + run "mkdir", [ "-p", dir ] + end + # Output functions. def title(s) return if @verbosity < -3 diff --git a/src/do.cr b/src/do.cr new file mode 100644 index 0000000..fddfbb8 --- /dev/null +++ b/src/do.cr @@ -0,0 +1,9 @@ + +class Do < Process + def self.require_cmd(cmd : String) + unless Process.run("which", [ cmd ]).success? + STDERR.puts "#{cmd} isn't installed" + exit 1 + end + end +end diff --git a/src/main.cr b/src/main.cr index 441bc5f..669123c 100644 --- a/src/main.cr +++ b/src/main.cr @@ -4,23 +4,25 @@ require "colorize" require "./context.cr" require "./recipe.cr" +require "./do.cr" extend Package context = Context.new() context.repositories << "." -configuration_file = "#{SYSCONF_DIR}/packaging.cfg" -configuration_file_requested = false - -requested_recipes = [] of String -download_only = false -do_not_clean = false -watch_only = false -skip_build_dependencies = false -print_deps = false -only_print_configuration = false +class CLIOpts + class_property requested_recipes = [] of String + class_property download_only = false + class_property do_not_clean = false + class_property watch_only = false + class_property skip_build_dependencies = false + class_property print_deps = false + class_property only_print_configuration = false + class_property configuration_file = "#{SYSCONF_DIR}/packaging.cfg" + class_property configuration_file_requested = false +end used_X = false OptionParser.parse do |parser| @@ -37,16 +39,16 @@ OptionParser.parse do |parser| } parser.on("-c FILE", "--conf FILE", "Use a configuration file other than the default one.") { |file| - configuration_file = file - configuration_file_requested = true + CLIOpts.configuration_file = file + CLIOpts.configuration_file_requested = true } parser.on("-D", "--download-only", "Only download sources, do not build.") { - download_only = true + CLIOpts.download_only = true } parser.on("-k", "--keep-work-dir", "Do not clean after building.") { - do_not_clean = true + CLIOpts.do_not_clean = true } parser.on("-h", "--help", "Prints this help message.") { @@ -60,11 +62,11 @@ OptionParser.parse do |parser| } parser.on("-w", "--watch", "Checks if the recipe is up to date and exits.") { - watch_only = true + CLIOpts.watch_only = true } parser.on("-B", "--print-deps", "Prints build dependencies and exits.") { - print_deps = true + CLIOpts.print_deps = true } parser.on("-v", "--verbose", "Runs more verbosely.") { @@ -76,11 +78,11 @@ OptionParser.parse do |parser| } parser.on("-n", "--ignore-dependencies", "Do not try to install build-dependencies.") { - skip_build_dependencies = true + CLIOpts.skip_build_dependencies = true } parser.on("-p", "--print-configuration", "Only print configuration.") { - only_print_configuration = true + CLIOpts.only_print_configuration = true } parser.invalid_option do |flag| @@ -90,23 +92,28 @@ OptionParser.parse do |parser| end parser.unknown_args do |arg| - requested_recipes = arg + CLIOpts.requested_recipes = arg end end -if File.exists? configuration_file - context.read_configuration configuration_file -elsif configuration_file_requested - STDERR.puts "ERROR: configuration file '#{configuration_file}' does not exist" + +# Verify package-create dependencies: tar, strip +Do.require_cmd "tar" +Do.require_cmd "strip" + +if File.exists? CLIOpts.configuration_file + context.read_configuration CLIOpts.configuration_file +elsif CLIOpts.configuration_file_requested + STDERR.puts "ERROR: configuration file '#{CLIOpts.configuration_file}' does not exist" exit 1 end -if only_print_configuration +if CLIOpts.only_print_configuration pp! context exit 0 end -found_recipes = requested_recipes.map do |name| +found_recipes = CLIOpts.requested_recipes.map do |name| context.find_recipe(name) || name end @@ -126,7 +133,7 @@ end # FIXME: Now we need to build their respective deptrees and to deduplicate # the list of recipes. -if watch_only +if CLIOpts.watch_only if recipes.size == 0 context.repositories.each do |repo| Dir.children(repo).each do |i| @@ -142,6 +149,10 @@ if watch_only exit 0 end +# TODO: verify package-create dependencies: +# - rsync +# - tar (bsdtar) + begin latest_build_dir = "" @@ -152,14 +163,13 @@ begin end end - if print_deps + if CLIOpts.print_deps puts dependencies.join "\n" exit 0 end - if dependencies.size > 0 && ! skip_build_dependencies && !download_only - # TODO: change this. We want other backends. - # TODO: write something in Context + # Install build dependencies + if dependencies.size > 0 && ! CLIOpts.skip_build_dependencies && !CLIOpts.download_only context.install dependencies end @@ -170,14 +180,14 @@ begin recipe.download - next if download_only + next if CLIOpts.download_only recipe.extract recipe.build recipe.package - recipe.clean unless do_not_clean + recipe.clean unless CLIOpts.do_not_clean end rescue e : Package::Exception STDERR.puts "!! #{e.message}".colorize(:red).bright @@ -188,4 +198,3 @@ rescue e STDERR.puts e exit 1 end - diff --git a/src/recipe.cr b/src/recipe.cr index 846fd7f..b4b3df5 100644 --- a/src/recipe.cr +++ b/src/recipe.cr @@ -227,7 +227,7 @@ class Package::Recipe end def extract - Dir.mkdir_p building_directory + @context.mkdir_p building_directory sources.each do |url| basename = url.filename @@ -278,7 +278,7 @@ class Package::Recipe # goes somehow wrong. # - Make things thread-safe. (those ENV[]= calls are definitely not) def build - Dir.mkdir_p fake_root_directory + @context.mkdir_p fake_root_directory ENV["PKG"] = fake_root_directory @@ -354,19 +354,19 @@ class Package::Recipe end if files_to_split.size > 0 - @context.info "Splitting '#{package.name}'" + @context.info "Splitting " + "'#{package.name}'".colorize(:light_red).underline.to_s end # FIXME: What do we do if those are not on the filesystem? files_to_split.each do |file| origin = "#{fake_root_directory}#{file}" - destination ="#{package.fake_root_directory}#{file}" + destination = "#{package.fake_root_directory}#{file}" @context.detail "Moving '#{file}' to split" - Dir.mkdir_p File.dirname destination + @context.mkdir_p File.dirname destination - FileUtils.mv( + @context.mv( "#{fake_root_directory}#{file}", "#{package.fake_root_directory}#{file}" ) @@ -386,12 +386,12 @@ class Package::Recipe def package # This tries to build them all and stops at the first failure # (failures are currently reported by Context#package) - (@packages + auto_splits).each do |package| + (auto_splits + @packages).each do |package| if package.automatic && ! File.exists? package.fake_root_directory next end - @context.info "Assempling '#{package.name}'" + @context.info "Assembling " + "'#{package.name}'".colorize(:light_red).underline.to_s unless @context.package package raise PackagingError.new self, package