[pacman-dev] [PATCH] makepkg: improve removal of installed dependencies
Cedric Staniewski
cedric at gmx.ca
Mon Dec 7 09:54:20 EST 2009
On 12/03/2009 03:33 PM, Allan McRae wrote:
> Compare a list of packages on the system before and after dependency resolution
> in order to get a complete list of packages to remove. This allows makepkg to
> remove packages installed due to provides.
>
> Bail in cases where packages that were on the system originally have been
> removed as there is a risk of breaking the system when removing the new
> packages
>
> Fixes FS#15144
>
> Signed-off-by: Allan McRae <allan at archlinux.org>
> ---
I have not tested the patch yet, so just some comments on the code for now.
>
> This moves the generation of the installed package list to directly after
> the installation of deps to prevent issues if the user installs packages
> while the build is occurring:
> http://bugs.archlinux.org/task/15144#comment53938
>
> Rebased on Cedric's run_pacman and $PACMAN patches.
>
> doc/makepkg.8.txt | 6 +++---
> scripts/makepkg.sh.in | 39 +++++++++++++++++++++------------------
> 2 files changed, 24 insertions(+), 21 deletions(-)
>
> diff --git a/doc/makepkg.8.txt b/doc/makepkg.8.txt
> index ad27bca..168b369 100644
> --- a/doc/makepkg.8.txt
> +++ b/doc/makepkg.8.txt
> @@ -166,9 +166,9 @@ Environment Variables
> ---------------------
> *PACMAN*::
> The command that will be used to check for missing dependencies and to
> - install and remove packages. Pacman's -U, -T, -S and -Rns operations
> - must be supported by this command. If the variable is not set or
> - empty, makepkg will fall back to `pacman'.
> + install and remove packages. Pacman's -Qq, -Rns, -S, -T, and -U
> + operations must be supported by this command. If the variable is not
> + set or empty, makepkg will fall back to `pacman'.
>
>
> Additional Features
> diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
> index c730150..5743ea4 100644
> --- a/scripts/makepkg.sh.in
> +++ b/scripts/makepkg.sh.in
> @@ -27,8 +27,10 @@
>
> # makepkg uses quite a few external programs during its execution. You
> # need to have at least the following installed for makepkg to function:
> -# bsdtar (libarchive), bzip2, coreutils, fakeroot, find (findutils),
> -# getopt (util-linux), gettext, grep, gzip, openssl, sed, tput (ncurses)
> +# bsdtar (libarchive), bzip2, coreutils, diff (diffutils), fakeroot,
> +# find (findutils), getopt (util-linux), gettext, grep, gzip, openssl,
> +# sed, tput (ncurses)
> +
>
> # gettext initialization
> export TEXTDOMAIN='pacman'
> @@ -343,7 +345,7 @@ download_file() {
>
> run_pacman() {
> local ret=0
> - if (( ! ASROOT )) && [[ $1 != "-T" ]] && sudo -l $PACMAN &>/dev/null; then
> + if (( ! ASROOT )) && [[ $1 != "-T" && $1 != "-Qq" ]] && sudo -l $PACMAN &>/dev/null; then
> sudo $PACMAN $PACMAN_OPTS "$@" || ret=$?
> else
> $PACMAN $PACMAN_OPTS "$@" || ret=$?
> @@ -398,7 +400,6 @@ handle_deps() {
> }
>
> resolve_deps() {
> - # $pkgdeps is a GLOBAL variable, used by remove_deps()
> local R_DEPS_SATISFIED=0
> local R_DEPS_MISSING=1
>
> @@ -408,7 +409,6 @@ resolve_deps() {
> fi
>
> if handle_deps $deplist; then
> - pkgdeps="$pkgdeps $deplist"
> # check deps again to make sure they were resolved
> deplist="$(check_deps $*)"
> [[ -z $deplist ]] && return $R_DEPS_SATISFIED
> @@ -425,23 +425,25 @@ resolve_deps() {
> return $R_DEPS_MISSING
> }
>
> -# fix flyspray bug #5923
> remove_deps() {
> - # $pkgdeps is a GLOBAL variable, set by resolve_deps()
> (( ! RMDEPS )) && return
> - [[ -z $pkgdeps ]] && return
>
> - local dep depstrip deplist
> - deplist=""
> - for dep in $pkgdeps; do
> - depstrip="${dep%%[<=>]*}"
> - deplist="$deplist $depstrip"
> - done
> + # check for packages removed during dependency install (e.g. due to conflicts)
> + # removing all installed packages is risky in this case
> + if (( $(diff <(printf "%s\n" "${original_pkglist[@]}") \
> + <(printf "%s\n" "${current_pkglist[@]}") | grep "<" | wc -l) > 0 )); then
> + warning "$(gettext "Failed to remove installed dependencies.")"
> + return 0
> + fi
>
You could use comm here. The advantage would be that it do not pull in
a new dependency as it is in coreutils too and you do not need grep to
get the unique lines.
if [[ -n $(printf "%s\n" ${original_pkglist[@]} \
| comm -23 - <(printf "%s\n" ${current_pkglist[@]})) ]]
Note the code above is untested.
> - msg "Removing installed dependencies..."
> + local deplist=($(diff <(printf "%s\n" "${original_pkglist[@]}") \
> + <(printf "%s\n" "${current_pkglist[@]}") | grep ">"))
> + deplist=(${deplist[@]#>})
local deplist=($(printf "%s\n" ${original_pkglist[@]} \
| comm -13 - <(printf "%s\n" ${current_pkglist[@]})))
> + [ ${#deplist[@]} -eq 0 ] && return
(( ${#deplist[@]} == 0 )) :)
>
> + msg "Removing installed dependencies..."
> # exit cleanly on failure to remove deps as package has been built successfully
> - if ! run_pacman -Rns $deplist; then
> + if ! run_pacman -Rn ${deplist[@]}; then
> warning "$(gettext "Failed to remove installed dependencies.")"
> return 0
> fi
> @@ -1874,14 +1876,13 @@ if (( SOURCEONLY )); then
> exit 0
> fi
>
> -# fix flyspray bug #5973
> if (( NODEPS || NOBUILD || REPKG )); then
> # no warning message needed for nobuild, repkg
> if (( NODEPS )); then
> warning "$(gettext "Skipping dependency checks.")"
> fi
> elif [ $(type -p "${PACMAN%% *}") ]; then
> - unset pkgdeps # Set by resolve_deps() and used by remove_deps()
> + original_pkglist=($(run_pacman -Qq)) # required by remove_deps
Could be skipped if RMDEPS == 0 but I do not know how fast / slow this
pacman operation actually is.
> deperr=0
>
> msg "$(gettext "Checking Runtime Dependencies...")"
> @@ -1890,6 +1891,8 @@ elif [ $(type -p "${PACMAN%% *}") ]; then
> msg "$(gettext "Checking Buildtime Dependencies...")"
> resolve_deps ${makedepends[@]} || deperr=1
>
> + current_pkglist=($(run_pacman -Qq)) # required by remove_deps
> +
Same as above.
> if (( deperr )); then
> error "$(gettext "Could not resolve all dependencies.")"
> exit 1
More information about the pacman-dev
mailing list