-. lib/for_line_in.sh
. lib/prefixed_msg.sh
-apt_get_digested() {
-prefixed_msg_init 'apt_get_digested'
+# NB: to avoid confusing the IFS handling, ensure none of the lines is empty –
+# even if ignored!
+apt_get_digested_SEDS=$(cat << "DELIMITER"
+Get:
+Get:[[:digit:]]+ (.*)
+\1
+--------------------
+Hit:
+Hit:[[:digit:]]+ (.*)
+\1
+--------------------
+.
+Generation complete.
+IGNORE
+--------------------
+.
+Preconfiguring packages \.\.\.
+IGNORE
+--------------------
+.
+Preparing to unpack [[:print:]]+ \.\.\.
+IGNORE
+--------------------
+.
+Unpacking [[:print:]]+ \([[:print:]]+\)( over \([[:print:]]+\))? \.\.\.
+IGNORE
+--------------------
+Adding diversion(s):
+Adding 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)'
+ \3:[\1 → \2]
+--------------------
+Created symlink(s):
+Created symlink '([[:print:]]+)' → '([[:print:]]+)'\.
+ [\1 → \2]
+--------------------
+Installing new version of config file(s):
+Installing new version of config file ([[:print:]]+) \.\.\.
+\1
+--------------------
+Processing triggers for:
+Processing triggers for ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Purging configuration files:
+Purging configuration files for ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Removing:
+Removing ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Removing diversion(s):
+Removing 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)
+ \3:[\1 → \2]
+--------------------
+Removing obsolete conffile(s):
+Removing obsolete conffile ([[:print:]]+) \.\.\.
+\1
+--------------------
+Selecting previously unselected:
+Selecting previously unselected package ([[:print:]]+)\.
+\1
+--------------------
+Setting up:
+Setting up ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Updating to current default:
+Updating ([[:print:]]+) to current default.
+\1
+--------------------
+disabled or static unit, so not starting:
+([[:print:]]+) is a disabled or a static unit, not starting it\.
+\1
+--------------------
-local FINISH_LINE='apt_get_digested_FINISH_LINE'
-local SEDS=\
-'|\(Reading database \.\.\. .*|IGNORE
-|Generation complete.|IGNORE
-|Preconfiguring packages \.\.\.|IGNORE
-|Preparing to unpack [[:print:]]+ \.\.\.|IGNORE
-|Unpacking [[:print:]]+ \([[:print:]]+\)( over \([[:print:]]+\))? \.\.\.|IGNORE
-Adding diversion(s):|Adding '"'"'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)'"'"'| \3:[\1 → \2]
-Created symlink(s):|Created symlink '"'"'([[:print:]]+)'"'"' → '"'"'([[:print:]]+)'"'"'\.| [\1 → \2]
-FOLLOW_PREFIX|([[:print:]]+) depends on ([[:print:]]+)( \([>=]+ [[:print:]]+\))?\.|[\2 → \1]
-Installing new version of config file(s):|Installing new version of config file ([[:print:]]+) \.\.\.|\1
-Processing triggers for:|Processing triggers for ([[:print:]]+) \([[:print:]]+\) \.\.\.|\1
-Purging configuration files:|Purging configuration files for ([[:print:]]+) \([[:print:]]+\) \.\.\.|\1
-Removing:|Removing ([[:print:]]+) \([[:print:]]+\) \.\.\.|\1
-Removing diversion(s):|Removing '"'"'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)| \3:[\1 → \2]
-Removing obsolete conffile(s):|Removing obsolete conffile ([[:print:]]+) \.\.\.|\1
-Selecting previously unselected:|Selecting previously unselected package ([[:print:]]+)\.|\1
-Setting up:|Setting up ([[:print:]]+) \([[:print:]]+\) \.\.\.|\1
-Updating to current default:|Updating ([[:print:]]+) to current default.|\1
-disabled or static unit, so not starting:|([[:print:]]+) is a disabled or a static unit, not starting it\.|\1
-disabled or static unit not running, so not starting:|([[:print:]]+) is a disabled or a static unit not running, not starting it\.|\1
-BECOME_NEXT_PREFIX|dpkg: ([[:print:]]+): dependency problems, but removing anyway as you requested:|dpkg warns: removing \1 despite dependency problems:
-dpkg warns: unable to delete old directories (not empty):|dpkg: warning: unable to delete old directory '"'"'([[:print:]]+)'"'"': Directory not empty|\1
-update-alternatives: providing in auto mode:|update-alternatives: using ([[:print:]]+) to provide ([[:print:]]+) \(([[:print:]]+)\) in auto mode| [\1 → \2 (\3)]'
+disabled or static unit not running, so not starting:
+([[:print:]]+) is a disabled or a static unit not running, not starting it\.
+\1
+--------------------
+dpkg warns: unable to delete old directories (not empty):
+dpkg: warning: unable to delete old directory '"'"'([[:print:]]+)'"'"': Directory not empty
+\1
+--------------------
+update-alternatives: providing in auto mode:
+update-alternatives: using ([[:print:]]+) to provide ([[:print:]]+) \(([[:print:]]+)\) in auto mode
+ [\1 → \2 (\3)]
+--------------------
+Warning: Problem unlinking files (Remove Caches/13: Permission denied):
+Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
+\1
+--------------------
+.
+\(Reading database \.\.\. .*
+IGNORE
+--------------------
+.
+WARNING: apt does not have a stable CLI interface.*
+IGNORE
+--------------------
+Warning: Problem unlinking files (Remove Caches/13: Permission denied):
+Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
+\1
+--------------------
+FOLLOW_PREFIX
+([[:print:]]+) depends on ([[:print:]]+)( \([>=]+ [[:print:]]+\))?\.
+[\2 → \1]
+--------------------
+BECOME_NEXT_PREFIX
+dpkg: ([[:print:]]+): dependency problems, but removing anyway as you requested:
+dpkg warns: removing \1 despite dependency problems:
+--------------------
+DELIMITER
+)
-print_nl_if_started_printing() {
- if [ -n "${STARTED_PRINTING}" ]; then
- printf '\n'
- fi
- printf '\r'
-}
-local LAST_PREFIX=''
-local STARTED_PRINTING=
-local LEADER_PREFIX=
-local APT_GET_EXIT_CODE=
-local APT_LINE=
-eval "set +e; DEBIAN_FRONTEND=noninteractive apt install -y $1; APT_GET_EXIT_CODE=\$?; set -e; echo ${FINISH_LINE} \${APT_GET_EXIT_CODE}" 2>&1 | while read APT_LINE; do
- APT_LINE=$(printf '%s' "${APT_LINE}" | tr -d '\r')
- if [ -z "${APT_LINE}" ]; then
- continue
- elif [ "$(echo ${APT_LINE} | cut -d' ' -f1)" = "${FINISH_LINE}" ]; then
- print_nl_if_started_printing
- local EXIT_CODE=$(echo ${APT_LINE} | cut -d' ' -f2)
- if [ "${EXIT_CODE}" != "0" ]; then
- false
- fi
- break
- fi
- local COMPRESSED_ITEM=''
- local PREFIX=
- try_seds() {
- local SED=$1
- PREFIX=$(printf '%s' "${SED}" | cut -d'|' -f1)
- local PATTERN=$(printf '^%s$' "${SED}" | cut -d'|' -f2)
- local REPLACEMENT=$(printf '%s' "${SED}" | cut -d'|' -f3)
- if printf '%s' "${APT_LINE}" | grep -E "${PATTERN}" > /dev/null; then
- COMPRESSED_ITEM=$(printf '%s' "${APT_LINE}" | sed -E "s|${PATTERN}|${REPLACEMENT}|")
- if [ "${PREFIX}" = "BECOME_NEXT_PREFIX" ]; then
- LEADER_PREFIX="${COMPRESSED_ITEM}"
- COMPRESSED_ITEM=IGNORE
- elif [ "${PREFIX}" = "FOLLOW_PREFIX" ]; then
- PREFIX="${LEADER_PREFIX}"
+apt_get_digested() {
+ prefixed_msg_init 'apt_get_digested'
+ local APT_GET_EXIT_CODE
+ local FINISH_LINE='apt_get_digested_FINISH_LINE'
+
+ run_apt() {
+ set +e
+ DEBIAN_FRONTEND=noninteractive apt -y "$@"
+ APT_GET_EXIT_CODE=$?
+ set -e
+ echo "${FINISH_LINE} ${APT_GET_EXIT_CODE}"
+ }
+
+ local OUR_NEWLINE='\r' # be \n\r except on 1st run, so no empty 1st line
+ local LAST_PREFIX=
+ local LEADER_PREFIX
+ local APT_LINE
+ run_apt "$@" 2>&1 | while read -r APT_LINE; do
+ APT_LINE=$(printf '%s' "${APT_LINE}" | tr -d '\r')
+ if [ -z "${APT_LINE}" ]; then
+ continue
+ else
+ local FIRST_FIELD
+ FIRST_FIELD=$(echo "${APT_LINE}" | cut -d' ' -f1)
+ if [ "${FIRST_FIELD}" = "${FINISH_LINE}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ local EXIT_CODE
+ EXIT_CODE=$(echo "${APT_LINE}" | cut -d' ' -f2)
+ if [ "${EXIT_CODE}" != "0" ]; then
+ false
+ fi
+ break
fi
- break
fi
- }
- for_line_in "${SEDS}" try_seds
- if [ "${COMPRESSED_ITEM}" = "IGNORE" ]; then
- continue
- elif [ -z "${COMPRESSED_ITEM}" ]; then
- print_nl_if_started_printing
- prefixed_msg_no_nl "${APT_LINE}"
- LAST_PREFIX=''
- else
- if [ "${PREFIX}" != "${LAST_PREFIX}" ]; then
- print_nl_if_started_printing
- prefixed_msg_no_nl "# ${PREFIX}"
- LAST_PREFIX="${PREFIX}"
+ local COMPRESSED_ITEM=
+ local PREFIX
+ local PATTERN
+ local REPLACEMENT
+ local I=0
+ local LINE
+ local OLD_IFS=${IFS}
+ local IFS
+ IFS=$(printf '\n\r')
+ for LINE in ${apt_get_digested_SEDS}; do
+ I=$((1 + "$I"))
+ if [ "$I" -eq 1 ]; then
+ PREFIX="${LINE}"
+ continue
+ elif [ "$I" -eq 2 ]; then
+ PATTERN="${LINE}"
+ continue
+ elif [ "$I" -eq 3 ]; then
+ REPLACEMENT="${LINE}"
+ continue
+ elif [ "$I" -eq 4 ]; then
+ I=0
+ fi
+ if printf '%s' "${APT_LINE}" | grep -E "${PATTERN}" > /dev/null; then
+ COMPRESSED_ITEM=$(printf '%s' "${APT_LINE}" | sed -E "s|${PATTERN}|${REPLACEMENT}|")
+ #if [ "${PREFIX}" = "BECOME_NEXT_PREFIX" ]; then
+ # LEADER_PREFIX="${COMPRESSED_ITEM}"
+ # COMPRESSED_ITEM=IGNORE
+ #elif [ "${PREFIX}" = "FOLLOW_PREFIX" ]; then
+ # PREFIX="${LEADER_PREFIX}"
+ #fi
+ break
+ fi
+ done
+ IFS=${OLD_IFS}
+ if [ "${COMPRESSED_ITEM}" = 'IGNORE' ]; then
+ continue
+ elif [ -z "${COMPRESSED_ITEM}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ prefixed_msg_no_nl "${APT_LINE}"
+ LAST_PREFIX=
+ else
+ if [ "${PREFIX}" != "${LAST_PREFIX}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ prefixed_msg_no_nl "# ${PREFIX}"
+ LAST_PREFIX="${PREFIX}"
+ fi
+ printf ' %s' "${COMPRESSED_ITEM}"
fi
- printf ' %s' "${COMPRESSED_ITEM}"
- fi
- STARTED_PRINTING=1
-done
-
-prefixed_msg_exit
+ OUR_NEWLINE='\n\r'
+ done
+
+ prefixed_msg_exit
}
--- /dev/null
+. lib/prefixed_msg.sh
+
+# NB: to avoid confusing the IFS handling, ensure none of the lines is empty –
+# even if ignored!
+apt_get_digested_SEDS=$(cat << "DELIMITER"
+Get:
+Get:[[:digit:]]+ (.*)
+\1
+--------------------
+Hit:
+Hit:[[:digit:]]+ (.*)
+\1
+--------------------
+.
+Generation complete.
+IGNORE
+--------------------
+.
+Preconfiguring packages \.\.\.
+IGNORE
+--------------------
+.
+Preparing to unpack [[:print:]]+ \.\.\.
+IGNORE
+--------------------
+.
+Unpacking [[:print:]]+ \([[:print:]]+\)( over \([[:print:]]+\))? \.\.\.
+IGNORE
+--------------------
+Adding diversion(s):
+Adding 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)'
+ \3:[\1 → \2]
+--------------------
+Created symlink(s):
+Created symlink '([[:print:]]+)' → '([[:print:]]+)'\.
+ [\1 → \2]
+--------------------
+Installing new version of config file(s):
+Installing new version of config file ([[:print:]]+) \.\.\.
+\1
+--------------------
+Processing triggers for:
+Processing triggers for ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Purging configuration files:
+Purging configuration files for ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Removing:
+Removing ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Removing diversion(s):
+Removing 'diversion of ([[:print:]]+) to ([[:print:]]+) by ([[:print:]]+)
+ \3:[\1 → \2]
+--------------------
+Removing obsolete conffile(s):
+Removing obsolete conffile ([[:print:]]+) \.\.\.
+\1
+--------------------
+Selecting previously unselected:
+Selecting previously unselected package ([[:print:]]+)\.
+\1
+--------------------
+Setting up:
+Setting up ([[:print:]]+) \([[:print:]]+\) \.\.\.
+\1
+--------------------
+Updating to current default:
+Updating ([[:print:]]+) to current default.
+\1
+--------------------
+disabled or static unit, so not starting:
+([[:print:]]+) is a disabled or a static unit, not starting it\.
+\1
+--------------------
+
+disabled or static unit not running, so not starting:
+([[:print:]]+) is a disabled or a static unit not running, not starting it\.
+\1
+--------------------
+dpkg warns: unable to delete old directories (not empty):
+dpkg: warning: unable to delete old directory '"'"'([[:print:]]+)'"'"': Directory not empty
+\1
+--------------------
+update-alternatives: providing in auto mode:
+update-alternatives: using ([[:print:]]+) to provide ([[:print:]]+) \(([[:print:]]+)\) in auto mode
+ [\1 → \2 (\3)]
+--------------------
+Warning: Problem unlinking files (Remove Caches/13: Permission denied):
+Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
+\1
+--------------------
+.
+\(Reading database \.\.\. .*
+IGNORE
+--------------------
+.
+WARNING: apt does not have a stable CLI interface.*
+IGNORE
+--------------------
+Warning: Problem unlinking files (Remove Caches/13: Permission denied):
+Warning: Problem unlinking the file ([[:print:]]+) - RemoveCaches \(13: Permission denied\)
+\1
+--------------------
+FOLLOW_PREFIX
+([[:print:]]+) depends on ([[:print:]]+)( \([>=]+ [[:print:]]+\))?\.
+[\2 → \1]
+--------------------
+BECOME_NEXT_PREFIX
+dpkg: ([[:print:]]+): dependency problems, but removing anyway as you requested:
+dpkg warns: removing \1 despite dependency problems:
+--------------------
+DELIMITER
+)
+
+apt_get_digested() {
+ prefixed_msg_init 'apt_get_digested'
+ local APT_GET_EXIT_CODE
+ local FINISH_LINE='apt_get_digested_FINISH_LINE'
+
+ run_apt() {
+ set +e
+ DEBIAN_FRONTEND=noninteractive apt -y "$@"
+ APT_GET_EXIT_CODE=$?
+ set -e
+ echo "${FINISH_LINE} ${APT_GET_EXIT_CODE}"
+ }
+
+ local OUR_NEWLINE='\r' # be \n\r except on 1st run, so no empty 1st line
+ local LAST_PREFIX=
+ local LEADER_PREFIX
+ local APT_LINE
+ run_apt "$@" 2>&1 | while read -r APT_LINE; do
+ APT_LINE=$(printf '%s' "${APT_LINE}" | tr -d '\r')
+ if [ -z "${APT_LINE}" ]; then
+ continue
+ else
+ local FIRST_FIELD
+ FIRST_FIELD=$(echo "${APT_LINE}" | cut -d' ' -f1)
+ if [ "${FIRST_FIELD}" = "${FINISH_LINE}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ local EXIT_CODE
+ EXIT_CODE=$(echo "${APT_LINE}" | cut -d' ' -f2)
+ if [ "${EXIT_CODE}" != "0" ]; then
+ false
+ fi
+ break
+ fi
+ fi
+ local COMPRESSED_ITEM=
+ local PREFIX
+ local PATTERN
+ local REPLACEMENT
+ local I=0
+ local LINE
+ local OLD_IFS=${IFS}
+ local IFS
+ IFS=$(printf '\n\r')
+ for LINE in ${apt_get_digested_SEDS}; do
+ I=$((1 + "$I"))
+ if [ "$I" -eq 1 ]; then
+ PREFIX="${LINE}"
+ continue
+ elif [ "$I" -eq 2 ]; then
+ PATTERN="${LINE}"
+ continue
+ elif [ "$I" -eq 3 ]; then
+ REPLACEMENT="${LINE}"
+ continue
+ elif [ "$I" -eq 4 ]; then
+ I=0
+ fi
+ if printf '%s' "${APT_LINE}" | grep -E "${PATTERN}" > /dev/null; then
+ COMPRESSED_ITEM=$(printf '%s' "${APT_LINE}" | sed -E "s|${PATTERN}|${REPLACEMENT}|")
+ #if [ "${PREFIX}" = "BECOME_NEXT_PREFIX" ]; then
+ # LEADER_PREFIX="${COMPRESSED_ITEM}"
+ # COMPRESSED_ITEM=IGNORE
+ #elif [ "${PREFIX}" = "FOLLOW_PREFIX" ]; then
+ # PREFIX="${LEADER_PREFIX}"
+ #fi
+ break
+ fi
+ done
+ IFS=${OLD_IFS}
+ if [ "${COMPRESSED_ITEM}" = 'IGNORE' ]; then
+ continue
+ elif [ -z "${COMPRESSED_ITEM}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ prefixed_msg_no_nl "${APT_LINE}"
+ LAST_PREFIX=
+ else
+ if [ "${PREFIX}" != "${LAST_PREFIX}" ]; then
+ printf '%s' "${OUR_NEWLINE}"
+ prefixed_msg_no_nl "# ${PREFIX}"
+ LAST_PREFIX="${PREFIX}"
+ fi
+ printf ' %s' "${COMPRESSED_ITEM}"
+ fi
+ OUR_NEWLINE='\n\r'
+ done
+
+ prefixed_msg_exit
+}