refactor: use a better class hierarchy for filesystems
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
Glenn Y. Rolland 2023-11-21 00:30:59 +01:00
parent 8f2c2442a3
commit 994f9e1885
8 changed files with 123 additions and 115 deletions

View file

@ -97,7 +97,7 @@ module GX
end end
def mount() def mount()
names_display = {} of String => NamedTuple(filesystem: Filesystem, ansi_name: String) names_display = {} of String => NamedTuple(filesystem: Filesystem::AbstractFilesystem, ansi_name: String)
@config.filesystems.each do |filesystem| @config.filesystems.each do |filesystem|
fs_str = filesystem.type.ljust(12,' ') fs_str = filesystem.type.ljust(12,' ')

View file

@ -23,7 +23,7 @@ module GX
record AddArgs, name : String, path : String record AddArgs, name : String, path : String
record DelArgs, name : String record DelArgs, name : String
getter filesystems : Array(Filesystem) getter filesystems : Array(Filesystem::AbstractFilesystem)
getter home_dir : String getter home_dir : String
getter global_mount_point : String? getter global_mount_point : String?
property verbose : Bool property verbose : Bool
@ -39,7 +39,7 @@ module GX
@verbose = false @verbose = false
@mode = Mode::Mount @mode = Mode::Mount
@filesystems = [] of Filesystem @filesystems = [] of Filesystem::AbstractFilesystem
@path = nil @path = nil
@global_mount_point = nil @global_mount_point = nil
@ -75,7 +75,7 @@ module GX
path = detect_config_file() path = detect_config_file()
end end
@path = path @path = path
@filesystems = [] of Filesystem @filesystems = [] of Filesystem::AbstractFilesystem
if !File.exists? path if !File.exists? path
Log.error { "File #{path} does not exist!".colorize(:red) } Log.error { "File #{path} does not exist!".colorize(:red) }
@ -111,7 +111,7 @@ module GX
type = filesystem_data["type"].as_s type = filesystem_data["type"].as_s
name = filesystem_data["name"].as_s name = filesystem_data["name"].as_s
# encrypted_path = filesystem_data["encrypted_path"].as_s # encrypted_path = filesystem_data["encrypted_path"].as_s
@filesystems << Filesystem.from_yaml(filesystem_data.to_yaml) @filesystems << Filesystem::AbstractFilesystem.from_yaml(filesystem_data.to_yaml)
# @filesystems << Filesystem.new(name, encrypted_path, "#{name}.Open") # @filesystems << Filesystem.new(name, encrypted_path, "#{name}.Open")
end end
end end

View file

@ -6,4 +6,4 @@
require "./filesystems/gocryptfs" require "./filesystems/gocryptfs"
require "./filesystems/sshfs" require "./filesystems/sshfs"
require "./filesystems/httpdirfs" require "./filesystems/httpdirfs"
require "./filesystems/filesystem" require "./filesystems/abstract_filesystem"

View file

@ -0,0 +1,50 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "yaml"
module GX
module Filesystem
abstract class AbstractFilesystem
include YAML::Serializable
use_yaml_discriminator "type", {
gocryptfs: GoCryptFS,
sshfs: SshFS,
httpdirfs: HttpDirFS
}
property type : String
end
module FilesystemBase
def unmount
system("fusermount -u #{mount_dir.shellescape}")
fusermount_status = $?
if fusermount_status.success?
puts "Filesystem #{name} is now closed.".colorize(:green)
else
puts "Error: Unable to unmount filesystem #{name} (exit code: #{fusermount_status.exit_code}).".colorize(:red)
end
end
def mount(&block)
Dir.mkdir_p(mount_dir) unless Dir.exists?(mount_dir)
if mounted?
puts "Already mounted. Skipping.".colorize(:yellow)
return
end
yield
puts "Filesystem #{name} is now available on #{mount_dir}".colorize(:green)
end
end
end
end
require "./gocryptfs"
require "./sshfs"

View file

@ -1,48 +0,0 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland <glenux@glenux.net>
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "yaml"
module GX
abstract class Filesystem
include YAML::Serializable
use_yaml_discriminator "type", {
gocryptfs: GoCryptFS,
sshfs: SshFS,
httpdirfs: HttpDirFS
}
property type : String
end
module GenericFilesystem
def unmount
system("fusermount -u #{mount_dir.shellescape}")
fusermount_status = $?
if fusermount_status.success?
puts "Filesystem #{name} is now closed.".colorize(:green)
else
puts "Error: Unable to unmount filesystem #{name} (exit code: #{fusermount_status.exit_code}).".colorize(:red)
end
end
def mount(&block)
Dir.mkdir_p(mount_dir) unless Dir.exists?(mount_dir)
if mounted?
puts "Already mounted. Skipping.".colorize(:yellow)
return
end
yield
puts "Filesystem #{name} is now available on #{mount_dir}".colorize(:green)
end
end
end
require "./gocryptfs"
require "./sshfs"

