@@ -22,7 +22,7 @@ if [ -z "$BASH_VERSION" ]; then
22
22
[ " $YADM_TEST " != 1 ] && exec bash " $0 " " $@ "
23
23
fi
24
24
25
- VERSION=3.4 .0
25
+ VERSION=3.5 .0
26
26
27
27
YADM_WORK=" $HOME "
28
28
YADM_DIR=
@@ -61,6 +61,7 @@ PROC_VERSION="/proc/version"
61
61
OPERATING_SYSTEM=" Unknown"
62
62
63
63
ENCRYPT_INCLUDE_FILES=" unparsed"
64
+ NO_ENCRYPT_TRACKED_FILES=()
64
65
65
66
LEGACY_WARNING_ISSUED=0
66
67
INVALID_ALT=()
@@ -179,39 +180,50 @@ function score_file() {
179
180
local value=${field#* .}
180
181
[ " $field " = " $label " ] && value=" " # when .value is omitted
181
182
183
+ # Check for negative condition prefix (e.g., "~<label>")
184
+ local negate=0
185
+ if [ " ${label: 0: 1} " = " ~" ]; then
186
+ negate=1
187
+ label=" ${label: 1} "
188
+ fi
189
+
182
190
shopt -s nocasematch
183
- local -i delta=-1
191
+ local -i delta=$(( negate ? 1 : - 1 ))
184
192
case " $label " in
185
193
default)
186
- delta=0
194
+ if (( negate)) ; then
195
+ INVALID_ALT+=(" $source " )
196
+ else
197
+ delta=0
198
+ fi
187
199
;;
188
200
a | arch)
189
- [[ " $value " = " $local_arch " ]] && delta=1
201
+ [[ " $value " = " $local_arch " ]] && delta=1 || delta=-1
190
202
;;
191
203
o | os)
192
- [[ " $value " = " $local_system " ]] && delta=2
204
+ [[ " $value " = " $local_system " ]] && delta=2 || delta=-2
193
205
;;
194
206
d | distro)
195
- [[ " ${value// / _} " = " ${local_distro// / _} " ]] && delta=4
207
+ [[ " ${value// / _} " = " ${local_distro// / _} " ]] && delta=4 || delta=-4
196
208
;;
197
209
f | distro_family)
198
- [[ " ${value// / _} " = " ${local_distro_family// / _} " ]] && delta=8
210
+ [[ " ${value// / _} " = " ${local_distro_family// / _} " ]] && delta=8 || delta=-8
199
211
;;
200
212
c | class)
201
- in_list " $value " " ${local_classes[@]} " && delta=16
213
+ in_list " $value " " ${local_classes[@]} " && delta=16 || delta=-16
202
214
;;
203
215
h | hostname)
204
- [[ " $value " = " $local_host " ]] && delta=32
216
+ [[ " $value " = " $local_host " ]] && delta=32 || delta=-32
205
217
;;
206
218
u | user)
207
- [[ " $value " = " $local_user " ]] && delta=64
219
+ [[ " $value " = " $local_user " ]] && delta=64 || delta=-64
208
220
;;
209
221
e | extension)
210
222
# extension isn't a condition and doesn't affect the score
211
223
continue
212
224
;;
213
225
t | template | yadm)
214
- if [ -d " $source " ]; then
226
+ if [ -d " $source " ] || (( negate )) ; then
215
227
INVALID_ALT+=(" $source " )
216
228
else
217
229
template_processor=$( choose_template_processor " $value " )
@@ -230,11 +242,12 @@ function score_file() {
230
242
esac
231
243
shopt -u nocasematch
232
244
245
+ (( negate)) && delta=$(( - delta))
233
246
if (( delta < 0 )) ; then
234
247
score=0
235
248
return
236
249
fi
237
- score=$(( score + 1000 + delta ))
250
+ score=$(( score + delta + (negate ? 0 : 1000 ) ) )
238
251
done
239
252
240
253
record_score " $score " " $target " " $source " " $template_processor "
@@ -366,7 +379,7 @@ BEGIN {
366
379
yadm["user"] = user
367
380
yadm["distro"] = distro
368
381
yadm["distro_family"] = distro_family
369
- yadm["source"] = source
382
+ yadm["source"] = ARGV[1]
370
383
371
384
VARIABLE = "(env|yadm)\\.[a-zA-Z0-9_]+"
372
385
@@ -456,6 +469,9 @@ function replace_vars(input) {
456
469
if (fields[1] == "env") {
457
470
output = output ENVIRON[fields[2]]
458
471
}
472
+ else if (fields[2] == "filename") {
473
+ output = output filename[current]
474
+ }
459
475
else {
460
476
output = output yadm[fields[2]]
461
477
}
472
488
-v user=" $local_user " \
473
489
-v distro=" $local_distro " \
474
490
-v distro_family=" $local_distro_family " \
475
- -v source=" $input " \
476
491
-v source_dir=" $( builtin_dirname " $input " ) " \
477
492
" $awk_pgm " \
478
493
" $input " " ${local_classes[@]} "
@@ -690,6 +705,11 @@ function set_local_alt_values() {
690
705
}
691
706
692
707
function alt_linking() {
708
+ local -a exclude=()
709
+
710
+ local log=" debug"
711
+ [ -n " $loud " ] && log=" echo"
712
+
693
713
local -i index
694
714
for (( index = 0 ; index < ${# alt_targets[@]} ; ++ index)) ; do
695
715
local target=" ${alt_targets[$index]} "
@@ -708,17 +728,17 @@ function alt_linking() {
708
728
if [[ -n " $template_processor " ]]; then
709
729
template " $template_processor " " $source " " $target "
710
730
elif [[ " $do_copy " -eq 1 ]]; then
711
- debug " Copying $source to $target "
712
- [[ -n " $loud " ]] && echo " Copying $source to $target "
713
-
731
+ $log " Copying $source to $target "
714
732
cp -f " $source " " $target "
715
733
else
716
- debug " Linking $source to $target "
717
- [[ -n " $loud " ]] && echo " Linking $source to $target "
718
-
734
+ $log " Linking $source to $target "
719
735
ln_relative " $source " " $target "
720
736
fi
737
+
738
+ exclude+=(" ${target# " $YADM_WORK " } " )
721
739
done
740
+
741
+ update_exclude alt " ${exclude[@]} "
722
742
}
723
743
724
744
function ln_relative() {
@@ -1042,6 +1062,12 @@ function encrypt() {
1042
1062
printf ' %s\n' " ${ENCRYPT_INCLUDE_FILES[@]} "
1043
1063
echo
1044
1064
1065
+ if [ ${# NO_ENCRYPT_TRACKED_FILES[@]} -gt 0 ]; then
1066
+ echo " Warning: The following files are tracked and will NOT be encrypted:"
1067
+ printf ' %s\n' " ${NO_ENCRYPT_TRACKED_FILES[@]} "
1068
+ echo
1069
+ fi
1070
+
1045
1071
# encrypt all files which match the globs
1046
1072
if tar -f - -c " ${ENCRYPT_INCLUDE_FILES[@]} " | _encrypt_to " $YADM_ARCHIVE " ; then
1047
1073
echo " Wrote new file: $YADM_ARCHIVE "
@@ -1466,52 +1492,91 @@ function version() {
1466
1492
1467
1493
# ****** Utility Functions ******
1468
1494
1469
- function exclude_encrypted () {
1495
+ function update_exclude () {
1470
1496
1497
+ local auto_exclude
1471
1498
auto_exclude=$( config --bool yadm.auto-exclude)
1472
1499
[ " $auto_exclude " == " false" ] && return 0
1473
1500
1474
- exclude_path=" ${YADM_REPO} /info/exclude"
1475
- newline=$' \n '
1476
- exclude_flag=" # yadm-auto-excludes"
1477
- exclude_header=" ${exclude_flag}${newline} "
1501
+ local exclude_path=" ${YADM_REPO} /info/exclude"
1502
+ local newline=$' \n '
1503
+
1504
+ local part_path=" $exclude_path .yadm-$1 "
1505
+ local part_str
1506
+ part_str=$( join_string " $newline " " ${@: 2} " )
1507
+
1508
+ if [ -e " $part_path " ]; then
1509
+ if [ " $part_str " = " $( < " $part_path " ) " ]; then
1510
+ return
1511
+ fi
1512
+
1513
+ rm -f " $part_path "
1514
+ elif [ -z " $part_str " ]; then
1515
+ return
1516
+ fi
1517
+
1518
+ if [ -n " $part_str " ]; then
1519
+ assert_parent " $part_path "
1520
+ cat > " $part_path " <<< " $part_str"
1521
+ fi
1522
+
1523
+ local exclude_flag=" # yadm-auto-excludes"
1524
+
1525
+ local exclude_header=" ${exclude_flag}${newline} "
1478
1526
exclude_header=" ${exclude_header} # This section is managed by yadm."
1479
1527
exclude_header=" ${exclude_header}${newline} "
1480
1528
exclude_header=" ${exclude_header} # Any edits below will be lost."
1481
1529
exclude_header=" ${exclude_header}${newline} "
1482
1530
1483
- # do nothing if there is no YADM_ENCRYPT
1484
- [ -e " $YADM_ENCRYPT " ] || return 0
1485
-
1486
- # read encrypt
1487
- encrypt_data=" "
1488
- while IFS=' ' read -r line || [ -n " $line " ]; do
1489
- encrypt_data=" ${encrypt_data}${line}${newline} "
1490
- done < " $YADM_ENCRYPT "
1491
-
1492
1531
# read info/exclude
1493
- unmanaged=" "
1494
- managed=" "
1532
+ local unmanaged=" "
1533
+ local managed=" "
1495
1534
if [ -e " $exclude_path " ]; then
1496
- flag_seen=0
1535
+ local -i flag_seen=0
1536
+ local line
1497
1537
while IFS=' ' read -r line || [ -n " $line " ]; do
1498
1538
[ " $line " = " $exclude_flag " ] && flag_seen=1
1499
- if [ " $flag_seen " -eq 0 ]; then
1500
- unmanaged=" ${unmanaged}${line}${newline} "
1501
- else
1539
+ if (( flag_seen)) ; then
1502
1540
managed=" ${managed}${line}${newline} "
1541
+ else
1542
+ unmanaged=" ${unmanaged}${line}${newline} "
1503
1543
fi
1504
1544
done < " $exclude_path "
1505
1545
fi
1506
1546
1507
- if [ " ${exclude_header}${encrypt_data} " != " $managed " ]; then
1547
+ local exclude_str=" "
1548
+ for suffix in alt encrypt; do
1549
+ if [ -e " ${exclude_path} .yadm-$suffix " ]; then
1550
+ local header=" # yadm $suffix$newline "
1551
+ exclude_str=" $exclude_str$header $( < " $exclude_path " .yadm-" $suffix " ) "
1552
+ fi
1553
+ done
1554
+
1555
+ if [ " ${exclude_header}${exclude_str}${newline} " != " $managed " ]; then
1508
1556
debug " Updating ${exclude_path} "
1509
- assert_parent " $exclude_path "
1510
- printf " %s" " ${unmanaged}${exclude_header}${encrypt_data} " > " $exclude_path "
1557
+ cat > " $exclude_path " <<< " ${unmanaged}${exclude_header}${exclude_str}"
1511
1558
fi
1512
1559
1513
1560
return 0
1561
+ }
1562
+
1563
+ function exclude_encrypted() {
1564
+ local -a exclude=()
1565
+
1566
+ if [ -r " $YADM_ENCRYPT " ]; then
1567
+ local pattern
1568
+ while IFS=' ' read -r pattern || [ -n " $pattern " ]; do
1569
+ # Prepend / to the pattern so that it matches the same files as in
1570
+ # parse_encrypt (i.e. only from the root)
1571
+ if [ " ${pattern: 0: 1} " = " !" ]; then
1572
+ exclude+=(" !/${pattern: 1} " )
1573
+ elif ! [[ $pattern =~ ^[[:blank:]]* (# |$) ]]; then
1574
+ exclude+=(" /$pattern " )
1575
+ fi
1576
+ done < " $YADM_ENCRYPT "
1577
+ fi
1514
1578
1579
+ update_exclude encrypt " ${exclude[@]} "
1515
1580
}
1516
1581
1517
1582
function query_distro() {
@@ -1926,26 +1991,36 @@ function parse_encrypt() {
1926
1991
local -a exclude
1927
1992
local -a include
1928
1993
1929
- while IFS= read -r pattern; do
1930
- case $pattern in
1931
- \# * )
1932
- # Ignore comments
1933
- ;;
1934
- !* )
1935
- exclude+=(" --exclude=${pattern: 1} " )
1936
- ;;
1937
- * )
1938
- if ! [[ $pattern =~ ^[[:blank:]]* $ ]]; then
1939
- include+=(" $pattern " )
1940
- fi
1941
- ;;
1942
- esac
1994
+ local pattern
1995
+ while IFS=' ' read -r pattern || [ -n " $pattern " ]; do
1996
+ if [ " ${pattern: 0: 1} " = " !" ]; then
1997
+ exclude+=(" --exclude=/${pattern: 1} " )
1998
+ elif ! [[ $pattern =~ ^[[:blank:]]* (# |$) ]]; then
1999
+ include+=(" $pattern " )
2000
+ fi
1943
2001
done < " $YADM_ENCRYPT "
1944
2002
1945
- if [[ ${# include} -gt 0 ]]; then
1946
- while IFS= read -r filename; do
1947
- ENCRYPT_INCLUDE_FILES+=(" ${filename%/ } " )
1948
- done <<< " $(" $GIT_PROGRAM " ls-files --others " ${exclude[@]} " -- " ${include[@]} " )"
2003
+ if [ ${# include[@]} -gt 0 ]; then
2004
+ while IFS=' ' read -r filename; do
2005
+ if [ -n " $filename " ]; then
2006
+ ENCRYPT_INCLUDE_FILES+=(" ${filename%/ } " )
2007
+ fi
2008
+ done <<< " $(
2009
+ " $GIT_PROGRAM " --glob-pathspecs ls-files --others \
2010
+ " ${exclude[@]} " -- " ${include[@]} " 2>/dev/null
2011
+ )"
2012
+
2013
+ [ " $YADM_COMMAND " = " encrypt" ] || return
2014
+
2015
+ # List files that matches encryption pattern but is tracked
2016
+ while IFS=' ' read -r filename; do
2017
+ if [ -n " $filename " ]; then
2018
+ NO_ENCRYPT_TRACKED_FILES+=(" ${filename%/ } " )
2019
+ fi
2020
+ done <<< " $(
2021
+ " $GIT_PROGRAM " --glob-pathspecs ls-files \
2022
+ " ${exclude[@]} " -- " ${include[@]} "
2023
+ )"
1949
2024
fi
1950
2025
}
1951
2026
0 commit comments