Repository file format: group attributes of a package

* Introduce new package attribute B_HPKG_ATTRIBUTE_ID_PACKAGE (valid
  only in a repository file) to group the attributes belonging to a
  package.
* BRepositoryContentHandler:
  - No longer derive from BPackageContentHandler.
  - Add hooks HandlePackage() and HandlePackageDone() that bracket the
    attributes for a package. This is more explicit and robust than
    handlers having to guess when one package ended and the next began.
* BRepositoryCache: Make use of BPackageInfoContentHandler. No need to
  duplicate the code for reading a package info from package info
  attributes.
This commit is contained in:
Ingo Weinhold
2013-07-04 19:20:14 +02:00
parent 17d00ecd27
commit e85334022e
12 changed files with 238 additions and 162 deletions
@@ -81,3 +81,4 @@ B_DEFINE_HPKG_ATTRIBUTE(52, STRING, "package:post-install-script",
PACKAGE_POST_INSTALL_SCRIPT)
B_DEFINE_HPKG_ATTRIBUTE(53, UINT, "package:is-writable-directory",
PACKAGE_IS_WRITABLE_DIRECTORY)
B_DEFINE_HPKG_ATTRIBUTE(54, STRING, "package", PACKAGE)
@@ -8,7 +8,7 @@
#include <SupportDefs.h>
#include <package/hpkg/PackageContentHandler.h>
#include <package/hpkg/HPKGDefs.h>
namespace BPackageKit {
@@ -20,10 +20,24 @@ class BRepositoryInfo;
namespace BHPKG {
class BRepositoryContentHandler : public BPackageContentHandler {
class BPackageInfoAttributeValue;
class BRepositoryContentHandler {
public:
virtual ~BRepositoryContentHandler();
virtual status_t HandleRepositoryInfo(
const BRepositoryInfo& info) = 0;
virtual status_t HandlePackage(const char* packageName) = 0;
virtual status_t HandlePackageAttribute(
const BPackageInfoAttributeValue& value)
= 0;
virtual status_t HandlePackageDone(const char* packageName) = 0;
virtual void HandleErrorOccurred() = 0;
};
@@ -38,7 +38,8 @@ public:
BRepositoryContentHandler* contentHandler);
private:
struct RootAttributeHandler;
class PackagesAttributeHandler;
class PackageContentHandlerAdapter;
private:
BRepositoryInfo fRepositoryInfo;
@@ -117,6 +117,10 @@ protected:
BPackageResolvableExpression>& list,
uint8 id);
PackageAttribute* AddStringAttribute(BHPKGAttributeID id,
const BString& value,
DoublyLinkedList<PackageAttribute>& list);
int32 WriteCachedStrings(const StringCache& cache,
uint32 minUsageCount);
@@ -163,9 +167,6 @@ private:
= B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR;
private:
PackageAttribute* _AddStringAttribute(BHPKGAttributeID id,
const BString& value,
DoublyLinkedList<PackageAttribute>& list);
inline PackageAttribute* _AddStringAttributeIfNotEmpty(
BHPKGAttributeID id, const BString& value,
DoublyLinkedList<PackageAttribute>& list);
@@ -267,7 +268,7 @@ WriterImplBase::_AddStringAttributeIfNotEmpty(BHPKGAttributeID id,
{
if (value.IsEmpty())
return NULL;
return _AddStringAttribute(id, value, list);
return AddStringAttribute(id, value, list);
}
+6 -12
View File
@@ -32,18 +32,7 @@ struct RepositoryContentListHandler : BRepositoryContentHandler {
{
}
virtual status_t HandleEntry(BPackageEntry* entry)
{
return B_OK;
}
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute)
{
return B_OK;
}
virtual status_t HandleEntryDone(BPackageEntry* entry)
virtual status_t HandlePackage(const char* packageName)
{
return B_OK;
}
@@ -204,6 +193,11 @@ struct RepositoryContentListHandler : BRepositoryContentHandler {
return B_OK;
}
virtual status_t HandlePackageDone(const char* packageName)
{
return B_OK;
}
virtual status_t HandleRepositoryInfo(const BRepositoryInfo& repositoryInfo)
{
printf("repository-info:\n");
+1
View File
@@ -46,6 +46,7 @@ HPKG_SOURCES =
PackageWriter.cpp
PackageWriterImpl.cpp
ReaderImplBase.cpp
RepositoryContentHandler.cpp
RepositoryReader.cpp
RepositoryReaderImpl.cpp
RepositoryWriter.cpp
+1
View File
@@ -37,6 +37,7 @@ HPKG_SOURCES =
PackageWriterImpl.cpp
PoolBuffer.cpp
ReaderImplBase.cpp
RepositoryContentHandler.cpp
RepositoryReader.cpp
RepositoryReaderImpl.cpp
RepositoryWriter.cpp
+27 -114
View File
@@ -1,9 +1,10 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Copyright 2011-2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
* Ingo Weinhold <[email protected]>
*/
@@ -26,6 +27,8 @@
#include <package/PackageInfo.h>
#include <package/RepositoryInfo.h>
#include <package/PackageInfoContentHandler.h>
namespace BPackageKit {
@@ -37,136 +40,45 @@ using namespace BHPKG;
struct BRepositoryCache::RepositoryContentHandler : BRepositoryContentHandler {
RepositoryContentHandler(BRepositoryInfo* repositoryInfo,
BPackageInfoSet& packages)
RepositoryContentHandler(BRepositoryInfo& repositoryInfo,
BPackageInfoSet& packages, BErrorOutput* errorOutput)
:
fRepositoryInfo(repositoryInfo),
fPackages(packages)
fPackageInfo(),
fPackages(packages),
fPackageInfoContentHandler(fPackageInfo, errorOutput)
{
}
virtual status_t HandleEntry(BPackageEntry* entry)
virtual status_t HandlePackage(const char* packageName)
{
fPackageInfo.Clear();
return B_OK;
}
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute)
{
return B_OK;
}
virtual status_t HandleEntryDone(BPackageEntry* entry)
{
return B_OK;
}
virtual status_t HandlePackageAttribute(
const BPackageInfoAttributeValue& value)
{
switch (value.attributeID) {
case B_PACKAGE_INFO_NAME:
fPackageInfo.SetName(value.string);
break;
return fPackageInfoContentHandler.HandlePackageAttribute(value);
}
case B_PACKAGE_INFO_SUMMARY:
fPackageInfo.SetSummary(value.string);
break;
virtual status_t HandlePackageDone(const char* packageName)
{
status_t result = fPackageInfo.InitCheck();
if (result != B_OK)
return result;
case B_PACKAGE_INFO_DESCRIPTION:
fPackageInfo.SetDescription(value.string);
break;
case B_PACKAGE_INFO_VENDOR:
fPackageInfo.SetVendor(value.string);
break;
case B_PACKAGE_INFO_PACKAGER:
fPackageInfo.SetPackager(value.string);
break;
case B_PACKAGE_INFO_FLAGS:
fPackageInfo.SetFlags(value.unsignedInt);
break;
case B_PACKAGE_INFO_ARCHITECTURE:
fPackageInfo.SetArchitecture(
(BPackageArchitecture)value.unsignedInt);
break;
case B_PACKAGE_INFO_VERSION:
fPackageInfo.SetVersion(value.version);
break;
case B_PACKAGE_INFO_COPYRIGHTS:
fPackageInfo.AddCopyright(value.string);
break;
case B_PACKAGE_INFO_LICENSES:
fPackageInfo.AddLicense(value.string);
break;
case B_PACKAGE_INFO_PROVIDES:
fPackageInfo.AddProvides(value.resolvable);
break;
case B_PACKAGE_INFO_REQUIRES:
fPackageInfo.AddRequires(value.resolvableExpression);
break;
case B_PACKAGE_INFO_SUPPLEMENTS:
fPackageInfo.AddSupplements(value.resolvableExpression);
break;
case B_PACKAGE_INFO_CONFLICTS:
fPackageInfo.AddConflicts(value.resolvableExpression);
break;
case B_PACKAGE_INFO_FRESHENS:
fPackageInfo.AddFreshens(value.resolvableExpression);
break;
case B_PACKAGE_INFO_REPLACES:
fPackageInfo.AddReplaces(value.string);
break;
case B_PACKAGE_INFO_URLS:
fPackageInfo.AddURL(value.string);
break;
case B_PACKAGE_INFO_SOURCE_URLS:
fPackageInfo.AddSourceURL(value.string);
break;
case B_PACKAGE_INFO_INSTALL_PATH:
fPackageInfo.SetInstallPath(value.string);
break;
case B_PACKAGE_INFO_CHECKSUM:
{
fPackageInfo.SetChecksum(value.string);
status_t result = fPackageInfo.InitCheck();
if (result != B_OK)
return result;
result = fPackages.AddInfo(fPackageInfo);
if (result != B_OK)
return result;
fPackageInfo.Clear();
break;
}
default:
return B_BAD_DATA;
}
result = fPackages.AddInfo(fPackageInfo);
if (result != B_OK)
return result;
return B_OK;
}
virtual status_t HandleRepositoryInfo(const BRepositoryInfo& repositoryInfo)
{
*fRepositoryInfo = repositoryInfo;
fRepositoryInfo = repositoryInfo;
return B_OK;
}
@@ -176,9 +88,10 @@ struct BRepositoryCache::RepositoryContentHandler : BRepositoryContentHandler {
}
private:
BRepositoryInfo* fRepositoryInfo;
BPackageInfo fPackageInfo;
BPackageInfoSet& fPackages;
BRepositoryInfo& fRepositoryInfo;
BPackageInfo fPackageInfo;
BPackageInfoSet& fPackages;
BPackageInfoContentHandler fPackageInfoContentHandler;
};
@@ -247,7 +160,7 @@ BRepositoryCache::SetTo(const BEntry& entry)
if ((result = repositoryReader.Init(repositoryCachePath.Path())) != B_OK)
return result;
RepositoryContentHandler handler(&fInfo, fPackages);
RepositoryContentHandler handler(fInfo, fPackages, &errorOutput);
if ((result = repositoryReader.ParseContent(&handler)) != B_OK)
return result;
@@ -0,0 +1,25 @@
/*
* Copyright 2013, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ingo Weinhold <[email protected]>
*/
#include <package/hpkg/RepositoryContentHandler.h>
namespace BPackageKit {
namespace BHPKG {
BRepositoryContentHandler::~BRepositoryContentHandler()
{
}
} // namespace BHPKG
} // namespace BPackageKit
+125 -2
View File
@@ -40,6 +40,127 @@ static const size_t kMaxRepositoryInfoSize = 1 * 1024 * 1024;
static const size_t kMaxPackageAttributesSize = 64 * 1024 * 1024;
// #pragma mark - PackagesAttributeHandler
class RepositoryReaderImpl::PackagesAttributeHandler
: public AttributeHandler {
public:
PackagesAttributeHandler(BRepositoryContentHandler* contentHandler)
:
fContentHandler(contentHandler),
fPackageName(NULL)
{
}
virtual status_t HandleAttribute(AttributeHandlerContext* context, uint8 id,
const AttributeValue& value, AttributeHandler** _handler)
{
switch (id) {
case B_HPKG_ATTRIBUTE_ID_PACKAGE:
{
status_t error = _NotifyPackageDone();
if (error != B_OK)
return error;
if (_handler != NULL) {
if (fContentHandler != NULL) {
error = fContentHandler->HandlePackage(value.string);
if (error != B_OK)
return error;
}
*_handler = new(std::nothrow) PackageAttributeHandler;
if (*_handler == NULL)
return B_NO_MEMORY;
fPackageName = value.string;
}
break;
}
default:
if (context->ignoreUnknownAttributes)
break;
context->errorOutput->PrintError(
"Error: Invalid package attribute section: unexpected "
"top level attribute id %d encountered\n", id);
return B_BAD_DATA;
}
return B_OK;
}
virtual status_t Delete(AttributeHandlerContext* context)
{
return _NotifyPackageDone();
}
private:
status_t _NotifyPackageDone()
{
if (fPackageName == NULL || fContentHandler == NULL)
return B_OK;
status_t error = fContentHandler->HandlePackageDone(fPackageName);
fPackageName = NULL;
return error;
}
private:
BRepositoryContentHandler* fContentHandler;
const char* fPackageName;
};
// #pragma mark - PackageContentHandlerAdapter
class RepositoryReaderImpl::PackageContentHandlerAdapter
: public BPackageContentHandler {
public:
PackageContentHandlerAdapter(BRepositoryContentHandler* contentHandler)
:
fContentHandler(contentHandler)
{
}
virtual status_t HandleEntry(BPackageEntry* entry)
{
return B_OK;
}
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute)
{
return B_OK;
}
virtual status_t HandleEntryDone(BPackageEntry* entry)
{
return B_OK;
}
virtual status_t HandlePackageAttribute(
const BPackageInfoAttributeValue& value)
{
return fContentHandler->HandlePackageAttribute(value);
}
virtual void HandleErrorOccurred()
{
return fContentHandler->HandleErrorOccurred();
}
private:
BRepositoryContentHandler* fContentHandler;
};
// #pragma mark - RepositoryReaderImpl
RepositoryReaderImpl::RepositoryReaderImpl(BErrorOutput* errorOutput)
:
inherited("repository", errorOutput)
@@ -140,10 +261,12 @@ RepositoryReaderImpl::ParseContent(BRepositoryContentHandler* contentHandler)
{
status_t result = contentHandler->HandleRepositoryInfo(fRepositoryInfo);
if (result == B_OK) {
AttributeHandlerContext context(ErrorOutput(), contentHandler,
PackageContentHandlerAdapter contentHandlerAdapter(contentHandler);
AttributeHandlerContext context(ErrorOutput(),
contentHandler != NULL ? &contentHandlerAdapter : NULL,
B_HPKG_SECTION_PACKAGE_ATTRIBUTES,
MinorFormatVersion() > B_HPKG_REPO_MINOR_VERSION);
PackageAttributeHandler rootAttributeHandler;
PackagesAttributeHandler rootAttributeHandler(contentHandler);
result = ParsePackageAttributesSection(&context, &rootAttributeHandler);
}
return result;
@@ -395,7 +395,9 @@ RepositoryWriterImpl::_RegisterCurrentPackageInfo()
if ((result = fPackageNames->Add(fPackageInfo.Name())) != B_OK)
return result;
RegisterPackageInfo(PackageAttributes(), fPackageInfo);
PackageAttribute* packageAttribute = AddStringAttribute(
B_HPKG_ATTRIBUTE_ID_PACKAGE, fPackageInfo.Name(), PackageAttributes());
RegisterPackageInfo(packageAttribute->children, fPackageInfo);
fPackageCount++;
fListener->OnPackageAdded(fPackageInfo);
+26 -26
View File
@@ -280,23 +280,23 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
const BPackageInfo& packageInfo)
{
// name
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, packageInfo.Name(),
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME, packageInfo.Name(),
attributeList);
// summary
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY,
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY,
packageInfo.Summary(), attributeList);
// description
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION,
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION,
packageInfo.Description(), attributeList);
// vendor
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR,
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR,
packageInfo.Vendor(), attributeList);
// packager
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER,
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER,
packageInfo.Packager(), attributeList);
// base package (optional)
@@ -345,7 +345,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
bool hasCompatibleVersion
= resolvable->CompatibleVersion().InitCheck() == B_OK;
PackageAttribute* provides = _AddStringAttribute(
PackageAttribute* provides = AddStringAttribute(
B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES, resolvable->Name(),
attributeList);
@@ -384,7 +384,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
= packageInfo.GlobalWritableFileInfos();
for (int32 i = 0; i < globalWritableFileInfos.CountItems(); ++i) {
BGlobalWritableFileInfo* info = globalWritableFileInfos.ItemAt(i);
PackageAttribute* attribute = _AddStringAttribute(
PackageAttribute* attribute = AddStringAttribute(
B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE, info->Path(),
attributeList);
@@ -412,7 +412,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
= packageInfo.UserSettingsFileInfos();
for (int32 i = 0; i < userSettingsFileInfos.CountItems(); ++i) {
BUserSettingsFileInfo* info = userSettingsFileInfos.ItemAt(i);
PackageAttribute* attribute = _AddStringAttribute(
PackageAttribute* attribute = AddStringAttribute(
B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE, info->Path(),
attributeList);
@@ -434,7 +434,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
const BObjectList<BUser>& users = packageInfo.Users();
for (int32 i = 0; i < users.CountItems(); ++i) {
const BUser* user = users.ItemAt(i);
PackageAttribute* attribute = _AddStringAttribute(
PackageAttribute* attribute = AddStringAttribute(
B_HPKG_ATTRIBUTE_ID_PACKAGE_USER, user->Name(), attributeList);
_AddStringAttributeIfNotEmpty(
@@ -448,7 +448,7 @@ WriterImplBase::RegisterPackageInfo(PackageAttributeList& attributeList,
attribute->children);
for (int32 k = 0; k < user->Groups().CountStrings(); k++) {
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP,
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP,
user->Groups().StringAt(k), attribute->children);
}
}
@@ -475,11 +475,11 @@ void
WriterImplBase::RegisterPackageVersion(PackageAttributeList& attributeList,
const BPackageVersion& version, BHPKGAttributeID attributeID)
{
PackageAttribute* versionMajor = _AddStringAttribute(attributeID,
PackageAttribute* versionMajor = AddStringAttribute(attributeID,
version.Major(), attributeList);
if (!version.Minor().IsEmpty()) {
_AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR,
AddStringAttribute(B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR,
version.Minor(), versionMajor->children);
_AddStringAttributeIfNotEmpty(
B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO, version.Micro(),
@@ -507,7 +507,7 @@ WriterImplBase::RegisterPackageResolvableExpressionList(
{
for (int i = 0; i < expressionList.CountItems(); ++i) {
BPackageResolvableExpression* resolvableExpr = expressionList.ItemAt(i);
PackageAttribute* name = _AddStringAttribute((BHPKGAttributeID)id,
PackageAttribute* name = AddStringAttribute((BHPKGAttributeID)id,
resolvableExpr->Name(), attributeList);
if (resolvableExpr->Version().InitCheck() == B_OK) {
@@ -523,6 +523,18 @@ WriterImplBase::RegisterPackageResolvableExpressionList(
}
WriterImplBase::PackageAttribute*
WriterImplBase::AddStringAttribute(BHPKGAttributeID id, const BString& value,
DoublyLinkedList<PackageAttribute>& list)
{
PackageAttribute* attribute = new PackageAttribute(id,
B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE);
attribute->string = fPackageStringCache.Get(value);
list.Add(attribute);
return attribute;
}
int32
WriterImplBase::WriteCachedStrings(const StringCache& cache,
uint32 minUsageCount)
@@ -682,24 +694,12 @@ WriterImplBase::RawWriteBuffer(const void* buffer, size_t size, off_t offset)
}
WriterImplBase::PackageAttribute*
WriterImplBase::_AddStringAttribute(BHPKGAttributeID id, const BString& value,
DoublyLinkedList<PackageAttribute>& list)
{
PackageAttribute* attribute = new PackageAttribute(id,
B_HPKG_ATTRIBUTE_TYPE_STRING, B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE);
attribute->string = fPackageStringCache.Get(value);
list.Add(attribute);
return attribute;
}
void
WriterImplBase::_AddStringAttributeList(BHPKGAttributeID id,
const BStringList& value, DoublyLinkedList<PackageAttribute>& list)
{
for (int32 i = 0; i < value.CountStrings(); i++)
_AddStringAttribute(id, value.StringAt(i), list);
AddStringAttribute(id, value.StringAt(i), list);
}