View file

@ -4,42 +4,44 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "shellwords" require "shellwords"
require "./filesystem" require "./abstract_filesystem"
module GX module GX
class GoCryptFS < Filesystem module Filesystem
getter name : String = "" class GoCryptFS < AbstractFilesystem
getter encrypted_path : String = "" getter name : String = ""
getter encrypted_path : String = ""
@[YAML::Field(key: "mount_dir", ignore: true)] @[YAML::Field(key: "mount_dir", ignore: true)]
getter mount_dir : String = "" getter mount_dir : String = ""
include GenericFilesystem include FilesystemBase
def after_initialize() def after_initialize()
home_dir = ENV["HOME"] || raise "Home directory not found" home_dir = ENV["HOME"] || raise "Home directory not found"
@mount_dir = File.join(home_dir, "mnt/#{@name}.Open") @mount_dir = File.join(home_dir, "mnt/#{@name}.Open")
end end
def mounted? : Bool def mounted? : Bool
`mount`.includes?("#{encrypted_path} on #{mount_dir}") `mount`.includes?("#{encrypted_path} on #{mount_dir}")
end end
def mount def mount
super do super do
input = STDIN input = STDIN
output = STDOUT output = STDOUT
error = STDERR error = STDERR
process = Process.new( process = Process.new(
"gocryptfs", "gocryptfs",
["-idle", "15m", encrypted_path, mount_dir], ["-idle", "15m", encrypted_path, mount_dir],
input: input, input: input,
output: output, output: output,
error: error error: error
) )
unless process.wait.success? unless process.wait.success?
puts "Error mounting the vault".colorize(:red) puts "Error mounting the vault".colorize(:red)
return return
end
end end
end end
end end

View file

@ -4,17 +4,18 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "shellwords" require "shellwords"
require "./filesystem" require "./abstract_filesystem"
module GX module GX
class HttpDirFS < Filesystem module Filesystem
class HttpDirFS < AbstractFilesystem
getter name : String = "" getter name : String = ""
getter url : String = "" getter url : String = ""
@[YAML::Field(key: "mount_dir", ignore: true)] @[YAML::Field(key: "mount_dir", ignore: true)]
getter mount_dir : String = "" getter mount_dir : String = ""
include GenericFilesystem include FilesystemBase
def after_initialize() def after_initialize()
home_dir = ENV["HOME"] || raise "Home directory not found" home_dir = ENV["HOME"] || raise "Home directory not found"
@ -44,5 +45,6 @@ module GX
end end
end end
end end
end
end end

View file

@ -4,38 +4,39 @@
# Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net> # Copyright © 2023 Glenn Y. Rolland <glenux@glenux.net>
require "shellwords" require "shellwords"
require "./filesystem" require "./abstract_filesystem"
module GX module GX
class SshFS < Filesystem module Filesystem
getter name : String = "" class SshFS < AbstractFilesystem
getter remote_path : String = "" getter name : String = ""
getter remote_user : String = "" getter remote_path : String = ""
getter remote_host : String = "" getter remote_user : String = ""
getter remote_port : String = "22" getter remote_host : String = ""
getter remote_port : String = "22"
@[YAML::Field(key: "mount_dir", ignore: true)] @[YAML::Field(key: "mount_dir", ignore: true)]
getter mount_dir : String = "" getter mount_dir : String = ""
include GenericFilesystem include FilesystemBase
def after_initialize() def after_initialize()
home_dir = ENV["HOME"] || raise "Home directory not found" home_dir = ENV["HOME"] || raise "Home directory not found"
@mount_dir = File.join(home_dir, "mnt/#{@name}") @mount_dir = File.join(home_dir, "mnt/#{@name}")
end end
def mounted? : Bool def mounted? : Bool
`mount`.includes?("#{remote_user}@#{remote_host}:#{remote_path} on #{mount_dir}") `mount`.includes?("#{remote_user}@#{remote_host}:#{remote_path} on #{mount_dir}")
end end
def mount def mount
super do super do
input = STDIN input = STDIN
output = STDOUT output = STDOUT
error = STDERR error = STDERR
process = Process.new( process = Process.new(
"sshfs", "sshfs",
[ [
"-p", remote_port, "-p", remote_port,
"#{remote_user}@#{remote_host}:#{remote_path}", "#{remote_user}@#{remote_host}:#{remote_path}",
mount_dir mount_dir
@ -43,10 +44,11 @@ module GX
input: input, input: input,
output: output, output: output,
error: error error: error
) )
unless process.wait.success? unless process.wait.success?
puts "Error mounting the filesystem".colorize(:red) puts "Error mounting the filesystem".colorize(:red)
return return
end
end end
end end
end end