102 lines
2.1 KiB
Crystal
102 lines
2.1 KiB
Crystal
require "./exception.cr"
|
|
|
|
class ::Package::InvalidManifest < ::Package::Exception
|
|
def initialize(@message)
|
|
end
|
|
end
|
|
|
|
class ::Package::CollisionException < ::Package::Exception
|
|
getter collisions
|
|
def initialize(@message, @collisions : Array(String))
|
|
end
|
|
end
|
|
|
|
# FIXME: split Entry into File, Symlink and Directory
|
|
record Package::ManifestEntry, file : String, type : String, data : String? do
|
|
def install(origin_root, destination_root)
|
|
origin = "#{origin_root}/#{@file}"
|
|
destination = "#{destination_root}/#{@file}"
|
|
|
|
destination = destination.gsub /\/\.\//, "/"
|
|
destination = destination.gsub /\/\/*/, "/"
|
|
|
|
case @type
|
|
when "directory"
|
|
FileUtils.mkdir destination unless Dir.exists? destination
|
|
when "symlink"
|
|
link = File.readlink origin
|
|
File.symlink link, destination
|
|
when "file", "other"
|
|
FileUtils.cp origin, destination
|
|
end
|
|
end
|
|
|
|
def remove(root)
|
|
path = "#{root}/#{@file}"
|
|
|
|
path = path.gsub /\/\.\//, "/"
|
|
path = path.gsub /\/\/*/, "/"
|
|
|
|
case @type
|
|
when "file", "symlink", "other"
|
|
FileUtils.rm path
|
|
when "directory"
|
|
if Dir.children(path).size == 0
|
|
FileUtils.rmdir path
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
class Package::Manifest < Array(Package::ManifestEntry)
|
|
getter file_path : String
|
|
|
|
def initialize(size : Int32, @file_path)
|
|
initialize size
|
|
end
|
|
|
|
def self.new(file_path) : self
|
|
lines = File.read(file_path).lines
|
|
instance = self.new lines.size, file_path
|
|
|
|
lines.each do |line|
|
|
line = line.split ':'
|
|
|
|
file, type = line
|
|
data = line[2]?
|
|
|
|
instance << ManifestEntry.new file, type, data
|
|
end
|
|
|
|
instance
|
|
rescue e : Errno
|
|
raise e
|
|
rescue e
|
|
raise InvalidManifest.new "Could not parse Manifest: invalid entries"
|
|
end
|
|
|
|
def list_collisions(root : String)
|
|
collisions = [] of ManifestEntry
|
|
|
|
each do |entry|
|
|
case entry.type
|
|
when "file", "symlink", "other"
|
|
if File.exists? "#{root}/#{entry.file}"
|
|
collisions << entry
|
|
end
|
|
end
|
|
end
|
|
|
|
collisions
|
|
end
|
|
|
|
def no_collisions!(context)
|
|
collisions = list_collisions context.root
|
|
|
|
if collisions.size > 0
|
|
raise CollisionException.new "Collisions detected.", collisions.map &.file
|
|
end
|
|
end
|
|
end
|
|
|