Skip to content

Commit d479610

Browse files
committed
Automatically exclude alt links and template files
unless yadm.auto-exclude is set to false (#234, #465). Alt files exclude pattern will be written to $GIT_DIR/info/exclude.yadm-alt and encrypt files exclude patthern to ...yadm-encrypt. Then these two files will be merged together and added to $GIT_DIR/info/exclude whenever one of them has changed.
1 parent 6726730 commit d479610

4 files changed

Lines changed: 110 additions & 54 deletions

File tree

test/test_alt.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,29 @@ def test_auto_alt(runner, yadm_cmd, paths, autoalt):
217217
assert str(paths.work.join(source_file)) not in linked
218218

219219

220+
@pytest.mark.usefixtures("ds1_copy")
221+
@pytest.mark.parametrize("autoexclude", [None, "true", "false"])
222+
def test_alt_exclude(runner, yadm_cmd, paths, autoexclude):
223+
"""Test alt exclude"""
224+
225+
# set the value of auto-exclude
226+
if autoexclude:
227+
os.system(" ".join(yadm_cmd("config", "yadm.auto-exclude", autoexclude)))
228+
229+
utils.create_alt_files(paths, "##default")
230+
run = runner(yadm_cmd("alt", "-d"))
231+
assert run.success
232+
233+
run = runner(yadm_cmd("status", "-z", "-uall", "--ignored"))
234+
assert run.success
235+
assert run.err == ""
236+
status = run.out.split("\0")
237+
238+
for link_path in TEST_PATHS:
239+
flags = "??" if autoexclude == "false" else "!!"
240+
assert f"{flags} {link_path}" in status
241+
242+
220243
@pytest.mark.usefixtures("ds1_copy")
221244
def test_stale_link_removal(runner, yadm_cmd, paths):
222245
"""Stale links to alternative files are removed

test/test_unit_exclude_encrypted.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@
99
def test_exclude_encrypted(runner, tmpdir, yadm, encrypt_exists, auto_exclude, exclude):
1010
"""Test exclude_encrypted()"""
1111

12-
header = "# yadm-auto-excludes\n# This section is managed by yadm.\n# Any edits below will be lost.\n"
12+
header = """\
13+
# yadm-auto-excludes
14+
# This section is managed by yadm.
15+
# Any edits below will be lost.
16+
# yadm encrypt
17+
"""
1318

1419
config_function = 'function config() { echo "false";}'
1520
if auto_exclude:

yadm

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,11 @@ function set_local_alt_values() {
691691
}
692692

693693
function alt_linking() {
694+
local -a exclude=()
695+
696+
local log="debug"
697+
[ -n "$loud" ] && log="echo"
698+
694699
local -i index
695700
for ((index = 0; index < ${#alt_targets[@]}; ++index)); do
696701
local target="${alt_targets[$index]}"
@@ -709,17 +714,17 @@ function alt_linking() {
709714
if [[ -n "$template_processor" ]]; then
710715
template "$template_processor" "$source" "$target"
711716
elif [[ "$do_copy" -eq 1 ]]; then
712-
debug "Copying $source to $target"
713-
[[ -n "$loud" ]] && echo "Copying $source to $target"
714-
717+
$log "Copying $source to $target"
715718
cp -f "$source" "$target"
716719
else
717-
debug "Linking $source to $target"
718-
[[ -n "$loud" ]] && echo "Linking $source to $target"
719-
720+
$log "Linking $source to $target"
720721
ln_relative "$source" "$target"
721722
fi
723+
724+
exclude+=("${target#"$YADM_WORK"}")
722725
done
726+
727+
update_exclude alt "${exclude[@]}"
723728
}
724729

725730
function ln_relative() {
@@ -1473,49 +1478,42 @@ function version() {
14731478

14741479
# ****** Utility Functions ******
14751480

1476-
function exclude_encrypted() {
1481+
function update_exclude() {
14771482

14781483
local auto_exclude
14791484
auto_exclude=$(config --bool yadm.auto-exclude)
14801485
[ "$auto_exclude" == "false" ] && return 0
14811486

1482-
# do nothing if there is no YADM_ENCRYPT
1483-
[ -e "$YADM_ENCRYPT" ] || return 0
1487+
local exclude_path="${YADM_REPO}/info/exclude"
1488+
local newline=$'\n'
14841489

1485-
readonly exclude_path="${YADM_REPO}/info/exclude"
1486-
readonly newline=$'\n'
1487-
readonly exclude_flag="# yadm-auto-excludes"
1490+
local part_path="$exclude_path.yadm-$1"
1491+
local part_str
1492+
part_str=$(join_string "$newline" "${@:2}")
1493+
1494+
if [ -e "$part_path" ]; then
1495+
if [ "$part_str" = "$(<"$part_path")" ]; then
1496+
return
1497+
fi
1498+
1499+
rm -f "$part_path"
1500+
elif [ -z "$part_str" ]; then
1501+
return
1502+
fi
1503+
1504+
if [ -n "$part_str" ]; then
1505+
assert_parent "$part_path"
1506+
cat >"$part_path" <<<"$part_str"
1507+
fi
1508+
1509+
local exclude_flag="# yadm-auto-excludes"
14881510

14891511
local exclude_header="${exclude_flag}${newline}"
14901512
exclude_header="${exclude_header}# This section is managed by yadm."
14911513
exclude_header="${exclude_header}${newline}"
14921514
exclude_header="${exclude_header}# Any edits below will be lost."
14931515
exclude_header="${exclude_header}${newline}"
14941516

1495-
# read encrypt
1496-
local encrypt_data=""
1497-
local pattern
1498-
while IFS='' read -r pattern || [ -n "$pattern" ]; do
1499-
case ${pattern:0:1} in
1500-
\#)
1501-
pattern=""
1502-
;;
1503-
!)
1504-
# Prepend / to the pattern so that it matches the same files as in
1505-
# parse_encrypt (i.e. only from the root)
1506-
pattern="!/${pattern:1}$newline"
1507-
;;
1508-
*)
1509-
if ! [[ $pattern =~ ^[[:blank:]]*(#|$) ]]; then
1510-
pattern="/$pattern$newline"
1511-
else
1512-
pattern=""
1513-
fi
1514-
;;
1515-
esac
1516-
encrypt_data="${encrypt_data}${pattern}"
1517-
done <"$YADM_ENCRYPT"
1518-
15191517
# read info/exclude
15201518
local unmanaged=""
15211519
local managed=""
@@ -1532,14 +1530,39 @@ function exclude_encrypted() {
15321530
done <"$exclude_path"
15331531
fi
15341532

1535-
if [ "${exclude_header}${encrypt_data}" != "$managed" ]; then
1533+
local exclude_str=""
1534+
for suffix in alt encrypt; do
1535+
if [ -e "${exclude_path}.yadm-$suffix" ]; then
1536+
local header="# yadm $suffix$newline"
1537+
exclude_str="$exclude_str$header$(<"$exclude_path".yadm-"$suffix")"
1538+
fi
1539+
done
1540+
1541+
if [ "${exclude_header}${exclude_str}${newline}" != "$managed" ]; then
15361542
debug "Updating ${exclude_path}"
1537-
assert_parent "$exclude_path"
1538-
printf "%s" "${unmanaged}${exclude_header}${encrypt_data}" >"$exclude_path"
1543+
cat >"$exclude_path" <<<"${unmanaged}${exclude_header}${exclude_str}"
15391544
fi
15401545

15411546
return 0
1547+
}
15421548

1549+
function exclude_encrypted() {
1550+
local -a exclude=()
1551+
1552+
if [ -r "$YADM_ENCRYPT" ]; then
1553+
local pattern
1554+
while IFS='' read -r pattern || [ -n "$pattern" ]; do
1555+
# Prepend / to the pattern so that it matches the same files as in
1556+
# parse_encrypt (i.e. only from the root)
1557+
if [ "${pattern:0:1}" = "!" ]; then
1558+
exclude+=("!/${pattern:1}")
1559+
elif ! [[ $pattern =~ ^[[:blank:]]*(#|$) ]]; then
1560+
exclude+=("/$pattern")
1561+
fi
1562+
done <"$YADM_ENCRYPT"
1563+
fi
1564+
1565+
update_exclude encrypt "${exclude[@]}"
15431566
}
15441567

15451568
function query_distro() {
@@ -1956,19 +1979,11 @@ function parse_encrypt() {
19561979

19571980
local pattern
19581981
while IFS='' read -r pattern || [ -n "$pattern" ]; do
1959-
case ${pattern:0:1} in
1960-
\#)
1961-
# Ignore comments
1962-
;;
1963-
!)
1964-
exclude+=("--exclude=/${pattern:1}")
1965-
;;
1966-
*)
1967-
if ! [[ $pattern =~ ^[[:blank:]]*(#|$) ]]; then
1968-
include+=("$pattern")
1969-
fi
1970-
;;
1971-
esac
1982+
if [ "${pattern:0:1}" = "!" ]; then
1983+
exclude+=("--exclude=/${pattern:1}")
1984+
elif ! [[ $pattern =~ ^[[:blank:]]*(#|$) ]]; then
1985+
include+=("$pattern")
1986+
fi
19721987
done <"$YADM_ENCRYPT"
19731988

19741989
if [ ${#include[@]} -gt 0 ]; then

yadm.1

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,8 @@ you may still run "yadm alt" manually to create the alternate links. This
363363
feature is enabled by default.
364364
.TP
365365
.B yadm.auto-exclude
366-
Disable the automatic exclusion of patterns defined in
366+
Disable the automatic exclusion of created alternate links, template files and
367+
patterns defined in
367368
.IR $HOME/.config/yadm/encrypt .
368369
This feature is enabled by default.
369370
.TP
@@ -614,6 +615,12 @@ configuration.
614615
Even if disabled, links can be manually created by running
615616
.BR "yadm alt" .
616617

618+
Created links are automatically added to the repository's
619+
.I info/exclude
620+
file. This can be disabled using the
621+
.I yadm.auto-exclude
622+
configuration.
623+
617624
Class is a special value which is stored locally on each host (inside the local
618625
repository). To use alternate symlinks using class, you must set the value of
619626
class using the configuration
@@ -748,6 +755,12 @@ would look like:
748755
<%+ whatever.extra %>
749756
<% fi -%>
750757

758+
Created files are automatically added to the repository's
759+
.I info/exclude
760+
file. This can be disabled using the
761+
.I yadm.auto-exclude
762+
configuration.
763+
751764
.SH ENCRYPTION
752765

753766
It can be useful to manage confidential files, like SSH or GPG keys, across

0 commit comments

Comments
 (0)