mirror of
https://github.com/TheLocehiliosan/yadm
synced 2025-06-04 08:33:57 +00:00
Add support for negative alt conditions (#522)
This commit is contained in:
parent
d4796108f4
commit
9ff5e09650
@ -321,3 +321,76 @@ def test_underscores_and_upper_case_in_distro_and_family(runner, yadm):
|
|||||||
assert run.success
|
assert run.success
|
||||||
assert run.err == ""
|
assert run.err == ""
|
||||||
assert run.out == expected
|
assert run.out == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_negative_class_condition(runner, yadm):
|
||||||
|
"""Test negative class condition: returns 0 when matching and proper score when not matching."""
|
||||||
|
script = f"""
|
||||||
|
YADM_TEST=1 source {yadm}
|
||||||
|
local_class="testclass"
|
||||||
|
local_classes=("testclass")
|
||||||
|
|
||||||
|
# 0
|
||||||
|
score=0
|
||||||
|
score_file "filename##~class.testclass" "dest"
|
||||||
|
echo "score: $score"
|
||||||
|
|
||||||
|
# 16
|
||||||
|
score=0
|
||||||
|
score_file "filename##~class.badclass" "dest"
|
||||||
|
echo "score2: $score"
|
||||||
|
|
||||||
|
# 16
|
||||||
|
score=0
|
||||||
|
score_file "filename##~c.badclass" "dest"
|
||||||
|
echo "score3: $score"
|
||||||
|
"""
|
||||||
|
run = runner(command=["bash"], inp=script)
|
||||||
|
assert run.success
|
||||||
|
output = run.out.strip().splitlines()
|
||||||
|
assert output[0] == "score: 0"
|
||||||
|
assert output[1] == "score2: 16"
|
||||||
|
assert output[2] == "score3: 16"
|
||||||
|
|
||||||
|
|
||||||
|
def test_negative_combined_conditions(runner, yadm):
|
||||||
|
"""Test negative conditions for multiple alt types: returns 0 when matching and proper score when not matching."""
|
||||||
|
script = f"""
|
||||||
|
YADM_TEST=1 source {yadm}
|
||||||
|
local_class="testclass"
|
||||||
|
local_classes=("testclass")
|
||||||
|
local_distro="testdistro"
|
||||||
|
|
||||||
|
# (0) + (0) = 0
|
||||||
|
score=0
|
||||||
|
score_file "filename##~class.testclass,~distro.testdistro" "dest"
|
||||||
|
echo "score: $score"
|
||||||
|
|
||||||
|
# (1000 + 16) + (1000 + 4) = 2020
|
||||||
|
score=0
|
||||||
|
score_file "filename##class.testclass,distro.testdistro" "dest"
|
||||||
|
echo "score2: $score"
|
||||||
|
|
||||||
|
# 0 (negated class condition)
|
||||||
|
score=0
|
||||||
|
score_file "filename##~class.badclass,~distro.testdistro" "dest"
|
||||||
|
echo "score3: $score"
|
||||||
|
|
||||||
|
# (1000 + 16) + (4) = 1020
|
||||||
|
score=0
|
||||||
|
score_file "filename##class.testclass,~distro.baddistro" "dest"
|
||||||
|
echo "score4: $score"
|
||||||
|
|
||||||
|
# (1000 + 16) + (16) = 1032
|
||||||
|
score=0
|
||||||
|
score_file "filename##class.testclass,~class.badclass" "dest"
|
||||||
|
echo "score5: $score"
|
||||||
|
"""
|
||||||
|
run = runner(command=["bash"], inp=script)
|
||||||
|
assert run.success
|
||||||
|
output = run.out.strip().splitlines()
|
||||||
|
assert output[0] == "score: 0"
|
||||||
|
assert output[1] == "score2: 2020"
|
||||||
|
assert output[2] == "score3: 0"
|
||||||
|
assert output[3] == "score4: 1020"
|
||||||
|
assert output[4] == "score5: 1032"
|
||||||
|
27
yadm
27
yadm
@ -180,32 +180,39 @@ function score_file() {
|
|||||||
local value=${field#*.}
|
local value=${field#*.}
|
||||||
[ "$field" = "$label" ] && value="" # when .value is omitted
|
[ "$field" = "$label" ] && value="" # when .value is omitted
|
||||||
|
|
||||||
|
# Check for negative condition prefix (e.g., "~<label>")
|
||||||
|
local negate=0
|
||||||
|
if [ "${label:0:1}" = "~" ]; then
|
||||||
|
negate=1
|
||||||
|
label="${label:1}"
|
||||||
|
fi
|
||||||
|
|
||||||
shopt -s nocasematch
|
shopt -s nocasematch
|
||||||
local -i delta=-1
|
local -i delta=$((negate ? 1 : -1))
|
||||||
case "$label" in
|
case "$label" in
|
||||||
default)
|
default)
|
||||||
delta=0
|
delta=0
|
||||||
;;
|
;;
|
||||||
a | arch)
|
a | arch)
|
||||||
[[ "$value" = "$local_arch" ]] && delta=1
|
[[ "$value" = "$local_arch" ]] && delta=1 || delta=-1
|
||||||
;;
|
;;
|
||||||
o | os)
|
o | os)
|
||||||
[[ "$value" = "$local_system" ]] && delta=2
|
[[ "$value" = "$local_system" ]] && delta=2 || delta=-2
|
||||||
;;
|
;;
|
||||||
d | distro)
|
d | distro)
|
||||||
[[ "${value// /_}" = "${local_distro// /_}" ]] && delta=4
|
[[ "${value// /_}" = "${local_distro// /_}" ]] && delta=4 || delta=-4
|
||||||
;;
|
;;
|
||||||
f | distro_family)
|
f | distro_family)
|
||||||
[[ "${value// /_}" = "${local_distro_family// /_}" ]] && delta=8
|
[[ "${value// /_}" = "${local_distro_family// /_}" ]] && delta=8 || delta=-8
|
||||||
;;
|
;;
|
||||||
c | class)
|
c | class)
|
||||||
in_list "$value" "${local_classes[@]}" && delta=16
|
in_list "$value" "${local_classes[@]}" && delta=16 || delta=-16
|
||||||
;;
|
;;
|
||||||
h | hostname)
|
h | hostname)
|
||||||
[[ "$value" = "$local_host" ]] && delta=32
|
[[ "$value" = "$local_host" ]] && delta=32 || delta=-32
|
||||||
;;
|
;;
|
||||||
u | user)
|
u | user)
|
||||||
[[ "$value" = "$local_user" ]] && delta=64
|
[[ "$value" = "$local_user" ]] && delta=64 || delta=-64
|
||||||
;;
|
;;
|
||||||
e | extension)
|
e | extension)
|
||||||
# extension isn't a condition and doesn't affect the score
|
# extension isn't a condition and doesn't affect the score
|
||||||
@ -231,11 +238,13 @@ function score_file() {
|
|||||||
esac
|
esac
|
||||||
shopt -u nocasematch
|
shopt -u nocasematch
|
||||||
|
|
||||||
|
((negate)) && delta=$((-delta))
|
||||||
if ((delta < 0)); then
|
if ((delta < 0)); then
|
||||||
score=0
|
score=0
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
score=$((score + 1000 + delta))
|
((negate)) || delta=$((delta + 1000))
|
||||||
|
score=$((score + delta))
|
||||||
done
|
done
|
||||||
|
|
||||||
record_score "$score" "$target" "$source" "$template_processor"
|
record_score "$score" "$target" "$source" "$template_processor"
|
||||||
|
24
yadm.1
24
yadm.1
@ -476,9 +476,11 @@ commas.
|
|||||||
|
|
||||||
Each condition is an attribute/value pair, separated by a period. Some
|
Each condition is an attribute/value pair, separated by a period. Some
|
||||||
conditions do not require a "value", and in that case, the period and value can
|
conditions do not require a "value", and in that case, the period and value can
|
||||||
be omitted. Most attributes can be abbreviated as a single letter.
|
be omitted. Most attributes can be abbreviated as a single letter. Prefixing an
|
||||||
|
attribute with "~" negates the condition, meaning the condition is considered
|
||||||
|
only if the attribute/value pair evaluates to false.
|
||||||
|
|
||||||
<attribute>[.<value>]
|
[~]<attribute>[.<value>]
|
||||||
|
|
||||||
.BR NOTE :
|
.BR NOTE :
|
||||||
Value is compared case-insensitive.
|
Value is compared case-insensitive.
|
||||||
@ -555,9 +557,10 @@ symbolic links will be created for the most appropriate version.
|
|||||||
|
|
||||||
The "most appropriate" version is determined by calculating a score for each
|
The "most appropriate" version is determined by calculating a score for each
|
||||||
version of a file. A template is always scored higher than any symlink
|
version of a file. A template is always scored higher than any symlink
|
||||||
condition. The number of conditions is the next largest factor in scoring.
|
condition. The number of conditions is the next largest factor in scoring;
|
||||||
Files with more conditions will always be favored. Any invalid condition will
|
files with more conditions will always be favored. Negative conditions (prefixed
|
||||||
disqualify that file completely.
|
with "~") are scored only relative to the number of non-negated conditions.
|
||||||
|
Any invalid condition will disqualify that file completely.
|
||||||
|
|
||||||
If you don't care to have all versions of alternates stored in the same
|
If you don't care to have all versions of alternates stored in the same
|
||||||
directory as the generated symlink, you can place them in the
|
directory as the generated symlink, you can place them in the
|
||||||
@ -576,6 +579,7 @@ files are managed by yadm's repository:
|
|||||||
- $HOME/path/example.txt##os.Linux
|
- $HOME/path/example.txt##os.Linux
|
||||||
- $HOME/path/example.txt##os.Linux,hostname.host1
|
- $HOME/path/example.txt##os.Linux,hostname.host1
|
||||||
- $HOME/path/example.txt##os.Linux,hostname.host2
|
- $HOME/path/example.txt##os.Linux,hostname.host2
|
||||||
|
- $HOME/path/example.txt##class.Work,~os.Darwin
|
||||||
|
|
||||||
If running on a Macbook named "host2",
|
If running on a Macbook named "host2",
|
||||||
yadm will create a symbolic link which looks like this:
|
yadm will create a symbolic link which looks like this:
|
||||||
@ -598,10 +602,18 @@ If running on a Solaris server, the link will use the default version:
|
|||||||
|
|
||||||
.IR $HOME/path/example.txt " -> " $HOME/path/example.txt##default
|
.IR $HOME/path/example.txt " -> " $HOME/path/example.txt##default
|
||||||
|
|
||||||
If running on a system, with class set to "Work", the link will be:
|
If running on a Macbook with class set to "Work", the link will be:
|
||||||
|
|
||||||
.IR $HOME/path/example.txt " -> " $HOME/path/example.txt##class.Work
|
.IR $HOME/path/example.txt " -> " $HOME/path/example.txt##class.Work
|
||||||
|
|
||||||
|
Negative conditions are supported via the "~" prefix. If again running on a system
|
||||||
|
with class set to "Work", but instead within Windows Subsystem for Linux, where the
|
||||||
|
os is reported as WSL, the link will be:
|
||||||
|
|
||||||
|
.IR $HOME/path/example.txt " -> " $HOME/path/example.txt##class.Work,~os.Darwin
|
||||||
|
|
||||||
|
Negative conditions use the same weight which corresponds to the attached attribute.
|
||||||
|
|
||||||
If no "##default" version exists and no files have valid conditions, then no
|
If no "##default" version exists and no files have valid conditions, then no
|
||||||
link will be created.
|
link will be created.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user