void WriterImplBase::RegisterPackageResolvableExpressionList( PackageAttributeList& attributeList, const BObjectList<BPackageResolvableExpression>& expressionList, uint8 id) { for (int i = 0; i < expressionList.CountItems(); ++i) { BPackageResolvableExpression* resolvableExpr = expressionList.ItemAt(i); bool hasVersion = resolvableExpr->Version().InitCheck() == B_OK; PackageAttribute* name = new PackageAttribute((BHPKGAttributeID)id, B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE); name->string = fPackageStringCache.Get(resolvableExpr->Name().String()); attributeList.Add(name); if (hasVersion) { PackageAttribute* op = new PackageAttribute( B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR, B_HPKG_ATTRIBUTE_TYPE_UINT, B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT); op->unsignedInt = resolvableExpr->Operator(); name->children.Add(op); RegisterPackageVersion(name->children, resolvableExpr->Version()); } } }
static void update_requires_expression(BPackageResolvableExpression& expression, const ProvidesList& providesList) { // find the best-matching provides BPackageResolvable* bestProvides = NULL; for (ProvidesList::const_iterator it = providesList.begin(); it != providesList.end(); ++it) { BPackageResolvable* provides = *it; if (!expression.Matches(*provides)) continue; if (bestProvides == NULL || bestProvides->Version().InitCheck() != B_OK || (provides->Version().InitCheck() == B_OK && provides->Version().Compare(bestProvides->Version()) > 0)) { bestProvides = provides; } } if (bestProvides == NULL || bestProvides->Version().InitCheck() != B_OK) return; // Update the expression. Enforce the minimum found version, if the requires // has no version requirement or also a minimum. Otherwise enforce the exact // version found. BPackageResolvableOperator newOperator = B_PACKAGE_RESOLVABLE_OP_EQUAL; switch (expression.Operator()) { case B_PACKAGE_RESOLVABLE_OP_LESS: case B_PACKAGE_RESOLVABLE_OP_LESS_EQUAL: case B_PACKAGE_RESOLVABLE_OP_EQUAL: case B_PACKAGE_RESOLVABLE_OP_NOT_EQUAL: break; case B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL: case B_PACKAGE_RESOLVABLE_OP_GREATER: case B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT: newOperator = B_PACKAGE_RESOLVABLE_OP_GREATER_EQUAL; break; } expression.SetTo(expression.Name(), newOperator, bestProvides->Version()); }
int32 BPackageManager::_FindBasePackage(const PackageList& packages, const BPackageInfo& info) { if (info.BasePackage().IsEmpty()) return -1; // find the requirement matching the base package BPackageResolvableExpression* basePackage = NULL; int32 count = info.RequiresList().CountItems(); for (int32 i = 0; i < count; i++) { BPackageResolvableExpression* requires = info.RequiresList().ItemAt(i); if (requires->Name() == info.BasePackage()) { basePackage = requires; break; } } if (basePackage == NULL) { fUserInteractionHandler->Warn(B_OK, "package %s-%s doesn't have a " "matching requires for its base package \"%s\"", info.Name().String(), info.Version().ToString().String(), info.BasePackage().String()); return -1; } // find the first package matching the base package requires count = packages.CountItems(); for (int32 i = 0; i < count; i++) { BSolverPackage* package = packages.ItemAt(i); if (package->Name() == basePackage->Name() && package->Info().Matches(*basePackage)) { return i; } } return -1; }
int main(int argc, const char* const* argv) { if (argc != 3) print_usage_and_exit(true); if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) print_usage_and_exit(false); const char* const packageInfoPath = argv[1]; const char* const repositoryCachePath = argv[2]; // read the repository cache BRepositoryCache repositoryCache; status_t error = repositoryCache.SetTo(repositoryCachePath); if (error != B_OK) { DIE(error, "failed to read repository cache file \"%s\"", repositoryCachePath); } // create a map for all provides (name -> resolvable list) typedef std::map<BString, ProvidesList> ProvidesMap; ProvidesMap providesMap; for (BRepositoryCache::Iterator it = repositoryCache.GetIterator(); const BPackageInfo* info = it.Next();) { const BObjectList<BPackageResolvable>& provides = info->ProvidesList(); int32 count = provides.CountItems(); for (int32 i = 0; i < count; i++) { BPackageResolvable* resolvable = provides.ItemAt(i); ProvidesList& providesList = providesMap[resolvable->Name()]; providesList.push_back(resolvable); } } // load the package info BPackageInfo packageInfo; error = packageInfo.ReadFromConfigFile(packageInfoPath); if (error != B_OK) DIE(error, "failed to read package info file \"%s\"", packageInfoPath); // clone the package info's requires list typedef std::list<BPackageResolvableExpression> RequiresList; RequiresList requiresList; int32 requiresCount = packageInfo.RequiresList().CountItems(); for (int32 i = 0; i < requiresCount; i++) requiresList.push_back(*packageInfo.RequiresList().ItemAt(i)); // rebuild the requires list with updated versions packageInfo.ClearRequiresList(); for (RequiresList::iterator it = requiresList.begin(); it != requiresList.end(); ++it) { BPackageResolvableExpression expression = *it; ProvidesMap::iterator foundIt = providesMap.find(expression.Name()); if (foundIt != providesMap.end()) update_requires_expression(expression, foundIt->second); error = packageInfo.AddRequires(expression); if (error != B_OK) DIE(error, "failed to add requires item to package info"); } // write updated package info BString configString; error = packageInfo.GetConfigString(configString); if (error != B_OK) DIE(error, "failed to get updated package info string"); FILE* file = fopen(packageInfoPath, "w"); if (file == NULL) { DIE(errno, "failed to open package info file \"%s\" for writing", packageInfoPath); } if (fwrite(configString.String(), configString.Length(), 1, file) != 1) { DIE(errno, "failed to write updated package info file \"%s\"", packageInfoPath); } fclose(file); return 0; }