removes for upgrades should happen inthe middle of transactions, not
authorewt <devnull@localhost>
Sun, 4 Apr 1999 21:26:36 +0000 (21:26 +0000)
committerewt <devnull@localhost>
Sun, 4 Apr 1999 21:26:36 +0000 (21:26 +0000)
clustered at the end

CVS patchset: 2943
CVS date: 1999/04/04 21:26:36

lib/depends.c
lib/depends.h
lib/transaction.c

index fd8eb27..97c4816 100644 (file)
@@ -5,13 +5,19 @@
 #include "depends.h"
 #include "misc.h"
 
+struct orderListIndex {
+    int alIndex;
+    int orIndex;
+};
+
+static int orderListIndexCmp(const void * one, const void * two);
 static void alMakeIndex(struct availableList * al);
 static void alCreate(struct availableList * al);
 static void alFreeIndex(struct availableList * al);
 static void alFree(struct availableList * al);
-static void alAddPackage(struct availableList * al, Header h, const void * key,
-                        FD_t fd, rpmRelocation * relocs);
-
+static struct availablePackage * alAddPackage(struct availableList * al, 
+                                             Header h, const void * key,
+                                             FD_t fd, rpmRelocation * relocs);
 static int intcmp(const void * a, const void *b);
 static int indexcmp(const void * a, const void *b);
 static int unsatisfiedDepend(rpmTransactionSet rpmdep, char * reqName, 
@@ -32,9 +38,10 @@ static int checkPackageSet(rpmTransactionSet rpmdep, struct problemsSet * psp,
                            char * package, dbiIndexSet * matches);
 static int addOrderedPack(rpmTransactionSet rpmdep, 
                        struct availablePackage * package,
-                       struct availablePackage * ordering, int * orderNumPtr, 
+                       int * ordering, int * orderNumPtr, 
                        int * selected, int selectionClass,
                        int satisfyDepends, char ** errorStack);
+static void removePackage(rpmTransactionSet rpmdep, int dboffset, int depends);
 
 static void alCreate(struct availableList * al) {
     al->list = malloc(sizeof(*al->list) * 5);
@@ -69,8 +76,9 @@ static void alFree(struct availableList * al) {
     alFreeIndex(al);
 }
 
-static void alAddPackage(struct availableList * al, Header h, const void * key,
-                        FD_t fd, rpmRelocation * relocs) {
+static struct availablePackage * alAddPackage(struct availableList * al, 
+                                             Header h, const void * key,
+                                             FD_t fd, rpmRelocation * relocs) {
     struct availablePackage * p;
 
     if (al->size == al->alloced) {
@@ -112,6 +120,8 @@ static void alAddPackage(struct availableList * al, Header h, const void * key,
     p->fd = fd;
 
     alFreeIndex(al);
+
+    return p;
 }
 
 static void alMakeIndex(struct availableList * al) {
@@ -226,6 +236,10 @@ rpmTransactionSet rpmtransCreateSet(rpmdb db, const char * root) {
     alCreate(&rpmdep->addedPackages);
     alCreate(&rpmdep->availablePackages);
 
+    rpmdep->orderAlloced = 5;
+    rpmdep->orderCount = 0;
+    rpmdep->order = malloc(sizeof(*rpmdep->order) * rpmdep->orderAlloced);
+
     return rpmdep;
 }
 
@@ -236,6 +250,7 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd,
     char * name;
     int count, i, j;
     char ** obsoletes;
+    int alNum;
 
     /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
     if (headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
@@ -246,7 +261,15 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd,
        makes it difficult to generate a return code based on the number of
        packages which failed. */
    
-    alAddPackage(&rpmdep->addedPackages, h, key, fd, relocs);
+    if (rpmdep->orderCount == rpmdep->orderAlloced) {
+       rpmdep->orderAlloced += 5;
+       rpmdep->order = realloc(rpmdep->order, 
+               sizeof(*rpmdep->order) * rpmdep->orderAlloced);
+    }
+    rpmdep->order[rpmdep->orderCount].type = TR_ADDED;
+    alNum = alAddPackage(&rpmdep->addedPackages, h, key, fd, relocs) - 
+               rpmdep->addedPackages.list;
+    rpmdep->order[rpmdep->orderCount++].u.addedIndex = alNum;
 
     if (!upgrade || rpmdep->db == NULL) return 0;
 
@@ -254,7 +277,7 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd,
 
     if (!rpmdbFindPackage(rpmdep->db, name, &matches))  {
        for (i = 0; i < dbiIndexSetCount(matches); i++) {
-           rpmtransRemovePackage(rpmdep, dbiIndexRecordOffset(matches, i));
+           removePackage(rpmdep, dbiIndexRecordOffset(matches, i), alNum);
        }
 
        dbiFreeIndexRecord(matches);
@@ -265,7 +288,8 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd,
        for (j = 0; j < count; j++) {
            if (!rpmdbFindPackage(rpmdep->db, obsoletes[j], &matches))  {
                for (i = 0; i < dbiIndexSetCount(matches); i++) {
-                   rpmtransRemovePackage(rpmdep, dbiIndexRecordOffset(matches, i));
+                   removePackage(rpmdep, dbiIndexRecordOffset(matches, i),
+                                 alNum);
                }
 
                dbiFreeIndexRecord(matches);
@@ -275,14 +299,14 @@ int rpmtransAddPackage(rpmTransactionSet rpmdep, Header h, FD_t fd,
        free(obsoletes);
     }
 
-       return 0;
+    return 0;
 }
 
 void rpmtransAvailablePackage(rpmTransactionSet rpmdep, Header h, void * key) {
     alAddPackage(&rpmdep->availablePackages, h, key, NULL, NULL);
 }
 
-void rpmtransRemovePackage(rpmTransactionSet rpmdep, int dboffset) {
+static void removePackage(rpmTransactionSet rpmdep, int dboffset, int depends) {
     if (rpmdep->numRemovedPackages == rpmdep->allocedRemovedPackages) {
        rpmdep->allocedRemovedPackages += 5;
        rpmdep->removedPackages = realloc(rpmdep->removedPackages,
@@ -290,6 +314,20 @@ void rpmtransRemovePackage(rpmTransactionSet rpmdep, int dboffset) {
     }
 
     rpmdep->removedPackages[rpmdep->numRemovedPackages++] = dboffset;
+
+    if (rpmdep->orderCount == rpmdep->orderAlloced) {
+       rpmdep->orderAlloced += 5;
+       rpmdep->order = realloc(rpmdep->order, 
+               sizeof(*rpmdep->order) * rpmdep->orderAlloced);
+    }
+
+    rpmdep->order[rpmdep->orderCount].type = TR_REMOVED;
+    rpmdep->order[rpmdep->orderCount].u.removed.dboffset = dboffset;
+    rpmdep->order[rpmdep->orderCount++].u.removed.dependsOnIndex = depends;
+}
+
+void rpmtransRemovePackage(rpmTransactionSet rpmdep, int dboffset) {
+    removePackage(rpmdep, dboffset, -1);
 }
 
 void rpmtransFree(rpmTransactionSet rpmdep) {
@@ -789,7 +827,7 @@ static int dbrecMatchesDepFlags(rpmTransactionSet rpmdep, int recOffset,
 
 static int addOrderedPack(rpmTransactionSet rpmdep, 
                        struct availablePackage * package,
-                       struct availablePackage * ordering, int * orderNumPtr, 
+                       int * ordering, int * orderNumPtr, 
                        int * selected, int selectionClass,
                        int satisfyDepends, char ** errorStack) {
     char ** requires, ** requiresVersion;
@@ -870,18 +908,21 @@ static int addOrderedPack(rpmTransactionSet rpmdep,
     }
 
     /* whew -- add this package */
-    ordering[(*orderNumPtr)++] = *package;
+    ordering[(*orderNumPtr)++] = packageNum;
     selected[packageNum] = -1;
 
     return 0;
 }
 
 int rpmdepOrder(rpmTransactionSet rpmdep) {
-    int i;
+    int i, j;
     int * selected;
-    struct availablePackage * order;
-    int orderNum;
+    int * ordering;
+    int orderingCount;
     char ** errorStack;
+    struct transactionElement * newOrder;
+    int newOrderCount = 0;
+    struct orderListIndex * orderList, * needle, key;
 
     alMakeIndex(&rpmdep->addedPackages);
     alMakeIndex(&rpmdep->availablePackages);
@@ -892,21 +933,76 @@ int rpmdepOrder(rpmTransactionSet rpmdep) {
     errorStack = alloca(sizeof(*errorStack) * (rpmdep->addedPackages.size + 1));
     *errorStack++ = NULL;
 
-    order = malloc(sizeof(*order) * (rpmdep->addedPackages.size + 1));
-    orderNum = 0;
+    ordering = alloca(sizeof(*ordering) * (rpmdep->addedPackages.size + 1));
+    orderingCount = 0;
 
     for (i = 0; i < rpmdep->addedPackages.size; i++) {
        if (!selected[i]) {
            if (addOrderedPack(rpmdep, rpmdep->addedPackages.list + i,
-                              order, &orderNum, selected, 1, 0, errorStack)) {
-               free(order);
+                              ordering, &orderingCount, selected, 1, 0, 
+                              errorStack)) {
+               free(ordering);
                return 1;
            }
        }
     }
 
-    free(rpmdep->addedPackages.list);
-    rpmdep->addedPackages.list = order;
+    /* The order ends up as installed packages followed by removed packages,
+       with removes for upgrades immediately follwing the installation of
+       the new package. This would be easier if we could sort the 
+       addedPackages array, but we store indexes into it in various places. */
+    orderList = malloc(sizeof(*orderList) * rpmdep->addedPackages.size);
+    for (i = 0, j = 0; i < rpmdep->orderCount; i++) {
+       if (rpmdep->order[i].type == TR_ADDED) {
+           orderList[j].alIndex = rpmdep->order[i].u.addedIndex;
+           orderList[j].orIndex = i;
+           j++;
+       }
+    }
+    qsort(orderList, rpmdep->addedPackages.size, sizeof(*orderList), 
+         orderListIndexCmp);
+
+    newOrder = malloc(sizeof(*newOrder) * rpmdep->orderCount);
+    for (i = 0, newOrderCount = 0; i < orderingCount; i++) {
+       key.alIndex = ordering[i];
+       needle = bsearch(&key, orderList, rpmdep->addedPackages.size,
+                        sizeof(key), orderListIndexCmp);
+       /* bsearch should never, ever fail */
+       
+       newOrder[newOrderCount++] = rpmdep->order[needle->orIndex];
+       for (j = needle->orIndex + 1; j < rpmdep->orderCount; j++) {
+           if (rpmdep->order[j].type == TR_REMOVED &&
+               rpmdep->order[j].u.removed.dependsOnIndex == needle->alIndex) {
+               newOrder[newOrderCount++] = rpmdep->order[j];
+           } else {
+               break;
+           }
+       }
+    }
+
+    for (i = 0; i < rpmdep->orderCount; i++) {
+       if (rpmdep->order[i].type == TR_REMOVED && 
+           rpmdep->order[i].u.removed.dependsOnIndex == -1)  {
+           newOrder[newOrderCount++] = rpmdep->order[i];
+       }
+    }
+
+    free(rpmdep->order);
+    rpmdep->order = newOrder;
+    rpmdep->orderAlloced = rpmdep->orderCount;
+    free(orderList);
+
+    return 0;
+}
+
+static int orderListIndexCmp(const void * one, const void * two) {
+    const struct orderListIndex * a = one;
+    const struct orderListIndex * b = two;
+
+    if (a->alIndex < b->alIndex)
+       return -1;
+    if (a->alIndex > b->alIndex)
+       return 1;
 
     return 0;
 }
index a0ae634..1831cca 100644 (file)
@@ -35,11 +35,24 @@ struct availableList {
     int size, alloced;
 };
 
+struct transactionElement {
+    enum rpmTransactionType { TR_ADDED, TR_REMOVED } type;
+    union { 
+       int addedIndex;
+       struct {
+           int dboffset;
+           int dependsOnIndex;
+       } removed;
+    } u;
+};
+
 struct rpmTransactionSet_s {
     rpmdb db;                                  /* may be NULL */
     int * removedPackages;
     int numRemovedPackages, allocedRemovedPackages;
     struct availableList addedPackages, availablePackages;
+    struct transactionElement * order;
+    int orderCount, orderAlloced;
     char * root;
     FD_t scriptFd;
 };
index 111a972..e27bac0 100644 (file)
@@ -28,7 +28,7 @@
 
 struct fileInfo {
   /* for all packages */
-    enum fileInfo_e { ADDED, REMOVED } type;
+    enum rpmTransactionType type;
     enum fileActions * actions;
     fingerPrint * fps;
     uint_32 * fflags, * fsizes;
@@ -37,14 +37,14 @@ struct fileInfo {
     uint_16 * fmodes;
     Header h;
     int fc;
-  /* these are for ADDED packages */
+    char * fstates;
+  /* these are for TR_ADDED packages */
     char ** flinks;
     struct availablePackage * ap;
     struct sharedFileInfo * replaced;
     uint_32 * replacedSizes;
-  /* for REMOVED packages */
+  /* for TR_REMOVED packages */
     unsigned int record;
-    char * fstates;
 };
 
 struct diskspaceInfo {
@@ -114,7 +114,7 @@ static void freeFi(struct fileInfo *fi)
            free(fi->fmd5s); fi->fmd5s = NULL;
        }
 
-       if (fi->type == REMOVED) {
+       if (fi->type == TR_REMOVED) {
            if (fi->fsizes) {
                free(fi->fsizes); fi->fsizes = NULL;
            }
@@ -132,17 +132,10 @@ static void freeFi(struct fileInfo *fi)
 
 static void freeFl(rpmTransactionSet ts, struct fileInfo *flList)
 {
-    struct availableList * al = &ts->addedPackages;
-    struct availablePackage * alp;
     struct fileInfo *fi;
-    int i;
+    int oc;
 
-    for (alp = al->list, fi = flList; (alp - al->list) < al->size; 
-                       alp++, fi++) {
-       freeFi(fi);
-    }
-
-    for (i = 0; i < ts->numRemovedPackages; i++, fi++) {
+    for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
        freeFi(fi);
     }
 }
@@ -155,10 +148,8 @@ static void freeFl(rpmTransactionSet ts, struct fileInfo *flList)
    happened */
 int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
                       void * notifyData, rpmProblemSet okProbs,
-                      rpmProblemSet * newProbs, int flags, int ignoreSet)
-{
+                      rpmProblemSet * newProbs, int flags, int ignoreSet) {
     int i, j;
-    struct availableList * al = &ts->addedPackages;
     int rc, ourrc = 0;
     struct availablePackage * alp;
     rpmProblemSet probs;
@@ -172,12 +163,14 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
     int numShared;
     int flEntries;
     int last;
+    int lastFailed;
     int beingRemoved;
     char * currDir, * chptr;
     FD_t fd;
     const char ** filesystems;
     int filesystemCount;
     struct diskspaceInfo * di = NULL;
+    int oc;
 
     /* FIXME: what if the same package is included in ts twice? */
 
@@ -206,9 +199,11 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
 
     probs = psCreate();
     *newProbs = probs;
-    hdrs = alloca(sizeof(*hdrs) * al->size);
+    hdrs = alloca(sizeof(*hdrs) * ts->addedPackages.size);
 
-    for (alp = al->list; (alp - al->list) < al->size; alp++) {
+    /* The ordering doesn't matter here */
+    for (alp = ts->addedPackages.list; (alp - ts->addedPackages.list) < 
+           ts->addedPackages.size; alp++) {
        if (!archOkay(alp->h) && !(ignoreSet & RPMPROB_FILTER_IGNOREARCH))
            psAppend(probs, RPMPROB_BADARCH, alp->key, alp->h, NULL, NULL, 0);
 
@@ -244,6 +239,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
     }
 
     /* FIXME: it seems a bit silly to read in all of these headers twice */
+    /* The ordering doesn't matter here */
     for (i = 0; i < ts->numRemovedPackages; i++) {
        Header h;
 
@@ -255,7 +251,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
        }
     }
 
-    flEntries = al->size + ts->numRemovedPackages;
+    flEntries = ts->addedPackages.size + ts->numRemovedPackages;
     flList = alloca(sizeof(*flList) * (flEntries));
 
     ht = htCreate(totalFileCount * 2, 0, fpHashFunction, fpEqual);
@@ -263,24 +259,46 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
     /* FIXME?: we'd be better off assembling one very large file list and
        calling fpLookupList only once. I'm not sure that the speedup is
        worth the trouble though. */
-    for (fi = flList, alp = al->list; (alp - al->list) < al->size; 
-               fi++, alp++) {
+    for (fi = flList, oc = 0; oc < ts->orderCount; fi++, oc++) {
        memset(fi, 0, sizeof(*fi));
 
-       if (!headerGetEntryMinMemory(alp->h, RPMTAG_FILENAMES, NULL, 
-                                    (void *) NULL, &fi->fc)) {
-           fi->h = headerLink(alp->h);
-           hdrs[alp - al->list] = headerLink(fi->h);
-           continue;
+       if (ts->order[oc].type == TR_ADDED) {
+           i = ts->order[oc].u.addedIndex;
+           alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
+
+           if (!headerGetEntryMinMemory(alp->h, RPMTAG_FILENAMES, NULL, 
+                                        (void *) NULL, &fi->fc)) {
+               fi->h = headerLink(alp->h);
+               hdrs[i] = headerLink(fi->h);
+               continue;
+           }
+
+           fi->actions = calloc(sizeof(*fi->actions), fi->fc);
+           hdrs[i] = relocateFileList(alp, probs, alp->h, fi->actions, 
+                                 ignoreSet & RPMPROB_FILTER_FORCERELOCATE);
+           fi->h = headerLink(hdrs[i]);
+           fi->type = TR_ADDED;
+           fi->ap = alp;
+       } else {
+           fi->record = ts->order[oc].u.removed.dboffset;
+           fi->h = rpmdbGetRecord(ts->db, fi->record);
+           if (!fi->h) {
+               /* ACK! */
+               continue;
+           }
+           fi->type = TR_REMOVED;
        }
 
-       fi->actions = calloc(sizeof(*fi->actions), fi->fc);
-       hdrs[alp - al->list] = relocateFileList(alp, probs, alp->h, 
-                fi->actions, ignoreSet & RPMPROB_FILTER_FORCERELOCATE);
-       fi->h = headerLink(hdrs[alp - al->list]);
+       if (!headerGetEntry(fi->h, RPMTAG_FILENAMES, NULL, 
+                                    (void *) &fi->fl, &fi->fc)) {
+           /* This catches removed packages w/ no file lists */
+           fi->fc = 0;
+           continue;
+       }
 
-       headerGetEntryMinMemory(fi->h, RPMTAG_FILENAMES, NULL, 
-                                    (void *) &fi->fl, &fi->fc);
+       /* actions is initialized earlier for added packages */
+       if (!fi->actions) 
+           fi->actions = calloc(sizeof(*fi->actions), fi->fc);
 
        headerGetEntryMinMemory(fi->h, RPMTAG_FILEMD5S, NULL, 
                                (void *) &fi->fmd5s, NULL);
@@ -292,59 +310,29 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
                                (void *) &fi->fflags, NULL);
        headerGetEntryMinMemory(fi->h, RPMTAG_FILESIZES, NULL, 
                                (void *) &fi->fsizes, NULL);
+       headerGetEntryMinMemory(fi->h, RPMTAG_FILESTATES, NULL, 
+                               (void *) &fi->fstates, NULL);
 
-       /* 0 makes for noops */
-       fi->replacedSizes = calloc(fi->fc, sizeof(*fi->replacedSizes));
-
-       skipFiles(fi, flags & RPMTRANS_FLAG_NODOCS);
-
-       fi->type = ADDED;
-        fi->fps = malloc(fi->fc * sizeof(*fi->fps));
-       fi->ap = alp;
-    }
-
-    for (i = 0; i < ts->numRemovedPackages; i++, fi++) {
-       memset(fi, 0, sizeof(*fi));
-
-       fi->type = REMOVED;
-       fi->record = ts->removedPackages[i];
-       fi->h = rpmdbGetRecord(ts->db, fi->record);
-       if (!fi->h) {
-           /* ACK! */
-           continue;
-       }
+       if (ts->order[oc].type == TR_REMOVED) {
+           fi->fsizes = memcpy(malloc(fi->fc * sizeof(*fi->fsizes)),
+                               fi->fsizes, fi->fc * sizeof(*fi->fsizes));
+           fi->fflags = memcpy(malloc(fi->fc * sizeof(*fi->fflags)),
+                               fi->fflags, fi->fc * sizeof(*fi->fflags));
+           fi->fmodes = memcpy(malloc(fi->fc * sizeof(*fi->fmodes)),
+                               fi->fmodes, fi->fc * sizeof(*fi->fmodes));
+           fi->fstates = memcpy(malloc(fi->fc * sizeof(*fi->fstates)),
+                               fi->fstates, fi->fc * sizeof(*fi->fstates));
+           headerFree(fi->h);
+           fi->h = NULL;
+       } else {
+           /* ADDED package */
 
-       if (!headerGetEntry(fi->h, RPMTAG_FILENAMES, NULL, 
-                                    (void *) &fi->fl, &fi->fc)) {
-           fi->fc = 0;
-           continue;
+           /* 0 makes for noops */
+           fi->replacedSizes = calloc(fi->fc, sizeof(*fi->replacedSizes));
+           skipFiles(fi, flags & RPMTRANS_FLAG_NODOCS);
        }
-       headerGetEntry(fi->h, RPMTAG_FILESIZES, NULL, 
-                               (void *) &fi->fsizes, NULL);
-       fi->fsizes = memcpy(malloc(fi->fc * sizeof(*fi->fsizes)),
-                           fi->fsizes, fi->fc * sizeof(*fi->fsizes));
-       headerGetEntry(fi->h, RPMTAG_FILEFLAGS, NULL, 
-                               (void *) &fi->fflags, NULL);
-       fi->fflags = memcpy(malloc(fi->fc * sizeof(*fi->fflags)),
-                           fi->fflags, fi->fc * sizeof(*fi->fflags));
-       headerGetEntry(fi->h, RPMTAG_FILEMD5S, NULL, 
-                               (void *) &fi->fmd5s, NULL);
 
-       headerGetEntry(fi->h, RPMTAG_FILEMODES, NULL, 
-                               (void *) &fi->fmodes, NULL);
-       fi->fmodes = memcpy(malloc(fi->fc * sizeof(*fi->fmodes)),
-                           fi->fmodes, fi->fc * sizeof(*fi->fmodes));
-       headerGetEntry(fi->h, RPMTAG_FILESTATES, NULL, 
-                               (void *) &fi->fstates, NULL);
-       fi->fstates = memcpy(malloc(fi->fc * sizeof(*fi->fstates)),
-                           fi->fstates, fi->fc * sizeof(*fi->fstates));
-
-       /* Note that as FA_UNKNOWN = 0, this does the right thing */
-       fi->actions = calloc(sizeof(*fi->actions), fi->fc);
         fi->fps = malloc(fi->fc * sizeof(*fi->fps));
-
-       headerFree(fi->h);
-       fi->h = NULL;
     }
 
     chptr = currentDirectory();
@@ -404,13 +392,13 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
            }
            beingRemoved = (j < ts->numRemovedPackages);
 
-           if (fi->type == ADDED)
+           if (fi->type == TR_ADDED)
                handleInstInstalledFiles(fi, ts->db, sharedList + i, 
                         last - i + 1, 
                         !(beingRemoved || 
                                (ignoreSet & RPMPROB_FILTER_REPLACEOLDFILES)), 
                         probs);
-           else if (fi->type == REMOVED && !beingRemoved)
+           else if (fi->type == TR_REMOVED && !beingRemoved)
                handleRmvdInstalledFiles(fi, ts->db, sharedList + i, 
                                         last - i + 1);
 
@@ -422,7 +410,7 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
        handleOverlappedFiles(fi, ht, 
               (ignoreSet & RPMPROB_FILTER_REPLACENEWFILES) ? NULL : probs, di);
 
-       if (di && fi->type == ADDED) {
+       if (di && fi->type == TR_ADDED) {
            for (i = 0; i < filesystemCount; i++) {
                if (di[i].needed > di[i].avail) {
                    psAppend(probs, RPMPROB_DISKSPACE, fi->ap->key, fi->ap->h,
@@ -440,11 +428,10 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
 
     htFree(ht);
 
-    for (alp = al->list, fi = flList; (alp - al->list) < al->size; 
-               alp++, fi++) {
+    for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
        if (fi->fc) {
            free(fi->fl); fi->fl = NULL;
-           if (fi->type == ADDED) {
+           if (fi->type == TR_ADDED) {
                free(fi->fmd5s); fi->fmd5s = NULL;
                free(fi->flinks); fi->flinks = NULL;
                free(fi->fps); fi->fps = NULL;
@@ -456,81 +443,72 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify,
            (probs->numProblems && (!okProbs || psTrim(okProbs, probs)))) {
        *newProbs = probs;
 
-       for (alp = al->list, fi = flList; (alp - al->list) < al->size
-                       alp++, fi++) {
-           headerFree(hdrs[alp - al->list]);
-           freeFi(fi); /* XXX ==> LEAK */
+       for (alp = ts->addedPackages.list, fi = flList
+               (alp - ts->addedPackages.list) < ts->addedPackages.size; 
+               alp++, fi++) {
+           headerFree(hdrs[alp - ts->addedPackages.list]);
        }
 
-       freeFl(ts, flList);     /* XXX ==> LEAK */
-       return al->size + ts->numRemovedPackages;
+       freeFl(ts, flList);
+       return ts->orderCount;
     }
 
-    NOTIFY((NULL, RPMCALLBACK_TRANS_START, 9, al->size, NULL, notifyData));
-
-    for (alp = al->list, fi = flList; (alp - al->list) < al->size; 
-                       alp++, fi++) {
-       if (alp->fd) {
-           fd = alp->fd;
-       } else {
-           fd = notify(fi->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, 
-                       alp->key, notifyData);
-           if (fd) {
-               Header h;
+    lastFailed = -2;
+    for (oc = 0, fi = flList; oc < ts->orderCount; oc++, fi++) {
+       if (ts->order[oc].type == TR_ADDED) {
+           alp = ts->addedPackages.list + ts->order[oc].u.addedIndex;
+           i = ts->order[oc].u.addedIndex;
 
-               headerFree(hdrs[alp - al->list]);
-               rc = rpmReadPackageHeader(fd, &h, NULL, NULL, NULL);
-               if (rc) {
-                   notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, 
-                               alp->key, notifyData);
-                   ourrc++;
-                   fd = NULL;
-               } else {
-                   hdrs[alp - al->list] = 
-                       relocateFileList(alp, probs, h, NULL, 1);
-                   headerFree(h);
+           if (alp->fd) {
+               fd = alp->fd;
+           } else {
+               fd = notify(fi->h, RPMCALLBACK_INST_OPEN_FILE, 0, 0, 
+                           alp->key, notifyData);
+               if (fd) {
+                   Header h;
+
+                   headerFree(hdrs[i]);
+                   rc = rpmReadPackageHeader(fd, &h, NULL, NULL, NULL);
+                   if (rc) {
+                       notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, 
+                                   alp->key, notifyData);
+                       ourrc++;
+                       fd = NULL;
+                   } else {
+                       hdrs[i] = relocateFileList(alp, probs, h, NULL, 1);
+                       headerFree(h);
+                   }
                }
            }
-       }
 
-       if (fd) {
-           if (installBinaryPackage(ts->root, ts->db, fd, 
-                                    hdrs[alp - al->list], flags, notify, 
-                                    notifyData, alp->key, fi->actions, 
-                                    fi->fc ? fi->replaced : NULL,
-                                    ts->scriptFd))
+           if (fd) {
+               if (installBinaryPackage(ts->root, ts->db, fd, 
+                                        hdrs[i], flags, notify, 
+                                        notifyData, alp->key, fi->actions, 
+                                        fi->fc ? fi->replaced : NULL,
+                                        ts->scriptFd)) {
+                   ourrc++;
+                   lastFailed = i;
+               }
+           } else {
                ourrc++;
-       } else {
-           ourrc++;
-       }
+               lastFailed = i;
+           }
 
-       headerFree(hdrs[alp - al->list]);
+           headerFree(hdrs[i]);
 
-       if (!alp->fd && fd)
-           notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, alp->key, 
+           if (!alp->fd && fd)
+               notify(fi->h, RPMCALLBACK_INST_CLOSE_FILE, 0, 0, alp->key, 
                   notifyData);
-    }
-    NOTIFY((NULL, RPMCALLBACK_TRANS_STOP, 9, al->size, NULL, notifyData));
-
-    NOTIFY((NULL, RPMCALLBACK_UNINST_START, 0, ts->numRemovedPackages,
-           NULL, notifyData));
-
-    /* fi is left at the first package which is to be removed */
-    for (i = 0; i < ts->numRemovedPackages; i++, fi++) {
-       
-    NOTIFY((fi->h, RPMCALLBACK_UNINST_PROGRESS, i, ts->numRemovedPackages,
-       NULL, notifyData));
+       } else if (ts->order[oc].u.removed.dependsOnIndex != lastFailed) {
+           if (removeBinaryPackage(ts->root, ts->db, fi->record,
+                                   flags, fi->actions, ts->scriptFd))
 
-       if (removeBinaryPackage(ts->root, ts->db, ts->removedPackages[i], 
-                               flags, fi->actions, ts->scriptFd))
-
-           ourrc++;
+               ourrc++;
+       }
     }
 
-    NOTIFY((NULL, RPMCALLBACK_UNINST_STOP, 0, ts->numRemovedPackages,
-       NULL, notifyData));
-
-    freeFl(ts, flList);        /* XXX ==> LEAK */
+    freeFl(ts, flList);
 
     if (ourrc) 
        return -1;
@@ -1096,7 +1074,7 @@ void handleOverlappedFiles(struct fileInfo * fi, hashTable ht,
        otherPkgNum = j - 1;
        otherFileNum = -1;                      /* keep gcc quiet */
        while (otherPkgNum >= 0) {
-           if (recs[otherPkgNum]->type == ADDED) {
+           if (recs[otherPkgNum]->type == TR_ADDED) {
                /* TESTME: there are more efficient searches in the world... */
                for (otherFileNum = 0; otherFileNum < recs[otherPkgNum]->fc; 
                     otherFileNum++)
@@ -1110,7 +1088,7 @@ void handleOverlappedFiles(struct fileInfo * fi, hashTable ht,
            otherPkgNum--;
        }
 
-       if (fi->type == ADDED && otherPkgNum < 0) {
+       if (fi->type == TR_ADDED && otherPkgNum < 0) {
            if (fi->actions[i] == FA_UNKNOWN) {
                if ((fi->fflags[i] & RPMFILE_CONFIG) && 
                            !lstat(fi->fl[i], &sb))
@@ -1118,7 +1096,7 @@ void handleOverlappedFiles(struct fileInfo * fi, hashTable ht,
                else
                    fi->actions[i] = FA_CREATE;
            }
-       } else if (fi->type == ADDED) {
+       } else if (fi->type == TR_ADDED) {
            if (probs && filecmp(recs[otherPkgNum]->fmodes[otherFileNum],
                        recs[otherPkgNum]->fmd5s[otherFileNum],
                        recs[otherPkgNum]->flinks[otherFileNum],
@@ -1135,9 +1113,9 @@ void handleOverlappedFiles(struct fileInfo * fi, hashTable ht,
               file handling choice we already made, which may very
               well be exactly right. What about noreplace files?? */
            fi->actions[i] = FA_CREATE;
-       } else if (fi->type == REMOVED && otherPkgNum >= 0) {
+       } else if (fi->type == TR_REMOVED && otherPkgNum >= 0) {
            fi->actions[i] = FA_SKIP;
-       } else if (fi->type == REMOVED) {
+       } else if (fi->type == TR_REMOVED) {
            if (fi->actions[i] != FA_SKIP && fi->actions[i] != FA_SKIPNSTATE &&
                        fi->fstates[i] == RPMFILE_STATE_NORMAL ) {
                if (S_ISREG(fi->fmodes[i]) &&