Skip to content

Commit

Permalink
Merge pull request #781 from sideeffect42/feature/type/__package_apt/…
Browse files Browse the repository at this point in the history
…mark-manual

__package_apt: Mark already installed packages as manual
  • Loading branch information
4nd3r committed Nov 14, 2021
2 parents 560374a + dbf604d commit d361665
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 34 deletions.
52 changes: 41 additions & 11 deletions cdist/conf/type/__package_apt/explorer/state
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh
#
# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
# 2021 Dennis Camera (cdist at dtnr.ch)
#
# This file is part of cdist.
#
Expand All @@ -21,19 +22,48 @@
# Retrieve the status of a package - parsed dpkg output
#

if [ -f "$__object/parameter/name" ]; then
name="$(cat "$__object/parameter/name")"
breify() {
# Convert arguments to a POSIX BRE-compatible form, i.e. escape special
# characters (incl. delimiter)
printf '%s' "$*" | sed -e 's/[].^$*\[]/\\&/g' -e 's:/:\\/:g'
}


if test -f "${__object}/parameter/name"
then
name=$(cat "${__object:?}/parameter/name")
else
name="$__object_id"
name=${__object_id:?}
fi

# Except dpkg failing, if package is not known / installed
packages="$(apt-cache showpkg "$name" | sed -e "1,/Reverse Provides:/d" | cut -d ' ' -f 1) $name"
for p in $packages; do
if dpkg -s "$p" 2>/dev/null | grep --quiet "^Status: install ok installed$" ; then
version=$(dpkg -s "$p" 2>/dev/null | grep "^Version:" | cut -d ' ' -f 2)
echo "present $p $version"
exit 0
fi
state_dir=$(apt-config dump | sed -n -e 's/^Dir::State *"\(.*\)";$/\/\1/p')
extended_states_file=${state_dir%/}/extended_states

# if $name is e.g. editor, check if any editor is installed instead
rprovides=$(apt-cache showpkg "${name}" | sed -e '1,/^Reverse Provides:/d' -e 's/ .*$//')

for pkg in ${name} ${rprovides}
do
if dpkg -s "${pkg}" 2>/dev/null | grep -qxF 'Status: install ok installed'
then
version=$(dpkg -s "${pkg}" 2>/dev/null | sed -n -e 's/^Version: *//p')

if test -f "${extended_states_file}"
then
# On Debian >= 5 check if the package is auto installed

# NOTE: instead of using apt-mark(8) parse the extended_states file
# directly. apt-mark is sloow and didn't have a stable
# interface in older Debian versions.
is_auto=$(sed -n -e '/^Package: '$(breify "${name}")'$/,/^$/!d' -e 's/^Auto-Installed: *//p' "${extended_states_file}")
fi

# NOTE: older versions don't have apt-mark -> all packages are manual
auto_word=$(test $((is_auto)) -ne 0 && echo auto || echo manual)

echo "present ${auto_word} ${pkg} ${version}"
exit 0
fi
done

echo absent
55 changes: 32 additions & 23 deletions cdist/conf/type/__package_apt/gencode-remote
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/bin/sh -e
#
# 2011-2013 Nico Schottelius (nico-cdist at schottelius.org)
# 2021 Dennis Camera (cdist at dtnr.ch)
#
# This file is part of cdist.
#
Expand Down Expand Up @@ -56,31 +57,36 @@ else
fi


# FIXME: use grep directly, state is a list, not a line!
state_is="$(cat "$__object/explorer/state")"
case "$state_is" in
present*)
name="$(echo "$state_is" | cut -d ' ' -f 2)"
version_is="$(echo "$state_is" | cut -d ' ' -f 3)"
state_is="present"
;;
*)
version_is=""
;;
esac

if [ "$state_is" = "$state_should" ]; then
if [ -z "$version" ] || [ "$version" = "$version_is" ]; then
exit 0;
fi
fi
read -r state_is auto_state name version_is <"${__object:?}/explorer/state"

# Hint if we need to avoid questions at some point:
# DEBIAN_PRIORITY=critical can reduce the number of questions
aptget="DEBIAN_FRONTEND=noninteractive apt-get --quiet --yes -o Dpkg::Options::=\"--force-confdef\" -o Dpkg::Options::=\"--force-confold\""

case "$state_should" in
case ${state_should}
in
present)
if test "${state_is}" = 'present'
then
if test -z "${version}" || test "${version}" = "${version_is}"
then
if test "${auto_state}" = 'auto'
then
# package is installed, but marked auto -> mark it manual so
# that it doesn't get removed by apt-get autoremove.

echo 'head -n1 "$(command -v apt-mark)" | grep -qvF python \'
# new implementation (Debian >= 7)
echo "&& apt-mark manual '${name}' \\"
# old Python implementation (Debian 5-7)
echo "|| apt-mark unmarkauto '${name}'"
# NOTE: older versions don't need to be supported because
# they will always be manual
fi
exit 0
fi
fi

# There are special arguments to apt(8) to prevent aborts if apt woudn't been
# updated after the 19th April 2021 till the bullseye release. The additional
# arguments acknoledge the happend suite change (the apt(8) update does the
Expand All @@ -104,12 +110,15 @@ EOF
if [ -n "$version" ]; then
name="${name}=${version}"
fi
echo "$aptget $recommendsparam install $target_release '$name'"
echo "installed" >> "$__messages_out"

echo "${aptget} ${recommendsparam} install ${target_release} '${name}'"
echo 'installed' >>"${__messages_out:?}"
;;
absent)
echo "$aptget remove $purgeparam '$name'"
echo "removed" >> "$__messages_out"
test "${state_is}" != 'absent' || exit 0

echo "${aptget} remove ${purgeparam} '${name}'"
echo 'removed' >>"${__messages_out:?}"
;;
*)
echo "Unknown state: $state_should" >&2
Expand Down

0 comments on commit d361665

Please sign in to comment.