1
0
mirror of https://github.com/TheLocehiliosan/yadm synced 2025-06-04 00:23:58 +00:00

Process alt files in submodules (#78, #528)

Ignore files are updated in each submodule's info/exclude file. The
top-level file still contains all files (for simplicity).
This commit is contained in:
Erik Flodin 2025-04-06 22:09:19 +02:00
parent bbb58e6625
commit 9b1d7eea00
No known key found for this signature in database
GPG Key ID: 420A7C865EE3F85F
3 changed files with 121 additions and 53 deletions

View File

@ -54,6 +54,50 @@ def test_alt_source(runner, paths, tracked, encrypt, exclude, yadm_alt):
assert str(source_file) not in linked
@pytest.mark.usefixtures("ds1_copy")
def test_alt_submodule(runner, paths, yadm_cmd):
"""Test alt handling in submodule"""
yadm_dir, yadm_data = setup_standard_yadm_dir(paths)
# Create alt files in separate alt dir
alt_dir = yadm_dir.join("alt")
utils.create_alt_files(paths, "##default", tracked=False, yadm_alt=True, yadm_dir=yadm_dir)
# Make alt dir be a separate repo
runner(["git", "init", alt_dir], report=False)
runner(["git", "-C", alt_dir, "add", "."], report=False)
run = runner(["git", "-C", alt_dir, "commit", "-m", "Add alt files"])
assert run.success
# And add it as a submodule
run = runner(
yadm_cmd("-Y", yadm_dir, "--yadm-data", yadm_data, "submodule", "add", "https://foobar/repo", alt_dir.basename),
cwd=alt_dir.dirname,
)
assert run.success
# Now when processing alt files
run = runner([paths.pgm, "-Y", yadm_dir, "--yadm-data", yadm_data, "alt"])
assert run.success
assert run.err == ""
linked = utils.parse_alt_output(run.out)
# Then files in submodule are also handled
for link_path in TEST_PATHS:
source_file_content = link_path + "##default"
source_file = alt_dir.join(source_file_content)
link_file = paths.work.join(link_path)
if link_path == utils.ALT_DIR:
source_file = source_file.join(utils.CONTAINED)
link_file = link_file.join(utils.CONTAINED)
assert link_file.islink()
target = py.path.local(os.path.realpath(link_file))
assert target.isfile()
assert link_file.read() == source_file_content
assert str(source_file) in linked
@pytest.mark.usefixtures("ds1_copy")
@pytest.mark.parametrize("yadm_alt", [True, False], ids=["alt", "worktree"])
def test_relative_link(runner, paths, yadm_alt):

View File

@ -34,6 +34,7 @@ def test_exclude_encrypted(runner, tmpdir, yadm, encrypt_exists, auto_exclude, e
script = f"""
YADM_TEST=1 source {yadm}
{config_function}
GIT_PROGRAM=true
DEBUG=1
YADM_ENCRYPT="{encrypt_file}"
YADM_REPO="{repo_dir}"

129
yadm
View File

@ -569,7 +569,7 @@ function alt() {
# determine all tracked files
local tracked_files=()
local IFS=$'\n'
for tracked_file in $("$GIT_PROGRAM" ls-files -- '*##*'); do
for tracked_file in $("$GIT_PROGRAM" ls-files --recurse-submodules -- '*##*'); do
tracked_files+=("$tracked_file")
done
@ -1490,64 +1490,87 @@ function update_exclude() {
auto_exclude=$(config --bool yadm.auto-exclude)
[ "$auto_exclude" == "false" ] && return 0
local exclude_path="${YADM_REPO}/info/exclude"
local newline=$'\n'
local part_path="$exclude_path.yadm-$1"
local part_str
part_str=$(join_string "$newline" "${@:2}")
while IFS='' read -r submodule; do
local exclude_path="${YADM_REPO}${submodule:+/modules/}${submodule}/info/exclude"
if [ -e "$part_path" ]; then
if [ "$part_str" = "$(<"$part_path")" ]; then
return
fi
rm -f "$part_path"
elif [ -z "$part_str" ]; then
return
fi
if [ -n "$part_str" ]; then
assert_parent "$part_path"
cat >"$part_path" <<<"$part_str"
fi
local exclude_flag="# yadm-auto-excludes"
local exclude_header="${exclude_flag}${newline}"
exclude_header="${exclude_header}# This section is managed by yadm."
exclude_header="${exclude_header}${newline}"
exclude_header="${exclude_header}# Any edits below will be lost."
exclude_header="${exclude_header}${newline}"
# read info/exclude
local unmanaged=""
local managed=""
if [ -e "$exclude_path" ]; then
local -i flag_seen=0
local line
while IFS='' read -r line || [ -n "$line" ]; do
[ "$line" = "$exclude_flag" ] && flag_seen=1
if ((flag_seen)); then
managed="${managed}${line}${newline}"
else
unmanaged="${unmanaged}${line}${newline}"
local part_path="$exclude_path.yadm-$1"
local part_str=""
if [ -z "$submodule" ]; then
part_str=$(join_string "$newline" "${@:2}")
else
for part in "${@:2}"; do
if [ "${part#/"${submodule}"/}" != "$part" ]; then
part_str="${part_str}${part#/"${submodule}"}${newline}"
fi
done
if [ -n "$part_str" ]; then
part_str="${part_str:0:-1}"
fi
done <"$exclude_path"
fi
local exclude_str=""
for suffix in alt encrypt; do
if [ -e "${exclude_path}.yadm-$suffix" ]; then
local header="# yadm $suffix$newline"
exclude_str="$exclude_str$header$(<"$exclude_path".yadm-"$suffix")"
fi
done
if [ "${exclude_header}${exclude_str}${newline}" != "$managed" ]; then
debug "Updating ${exclude_path}"
cat >"$exclude_path" <<<"${unmanaged}${exclude_header}${exclude_str}"
fi
if [ -e "$part_path" ]; then
if [ "$part_str" = "$(<"$part_path")" ]; then
continue
fi
rm -f "$part_path"
elif [ -z "$part_str" ]; then
continue
fi
if [ -n "$part_str" ]; then
if [ -n "$submodule" ] && [ ! -d "${YADM_REPO}/modules/$submodule" ]; then
echo "Warning: not updating exclude for submodule '$submodule';" \
"consider running 'yadm submodule absorbgitdirs'"
continue
fi
assert_parent "$part_path"
cat >"$part_path" <<<"$part_str"
fi
local exclude_flag="# yadm-auto-excludes"
local exclude_header="${exclude_flag}${newline}"
exclude_header="${exclude_header}# This section is managed by yadm."
exclude_header="${exclude_header}${newline}"
exclude_header="${exclude_header}# Any edits below will be lost."
exclude_header="${exclude_header}${newline}"
# read info/exclude
local unmanaged=""
local managed=""
if [ -e "$exclude_path" ]; then
local -i flag_seen=0
local line
while IFS='' read -r line || [ -n "$line" ]; do
[ "$line" = "$exclude_flag" ] && flag_seen=1
if ((flag_seen)); then
managed="${managed}${line}${newline}"
else
unmanaged="${unmanaged}${line}${newline}"
fi
done <"$exclude_path"
fi
local exclude_str=""
for suffix in alt encrypt; do
if [ -e "${exclude_path}.yadm-$suffix" ]; then
local header="# yadm $suffix$newline"
exclude_str="$exclude_str$header$(<"$exclude_path".yadm-"$suffix")"
fi
done
if [ "${exclude_header}${exclude_str}${newline}" != "$managed" ]; then
debug "Updating ${exclude_path}"
cat >"$exclude_path" <<<"${unmanaged}${exclude_header}${exclude_str}"
fi
done <<<"$(
echo ""
"$GIT_PROGRAM" -C "$YADM_WORK" submodule --quiet \
foreach --recursive "echo \$displaypath"
)"
return 0
}