Modern Update System

David Woodhouse dwmw2 at infradead.org
Tue Nov 29 15:30:51 UTC 2005


On Mon, 2005-11-28 at 19:13 -0500, Benjy Grogan wrote:
> Is there any work being done for a modern update system that would
> only download what is needed instead of an entirely new rpm? 

One trick I've had moderate success with is to extract the RPM payload
(on the remote end) into a cpio file. Then create a cpio file locally
using the contents of the old package, and rsync the new cpio using the
old cpio as seed. Once that's done, recompress (using 'minigzip -9' so
that it precisely matches what RPM does) and then use that as seed for
rsyncing the RPM itself, just to get the header.

#!/bin/sh

export RSYNC_RSH=`which ssh`
REMOTETMPDIR=/tmp/getrpm-`hostname`-$$
LOCALTMPDIR=/tmp/getrpm-$$

REMOTEHOST=$1

if ! minigzip < /dev/null > /dev/null; then
    echo "minigzip not found. We need it to match rpm's compression"
    echo "Get the rpm source, build its minigzip using its zlib."
    echo "Stick it on your PATH somewhere"
    exit 1
fi

if [ -z $REMOTEHOST ]; then
    echo "Usage: $0 <remotehost> <rpm> [<rpm> ...]"
    exit 1
fi

if ! mkdir $LOCALTMPDIR; then
    echo "Cannot create temp directory $LOCALTMPDIR"
    exit 1
fi

if ! pushd $LOCALTMPDIR > /dev/null ; then
    echo "Change to local temporary directory failed";
    exit 1
fi

mkdir rpms

if ! ssh $REMOTEHOST mkdir $REMOTETMPDIR; then
    echo "Failed to create temp directory $REMOTETMPDIR on $REMOTEHOST"
    rmdir $LOCALTMPDIR
    exit 1
fi


shift

for PACKAGE in $* ; do
    if ! ssh $REMOTEHOST rpm -qp --queryformat="%{NAME}" $PACKAGE > packagename; then
        echo "Package listing for $REMOTEHOST:$PACKAGE failed"
        continue;
    fi
    PACKAGENAME=`cat packagename`
    if [ -z $PACKAGENAME ]; then
        echo "Error: No package name although command succeeded"
        continue;
    fi
    if rpm -ql $PACKAGENAME > files 2>/dev/null; then
        echo "Package $PACKAGENAME is currently installed. Using existing files as seed"
        cpio -Hnewc -o < files > $PACKAGENAME.cpio 2>/dev/null

        if ! ssh $REMOTEHOST rpm2cpio $PACKAGE \> $REMOTETMPDIR/$PACKAGENAME.cpio; then
            echo "Error: rpm2cpio of $REMOTEHOST:$PACKAGE failed"
            continue;
        fi

        if ! rsync -vz --progress $REMOTEHOST:$REMOTETMPDIR/$PACKAGENAME.cpio $PACKAGENAME.cpio; then
            echo "rsync of $PACKAGENAME.cpio failed"
            rm $PACKAGENAME.cpio
            continue
        fi
        ssh $REMOTEHOST rm $REMOTETMPDIR/$PACKAGENAME.cpio
        echo -n "Compressing $PACKAGENAME.cpio..."
        minigzip -9 $PACKAGENAME.cpio
        echo "done."
        mv $PACKAGENAME.cpio.gz `basename $PACKAGE`
        if ! rsync -vz --progress $REMOTEHOST:$PACKAGE `basename $PACKAGE` ; then
            echo "rsync failed"
            rm `basename $PACKAGE`
            continue
        fi
        mv `basename $PACKAGE` rpms
    else
        echo "Package $PACKAGENAME not installed. Copying whole package"
        scp $REMOTEHOST:$PACKAGE rpms
    fi
done

rm -f packagename *.cpio files

ssh $REMOTEHOST "rm -f $REMOTETMPDIR/*.cpio ; rmdir $REMOTETMPDIR"
popd
mv $LOCALTMPDIR/rpms/*.rpm .
rmdir $LOCALTMPDIR/rpm

-- 
dwmw2





More information about the fedora-devel-list mailing list