Skip to content

Commit

Permalink
Implement option to bind directories
Browse files Browse the repository at this point in the history
  • Loading branch information
HanabishiRecca committed Nov 12, 2022
1 parent 8e7587e commit 5d3a654
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 26 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## Caches manager

A simple script that helps keep selected directories clean by symlinking to tmpfs ramdisk. Useful for temporary, cache and other junk directories.
Systemd services are included to automate this process.
A simple script that helps keep selected directories clean by symlinking or binding to tmpfs ramdisk.
Useful for temporary, cache and other junk directories.

### Usage

Expand All @@ -19,8 +19,9 @@ The script reads all `.conf` files from respective directories:
- `/etc/caches-manager/user` - configs for all users.
- `$XDG_CONFIG_HOME/caches-manager` (`~/.config/caches-manager`) - per-user configs.

Configs are read simply as one path per line.
System-wide configs require full absolute paths (e.g. `/var/cache`).
Configs are read as one path per line. Default mode of operation is to symlink the directory.
If you want to use bind mount instead, prefix the path with `b:`. Bind mounts are more failsafe and keep actual directories if the service disabled/uninstalled, so they are preferred for system directories.
System-wide configs require full absolute paths (e.g. `b:/var/cache`).
User configs treat paths relative to user home directory (e.g. `.cache` will be resolved to `~/.cache`).

**WARNING!** All content in the target directories will be purged!
Expand Down
92 changes: 71 additions & 21 deletions caches-manager
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,61 @@
APP_NAME="caches-manager"

set -euo pipefail
shopt -s nullglob
shopt -s nullglob dotglob

backup() {
[ -e "$1" ] || return
echo -n "target exists, backing up... "
mv -T --backup=numbered "$1" "$1.bak"
}

is_not_empty() {
for _ in "$1/"*; do
return 0
done
return 1
}

make_bind() {
if ((UID != 0)); then
echo "can not bind without root privileges, skip."
return 13
fi

if [ -L "$2" ]; then
unlink "$2"
elif [ -d "$2" ]; then
is_not_empty "$2" && backup "$2"
else
backup "$2"
fi

mkdir -p "$2"
mount -B "$1" "$2"
}

make_link() {
if [ -L "$2" ]; then
[ "$(readlink "$2")" == "$1" ] && return
else
backup "$2"
fi

ln -sfT "$1" "$2"
}

create_cache() {
local dir
local parent
dir="$(realpath -s "$2")"
parent="$(dirname "${dir}")"
echo -n "Linking '${dir}'... "

if [ "$3" == "b" ]; then
echo -n "Binding '${dir}'... "
else
echo -n "Linking '${dir}'... "
fi

mkdir -p "$1"

if [ ! -d "${parent}" ]; then
Expand All @@ -23,25 +70,32 @@ create_cache() {
return
fi

if [ -L "${dir}" ]; then
if [ "$(readlink "${dir}")" == "$1" ]; then
echo "done."
return
fi
elif [ -e "${dir}" ]; then
echo -n "target exists, backing up... "
mv -fT --backup=numbered "${dir}" "${dir}.bak"
if mountpoint -q "${dir}"; then
echo "mount point found, skip."
return
fi

if ln -sfT "$1" "${dir}"; then
echo "done."
if [ "$3" == "b" ]; then
make_bind "$1" "${dir}" || return 0
else
echo "failed."
make_link "$1" "${dir}" || return 0
fi

echo "done."
}

declare -a TARGETS

create_caches() {
local flag
local path
for t in "${TARGETS[@]}"; do
flag="$(expr "${t}" : '\(.*\):')" || true
path="${t#*:}"
create_cache "$1/${path}" "$2/${path}" "${flag}"
done
}

read_config() {
while read -r line || [ -n "${line}" ]; do
[ "${line}" ] && TARGETS+=("${line}")
Expand Down Expand Up @@ -69,13 +123,11 @@ create_system_caches() {
return 2
fi

echo "Linking system targets..."
echo "Processing system targets..."
TARGETS=()
read_configs_from "/etc/${APP_NAME}/system"

for t in "${TARGETS[@]}"; do
create_cache "${dir}/tmp/${t}" "${t}"
done
create_caches "${dir}/tmp" ""
}

create_user_caches() {
Expand All @@ -86,14 +138,12 @@ create_user_caches() {
return 2
fi

echo "Linking user targets..."
echo "Processing user targets..."
TARGETS=()
read_configs_from "/etc/${APP_NAME}/user"
read_configs_from "${XDG_CONFIG_HOME:-"${HOME}/.config"}/${APP_NAME}"

for t in "${TARGETS[@]}"; do
create_cache "${dir}/tmp/${t}" "${HOME}/${t}"
done
create_caches "${dir}/tmp" "${HOME}"
}

declare -A ARGS=()
Expand Down
2 changes: 1 addition & 1 deletion config/system.conf.example
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/var/cache
b:/var/cache

0 comments on commit 5d3a654

Please sign in to comment.