added a new script 'mntstack' for easily handling storage volumes that require binding
This commit is contained in:
@@ -224,3 +224,17 @@ included in my nixpkgs overlay as custom packages, and these packages are declar
|
||||
- *Usage*:
|
||||
- `git commit -m "message" | color-commit`
|
||||
- *Defined in*: `overlay/scripts/misc/color-commit.nix`
|
||||
|
||||
---
|
||||
|
||||
- **mntstack**
|
||||
- *Description*:
|
||||
- Keeps mounts in a stack and allows you to easily mount and then unmount volumes in the same order that they were mounted. Useful for quickly setting up and tearing down chroot environments.
|
||||
- *Usage*:
|
||||
- `mntstack push </device/path> </mount/point/path>` -Push an entry into the stack
|
||||
- `mntstack push --bind </directory/path> </mount/point/path>` -Use bind to mount directories
|
||||
- `mntstack pop` -Unmounts and removes the most recently mounted volume
|
||||
- `mntstack pop -c #` -Pops a given number of mounts
|
||||
- `mntstack pop -a` -Pops the entire stack
|
||||
- `mntstack list` -Shows the current stack, and the order which they will be popped in
|
||||
- *Defined in*: `overlay/scripts/misc/mntstack.nix`
|
||||
|
||||
@@ -23,6 +23,7 @@ let
|
||||
myScripts.git-compose
|
||||
myScripts.playshellsound
|
||||
myScripts.color-commit
|
||||
myScripts.mntstack
|
||||
];
|
||||
in {
|
||||
options = {
|
||||
|
||||
@@ -47,5 +47,6 @@ in
|
||||
s_check = super.callPackage ./scripts/wm-controls/s_check.nix {};
|
||||
switchmon = super.callPackage ./scripts/wm-controls/switchmon.nix {};
|
||||
color-commit = super.callPackage ./scripts/misc/color-commit.nix {};
|
||||
mntstack = super.callPackage ./scripts/misc/mntstack.nix {};
|
||||
};
|
||||
}
|
||||
|
||||
199
overlay/scripts/misc/mntstack.nix
Normal file
199
overlay/scripts/misc/mntstack.nix
Normal file
@@ -0,0 +1,199 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.writeShellApplication {
|
||||
name = "mntstack";
|
||||
runtimeInputs = [];
|
||||
text = ''
|
||||
set -e
|
||||
|
||||
# File to store the stack
|
||||
STACK_FILE="/tmp/mntstack.txt"
|
||||
|
||||
validate_entry() {
|
||||
local entry_dev entry_mntpoint test_mntpoint
|
||||
IFS=' ' read -r entry_dev entry_mntpoint <<< "$1"
|
||||
[ -n "$(findmnt -no SOURCE,TARGET "$entry_mntpoint" | cut -d' ' -f1-)" ]
|
||||
}
|
||||
|
||||
# Function to push a path onto the stack
|
||||
push_path() {
|
||||
local device="$1"
|
||||
local mount_point="$2"
|
||||
local bind_flag="$3"
|
||||
|
||||
if [ ! -f "$STACK_FILE" ]; then
|
||||
touch "$STACK_FILE"
|
||||
fi
|
||||
|
||||
# Validate the paths
|
||||
if [[ ! -e "$device" || ! -d "$mount_point" ]]; then
|
||||
echo "Error: Invalid device or mount point."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the device is a normal directory
|
||||
if [[ -d "$device" && "$bind_flag" != "--bind" ]]; then
|
||||
echo "Error: Cannot mount a normal directory without --bind flag."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for duplicate entries
|
||||
if grep -q "^$device $mount_point\$" "$STACK_FILE"; then
|
||||
echo "Error: Duplicate entry detected."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Mount the device to the mount point
|
||||
if [[ "$bind_flag" == "--bind" ]]; then
|
||||
sudo mount --bind "$device" "$mount_point"
|
||||
else
|
||||
sudo mount "$device" "$mount_point"
|
||||
fi
|
||||
|
||||
# Append the path to the stack file
|
||||
echo "$device $mount_point" >> "$STACK_FILE"
|
||||
echo "Pushed and mounted: $device $mount_point"
|
||||
}
|
||||
|
||||
# Function to pop a path from the stack
|
||||
pop_path() {
|
||||
|
||||
|
||||
if [[ ! -f "$STACK_FILE" || ''${#stack[@]} -eq 0 ]]; then
|
||||
echo "Warning: Stack is empty. Nothing to pop."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mapfile -t stack < "$STACK_FILE"
|
||||
|
||||
# Get the last entry
|
||||
last_path="${stack[-1]}"
|
||||
if ! validate_entry "$last_path"; then
|
||||
echo "Warning: Invalid stack entry '${stack[-1]}'"
|
||||
sed -i '$d' "$STACK_FILE"
|
||||
return 0
|
||||
fi
|
||||
|
||||
IFS=' ' read -r device mount_point <<< "$last_path"
|
||||
|
||||
# Unmount the device
|
||||
sudo umount "$mount_point"
|
||||
sed -i '$d' "$STACK_FILE"
|
||||
|
||||
echo "Popped and unmounted: $device"
|
||||
}
|
||||
|
||||
# Function to list the current stack
|
||||
list_stack() {
|
||||
# Check if the stack file exists
|
||||
if [[ ! -f "$STACK_FILE" ]]; then
|
||||
echo "Stack is empty."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Read the stack file into an array
|
||||
mapfile -t stack < "$STACK_FILE"
|
||||
|
||||
# Check if the stack is empty
|
||||
if [[ ''${#stack[@]} -eq 0 ]]; then
|
||||
echo "Stack is empty."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Display the stack elements
|
||||
for ((i=0; i<''${#stack[@]}; i++)); do
|
||||
IFS=' ' read -r device mount_point <<< "''${stack[i]}"
|
||||
echo "$((i+1)). $mount_point -> $device"
|
||||
done
|
||||
}
|
||||
|
||||
pop_num=1
|
||||
all=false
|
||||
bind=false
|
||||
pos_args=()
|
||||
|
||||
# Early check for help
|
||||
if [[ "$1" == "help" ]]; then
|
||||
echo "Usage: $0 {push|pop|list} [--bind] [<device> <mount_point>]"
|
||||
echo "Flags:"
|
||||
echo "pop -c,--count: specify a number of mounts to pop"
|
||||
echo "pop -a,--all: pop the entire stack"
|
||||
echo "push <dir> <mount_point> -b,--bind: use --bind when mounting"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Process flags
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-a|--all)
|
||||
all=true
|
||||
shift
|
||||
;;
|
||||
-c|--count)
|
||||
if [[ "$2" =~ ^-?[0-9]+$ ]]; then
|
||||
pop_num="$2"
|
||||
shift 2
|
||||
else
|
||||
echo "Invalid count: please give an integer like -c 5"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-b|--bind)
|
||||
bind=true
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
pos_args+=("$1")
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Main command processing
|
||||
case "''${pos_args[0]}" in
|
||||
push)
|
||||
if [[ ''${#pos_args[@]} -lt 3 || ''${#pos_args[@]} -gt 4 ]]; then
|
||||
echo "Usage: $0 push [--bind] <device> <mount_point>"
|
||||
exit 1
|
||||
fi
|
||||
push_path "''${pos_args[1]}" "''${pos_args[2]}" "$([[ $bind == true ]] && echo "--bind")"
|
||||
;;
|
||||
pop)
|
||||
if [[ ''${#pos_args[@]} -ne 1 ]]; then
|
||||
echo "Usage: $0 pop"
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! -f "$STACK_FILE" ]]; then
|
||||
echo "Stack file does not exist. Nothing to pop."
|
||||
fi
|
||||
if [[ $all == false ]]; then
|
||||
mapfile -t stack < "$STACK_FILE"
|
||||
while [[ $pop_num -gt 0 ]]; do
|
||||
pop_path || break
|
||||
mapfile -t stack < "$STACK_FILE"
|
||||
((pop_num--))
|
||||
done
|
||||
else
|
||||
mapfile -t stack < "$STACK_FILE"
|
||||
while [[ ''${#stack[@]} -gt 0 ]]; do
|
||||
if ! pop_path; then
|
||||
break
|
||||
fi
|
||||
mapfile -t stack < "$STACK_FILE"
|
||||
done
|
||||
fi
|
||||
;;
|
||||
list)
|
||||
if [[ ''${#pos_args[@]} -ne 1 ]]; then
|
||||
echo "Usage: $0 list"
|
||||
exit 1
|
||||
fi
|
||||
list_stack
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {push|pop|list} [--bind] [<device> <mount_point>]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
'';
|
||||
}
|
||||
Reference in New Issue
Block a user