commit:     246dcdb800726022756d13a2798f1663727136f6
Author:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
AuthorDate: Sun Feb 22 09:05:28 2015 +0000
Commit:     Mike Frysinger <vapier <AT> gentoo <DOT> org>
CommitDate: Sun Feb 22 09:07:55 2015 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/portage-utils.git;a=commit;h=246dcdb8

qmerge: switch to qvdb to properly process user args

This way we support atoms on the command line correctly e.g. python:2.7.

---
 main.c              |  18 -----
 qmerge.c            | 218 ++++++++++++++++++++++------------------------------
 tests/qmerge/dotest |   4 +-
 3 files changed, 93 insertions(+), 147 deletions(-)

diff --git a/main.c b/main.c
index 436387d..c06cf49 100644
--- a/main.c
+++ b/main.c
@@ -1240,24 +1240,6 @@ char *atom_to_pvr(depend_atom *atom) {
        return (atom->PR_int == 0 ? atom->P : atom->PVR );
 }
 
-/* TODO: Delete this in favor of libq/vdb.c API. */
-static char *grab_vdb_item(const char *item, const char *CATEGORY, const char 
*PF)
-{
-       static char *buf;
-       static size_t buf_len;
-
-       if (buf == NULL) {
-               buf_len = _Q_PATH_MAX;
-               buf = xmalloc(buf_len);
-       }
-
-       snprintf(buf, buf_len, "%s%s/%s/%s/%s", portroot, portvdb, CATEGORY, 
PF, item);
-       eat_file(buf, &buf, &buf_len);
-       rmspace(buf);
-
-       return buf;
-}
-
 /* TODO: Merge this into libq/vdb.c somehow. */
 _q_static queue *get_vdb_atoms(int fullcpv)
 {

diff --git a/qmerge.c b/qmerge.c
index 980a5b6..e125258 100644
--- a/qmerge.c
+++ b/qmerge.c
@@ -106,7 +106,7 @@ typedef struct llist_char_t llist_char;
 
 _q_static void pkg_fetch(int, const depend_atom *, const struct pkg_t *);
 _q_static void pkg_merge(int, const depend_atom *, const struct pkg_t *);
-_q_static int pkg_unmerge(const char *, const char *, queue *);
+_q_static int pkg_unmerge(q_vdb_pkg_ctx *, queue *);
 _q_static struct pkg_t *grab_binpkg_info(const char *);
 _q_static char *find_binpkg(const char *);
 
@@ -470,9 +470,9 @@ pkg_run_func_at(int dirfd, const char *vdb_path, const char 
*phases, const char
                "MERGE_TYPE=binary\n"
                "ROOT='%4$s'\n"
                "EROOT=\"${EPREFIX%%/}/${ROOT#/}\"\n"
-               "D='%5$s'\n"
+               "D=\"%5$s\"\n"
                "ED=\"${EPREFIX%%/}/${D#/}\"\n"
-               "T='%6$s'\n"
+               "T=\"%6$s\"\n"
                /* Finally run the func */
                "%7$s%2$s\n"
                /* Ignore func return values (not exit values) */
@@ -758,6 +758,8 @@ _q_static void
 pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
 {
        queue *objs;
+       q_vdb_ctx *vdb_ctx;
+       q_vdb_cat_ctx *cat_ctx;
        FILE *fp, *contents;
        static char *phases;
        static size_t phases_len;
@@ -865,6 +867,20 @@ pkg_merge(int level, const depend_atom *atom, const struct 
pkg_t *pkg)
        if (pretend)
                return;
 
+       /* Get a handle on the main vdb repo */
+       vdb_ctx = q_vdb_open();
+       if (!vdb_ctx)
+               return;
+       cat_ctx = q_vdb_open_cat(vdb_ctx, pkg->CATEGORY);
+       if (!cat_ctx) {
+               if (errno != ENOENT)
+                       return;
+               mkdirat(vdb_ctx->vdb_fd, pkg->CATEGORY, 0755);
+               cat_ctx = q_vdb_open_cat(vdb_ctx, pkg->CATEGORY);
+               if (!cat_ctx)
+                       return;
+       }
+
        /* Set up our temp dir to unpack this stuff */
        xasprintf(&p, "%s/qmerge/%s/%s", port_tmpdir, pkg->CATEGORY, pkg->PF);
        mkdir_p(p, 0755);
@@ -942,48 +958,40 @@ pkg_merge(int level, const depend_atom *atom, const 
struct pkg_t *pkg)
 
        /* FIXME */ /* move unmerging to around here ? */
        /* check for an already installed pkg */
-       snprintf(buf, sizeof(buf), "%s/%s", atom->CATEGORY, pkg->PF);
 
        /* Unmerge any stray pieces from the older version which we didn't 
replace */
-       p = best_version(atom->CATEGORY, atom->PN);
-       if (*p) {
-               /* XXX: Should see about merging with unmerge_packages() */
-               makeargv(p, &ARGC, &ARGV);
-               for (i = 1; i < ARGC; i++) {
-                       int ret, u;
-                       const char *pn;
-                       char *pf;
-                       char *slot = NULL;
-
-                       pf = ARGV[i];
-                       switch ((ret = atom_compare_str(buf, pf))) {
-                               case ERROR:
-                               case NOT_EQUAL:
-                                       continue;
-                               case NEWER:
-                               case OLDER:
-                               case EQUAL:
-                                       u = 1;
-                                       pn = basename(pf);
-                                       slot = grab_vdb_item("SLOT", 
atom->CATEGORY, pn);
-                                       if (pkg->SLOT[0] && slot) {
-                                               if (strcmp(pkg->SLOT, slot) != 
0)
-                                                       u = 0;
-                                       }
-                                       /* We need to really set this unmerge 
pending after we look at contents of the new pkg */
-                                       if (u)
-                                               break;
-                                       continue;
-                               default:
-                                       warn("no idea how we reached here.");
-                                       continue;
-                       }
+       /* XXX: Should see about merging with unmerge_packages() */
+       while (1) {
+               int ret;
+               q_vdb_pkg_ctx *pkg_ctx;
+               depend_atom *old_atom;
+
+               pkg_ctx = q_vdb_next_pkg(cat_ctx);
+               if (!pkg_ctx)
+                       break;
+
+               old_atom = atom_explode(pkg_ctx->name);
+               /* This cast sucks, but we know for now the field isn't 
modified */
+               old_atom->CATEGORY = (char *)cat_ctx->name;
+               ret = atom_compare(atom, old_atom);
+               atom_implode(old_atom);
+               switch (ret) {
+                       case NEWER:
+                       case OLDER:
+                       case EQUAL:
+                               /* We need to really set this unmerge pending 
after we look at contents of the new pkg */
+                               break;
+                       default:
+                               warn("no idea how we reached here.");
+                       case ERROR:
+                       case NOT_EQUAL:
+                               continue;
+               }
 
-                       qprintf("%s+++%s %s %s %s\n", GREEN, NORM, buf, 
booga[ret], pf);
+               qprintf("%s+++%s %s/%s %s %s/%s\n", GREEN, NORM, 
atom->CATEGORY, pkg->PF,
+                       booga[ret], cat_ctx->name, pkg_ctx->name);
 
-                       pkg_unmerge(atom->CATEGORY, pn, objs);
-               }
-               freeargv(ARGC, ARGV);
+               pkg_unmerge(pkg_ctx, objs);
        }
 
        /* Clean up the package state */
@@ -1023,68 +1031,45 @@ pkg_merge(int level, const depend_atom *atom, const 
struct pkg_t *pkg)
 }
 
 _q_static int
-pkg_unmerge(const char *cat, const char *pkgname, queue *keep)
+pkg_unmerge(q_vdb_pkg_ctx *pkg_ctx, queue *keep)
 {
+       q_vdb_cat_ctx *cat_ctx = pkg_ctx->cat_ctx;
+       const char *cat = cat_ctx->name;
+       const char *pkgname = pkg_ctx->name;
        size_t buflen;
        static char *phases;
        static size_t phases_len;
-       char *buf, *vdb_path, *T;
+       const char *T;
+       char *buf;
        FILE *fp;
-       int ret, fd, vdb_fd, portroot_fd;
+       int ret, portroot_fd;
        int cp_argc, cpm_argc;
        char **cp_argv, **cpm_argv;
        llist_char *dirs = NULL;
 
        ret = 1;
-       buf = NULL;
-       vdb_path = NULL;
-       vdb_fd = portroot_fd = fd = -1;
+       buf = phases = NULL;
+       T = "${PWD}/temp";
 
-       if ((strchr(pkgname, ' ') != NULL) || (strchr(cat, ' ') != NULL)) {
-               qfprintf(stderr, "%s!!!%s '%s' '%s' (ambiguous name) specify 
fully-qualified pkgs\n", RED, NORM, cat, pkgname);
-               qfprintf(stderr, "%s!!!%s %s/%s (ambiguous name) specify 
fully-qualified pkgs\n", RED, NORM, cat, pkgname);
-               /* qfprintf(stderr, "%s!!!%s %s %s (ambiguous name) specify 
fully-qualified pkgs\n", RED, NORM, pkgname); */
-               return 1;
-       }
        printf("%s<<<%s %s%s%s/%s%s%s\n", YELLOW, NORM, WHITE, cat, NORM, CYAN, 
pkgname, NORM);
 
        if (pretend == 100)
                return 0;
 
-       /* Get a handle to the root to play with */
-       portroot_fd = open(portroot, O_RDONLY|O_CLOEXEC|O_PATH);
-       if (portroot_fd == -1) {
-               warnp("unable to read %s", portroot);
+       /* First get a handle on the things to clean up */
+       fp = q_vdb_pkg_fopenat_ro(pkg_ctx, "CONTENTS");
+       if (fp == NULL)
                goto done;
-       }
 
-       /* Get a handle on the vdb path which we'll use everywhere else */
-       /* Note: This vdb_path must be absolute since we use it in 
pkg_run_func() */
-       xasprintf(&vdb_path, "%s%s/%s/%s/", portroot, portvdb, cat, pkgname);
-       xasprintf(&T, "%stemp", vdb_path);
-       vdb_fd = openat(portroot_fd, vdb_path, O_RDONLY|O_CLOEXEC|O_PATH);
-       if (vdb_fd == -1) {
-               warnp("unable to read %s", vdb_path);
-               goto done;
-       }
+       portroot_fd = cat_ctx->ctx->portroot_fd;
 
-       /* First execute the pkg_prerm step */
+       /* Then execute the pkg_prerm step */
        if (!pretend) {
-               eat_file_at(vdb_fd, "DEFINED_PHASES", &phases, &phases_len);
-               mkdir_p(T, 0755);
-               pkg_run_func(vdb_path, phases, "pkg_prerm", T, T);
+               q_vdb_pkg_eat(pkg_ctx, "DEFINED_PHASES", &phases, &phases_len);
+               mkdirat(pkg_ctx->fd, "temp", 0755);
+               pkg_run_func_at(pkg_ctx->fd, ".", phases, "pkg_prerm", T, T);
        }
 
-       /* Now start removing all the installed files */
-       fd = openat(vdb_fd, "CONTENTS", O_RDONLY | O_CLOEXEC);
-       if (fd == -1) {
-               warnp("unable to read %s", "CONTENTS");
-               goto done;
-       }
-       fp = fdopen(fd, "r");
-       if (fp == NULL)
-               goto done;
-
        /* XXX: be nice to pull this out of the current func
         *      so we don't keep reparsing the same env var
         *      when unmerging multiple packages.
@@ -1186,7 +1171,6 @@ pkg_unmerge(const char *cat, const char *pkgname, queue 
*keep)
        }
 
        fclose(fp);
-       fd = -1;
 
        /* Then remove all dirs in reverse order */
        while (dirs != NULL) {
@@ -1208,27 +1192,20 @@ pkg_unmerge(const char *cat, const char *pkgname, queue 
*keep)
 
        if (!pretend) {
                /* Then execute the pkg_postrm step */
-               pkg_run_func(vdb_path, phases, "pkg_postrm", T, T);
-               rm_rf(T);
+               pkg_run_func_at(pkg_ctx->fd, ".", phases, "pkg_postrm", T, T);
 
                /* Finally delete the vdb entry */
-               rm_rf_at(portroot_fd, vdb_path);
+               rm_rf_at(pkg_ctx->fd, ".");
+               unlinkat(cat_ctx->fd, pkg_ctx->name, AT_REMOVEDIR);
 
-               /* And prune any empty vdb dirs */
-               rmdir_r_at(portroot_fd, vdb_path);
+               /* And prune the category if it's empty */
+               unlinkat(cat_ctx->ctx->vdb_fd, cat_ctx->name, AT_REMOVEDIR);
        }
 
        ret = 0;
  done:
-       if (fd != -1)
-               close(fd);
-       if (vdb_fd != -1)
-               close(vdb_fd);
-       if (portroot_fd != -1)
-               close(portroot_fd);
+       free(phases);
        free(buf);
-       free(T);
-       free(vdb_path);
 
        return ret;
 }
@@ -1485,42 +1462,25 @@ print_Pkg(int full, struct pkg_t *pkg)
 }
 
 _q_static int
-unmerge_packages(queue *todo)
+qmerge_unmerge_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 {
-       depend_atom *atom;
-       char *p;
-       int i, argc;
-       char **argv;
+       queue *todo = priv;
 
        while (todo) {
-               char buf[512];
-
-               if (todo->name[0] == '-')
-                       goto next;
-
-               p = best_version(NULL, todo->name);
-               if (!*p)
-                       goto next;
-
-               makeargv(p, &argc, &argv);
-               for (i = 1; i < argc; ++i) {
-                       if ((atom = atom_explode(argv[i])) == NULL)
-                               continue;
-                       if (atom->CATEGORY) {
-                               atom2str(atom, buf, sizeof(buf));
-                               pkg_unmerge(atom->CATEGORY, buf, NULL);
-                       }
-                       atom_implode(atom);
-               }
-               freeargv(argc, argv);
-
- next:
+               if (qlist_match(pkg_ctx, todo->name, NULL, true))
+                       pkg_unmerge(pkg_ctx, NULL);
                todo = todo->next;
        }
 
        return 0;
 }
 
+_q_static int
+unmerge_packages(queue *todo)
+{
+       return q_vdb_foreach_pkg(qmerge_unmerge_cb, todo, NULL);
+}
+
 _q_static FILE *
 open_binpkg_index(void)
 {
@@ -1858,13 +1818,15 @@ _q_static queue *
 qmerge_add_set_atom(char *satom, queue *set)
 {
        char *p;
-       const char *slot;
+       const char *slot = "";
 
-       if ((p = strchr(satom, ':')) != NULL) {
-               *p = 0;
-               slot = p + 1;
-       } else
-               slot = "0";
+       if (!uninstall) {
+               if ((p = strchr(satom, ':')) != NULL) {
+                       *p = 0;
+                       slot = p + 1;
+               } else
+                       slot = "0";
+       }
 
        return add_set(satom, slot, set);
 }

diff --git a/tests/qmerge/dotest b/tests/qmerge/dotest
index 9c4bcb4..fac6437 100755
--- a/tests/qmerge/dotest
+++ b/tests/qmerge/dotest
@@ -17,6 +17,8 @@ mktmpdir
 export ROOT=${PWD}/root
 export PORTAGE_TMPDIR=${PWD}
 
+mkdir -p "${ROOT}/var/db/pkg"
+
 set +e
 
 # Do a merge into an empty tree.
@@ -72,7 +74,7 @@ tend $? "qmerge-test: [C] pkg_* order of execution" || printf 
'%s\n' "${order}"
 [[ ! -x ${ROOT}/usr/bin/qmerge-test && \
      -f ${ROOT}/etc/some.conf && \
    ! -f ${ROOT}/etc/another.conf && \
-   ! -d ${ROOT}/var ]]
+   ! -d ${ROOT}/var/pkg/db/sys-devel ]]
 tend $? "qmerge-test: [C] uninstalled expected files" || treedir "${ROOT}"
 
 set -e

Reply via email to