packages[i] = alloca(strlen(*filename) + 30 + strlen(rootdir));
sprintf(packages[i], "%s/var/tmp/rpm-ftp-%d-%d.tmp", rootdir,
tmpnum++, (int) getpid());
- rpmMessage(RPMMESS_DEBUG, "getting %s as %s\n", *filename, packages[i]);
+ rpmMessage(RPMMESS_DEBUG,
+ "getting %s as %s\n", *filename, packages[i]);
fd = urlGetFile(*filename, packages[i]);
if (fd < 0) {
fprintf(stderr,
continue;
}
- rc = rpmReadPackageHeader(fd, &binaryHeaders[numBinaryPackages], &isSource,
- NULL, NULL);
+ rc = rpmReadPackageHeader(fd, &binaryHeaders[numBinaryPackages],
+ &isSource, NULL, NULL);
close(fd);
exit(1);
}
- if (!(interfaceFlags & INSTALL_NODEPS)) {
- rpmdep = rpmdepDependencies(db);
- for (i = 0; i < numBinaryPackages; i++)
- if (installFlags & RPMINSTALL_UPGRADE)
- rpmdepUpgradePackage(rpmdep, binaryHeaders[i]);
- else
- rpmdepAddPackage(rpmdep, binaryHeaders[i]);
+ rpmdep = rpmdepDependencies(db);
+ for (i = 0; i < numBinaryPackages; i++)
+ if (installFlags & RPMINSTALL_UPGRADE)
+ rpmdepUpgradePackage(rpmdep, binaryHeaders[i],
+ packages[i]);
+ else
+ rpmdepAddPackage(rpmdep, binaryHeaders[i],
+ packages[i]);
+ if (!(interfaceFlags & INSTALL_NODEPS)) {
if (rpmdepCheck(rpmdep, &conflicts, &numConflicts)) {
numFailed = numPackages;
stopInstall = 1;
}
- rpmdepDone(rpmdep);
-
if (!stopInstall && conflicts) {
fprintf(stderr, _("failed dependencies:\n"));
printDepProblems(stderr, conflicts, numConflicts);
stopInstall = 1;
}
}
+
+ if (!(interfaceFlags & INSTALL_NOORDER)) {
+ if (rpmdepOrder(rpmdep, (void ***) &packages)) {
+ numFailed = numPackages;
+ stopInstall = 1;
+ }
+ }
+
+ rpmdepDone(rpmdep);
}
else
db = NULL;
enum indexEntryType { IET_NAME, IET_PROVIDES, IET_FILE };
+enum selectionStatus { UNSELECTED = 0, SELECTED, INPROCESS };
+
struct availableIndexEntry {
struct availablePackage * package;
char * entry;
struct problemsSet * psp, char * package);
static int checkPackageSet(rpmDependencies rpmdep, struct problemsSet * psp,
char * package, dbiIndexSet * matches);
+static int addOrderedPack(rpmDependencies rpmdep,
+ struct availablePackage * package,
+ void ** ordering, int * orderNumPtr,
+ enum selectionStatus * selected,
+ int satisfyDepends);
static void alCreate(struct availableList * al) {
al->list = malloc(sizeof(*al->list) * 5);
return rpmdep;
}
-void rpmdepUpgradePackage(rpmDependencies rpmdep, Header h) {
+void rpmdepUpgradePackage(rpmDependencies rpmdep, Header h, void * key) {
/* this is an install followed by uninstalls */
dbiIndexSet matches;
char * name;
int count, type, i;
- alAddPackage(&rpmdep->addedPackages, h, NULL);
+ alAddPackage(&rpmdep->addedPackages, h, key);
if (!rpmdep->db) return;
}
}
-void rpmdepAddPackage(rpmDependencies rpmdep, Header h) {
- alAddPackage(&rpmdep->addedPackages, h, NULL);
+void rpmdepAddPackage(rpmDependencies rpmdep, Header h, void * key) {
+ alAddPackage(&rpmdep->addedPackages, h, key);
}
void rpmdepAvailablePackage(rpmDependencies rpmdep, Header h, void * key) {
headerGetEntry(h, RPMTAG_NAME, &type, (void *) &name, &count);
- if (!reqFlags) {
+ if (!(reqFlags & RPMSENSE_SENSEMASK)) {
return 1;
}
return rc;
}
+
+static int addOrderedPack(rpmDependencies rpmdep,
+ struct availablePackage * package,
+ void ** ordering, int * orderNumPtr,
+ enum selectionStatus * selected,
+ int satisfyDepends) {
+ char ** requires, ** requiresVersion;
+ int_32 * requireFlags;
+ int requiresCount;
+ int packageNum = package - rpmdep->addedPackages.list;
+ int i;
+ struct availablePackage * match;
+
+ if (selected[packageNum] == INPROCESS) {
+ rpmError(RPMMESS_PREREQLOOP, "loop in prerequisite chain");
+ return 1;
+ }
+
+ selected[packageNum] = INPROCESS;
+
+ if (headerGetEntry(package->h, RPMTAG_REQUIRENAME, NULL,
+ (void **) &requires, &requiresCount)) {
+ headerGetEntry(package->h, RPMTAG_REQUIREFLAGS, NULL,
+ (void **) &requireFlags, NULL);
+ headerGetEntry(package->h, RPMTAG_REQUIREVERSION, NULL,
+ (void **) &requiresVersion, NULL);
+
+ for (i = 0; i < requiresCount; i++) {
+ if (satisfyDepends || (requireFlags[i] & RPMSENSE_PREREQ)) {
+ match = alSatisfiesDepend(&rpmdep->addedPackages,
+ requires[i], requiresVersion[i],
+ requireFlags[i]);
+ /* broken dependencies don't concern us */
+ if (!match) continue;
+ if (addOrderedPack(rpmdep, match, ordering, orderNumPtr,
+ selected, 1)) return 1;
+ }
+ }
+ }
+
+ /* whew -- add this package */
+ ordering[(*orderNumPtr)++] = package->key;
+ selected[packageNum] = SELECTED;
+
+ return 0;
+}
+
+int rpmdepOrder(rpmDependencies rpmdep, void *** keysListPtr) {
+ int i;
+ enum selectionStatus * selected;
+ void ** order;
+ int orderNum;
+
+ selected = alloca(sizeof(*selected) * rpmdep->addedPackages.size);
+ memset(selected, 0, sizeof(*selected) * rpmdep->addedPackages.size);
+
+ order = malloc(sizeof(*order) * (rpmdep->addedPackages.size + 1));
+ orderNum = 0;
+
+ for (i = 0; i < rpmdep->addedPackages.size; i++) {
+ if (selected[i] == UNSELECTED) {
+ if (addOrderedPack(rpmdep, rpmdep->addedPackages.list + i,
+ order, &orderNum, selected, 0)) {
+ free(order);
+ return 1;
+ }
+ }
+ }
+
+ order[orderNum] = NULL;
+ *keysListPtr = order;
+
+ return 0;
+}
} ;
rpmDependencies rpmdepDependencies(rpmdb db); /* db may be NULL */
-void rpmdepAddPackage(rpmDependencies rpmdep, Header h);
+void rpmdepAddPackage(rpmDependencies rpmdep, Header h, void * key);
void rpmdepAvailablePackage(rpmDependencies rpmdep, Header h, void * key);
-void rpmdepUpgradePackage(rpmDependencies rpmdep, Header h);
+void rpmdepUpgradePackage(rpmDependencies rpmdep, Header h, void * key);
void rpmdepRemovePackage(rpmDependencies rpmdep, int dboffset);
+
+/* this checks for dependency satisfaction, but *not* ordering */
int rpmdepCheck(rpmDependencies rpmdep,
struct rpmDependencyConflict ** conflicts, int * numConflicts);
+/* Orders items, returns error on circle, finals keys[] is NULL. No dependency
+ check is done, use rpmdepCheck() for that. If dependencies are not
+ satisfied a "best-try" ordering is returned. */
+int rpmdepOrder(rpmDependencies order, void *** keysListPtr);
+
void rpmdepDone(rpmDependencies rpmdep);
void rpmdepFreeConflicts(struct rpmDependencyConflict * conflicts, int
numConflicts);
#define RPMERR_STAT -36 /* failed to stat something */
#define RPMERR_BADDEV -37 /* file on device not listed in mtab */
#define RPMMESS_ALTNAME -38 /* file written as .rpmnew */
+#define RPMMESS_PREREQLOOP -39 /* loop in prerequisites */
/* spec.c build.c pack.c */
#define RPMERR_UNMATCHEDIF -107 /* unclosed %ifarch or %ifos */