package/src/package/context.cr

177 lines
3.6 KiB
Crystal
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

require "colorize"
require "uuid"
require "file_utils"
require "../io.cr"
require "./weird.cr"
class Package::Context < Weird::Context
property root = "/"
# Stores informations about already installed packages, their
# manifests, and so on.
@database = Database.new
def initialize()
end
def root=(@root)
@database.root = "#{@root}#{Database::PATH_FROM_ROOT}"
end
def install(package : Package, data_directory : String)
end
# FIXME: Should atomic upgrades be handled here?
def install(files : Array(String))
work_dirs = Hash(String, String).new
manifests = Hash(String, Manifest).new
packages = Hash(String, Package).new
files.each do |file|
work_dir = get_work_directory
data_dir = "#{work_dir}/data"
work_dirs[file] = work_dir
Weird.extract file, work_dir, data_dir
package = Package.new "#{work_dir}/control.spec"
packages[file] = package
if is_installed? package.to_atom
raise ::Package::Exception.new "Package '#{package.to_atom.to_s}' is already installed."
end
Manifest.new("#{work_dir}/manifest").tap do |manifest|
manifest.no_collisions! self
manifests[file] = manifest
end
# FIXME: Check signatures (not implemented in packages ATM).
end
files.each do |file|
info "Installing '#{file}'"
work_dir = work_dirs[file]
data_dir = "#{work_dir}/data"
package = packages[file]
manifest = manifests[file]
manifest.each do |entry|
if entry.type == "directory" && Dir.exists? entry.file
next
end
debug "++ #{entry.file}"
entry.install data_dir, @root
end
@database << {package, manifest}
FileUtils.rm_r work_dir
end
end
def install(file : String)
install [file]
end
def install(atoms : Array(Atom))
end
def install(atom : Atom)
install [atom]
end
def upgrade(atom : Atom)
end
def remove(packages : Array(Package))
# First part of this function is about extracting
# reverse-dependencies. Once we have them all, we remove
# everything one by one.
all_packages = @database.get_all_packages
packages_to_remove = [] of Package
unchecked_packages = Deque(Package).new
packages.each do |package|
unchecked_packages << package
end
while unchecked_packages.size > 0
package = unchecked_packages.pop
packages_to_remove << package
all_packages
.select do |p|
p.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
.each do |p|
if unchecked_packages.find &.==(p)
next
end
if packages_to_remove.find &.==(p)
next
end
unchecked_packages << p
end
end
packages_to_remove.reverse.each do |package|
manifest = @database.get_manifest package
manifest.reverse.each do |entry|
if entry.type == "directory" && (!Dir.exists?(entry.file) || !Dir.empty?(entry.file))
next
end
debug "-- #{entry.file}"
entry.remove @root
end
@database.remove package
end
end
def remove(package : Package)
remove [package]
end
def remove(atoms : Array(Atom))
remove atoms.map { |atom| @database.get_package atom }
end
def remove(atom : Atom)
remove [atom]
end
def installed_packages : Array(Package)
end
def is_installed?(atom : Atom)
@database.is_installed? atom
end
def update_repository_cache
end
def download_to_cache(atom : Atom, url : String)
end
def database_directory
end
def get_work_directory
directory = "/tmp/package-#{UUID.random}"
FileUtils.mkdir_p directory
directory
end
end