1
0
mirror of https://github.com/TheLocehiliosan/yadm synced 2026-03-02 03:49:29 +00:00

Change handling of dirs with alt conditions

Instead of creating symlinks pointing at the directory, create individual
symlinks for each file within the dir alternate (fixes #490).

Also rework how stale symlinks are removed. Now a (stale) symlink will only be
removed if it's pointing at a file that's an altnerate file (fixes #236).
This commit is contained in:
Erik Flodin
2025-01-27 21:06:34 +01:00
parent 7f76a455bb
commit 4214de8d91
6 changed files with 244 additions and 233 deletions

84
yadm
View File

@@ -169,7 +169,7 @@ function main() {
function score_file() {
local source="$1"
local target="$2"
local conditions="${source#*##}"
local conditions="$3"
score=0
local template_processor=""
@@ -223,7 +223,7 @@ function score_file() {
continue
;;
t | template | yadm)
if [ -d "$source" ] || ((negate)); then
if ((negate)); then
INVALID_ALT+=("$source")
else
template_processor=$(choose_template_processor "$value")
@@ -578,42 +578,50 @@ function alt() {
local alt_scores=()
local alt_template_processors=()
# For removing stale links
local possible_alt_targets=()
local alt_source
for alt_source in "${tracked_files[@]}" "${ENCRYPT_INCLUDE_FILES[@]}"; do
local conditions="${alt_source#*##}"
if [ "$alt_source" = "$conditions" ]; then
local filename
for filename in "${tracked_files[@]}" "${ENCRYPT_INCLUDE_FILES[@]}"; do
local suffix="${filename#*##}"
if [ "$filename" = "$suffix" ]; then
continue
fi
local conditions="${suffix%%/*}"
suffix="${suffix:${#conditions}}"
local target_base="${alt_source%%##*}"
alt_source="${YADM_BASE}/${target_base}##${conditions%%/*}"
local alt_target="${YADM_BASE}/${target_base}"
if [ "${alt_target#"$YADM_ALT/"}" != "$alt_target" ]; then
target_base="${alt_target#"$YADM_ALT/"}"
local target="${YADM_BASE}/${filename%%##*}"
if [ "${target#"$YADM_ALT/"}" != "$target" ]; then
target="${YADM_BASE}/${target#"$YADM_ALT/"}"
fi
alt_target="${YADM_BASE}/${target_base}"
local source="${YADM_BASE}/${filename}"
if ! in_list "$alt_target" "${possible_alt_targets[@]}"; then
possible_alt_targets+=("$alt_target")
# If conditions are given on a directory we check if this alt, without the
# filename part, has a target that's a symlink pointing at this source
# (which was the legacy behavior for yadm) and if so remove this target.
if [ -n "$suffix" ]; then
if [ -L "$target" ] && [ "$target" -ef "${YADM_BASE}/${filename%"$suffix"}" ]; then
rm -f "$target"
fi
target="$target$suffix"
fi
score_file "$alt_source" "$alt_target"
# Remove target if it's a symlink pointing at source
if [ -L "$target" ] && [ "$target" -ef "$source" ]; then
rm -f "$target"
fi
score_file "$source" "$target" "$conditions"
done
local alt_linked=()
alt_linking
remove_stale_links
report_invalid_alts
}
function report_invalid_alts() {
[ "$LEGACY_WARNING_ISSUED" = "1" ] && return
[ "${#INVALID_ALT[@]}" = "0" ] && return
local path_list
local path_list=""
local invalid
for invalid in "${INVALID_ALT[@]}"; do
path_list="$path_list * $invalid"$'\n'
done
@@ -643,25 +651,6 @@ EOF
printf '%s\n' "$msg" >&2
}
function remove_stale_links() {
# review alternate candidates for stale links
# if a possible alt IS linked, but it's source is not part of alt_linked,
# remove it.
if readlink_available; then
for stale_candidate in "${possible_alt_targets[@]}"; do
if [ -L "$stale_candidate" ]; then
src=$(readlink "$stale_candidate" 2>/dev/null)
if [ -n "$src" ]; then
for review_link in "${alt_linked[@]}"; do
[ "$src" = "$review_link" ] && continue 2
done
rm -f "$stale_candidate"
fi
fi
done
fi
}
function set_local_alt_values() {
local -a all_classes
@@ -716,20 +705,23 @@ function alt_linking() {
local source="${alt_sources[$index]}"
local template_processor="${alt_template_processors[$index]}"
if [[ -L "$target" ]]; then
if [ -L "$target" ]; then
rm -f "$target"
elif [[ -d "$target" ]]; then
elif [ -d "$target" ]; then
echo "Skipping alt $source as $target is a directory"
continue
else
assert_parent "$target"
fi
if [[ -n "$template_processor" ]]; then
if [ -n "$template_processor" ]; then
template "$template_processor" "$source" "$target"
elif [[ "$do_copy" -eq 1 ]]; then
elif [ "$do_copy" -eq 1 ]; then
$log "Copying $source to $target"
cp -f "$source" "$target"
elif [ -e "$target" ]; then
echo "Skipping alt $source as $target exists"
continue
else
$log "Linking $source to $target"
ln_relative "$source" "$target"
@@ -748,7 +740,7 @@ function ln_relative() {
local rel_source
rel_source=$(relative_path "$(builtin_dirname "$target")" "$source")
ln -fs "$rel_source" "$target"
ln -s "$rel_source" "$target"
alt_linked+=("$rel_source")
}
@@ -2263,10 +2255,6 @@ function esh_available() {
command -v "$ESH_PROGRAM" &>/dev/null && return
return 1
}
function readlink_available() {
command -v "readlink" &>/dev/null && return
return 1
}
# ****** Directory translations ******