checkpoint, misc rewritage
authorDan Winship <danw@gnome.org>
Wed, 5 Mar 2008 00:07:14 +0000 (19:07 -0500)
committerDan Winship <danw@gnome.org>
Wed, 5 Mar 2008 00:07:14 +0000 (19:07 -0500)
razor.c

diff --git a/razor.c b/razor.c
index 605f8a8..3dba9b5 100644 (file)
--- a/razor.c
+++ b/razor.c
@@ -1682,105 +1682,135 @@ struct razor_transaction_resolver {
        int errors;
 };
 
+static int
+package_in_set(void *package, struct razor_set *set)
+{
+       return package >= set->packages.data &&
+               package < set->packages.data + set->packages.size;
+}
+
+static int
+property_in_set(void *property, struct razor_set *set)
+{
+       return property >= set->properties.data &&
+               property < set->properties.data + set->properties.size;
+}
+
+static int
+compare_transaction_packages(const void *one, const void *two)
+{
+       const struct razor_transaction_package *tp1 = one;
+       const struct razor_transaction_package *tp2 = two;
+
+       return strcmp(tp1->name, tp2->name);
+}
+
 static void
 find_packages(struct razor_transaction_resolver *trans,
-             int count, const char **package_names,
-             enum razor_transaction_package_state state)
+             int update_count, const char **update_packages,
+             int remove_count, const char **remove_packages)
 {
-       struct razor_set *set;
-       struct bitarray *pkgbits;
-       struct razor_package_iterator *pi;
-       struct razor_package *p, *packages;
-       const char *name, *version;
-       struct razor_transaction_package *tp;
-       int i, *found;
-
-       if (state == RAZOR_PACKAGE_INSTALL) {
-               set = trans->upstream;
-               pkgbits = &trans->uppkgs;
-       } else {
-               set = trans->system;
-               pkgbits = &trans->syspkgs;
-       }
+       struct razor_package *sp, *spkgs, *up, *upkgs, *send, *uend;
+       struct razor_transaction_package *packages, *tp;
+       const char *spool, *upool;
+       int i;
 
-       packages = (struct razor_package *) set->packages.data;
-       pi = razor_package_iterator_create(set);
-       found = zalloc(count * sizeof (int));
+       spkgs = trans->system->packages.data;
+       send = trans->system->packages.data + trans->system->packages.size;
+       spool = trans->system->string_pool.data;
+       upkgs = trans->upstream->packages.data;
+       uend = trans->upstream->packages.data + trans->upstream->packages.size;
+       upool = trans->upstream->string_pool.data;
 
-       while (razor_package_iterator_next(pi, &p, &name, &version)) {
-               for (i = 0; i < count; i++) {
-                       if (strcmp(name, package_names[i]) == 0) {
-                               found[i] = 1;
-                               tp = array_add(&trans->packages, sizeof *tp);
-                               memset(tp, 0, sizeof *tp);
-                               tp->package = p;
-                               tp->name = name;
-                               tp->version = version;
-                               tp->state = state;
-                               bitarray_set(pkgbits, p - packages,
-                                            state == RAZOR_PACKAGE_INSTALL);
-                               break;
-                       }
-               }
+       for (i = 0; i < update_count; i++) {
+               tp = array_add(&trans->packages, sizeof *tp);
+               memset(tp, 0, sizeof *tp);
+               tp->name = update_packages[i];
+               tp->state = RAZOR_PACKAGE_INSTALL;
        }
+       for (i = 0; i < remove_count; i++) {
+               tp = array_add(&trans->packages, sizeof *tp);
+               memset(tp, 0, sizeof *tp);
+               tp->name = remove_packages[i];
+               tp->state = RAZOR_PACKAGE_REMOVE;
+       }
+       qsort(trans->packages.data, update_count + remove_count,
+             sizeof *tp, compare_transaction_packages);
+       packages = trans->packages.data;
+
+       sp = spkgs;
+       up = upkgs;
+       for (i = 0; i < update_count + remove_count; i++) {
+               while (sp < send && strcmp(&spool[sp->name], packages[i].name) < 0)
+                       sp++;
+               while (up < uend && strcmp(&upool[up->name], packages[i].name) < 0)
+                       up++;
 
-       for (i = 0; i < count; i++) {
-               if (!found[i]) {
-                       tp = array_add(&trans->packages, sizeof *tp);
-                       memset(tp, 0, sizeof *tp);
-                       tp->name = strdup(package_names[i]);
-                       tp->state = state | RAZOR_PACKAGE_UNAVAILABLE;
-                       trans->errors++;
+               if (packages[i].state == RAZOR_PACKAGE_REMOVE) {
+                       if (sp < send && strcmp(packages[i].name, &spool[sp->name]) == 0) {
+                               packages[i].package = sp;
+                               packages[i].name = &spool[sp->name];
+                               packages[i].version = &spool[sp->version];
+                               bitarray_set(&trans->syspkgs, sp - spkgs, 0);
+                       } else {
+                               packages[i].name = strdup(packages[i].name);
+                               packages[i].state |= RAZOR_PACKAGE_UNAVAILABLE;
+                               trans->errors++;
+                       }
+               } else {
+                       if (up < uend && strcmp(packages[i].name, &upool[up->name]) == 0) {
+                               if (sp < send && strcmp(packages[i].name, &spool[sp->name]) == 0) {
+                                       if (versioncmp(&spool[sp->version], &upool[up->version]) >= 0) {
+                                               /* FIXME: need a distinct error */
+                                               packages[i].name = strdup(packages[i].name);
+                                               packages[i].state |= RAZOR_PACKAGE_UNAVAILABLE;
+                                               trans->errors++;
+                                               continue;
+                                       }
+                                       bitarray_set(&trans->syspkgs, sp - spkgs, 0);
+                               }
+                               packages[i].package = up;
+                               packages[i].name = &upool[up->name];
+                               packages[i].version = &upool[up->version];
+                               bitarray_set(&trans->uppkgs, up - upkgs, 1);
+                       } else {
+                               packages[i].name = strdup(packages[i].name);
+                               packages[i].state |= RAZOR_PACKAGE_UNAVAILABLE;
+                               trans->errors++;
+                       }
                }
        }
-
-       razor_package_iterator_destroy(pi);
-       free(found);
 }
 
 static void
 find_all_packages(struct razor_transaction_resolver *trans)
 {
        struct razor_transaction_package *tp;
-       struct razor_package *p, *packages, *u, *pend, *uend;
-       char *pool, *upool;
+       struct razor_package *sp, *spkgs, *send, *up, *upkgs, *uend;
+       const char *spool, *upool;
 
-       packages = trans->system->packages.data;
-       pend = trans->system->packages.data + trans->system->packages.size;
-       pool = trans->system->string_pool.data;
-       u = trans->upstream->packages.data;
+       spkgs = trans->system->packages.data;
+       send = trans->system->packages.data + trans->system->packages.size;
+       spool = trans->system->string_pool.data;
+       up = upkgs = trans->upstream->packages.data;
        uend = trans->upstream->packages.data + trans->upstream->packages.size;
        upool = trans->upstream->string_pool.data;
 
-       for (p = packages; p < pend; p++) {
-               while (u < uend && strcmp(&pool[p->name], &upool[u->name]) > 0)
-                       u++;
-               if (strcmp(&pool[p->name], &upool[u->name]) == 0) {
+       for (sp = spkgs; sp < send; sp++) {
+               while (up < uend && strcmp(&spool[sp->name], &upool[up->name]) > 0)
+                       up++;
+               if (strcmp(&spool[sp->name], &upool[up->name]) == 0) {
                        tp = array_add(&trans->packages, sizeof *tp);
                        memset(tp, 0, sizeof *tp);
-                       tp->name = &upool[u->name];
-                       tp->version = &upool[u->version];
+                       tp->name = &upool[up->name];
+                       tp->version = &upool[up->version];
                        tp->state = RAZOR_PACKAGE_INSTALL;
-                       bitarray_set(&trans->uppkgs, p - packages, 1);
+                       bitarray_set(&trans->uppkgs, up - upkgs, 1);
+                       bitarray_set(&trans->syspkgs, sp - spkgs, 0);
                }
        }
 }
 
-/* FIXME: wrong, need to compare names, not razor_package* */
-static int
-find_transaction_package(struct array *package_array,
-                        struct razor_package *package)
-{
-       struct razor_transaction_package *tps = package_array->data;
-       int i, tpcount = package_array->size / sizeof *tps;
-
-       for (i = 0; i < tpcount; i++) {
-               if (tps[i].package == package)
-                       return i;
-       }
-       return -1;
-}
-
 static int
 provider_satisfies_requirement(struct razor_property *provider,
                               const char *provider_strings,
@@ -1827,8 +1857,8 @@ provider_satisfies_requirement(struct razor_property *provider,
 }
 
 static struct razor_package *
-find_file(struct razor_set *set, struct bitarray *pkgbits,
-         const char *filename, int installed)
+find_package_for_file(struct razor_set *set, struct bitarray *pkgbits,
+                     const char *filename, int installed)
 {
        struct razor_package *pkgs = set->packages.data;
        struct razor_entry *entry;
@@ -1849,179 +1879,278 @@ find_file(struct razor_set *set, struct bitarray *pkgbits,
 }
 
 static struct razor_package *
-find_system_file(struct razor_transaction_resolver *trans,
-                const char *filename, int installed)
+find_installed_package_for_file(struct razor_transaction_resolver *trans,
+                               const char *filename)
 {
-       return find_file(trans->system, &trans->syspkgs, filename, installed);
+       struct razor_package *pkg;
+
+       pkg = find_package_for_file(trans->system, &trans->syspkgs,
+                                   filename, 1);
+       if (!pkg)
+               pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
+                                           filename, 1);
+       return pkg;
 }
 
 static struct razor_package *
-find_upstream_file(struct razor_transaction_resolver *trans,
-                  const char *filename, int installed)
+find_uninstalled_package_for_file(struct razor_transaction_resolver *trans,
+                                 const char *filename)
 {
-       return find_file(trans->upstream, &trans->uppkgs, filename, installed);
+       struct razor_package *pkg;
+
+       pkg = find_package_for_file(trans->upstream, &trans->uppkgs,
+                                   filename, 0);
+       if (!pkg)
+               pkg = find_package_for_file(trans->system, &trans->syspkgs,
+                                           filename, 0);
+       return pkg;
 }
 
 static struct razor_package *
-find_system_provider(struct razor_transaction_resolver *trans,
-                    int installed, int match_name,
-                    struct razor_property *req, int *sp)
-{
-       struct razor_package *spkgs = trans->system->packages.data;
-       struct razor_property *sprops = trans->system->properties.data;
-       const char *spool = trans->system->string_pool.data;
-       const char *upool = trans->upstream->string_pool.data;
-       int scount = trans->system->properties.size / sizeof *sprops;
-
-       /* Skip ahead to first matching PROVIDES */
-       while (*sp < scount &&
-              strcmp(&spool[sprops[*sp].name], &upool[req->name]) < 0)
-               (*sp)++;
-       while (*sp < scount &&
-              sprops[*sp].type != RAZOR_PROPERTY_PROVIDES &&
-              strcmp(&spool[sprops[*sp].name], &upool[req->name]) == 0)
-               (*sp)++;               
-
-       /* Scan matching PROVIDES */
-       while (*sp < scount &&
-              sprops[*sp].type == RAZOR_PROPERTY_PROVIDES &&
-              strcmp(&spool[sprops[*sp].name],
-                     &upool[req->name]) == 0) {
-               if (provider_satisfies_requirement(&sprops[*sp], spool,
-                                                  req, upool)) {
-                       struct list *pkg;
+find_package_matching(struct razor_transaction_resolver *trans, int installed,
+                     struct razor_property **start_prop,
+                     struct razor_property *req,
+                     struct razor_set *req_set)
+{
+       struct razor_set *set;
+       struct bitarray *pkgbits;
+       struct razor_package *pkgs;
+       struct razor_property *prop, *props, *prop_end;
+       enum razor_property_type match_type;
+       const char *pool;
+       const char *rpool = req_set->string_pool.data;
+       int match_name = (req->type == RAZOR_PROPERTY_OBSOLETES ||
+                         req->type == RAZOR_PROPERTY_CONFLICTS);
+       int match;
 
-                       for (pkg = list_first(&sprops[*sp].packages, &trans->system->package_pool); pkg; pkg = list_next(pkg)) {
-                               if (bitarray_get(&trans->syspkgs, pkg->data) != installed)
-                                       continue;
-                               if (!match_name ||
-                                   strcmp(&spool[spkgs[pkg->data].name],
-                                          &upool[req->name]) == 0)
-                                       return &spkgs[pkg->data];
-                       }
-               }
-               (*sp)++;
-       }
+       prop = *start_prop;
+       if (property_in_set(prop, trans->system)) {
+               set = trans->system;
+               pkgbits = &trans->syspkgs;
+       } else if (property_in_set(prop, trans->upstream)) {
+               set = trans->upstream;
+               pkgbits = &trans->uppkgs;
+       } else
+               return NULL;
 
-       return NULL;
-}
+       if (req->type == RAZOR_PROPERTY_PROVIDES)
+               match_type = RAZOR_PROPERTY_CONFLICTS;
+       else
+               match_type = RAZOR_PROPERTY_PROVIDES;
 
-static struct razor_package *
-find_upstream_provider(struct razor_transaction_resolver *trans,
-                      int installed, int match_name,
-                      struct razor_property *req, int up)
-{
-       struct razor_package *upkgs = trans->upstream->packages.data;
-       struct razor_property *uprops = trans->upstream->properties.data;
-       const char *upool = trans->upstream->string_pool.data;
-       int ucount = trans->upstream->properties.size / sizeof *uprops;
-
-       /* Skip to first matching provide */
-       if (req->type < RAZOR_PROPERTY_PROVIDES) {
-               while (up < ucount &&
-                      uprops[up].type != RAZOR_PROPERTY_PROVIDES)
-                       up++;
+       pkgs = set->packages.data;
+       props = set->properties.data;
+       prop_end = set->properties.data + set->properties.size;
+       pool = set->string_pool.data;
+
+       /* Find first matching property */
+       while (prop < prop_end &&
+              strcmp(&pool[prop->name], &rpool[req->name]) < 0)
+               prop++;
+       *start_prop = prop;
+       if (prop == prop_end ||
+           strcmp(&pool[prop->name], &rpool[req->name]) > 0)
+               return NULL;
+
+       if (prop->type < match_type) {
+               while (prop < prop_end && prop->type != match_type)
+                       prop++;
        } else {
-               while (up >= 0 &&
-                      uprops[up].type != RAZOR_PROPERTY_PROVIDES)
-                       up--;
-               while (up > 0 &&
-                      uprops[up - 1].type == RAZOR_PROPERTY_PROVIDES)
-                       up--;
-               if (up < 0)
-                       return NULL;
+               while (prop >= props && prop->type != match_type)
+                       prop--;
+               while (prop > props + 1 && (prop - 1)->type == match_type)
+                       prop--;
        }
 
-       /* Scan matching PROVIDES */
-       while (up < ucount &&
-              uprops[up].type == RAZOR_PROPERTY_PROVIDES &&
-              uprops[up].name == req->name) {
-               if (provider_satisfies_requirement(&uprops[up], upool,
-                                                  req, upool)) {
+       /* Scan matching proeprties */
+       while (prop < prop_end && prop->type == match_type &&
+              strcmp(&pool[prop->name], &rpool[req->name]) == 0) {
+               if (match_type == RAZOR_PROPERTY_PROVIDES)
+                       match = provider_satisfies_requirement(prop, pool, req, rpool);
+               else
+                       match = provider_satisfies_requirement(req, rpool, prop, pool);
+               if (match) {
                        struct list *pkg;
 
-                       for (pkg = list_first(&uprops[up].packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
-                               if (bitarray_get(&trans->uppkgs, pkg->data) != installed)
+                       for (pkg = list_first(&prop->packages, &set->package_pool); pkg; pkg = list_next(pkg)) {
+                               if (bitarray_get(pkgbits, pkg->data) != installed)
                                        continue;
                                if (!match_name ||
-                                   strcmp(&upool[upkgs[pkg->data].name],
-                                          &upool[req->name]) == 0)
-                                       return &upkgs[pkg->data];
+                                   strcmp(&pool[pkgs[pkg->data].name],
+                                          &rpool[req->name]) == 0)
+                                       return &pkgs[pkg->data];
                        }
                }
-               up++;
+               prop++;
        }
+
        return NULL;
 }
 
 static struct razor_package *
+find_installed_package_for_property(struct razor_transaction_resolver *trans,
+                                   struct razor_property **sys_sp,
+                                   struct razor_property *req)
+{
+       struct razor_package *pkg;
+
+       pkg = find_package_matching(trans, 1, sys_sp, req, trans->upstream);
+       if (!pkg)
+               pkg = find_package_matching(trans, 1, &req, req, trans->upstream);
+       return pkg;
+}
+
+static struct razor_package *
+find_uninstalled_package_for_property(struct razor_transaction_resolver *trans,
+                                     struct razor_property **sys_sp,
+                                     struct razor_property *req)
+{
+       struct razor_package *pkg;
+
+       pkg = find_package_matching(trans, 0, sys_sp, req, trans->upstream);
+       if (!pkg)
+               pkg = find_package_matching(trans, 0, &req, req, trans->upstream);
+       return pkg;
+}
+
+static struct razor_package *
 find_upgrade(struct razor_transaction_resolver *trans,
-            struct razor_property *obsolete, int up)
+            struct razor_property *sp, struct razor_property *up)
 {
-       struct razor_property *uprops = trans->upstream->properties.data;
-       const char *upool = trans->upstream->string_pool.data;
-       struct razor_property req;
+       struct razor_property *conflict, req;
+       struct razor_set *set;
+       const char *pool;
+
+       if (sp->type == RAZOR_PROPERTY_CONFLICTS) {
+               conflict = sp;
+               set = trans->system;
+       } else {
+               conflict = up;
+               set = trans->upstream;
+       }
+       pool = set->string_pool.data;
 
-       if (uprops[up].relation > RAZOR_VERSION_EQUAL ||
-           !upool[uprops[up].version])
+       if (conflict->relation > RAZOR_VERSION_EQUAL ||
+           !pool[conflict->version])
                return NULL;
 
-       memcpy(&req, obsolete, sizeof req);
+       memcpy(&req, conflict, sizeof req);
        req.type = RAZOR_PROPERTY_REQUIRES;
-       if (uprops[up].relation == RAZOR_VERSION_LESS)
+       if (conflict->relation == RAZOR_VERSION_LESS)
                req.relation = RAZOR_VERSION_GREATER_OR_EQUAL;
        else
                req.relation = RAZOR_VERSION_GREATER;
 
-       /* We need to rewind up, since OBSOLETES > PROVIDES, so we've
-        * already gone past the possible upgrades.
-        */
-       while (up >= 0 &&
-              uprops[up].type != RAZOR_PROPERTY_PROVIDES)
-               up--;
-       while (up > 0 &&
-              uprops[up - 1].type == RAZOR_PROPERTY_PROVIDES)
-               up--;
-       if (up < 0)
+       return find_package_matching(trans, 0, &up, &req, set);
+}
+
+/* FIXME */
+static struct razor_package *
+find_upgrade_for_installed_conflict(struct razor_transaction_resolver *trans,
+                                   struct razor_package *conflicting_pkg,
+                                   struct razor_property *provider)
+{
+       struct razor_package *upkgs, *up, *uend;
+       struct razor_property *uprops;
+       const char *spool, *upool;
+       struct list *prop;
+
+       if (!package_in_set(conflicting_pkg, trans->system))
+               return NULL;
+
+       up = upkgs = trans->upstream->packages.data;
+       uend = trans->upstream->packages.data + trans->upstream->packages.size;
+       upool = trans->upstream->string_pool.data;
+       uprops = trans->upstream->properties.data;
+       spool = trans->system->string_pool.data;
+
+       while (up < uend &&
+              strcmp(&upool[up->name], &spool[conflicting_pkg->name]) < 0)
+               up++;
+       if (up == uend || strcmp(&upool[up->name], &spool[conflicting_pkg->name]) != 0)
                return NULL;
 
-       return find_upstream_provider(trans, 0, 1, &req, up);
+       for (prop = list_first(&up->properties, &trans->system->property_pool); prop; prop = list_next(prop)) {
+               if (uprops[prop->data].type == RAZOR_PROPERTY_CONFLICTS &&
+                   provider_satisfies_requirement(provider, upool, &uprops[prop->data], upool))
+                       return NULL;
+       }
+       return up;
+}
+
+/* FIXME */
+static int
+prop_is_being_installed(struct razor_transaction_resolver *trans,
+                       struct razor_property *prop)
+{
+       struct list *pkg;
+
+       for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
+               if (bitarray_get(&trans->uppkgs, pkg->data))
+                       return 1;
+       }
+       return 0;
 }
 
 static void
 add_transaction_package(struct razor_transaction_resolver *trans,
                        struct razor_package *package,
-                       struct razor_set *package_set,
                        enum razor_transaction_package_state state,
-                       struct razor_property *req_prop,
-                       struct razor_set *req_set)
+                       const char *req_package,
+                       struct razor_property *req_prop)
 {
-       struct razor_transaction_package *tp;
+       struct razor_set *package_set;
+       struct razor_transaction_package *tp, *packages;
        const char *pool;
        struct razor_package *pkgs;
        struct list *pkg;
 
+       package_set = package_in_set(package, trans->system) ? trans->system : trans->upstream;
+
        tp = array_add(&trans->packages, sizeof *tp);
        memset(tp, 0, sizeof *tp);
 
        if (package) {
-               tp->package = package;
+               int i, count;
+
+               /* Make sure we aren't already acting on this package */
+               packages = trans->packages.data;
+               count = trans->packages.size / sizeof *packages;
                pool = package_set->string_pool.data;
+               for (i = 0; i < count; i++) {
+                       if (packages[i].name &&
+                           !strcmp(packages[i].name, &pool[package->name])) {
+                               if (state == packages[i].state) {
+                                       /* Already taken care of */
+                                       return;
+                               }
+                               /* Oops. We lose */
+                               state |= RAZOR_PACKAGE_BLOCKED;
+                               break;
+                       }
+               }
+
+               tp->package = package;
                tp->name = &pool[package->name];
                tp->version = &pool[package->version];
                tp->state = state;
        } else
                tp->state = state | RAZOR_PACKAGE_UNSATISFIABLE;
 
-       for (pkg = list_first(&req_prop->packages, &req_set->package_pool); pkg; pkg = list_next(pkg)) {
-               if (bitarray_get(&trans->uppkgs, pkg->data))
-                       break;
-       }
-       if (pkg) {
-               pool = req_set->string_pool.data;
-               pkgs = req_set->packages.data;
-               tp->req_package = &pool[pkgs[pkg->data].name];
+       if (req_package)
+               tp->req_package = req_package;
+       else {
+               for (pkg = list_first(&req_prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
+                       if (bitarray_get(&trans->uppkgs, pkg->data))
+                               break;
+               }
+               if (pkg) {
+                       pool = trans->upstream->string_pool.data;
+                       pkgs = trans->upstream->packages.data;
+                       tp->req_package = &pool[pkgs[pkg->data].name];
+               }
        }
+
        tp->req_type = req_prop->type;
        tp->req_property = &pool[req_prop->name];
        tp->req_relation = req_prop->relation;
@@ -2036,57 +2165,61 @@ add_transaction_package(struct razor_transaction_resolver *trans,
                trans->errors++;
 }
 
-/* FIXME */
-static int
-prop_is_being_installed(struct razor_transaction_resolver *trans,
-                       struct razor_property *prop)
+/* FIXME: make this more efficient */
+static void
+maybe_mark_upgraded(struct razor_transaction_resolver *trans,
+                   struct razor_package *pkg)
 {
-       struct list *pkg;
+       struct razor_package *spkgs, *sp, *send;
+       const char *spool, *upool;
 
-       for (pkg = list_first(&prop->packages, &trans->upstream->package_pool); pkg; pkg = list_next(pkg)) {
-               if (bitarray_get(&trans->uppkgs, pkg->data))
-                       return 1;
-       }
-       return 0;
+       sp = spkgs = trans->system->packages.data;
+       send = trans->system->packages.data + trans->system->packages.size;
+       spool = trans->system->string_pool.data;
+       upool = trans->upstream->string_pool.data;
+
+       while (sp < send &&
+              strcmp(&spool[sp->name], &upool[pkg->name]) < 0)
+               sp++;
+       if (sp < send && strcmp(&spool[sp->name], &upool[pkg->name]) == 0)
+               bitarray_set(&trans->syspkgs, sp - spkgs, 0);
 }
 
 static void
 razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans)
 {
-       struct razor_package *spkgs, *upkgs, *pkg;
-       struct razor_property *prop, *sprops, *uprops;
-       int sp, up, ucount;
+       struct razor_package *spkgs, *upkgs, *pkg, *upgrade;
+       struct razor_property *sp, *sprops, *sprop_end;
+       struct razor_property *up, *uprops, *uprop_end;
        const char *upool;
 
        spkgs = trans->system->packages.data;
        sprops = trans->system->properties.data;
+       sprop_end = trans->system->properties.data + trans->system->properties.size;
        upkgs = trans->upstream->packages.data;
        uprops = trans->upstream->properties.data;
-       ucount = trans->upstream->properties.size / sizeof *uprops;
+       uprop_end = trans->upstream->properties.data + trans->upstream->properties.size;
        upool = trans->upstream->string_pool.data;
 
-       sp = up = 0;
-       while (up < ucount) {
+       sp = sprops;
+       up = uprops;
+       while (up < uprop_end) {
                /* Skip 'up' ahead to a property of a package which is
                 * to-be-installed.
                 */
-               while (up < ucount &&
-                      (uprops[up].type == RAZOR_PROPERTY_PROVIDES ||
-                       !prop_is_being_installed(trans, &uprops[up])))
+               while (up < uprop_end &&
+                      !prop_is_being_installed(trans, up))
                        up++;
-               if (up == ucount)
+               if (up == uprop_end)
                        break;
 
-               prop = &uprops[up];
-               switch (prop->type) {
+               switch (up->type) {
                case RAZOR_PROPERTY_REQUIRES:
-                       if (!strncmp(&upool[prop->name], "rpmlib(", 7))
+                       if (!strncmp(&upool[up->name], "rpmlib(", 7))
                                break;
 
-                       if (find_system_provider(trans, 1, 0, prop, &sp) ||
-                           find_upstream_provider(trans, 1, 0, prop, up) ||
-                           find_system_file(trans, &upool[prop->name], 1) ||
-                           find_upstream_file(trans, &upool[prop->name], 1)) {
+                       if (find_installed_package_for_property(trans, &sp, up) ||
+                           find_installed_package_for_file(trans, &upool[up->name])) {
                                /* Requires something that is either installed
                                 * or to-be-installed.
                                 */
@@ -2094,56 +2227,87 @@ razor_transaction_satisfy_installs(struct razor_transaction_resolver *trans)
                        }
 
                        /* See if we can install a new upstream provider */
-                       pkg = find_upstream_provider(trans, 0, 0, prop, up);
-                       if (!pkg)
-                               pkg = find_upstream_file(trans, &upool[prop->name], 0);
-                       add_transaction_package(trans, pkg, trans->upstream,
+                       pkg = find_uninstalled_package_for_property(trans, &sp, up);
+                       if (!pkg) {
+                               pkg = find_uninstalled_package_for_file(trans, &upool[up->name]);
+                               if (pkg) {
+                                       /* FIXME: find a way to do this more efficiently */
+                                       maybe_mark_upgraded(trans, pkg);
+                               }
+                       }
+                       add_transaction_package(trans, pkg,
                                                RAZOR_PACKAGE_INSTALL,
-                                               prop, trans->upstream);
+                                               NULL, up);
+                       break;
+
+               case RAZOR_PROPERTY_PROVIDES:
+                       /* find_installed_package_for_property works backwards
+                        * here, finding a *conflicting* installed package.
+                        */
+                       pkg = find_installed_package_for_property(trans, &sp, up);
+                       if (!pkg)
+                               break;
+
+                       /* pkg CONFLICTS with what 'up' PROVIDES. Try
+                        * finding an upgrade
+                        */
+                       upgrade = find_upgrade_for_installed_conflict(trans, pkg, up);
+                       if (upgrade) {
+                               bitarray_set(&trans->syspkgs, pkg - spkgs, 0);
+                               add_transaction_package(trans, upgrade,
+                                                       RAZOR_PACKAGE_INSTALL,
+                                                       NULL, up);
+                       } else {
+                               add_transaction_package(trans, pkg,
+                                                       /* FIXME? */
+                                                       RAZOR_PACKAGE_REMOVE_CONFLICT,
+                                                       NULL, up);
+                       }
                        break;
 
                case RAZOR_PROPERTY_CONFLICTS:
-                       if ((pkg = find_system_provider(trans, 1, 1, prop, &sp))) {
-                               struct razor_package *upgrade;
+                       pkg = find_installed_package_for_property(trans, &sp, up);
+                       if (!pkg)
+                               break;
 
+                       if (package_in_set(pkg, trans->system)) {
                                /* Conflicts with something already installed.
                                 * Try to upgrade out.
                                 */
-                               upgrade = find_upgrade(trans, prop, up);
+                               upgrade = find_upgrade(trans, sp, up);
                                if (upgrade) {
                                        bitarray_set(&trans->syspkgs, pkg - spkgs, 0);
                                        add_transaction_package(trans, upgrade,
-                                                               trans->upstream,
                                                                RAZOR_PACKAGE_INSTALL,
-                                                               prop, trans->upstream);
+                                                               NULL, up);
                                } else {
                                        add_transaction_package(trans, pkg,
-                                                               trans->system, 
                                                                RAZOR_PACKAGE_INSTALL_CONFLICT,
-                                                               prop, trans->upstream);
+                                                               NULL, up);
                                }
-                       } else if ((pkg = find_upstream_provider(trans, 1, 1, prop, up))) {
+                       } else {
                                /* Conflicts with something already to-be-installed */
                                add_transaction_package(trans, pkg,
-                                                       trans->upstream, 
                                                        RAZOR_PACKAGE_INSTALL_CONFLICT,
-                                                       prop, trans->upstream);
+                                                       NULL, up);
                        }
                        break;
 
                case RAZOR_PROPERTY_OBSOLETES:
-                       if ((pkg = find_system_provider(trans, 1, 1, prop, &sp))) {
+                       pkg = find_installed_package_for_property(trans, &sp, up);
+                       if (!pkg)
+                               break;
+
+                       if (package_in_set(pkg, trans->system)) {
                                /* Obsoletes something installed */
                                add_transaction_package(trans, pkg,
-                                                       trans->system, 
                                                        RAZOR_PACKAGE_REMOVE,
-                                                       prop, trans->upstream);
-                       } else if ((pkg = find_upstream_provider(trans, 1, 1, prop, up))) {
+                                                       NULL, up);
+                       } else {
                                /* Obsoletes something that was to-be-installed */
                                add_transaction_package(trans, pkg,
-                                                       trans->upstream, 
                                                        RAZOR_PACKAGE_REMOVE_CONFLICT,
-                                                       prop, trans->upstream);
+                                                       NULL, up);
                        }
                        break;
 
@@ -2204,36 +2368,14 @@ lose_required_package(struct razor_transaction_resolver *trans,
        struct razor_package *pkgs, *lost_package;
        char *pool = trans->system->string_pool.data;
        struct list *p;
-       struct razor_transaction_package *tp, *packages;;
-       int already;
 
        pkgs = trans->system->packages.data;
        lost_package = &pkgs[list_first(lost_package_list, &trans->system->package_pool)->data];
 
        for (p = list_first(&req->packages, &trans->system->package_pool); p; p = list_next(p)) {
-               packages = trans->packages.data;
-               already = find_transaction_package(&trans->packages, &pkgs[p->data]);
-               if (already != -1 &&
-                   (packages[already].state & RAZOR_PACKAGE_REMOVE))
-                       continue;
-
-               tp = array_add(&trans->packages, sizeof *tp);
-               memset(tp, 0, sizeof *tp);
-               tp->package = &pkgs[p->data];
-               tp->name = &pool[tp->package->name];
-               tp->version = &pool[tp->package->version];
-               tp->req_package = &pool[lost_package->name];
-               tp->req_type = req->type;
-               tp->req_property = &pool[req->name];
-               tp->req_relation = req->relation;
-               tp->req_version = &pool[req->version];
-               if (already != -1) {
-                       tp->state = RAZOR_PACKAGE_REMOVE_BLOCKED;
-                       trans->errors++;
-               } else {
-                       tp->state = RAZOR_PACKAGE_REMOVE;
-                       bitarray_set(&trans->syspkgs, p->data, 0);
-               }
+               add_transaction_package(trans, &pkgs[p->data],
+                                       RAZOR_PACKAGE_REMOVE,
+                                       &pool[lost_package->name], req);
        }
 }
 
@@ -2280,11 +2422,11 @@ razor_transaction_satisfy_removes(struct razor_transaction_resolver *trans,
        props = trans->system->properties.data;
        prop_end = trans->system->properties.data + trans->system->properties.size;
        pool = trans->system->string_pool.data;
+       packages = trans->packages.data;
 
        array_init(&lost_files);
        array_init(&lost_provides);
        for (r = start; r < end; r++) {
-               packages = trans->packages.data;
                if (packages[r].state != RAZOR_PACKAGE_REMOVE)
                        continue;
 
@@ -2401,19 +2543,13 @@ razor_transaction_create(struct razor_set *system, struct razor_set *upstream,
        bitarray_init(&trans.uppkgs, trans.upstream->packages.size / sizeof (struct razor_package), 0);
        trans.errors = 0;
 
-       /* Find initial upstream packages to be installed */
-       if (update_count > 0) {
-               find_packages(&trans, update_count, update_packages,
-                             RAZOR_PACKAGE_INSTALL);
-       } else if (remove_count == 0)
+       if (update_count > 0 || remove_count > 0) {
+               find_packages(&trans,
+                             update_count, update_packages,
+                             remove_count, remove_packages);
+       } else
                find_all_packages(&trans);
 
-       /* Find initial installed packages to remove. */
-       if (remove_count > 0) {
-               find_packages(&trans, remove_count, remove_packages,
-                             RAZOR_PACKAGE_REMOVE);
-       }
-
        start = 0;
        end = trans.packages.size / sizeof (struct razor_transaction_package);
 
@@ -2483,24 +2619,26 @@ razor_transaction_describe(struct razor_transaction *trans)
                        break;
 
                case RAZOR_PACKAGE_INSTALL_UNAVAILABLE:
-                       if (*p->req_version && strcmp(p->req_property, p->name) == 0) {
-                               printf ("Can't find %s %s %s, which is required by %s",
-                                       p->name,
-                                       razor_version_relations[p->req_relation],
-                                       p->req_version,
-                                       p->req_package);
-                       } else {
-                               printf ("Can't find %s", p->name);
-                               if (*p->version)
-                                       printf (" %s", p->version);
-                               
-                               if (p->req_package) {
-                                       printf ("  which is required by %s",
+                       printf ("Can't find %s", p->name);
+                       if (p->req_package) {
+                               if (*p->req_version && strcmp(p->req_property, p->name) == 0) {
+                                       printf ("%s %s, which is required by %s",
+                                               razor_version_relations[p->req_relation],
+                                               p->req_version,
                                                p->req_package);
-                                       if (strcmp(p->req_property, p->name) != 0)
-                                               printf (" for %s", p->req_property);
+                               } else {
+                                       if (*p->version)
+                                               printf (" %s", p->version);
+
+                                       if (p->req_package) {
+                                               printf ("  which is required by %s",
+                                                       p->req_package);
+                                               if (strcmp(p->req_property, p->name) != 0)
+                                                       printf (" for %s", p->req_property);
+                                       }
                                }
-                       }
+                       } else if (p->version && *p->version)
+                               printf (" %s", p->version);
                        printf("\n");
                        errors_only = 1;
                        break;