示例#1
0
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());
}
示例#3
0
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;
}