Reimplement rpmal by using hashes and cleaning up the color handling
This commit is contained in:
parent
3e37044eb9
commit
3a6f3133a1
|
@ -209,7 +209,7 @@ int rpmtsAddInstallElement(rpmts ts, Header h,
|
|||
(pkgNEVR ? pkgNEVR + 2 : "?pkgNEVR?"),
|
||||
(addNEVR ? addNEVR + 2 : "?addNEVR?"));
|
||||
duplicate = 1;
|
||||
rpmalDel(&ts->addedPackages, p);
|
||||
rpmalDel(ts->addedPackages, p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ addheader:
|
|||
rpmcliPackagesTotal++;
|
||||
}
|
||||
|
||||
rpmalAdd(&ts->addedPackages, p, tscolor);
|
||||
rpmalAdd(ts->addedPackages, p);
|
||||
|
||||
if (!duplicate) {
|
||||
ts->numAddedPackages++;
|
||||
|
@ -893,7 +893,6 @@ static inline int addRelation(rpmts ts,
|
|||
tsortInfo tsi;
|
||||
const char * Name;
|
||||
int teType = rpmteType(p);
|
||||
int i = 0;
|
||||
|
||||
if ((Name = rpmdsN(requires)) == NULL)
|
||||
return 0;
|
||||
|
@ -1019,7 +1018,7 @@ int rpmtsOrder(rpmts ts)
|
|||
int breadth;
|
||||
int qlen;
|
||||
int rc;
|
||||
rpmal erasedPackages = rpmalCreate(5);
|
||||
rpmal erasedPackages = rpmalCreate(5, rpmtsColor(ts));
|
||||
|
||||
(void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_ORDER), 0);
|
||||
|
||||
|
@ -1031,9 +1030,8 @@ int rpmtsOrder(rpmts ts)
|
|||
|
||||
/* Create erased package index. */
|
||||
pi = rpmtsiInit(ts);
|
||||
rpm_color_t tscolor = rpmtsColor(ts);
|
||||
while ((p = rpmtsiNext(pi, TR_REMOVED)) != NULL) {
|
||||
rpmalAdd(&erasedPackages, p, tscolor);
|
||||
rpmalAdd(erasedPackages, p);
|
||||
}
|
||||
pi = rpmtsiFree(pi);
|
||||
rpmalMakeIndex(erasedPackages);
|
||||
|
|
678
lib/rpmal.c
678
lib/rpmal.c
|
@ -9,6 +9,7 @@
|
|||
#include <rpm/rpmds.h>
|
||||
#include <rpm/rpmte.h>
|
||||
#include <rpm/rpmfi.h>
|
||||
#include "rpmhash.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -25,10 +26,7 @@ struct availablePackage_s {
|
|||
rpmte p; /*!< transaction member */
|
||||
rpmds provides; /*!< Provides: dependencies. */
|
||||
rpmfi fi; /*!< File info set. */
|
||||
rpm_color_t tscolor; /*!< Transaction color bits. */
|
||||
|
||||
fnpyKey key; /*!< Associated file name/python object */
|
||||
|
||||
};
|
||||
|
||||
typedef struct availableIndexEntry_s * availableIndexEntry;
|
||||
|
@ -38,61 +36,56 @@ typedef struct availableIndexEntry_s * availableIndexEntry;
|
|||
*/
|
||||
struct availableIndexEntry_s {
|
||||
rpmalNum pkgNum; /*!< Containing package index. */
|
||||
const char * entry; /*!< Dependency name. */
|
||||
unsigned short entryLen; /*!< No. of bytes in name. */
|
||||
unsigned short entryIx; /*!< Dependency index. */
|
||||
enum indexEntryType {
|
||||
IET_PROVIDES=1 /*!< A Provides: dependency. */
|
||||
} type; /*!< Type of available item. */
|
||||
unsigned int entryIx; /*!< Dependency index. */
|
||||
};
|
||||
|
||||
typedef struct availableIndex_s * availableIndex;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* Index of all available items.
|
||||
*/
|
||||
struct availableIndex_s {
|
||||
availableIndexEntry index; /*!< Array of available items. */
|
||||
int size; /*!< No. of available items. */
|
||||
int k; /*!< Current index. */
|
||||
struct fileNameEntry_s {
|
||||
const char * dirName;
|
||||
const char * baseName;
|
||||
};
|
||||
|
||||
typedef struct fileIndexEntry_s * fileIndexEntry;
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A file to be installed/removed.
|
||||
*/
|
||||
typedef struct fileIndexEntry_s * fileIndex;
|
||||
|
||||
struct fileIndexEntry_s {
|
||||
const char * baseName; /*!< File basename. */
|
||||
int baseNameLen;
|
||||
rpmalNum pkgNum; /*!< Containing package index. */
|
||||
rpm_color_t ficolor;
|
||||
unsigned int entryIx;
|
||||
};
|
||||
|
||||
typedef struct dirInfo_s * dirInfo;
|
||||
#undef HASHTYPE
|
||||
#undef HTKEYTYPE
|
||||
#undef HTDATATYPE
|
||||
#define HASHTYPE rpmalProvidesHash
|
||||
#define HTKEYTYPE const char *
|
||||
#define HTDATATYPE struct availableIndexEntry_s
|
||||
#include "lib/rpmhash.H"
|
||||
#include "lib/rpmhash.C"
|
||||
|
||||
#undef HASHTYPE
|
||||
#undef HTKEYTYPE
|
||||
#undef HTDATATYPE
|
||||
#define HASHTYPE rpmalFileHash
|
||||
#define HTKEYTYPE struct fileNameEntry_s
|
||||
#define HTDATATYPE struct fileIndexEntry_s
|
||||
#include "lib/rpmhash.H"
|
||||
#include "lib/rpmhash.C"
|
||||
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* A directory to be installed/removed.
|
||||
*/
|
||||
struct dirInfo_s {
|
||||
char * dirName; /*!< Directory path (+ trailing '/'). */
|
||||
int dirNameLen; /*!< No. bytes in directory path. */
|
||||
fileIndexEntry files; /*!< Array of files in directory. */
|
||||
int numFiles; /*!< No. files in directory. */
|
||||
};
|
||||
|
||||
/** \ingroup rpmdep
|
||||
* Set of available packages, items, and directories.
|
||||
*/
|
||||
struct rpmal_s {
|
||||
availablePackage list; /*!< Set of packages. */
|
||||
struct availableIndex_s index; /*!< Set of available items. */
|
||||
rpmalProvidesHash providesHash;
|
||||
rpmalFileHash fileHash;
|
||||
int delta; /*!< Delta for pkg list reallocation. */
|
||||
int size; /*!< No. of pkgs in list. */
|
||||
int alloced; /*!< No. of pkgs allocated for list. */
|
||||
rpm_color_t tscolor; /*!< Transaction color. */
|
||||
int numDirs; /*!< No. of directories. */
|
||||
dirInfo dirs; /*!< Set of directories. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -101,35 +94,29 @@ struct rpmal_s {
|
|||
*/
|
||||
static void rpmalFreeIndex(rpmal al)
|
||||
{
|
||||
availableIndex ai = &al->index;
|
||||
if (ai->size > 0) {
|
||||
ai->index = _free(ai->index);
|
||||
ai->size = 0;
|
||||
}
|
||||
al->providesHash = rpmalProvidesHashFree(al->providesHash);
|
||||
al->fileHash = rpmalFileHashFree(al->fileHash);
|
||||
}
|
||||
|
||||
rpmal rpmalCreate(int delta)
|
||||
rpmal rpmalCreate(int delta, rpm_color_t tscolor)
|
||||
{
|
||||
rpmal al = xcalloc(1, sizeof(*al));
|
||||
availableIndex ai = &al->index;
|
||||
|
||||
al->delta = delta;
|
||||
al->size = 0;
|
||||
al->list = xcalloc(al->delta, sizeof(*al->list));
|
||||
al->alloced = al->delta;
|
||||
al->list = xmalloc(sizeof(*al->list) * al->alloced);;
|
||||
|
||||
ai->index = NULL;
|
||||
ai->size = 0;
|
||||
al->providesHash = NULL;
|
||||
al->fileHash = NULL;
|
||||
al->tscolor = tscolor;
|
||||
|
||||
al->numDirs = 0;
|
||||
al->dirs = NULL;
|
||||
return al;
|
||||
}
|
||||
|
||||
rpmal rpmalFree(rpmal al)
|
||||
{
|
||||
availablePackage alp;
|
||||
dirInfo die;
|
||||
int i;
|
||||
|
||||
if (al == NULL)
|
||||
|
@ -140,80 +127,29 @@ rpmal rpmalFree(rpmal al)
|
|||
alp->provides = rpmdsFree(alp->provides);
|
||||
alp->fi = rpmfiFree(alp->fi);
|
||||
}
|
||||
|
||||
if ((die = al->dirs) != NULL)
|
||||
for (i = 0; i < al->numDirs; i++, die++) {
|
||||
die->dirName = _free(die->dirName);
|
||||
die->files = _free(die->files);
|
||||
}
|
||||
al->dirs = _free(al->dirs);
|
||||
al->numDirs = 0;
|
||||
|
||||
al->list = _free(al->list);
|
||||
al->alloced = 0;
|
||||
|
||||
rpmalFreeIndex(al);
|
||||
al = _free(al);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two directory info entries by name (qsort/bsearch).
|
||||
* @param one 1st directory info
|
||||
* @param two 2nd directory info
|
||||
* @return result of comparison
|
||||
*/
|
||||
static int dieCompare(const void * one, const void * two)
|
||||
{
|
||||
const dirInfo a = (const dirInfo) one;
|
||||
const dirInfo b = (const dirInfo) two;
|
||||
int lenchk = a->dirNameLen - b->dirNameLen;
|
||||
|
||||
if (lenchk || a->dirNameLen == 0)
|
||||
return lenchk;
|
||||
|
||||
if (a->dirName == NULL || b->dirName == NULL)
|
||||
return lenchk;
|
||||
|
||||
/* XXX FIXME: this might do "backward" strcmp for speed */
|
||||
return strcmp(a->dirName, b->dirName);
|
||||
static unsigned int fileHash(struct fileNameEntry_s file){
|
||||
return hashFunctionString(file.dirName) ^ hashFunctionString(file.baseName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two file info entries by name (qsort/bsearch).
|
||||
* @param one 1st directory info
|
||||
* @param two 2nd directory info
|
||||
* @return result of comparison
|
||||
*/
|
||||
static int fieCompare(const void * one, const void * two)
|
||||
{
|
||||
const fileIndexEntry a = (const fileIndexEntry) one;
|
||||
const fileIndexEntry b = (const fileIndexEntry) two;
|
||||
int lenchk = a->baseNameLen - b->baseNameLen;
|
||||
|
||||
if (lenchk)
|
||||
return lenchk;
|
||||
|
||||
if (a->baseName == NULL || b->baseName == NULL)
|
||||
return lenchk;
|
||||
|
||||
#ifdef NOISY
|
||||
if (_rpmal_debug) {
|
||||
fprintf(stderr, "\t\tstrcmp(%p:%p, %p:%p)", a, a->baseName, b, b->baseName);
|
||||
#if 0
|
||||
fprintf(stderr, " a %s", a->baseName);
|
||||
#endif
|
||||
fprintf(stderr, " b %s", a->baseName);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return strcmp(a->baseName, b->baseName);
|
||||
static int fileCompare(struct fileNameEntry_s one, struct fileNameEntry_s two) {
|
||||
int rc = 0;
|
||||
rc = strcmp(one.dirName, two.dirName);
|
||||
if (!rc)
|
||||
rc = strcmp(one.baseName, two.baseName);
|
||||
return rc;
|
||||
}
|
||||
|
||||
void rpmalDel(rpmal al, rpmte p)
|
||||
{
|
||||
availablePackage alp;
|
||||
rpmfi fi;
|
||||
rpmalNum pkgNum;
|
||||
|
||||
if (al == NULL || al->list == NULL)
|
||||
|
@ -228,108 +164,57 @@ void rpmalDel(rpmal al, rpmte p)
|
|||
if (pkgNum == al->size ) return; // Not found!
|
||||
|
||||
alp = al->list + pkgNum;
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "*** del %p[%d]\n", al->list, (int) pkgNum);
|
||||
|
||||
/* Delete directory/file info entries from added package list. */
|
||||
if ((fi = alp->fi) != NULL)
|
||||
if (rpmfiFC(fi) > 0) {
|
||||
int origNumDirs = al->numDirs;
|
||||
int dx;
|
||||
struct dirInfo_s dieNeedle;
|
||||
dirInfo die;
|
||||
int last;
|
||||
int i;
|
||||
|
||||
memset(&dieNeedle, 0, sizeof(dieNeedle));
|
||||
/* XXX FIXME: We ought to relocate the directory list here */
|
||||
|
||||
if (al->dirs != NULL)
|
||||
for (dx = rpmfiDC(fi) - 1; dx >= 0; dx--)
|
||||
{
|
||||
fileIndexEntry fie;
|
||||
|
||||
(void) rpmfiSetDX(fi, dx);
|
||||
|
||||
/* XXX: reference to within rpmfi, must not be freed */
|
||||
dieNeedle.dirName = (char *) rpmfiDN(fi);
|
||||
dieNeedle.dirNameLen = (dieNeedle.dirName != NULL
|
||||
? strlen(dieNeedle.dirName) : 0);
|
||||
die = bsearch(&dieNeedle, al->dirs, al->numDirs,
|
||||
sizeof(dieNeedle), dieCompare);
|
||||
if (die == NULL)
|
||||
continue;
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "--- die[%5ld] %p [%3d] %s\n", (long)(die - al->dirs), die, die->dirNameLen, die->dirName);
|
||||
|
||||
last = die->numFiles;
|
||||
fie = die->files + last - 1;
|
||||
for (i = last - 1; i >= 0; i--, fie--) {
|
||||
if (fie->pkgNum != pkgNum)
|
||||
continue;
|
||||
die->numFiles--;
|
||||
|
||||
if (i < die->numFiles) {
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "\t%p[%3d] memmove(%p:%p,%p:%p,0x%lx) %s <- %s\n", die->files, die->numFiles, fie, fie->baseName, fie+1, (fie+1)->baseName, (long)((die->numFiles - i) * sizeof(*fie)), fie->baseName, (fie+1)->baseName);
|
||||
|
||||
memmove(fie, fie+1, (die->numFiles - i) * sizeof(*fie));
|
||||
}
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "\t%p[%3d] memset(%p,0,0x%lx) %p [%3d] %s\n", die->files, die->numFiles, die->files + die->numFiles, (long) sizeof(*fie), fie->baseName, fie->baseNameLen, fie->baseName);
|
||||
memset(die->files + die->numFiles, 0, sizeof(*fie)); /* overkill */
|
||||
|
||||
}
|
||||
if (die->numFiles > 0) {
|
||||
if (last > i)
|
||||
die->files = xrealloc(die->files,
|
||||
die->numFiles * sizeof(*die->files));
|
||||
continue;
|
||||
}
|
||||
die->files = _free(die->files);
|
||||
die->dirName = _free(die->dirName);
|
||||
al->numDirs--;
|
||||
if ((die - al->dirs) < al->numDirs) {
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, " die[%5ld] memmove(%p,%p,0x%lx)\n", (long) (die - al->dirs), die, die+1, (long) ((al->numDirs - (die - al->dirs)) * sizeof(*die)));
|
||||
|
||||
memmove(die, die+1, (al->numDirs - (die - al->dirs)) * sizeof(*die));
|
||||
}
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, " die[%5d] memset(%p,0,0x%lx)\n", al->numDirs, al->dirs + al->numDirs, (long) sizeof(*die));
|
||||
memset(al->dirs + al->numDirs, 0, sizeof(*al->dirs)); /* overkill */
|
||||
}
|
||||
|
||||
if (origNumDirs > al->numDirs) {
|
||||
if (al->numDirs > 0)
|
||||
al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
|
||||
else
|
||||
al->dirs = _free(al->dirs);
|
||||
}
|
||||
}
|
||||
|
||||
alp->provides = rpmdsFree(alp->provides);
|
||||
alp->fi = rpmfiFree(alp->fi);
|
||||
|
||||
memset(alp, 0, sizeof(*alp)); /* XXX trash and burn */
|
||||
// XXX leaves empty entry that is not recovered
|
||||
return;
|
||||
// do not actually delete, just set p to NULL
|
||||
// and later filter that out of the results
|
||||
alp->p = NULL;
|
||||
}
|
||||
|
||||
void rpmalAdd(rpmal * alistp, rpmte p, rpm_color_t tscolor)
|
||||
static void rpmalAddFiles(rpmal al, rpmalNum pkgNum, rpmfi fi){
|
||||
struct fileNameEntry_s fileName;
|
||||
struct fileIndexEntry_s fileEntry;
|
||||
int i;
|
||||
rpm_color_t ficolor;
|
||||
|
||||
fileEntry.pkgNum = pkgNum;
|
||||
|
||||
fi = rpmfiInit(fi, 0);
|
||||
while ((i = rpmfiNext(fi)) >= 0) {
|
||||
/* Ignore colored provides not in our rainbow. */
|
||||
ficolor = rpmfiColor(fi);
|
||||
if (al->tscolor && ficolor && !(al->tscolor & ficolor))
|
||||
continue;
|
||||
|
||||
fileName.dirName = rpmfiDN(fi);
|
||||
fileName.baseName = rpmfiBN(fi);
|
||||
|
||||
fileEntry.entryIx = i;
|
||||
|
||||
rpmalFileHashAddEntry(al->fileHash, fileName, fileEntry);
|
||||
}
|
||||
}
|
||||
|
||||
static void rpmalAddProvides(rpmal al, rpmalNum pkgNum, rpmds provides){
|
||||
struct availableIndexEntry_s indexEntry;
|
||||
rpm_color_t dscolor;
|
||||
|
||||
indexEntry.pkgNum = pkgNum;
|
||||
|
||||
if (rpmdsInit(provides) != NULL)
|
||||
while (rpmdsNext(provides) >= 0) {
|
||||
/* Ignore colored provides not in our rainbow. */
|
||||
dscolor = rpmdsColor(provides);
|
||||
if (al->tscolor && dscolor && !(al->tscolor & dscolor))
|
||||
continue;
|
||||
|
||||
indexEntry.entryIx = rpmdsIx(provides);
|
||||
rpmalProvidesHashAddEntry(al->providesHash, rpmdsN(provides), indexEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void rpmalAdd(rpmal al, rpmte p)
|
||||
{
|
||||
rpmalNum pkgNum;
|
||||
rpmal al;
|
||||
availablePackage alp;
|
||||
rpmfi fi;
|
||||
|
||||
/* If list doesn't exist yet, create. */
|
||||
if (*alistp == NULL)
|
||||
*alistp = rpmalCreate(5);
|
||||
al = *alistp;
|
||||
|
||||
if (al->size == al->alloced) {
|
||||
al->alloced += al->delta;
|
||||
|
@ -340,338 +225,120 @@ void rpmalAdd(rpmal * alistp, rpmte p, rpm_color_t tscolor)
|
|||
alp = al->list + pkgNum;
|
||||
|
||||
alp->p = p;
|
||||
alp->tscolor = tscolor;
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "*** add %p[%d] 0x%x\n", al->list, (int) pkgNum, tscolor);
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "*** add %p[%d]\n", al->list, (int) pkgNum);
|
||||
|
||||
alp->provides = rpmdsLink(rpmteDS(p, RPMTAG_PROVIDENAME),
|
||||
RPMDBG_M("Provides (rpmalAdd)"));
|
||||
alp->fi = rpmfiLink(rpmteFI(p), RPMDBG_M("Files (rpmalAdd)"));
|
||||
|
||||
fi = rpmfiLink(alp->fi, RPMDBG_M("Files index (rpmalAdd)"));
|
||||
fi = rpmfiInit(fi, 0);
|
||||
if (rpmfiFC(fi) > 0) {
|
||||
struct dirInfo_s dieNeedle;
|
||||
dirInfo die;
|
||||
int dc = rpmfiDC(fi);
|
||||
int dx;
|
||||
int *dirMapping = xmalloc(sizeof(*dirMapping) * dc);
|
||||
int *dirUnique = xmalloc(sizeof(*dirUnique) * dc);
|
||||
const char * DN;
|
||||
int origNumDirs;
|
||||
int first;
|
||||
int i = 0;
|
||||
|
||||
memset(&dieNeedle, 0, sizeof(dieNeedle));
|
||||
/* XXX FIXME: We ought to relocate the directory list here */
|
||||
|
||||
/* XXX enough space for all directories, late realloc to truncate. */
|
||||
al->dirs = xrealloc(al->dirs, (al->numDirs + dc) * sizeof(*al->dirs));
|
||||
|
||||
/* Only previously allocated dirInfo is sorted and bsearch'able. */
|
||||
origNumDirs = al->numDirs;
|
||||
|
||||
/* Package dirnames are not currently unique. Create unique mapping. */
|
||||
for (dx = 0; dx < dc; dx++) {
|
||||
(void) rpmfiSetDX(fi, dx);
|
||||
DN = rpmfiDN(fi);
|
||||
if (DN != NULL)
|
||||
for (i = 0; i < dx; i++) {
|
||||
const char * iDN;
|
||||
(void) rpmfiSetDX(fi, i);
|
||||
iDN = rpmfiDN(fi);
|
||||
if (iDN != NULL && !strcmp(DN, iDN))
|
||||
break;
|
||||
}
|
||||
dirUnique[dx] = i;
|
||||
}
|
||||
|
||||
/* Map package dirs into transaction dirInfo index. */
|
||||
for (dx = 0; dx < dc; dx++) {
|
||||
|
||||
/* Non-unique package dirs use the 1st entry mapping. */
|
||||
if (dirUnique[dx] < dx) {
|
||||
dirMapping[dx] = dirMapping[dirUnique[dx]];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find global dirInfo mapping for first encounter. */
|
||||
(void) rpmfiSetDX(fi, dx);
|
||||
|
||||
{ DN = rpmfiDN(fi);
|
||||
|
||||
/* XXX: reference to within rpmfi, must not be freed */
|
||||
dieNeedle.dirName = (char *) DN;
|
||||
}
|
||||
|
||||
dieNeedle.dirNameLen = (dieNeedle.dirName != NULL
|
||||
? strlen(dieNeedle.dirName) : 0);
|
||||
die = bsearch(&dieNeedle, al->dirs, origNumDirs,
|
||||
sizeof(dieNeedle), dieCompare);
|
||||
if (die) {
|
||||
dirMapping[dx] = die - al->dirs;
|
||||
} else {
|
||||
dirMapping[dx] = al->numDirs;
|
||||
die = al->dirs + al->numDirs;
|
||||
if (dieNeedle.dirName != NULL)
|
||||
die->dirName = xstrdup(dieNeedle.dirName);
|
||||
die->dirNameLen = dieNeedle.dirNameLen;
|
||||
die->files = NULL;
|
||||
die->numFiles = 0;
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "+++ die[%5d] %p [%3d] %s\n", al->numDirs, die, die->dirNameLen, die->dirName);
|
||||
|
||||
al->numDirs++;
|
||||
}
|
||||
}
|
||||
|
||||
for (first = rpmfiNext(fi); first >= 0;) {
|
||||
fileIndexEntry fie;
|
||||
int next;
|
||||
|
||||
/* Find the first file of the next directory. */
|
||||
dx = rpmfiDX(fi);
|
||||
while ((next = rpmfiNext(fi)) >= 0) {
|
||||
if (dx != rpmfiDX(fi))
|
||||
break;
|
||||
}
|
||||
if (next < 0) next = rpmfiFC(fi); /* XXX reset end-of-list */
|
||||
|
||||
die = al->dirs + dirMapping[dx];
|
||||
die->files = xrealloc(die->files,
|
||||
(die->numFiles + next - first) * sizeof(*die->files));
|
||||
|
||||
fie = die->files + die->numFiles;
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, " die[%5d] %p->files [%p[%d],%p) -> [%p[%d],%p)\n", dirMapping[dx], die,
|
||||
die->files, die->numFiles, die->files+die->numFiles,
|
||||
fie, (next - first), fie + (next - first));
|
||||
|
||||
/* Rewind to first file, generate file index entry for each file. */
|
||||
fi = rpmfiInit(fi, first);
|
||||
while ((first = rpmfiNext(fi)) >= 0 && first < next) {
|
||||
fie->baseName = rpmfiBN(fi);
|
||||
fie->baseNameLen = (fie->baseName ? strlen(fie->baseName) : 0);
|
||||
fie->pkgNum = pkgNum;
|
||||
fie->ficolor = rpmfiFColor(fi);
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "\t%p[%3d] %p:%p[%2d] %s\n", die->files, die->numFiles, fie, fie->baseName, fie->baseNameLen, rpmfiFN(fi));
|
||||
|
||||
die->numFiles++;
|
||||
fie++;
|
||||
}
|
||||
qsort(die->files, die->numFiles, sizeof(*die->files), fieCompare);
|
||||
}
|
||||
|
||||
/* Resize the directory list. If any directories were added, resort. */
|
||||
al->dirs = xrealloc(al->dirs, al->numDirs * sizeof(*al->dirs));
|
||||
if (origNumDirs != al->numDirs)
|
||||
qsort(al->dirs, al->numDirs, sizeof(*al->dirs), dieCompare);
|
||||
free(dirUnique);
|
||||
free(dirMapping);
|
||||
if (al->providesHash != NULL) { // index is already created
|
||||
rpmalAddProvides(al, pkgNum, alp->provides);
|
||||
rpmalAddFiles(al, pkgNum, alp->fi);
|
||||
}
|
||||
fi = rpmfiUnlink(fi, RPMDBG_M("Files index (rpmalAdd)"));
|
||||
|
||||
rpmalFreeIndex(al);
|
||||
|
||||
assert(((rpmalNum)(alp - al->list)) == pkgNum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two available index entries by name (qsort/bsearch).
|
||||
* @param one 1st available index entry
|
||||
* @param two 2nd available index entry
|
||||
* @return result of comparison
|
||||
*/
|
||||
static int indexcmp(const void * one, const void * two)
|
||||
{
|
||||
const availableIndexEntry a = (const availableIndexEntry) one;
|
||||
const availableIndexEntry b = (const availableIndexEntry) two;
|
||||
int lenchk;
|
||||
|
||||
lenchk = a->entryLen - b->entryLen;
|
||||
if (lenchk)
|
||||
return lenchk;
|
||||
|
||||
return strcmp(a->entry, b->entry);
|
||||
}
|
||||
|
||||
static void rpmalAddProvides(rpmal al, rpmalNum pkgNum, rpmds provides, rpm_color_t tscolor)
|
||||
{
|
||||
rpm_color_t dscolor;
|
||||
const char * Name;
|
||||
availableIndex ai = &al->index;
|
||||
availableIndexEntry aie;
|
||||
int ix;
|
||||
|
||||
if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size)
|
||||
return;
|
||||
|
||||
if (rpmdsInit(provides) != NULL)
|
||||
while (rpmdsNext(provides) >= 0) {
|
||||
|
||||
if ((Name = rpmdsN(provides)) == NULL)
|
||||
continue; /* XXX can't happen */
|
||||
|
||||
/* Ignore colored provides not in our rainbow. */
|
||||
dscolor = rpmdsColor(provides);
|
||||
if (tscolor && dscolor && !(tscolor & dscolor))
|
||||
continue;
|
||||
|
||||
aie = ai->index + ai->k;
|
||||
ai->k++;
|
||||
|
||||
aie->pkgNum = pkgNum;
|
||||
aie->entry = Name;
|
||||
aie->entryLen = strlen(Name);
|
||||
ix = rpmdsIx(provides);
|
||||
|
||||
/* XXX make sure that element index fits in unsigned short */
|
||||
assert(ix < 0x10000);
|
||||
|
||||
aie->entryIx = ix;
|
||||
aie->type = IET_PROVIDES;
|
||||
}
|
||||
assert(((rpmalNum)(alp - al->list)) == pkgNum);
|
||||
}
|
||||
|
||||
void rpmalMakeIndex(rpmal al)
|
||||
{
|
||||
availableIndex ai;
|
||||
availablePackage alp;
|
||||
intptr_t i;
|
||||
int i;
|
||||
int providesCnt = 0;
|
||||
int fileCnt = 0;
|
||||
|
||||
if (al == NULL || al->list == NULL) return;
|
||||
ai = &al->index;
|
||||
|
||||
ai->size = 0;
|
||||
if (al->providesHash != NULL || al->fileHash != NULL)
|
||||
return;
|
||||
for (i = 0; i < al->size; i++) {
|
||||
alp = al->list + i;
|
||||
if (alp->provides != NULL)
|
||||
ai->size += rpmdsCount(alp->provides);
|
||||
providesCnt += rpmdsCount(alp->provides);
|
||||
if (alp->fi != NULL)
|
||||
fileCnt += rpmfiFC(alp->fi);
|
||||
}
|
||||
if (ai->size == 0) return;
|
||||
|
||||
ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index));
|
||||
ai->k = 0;
|
||||
al->providesHash = rpmalProvidesHashCreate(providesCnt/4+128, hashFunctionString,
|
||||
strcmp, NULL, NULL);
|
||||
al->fileHash = rpmalFileHashCreate(fileCnt/4+128, fileHash, fileCompare,
|
||||
NULL, NULL);
|
||||
|
||||
for (i = 0; i < al->size; i++) {
|
||||
alp = al->list + i;
|
||||
rpmalAddProvides(al, i, alp->provides, alp->tscolor);
|
||||
rpmalAddProvides(al, i, alp->provides);
|
||||
rpmalAddFiles(al, i, alp->fi);
|
||||
}
|
||||
|
||||
/* Reset size to the no. of provides added. */
|
||||
ai->size = ai->k;
|
||||
qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp);
|
||||
}
|
||||
|
||||
rpmte *
|
||||
rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds)
|
||||
{
|
||||
rpm_color_t tscolor;
|
||||
rpm_color_t ficolor;
|
||||
int found = 0;
|
||||
char * dirName;
|
||||
const char * baseName;
|
||||
struct dirInfo_s dieNeedle;
|
||||
dirInfo die;
|
||||
struct fileIndexEntry_s fieNeedle;
|
||||
fileIndexEntry fie;
|
||||
struct fileNameEntry_s fileNameEntry;
|
||||
const char * fileName;
|
||||
char * t;
|
||||
|
||||
fileIndex result;
|
||||
int resultCnt;
|
||||
int i, found;
|
||||
availablePackage alp;
|
||||
rpmte * ret = NULL;
|
||||
const char * fileName;
|
||||
/* FIX: ret is a problem */
|
||||
|
||||
memset(&dieNeedle, 0, sizeof(dieNeedle));
|
||||
memset(&fieNeedle, 0, sizeof(fieNeedle));
|
||||
|
||||
if (al == NULL || (fileName = rpmdsN(ds)) == NULL || *fileName != '/')
|
||||
return NULL;
|
||||
|
||||
/* Solaris 2.6 bsearch sucks down on this. */
|
||||
if (al->numDirs == 0 || al->dirs == NULL || al->list == NULL)
|
||||
return NULL;
|
||||
|
||||
{ char * t;
|
||||
dirName = t = xstrdup(fileName);
|
||||
if ((t = strrchr(t, '/')) != NULL) {
|
||||
t++; /* leave the trailing '/' */
|
||||
*t = '\0';
|
||||
}
|
||||
fileNameEntry.dirName = t = xstrdup(fileName);
|
||||
if ((t = strrchr(t, '/')) != NULL) {
|
||||
t++; /* leave the trailing '/' */
|
||||
*t = '\0';
|
||||
}
|
||||
if ((fileNameEntry.baseName = strrchr(fileName, '/')) == NULL)
|
||||
goto exit;
|
||||
fileNameEntry.baseName++;
|
||||
|
||||
dieNeedle.dirName = (char *) dirName;
|
||||
dieNeedle.dirNameLen = strlen(dirName);
|
||||
die = bsearch(&dieNeedle, al->dirs, al->numDirs,
|
||||
sizeof(dieNeedle), dieCompare);
|
||||
if (die == NULL)
|
||||
rpmalFileHashGetEntry(al->fileHash, fileNameEntry, &result,
|
||||
&resultCnt, NULL);
|
||||
|
||||
if (resultCnt==0)
|
||||
goto exit;
|
||||
|
||||
/* rewind to the first match */
|
||||
while (die > al->dirs && dieCompare(die-1, &dieNeedle) == 0)
|
||||
die--;
|
||||
ret = xmalloc((resultCnt+1) * sizeof(*ret));
|
||||
|
||||
if ((baseName = strrchr(fileName, '/')) == NULL)
|
||||
goto exit;
|
||||
baseName++;
|
||||
|
||||
/* FIX: ret is a problem */
|
||||
for (found = 0, ret = NULL;
|
||||
die < al->dirs + al->numDirs && dieCompare(die, &dieNeedle) == 0;
|
||||
die++)
|
||||
{
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "==> die %p %s\n", die, (die->dirName ? die->dirName : "(nil)"));
|
||||
|
||||
fieNeedle.baseName = baseName;
|
||||
fieNeedle.baseNameLen = strlen(fieNeedle.baseName);
|
||||
fie = bsearch(&fieNeedle, die->files, die->numFiles,
|
||||
sizeof(fieNeedle), fieCompare);
|
||||
if (fie == NULL)
|
||||
continue; /* XXX shouldn't happen */
|
||||
|
||||
if (_rpmal_debug)
|
||||
fprintf(stderr, "==> fie %p %s\n", fie, (fie->baseName ? fie->baseName : "(nil)"));
|
||||
|
||||
alp = al->list + fie->pkgNum;
|
||||
|
||||
/* Ignore colored files not in our rainbow. */
|
||||
tscolor = alp->tscolor;
|
||||
ficolor = fie->ficolor;
|
||||
if (tscolor && ficolor && !(tscolor & ficolor))
|
||||
continue;
|
||||
for (found=i=0; i<resultCnt; i++) {
|
||||
alp = al->list + result[i].pkgNum;
|
||||
if (alp->p == NULL) // deleted
|
||||
continue;
|
||||
|
||||
rpmdsNotify(ds, _("(added files)"), 0);
|
||||
|
||||
ret = xrealloc(ret, (found+2) * sizeof(*ret));
|
||||
if (ret) /* can't happen */
|
||||
ret[found] = alp->p;
|
||||
ret[found] = alp->p;
|
||||
found++;
|
||||
}
|
||||
ret[found] = NULL;
|
||||
|
||||
exit:
|
||||
dirName = _free(dirName);
|
||||
if (ret)
|
||||
ret[found] = NULL;
|
||||
fileNameEntry.dirName = _constfree(fileNameEntry.dirName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rpmte *
|
||||
rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds)
|
||||
{
|
||||
availableIndex ai;
|
||||
struct availableIndexEntry_s needle;
|
||||
availableIndexEntry match;
|
||||
rpmte * ret = NULL;
|
||||
int found = 0;
|
||||
const char * KName;
|
||||
int i, found;
|
||||
const char * name;
|
||||
availableIndexEntry result;
|
||||
int resultCnt;
|
||||
|
||||
availablePackage alp;
|
||||
int rc;
|
||||
|
||||
if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL)
|
||||
if (al == NULL || ds == NULL || (name = rpmdsN(ds)) == NULL)
|
||||
return ret;
|
||||
|
||||
if (*KName == '/') {
|
||||
if (*name == '/') {
|
||||
/* First, look for files "contained" in package ... */
|
||||
ret = rpmalAllFileSatisfiesDepend(al, ds);
|
||||
if (ret != NULL && *ret != NULL)
|
||||
|
@ -680,56 +347,31 @@ rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds)
|
|||
ret = _free(ret);
|
||||
}
|
||||
|
||||
ai = &al->index;
|
||||
if (ai->index == NULL || ai->size <= 0)
|
||||
return NULL;
|
||||
rpmalProvidesHashGetEntry(al->providesHash, name, &result,
|
||||
&resultCnt, NULL);
|
||||
|
||||
memset(&needle, 0, sizeof(needle));
|
||||
needle.entry = KName;
|
||||
needle.entryLen = strlen(needle.entry);
|
||||
if (resultCnt==0) return NULL;
|
||||
|
||||
match = bsearch(&needle, ai->index, ai->size, sizeof(*ai->index), indexcmp);
|
||||
if (match == NULL)
|
||||
return NULL;
|
||||
|
||||
/* rewind to the first match */
|
||||
while (match > ai->index && indexcmp(match-1, &needle) == 0)
|
||||
match--;
|
||||
|
||||
if (al->list != NULL) /* XXX always true */
|
||||
for (ret = NULL, found = 0;
|
||||
match < ai->index + ai->size && indexcmp(match, &needle) == 0;
|
||||
match++)
|
||||
{
|
||||
alp = al->list + match->pkgNum;
|
||||
ret = xmalloc((resultCnt+1) * sizeof(*ret));
|
||||
|
||||
for (found=i=0; i<resultCnt; i++) {
|
||||
alp = al->list + result[i].pkgNum;
|
||||
if (alp->p == NULL) // deleted
|
||||
continue;
|
||||
/* XXX single step on rpmdsNext to regenerate DNEVR string */
|
||||
(void) rpmdsSetIx(alp->provides, result[i].entryIx - 1);
|
||||
rc = 0;
|
||||
if (alp->provides != NULL) /* XXX can't happen */
|
||||
switch (match->type) {
|
||||
case IET_PROVIDES:
|
||||
/* XXX single step on rpmdsNext to regenerate DNEVR string */
|
||||
(void) rpmdsSetIx(alp->provides, match->entryIx - 1);
|
||||
if (rpmdsNext(alp->provides) >= 0)
|
||||
rc = rpmdsCompare(alp->provides, ds);
|
||||
|
||||
if (rc)
|
||||
rpmdsNotify(ds, _("(added provide)"), 0);
|
||||
|
||||
break;
|
||||
}
|
||||
if (rpmdsNext(alp->provides) >= 0)
|
||||
rc = rpmdsCompare(alp->provides, ds);
|
||||
|
||||
if (rc) {
|
||||
ret = xrealloc(ret, (found + 2) * sizeof(*ret));
|
||||
if (ret) /* can't happen */
|
||||
ret[found] = alp->p;
|
||||
rpmdsNotify(ds, _("(added provide)"), 0);
|
||||
ret[found] = alp->p;
|
||||
found++;
|
||||
}
|
||||
}
|
||||
ret[found] = NULL;
|
||||
|
||||
if (ret)
|
||||
ret[found] = NULL;
|
||||
|
||||
/* FIX: *keyp may be NULL */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
11
lib/rpmal.h
11
lib/rpmal.h
|
@ -17,9 +17,10 @@ extern int _rpmal_debug;
|
|||
/**
|
||||
* Initialize available packckages, items, and directory list.
|
||||
* @param delta no. of entries to add on each realloc
|
||||
* @param tscolor transaction color bits
|
||||
* @return al new available list
|
||||
*/
|
||||
rpmal rpmalCreate(int delta);
|
||||
rpmal rpmalCreate(int delta, rpm_color_t tscolor);
|
||||
|
||||
/**
|
||||
* Free available packages, items, and directory members.
|
||||
|
@ -37,14 +38,12 @@ void rpmalDel(rpmal al, rpmte p);
|
|||
|
||||
/**
|
||||
* Add package to available list.
|
||||
* @param alistp address of available list
|
||||
* @param al available list
|
||||
* @param p package
|
||||
* @param tscolor transaction color bits
|
||||
* @return available package index
|
||||
*/
|
||||
void rpmalAdd(rpmal * alistp,
|
||||
rpmte p,
|
||||
rpm_color_t tscolor);
|
||||
void rpmalAdd(rpmal al,
|
||||
rpmte p);
|
||||
|
||||
/**
|
||||
* Generate index for available list.
|
||||
|
|
|
@ -50,7 +50,7 @@ Bucket HASHPREFIX(findEntry)(HASHTYPE ht, HTKEYTYPE key)
|
|||
hash = ht->fn(key) % ht->numBuckets;
|
||||
b = ht->buckets[hash];
|
||||
|
||||
while (b && b->key && ht->eq(b->key, key))
|
||||
while (b && ht->eq(b->key, key))
|
||||
b = b->next;
|
||||
|
||||
return b;
|
||||
|
@ -92,7 +92,7 @@ void HASHPREFIX(AddEntry)(HASHTYPE ht, HTKEYTYPE key
|
|||
b = ht->buckets[hash];
|
||||
b_addr = ht->buckets + hash;
|
||||
|
||||
while (b && b->key && ht->eq(b->key, key)) {
|
||||
while (b && ht->eq(b->key, key)) {
|
||||
b_addr = &(b->next);
|
||||
b = b->next;
|
||||
}
|
||||
|
@ -123,7 +123,8 @@ HASHTYPE HASHPREFIX(Free)(HASHTYPE ht)
|
|||
{
|
||||
Bucket b, n;
|
||||
int i;
|
||||
|
||||
if (ht==NULL)
|
||||
return ht;
|
||||
for (i = 0; i < ht->numBuckets; i++) {
|
||||
b = ht->buckets[i];
|
||||
if (b == NULL)
|
||||
|
@ -171,8 +172,8 @@ int HASHPREFIX(GetEntry)(HASHTYPE ht, HTKEYTYPE key, HTDATATYPE** data,
|
|||
*data = rc ? b->data : NULL;
|
||||
if (dataCount)
|
||||
*dataCount = rc ? b->dataCount : 0;
|
||||
if (tableKey)
|
||||
*tableKey = rc ? b->key : NULL;
|
||||
if (tableKey && rc)
|
||||
*tableKey = b->key;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1135,7 +1135,7 @@ rpmts rpmtsCreate(void)
|
|||
ts->selinuxEnabled = is_selinux_enabled();
|
||||
|
||||
ts->numAddedPackages = 0;
|
||||
ts->addedPackages = NULL;
|
||||
ts->addedPackages = rpmalCreate(5, ts->color);
|
||||
|
||||
ts->orderAlloced = 0;
|
||||
ts->orderCount = 0;
|
||||
|
|
|
@ -32,9 +32,7 @@ rpmal_Add(rpmalObject * s, PyObject * args, PyObject * kwds)
|
|||
&p))
|
||||
return NULL;
|
||||
|
||||
/* XXX errors */
|
||||
/* XXX transaction colors */
|
||||
rpmalAdd(&s->al, p, 0);
|
||||
rpmalAdd(s->al, p);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
|
Loading…
Reference in New Issue