From 09feb190733a00fa1fd2a276bf3e389ddcbe22eb Mon Sep 17 00:00:00 2001 From: Luka Vandervelden Date: Sat, 3 Aug 2019 12:55:47 +0200 Subject: [PATCH] CLI & removal of test recipes. --- src/context.cr | 18 ++ src/main.cr | 528 +++++++------------------------------------------ src/recipe.cr | 70 ++++++- 3 files changed, 154 insertions(+), 462 deletions(-) diff --git a/src/context.cr b/src/context.cr index 7601a7a..711f885 100644 --- a/src/context.cr +++ b/src/context.cr @@ -46,6 +46,9 @@ class Package::Context getter building_backends = [] of Backend::Building getter splitter_backends = [] of Backend::Splitter + # Directories where ports can be found. + getter repositories = [] of String + # Well, this will need configuration, auto-detection and conversion, # but it’ll be kind of enough for now. property architecture = "x86_64" @@ -181,5 +184,20 @@ class Package::Context def read_recipe(filename : String) Recipe.new self, filename end + + def find_recipe(name : String) : Recipe? + recipe_file_name = "" + + repo = @repositories.find do |repo| + repo_dir_name = "#{repo}/#{name}" + recipe_file_name = "#{repo_dir_name}/recipe.spec" + + if Dir.exists?(repo_dir_name) && File.exists?(recipe_file_name) + next true + end + end + + read_recipe recipe_file_name if repo + end end diff --git a/src/main.cr b/src/main.cr index 61b9f9a..a5f4912 100644 --- a/src/main.cr +++ b/src/main.cr @@ -1,478 +1,88 @@ +require "option_parser" +require "file_utils" +require "colorize" require "./context.cr" require "./recipe.cr" extend Package -# FIXME: recipe.clean? context autoclean? context = Context.new() context.packaging_backend = "apk" +context.repositories << "." -recipes = [] of Package::Recipe +requested_recipes = [] of String +download_only = false +do_not_clean = false -# FIXME: context.new_recipe? context.recipe? -recipes << Recipe.new(context, "hello", "2.10").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz" +used_X = false +OptionParser.parse! do |parser| + parser.banner = "Usage: package [options] >>" - # 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=/usr" - - recipe.url = "https://www.gnu.org/software/hello/" - recipe.description = "The GNU Hello program produces a familiar, friendly greeting." - recipe.dependencies << "gettext" - - # Should be automatic now. - #recipe.packages << Package::Package.new(recipe).tap do |package| - # package.name = "#{recipe.name}-man" - # package.files = ["/package/share/man"] - #end -end - -recipes << Recipe.new(context, "automake", "1.16").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/automake/automake-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "autoconf", "2.69").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/autoconf/autoconf-#{recipe.version}.tar.gz" - - recipe.dependencies << "m4" << "perl" -end - -recipes << Recipe.new(context, "libtool", "2.4.6").tap do |recipe| - recipe.sources << "http://ftpmirror.gnu.org/libtool/libtool-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "m4", "1.4.18").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/m4/m4-#{recipe.version}.tar.gz" - recipe.dependencies << "perl" -end - -recipes << Recipe.new(context, "bzip2", "1.0.6").tap do |recipe| - recipe.sources << "https://downloads.sourceforge.net/project/bzip2/bzip2-#{recipe.version}.tar.gz" - - recipe.instructions.configure << "sed -i.orig -e '/^CFLAGS=/s/.*/CFLAGS = -O2 -fPIC/' #{recipe.dirname}/Makefile" - recipe.options["make install"] = "PREFIX='#{recipe.fake_root_directory}/usr'" -end - -recipes << Recipe.new(context, "perl", "5.30.0").tap do |recipe| - recipe.sources << "https://www.cpan.org/src/5.0/perl-#{recipe.version}.tar.gz" - - recipe.dependencies << "zlib" << "bzip2" - - recipe.instructions.build << %( - set -e -x; - cd #{recipe.dirname}; - BUILD_ZLIB=0; - BUILD_BZIP2=0; - BZIP2_LIB=/usr/lib; - BZIP2_INCLUDE=/usr/inculde; - - export BUILD_ZLIB BUILD_BZIP2 BZIP2_LIB BZIP2_INCLUDE; - ./Configure -des \ - -Dcccdlflags='-fPIC' \ - -Dcccdlflags='-fPIC' \ - -Dccdlflags='-rdynamic' \ - -Dprefix=/usr \ - -Uprivlib=$_privlib \ - -Darchlib=$_archlib \ - -Dvendorprefix=/usr \ - -Dvendorlib=/usr/share/perl5/vendor_perl \ - -Dvendorarch=/usr/lib/perl5/vendor_perl \ - -Dsiteprefix=/usr/local \ - -Dsitelib=/usr/local/share/perl5/site_perl \ - -Dsitearch=/usr/local/lib/perl5/site_perl \ - -Dlocincpth=' ' \ - -Dcc=gcc \ - -Uoptimize="$CFLAGS" \ - -Duselargefiles \ - -Dusethreads \ - -Duseshrplib \ - -Dd_semctl_semun \ - -Dman1dir=/usr/share/man/man1 \ - -Dman3dir=/usr/share/man/man3 \ - -Dinstallman1dir=/usr/share/man/man1 \ - -Dinstallman3dir=/usr/share/man/man3 \ - -Dman1ext='1' \ - -Dman3ext='3pm' \ - -Dcf_by='Alpine' \ - -Ud_csh \ - -Dusenm \ - || return 1 - make libperl.so && make || return 1 - ) -end - -recipes << Recipe.new(context, "apk-tools", "2.10.4").tap do |recipe| - recipe.sources << "https://dev.alpinelinux.org/archive/apk-tools/apk-tools-#{recipe.version}.tar.xz" - - recipe.options["make"] = "LUAAPK= static" - - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/sbin'" - recipe.instructions.install << "cp apk-tools-#{recipe.version}/src/apk.static '#{recipe.fake_root_directory}/sbin/apk'" - - [ - "/var/lib/apk", - "/var/cache/misc", - "/etc/apk/keys", - "/etc/apk/protected_paths.d" - ].each do |dir| - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}#{dir}'" - end - - #recipe.build_dependencies << "zlib-dev" << "openssl-dev" << "linux-dev" -end - -recipes << Recipe.new(context, "abuild", "3.4.0").tap do |recipe| - recipe.sources << "https://dev.alpinelinux.org/archive/abuild/abuild-#{recipe.version}.tar.xz" -end - -recipes << Recipe.new(context, "pkg-config", "0.29.2").tap do |recipe| - recipe.sources << "http://pkgconfig.freedesktop.org/releases/pkg-config-#{recipe.version}.tar.gz" - - # FIXME: We’ll want to remove this at some point. - recipe.options["configure"] = "--with-internal-glib" -end - -recipes << Recipe.new(context, "tar", "1.32").tap do |recipe| - recipe.sources << "http://ftp.gnu.org/gnu/tar/tar-#{recipe.version}.tar.gz" - recipe.options["configure"] = "FORCE_UNSAFE_CONFIGURE=1" -end - -recipes << Recipe.new(context, "libarchive", "3.3.3").tap do |recipe| - recipe.sources << "https://www.libarchive.org/downloads/libarchive-#{recipe.version}.tar.gz" - - # Conflicts with “tar” (gnu tar) - #recipe.instructions.install << "cd #{recipe.dirname} && make DESTDIR='#{recipe.fake_root_directory}' install" - #recipe.instructions.install << "cd '#{recipe.fake_root_directory}' && ln -s /usr/bin/bsdtar usr/bin/tar" -end - -# FIXME: Build and install the actual kernel. -recipes << Recipe.new(context, "linux", "5.2.4").tap do |recipe| - recipe.sources << "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-#{recipe.version}.tar.xz" - - recipe.instructions.build << "true" - - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/usr'" - recipe.instructions.install << "cd '#{recipe.dirname}' && make headers_install ARCH=x86_64 INSTALL_HDR_PATH='#{recipe.fake_root_directory}/usr'" -end - -recipes << Recipe.new(context, "make", "4.2").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/make/make-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "zlib", "1.2.11").tap do |recipe| - recipe.sources << "https://www.zlib.net/zlib-#{recipe.version}.tar.gz" -end - -# Be careful with that one. It’s not configured to use proper prefixes. -# (Not sure that it should though. It’s gotta put things in /sbin anyway.) -recipes << Recipe.new(context, "sysvinit", "2.95").tap do |recipe| - recipe.sources << "https://git.savannah.nongnu.org/cgit/sysvinit.git/snapshot/sysvinit-#{recipe.version}.tar.gz" - recipe.url = "https://savannah.nongnu.org/projects/sysvinit" - recipe.description = "System V-like init system." - recipe.dependencies << "util-linux" - - recipe.instructions.install << "cd sysvinit-#{recipe.version} && make ROOT='#{recipe.fake_root_directory}' install" -end - -recipes << Recipe.new(context, "musl", "1.1.23").tap do |recipe| - recipe.sources << "https://www.musl-libc.org/releases/musl-#{recipe.version}.tar.gz" - recipe.url = "https://www.musl-libc.org/" - recipe.description = "The musl c library (libc) implementation." - recipe.options["configure"] = "--prefix=/usr --libdir=/lib --syslibdir=/lib --enable-shared --enable-static" - # FIXME: We need to make a few symlinks (libm.so, libpthread.so, librt.so, libdl.so.) - # FIXME: We should probably add a ldd script too. -end - -recipes << Recipe.new(context, "libffi", "3.2.1").tap do |recipe| - recipe.sources << "ftp://sourceware.org/pub/libffi/libffi-#{recipe.version}.tar.gz" - - recipe.instructions.install << %{ - set -e; - cd #{recipe.dirname}; - make DESTDIR="#{recipe.fake_root_directory}" install; - cd "#{recipe.fake_root_directory}"; - mv usr/lib/libffi-#{recipe.version}/include usr; - nuke usr/lib/libffi-#{recipe.version} - } -end - -recipes << Recipe.new(context, "python", "3.7.4").tap do |recipe| - recipe.sources << "https://www.python.org/ftp/python/#{recipe.version}/Python-#{recipe.version}.tgz" - recipe.dirname = "Python-#{recipe.version}" -end - -recipes << Recipe.new(context, "crystal", "0.29.9").tap do |recipe| - # FIXME: Arrows, ASAP. - #recipe.sources << "https://github.com/crystal-lang/crystal/archive/#{recipe.version}.tar.gz" - - recipe.dirname = "crystal-8b3dba72bd681118b2b761c68d7d2fdcbbbfceb2" - recipe.sources << "https://github.com/crystal-lang/crystal/archive/8b3dba72bd681118b2b761c68d7d2fdcbbbfceb2.zip" - - recipe.dependencies << "libyaml" << "libevent" << "pcre" << "openssl" - - recipe.options["make"] = "release=1 LLVM_CONFIG=/usr/bad/llvm-6/bin/llvm-config" - recipe.instructions.install << %{ - set -e - cd #{recipe.dirname}; - PKG="#{recipe.fake_root_directory}"; - mkdir -p "$PKG/usr/bin"; - mkdir -p "$PKG/usr/lib/crystal/core"; - mkdir -p "$PKG/usr/share/man/man1"; - - install -D -m 755 .build/crystal "$PKG"/usr/bin/crystal; - install -D -m 644 man/crystal.1 "$PKG"/usr/share/man/man1/crystal.1; - cp -r src/* "$PKG/usr/lib/crystal/core"; - cd "$PKG/usr/lib/crystal/core"; - nuke ext/sigfault.* llvm/ext/llvm_ext.o - } -end - -[{"6", "6.0.1"}, {"7", "7.1.0"},{"8", "8.0.0"}].each do |branch, version| - recipes << Recipe.new(context, "llvm-#{branch}", version).tap do |recipe| - recipe.sources << "http://releases.llvm.org/#{recipe.version}/llvm-#{recipe.version}.src.tar.xz" - recipe.url = "http://llvm.org" - recipe.description = "The LLVM Project is a collection of modular and reusable compiler and toolchain technologies." - - recipe.dependencies << "libffi" - - # Build-deps. - #recipe.build_dependencies << "cmake" - #recipe.build_dependencies << "make" - #recipe.build_dependencies << "libffi-dev" - #recipe.build_dependencies << "musl-dev" - - recipe.instructions.configure << "mkdir #{recipe.name}-#{recipe.version}" - # FIXME: BROKEN - recipe.instructions.configure << <<-EOF - cd #{recipe.name}-#{recipe.version} && \ - cmake ../llvm-#{recipe.version}.src \ - -DCMAKE_INSTALL_PREFIX=/usr/bad/llvm-#{branch} \ - -DLLVM_BUILD_DOCS=OFF \ - -DLLVM_BUILD_EXAMPLES=OFF \ - -DLLVM_BUILD_EXTERNAL_COMPILER_RT=ON \ - -DLLVM_BUILD_LLVM_DYLIB=ON \ - -DLLVM_ENABLE_ASSERTIONS=OFF \ - -DLLVM_ENABLE_CXX1Y=ON \ - -DLLVM_ENABLE_FFI=ON \ - -DLLVM_ENABLE_LIBCXX=OFF \ - -DLLVM_ENABLE_PIC=ON \ - -DLLVM_ENABLE_RTTI=ON \ - -DLLVM_ENABLE_SPHINX=OFF \ - -DLLVM_ENABLE_TERMINFO=ON \ - -DLLVM_ENABLE_ZLIB=ON \ - -DLLVM_INCLUDE_EXAMPLES=OFF \ - -DLLVM_LINK_LLVM_DYLIB=ON \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_CXX_FLAGS="-fPIC -O2" \ - -DCMAKE_C_FLAGS="-fPIC -O2" -EOF - - recipe.instructions.build << "pwd && ls && cd #{recipe.name}-#{recipe.version} && make" - recipe.instructions.install << "cd #{recipe.name}-#{recipe.version} && make DESTDIR='#{recipe.fake_root_directory}' install" - end -end - -recipes << Recipe.new(context, "cmake", "3.15.1").tap do |recipe| - recipe.sources << "https://github.com/Kitware/CMake/releases/download/v3.15.1/cmake-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "gmp", "6.1.2").tap do |recipe| - recipe.sources << "https://gmplib.org/download/gmp/gmp-#{recipe.version}.tar.xz" -end - -recipes << Recipe.new(context, "mpfr", "4.0.2").tap do |recipe| - recipe.sources << "https://www.mpfr.org/mpfr-current/mpfr-#{recipe.version}.tar.xz" -end - -recipes << Recipe.new(context, "mpc", "1.1.0").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/mpc/mpc-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "gcc", "9.1.0").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/gcc/gcc-9.1.0/gcc-#{recipe.version}.tar.xz" - - recipe.dependencies << "gmp" << "mpfr" << "mpc" << "binutils" - - recipe.dirname = "build" - recipe.instructions.configure << %( - set -e; - mkdir build; - cd build; - sed -e '/m64=/s/lib64/lib/' \ - -i.orig ../gcc-#{recipe.version}/gcc/config/i386/t-linux64; - ../gcc-#{recipe.version}/configure \ - --prefix=/usr \ - --libdir=/usr/lib \ - --disable-multilib \ - --disable-libssp \ - --disable-libmpx \ - --disable-libmudflap \ - --disable-libsanitizer \ - --disable-nls \ - --disable-werror \ - --enable-languages=c,c++ \ - --target=x86_64-junk-linux-musl \ - --build=x86_64-junk-linux-musl \ - --host=x86_64-junk-linux-musl - ) -end - -recipes << Recipe.new(context, "zsh", "5.7.1").tap do |recipe| - recipe.sources << "https://downloads.sourceforge.net/project/zsh/zsh/#{recipe.version}/zsh-#{recipe.version}.tar.xz" - recipe.url = "https://zsh.org" - recipe.description = "Zsh is a shell designed for interactive use, although it is also a powerful scripting language." - recipe.dependencies << "ncurses" - recipe.options["configure"] = "--with-tcsetpgrp" - - # Build-deps. - #recipe.build_dependencies << "ncurses-dev" -end - -recipes << Recipe.new(context, "ncurses", "6.1").tap do |recipe| - recipe.sources << "ftp://ftp.invisible-island.net/ncurses/ncurses-#{recipe.version}.tar.gz" - recipe.url = "https://www.gnu.org/software/ncurses/" - recipe.options["configure"] = "--enable-widec --without-ada --with-shared --enable-pc-files --disable-termcap" - - recipe.instructions.install << "cd ncurses-#{recipe.version} && make 'DESTDIR=#{recipe.fake_root_directory}' install" - - # Already provided bu busybox. - recipe.instructions.install << "cd '#{recipe.fake_root_directory}' && rm usr/bin/clear usr/bin/reset" -end - -recipes << Recipe.new(context, "busybox", "1.31.0").tap do |recipe| - recipe.sources << "https://busybox.net/downloads/busybox-#{recipe.version}.tar.bz2" - - recipe.instructions.configure << "cd busybox-#{recipe.version} && make defconfig" - recipe.instructions.configure << "sed -i -e 's/.*CONFIG_STATIC.*/CONFIG_STATIC=y/' busybox-#{recipe.version}/.config" - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/bin'" - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/sbin'" - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/usr/bin'" - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/usr/sbin'" - recipe.instructions.install << "cp busybox-#{recipe.version}/busybox '#{recipe.fake_root_directory}/bin/busybox'" - recipe.instructions.install << "chroot '#{recipe.fake_root_directory}' /bin/busybox --install -s" - - #recipe.build_dependencies << "linux-dev" -end - -recipes << Recipe.new(context, "rc", "0.0.1").tap do |recipe| - recipe.sources << "https://git.karchnu.fr/JunkOS/rc/archive/579e431144e33b2510260b1bce5505fd328d2961.tar.gz" - - # Those two are required due to a lack of robustness in our current backends. - recipe.instructions.configure << "true" - recipe.instructions.build << "true" - - recipe.instructions.install << "mkdir -p '#{recipe.fake_root_directory}/etc'" - recipe.instructions.install << "cp rc/* '#{recipe.fake_root_directory}/etc/'" -end - -recipes << Recipe.new(context, "libyaml", "0.2.2").tap do |recipe| - recipe.sources << "https://github.com/yaml/libyaml/archive/#{recipe.version}.tar.gz" - - recipe.instructions.configure << "cd libyaml-#{recipe.version} && ./bootstrap && ./configure --prefix=/usr" - - # recipe.build_dependencies << "autoconf" << "libtool" -end - -# FIXME: This one will fail on non-x86_64 platforms. Also on non-linux -# platforms. This build script is total shit. -recipes << Recipe.new(context, "openssl", "1.1.1c").tap do |recipe| - recipe.sources << "https://www.openssl.org/source/openssl-#{recipe.version}.tar.gz" - - recipe.instructions.configure << "cd openssl-#{recipe.version} && ./Configure --prefix=/usr linux-x86_64" -end - -recipes << Recipe.new(context, "libevent", "2.1.10").tap do |recipe| - recipe.sources << "https://github.com/libevent/libevent/releases/download/release-#{recipe.version}-stable/libevent-#{recipe.version}-stable.tar.gz" - - recipe.dirname = "libevent-#{recipe.version}-stable" -end - -recipes << Recipe.new(context, "pcre2", "10.33").tap do |recipe| - recipe.sources << "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre2-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "pcre", "8.43").tap do |recipe| - recipe.sources << "ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-#{recipe.version}.tar.gz" - - recipe.options["configure"] = %( \ - --enable-utf8 \ - --enable-unicode-properties \ - --enable-pcre8 \ - --enable-pcre16 \ - --enable-pcre32 \ - --with-match-limit-recursion=8192 - ) -end - -recipes << Recipe.new(context, "binutils", "2.32").tap do |recipe| - recipe.sources << "https://ftp.gnu.org/gnu/binutils/binutils-#{recipe.version}.tar.xz" - - recipe.options["configure"] = %( \ - --disable-multilib \ - --with-pic --disable-nls - ) - recipe.options["make"] = "tooldir=/usr" - recipe.instructions.install << "cd #{recipe.dirname} && make 'DESTDIR=#{recipe.fake_root_directory}' tooldir=/usr install && rm '#{recipe.fake_root_directory}/usr/bin/strings'" -end - -recipes << Recipe.new(context, "readline", "8.0").tap do |recipe| - recipe.sources << "ftp://ftp.gnu.org/gnu/readline/readline-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "gc", "8.0.4").tap do |recipe| - recipe.sources << "https://github.com/ivmai/bdwgc/releases/download/v#{recipe.version}/gc-#{recipe.version}.tar.gz" -end - -recipes << Recipe.new(context, "clang", "8.0.1").tap do |recipe| - recipe.sources << "https://github.com/llvm/llvm-project/releases/download/llvmorg-#{recipe.version}/cfe-#{recipe.version}.src.tar.xz" - recipe.dirname = "build" - - recipe.instructions.configure << "mkdir build && cd build && cmake ../cfe-#{recipe.version}.src -DCMAKE_PREFIX_PATH=/usr/bad/llvm-8 -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release" -end - -recipes << Recipe.new(context, "service", "0.0.1").tap do |recipe| - recipe.sources << "" # FIXME -end - -if ARGV.size == 0 || ARGV[0]? == "-h" - pp recipes.map &.name - exit 0 -end - -selected_recipes = ARGV.map do |name| - recipes.find(&.name.==(name)) || name -end - -if selected_recipes.any? &.is_a?(String) - puts "At least one of the requested recipes is not known." - - selected_recipes.select! &.is_a?(String) - pp! selected_recipes - end - - # Getting rid of Strings. - selected_recipes = selected_recipes.compact_map do |recipe| - if recipe.is_a? String - nil - else - recipe + parser.on("-X DIR", "--repository DIR", "Sets a ports repository for finding dependencies (default=.).") { |dir| + unless used_X + while context.repositories.pop? + end + used_X = true end + + context.repositories << dir + } + + parser.on("-D", "--download-only", "Only download sources, do not build.") { + download_only = true + } + + parser.on("-k", "--keep-work-dir", "Do not clean after building.") { + do_not_clean = true + } + + parser.invalid_option do |flag| + STDERR.puts "ERROR: #{flag} is not a valid option." + STDERR.puts parser + exit(1) end - selected_recipes.each do |recipe| - pp recipe + parser.unknown_args do |arg| + requested_recipes = arg + end +end - raise "oh no, download failed" unless recipe.download - raise "oh no, extraction failed" unless recipe.extract +found_recipes = requested_recipes.map do |name| + puts context.find_recipe(name) + context.find_recipe(name) || name +end - raise "oh no, build failed" unless recipe.build - raise "oh no, packaging failed" unless recipe.package +invalid_recipes = found_recipes.select &.is_a?(String) +if invalid_recipes.size > 0 + STDERR.puts "ERROR: some of the requested recipes could not be found:" + invalid_recipes.each do |name| + STDERR.puts " - #{name}" + end + STDERR.puts " (try using -X?)" +end - recipe.clean +recipes = found_recipes.compact_map do |recipe_or_string| + recipe_or_string unless recipe_or_string.is_a?(String) +end + +# FIXME: Now we need to build their respective deptrees and to deduplicate +# the list of recipes. + +recipes.each do |recipe| + puts " >> #{recipe.name}".colorize :white + + raise "oh no, download failed" unless recipe.download + + if download_only + exit 0 end + raise "oh no, extraction failed" unless recipe.extract + + raise "oh no, build failed" unless recipe.build + raise "oh no, packaging failed" unless recipe.package + + recipe.clean unless do_not_clean +end + diff --git a/src/recipe.cr b/src/recipe.cr index ea13160..d1e6f29 100644 --- a/src/recipe.cr +++ b/src/recipe.cr @@ -131,10 +131,10 @@ class Package::Recipe "pkg" => fake_root_directory } - raise "Could not parse `#{filename}`" if specs.nil? + name : String? = nil + version : String? = nil - @name = "" # Needed to avoid build-time errors. - @version = "" # Same. + raise "Could not parse `#{filename}`" if specs.nil? specs.assignments.each do |key, value| case key @@ -352,5 +352,69 @@ class Package::Recipe def to_s "#{name}-#{version}" end + + def to_spec_s + spec = [ + "name: #{name}", + "version: #{version}", + "release: #{release}" + ].join("\n") + "\n" + + if @sources.size == 1 + spec += "sources: #{sources[0].to_s.gsub @version, "%{version}"}\n" + end + + if maintainer + spec += "maintainer: #{maintainer}\n" + end + if packager + spec += "packager: #{packager}\n" + end + + if @options.size > 0 + spec += "options:\n" + @options.each do |key, value| + value = value.gsub fake_root_directory, "%{pkg}" + spec += "\t- #{key}: #{value}\n" + end + spec += "\n" # Limitation of the current implementation. + end + + if @dependencies.size > 0 + spec += "dependencies:\n" + @dependencies.each do |dep| + spec += "\t- #{dep}\n" + end + spec += "\n" + end + + if @dirname + spec += "dirname: #{@dirname}\n" + end + + [ + {"configure", @instructions.configure}, + {"build", @instructions.build}, + {"install", @instructions.install} + ].each do |name, instructions| + if instructions.size > 0 + spec += "@#{name}\n" + instructions.each do |line| + line = line.gsub /^\t* *\n/, "" + line = line.gsub /\n *\t*\n/, "\n" + line = line.gsub /\n *\t*$/, "" + line = line.gsub fake_root_directory, "%{pkg}" + line = line.gsub name, "%{name}" + line = line.gsub version, "%{version}" + line = line.gsub dirname, "%{dirname}" + line = line.gsub(/^[\t ]*/, "").gsub(/\n\t*/, "\n\t") + spec += "\t#{line}\n" + end + spec += "\n" # Limitation of the current implementation. + end + end + + spec + end end