Various.
This commit is contained in:
parent
24edb0a159
commit
e458df0afd
@ -23,7 +23,7 @@ args.shift
|
|||||||
begin
|
begin
|
||||||
case command
|
case command
|
||||||
when "add"
|
when "add"
|
||||||
context.install args
|
context.install args.map { |s| Package::Atom.from_string s }
|
||||||
when "remove"
|
when "remove"
|
||||||
context.remove args.map { |s| Package::Atom.from_string s }
|
context.remove args.map { |s| Package::Atom.from_string s }
|
||||||
end
|
end
|
||||||
|
29
src/package/configuration.cr
Normal file
29
src/package/configuration.cr
Normal 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
|
||||||
|
|
@ -1,10 +1,13 @@
|
|||||||
require "colorize"
|
require "colorize"
|
||||||
require "uuid"
|
require "uuid"
|
||||||
require "file_utils"
|
require "file_utils"
|
||||||
|
require "uri"
|
||||||
|
|
||||||
require "../io.cr"
|
require "../io.cr"
|
||||||
|
|
||||||
require "./weird.cr"
|
require "./weird.cr"
|
||||||
|
require "./configuration.cr"
|
||||||
|
require "./repository.cr"
|
||||||
|
|
||||||
class Package::Context < Weird::Context
|
class Package::Context < Weird::Context
|
||||||
property root = "/"
|
property root = "/"
|
||||||
@ -12,12 +15,16 @@ class Package::Context < Weird::Context
|
|||||||
# Stores informations about already installed packages, their
|
# Stores informations about already installed packages, their
|
||||||
# manifests, and so on.
|
# manifests, and so on.
|
||||||
@database = Database.new
|
@database = Database.new
|
||||||
|
@configuration = Configuration.new
|
||||||
|
@cache_directory = "/var/cache/package"
|
||||||
|
|
||||||
def initialize()
|
def initialize()
|
||||||
|
self.root = "/"
|
||||||
end
|
end
|
||||||
|
|
||||||
def root=(@root)
|
def root=(@root)
|
||||||
@database.root = "#{@root}#{Database::PATH_FROM_ROOT}"
|
@database.root = "#{@root}#{Database::PATH_FROM_ROOT}"
|
||||||
|
@configuration = Configuration.new "#{@root}#{Configuration::PATH_FROM_ROOT}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def install(package : Package, data_directory : String)
|
def install(package : Package, data_directory : String)
|
||||||
@ -81,11 +88,71 @@ class Package::Context < Weird::Context
|
|||||||
install [file]
|
install [file]
|
||||||
end
|
end
|
||||||
def install(atoms : Array(Atom))
|
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
|
end
|
||||||
def install(atom : Atom)
|
def install(atom : Atom)
|
||||||
install [atom]
|
install [atom]
|
||||||
end
|
end
|
||||||
def upgrade(atom : Atom)
|
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
|
end
|
||||||
|
|
||||||
def remove(packages : Array(Package))
|
def remove(packages : Array(Package))
|
||||||
@ -106,14 +173,13 @@ class Package::Context < Weird::Context
|
|||||||
packages_to_remove << package
|
packages_to_remove << package
|
||||||
|
|
||||||
all_packages
|
all_packages
|
||||||
.select do |p|
|
.select(&.dependencies.any? do |dependency|
|
||||||
p.dependencies.any? do |dependency|
|
|
||||||
# FIXME: Check full atoms and not just names.
|
# FIXME: Check full atoms and not just names.
|
||||||
|
|
||||||
# FIXME: Checking there’s no collision with world files is probably done around here.
|
# FIXME: Checking there’s no collision with world files is probably done around here.
|
||||||
packages_to_remove.find &.name.==(dependency)
|
|
||||||
end
|
packages_to_remove.find &.matches? dependency
|
||||||
end
|
end)
|
||||||
.each do |p|
|
.each do |p|
|
||||||
if unchecked_packages.find &.==(p)
|
if unchecked_packages.find &.==(p)
|
||||||
next
|
next
|
||||||
@ -130,6 +196,8 @@ class Package::Context < Weird::Context
|
|||||||
packages_to_remove.reverse.each do |package|
|
packages_to_remove.reverse.each do |package|
|
||||||
manifest = @database.get_manifest package
|
manifest = @database.get_manifest package
|
||||||
|
|
||||||
|
info "Removing '#{package.to_atom.to_s}'"
|
||||||
|
|
||||||
manifest.reverse.each do |entry|
|
manifest.reverse.each do |entry|
|
||||||
if entry.type == "directory" && (!Dir.exists?(entry.file) || !Dir.empty?(entry.file))
|
if entry.type == "directory" && (!Dir.exists?(entry.file) || !Dir.empty?(entry.file))
|
||||||
next
|
next
|
||||||
|
@ -28,8 +28,13 @@ class Package::Database
|
|||||||
end
|
end
|
||||||
|
|
||||||
def is_installed?(atom : Atom)
|
def is_installed?(atom : 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)
|
Dir.exists? get_entry_path(atom)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_package(atom : Atom)
|
def get_package(atom : Atom)
|
||||||
if atom.slot.nil?
|
if atom.slot.nil?
|
||||||
|
@ -8,7 +8,7 @@ class Package::Package
|
|||||||
getter release : Int32
|
getter release : Int32
|
||||||
getter slot : String
|
getter slot : String
|
||||||
|
|
||||||
getter dependencies = Array(String).new
|
getter dependencies = Array(Atom).new
|
||||||
|
|
||||||
getter file_path : String
|
getter file_path : String
|
||||||
|
|
||||||
@ -31,7 +31,9 @@ class Package::Package
|
|||||||
when "slot"
|
when "slot"
|
||||||
slot = value.as_s
|
slot = value.as_s
|
||||||
when "dependencies"
|
when "dependencies"
|
||||||
@dependencies = value.as_a_or_s
|
@dependencies = value.as_a_or_s.map do |s|
|
||||||
|
Atom.from_string s
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -41,9 +43,48 @@ class Package::Package
|
|||||||
@slot = slot.not_nil!
|
@slot = slot.not_nil!
|
||||||
end
|
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
|
def to_atom
|
||||||
Atom.new @name, slot: @slot
|
Atom.new @name, slot: @slot
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
35
src/package/repository.cr
Normal file
35
src/package/repository.cr
Normal 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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user