From 994f9e1885a3188f808ff1416a87b74034a8a12b Mon Sep 17 00:00:00 2001 From: Glenn Date: Tue, 21 Nov 2023 00:30:59 +0100 Subject: [PATCH] refactor: use a better class hierarchy for filesystems --- src/cli.cr | 2 +- src/config.cr | 8 ++-- src/filesystems.cr | 2 +- src/filesystems/abstract_filesystem.cr | 50 +++++++++++++++++++++ src/filesystems/filesystem.cr | 48 --------------------- src/filesystems/gocryptfs.cr | 60 +++++++++++++------------- src/filesystems/httpdirfs.cr | 8 ++-- src/filesystems/sshfs.cr | 60 +++++++++++++------------- 8 files changed, 123 insertions(+), 115 deletions(-) create mode 100644 src/filesystems/abstract_filesystem.cr delete mode 100644 src/filesystems/filesystem.cr diff --git a/src/cli.cr b/src/cli.cr index f9a6578..f7ebb1d 100644 --- a/src/cli.cr +++ b/src/cli.cr @@ -97,7 +97,7 @@ module GX end 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| fs_str = filesystem.type.ljust(12,' ') diff --git a/src/config.cr b/src/config.cr index 311485f..b35f6b7 100644 --- a/src/config.cr +++ b/src/config.cr @@ -23,7 +23,7 @@ module GX record AddArgs, name : String, path : String record DelArgs, name : String - getter filesystems : Array(Filesystem) + getter filesystems : Array(Filesystem::AbstractFilesystem) getter home_dir : String getter global_mount_point : String? property verbose : Bool @@ -39,7 +39,7 @@ module GX @verbose = false @mode = Mode::Mount - @filesystems = [] of Filesystem + @filesystems = [] of Filesystem::AbstractFilesystem @path = nil @global_mount_point = nil @@ -75,7 +75,7 @@ module GX path = detect_config_file() end @path = path - @filesystems = [] of Filesystem + @filesystems = [] of Filesystem::AbstractFilesystem if !File.exists? path Log.error { "File #{path} does not exist!".colorize(:red) } @@ -111,7 +111,7 @@ module GX type = filesystem_data["type"].as_s name = filesystem_data["name"].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") end end diff --git a/src/filesystems.cr b/src/filesystems.cr index 2026122..a8a1425 100644 --- a/src/filesystems.cr +++ b/src/filesystems.cr @@ -6,4 +6,4 @@ require "./filesystems/gocryptfs" require "./filesystems/sshfs" require "./filesystems/httpdirfs" -require "./filesystems/filesystem" +require "./filesystems/abstract_filesystem" diff --git a/src/filesystems/abstract_filesystem.cr b/src/filesystems/abstract_filesystem.cr new file mode 100644 index 0000000..443535d --- /dev/null +++ b/src/filesystems/abstract_filesystem.cr @@ -0,0 +1,50 @@ +# SPDX-License-Identifier: GPL-3.0-or-later +# +# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland +# Copyright © 2023 Glenn Y. Rolland + +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" diff --git a/src/filesystems/filesystem.cr b/src/filesystems/filesystem.cr deleted file mode 100644 index 8881bad..0000000 --- a/src/filesystems/filesystem.cr +++ /dev/null @@ -1,48 +0,0 @@ -# SPDX-License-Identifier: GPL-3.0-or-later -# -# SPDX-FileCopyrightText: 2023 Glenn Y. Rolland -# Copyright © 2023 Glenn Y. Rolland - -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" diff --git a/src/filesystems/gocryptfs.cr b/src/filesystems/gocryptfs.cr index ebe7f83..b405482 100644 --- a/src/filesystems/gocryptfs.cr +++ b/src/filesystems/gocryptfs.cr @@ -4,42 +4,44 @@ # Copyright © 2023 Glenn Y. Rolland require "shellwords" -require "./filesystem" +require "./abstract_filesystem" module GX - class GoCryptFS < Filesystem - getter name : String = "" - getter encrypted_path : String = "" + module Filesystem + class GoCryptFS < AbstractFilesystem + getter name : String = "" + getter encrypted_path : String = "" - @[YAML::Field(key: "mount_dir", ignore: true)] - getter mount_dir : String = "" + @[YAML::Field(key: "mount_dir", ignore: true)] + getter mount_dir : String = "" - include GenericFilesystem + include FilesystemBase - def after_initialize() - home_dir = ENV["HOME"] || raise "Home directory not found" - @mount_dir = File.join(home_dir, "mnt/#{@name}.Open") - end + def after_initialize() + home_dir = ENV["HOME"] || raise "Home directory not found" + @mount_dir = File.join(home_dir, "mnt/#{@name}.Open") + end - def mounted? : Bool - `mount`.includes?("#{encrypted_path} on #{mount_dir}") - end + def mounted? : Bool + `mount`.includes?("#{encrypted_path} on #{mount_dir}") + end - def mount - super do - input = STDIN - output = STDOUT - error = STDERR - process = Process.new( - "gocryptfs", - ["-idle", "15m", encrypted_path, mount_dir], - input: input, - output: output, - error: error - ) - unless process.wait.success? - puts "Error mounting the vault".colorize(:red) - return + def mount + super do + input = STDIN + output = STDOUT + error = STDERR + process = Process.new( + "gocryptfs", + ["-idle", "15m", encrypted_path, mount_dir], + input: input, + output: output, + error: error + ) + unless process.wait.success? + puts "Error mounting the vault".colorize(:red) + return + end end end end diff --git a/src/filesystems/httpdirfs.cr b/src/filesystems/httpdirfs.cr index e1e4279..481e4ba 100644 --- a/src/filesystems/httpdirfs.cr +++ b/src/filesystems/httpdirfs.cr @@ -4,17 +4,18 @@ # Copyright © 2023 Glenn Y. Rolland require "shellwords" -require "./filesystem" +require "./abstract_filesystem" module GX - class HttpDirFS < Filesystem + module Filesystem + class HttpDirFS < AbstractFilesystem getter name : String = "" getter url : String = "" @[YAML::Field(key: "mount_dir", ignore: true)] getter mount_dir : String = "" - include GenericFilesystem + include FilesystemBase def after_initialize() home_dir = ENV["HOME"] || raise "Home directory not found" @@ -44,5 +45,6 @@ module GX end end end + end end diff --git a/src/filesystems/sshfs.cr b/src/filesystems/sshfs.cr index 44ddab9..16ca006 100644 --- a/src/filesystems/sshfs.cr +++ b/src/filesystems/sshfs.cr @@ -4,38 +4,39 @@ # Copyright © 2023 Glenn Y. Rolland require "shellwords" -require "./filesystem" +require "./abstract_filesystem" module GX - class SshFS < Filesystem - getter name : String = "" - getter remote_path : String = "" - getter remote_user : String = "" - getter remote_host : String = "" - getter remote_port : String = "22" + module Filesystem + class SshFS < AbstractFilesystem + getter name : String = "" + getter remote_path : String = "" + getter remote_user : String = "" + getter remote_host : String = "" + getter remote_port : String = "22" - @[YAML::Field(key: "mount_dir", ignore: true)] - getter mount_dir : String = "" + @[YAML::Field(key: "mount_dir", ignore: true)] + getter mount_dir : String = "" - include GenericFilesystem + include FilesystemBase - def after_initialize() - home_dir = ENV["HOME"] || raise "Home directory not found" - @mount_dir = File.join(home_dir, "mnt/#{@name}") - end + def after_initialize() + home_dir = ENV["HOME"] || raise "Home directory not found" + @mount_dir = File.join(home_dir, "mnt/#{@name}") + end - def mounted? : Bool - `mount`.includes?("#{remote_user}@#{remote_host}:#{remote_path} on #{mount_dir}") - end + def mounted? : Bool + `mount`.includes?("#{remote_user}@#{remote_host}:#{remote_path} on #{mount_dir}") + end - def mount - super do - input = STDIN - output = STDOUT - error = STDERR - process = Process.new( - "sshfs", - [ + def mount + super do + input = STDIN + output = STDOUT + error = STDERR + process = Process.new( + "sshfs", + [ "-p", remote_port, "#{remote_user}@#{remote_host}:#{remote_path}", mount_dir @@ -43,10 +44,11 @@ module GX input: input, output: output, error: error - ) - unless process.wait.success? - puts "Error mounting the filesystem".colorize(:red) - return + ) + unless process.wait.success? + puts "Error mounting the filesystem".colorize(:red) + return + end end end end