diff --git a/src/backends.cr b/src/backends.cr new file mode 100644 index 0000000..168e8ae --- /dev/null +++ b/src/backends.cr @@ -0,0 +1,61 @@ +require "./quadruplet.cr" + +abstract class RootFS::Backend + class_getter name : String = "" + + def name : String + @@name + end + + # FIXME: Remove @application once `def execute` is moved in the current + # class. + def initialize(@directory : String, @application : ::RootFS::RootFS) + end + + abstract def create!(architecture : String?, version : String?, variant : String?) + #abstract def add_package(name : String) + #abstract def remove_package(name : String) + + class_property all = Array(::RootFS::Backend.class).new + + macro register(name) + class ::RootFS::Backend::{{name.camelcase.id}} < ::RootFS::Backend + def self.name : String + {{name}} + end + + {{yield}} + end + + ::RootFS::Backend.all << ::RootFS::Backend::{{name.camelcase.id}} + end +end + +RootFS::Backend.register "debian" do + class_getter name : String = "debian" + + def create!(architecture = nil, version = nil, variant = nil) + version = version || "buster" + architecture = architecture || "amd64" + + @application.execute "debootstrap --arch '#{architecture}' '#{version}' '#{@directory}'" + end +end + +RootFS::Backend.register "alpine" do + def create!(architecture = nil, version = nil, variant = nil) + version = version || "latest-stable" + + if version == "latest" + version = "latest-stable" + elsif version == "latest-stable" || version == "edge" + else + version = "v" + version + end + + arch = architecture || "x86_64" + + @application.execute "apk --arch '#{arch}' -X http://dl-cdn.alpinelinux.org/alpine/#{version}/main/ -U --allow-untrusted --root '#{@directory}' --initdb add alpine-base" + end +end + diff --git a/src/main.cr b/src/main.cr index 97f3668..d18f9fc 100644 --- a/src/main.cr +++ b/src/main.cr @@ -2,6 +2,9 @@ require "colorize" require "option_parser" require "file_utils" +require "./quadruplet.cr" +require "./backends.cr" + # Not currently used. Waiting for API updates. #require "baguette-crystal-base" @@ -141,11 +144,7 @@ class RootFS::RootFS end protected def create!(template : String) - template_as_array = template.split /-/ - - template_name = template_as_array[0].downcase - template_version = template_as_array[1]? - template_architecture = template_as_array[2]? + quadruplet = Quadruplet.new template is_btrfs = true # FIXME: do the actual detection @@ -153,27 +152,17 @@ class RootFS::RootFS raise "can only create rootfs in a btrfs filesystem" end + unless backend = Backend.all.find &.name.==(quadruplet.name) + error "unrecognized quadruplet name: #{quadruplet.name}" + exit 2 + end + execute "btrfs subvolume create '#{@directory}'" - if template_name == "debian" - version = template_version || "buster" + # FIXME: We should homogeneize quadruplet components. + backend.new(@directory, self).create! quadruplet.architecture, quadruplet.version, quadruplet.variant - execute "debootstrap --arch amd64 '#{version}' '#{@directory}'" - elsif template_name == "alpine" - version = template_version || "latest-stable" - - if version == "latest" - version = "latest-stable" - elsif version == "latest-stable" || version == "edge" - else - version = "v" + version - end - - # FIXME: We should homogeneize triplets. - arch = template_architecture || "x86_64" - - execute "apk --arch '#{arch}' -X http://dl-cdn.alpinelinux.org/alpine/#{version}/main/ -U --allow-untrusted --root '#{@directory}' --initdb add alpine-base" - end + File.write template, "#{@directory}/rootfs" end def self.load(directory) diff --git a/src/quadruplet.cr b/src/quadruplet.cr new file mode 100644 index 0000000..816ee81 --- /dev/null +++ b/src/quadruplet.cr @@ -0,0 +1,15 @@ +class RootFS::Quadruplet + getter name : String + getter version : String? + getter architecture : String? + getter variant : String? + + def initialize(template : String) + template_as_array = template.split /-/ + + @name = template_as_array[0].downcase + @version = template_as_array[1]? + @architecture = template_as_array[2]? + @variant = template_as_array[3]? + end +end