From 1a48ffbf222f4b82f3be86db70739efb79238349 Mon Sep 17 00:00:00 2001 From: Roberto Alsina Date: Fri, 5 Jul 2024 15:27:27 -0300 Subject: [PATCH] Refactor runtime code into reason --- src/commands/new.cr | 72 +++++---------------------------- src/funko.cr | 26 +++++------- src/runtime.cr | 98 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 77 deletions(-) create mode 100644 src/runtime.cr diff --git a/src/commands/new.cr b/src/commands/new.cr index e098994..36a4968 100644 --- a/src/commands/new.cr +++ b/src/commands/new.cr @@ -1,86 +1,34 @@ -require "rucksack" +require "../runtime.cr" module Faaso module Commands # Creates a new empty funko out of a given runtime struct New - @@known : Array(String) = {{`find ./runtimes -type d -mindepth 1`.split('\n').reject(&.empty?)}} - @@filelist : Array(String) = {{`find ./runtimes -type f -mindepth 1`.split('\n').reject(&.empty?)}} - def run(options, folder) : Int32 - Log.debug { "@@known: #{@@known}" } - Log.debug { "@@filelist: #{@@filelist}" } - runtime = options["-r"].as(String) # Give a list of known runtimes if runtime == "list" - Log.info { "Crystal has some included runtimes:\n" } - @@known.each do |i| - Log.info { " * #{Path[i].basename}" } - end - Log.info { "\nOr if you have your own, use a folder name" } + Runtime.list return 0 end - # Get runtime template files list - template_base = "" - template_files = [] of String - if @@known.includes? "./runtimes/#{runtime}" - Log.info { "Using known runtime #{runtime}" } - template_base = "./runtimes/#{runtime}/template" - template_files = @@filelist.select(&.starts_with?(template_base)) - elsif File.exists? runtime - Log.info { "Using directory #{runtime} as runtime" } - template_base = "#{runtime}/template" - template_files = Dir.glob("#{template_base}/**/*") - else - Log.error { "Can't find runtime #{runtime}" } - return 1 - end - # Create new folder if Dir.exists? folder Log.error { "Folder #{folder} already exists" } return 1 end - Dir.mkdir_p folder - - template_files.each do |t_file| - content = IO::Memory.new - # We need to use RUCKSACK_MODE=0 so it - # fallbacks to the filesystem - rucksack(t_file).read(content) - if content.nil? - Log.error { "Can't find file #{t_file}" } - return 1 - end - - # t_file is like "#{template_base}/foo" - # dst is like #{folder}/foo - dst = Path[folder] / Path[t_file].relative_to(template_base) - # Render templated files - if t_file.ends_with? ".j2" - dst = dst.sibling(dst.stem) - Log.info { " Creating file #{dst} from #{t_file}" } - File.open(dst, "w") do |file| - file << Crinja.render(content.to_s, {"name" => Path[folder].basename}) - end - else # Just copy the file - Log.info { " Creating file #{dst} from #{t_file}" } - File.open(dst, "w") do |file| - file << content.to_s - end - end - end + # Get runtime template files list + template_base, template_files = Runtime.template_files(runtime) + Runtime.copy_templated( + template_base, + template_files, + folder, + {"name" => Path[folder].basename} + ) 0 end end end end - -# Embed runtimes in the binary using rucksack -{% for name in `find ./runtimes -type f`.split('\n') %} - rucksack({{name}}) -{% end %} diff --git a/src/funko.cr b/src/funko.cr index 8de06a9..5d2ba1a 100644 --- a/src/funko.cr +++ b/src/funko.cr @@ -1,3 +1,4 @@ +require "./runtime.cr" require "crinja" require "file_utils" require "yaml" @@ -121,23 +122,18 @@ module Funko def prepare_build(path : Path) # Copy runtime if requested if !runtime.nil? - runtime_dir = Path.new("runtimes", runtime.as(String)) - raise Exception.new("Error: runtime #{runtime} not found for funko #{name} in #{path}") unless File.exists?(runtime_dir) - Dir.glob("#{runtime_dir}/*").each { |src| - FileUtils.cp_r(src, path) - } - # Replace templates with processed files - context = _to_context - Dir.glob("#{path}/**/*.j2").each { |template| - dst = template[..-4] - File.open(dst, "w") do |file| - file << Crinja.render(File.read(template), context) - end - File.delete template - } + # Get runtime files list + runtime_base, runtime_files = Runtime.runtime_files(runtime.as(String)) + + Runtime.copy_templated( + runtime_base, + runtime_files, + path.to_s, + _to_context + ) end - # Copy funko + # Copy funko on top of runtime raise Exception.new("Internal error: empty funko path for #{name}") if self.path.empty? Dir.glob("#{self.path}/*").each { |src| FileUtils.cp_r(src, path) diff --git a/src/runtime.cr b/src/runtime.cr new file mode 100644 index 0000000..a4b4b9a --- /dev/null +++ b/src/runtime.cr @@ -0,0 +1,98 @@ +require "rucksack" + +module Runtime + extend self + + @@known : Array(String) = {{`find ./runtimes -type d -mindepth 1`.split('\n').reject(&.empty?)}} + @@filelist : Array(String) = {{`find ./runtimes -type f -mindepth 1`.split('\n').reject(&.empty?)}} + + Log.debug { "@@known: #{@@known}" } + Log.debug { "@@filelist: #{@@filelist}" } + + def list + Log.info { "Crystal has some included runtimes:\n" } + @@known.each do |i| + Log.info { " * #{Path[i].basename}" } + end + Log.info { "\nOr if you have your own, use a folder name" } + end + + def self.runtime_files(runtime : String) : {String, Array(String)} + runtime_base = "" + runtime_files = [] of String + if @@known.includes? "./runtimes/#{runtime}" + Log.info { "Using known runtime #{runtime}" } + runtime_base = "./runtimes/#{runtime}/" + runtime_files = @@filelist.select(&.starts_with?(runtime_base)) + elsif File.exists? runtime + Log.info { "Using directory #{runtime} as runtime" } + runtime_base = "#{runtime}" + runtime_files = Dir.glob("#{runtime_base}/**/*") + else + raise Exception.new("Can't find runtime #{runtime}") + end + {runtime_base, runtime_files.reject(&.starts_with? "#{runtime_base}template")} + end + + def self.template_files(runtime : String) : {String, Array(String)} + template_base = "" + template_files = [] of String + if @@known.includes? "./runtimes/#{runtime}" + Log.info { "Using known runtime #{runtime}" } + template_base = "./runtimes/#{runtime}/template" + template_files = @@filelist.select(&.starts_with?(template_base)) + elsif File.exists? runtime + Log.info { "Using directory #{runtime} as runtime" } + template_base = "#{runtime}/template" + template_files = Dir.glob("#{template_base}/**/*") + else + raise Exception.new("Can't find runtime #{runtime}") + end + {template_base, template_files} + end + + # Copyes files from a runtime to a destination folder. + # Files ending in .j2 are rendered as Jinja2 templates + # using the provided context + def copy_templated( + base_path : String, + files : Array(String), + dst_path : String, + context + ) + Dir.mkdir_p dst_path + files.each do |file| + content = IO::Memory.new + # We need to use RUCKSACK_MODE=0 so it + # fallbacks to the filesystem. Read the + # file into a buffer + rucksack(file).read(content) + if content.nil? + raise Exception.new("Can't find file #{file}") + return 1 + end + + # file is like "#{base}/foo" + # dst is like #{dst_path}/foo + dst = Path[dst_path] / Path[file].relative_to(base_path) + # Render templated files + if file.ends_with? ".j2" + dst = dst.sibling(dst.stem) + Log.info { " Creating file #{dst} from #{file}" } + File.open(dst, "w") do |outf| + outf << Crinja.render(content.to_s, context) + end + else # Just copy the file + Log.info { " Creating file #{dst} from #{file}" } + File.open(dst, "w") do |outf| + outf << content.to_s + end + end + end + end +end + +# Embed runtimes in the binary using rucksack +{% for name in `find ./runtimes -type f`.split('\n') %} + rucksack({{name}}) +{% end %}