From 2e468963f264e40379425a83048000965320a78e Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Sun, 21 Oct 2018 08:11:50 +0000 Subject: [PATCH] add tests and code for config file updates --- t/update.t | 104 +++++++++++++++++++++++++++++++++++++++++++++++ zpm-syncfs.c | 113 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 194 insertions(+), 23 deletions(-) create mode 100755 t/update.t diff --git a/t/update.t b/t/update.t new file mode 100755 index 0000000..8828749 --- /dev/null +++ b/t/update.t @@ -0,0 +1,104 @@ +#!/bin/sh + +# vim: syn=sh + +# test addfile + +. tap.sh + +plan 32 + +owner=$(id -un) +group=$(id -gn) + +newpkg() { + pkgid=$1 + tryrun zpm init $pkgid.zpm + if [ $? -eq 0 ]; then + tryrun zpm newpackage -f $pkgid.zpm $pkgid + if [ $? -eq 0 ]; then + shift + tryrun zpm add -u $owner -g $group -f $pkgid.zpm $pkgid "$@" + return $? + else + skip 1 not adding files init failed + return 1 + fi + else + skip 2 "unable to init $pkgid.zpm" + fi + return 0 +} + +oktest() { + test $1 $2 + okexit test $1 $2 +} + +oknottest() { + test $1 $2 + failsok test $1 $2 fails +} + +require rm -rf tmp +require mkdir tmp +cd tmp || bailout + +# set up a new package + +pkgid=itest-1.0-1 +newpkg $pkgid /bin/true +okexit setup package $pkgid +PF=$pkgid.zpm +require mkdir etc +echo foo > etc/conf +zpm add -f $PF -C -c $pkgid etc/conf +okexit added foo conf +isconf=$(zpm pkgfile -f $PF $pkgid /etc/conf configuration) +okstreq $isconf 1 etc/conf 1.0 is config file + +pkgid=itest-2.0-1 +newpkg $pkgid /bin/true +okexit setup package $pkgid +PF=$pkgid.zpm +echo bar > etc/conf +zpm add -f $PF -C -c $pkgid etc/conf +okexit added bar conf +isconf=$(zpm pkgfile -f $PF $pkgid /etc/conf configuration) +okstreq $isconf 1 etc/conf 2.0 is config file + +pkgid=itest-3.0-1 +newpkg $pkgid /bin/true +okexit setup package $pkgid +PF=$pkgid.zpm +echo baz > etc/conf +zpm add -f $PF -C -c $pkgid etc/conf +okexit added baz conf +isconf=$(zpm pkgfile -f $PF $pkgid /etc/conf configuration) +okstreq $isconf 1 etc/conf 3.0 is config file + +require rm etc/conf + +require mkdir var +require mkdir var/lib +require mkdir var/lib/zpm + +require zpm install -R. -f itest-1.0-1.zpm itest-1.0-1 + +test -f etc/conf +okexit etc/conf installed via zpm-install +conf=$(cat etc/conf) +okstreq "$conf" foo conf is foo + +# update unchanged config file +require zpm install -R. -f itest-2.0-1.zpm itest-2.0-1 +conf=$(cat etc/conf) +okstreq "$conf" bar new conf is bar + +echo quux > etc/conf + +require zpm install -R. -f itest-3.0-1.zpm itest-3.0-1 +conf=$(cat etc/conf) +okstreq "$conf" quux kept conf as quux + +zpm note -f var/lib/zpm/local.db -l | diagstdin diff --git a/zpm-syncfs.c b/zpm-syncfs.c index 94297a0..ecc66c8 100644 --- a/zpm-syncfs.c +++ b/zpm-syncfs.c @@ -709,12 +709,94 @@ static int install(struct config *conf, struct nitem *item, unsigned int flags) return success; } +/* + * + */ +static int adjust_for_config(struct config *conf, struct nitem *n, unsigned int + diffs) { +#if 0 + if (!n->oldwasconf) { + return 0; + } +#endif + /* TODO what if old was a directory? */ + if (!n->configuration) { + /* replacing conf with non-conf */ + /* absorb file, mark todo */ + char hash[ZPM_HASH_STRLEN+1]; + if (zpm_import(conf->log, n->dest, 0, hash)) { + zpm_note_add(conf->log, n->pkglist, n->dest, hash, + "replaced config file with non-config. zpm-cat %.8s", hash); + } else { + fprintf(stderr, "unable to import existing config file %s\n", n->dest); + return 1; + } + return 0; + } + + int sametype = (!(diffs & D_TYPE)); + int isdir = (diffs & D_ISDIR); + int eisdir = (diffs & D_EISDIR); + + /* both old and new are config files */ + if (isdir && sametype) { + /* both config directories, can only be changing + * metadata, so no adjustment needed + */ + return 0; + } + + if (isdir) { + char hash[ZPM_HASH_STRLEN+1]; + + /* replacing old file with new directory */ + /* absorb, make note */ + if (zpm_import(conf->log, n->dest, 0, hash)) { + zpm_note_add(conf->log, n->pkglist, n->dest, hash, + "replaced config file with config directory. zpm-cat %.8s", hash); + } else { + fprintf(stderr, "unable to import existing config file %s\n", n->dest); + return -1; + } + return 0; + } + + if (eisdir) { + /* replacing old conf directory with a conf file. + * nothing needs to be done, if the directory + * is empty, it's ok to remove. if it's not empty, + * the install will fail + */ + return 0; + } + + /* replacing old file with new file */ + /* new is same as on disk */ + if (!(diffs & D_HASH)) { + return 0; + } + + /* new is different than on disk, but on disk is same as old */ + if (!(diffs & D_OHASH)) { + /* ok to do the update, since same as default */ + fprintf(stderr, "updating default config %s\n", n->dest); + return 0; + } + + /* new is different than on disk, and disk different than old */ + /* log */ + zpm_note_add(conf->log, n->pkglist, n->dest, n->hash, + "default config file update. zpm-cat %.8s", n->hash); + /* TODO check for note error */ + return 1; + +} + static int install_files(void *f, int ncols, char **vals, char **cols) { struct config *conf = f; struct nitem nitem; struct stat existing; int update = 0; - char dest[4096]; /* TODO put the result row in a hash table. May not actually * be faster @@ -776,28 +858,12 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { return install(conf, &nitem, 3); } - if (nitem.configuration) { - /* ohash == nhash, not an update */ - /* fhash == ohash, just update */ - /* fhash != ohash, install as dest.zpmnew, warn */ - /* TODO handle replacing config file - * with config directory */ - /* We don't have the information as to which - * package this is a config file for, so - * we'll need to look it up. - */ - if (diffs & D_OHASH) { - zpm_note_add(conf->log, nitem.pkglist, - nitem.path, nitem.hash, - "default config file update installed as %s.zpmnew", nitem.dest); - - if (strlen(nitem.dest) > sizeof dest - 8) { - return seterror(conf,"config file path too long for install as %s.zpmnew", nitem.dest); - } - fprintf(stderr, "installing as .zpmnew\n"); - sprintf(dest, "%s.zpmnew", nitem.dest); - nitem.dest = dest; - } + switch (adjust_for_config(conf, &nitem, diffs)) { + case -1: return conf->errabort; break; + case 1: + fprintf(stderr, "skipping changed default config file: %s\n", nitem.dest); + return 0; break; + default: break; } /* file exists in filesystem */ @@ -861,6 +927,7 @@ static int install_files(void *f, int ncols, char **vals, char **cols) { return install(conf, &nitem, 7); } /* error, should not be possible, assert(0)? */ + fprintf(stderr,"impossible state: %s:%d\n", __func__, __LINE__); } if (installing) { -- 2.40.0