Re: multiple installed package versions

Lars Ellenberg <[email protected]> Wed, 27 Oct 2004 01:17:15 +0200
Newsgroups gmane.linux.suse.fou4s.devel
Message-ID <[email protected]>
> > I've found a bug in fou4s (thanks to Klaus Lehmann for reporting :) and it 
> > doesn't like duplicate entries in the RPM database (causing wrong attempts 
> > to update packages that already have the right version). A few other 
> > people have reported this and I couldn't find the solution before.
> 
> If you give me an example, I'll try to find some workaround.

hm. you did not.

but anyways, how about going back to my very initial hack to find the
most recent version of things?


use this to generate your rpm cache.
I think the output will be identical to your current code,
but in case there is more than one package with a given name,
this filters older versions out.
so only the most recent will survive in the output.

since you already have the "SuSE-release" as external helper,
you could use this as external helper, too.
Or replcae updateRpmCache with it, I don't mind.

also attached, a "fou4s-cleanup", with a slightly different variant of
the same technique, to get rid of all the "outdated update" packages
that pile up after some time.

it does a find over all server directories, and suggests to remove
files corresponding to packages where a newer package file is around.

as you can see, currently 
  BASE_DIR=/var/cache/fou4s/packages
  ARCH=i386
  VER=9.0
are hardcoded there, but hey...
"works for me" :)

thanks,

	lge

-- 
_______________________________________________
Fou4s-devel mailing list
[email protected]
https://mail.gaugusch.at/mailman/listinfo/fou4s-devel
fou4s-rpmcache (text/plain, 1.8 KB)
#!/bin/bash

sort_by_version_release()
# in case there is more than one package with a given name,
# this filters older versions out
# (as long as version and release are well-behaved)
{
	# input is three lines per package:
	# name
	# version
	# -release
	sed -ne '
		1~4h ; # hold it
		; # insert space separators around version numbers
		2~4{s/\([0-9]\+\)/ \1 /g;H;}
		; # insert space separators around release numbers
		; # in case there are non-digits in the release
		3~4{s/\([0-9]\+\)/ \1 /g;H;}
		; # and print it
		4~4{H;x;s/'$'\\\n''//g;p;}' |
	# the even fields are numeric parts of the version/release
	# the odd  fields are non numeric, but should be used for
	# sorting, too, since it could be 2.05b, 0.9.7c etc... 
	# non existing fields are ignored, I truncate at 25 ;)
	  sort -s \
		-k2,2nr -k3,3r -k4,4nr -k5,5r -k6,6nr -k7,7r -k8,8nr -k9,9r \
		-k10,10nr -k11,11r -k12,12nr -k13,13r -k14,14nr -k15,15r \
		-k16,16nr -k17,17r -k18,18nr -k19,19r -k20,20nr -k21,21r -k22,22nr \
		-k23,23r -k24,24nr -k25,25r |
	  sort -t= -s -u -k 1,1 |
	  sed 's/ //g;s,/, ,g'
	  # return non-zero if any of the pipe commands exited with non-zero
	  # note that this MUST be [[ ]] -- not [ ], neither test !
	  [[ -z ${PIPESTATUS[*]//0} ]]
}

make_bash_variable_assignment()
{
	sed 'h;              # remember line
	s/^.*=/=/;           # cut
	x;                   # exchange
	s/=.*$//;            # cut
	s/[^A-Za-z0-9_]/_/g; # valid identifier
	s/^/pkg_/;           # prefix
	G;                   # append again
	s/'$'\\\n''//;       # newer sed would say s/\n//;'
}

rpm -qa --qf "%{NAME}='\n%{VERSION}\n-%{RELEASE}\n/%{BUILDTIME}/%{ARCH}/%{SIZE}'\n" |
sort_by_version_release | make_bash_variable_assignment

# return non-zero if any of the pipe commands exited with non-zero
# note that this MUST be [[ ]] -- not [ ], neither test !
[[ -z ${PIPESTATUS[*]//0} ]]
fou4s-cleanup (text/plain, 2.5 KB)
#!/bin/bash
BASE_DIR=/var/cache/fou4s/packages
ARCH=i386
VER=9.0

cd $BASE_DIR
CLEAN_DIRS=`find ./*/$ARCH/update/$VER/rpm/* -type d -maxdepth 0`

#
# helper functions
#
sort_by_version_release() {
	# note that I _expect_ release to be numeric...
	# so if you have releases that contain alphas, this may not work.
	# anything/  name-   version-      release         extension
	sed -ne '
	s,^\(.*\)/\([^/]*-\)\([^-]\+-\)\([0-9]\+\)\(\.[^-]*\)$,\1|\2|\
\3\
 |\4|\5,p' \
	| sed -ne '
		1~3h ; # hold it
		; # insert space separators around version numbers
		2~3{s/\([0-9]\+\)/ \1 /g;H;}
		; # and print it
		3~3{H;x;s/'$'\\\n''//g;p;}' \
	| sort -t "|" -k 4,4nr |
	# the even fields are numeric parts of the version/release
	# the odd  fields are non numeric, but should be used for
	# sorting, too, since it could be 2.05b, 0.9.7c etc... 
	# non existing fields are ignored, I truncate at 25 ;)
	  sort -t " " -s \
		-k2,2nr -k3,3r -k4,4nr -k5,5r -k6,6nr -k7,7r -k8,8nr -k9,9r \
		-k10,10nr -k11,11r -k12,12nr -k13,13r -k14,14nr -k15,15r \
		-k16,16nr -k17,17r -k18,18nr -k19,19r -k20,20nr -k21,21r -k22,22nr \
		-k23,23r -k24,24nr -k25,25r \
	| sort -t "|" -s -k 2,2 \
	| sed 's,|,/,; s/[ |]//g;'
}

split_dir_name_version_extension() {
  sed -ne 's,^\(.*\)/\([^/]*\)-\([^-]*\)-\([^-.]*\).\(.*\)$,\1\t\2\t\3\t\4\t\5,p'
}

list_and_delete_outdated()
{
  latext_dir='';
  latest_name='';
  latest_ext='';
  latest_full='';
  current_full='';
  did_header=false
  while read dir name version release ext ; do
	current_full=$name-$version-$release.$ext
	if [[ $name == $latest_name && $ext == $latest_ext ]]; then
		# some paranoia checks
		if [[ $dir/$current_full -nt $latest_dir/$latest_full ]] ; then
			echo " -- "
			echo "don't know what to do:"
			ls -l $dir/$current_full $latest_dir/$latest_full
			echo " -- "
		# maybe double check version and release, and ...
		else
			if ! $did_header ; then
				echo "---------------"
				echo -e "latest is: $latest_full\t[$latest_dir]"
				did_header=true
			fi
			# once you are convinced that this doe work,
			# just remove unconditionally...
			# rm "$dir/$current_full"
			echo -e "delete   : $current_full\t[$dir] ?"
			# confirmation from stderr, since stdin is the file names ...
			rm -i "$dir/$current_full" <&2
		fi
	else
		did_header=false
		latest_dir=$dir
		latest_name=$name
		latest_ext=$ext
		latest_full=$current_full
	fi
  done
}

#
# MAIN program
#

find $CLEAN_DIRS -type f -name "*.rpm" |
               sort_by_version_release |
      split_dir_name_version_extension |
              list_and_delete_outdated