#!/usr/bin/env nuxr-nuxsh nux.use nux/fs @prefix fs nux.fs. VFS_SOURCES_FILE=".vfs.sources" CURRENT_SOURCES_FILE=$(nux.fs.closest "$VFS_SOURCES_FILE"); if fs:exists "$CURRENT_SOURCES_FILE" { CURRENT_MOUNT="${CURRENT_SOURCES_FILE%/*}"; declare -gA CURRENT_SOURCES nux.log debug "Current VFS mount: ${CURRENT_MOUNT%/*}"; while read name path; do CURRENT_SOURCES[${name}]="$path" done < "$CURRENT_SOURCES_FILE" } function vfs.path name { echo ${CURRENT_SOURCES[$name]}; } function vfs.path.real file { for root in "${CURRENT_SOURCES[@]}" ; do nux.log trace "Testing $root$file" if fs:exists "${root}${file}" { echo ${root}${file}; return 0; } done } ## list:: ## Lists all **mergerfs** based virtual filesystems managed by **vfs** tool @command list { echo "1" } ## info:: ## Displays info about current path @command info { nux.log debug "VFS mount: ${CURRENT_MOUNT}"; echo "path:" $CURRENT_MOUNT; echo "sources:" for key in "${!CURRENT_SOURCES[@]}"; do echo " $key: ${CURRENT_SOURCES[$key]}"; done } ## switch:: ## Moves specified **paths** to named **storage** for particular **vfs**. ## This is ideal for marking files as keep or migrating them to remote, ## rather then local. ### ### The switch uses **.vfs.sources** file to determine location of target ### directory and creates necessary directory structures in target directory ### to preserve local rooted path. ### ### FIXME: Switch does not support merging of directories @command switch storage { target="$(vfs.path "$storage")" if [ -z "$target" ] { nux.fatal "$storage does not exists." } nux.log debug "Target path $target" for arg_path in "$@" ; do rooted_path="/$(realpath -m --relative-to="$CURRENT_MOUNT" ${arg_path%/})"; target_dir="${target}${rooted_path%/*}" real_file="$(vfs.path.real "$rooted_path")" nux.log trace "Rooted path: $rooted_path"; nux.log trace "Real file: $real_file"; nux.log trace "Target dir: $target_dir"; if [ -n "$real_file" ]; then fs:stage mkdir -p "$target_dir"; fs:info "$arg_path" moving from "$NC_LightPurple${real_file}$NC_No" to "$NC_LightPurple$target_dir" fs:stage mv "$real_file" "$target_dir"; else fs:error $arg_path does not exists. fi done } ## mount:: [+] ## Mounts **mergerfs** on **target**. The mount is merge of specified pairs ## of storage **name** and **path**. ## @command mount target { local mount_paths=""; nux.log debug "MergerFS mount: $target" source_tempfs="$(mktemp -d)" for source in "$@" ; do source_name="${source%%:*}" source_path="$(realpath "${source#*:}")" source_path="${source_path%/}" nux.log debug " Source: $source_name Path: $source_path"; mount_paths="$mount_paths:${source_path}" echo "$source_name $source_path" >> "$source_tempfs/.vfs.sources" done echo "temp $source_tempfs" >> "$source_tempfs/$VFS_SOURCES_FILE=" mergerfs_mounts="$source_tempfs:${mount_paths}" nux.log debug "MergerFS command:" $mergerfs_mounts; mergerfs "$mergerfs_mounts" "$target" (cd $target; vfs info ) } ## unmount:: ## Unmounts target VFS filesystem. @command :unmount target { fusermount -u "$target" fs:info "${CURRENT_SOURCES[temp]}" removing temporary metadata. fs:stage rm -rf "${CURRENT_SOURCES[temp]}" }