master
Luka Vandervelden 2019-11-02 20:59:08 +01:00
parent 24edb0a159
commit e458df0afd
6 changed files with 190 additions and 12 deletions

View File

@ -23,7 +23,7 @@ args.shift
begin
case command
when "add"
context.install args
context.install args.map { |s| Package::Atom.from_string s }
when "remove"
context.remove args.map { |s| Package::Atom.from_string s }
end

View File

@ -0,0 +1,29 @@
require "specparser"
class Package::Configuration
PATH_FROM_ROOT = "/etc/package.cfg"
getter file_path : String?
getter repositories = Array(Repository).new
getter cache_directory = "/var/cache/package"
def initialize
end
def initialize(@file_path : String)
specs = SpecParser.parse File.read @file_path.not_nil!
specs.sections.each do |section|
case section.name
when "repository"
@repositories << Repository.new(
File.read("#{section.options[0]}/repository.spec"),
section.options[0]
)
end
end
end
end

View File

@ -1,10 +1,13 @@
require "colorize"
require "uuid"
require "file_utils"
require "uri"
require "../io.cr"
require "./weird.cr"
require "./configuration.cr"
require "./repository.cr"
class Package::Context < Weird::Context
property root = "/"
@ -12,12 +15,16 @@ class Package::Context < Weird::Context
# Stores informations about already installed packages, their
# manifests, and so on.
@database = Database.new
@configuration = Configuration.new
@cache_directory = "/var/cache/package"
def initialize()
self.root = "/"
end
def root=(@root)
@database.root = "#{@root}#{Database::PATH_FROM_ROOT}"
@configuration = Configuration.new "#{@root}#{Configuration::PATH_FROM_ROOT}"
end
def install(package : Package, data_directory : String)
@ -81,11 +88,71 @@ class Package::Context < Weird::Context
install [file]
end
def install(atoms : Array(Atom))
unchecked_atoms = Deque.new atoms
packages_to_install = Array(Tuple(Repository, Package)).new
while unchecked_atoms.size > 0
atom = unchecked_atoms.pop
tuple = get_installable atom
if tuple.nil?
raise Exception.new "Could not find '#{atom}'."
end
packages_to_install << tuple
_, package = tuple
package.dependencies.each do |atom|
unless is_installed? atom
unchecked_atoms.push atom
end
end
end
#pp! packages_to_install.map &.[1].to_atom.to_s
packages_to_install.reverse.each do |tuple|
download tuple
end
# FIXME: Install everything here.
packages_to_install.reverse.each do |tuple|
repository, package = tuple
url = "#{repository.url}/#{package.file_path}"
install url
end
end
def install(atom : Atom)
install [atom]
end
def upgrade(atom : Atom)
warning "(unimplemented) upgrade(Atom)"
end
# XXX: Unimplemented.
def download(tuple : Tuple(Repository, Package))
repository, package = tuple
uri = URI.parse package.file_path
if uri.scheme == "http" || uri.scheme == "https"
FileUtils.mkdir_p @cache_directory
pp package.file_path
#File.write HTTP::Client.get
end
end
def get_installable(atom : Atom)
@configuration.repositories.each do |repository|
match = repository.find &.matches?(atom)
return {repository, match} if match
end
end
def remove(packages : Array(Package))
@ -106,14 +173,13 @@ class Package::Context < Weird::Context
packages_to_remove << package
all_packages
.select do |p|
p.dependencies.any? do |dependency|
# FIXME: Check full atoms and not just names.
.select(&.dependencies.any? do |dependency|
# FIXME: Check full atoms and not just names.
# FIXME: Checking theres no collision with world files is probably done around here.
packages_to_remove.find &.name.==(dependency)
end
end
# FIXME: Checking theres no collision with world files is probably done around here.
packages_to_remove.find &.matches? dependency
end)
.each do |p|
if unchecked_packages.find &.==(p)
next
@ -130,6 +196,8 @@ class Package::Context < Weird::Context
packages_to_remove.reverse.each do |package|
manifest = @database.get_manifest package
info "Removing '#{package.to_atom.to_s}'"
manifest.reverse.each do |entry|
if entry.type == "directory" && (!Dir.exists?(entry.file) || !Dir.empty?(entry.file))
next

View File

@ -28,7 +28,12 @@ class Package::Database
end
def is_installed?(atom : Atom)
Dir.exists? get_entry_path(atom)
if atom.slot.nil?
Dir.exists?(get_entry_path(atom)) &&
Dir.children(get_entry_path(atom)).size > 0
else
Dir.exists? get_entry_path(atom)
end
end
def get_package(atom : Atom)

View File

@ -8,7 +8,7 @@ class Package::Package
getter release : Int32
getter slot : String
getter dependencies = Array(String).new
getter dependencies = Array(Atom).new
getter file_path : String
@ -31,7 +31,9 @@ class Package::Package
when "slot"
slot = value.as_s
when "dependencies"
@dependencies = value.as_a_or_s
@dependencies = value.as_a_or_s.map do |s|
Atom.from_string s
end
end
end
@ -41,9 +43,48 @@ class Package::Package
@slot = slot.not_nil!
end
def initialize(section : SpecParser::Section)
@file_path, @name, @version, release, @slot = section.options[0].split " "
@release = release.to_i
section.content.each do |key, value|
case key
when "dependencies"
@dependencies = value.as_a_or_s.map do |s|
Atom.from_string s
end
end
end
end
def to_atom
Atom.new @name, slot: @slot
end
def matches?(atom : Atom)
return false unless @name == atom.name
if slot = atom.slot
return false unless @slot == atom.slot
end
true
end
# Returns Array({package, file_name})
def self.parse_repository_index(file_path : String) : Array(Package)
output = Array(Tuple(Package, String)).new
specs = SpecParser.parse File.read file_path
specs.sections.each do |section|
case section.name
when "package"
package = Package.new section
output << {package, file_name}
end
end
output
end
end

35
src/package/repository.cr Normal file
View File

@ -0,0 +1,35 @@
require "specparser"
require "./exception.cr"
class Package::Package
def initialize(section : SpecParser::Section)
@file_name, @name, @version, release, @slot = section.options[0].split " "
@release = release.to_i
section.content.each do |key, value|
case key
when "dependencies"
@dependencies = value.as_a_or_s
end
end
end
end
class Package::Repository < Array(Package::Package)
getter url : String
def initialize(index_body : String, @url)
initialize
specs = SpecParser.parse index_body
specs.sections.each do |section|
case section.name
when "package"
self << ::Package::Package.new section
end
end
end
end