Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/common.bash
Original file line number Diff line number Diff line change
Expand Up @@ -1441,6 +1441,7 @@ function AconfNeedPackageFile() {
do
if sudo test -d "$dir"
then
local file
sudo find "$dir" -type f -name "$filemask" -not -name '*.sig' -print0 | \
while read -r -d $'\0' file
do
Expand Down Expand Up @@ -1844,6 +1845,21 @@ function SuperCat() {
fi
}

function ChooseHeredocTerminator() {
local src="$1" delim=EOF

while grep -q "^$delim" "$src"; do delim="$delim$delim"; done

echo $delim
}

# determine if a file can be inlined into the config when saving
function AconfIsFileInlinable() {
# implicitly inhibit errexit:
LC_ALL=C awk '/[\x00-\x09\x0B\x0C\x0E-\x1F\x7F]/{exit 1;}' "$1" && true
return $?
}

if ! ( empty_array=() ; : "${empty_array[@]}" )
then
# Old bash versions treat substitution of an empty array
Expand Down
100 changes: 93 additions & 7 deletions src/save.bash
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ function AconfSave() {
then
LogEnter 'Found %s new and %s changed files.\n' "$(Color G ${#system_only_files[@]})" "$(Color G ${#changed_files[@]})"
printf '\n\n# %s - New / changed files\n\n\n' "$(date)" >> "$config_save_target"
local file
( Print0Array system_only_files ; Print0Array changed_files ) | \
while read -r -d $'\0' file
do
Expand All @@ -147,7 +148,8 @@ function AconfSave() {
# shellcheck disable=SC2174
mkdir --mode=700 --parents "$config_dir"/files/"$dir"

local func args props suffix=''
unset func suffix heredoc_src prefix_to_expand # remove the previous values
local func suffix heredoc_src prefix_to_expand args=() props=()

local output_file="$output_dir"/files/"$file"
local system_file="$system_dir"/files/"$file"
Expand Down Expand Up @@ -185,23 +187,85 @@ function AconfSave() {
args=("$file")
props=(mode owner group)
else
local size
size=$(LC_ALL=C stat --format=%s "$system_file")
local size package
size="$(LC_ALL=C stat --format=%s "$system_file")"
package="$(pacman -Qoq "$file" 2>/dev/null || true)"
if [[ $size -eq 0 ]]
then
func=CreateFile
args=("$file")
props=(mode owner group)
suffix=' > /dev/null'

if [[ -h "$output_file" || -e "$output_file" ]]
then
printf 'RemoveFile %q\n' "$file" >> "$config_save_target"
fi
elif [[ $(wc -w <<<"$package") -le 1 ]] && AconfIsFileInlinable "$system_file"
then
AconfNeedProgram diff diffutils n
if [[ -n "$package" ]]
then
AconfNeedPackageFile "$package" >/dev/null
function GetOutputFileElsePackageFile() {
if [[ -f "$output_file" ]]
then
cat "$output_file"
else
AconfGetPackageOriginalFile "$package" "$file"
fi
}
{
# the output should contain a quoted command expansion
# shellcheck disable=SC2016
printf 'patch --no-backup-if-mismatch "$(GetPackageOriginalFile --no-clobber %s %q)" <<"EOF"\n' "$package" "$file"
diff --unified=5 --label "output/$file" --label "system/$file" \
<(GetOutputFileElsePackageFile) "$system_file" || true;
printf 'EOF\n'
# we didn't have to worry about heredoc delimiter collisions because
# unified diff lines always begin with space, plus or minus
} >> "$config_save_target"
elif [[ -f "$output_file" ]]
then
{
# the output should contain a quoted command expansion
# shellcheck disable=SC2016
printf 'patch --no-backup-if-mismatch "$(CreateFile --no-clobber %q)" <<"EOF"\n' "$file"
diff --unified=5 --label "output/$file" --label "system/$file" \
"$output_file" "$system_file" || true;
printf 'EOF\n'
# we didn't have to worry about heredoc delimiter collisions because
# unified diff lines always begin with space, plus or minus
} >> "$config_save_target"
else
func=CreateFile
args=("$file")
props=(mode owner group)
prefix_to_expand='cat >'
if [[ -f "$output_file" ]]
then
heredoc_src="$output_file"
else
heredoc_src="$system_file"
fi
local contents
case "$(head -n2 "$heredoc_src" | wc -l)" in
0|1)
contents=$(<"$heredoc_src")
unset heredoc_src
prefix_to_expand="printf -- '%s\n' ${contents@Q} >"
;;&
0)
prefix_to_expand="printf -- '%s' ${contents@Q} >"
;;
esac
fi
else
cp "$system_file" "$config_dir"/files/"$file"
func=CopyFile
args=("$file")
props=(mode owner group)
fi
args=("$file")
props=(mode owner group)
fi

# Calculate the optional function parameters
Expand All @@ -220,12 +284,34 @@ function AconfSave() {
done

# Trim redundant blank parameters
while [[ -z "${args[-1]}" ]]
while [[ "${#args[*]}" -gt 0 && -z "${args[-1]}" ]]
Comment on lines -223 to +287
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense; alternatively, it could also be moved inside the if [[ -n $func ]] block.

do
unset 'args[${#args[@]}-1]'
done

printf '%s%s%s\n' "$func" "$(printf ' %q' "${args[@]}")" "$suffix" >> "$config_save_target"
if [[ -v func ]]
then
if [[ -v prefix_to_expand ]]
then
if [[ -v heredoc_src ]]
then
local heredoc_delim
heredoc_delim="$(ChooseHeredocTerminator "$heredoc_src")"
# the output should contain a quoted command expansion
# shellcheck disable=SC2016
printf '%s "$(%s%s%s)" <<"%s"\n' "$prefix_to_expand" "$func" "$(printf ' %q' "${args[@]}")" "${suffix:-}" "$heredoc_delim"
# use sed to enforce trailing newline, via https://unix.stackexchange.com/a/31955
# shellcheck disable=SC1003
sed -e '$a\' "$heredoc_src"
printf '%s\n' "$heredoc_delim"
else
# shellcheck disable=SC2016
printf '%s "$(%s%s%s)"\n' "$prefix_to_expand" "$func" "$(printf ' %q' "${args[@]}")" "${suffix:-}"
fi
else
printf '%s%s%s\n' "$func" "$(printf ' %q' "${args[@]}")" "${suffix:-}"
fi >> "$config_save_target"
fi
done
modified=y
LogLeave
Expand Down
6 changes: 2 additions & 4 deletions test/t/t-1_save-2_files-1_stray-1_file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ TestPhase_Run #################################################################
AconfSave

TestPhase_Check ###############################################################
TestExpectConfig <<EOF
CopyFile /strayfile.txt
TestExpectConfig <<"EOF"
printf -- '%s' 'Stray file contents' > "$(CreateFile /strayfile.txt)"
EOF

diff -u "$config_dir"/files/strayfile.txt <(printf "Stray file contents")

TestDone ######################################################################
5 changes: 2 additions & 3 deletions test/t/t-1_save-2_files-1_stray-5_dirfile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@ TestPhase_Run #################################################################
AconfSave

TestPhase_Check ###############################################################
TestExpectConfig <<EOF
CopyFile /dir/strayfile.txt
TestExpectConfig <<"EOF"
printf -- '%s' 'Stray file contents' > "$(CreateFile /dir/strayfile.txt)"
EOF

diff -u "$config_dir"/files/dir/strayfile.txt <(printf "Stray file contents")

TestDone ######################################################################
6 changes: 2 additions & 4 deletions test/t/t-1_save-2_files-1_stray-6_props.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@ TestPhase_Run #################################################################
AconfSave

TestPhase_Check ###############################################################
TestExpectConfig <<EOF
CopyFile /strayfile.txt 777 billy wheel
TestExpectConfig <<"EOF"
printf -- '%s' 'Stray file contents' > "$(CreateFile /strayfile.txt 777 billy wheel)"
EOF

diff -u "$config_dir"/files/strayfile.txt <(printf "Stray file contents")

TestDone ######################################################################
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ AconfSave

TestPhase_Check ###############################################################

TestExpectConfig <<EOF
CopyFile /badfile.txt
TestExpectConfig <<"EOF"
printf -- '%s' 'Not original file' > "$(CreateFile /badfile.txt)"
EOF

TestDone ######################################################################
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ AconfSave

TestPhase_Check ###############################################################

TestExpectConfig <<EOF
CopyFile /badfile.txt
TestExpectConfig <<"EOF"
printf -- '%s' 'Another file!' > "$(CreateFile /badfile.txt)"
EOF

TestDone ######################################################################
10 changes: 5 additions & 5 deletions test/t/t-1_save-2_files-4_ignored-2_shellpatterns.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ TestPhase_Run #################################################################
AconfSave

TestPhase_Check ###############################################################
TestExpectConfig <<EOF
CopyFile /strayfile\ e\ y\ ff.txt
CopyFile /strayfile-three.txt
CopyFile /strayfilex.txt
CopyFile /strayfilez.txt
TestExpectConfig <<"EOF"
printf -- '%s' 'Stray file contents' > "$(CreateFile /strayfile\ e\ y\ ff.txt)"
printf -- '%s' 'Stray file contents' > "$(CreateFile /strayfile-three.txt)"
printf -- '%s' 'Stray file contents' > "$(CreateFile /strayfilex.txt)"
printf -- '%s' 'Stray file contents' > "$(CreateFile /strayfilez.txt)"
EOF

TestDone ######################################################################
Loading