Initial import
This commit is contained in:
commit
97212b20ad
5 changed files with 229 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
bin
|
||||||
|
lib
|
5
Makefile
Normal file
5
Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
build:
|
||||||
|
shards build
|
106
_attic/gx-vault.bash
Executable file
106
_attic/gx-vault.bash
Executable file
|
@ -0,0 +1,106 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# vim: set ft=sh :
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -u
|
||||||
|
|
||||||
|
CONFIG_FILE="$HOME/.config/gx-vault.yml"
|
||||||
|
MNTDIR="$HOME/mnt"
|
||||||
|
|
||||||
|
gxvault_gocryptfs_is_mounted() {
|
||||||
|
src="$1"
|
||||||
|
|
||||||
|
if LANG=C mount |grep -q "^$src on " ; then
|
||||||
|
# >&2 echo "W: $src is already mounted"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
gxvault_gocryptfs_mount() {
|
||||||
|
name="$1"
|
||||||
|
src="$2"
|
||||||
|
dst="$3"
|
||||||
|
mkdir -p "$dst"
|
||||||
|
|
||||||
|
if [ ! -e "$src" ]; then
|
||||||
|
printf '\033[31m-> Missing input directory. Skipping.\033[0m\n'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if LANG=C mount |grep -q "$src on $dst" ; then
|
||||||
|
printf '\033[33m-> Already mounted. Skipping.\033[0m\n'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
gocryptfs -idle 15m "$src" "$dst"
|
||||||
|
printf '\033[32mVault %s is now available on %s\033[0m\n' "$name" "$(echo "$dst" |sed -e "s|^$HOME|~|")"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure that yq is installed with the right version
|
||||||
|
gxvault_ensure_dependency_yq() {
|
||||||
|
if ! hash yq >/dev/null 2>&1 ; then
|
||||||
|
>&2 echo "ERROR: unable to find yq (yaml util)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
YQ_VERSION="$(yq --version |sed 's/.*version //' |cut -d '.' -f1 |sed -e 's/^v//' )"
|
||||||
|
if [ "$YQ_VERSION" -lt 4 ]; then
|
||||||
|
>&2 echo "ERROR: installed version of yq is too old (found $YQ_VERSION instead of 4+)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure that all dependencies are installed
|
||||||
|
gxvault_ensure_dependency_yq
|
||||||
|
|
||||||
|
|
||||||
|
# Get list of sources
|
||||||
|
SRC_LIST="$(mktemp)"
|
||||||
|
SRC_COUNT="$(yq eval '.vaults[].name' "$CONFIG_FILE" |wc -l )"
|
||||||
|
|
||||||
|
{
|
||||||
|
for INDEX1 in $(seq 1 "$SRC_COUNT") ; do
|
||||||
|
INDEX0=$((INDEX1 - 1))
|
||||||
|
CUR_NAME="$(yq eval ".vaults[$INDEX0].name" "$CONFIG_FILE")"
|
||||||
|
CUR_DIR="$(yq eval ".vaults[$INDEX0].encrypted_path" "$CONFIG_FILE")"
|
||||||
|
if gxvault_gocryptfs_is_mounted "$CUR_DIR" ; then
|
||||||
|
printf "%s\v [\e[32mopen\e[0m]\n" "$CUR_NAME"
|
||||||
|
else
|
||||||
|
echo "$CUR_NAME"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
} | sort > "$SRC_LIST"
|
||||||
|
|
||||||
|
# cat "$SRC_LIST"
|
||||||
|
SRC_NAME="$(fzf --ansi < "$SRC_LIST")"
|
||||||
|
# echo "fzf: $SRC_NAME"
|
||||||
|
SRC_NAME="$(echo "$SRC_NAME" |sed -e "s/\v.*//")"
|
||||||
|
# echo "sed: $SRC_NAME"
|
||||||
|
rm -f "$SRC_LIST"
|
||||||
|
|
||||||
|
if [ -z "$SRC_NAME" ]; then
|
||||||
|
echo "All vaults already mounted or no vaults defined"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
SRC_DIR="$(yq eval ".vaults[] | select(.name == \"$SRC_NAME\").encrypted_path" "$CONFIG_FILE")"
|
||||||
|
DST_DIR="$MNTDIR/$SRC_NAME.Open"
|
||||||
|
if [ -z "$SRC_DIR" ]; then
|
||||||
|
>&2 echo "ERROR: Unable to detect encrypted_path for $SRC_NAME"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! gxvault_gocryptfs_is_mounted "$SRC_DIR" ; then
|
||||||
|
echo "Opening vault $SRC_NAME..."
|
||||||
|
# echo " src_name=$SRC_NAME"
|
||||||
|
# echo " src_dir=$SRC_DIR"
|
||||||
|
# echo " dst_dir=$DST_DIR"
|
||||||
|
gxvault_gocryptfs_mount \
|
||||||
|
"$SRC_NAME" \
|
||||||
|
"$SRC_DIR" \
|
||||||
|
"$DST_DIR"
|
||||||
|
else
|
||||||
|
echo "Closing vault $SRC_NAME..."
|
||||||
|
fusermount -u "$DST_DIR"
|
||||||
|
printf '\033[32mVault %s is now closed\033[0m\n' "$SRC_NAME"
|
||||||
|
fi
|
||||||
|
|
23
shard.yml
Normal file
23
shard.yml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
name: gx-vault
|
||||||
|
version: 0.1.0
|
||||||
|
|
||||||
|
targets:
|
||||||
|
gx-vault:
|
||||||
|
main: src/main.cr
|
||||||
|
|
||||||
|
# authors:
|
||||||
|
# - name <email@example.com>
|
||||||
|
|
||||||
|
# description: |
|
||||||
|
# Short description of gx-vault
|
||||||
|
|
||||||
|
# dependencies:
|
||||||
|
# pg:
|
||||||
|
# github: will/crystal-pg
|
||||||
|
# version: "~> 0.5"
|
||||||
|
|
||||||
|
# development_dependencies:
|
||||||
|
# webmock:
|
||||||
|
# github: manastech/webmock.cr
|
||||||
|
|
||||||
|
# license: MIT
|
93
src/main.cr
Normal file
93
src/main.cr
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
require "yaml"
|
||||||
|
require "colorize"
|
||||||
|
require "json"
|
||||||
|
|
||||||
|
# Vault class
|
||||||
|
class Vault
|
||||||
|
getter name : String
|
||||||
|
getter encrypted_path : String
|
||||||
|
getter mount_dir : String
|
||||||
|
|
||||||
|
def initialize(@name, @encrypted_path, mount_name : String)
|
||||||
|
home_dir = ENV["HOME"] || raise "Home directory not found"
|
||||||
|
@mount_dir = File.join(home_dir, "mnt/#{mount_name}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def mounted? : Bool
|
||||||
|
`mount`.includes?("#{encrypted_path} on #{mount_dir}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def mount
|
||||||
|
Dir.mkdir_p(mount_dir) unless Dir.exists?(mount_dir)
|
||||||
|
|
||||||
|
if mounted?
|
||||||
|
puts "Already mounted. Skipping.".colorize(:yellow)
|
||||||
|
else
|
||||||
|
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
|
||||||
|
puts "Vault #{name} is now available on #{mount_dir}".colorize(:green)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
def unmount
|
||||||
|
`fusermount -u #{mount_dir}`
|
||||||
|
puts "Vault #{name} is now closed.".colorize(:green)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Config class
|
||||||
|
class Config
|
||||||
|
getter vaults : Array(Vault)
|
||||||
|
|
||||||
|
def initialize(config_path : String)
|
||||||
|
@vaults = [] of Vault
|
||||||
|
load_vaults(config_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
private def load_vaults(config_path : String)
|
||||||
|
yaml_data = YAML.parse(File.read(config_path))
|
||||||
|
vaults_data = yaml_data["vaults"].as_a
|
||||||
|
|
||||||
|
vaults_data.each do |vault_data|
|
||||||
|
name = vault_data["name"].as_s
|
||||||
|
encrypted_path = vault_data["encrypted_path"].as_s
|
||||||
|
@vaults << Vault.new(name, encrypted_path, "#{name}.Open")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Main execution starts here
|
||||||
|
home_dir = ENV["HOME"] || raise "Home directory not found"
|
||||||
|
config = Config.new(File.join(home_dir, ".config/gx-vault.yml"))
|
||||||
|
|
||||||
|
# Correcting the fzf interaction part
|
||||||
|
input = IO::Memory.new
|
||||||
|
config.vaults.each do |vault|
|
||||||
|
name_display = vault.mounted? ? "#{vault.name} [#{ "open".colorize(:green) }]" : vault.name
|
||||||
|
input.puts name_display
|
||||||
|
end
|
||||||
|
input.rewind
|
||||||
|
|
||||||
|
output = IO::Memory.new
|
||||||
|
error = STDERR
|
||||||
|
process = Process.new("fzf", ["--ansi"], input: input, output: output, error: error)
|
||||||
|
|
||||||
|
unless process.wait.success?
|
||||||
|
puts "Error executing fzf: #{error.to_s.strip}".colorize(:red)
|
||||||
|
exit(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
selected_vault_name = output.to_s.strip.split.first?
|
||||||
|
selected_vault = config.vaults.find { |v| v.name == selected_vault_name }
|
||||||
|
|
||||||
|
if selected_vault
|
||||||
|
selected_vault.mounted? ? selected_vault.unmount : selected_vault.mount
|
||||||
|
else
|
||||||
|
puts "Vault not found.".colorize(:red)
|
||||||
|
end
|
||||||
|
|
Loading…
Reference in a new issue