Implemented repository writing:

* fleshed out RepositoryWriterImpl
* renamed BRepositoryHeader to BRepositoryInfo (in accordance with
  BPackageInfo)
* adjusted BRepositoryInfo to be able to parse itself from a
  driver_settings file
* added package_repo binary (only 'create' works as of yet)


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40405 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe 2011-02-09 19:11:23 +00:00
parent 78a471321c
commit 0d68f6afb3
37 changed files with 1425 additions and 301 deletions

View File

@ -55,6 +55,7 @@ public:
const BString& Description() const;
const BString& Vendor() const;
const BString& Packager() const;
const BString& Checksum() const;
uint32 Flags() const;
@ -81,6 +82,7 @@ public:
void SetDescription(const BString& description);
void SetVendor(const BString& vendor);
void SetPackager(const BString& packager);
void SetChecksum(const BString& checksum);
void SetFlags(uint32 flags);
@ -120,6 +122,9 @@ public:
void Clear();
public:
static status_t GetArchitectureByName(const BString& name,
BPackageArchitecture& _architecture);
static const char* kElementNames[];
static const char* kArchitectureNames[];
@ -152,6 +157,8 @@ private:
BObjectList<BPackageResolvableExpression> fFreshensList;
BObjectList<BString> fReplacesList;
BString fChecksum;
};

View File

@ -34,6 +34,7 @@ enum BPackageInfoAttributeIndex {
B_PACKAGE_INFO_REPLACES, // list of resolvables that this package
// will replace (upon update)
B_PACKAGE_INFO_FLAGS,
B_PACKAGE_INFO_CHECKSUM, // sha256-checksum
//
B_PACKAGE_INFO_ENUM_COUNT,
};

View File

@ -15,6 +15,12 @@
namespace BPackageKit {
namespace BHPKG {
class BPackageResolvableData;
}
using BHPKG::BPackageResolvableData;
/*
* Defines a resolvable (something other packages can depend upon).
* Each resolvable is defined as a name (with an optional type prefix)
@ -39,6 +45,8 @@ namespace BPackageKit {
class BPackageResolvable {
public:
BPackageResolvable();
BPackageResolvable(
const BPackageResolvableData& data);
BPackageResolvable(const BString& name,
BPackageResolvableType type
= B_PACKAGE_RESOLVABLE_TYPE_DEFAULT,

View File

@ -15,6 +15,12 @@
namespace BPackageKit {
namespace BHPKG {
class BPackageResolvableExpressionData;
}
using BHPKG::BPackageResolvableExpressionData;
/*
* Expresses a constraint on a specific resolvable, either just a name
* or a name plus a relational operator and a version.
@ -33,6 +39,9 @@ namespace BPackageKit {
class BPackageResolvableExpression {
public:
BPackageResolvableExpression();
BPackageResolvableExpression(
const BPackageResolvableExpressionData& data
);
BPackageResolvableExpression(
const BString& name,
BPackageResolvableOperator _op

View File

@ -12,9 +12,17 @@
namespace BPackageKit {
namespace BHPKG {
class BPackageVersionData;
}
using BHPKG::BPackageVersionData;
class BPackageVersion {
public:
BPackageVersion();
BPackageVersion(
const BPackageVersionData& data);
BPackageVersion(const BString& major,
const BString& minor, const BString& micro,
uint8 release);

View File

@ -9,15 +9,12 @@
#include <Entry.h>
#include <String.h>
#include <package/RepositoryHeader.h>
#include <package/RepositoryInfo.h>
namespace BPackageKit {
//class RepositoryHeader;
class BRepositoryCache {
public:
BRepositoryCache();
@ -27,7 +24,7 @@ public:
status_t SetTo(const BEntry& entry);
status_t InitCheck() const;
const BRepositoryHeader& Header() const;
const BRepositoryInfo& Info() const;
const BEntry& Entry() const;
bool IsUserSpecific() const;
@ -37,7 +34,7 @@ private:
status_t fInitStatus;
BEntry fEntry;
BRepositoryHeader fHeader;
BRepositoryInfo fInfo;
bool fIsUserSpecific;
};

View File

@ -2,55 +2,60 @@
* Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _PACKAGE__REPOSITORY_HEADER_H_
#define _PACKAGE__REPOSITORY_HEADER_H_
#ifndef _PACKAGE__REPOSITORY_INFO_H_
#define _PACKAGE__REPOSITORY_INFO_H_
#include <Archivable.h>
#include <Entry.h>
#include <String.h>
#include <package/PackageArchitecture.h>
namespace BPackageKit {
class BRepositoryHeader : public BArchivable {
class BRepositoryInfo : public BArchivable {
typedef BArchivable inherited;
public:
BRepositoryHeader();
BRepositoryHeader(BMessage* data);
virtual ~BRepositoryHeader();
BRepositoryInfo();
BRepositoryInfo(BMessage* data);
BRepositoryInfo(const BEntry& entry);
virtual ~BRepositoryInfo();
virtual status_t Archive(BMessage* data, bool deep = true) const;
status_t SetTo(const BMessage* data);
status_t SetTo(const BEntry& entry);
status_t InitCheck() const;
const BString& Name() const;
const BString& OriginalBaseURL() const;
const BString& Vendor() const;
const BString& ShortDescription() const;
const BString& LongDescription() const;
const BString& Summary() const;
uint8 Priority() const;
BPackageArchitecture Architecture() const;
void SetName(const BString& name);
void SetOriginalBaseURL(const BString& url);
void SetVendor(const BString& vendor);
void SetShortDescription(const BString& description);
void SetLongDescription(const BString& description);
void SetSummary(const BString& summary);
void SetPriority(uint8 priority);
void SetArchitecture(BPackageArchitecture arch);
public:
static BRepositoryHeader* Instantiate(BMessage* data);
static BRepositoryInfo* Instantiate(BMessage* data);
static const uint8 kDefaultPriority;
static const char* kNameField;
static const char* kURLField;
static const char* kVendorField;
static const char* kShortDescriptionField;
static const char* kLongDescriptionField;
static const char* kSummaryField;
static const char* kPriorityField;
static const char* kArchitectureField;
private:
status_t fInitStatus;
@ -58,13 +63,13 @@ private:
BString fName;
BString fOriginalBaseURL;
BString fVendor;
BString fShortDescription;
BString fLongDescription;
BString fSummary;
uint8 fPriority;
BPackageArchitecture fArchitecture;
};
} // namespace BPackageKit
#endif // _PACKAGE__REPOSITORY_HEADER_H_
#endif // _PACKAGE__REPOSITORY_INFO_H_

View File

@ -47,6 +47,7 @@ public:
virtual status_t HandlePackageAttribute(
const BPackageInfoAttributeValue& value
) = 0;
virtual status_t HandlePackageAttributesDone() = 0;
virtual void HandleErrorOccurred() = 0;
};

View File

@ -16,6 +16,7 @@ namespace BPackageKit {
class BPackageInfo;
class BRepositoryInfo;
namespace BHPKG {
@ -38,6 +39,8 @@ public:
virtual void OnPackageAttributesSizeInfo(uint32 stringCount,
uint32 uncompressedSize) = 0;
virtual void OnRepositorySizeInfo(uint32 headerSize,
uint32 repositoryInfoLength,
uint32 packageCount,
uint32 packageAttributesSize,
uint64 totalSize) = 0;
};
@ -47,7 +50,8 @@ class BRepositoryWriter {
public:
public:
BRepositoryWriter(
BRepositoryWriterListener* listener);
BRepositoryWriterListener* listener,
const BRepositoryInfo* repositoryInfo);
~BRepositoryWriter();
status_t Init(const char* fileName);

View File

@ -25,7 +25,7 @@ public:
ActivateRepositoryConfigJob(
const BContext& context,
const BString& title,
const BEntry& archivedRepoHeaderEntry,
const BEntry& archivedRepoInfoEntry,
const BString& repositoryBaseURL,
const BDirectory& targetDirectory);
virtual ~ActivateRepositoryConfigJob();
@ -37,7 +37,7 @@ protected:
virtual void Cleanup(status_t jobResult);
private:
BEntry fArchivedRepoHeaderEntry;
BEntry fArchivedRepoInfoEntry;
BString fRepositoryBaseURL;
BDirectory fTargetDirectory;
BEntry fTargetEntry;

View File

@ -8,17 +8,21 @@
#include <Entry.h>
#include <package/hpkg/PackageContentHandler.h>
#include <package/hpkg/RepositoryWriter.h>
#include <package/hpkg/WriterImplBase.h>
#include <package/PackageInfo.h>
namespace BPackageKit {
namespace BHPKG {
class BDataReader;
class BErrorOutput;
class BPackageEntry;
class BPackageEntryAttribute;
class BPackageInfoAttributeValue;
namespace BPrivate {
@ -26,26 +30,54 @@ namespace BPrivate {
struct hpkg_header;
class RepositoryWriterImpl : public WriterImplBase {
class RepositoryWriterImpl
: public WriterImplBase, private BPackageContentHandler {
public:
RepositoryWriterImpl(
BRepositoryWriterListener* listener);
BRepositoryWriterListener* listener,
const BRepositoryInfo* repositoryInfo);
~RepositoryWriterImpl();
status_t Init(const char* fileName);
status_t AddPackage(const BEntry& packageEntry);
status_t Finish();
private:
// BPackageContentHandler
virtual status_t HandleEntry(BPackageEntry* entry);
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute);
virtual status_t HandleEntryDone(BPackageEntry* entry);
virtual status_t HandlePackageAttribute(
const BPackageInfoAttributeValue& value
);
virtual status_t HandlePackageAttributesDone();
virtual void HandleErrorOccurred();
private:
status_t _Init(const char* fileName);
status_t _AddPackage(const BEntry& packageEntry);
status_t _Finish();
status_t _RegisterCurrentPackageInfo();
status_t _WriteRepositoryInfo(
ssize_t& _repositoryInfoLength);
off_t _WritePackageAttributes(
hpkg_repo_header& header);
hpkg_repo_header& header,
off_t startOffset);
struct PackageNameSet;
private:
BRepositoryWriterListener* fListener;
const BRepositoryInfo* fRepositoryInfo;
BPackageInfo fPackageInfo;
uint32 fPackageCount;
PackageNameSet* fPackageNames;
};

View File

@ -51,6 +51,9 @@ struct hpkg_repo_header {
uint16 version;
uint64 total_size;
// repository header
uint32 repository_header_length;
// package attributes section
uint32 attributes_compression;
uint32 attributes_length_compressed;

View File

@ -264,6 +264,12 @@ struct Volume::PackageLoaderContentHandler : BPackageContentHandler {
return B_OK;
}
virtual status_t HandlePackageAttributesDone()
{
// TODO!
return B_OK;
}
virtual void HandleErrorOccurred()
{
fErrorOccurred = true;

View File

@ -255,6 +255,7 @@ SubInclude HAIKU_TOP src bin mkdos ;
SubInclude HAIKU_TOP src bin mkfs ;
SubInclude HAIKU_TOP src bin multiuser ;
SubInclude HAIKU_TOP src bin package ;
SubInclude HAIKU_TOP src bin package_repo ;
SubInclude HAIKU_TOP src bin patch ;
SubInclude HAIKU_TOP src bin pc ;
SubInclude HAIKU_TOP src bin pcmcia-cs ;

View File

@ -88,7 +88,7 @@ public:
printf("TOC size: %10llu\n", tocSize);
printf("package attributes size: %10lu\n", packageAttributesSize);
printf("total size: %10llu\n", totalSize);
printf("-----------------------------------\n");
}
private:

View File

@ -229,6 +229,11 @@ struct PackageContentExtractHandler : BPackageContentHandler {
return B_OK;
}
virtual status_t HandlePackageAttributesDone()
{
return B_OK;
}
virtual void HandleErrorOccurred()
{
fErrorOccurred = true;

View File

@ -144,7 +144,7 @@ struct PackageContentListHandler : BPackageContentHandler {
break;
case B_PACKAGE_INFO_ARCHITECTURE:
printf("\tarchitecure: %s\n",
printf("\tarchitecture: %s\n",
BPackageInfo::kArchitectureNames[value.unsignedInt]);
break;
@ -226,6 +226,11 @@ struct PackageContentListHandler : BPackageContentHandler {
return B_OK;
}
virtual status_t HandlePackageAttributesDone()
{
return B_OK;
}
virtual void HandleErrorOccurred()
{
}

View File

@ -13,8 +13,6 @@
#include <stdlib.h>
#include <string.h>
#include <package/hpkg/PackageWriter.h>
extern const char* __progname;
const char* kCommandName = __progname;
@ -28,7 +26,9 @@ static const char* kUsage =
" create [ <options> ] <package>\n"
" Creates package file <package> from contents of current directory.\n"
"\n"
" -C <dir> - Change to directory <dir> before starting.\n"
" -C <dir> - Change to directory <dir> before starting.\n"
" -q - be quiet (don't show any output except for errors).\n"
" -v - be verbose (show more info about created package).\n"
"\n"
" dump [ <options> ] <package>\n"
" Dumps the TOC section of package file <package>. For debugging only.\n"
@ -36,7 +36,7 @@ static const char* kUsage =
" extract [ <options> ] <package>\n"
" Extracts the contents of package file <package>.\n"
"\n"
" -C <dir> - Change to directory <dir> before extracting the "
" -C <dir> - Change to directory <dir> before extracting the "
"contents\n"
" of the archive.\n"
"\n"

View File

@ -0,0 +1,20 @@
SubDir HAIKU_TOP src bin package_repo ;
UsePrivateHeaders kernel shared ;
DEFINES += B_ENABLE_INCOMPLETE_POSIX_AT_SUPPORT ;
# TODO: Remove when it is complete!
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src bin package ] ;
BinCommand package_repo :
BlockBufferCacheNoLock.cpp
command_create.cpp
command_list.cpp
package_repo.cpp
StandardErrorOutput.cpp
:
package be
$(TARGET_LIBSUPC++)
;

View File

@ -0,0 +1,218 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#include <dirent.h>
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Entry.h>
#include <Path.h>
#include <package/hpkg/HPKGDefs.h>
#include <package/hpkg/RepositoryWriter.h>
#include <package/PackageInfo.h>
#include <package/RepositoryInfo.h>
#include "package.h"
#include "StandardErrorOutput.h"
using BPackageKit::BHPKG::BRepositoryWriterListener;
using BPackageKit::BHPKG::BRepositoryWriter;
using namespace BPackageKit;
class RepositoryWriterListener : public BRepositoryWriterListener {
public:
RepositoryWriterListener(bool verbose, bool quiet)
: fVerbose(verbose), fQuiet(quiet)
{
}
virtual void PrintErrorVarArgs(const char* format, va_list args)
{
vfprintf(stderr, format, args);
}
virtual void OnPackageAdded(const BPackageInfo& packageInfo)
{
if (fQuiet)
return;
printf("%s (%s)\n", packageInfo.Name().String(),
packageInfo.Version().ToString().String());
if (fVerbose) {
printf("\tsummary: %s\n", packageInfo.Summary().String());
printf("\tvendor: %s\n", packageInfo.Vendor().String());
printf("\tpackager: %s\n", packageInfo.Packager().String());
if (uint32 flags = packageInfo.Flags()) {
printf("\tflags:\n");
if ((flags & B_PACKAGE_FLAG_APPROVE_LICENSE) != 0)
printf("\t\tapprove_license\n");
if ((flags & B_PACKAGE_FLAG_SYSTEM_PACKAGE) != 0)
printf("\t\tsystem_package\n");
}
}
}
virtual void OnPackageAttributesSizeInfo(uint32 stringCount,
uint32 uncompressedSize)
{
if (fQuiet || !fVerbose)
return;
printf("----- Package Attribute Info ---------------------\n");
printf("string count: %10lu\n", stringCount);
printf("package attributes size: %10lu (uncompressed)\n",
uncompressedSize);
}
virtual void OnRepositorySizeInfo(uint32 headerSize,
uint32 repositoryInfoSize, uint32 packageCount,
uint32 packageAttributesSize, uint64 totalSize)
{
if (fQuiet)
return;
printf("----- Package Repository Info -----\n");
printf("package count %10lu\n", packageCount);
printf("-----------------------------------\n");
printf("header size: %10lu\n", headerSize);
printf("repository header size: %10lu\n", repositoryInfoSize);
printf("package attributes size: %10lu\n", packageAttributesSize);
printf("total size: %10llu\n", totalSize);
printf("-----------------------------------\n");
}
private:
bool fVerbose;
bool fQuiet;
};
int
command_create(int argc, const char* const* argv)
{
const char* changeToDirectory = NULL;
bool quiet = false;
bool verbose = false;
while (true) {
static struct option sLongOptions[] = {
{ "help", no_argument, 0, 'h' },
{ "quiet", no_argument, 0, 'q' },
{ "verbose", no_argument, 0, 'v' },
{ 0, 0, 0, 0 }
};
opterr = 0; // don't print errors
int c = getopt_long(argc, (char**)argv, "+C:hqv", sLongOptions, NULL);
if (c == -1)
break;
switch (c) {
case 'C':
changeToDirectory = optarg;
break;
case 'h':
print_usage_and_exit(false);
break;
case 'q':
quiet = true;
break;
case 'v':
verbose = true;
break;
default:
print_usage_and_exit(true);
break;
}
}
// The remaining arguments are the repository info file plus one or more
// package files, i.e. at least two more arguments.
if (optind + 2 >= argc)
print_usage_and_exit(true);
const char* repositoryInfoFileName = argv[optind++];
const char* const* packageFileNames = argv + optind;
RepositoryWriterListener listener(verbose, quiet);
BEntry repositoryInfoEntry(repositoryInfoFileName);
if (!repositoryInfoEntry.Exists()) {
listener.PrintError(
"Error: given repository-info file '%s' doesn't exist!\n",
repositoryInfoFileName);
return 1;
}
// determine path for 'repo' file from given info file
BEntry repositoryParentEntry;
repositoryInfoEntry.GetParent(&repositoryParentEntry);
BPath repositoryPath;
if (repositoryParentEntry.GetPath(&repositoryPath) != B_OK) {
listener.PrintError(
"Error: can't determine path of given repository-info file!\n");
return 1;
}
repositoryPath.Append("repo");
// create repository
BRepositoryInfo repositoryInfo(repositoryInfoEntry);
status_t result = repositoryInfo.InitCheck();
if (result != B_OK) {
listener.PrintError(
"Error: can't parse given repository-info file : %s\n",
strerror(result));
return 1;
}
BRepositoryWriter repositoryWriter(&listener, &repositoryInfo);
if ((result = repositoryWriter.Init(repositoryPath.Path())) != B_OK) {
listener.PrintError("Error: can't initialize repository-writer : %s\n",
strerror(result));
return 1;
}
// change directory, if requested
if (changeToDirectory != NULL) {
if (chdir(changeToDirectory) != 0) {
listener.PrintError(
"Error: Failed to change the current working directory to "
"\"%s\": %s\n", changeToDirectory, strerror(errno));
return 1;
}
}
// add all given package files
for (int i = 0; i < argc - optind; ++i) {
if (verbose)
printf("reading package '%s' ...\n", packageFileNames[i]);
BEntry entry(packageFileNames[i]);
result = repositoryWriter.AddPackage(entry);
if (result != B_OK)
return 1;
}
// write the repository
result = repositoryWriter.Finish();
if (result != B_OK)
return 1;
if (verbose) {
printf("\nsuccessfully created repository '%s'\n",
repositoryPath.Path());
}
return 0;
}

View File

@ -0,0 +1,323 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <package/hpkg/PackageContentHandler.h>
#include <package/hpkg/PackageEntry.h>
#include <package/hpkg/PackageEntryAttribute.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
#include <package/hpkg/PackageReader.h>
#include <package/PackageInfo.h>
#include "package.h"
#include "StandardErrorOutput.h"
using namespace BPackageKit::BHPKG;
using namespace BPackageKit;
struct PackageContentListHandler : BPackageContentHandler {
PackageContentListHandler(bool listAttributes)
:
fLevel(0),
fListAttribute(listAttributes)
{
}
virtual status_t HandleEntry(BPackageEntry* entry)
{
fLevel++;
int indentation = (fLevel - 1) * 2;
printf("%*s", indentation, "");
// name and size
printf("%-*s", indentation < 32 ? 32 - indentation : 0, entry->Name());
printf(" %8llu", entry->Data().UncompressedSize());
// time
struct tm* time = localtime(&entry->ModifiedTime().tv_sec);
printf(" %04d-%02d-%02d %02d:%02d:%02d",
1900 + time->tm_year, time->tm_mon + 1, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec);
// file type
mode_t mode = entry->Mode();
if (S_ISREG(mode))
printf(" -");
else if (S_ISDIR(mode))
printf(" d");
else if (S_ISLNK(mode))
printf(" l");
else
printf(" ?");
// permissions
char buffer[4];
printf("%s", _PermissionString(buffer, mode >> 6,
(mode & S_ISUID) != 0));
printf("%s", _PermissionString(buffer, mode >> 3,
(mode & S_ISGID) != 0));
printf("%s", _PermissionString(buffer, mode, false));
// print the symlink path
if (S_ISLNK(mode))
printf(" -> %s", entry->SymlinkPath());
printf("\n");
return B_OK;
}
virtual status_t HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute)
{
if (!fListAttribute)
return B_OK;
int indentation = fLevel * 2;
printf("%*s<", indentation, "");
printf("%-*s %8llu", indentation < 31 ? 31 - indentation : 0,
attribute->Name(), attribute->Data().UncompressedSize());
uint32 type = attribute->Type();
if (isprint(type & 0xff) && isprint((type >> 8) & 0xff)
&& isprint((type >> 16) & 0xff) && isprint(type >> 24)) {
printf(" '%c%c%c%c'", int(type >> 24), int((type >> 16) & 0xff),
int((type >> 8) & 0xff), int(type & 0xff));
} else
printf(" %#lx", type);
printf(">\n");
return B_OK;
}
virtual status_t HandleEntryDone(BPackageEntry* entry)
{
fLevel--;
return B_OK;
}
virtual status_t HandlePackageAttribute(
const BPackageInfoAttributeValue& value)
{
switch (value.attributeIndex) {
case B_PACKAGE_INFO_NAME:
printf("package-attributes:\n");
printf("\tname: %s\n", value.string);
break;
case B_PACKAGE_INFO_SUMMARY:
printf("\tsummary: %s\n", value.string);
break;
case B_PACKAGE_INFO_DESCRIPTION:
printf("\tdescription: %s\n", value.string);
break;
case B_PACKAGE_INFO_VENDOR:
printf("\tvendor: %s\n", value.string);
break;
case B_PACKAGE_INFO_PACKAGER:
printf("\tpackager: %s\n", value.string);
break;
case B_PACKAGE_INFO_FLAGS:
if (value.unsignedInt == 0)
break;
printf("\tflags:\n");
if ((value.unsignedInt & B_PACKAGE_FLAG_APPROVE_LICENSE) != 0)
printf("\t\tapprove_license\n");
if ((value.unsignedInt & B_PACKAGE_FLAG_SYSTEM_PACKAGE) != 0)
printf("\t\tsystem_package\n");
break;
case B_PACKAGE_INFO_ARCHITECTURE:
printf("\tarchitecture: %s\n",
BPackageInfo::kArchitectureNames[value.unsignedInt]);
break;
case B_PACKAGE_INFO_VERSION:
printf("\tversion: %s.%s.%s-%d\n", value.version.major,
value.version.minor, value.version.micro,
value.version.release);
break;
case B_PACKAGE_INFO_COPYRIGHTS:
printf("\tcopyright: %s\n", value.string);
break;
case B_PACKAGE_INFO_LICENSES:
printf("\tlicense: %s\n", value.string);
break;
case B_PACKAGE_INFO_PROVIDES:
printf("\tprovides: %s", value.resolvable.name);
if (value.resolvable.haveVersion) {
printf(" = ");
_PrintPackageVersion(value.resolvable.version);
}
printf("\n");
break;
case B_PACKAGE_INFO_REQUIRES:
printf("\trequires: %s", value.resolvableExpression.name);
if (value.resolvableExpression.haveOpAndVersion) {
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
value.resolvableExpression.op]);
_PrintPackageVersion(value.resolvableExpression.version);
}
printf("\n");
break;
case B_PACKAGE_INFO_SUPPLEMENTS:
printf("\tsupplements: %s", value.resolvableExpression.name);
if (value.resolvableExpression.haveOpAndVersion) {
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
value.resolvableExpression.op]);
_PrintPackageVersion(value.resolvableExpression.version);
}
printf("\n");
break;
case B_PACKAGE_INFO_CONFLICTS:
printf("\tconflicts: %s", value.resolvableExpression.name);
if (value.resolvableExpression.haveOpAndVersion) {
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
value.resolvableExpression.op]);
_PrintPackageVersion(value.resolvableExpression.version);
}
printf("\n");
break;
case B_PACKAGE_INFO_FRESHENS:
printf("\tfreshens: %s", value.resolvableExpression.name);
if (value.resolvableExpression.haveOpAndVersion) {
printf(" %s ", BPackageResolvableExpression::kOperatorNames[
value.resolvableExpression.op]);
_PrintPackageVersion(value.resolvableExpression.version);
}
printf("\n");
break;
case B_PACKAGE_INFO_REPLACES:
printf("\treplaces: %s\n", value.string);
break;
default:
printf(
"*** Invalid package attribute section: unexpected "
"package attribute index %d encountered\n",
value.attributeIndex);
return B_BAD_DATA;
}
return B_OK;
}
virtual status_t HandlePackageAttributesDone()
{
return B_OK;
}
virtual void HandleErrorOccurred()
{
}
private:
static const char* _PermissionString(char* buffer, uint32 mode, bool sticky)
{
buffer[0] = (mode & 0x4) != 0 ? 'r' : '-';
buffer[1] = (mode & 0x2) != 0 ? 'w' : '-';
if ((mode & 0x1) != 0)
buffer[2] = sticky ? 's' : 'x';
else
buffer[2] = '-';
buffer[3] = '\0';
return buffer;
}
static void _PrintPackageVersion(const BPackageVersionData& version)
{
printf("%s", version.major);
if (version.minor != NULL && version.minor[0] != '\0')
printf(".%s", version.minor);
if (version.micro != NULL && version.micro[0] != '\0')
printf(".%s", version.micro);
if (version.release > 0)
printf("-%d", version.release);
}
private:
int fLevel;
bool fListAttribute;
};
int
command_list(int argc, const char* const* argv)
{
bool listAttributes = false;
while (true) {
static struct option sLongOptions[] = {
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
opterr = 0; // don't print errors
int c = getopt_long(argc, (char**)argv, "+ha", sLongOptions, NULL);
if (c == -1)
break;
switch (c) {
case 'a':
listAttributes = true;
break;
case 'h':
print_usage_and_exit(false);
break;
default:
print_usage_and_exit(true);
break;
}
}
// One argument should remain -- the package file name.
if (optind + 1 != argc)
print_usage_and_exit(true);
const char* packageFileName = argv[optind++];
// open package
StandardErrorOutput errorOutput;
BPackageReader packageReader(&errorOutput);
status_t error = packageReader.Init(packageFileName);
printf("Init(): %s\n", strerror(error));
if (error != B_OK)
return 1;
// list
PackageContentListHandler handler(listAttributes);
error = packageReader.ParseContent(&handler);
printf("ParseContent(): %s\n", strerror(error));
if (error != B_OK)
return 1;
return 0;
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#include "package_repo.h"
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern const char* __progname;
const char* kCommandName = __progname;
static const char* kUsage =
"Usage: %s <command> <command args>\n"
"Creates or inspects a Haiku package repository file.\n"
"\n"
"Commands:\n"
" create [ <options> ] <package-repo> <package-file ...> \n"
" Creates package repository file <package-repo> from the given\n"
" package files.\n"
"\n"
" -C <dir> - Change to directory <dir> before starting.\n"
" -q - be quiet (don't show any output except for errors).\n"
" -v - be verbose (list package attributes as encountered).\n"
"\n"
" list [ <options> ] <package-repo>\n"
" Lists the contents of package repository file <package-repo>.\n"
"\n"
" -v - be verbose (list attributes of all packages found).\n"
"\n"
"Common Options:\n"
" -h, --help - Print this usage info.\n"
;
void
print_usage_and_exit(bool error)
{
fprintf(error ? stderr : stdout, kUsage, kCommandName);
exit(error ? 1 : 0);
}
int
main(int argc, const char* const* argv)
{
if (argc < 2)
print_usage_and_exit(true);
const char* command = argv[1];
if (strcmp(command, "create") == 0)
return command_create(argc - 1, argv + 1);
if (strcmp(command, "list") == 0)
return command_list(argc - 1, argv + 1);
if (strcmp(command, "help") == 0)
print_usage_and_exit(false);
else
print_usage_and_exit(true);
// never gets here
return 0;
}

View File

@ -0,0 +1,15 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef PACKAGE_REPO_H
#define PACKAGE_REPO_H
void print_usage_and_exit(bool error);
int command_create(int argc, const char* const* argv);
int command_list(int argc, const char* const* argv);
#endif // PACKAGE_REPO_H

View File

@ -9,14 +9,9 @@
#include <package/ActivateRepositoryConfigJob.h>
#include <File.h>
#include <Message.h>
#include <AutoDeleter.h>
#include <package/Context.h>
#include <package/RepositoryConfig.h>
#include <package/RepositoryHeader.h>
#include <package/RepositoryInfo.h>
namespace BPackageKit {
@ -26,11 +21,11 @@ namespace BPrivate {
ActivateRepositoryConfigJob::ActivateRepositoryConfigJob(
const BContext& context, const BString& title,
const BEntry& archivedRepoHeaderEntry, const BString& repositoryBaseURL,
const BEntry& archivedRepoInfoEntry, const BString& repositoryBaseURL,
const BDirectory& targetDirectory)
:
inherited(context, title),
fArchivedRepoHeaderEntry(archivedRepoHeaderEntry),
fArchivedRepoInfoEntry(archivedRepoInfoEntry),
fRepositoryBaseURL(repositoryBaseURL),
fTargetDirectory(targetDirectory)
{
@ -45,26 +40,15 @@ ActivateRepositoryConfigJob::~ActivateRepositoryConfigJob()
status_t
ActivateRepositoryConfigJob::Execute()
{
BFile archiveFile(&fArchivedRepoHeaderEntry, B_READ_ONLY);
status_t result = archiveFile.InitCheck();
BRepositoryInfo repoInfo(fArchivedRepoInfoEntry);
status_t result = repoInfo.InitCheck();
if (result != B_OK)
return result;
BMessage archive;
if ((result = archive.Unflatten(&archiveFile)) != B_OK)
return result;
BRepositoryHeader* repoHeader = BRepositoryHeader::Instantiate(&archive);
if (repoHeader == NULL)
return B_BAD_DATA;
ObjectDeleter<BRepositoryHeader> repoHeaderDeleter(repoHeader);
if ((result = repoHeader->InitCheck()) != B_OK)
return result;
fTargetEntry.SetTo(&fTargetDirectory, repoHeader->Name().String());
fTargetEntry.SetTo(&fTargetDirectory, repoInfo.Name().String());
if (fTargetEntry.Exists()) {
BString description = BString("A repository configuration for ")
<< repoHeader->Name() << " already exists.";
<< repoInfo.Name() << " already exists.";
BString question("overwrite?");
bool yes = fContext.DecisionProvider().YesNoDecisionNeeded(
description, question, "yes", "no", "no");
@ -77,9 +61,9 @@ ActivateRepositoryConfigJob::Execute()
// create and store the configuration (injecting the BaseURL that was
// actually used)
BRepositoryConfig repoConfig;
repoConfig.SetName(repoHeader->Name());
repoConfig.SetName(repoInfo.Name());
repoConfig.SetBaseURL(fRepositoryBaseURL);
repoConfig.SetPriority(repoHeader->Priority());
repoConfig.SetPriority(repoInfo.Priority());
if ((result = repoConfig.Store(fTargetEntry)) != B_OK)
return result;

View File

@ -48,13 +48,13 @@ AddRepositoryRequest::CreateInitialJobs()
return B_NO_INIT;
BEntry tempEntry;
result = fContext.GetNewTempfile("repoheader-", &tempEntry);
result = fContext.GetNewTempfile("repoinfo-", &tempEntry);
if (result != B_OK)
return result;
BString repoHeaderURL = BString(fRepositoryBaseURL) << "/" << "repo.header";
BString repoInfoURL = BString(fRepositoryBaseURL) << "/" << "repo.info";
FetchFileJob* fetchJob = new (std::nothrow) FetchFileJob(fContext,
BString("Fetching repository header from ") << fRepositoryBaseURL,
repoHeaderURL, tempEntry);
BString("Fetching repository info from ") << fRepositoryBaseURL,
repoInfoURL, tempEntry);
if (fetchJob == NULL)
return B_NO_MEMORY;
if ((result = QueueJob(fetchJob)) != B_OK) {

View File

@ -25,6 +25,7 @@ HPKG_SOURCES =
PackageReaderImpl.cpp
PackageWriter.cpp
PackageWriterImpl.cpp
RepositoryWriter.cpp
RepositoryWriterImpl.cpp
Strings.cpp
WriterImplBase.cpp
@ -56,7 +57,7 @@ SharedLibrary libpackage.so
RemoveRepositoryJob.cpp
RepositoryCache.cpp
RepositoryConfig.cpp
RepositoryHeader.cpp
RepositoryInfo.cpp
Request.cpp
TempfileManager.cpp
ValidateChecksumJob.cpp

View File

@ -809,6 +809,7 @@ const char* BPackageInfo::kElementNames[B_PACKAGE_INFO_ENUM_COUNT] = {
"freshens",
"replaces",
"flags",
"checksum", // not being parsed, computed externally
};
@ -936,6 +937,13 @@ BPackageInfo::Packager() const
}
const BString&
BPackageInfo::Checksum() const
{
return fChecksum;
}
uint32
BPackageInfo::Flags() const
{
@ -1048,6 +1056,13 @@ BPackageInfo::SetPackager(const BString& packager)
}
void
BPackageInfo::SetChecksum(const BString& checksum)
{
fChecksum = checksum;
}
void
BPackageInfo::SetVersion(const BPackageVersion& version)
{
@ -1226,8 +1241,10 @@ BPackageInfo::Clear()
fDescription.Truncate(0);
fVendor.Truncate(0);
fPackager.Truncate(0);
fVersion.Clear();
fChecksum.Truncate(0);
fFlags = 0;
fArchitecture = B_PACKAGE_ARCHITECTURE_ENUM_COUNT;
fVersion.Clear();
fCopyrightList.MakeEmpty();
fLicenseList.MakeEmpty();
fRequiresList.MakeEmpty();
@ -1239,4 +1256,17 @@ BPackageInfo::Clear()
}
/*static*/ status_t
BPackageInfo::GetArchitectureByName(const BString& name,
BPackageArchitecture& _architecture)
{
for (int i = 0; i < B_PACKAGE_ARCHITECTURE_ENUM_COUNT; ++i) {
if (name.ICompare(kArchitectureNames[i]) == 0) {
_architecture = (BPackageArchitecture)i;
return B_OK;
}
}
return B_NAME_NOT_FOUND;
}
} // namespace BPackageKit

View File

@ -6,6 +6,8 @@
#include <package/PackageResolvable.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
namespace BPackageKit {
@ -27,6 +29,15 @@ BPackageResolvable::BPackageResolvable()
}
BPackageResolvable::BPackageResolvable(const BPackageResolvableData& data)
:
fName(data.name),
fType(data.type),
fVersion(data.version)
{
}
BPackageResolvable::BPackageResolvable(const BString& name,
BPackageResolvableType type, const BPackageVersion& version)
:

View File

@ -6,6 +6,8 @@
#include <package/PackageResolvableExpression.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
namespace BPackageKit {
@ -29,6 +31,16 @@ BPackageResolvableExpression::BPackageResolvableExpression()
}
BPackageResolvableExpression::BPackageResolvableExpression(
const BPackageResolvableExpressionData& data)
:
fName(data.name),
fOperator(data.op),
fVersion(data.version)
{
}
BPackageResolvableExpression::BPackageResolvableExpression(const BString& name,
BPackageResolvableOperator _operator, const BPackageVersion& version)
:
@ -46,10 +58,8 @@ BPackageResolvableExpression::InitCheck() const
return B_NO_INIT;
// either both or none of operator and version must be set
if ((fOperator == B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT
&& fVersion.InitCheck() == B_OK)
|| (fOperator >= 0 && fOperator < B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT
&& fVersion.InitCheck() != B_OK))
if ((fOperator >= 0 && fOperator < B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT)
!= (fVersion.InitCheck() == B_OK))
return B_NO_INIT;
return B_OK;

View File

@ -8,6 +8,8 @@
#include <NaturalCompare.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
using BPrivate::NaturalCompare;
@ -20,6 +22,16 @@ BPackageVersion::BPackageVersion()
}
BPackageVersion::BPackageVersion(const BPackageVersionData& data)
:
fMajor(data.major),
fMinor(data.minor),
fMicro(data.micro),
fRelease(data.release)
{
}
BPackageVersion::BPackageVersion(const BString& major, const BString& minor,
const BString& micro, uint8 release)
:

View File

@ -55,10 +55,10 @@ BRepositoryCache::Entry() const
}
const BRepositoryHeader&
BRepositoryCache::Header() const
const BRepositoryInfo&
BRepositoryCache::Info() const
{
return fHeader;
return fInfo;
}
@ -90,7 +90,7 @@ BRepositoryCache::SetTo(const BEntry& entry)
if ((result = headerMsg.Unflatten(&file)) != B_OK)
return result;
if ((result = fHeader.SetTo(&headerMsg)) != B_OK)
if ((result = fInfo.SetTo(&headerMsg)) != B_OK)
return result;
BPath userSettingsPath;

View File

@ -1,202 +0,0 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/RepositoryHeader.h>
#include <new>
namespace BPackageKit {
const uint8 BRepositoryHeader::kDefaultPriority = 50;
const char* BRepositoryHeader::kNameField = "name";
const char* BRepositoryHeader::kURLField = "url";
const char* BRepositoryHeader::kVendorField = "vendor";
const char* BRepositoryHeader::kShortDescriptionField = "shortDescr";
const char* BRepositoryHeader::kLongDescriptionField = "longDescr";
const char* BRepositoryHeader::kPriorityField = "priority";
BRepositoryHeader::BRepositoryHeader()
:
fInitStatus(B_NO_INIT),
fPriority(kDefaultPriority)
{
}
BRepositoryHeader::BRepositoryHeader(BMessage* data)
:
inherited(data)
{
fInitStatus = SetTo(data);
}
BRepositoryHeader::~BRepositoryHeader()
{
}
/*static*/ BRepositoryHeader*
BRepositoryHeader::Instantiate(BMessage* data)
{
if (validate_instantiation(data, "BPackageKit::BRepositoryHeader"))
return new (std::nothrow) BRepositoryHeader(data);
return NULL;
}
status_t
BRepositoryHeader::Archive(BMessage* data, bool deep) const
{
status_t result = inherited::Archive(data, deep);
if (result != B_OK)
return result;
if ((result = data->AddString(kNameField, fName)) != B_OK)
return result;
if ((result = data->AddString(kURLField, fOriginalBaseURL)) != B_OK)
return result;
if ((result = data->AddString(kVendorField, fVendor)) != B_OK)
return result;
result = data->AddString(kShortDescriptionField, fShortDescription);
if (result != B_OK)
return result;
result = data->AddString(kLongDescriptionField, fLongDescription);
if (result != B_OK)
return result;
if ((result = data->AddUInt8(kPriorityField, fPriority)) != B_OK)
return result;
return B_OK;
}
status_t
BRepositoryHeader::InitCheck() const
{
return fInitStatus;
}
status_t
BRepositoryHeader::SetTo(const BMessage* data)
{
if (data == NULL)
return B_BAD_VALUE;
status_t result;
if ((result = data->FindString(kNameField, &fName)) != B_OK)
return result;
if ((result = data->FindString(kURLField, &fOriginalBaseURL)) != B_OK)
return result;
if ((result = data->FindString(kVendorField, &fVendor)) != B_OK)
return result;
result = data->FindString(kShortDescriptionField, &fShortDescription);
if (result != B_OK)
return result;
result = data->FindString(kLongDescriptionField, &fLongDescription);
if (result != B_OK)
return result;
if ((result = data->FindUInt8(kPriorityField, &fPriority)) != B_OK)
return result;
return B_OK;
}
const BString&
BRepositoryHeader::Name() const
{
return fName;
}
const BString&
BRepositoryHeader::OriginalBaseURL() const
{
return fOriginalBaseURL;
}
const BString&
BRepositoryHeader::Vendor() const
{
return fVendor;
}
const BString&
BRepositoryHeader::ShortDescription() const
{
return fShortDescription;
}
const BString&
BRepositoryHeader::LongDescription() const
{
return fLongDescription;
}
uint8
BRepositoryHeader::Priority() const
{
return fPriority;
}
void
BRepositoryHeader::SetName(const BString& name)
{
fName = name;
}
void
BRepositoryHeader::SetOriginalBaseURL(const BString& url)
{
fOriginalBaseURL = url;
}
void
BRepositoryHeader::SetVendor(const BString& vendor)
{
fVendor = vendor;
}
void
BRepositoryHeader::SetShortDescription(const BString& description)
{
fShortDescription = description;
}
void
BRepositoryHeader::SetLongDescription(const BString& description)
{
fLongDescription = description;
}
void
BRepositoryHeader::SetPriority(uint8 priority)
{
fPriority = priority;
}
} // namespace BPackageKit

View File

@ -0,0 +1,284 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/RepositoryInfo.h>
#include <stdlib.h>
#include <new>
#include <driver_settings.h>
#include <File.h>
#include <package/PackageInfo.h>
namespace BPackageKit {
const uint8 BRepositoryInfo::kDefaultPriority = 50;
const char* BRepositoryInfo::kNameField = "name";
const char* BRepositoryInfo::kURLField = "url";
const char* BRepositoryInfo::kVendorField = "vendor";
const char* BRepositoryInfo::kSummaryField = "summary";
const char* BRepositoryInfo::kPriorityField = "priority";
const char* BRepositoryInfo::kArchitectureField = "architecture";
BRepositoryInfo::BRepositoryInfo()
:
fInitStatus(B_NO_INIT),
fPriority(kDefaultPriority),
fArchitecture(B_PACKAGE_ARCHITECTURE_ENUM_COUNT)
{
}
BRepositoryInfo::BRepositoryInfo(BMessage* data)
:
inherited(data)
{
fInitStatus = SetTo(data);
}
BRepositoryInfo::BRepositoryInfo(const BEntry& entry)
{
SetTo(entry);
}
BRepositoryInfo::~BRepositoryInfo()
{
}
/*static*/ BRepositoryInfo*
BRepositoryInfo::Instantiate(BMessage* data)
{
if (validate_instantiation(data, "BPackageKit::BRepositoryInfo"))
return new (std::nothrow) BRepositoryInfo(data);
return NULL;
}
status_t
BRepositoryInfo::Archive(BMessage* data, bool deep) const
{
status_t result = inherited::Archive(data, deep);
if (result != B_OK)
return result;
if ((result = data->AddString(kNameField, fName)) != B_OK)
return result;
if ((result = data->AddString(kURLField, fOriginalBaseURL)) != B_OK)
return result;
if ((result = data->AddString(kVendorField, fVendor)) != B_OK)
return result;
result = data->AddString(kSummaryField, fSummary);
if (result != B_OK)
return result;
if ((result = data->AddUInt8(kPriorityField, fPriority)) != B_OK)
return result;
if ((result = data->AddUInt8(kArchitectureField, fArchitecture)) != B_OK)
return result;
return B_OK;
}
status_t
BRepositoryInfo::InitCheck() const
{
return fInitStatus;
}
status_t
BRepositoryInfo::SetTo(const BMessage* data)
{
if (data == NULL)
return B_BAD_VALUE;
status_t result;
if ((result = data->FindString(kNameField, &fName)) != B_OK)
return result;
if ((result = data->FindString(kURLField, &fOriginalBaseURL)) != B_OK)
return result;
if ((result = data->FindString(kVendorField, &fVendor)) != B_OK)
return result;
result = data->FindString(kSummaryField, &fSummary);
if (result != B_OK)
return result;
if ((result = data->FindUInt8(kPriorityField, &fPriority)) != B_OK)
return result;
result = data->FindUInt8(kArchitectureField, (uint8*)&fArchitecture);
if (result != B_OK)
return result;
return B_OK;
}
status_t
BRepositoryInfo::SetTo(const BEntry& entry)
{
BFile file(&entry, B_READ_ONLY);
status_t result = file.InitCheck();
if (result != B_OK)
return result;
off_t size;
if ((result = file.GetSize(&size)) != B_OK)
return result;
BString configString;
char* buffer = configString.LockBuffer(size);
if (buffer == NULL)
return B_NO_MEMORY;
if ((result = file.Read(buffer, size)) < size) {
configString.UnlockBuffer(0);
return (result >= 0) ? B_IO_ERROR : result;
}
buffer[size] = '\0';
configString.UnlockBuffer(size);
void* settingsHandle = parse_driver_settings_string(configString.String());
if (settingsHandle == NULL)
return B_BAD_DATA;
const char* name = get_driver_parameter(settingsHandle, "name", NULL, NULL);
const char* url = get_driver_parameter(settingsHandle, "url", NULL, NULL);
const char* vendor
= get_driver_parameter(settingsHandle, "vendor", NULL, NULL);
const char* summary
= get_driver_parameter(settingsHandle, "summary", NULL, NULL);
const char* priorityString
= get_driver_parameter(settingsHandle, "priority", NULL, NULL);
const char* architectureString
= get_driver_parameter(settingsHandle, "architecture", NULL, NULL);
unload_driver_settings(settingsHandle);
if (name == NULL || *name == '\0' || url == NULL || *url == '\0'
|| vendor == NULL || *vendor == '\0'
|| summary == NULL || *summary == '\0'
|| priorityString == NULL || *priorityString == '\0'
|| architectureString == NULL || *architectureString == '\0') {
return B_BAD_DATA;
}
BPackageArchitecture architecture;
if (BPackageInfo::GetArchitectureByName(architectureString, architecture)
!= B_OK) {
return B_BAD_DATA;
}
fName = name;
fOriginalBaseURL = url;
fVendor = vendor;
fSummary = summary;
fPriority = atoi(priorityString);
fArchitecture = architecture;
fInitStatus = B_OK;
return B_OK;
}
const BString&
BRepositoryInfo::Name() const
{
return fName;
}
const BString&
BRepositoryInfo::OriginalBaseURL() const
{
return fOriginalBaseURL;
}
const BString&
BRepositoryInfo::Vendor() const
{
return fVendor;
}
const BString&
BRepositoryInfo::Summary() const
{
return fSummary;
}
uint8
BRepositoryInfo::Priority() const
{
return fPriority;
}
BPackageArchitecture
BRepositoryInfo::Architecture() const
{
return fArchitecture;
}
void
BRepositoryInfo::SetName(const BString& name)
{
fName = name;
}
void
BRepositoryInfo::SetOriginalBaseURL(const BString& url)
{
fOriginalBaseURL = url;
}
void
BRepositoryInfo::SetVendor(const BString& vendor)
{
fVendor = vendor;
}
void
BRepositoryInfo::SetSummary(const BString& summary)
{
fSummary = summary;
}
void
BRepositoryInfo::SetPriority(uint8 priority)
{
fPriority = priority;
}
void
BRepositoryInfo::SetArchitecture(BPackageArchitecture architecture)
{
fArchitecture = architecture;
}
} // namespace BPackageKit

View File

@ -1134,8 +1134,10 @@ PackageReaderImpl::_ParsePackageAttributes(AttributeHandlerContext* context)
if (error != B_OK)
return error;
if (tag == 0)
return B_OK;
if (tag == 0) {
return
context->packageContentHandler->HandlePackageAttributesDone();
}
switch (id) {
case HPKG_PACKAGE_ATTRIBUTE_NAME:

View File

@ -9,6 +9,7 @@
#include <new>
#include <package/hpkg/RepositoryWriterImpl.h>
#include <package/RepositoryInfo.h>
namespace BPackageKit {
@ -16,9 +17,10 @@ namespace BPackageKit {
namespace BHPKG {
BRepositoryWriter::BRepositoryWriter(BRepositoryWriterListener* listener)
BRepositoryWriter::BRepositoryWriter(BRepositoryWriterListener* listener,
const BRepositoryInfo* repositoryInfo)
:
fImpl(new (std::nothrow) RepositoryWriterImpl(listener))
fImpl(new (std::nothrow) RepositoryWriterImpl(listener, repositoryInfo))
{
}

View File

@ -8,12 +8,17 @@
#include <algorithm>
#include <new>
#include <set>
#include <ByteOrder.h>
#include <Message.h>
#include <Path.h>
#include <package/hpkg/haiku_package.h>
#include <package/PackageInfo.h>
#include <package/hpkg/PackageInfoAttributeValue.h>
#include <package/hpkg/PackageReader.h>
#include <package/ChecksumAccessors.h>
#include <package/RepositoryInfo.h>
namespace BPackageKit {
@ -23,16 +28,28 @@ namespace BHPKG {
namespace BPrivate {
RepositoryWriterImpl::RepositoryWriterImpl(BRepositoryWriterListener* listener)
using BPackageKit::BPrivate::GeneralFileChecksumAccessor;
struct RepositoryWriterImpl::PackageNameSet : public std::set<BString> {
};
RepositoryWriterImpl::RepositoryWriterImpl(BRepositoryWriterListener* listener,
const BRepositoryInfo* repositoryInfo)
:
WriterImplBase(listener),
fListener(listener)
fListener(listener),
fRepositoryInfo(repositoryInfo),
fPackageCount(0),
fPackageNames(NULL)
{
}
RepositoryWriterImpl::~RepositoryWriterImpl()
{
delete fPackageNames;
}
@ -40,6 +57,7 @@ status_t
RepositoryWriterImpl::Init(const char* fileName)
{
try {
fPackageNames = new PackageNameSet();
return _Init(fileName);
} catch (status_t error) {
return error;
@ -78,6 +96,129 @@ RepositoryWriterImpl::Finish()
}
status_t
RepositoryWriterImpl::HandleEntry(BPackageEntry* entry)
{
return B_OK;
}
status_t
RepositoryWriterImpl::HandleEntryAttribute(BPackageEntry* entry,
BPackageEntryAttribute* attribute)
{
return B_OK;
}
status_t
RepositoryWriterImpl::HandleEntryDone(BPackageEntry* entry)
{
return B_OK;
}
status_t
RepositoryWriterImpl::HandlePackageAttribute(
const BPackageInfoAttributeValue& value)
{
switch (value.attributeIndex) {
case B_PACKAGE_INFO_NAME:
fPackageInfo.SetName(value.string);
break;
case B_PACKAGE_INFO_SUMMARY:
fPackageInfo.SetSummary(value.string);
break;
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;
default:
fListener->PrintError(
"Invalid package attribute section: unexpected package "
"attribute index %d encountered\n", value.attributeIndex);
return B_BAD_DATA;
}
return B_OK;
}
status_t
RepositoryWriterImpl::HandlePackageAttributesDone()
{
status_t result = _RegisterCurrentPackageInfo();
fPackageInfo.Clear();
return result;
}
void
RepositoryWriterImpl::HandleErrorOccurred()
{
}
status_t
RepositoryWriterImpl::_Init(const char* fileName)
{
@ -90,15 +231,24 @@ RepositoryWriterImpl::_Finish()
{
hpkg_repo_header header;
// write package attributes
off_t totalSize = _WritePackageAttributes(header);
// write repository header
ssize_t repositoryInfoLength;
status_t result = _WriteRepositoryInfo(repositoryInfoLength);
if (result != B_OK)
return result;
fListener->OnRepositorySizeInfo(sizeof(header),
header.repository_header_length
= B_HOST_TO_BENDIAN_INT32(repositoryInfoLength);
// write package attributes
off_t totalSize = _WritePackageAttributes(header,
sizeof(header) + repositoryInfoLength);
fListener->OnRepositorySizeInfo(sizeof(header), repositoryInfoLength,
fPackageCount,
B_BENDIAN_TO_HOST_INT32(header.attributes_length_compressed),
totalSize);
// prepare the header
// general
header.magic = B_HOST_TO_BENDIAN_INT32(B_HPKG_REPO_MAGIC);
header.header_size = B_HOST_TO_BENDIAN_INT16((uint16)sizeof(header));
@ -116,17 +266,119 @@ RepositoryWriterImpl::_Finish()
status_t
RepositoryWriterImpl::_AddPackage(const BEntry& packageEntry)
{
// TODO!
status_t result = packageEntry.InitCheck();
if (result != B_OK) {
fListener->PrintError("entry not initialized!\n");
return result;
}
BPath packagePath;
if ((result = packageEntry.GetPath(&packagePath)) != B_OK) {
fListener->PrintError("can't get path for entry!\n");
return result;
}
BPackageReader packageReader(fListener);
if ((result = packageReader.Init(packagePath.Path())) != B_OK) {
fListener->PrintError("can't create package reader!\n");
return result;
}
fPackageInfo.Clear();
GeneralFileChecksumAccessor checksumAccessor(packageEntry);
BString checksum;
if ((result = checksumAccessor.GetChecksum(checksum)) != B_OK) {
fListener->PrintError("can't compute checksum!\n");
return result;
}
fPackageInfo.SetChecksum(checksum);
return packageReader.ParseContent(this);
}
status_t
RepositoryWriterImpl::_RegisterCurrentPackageInfo()
{
status_t result = fPackageInfo.InitCheck();
if (result != B_OK) {
fListener->PrintError("package %s has incomplete package-info!\n",
fPackageInfo.Name().String());
return result;
}
// reject package with a name that we've seen already
PackageNameSet::const_iterator namePos
= fPackageNames->find(fPackageInfo.Name());
if (namePos != fPackageNames->end()) {
fListener->PrintError("package %s has already been added!\n",
fPackageInfo.Name().String());
return B_NAME_IN_USE;
}
// all packages must have the same vendor as the repository
const BString& expectedVendor = fRepositoryInfo->Vendor();
if (fPackageInfo.Vendor().ICompare(expectedVendor) != 0) {
fListener->PrintError("package '%s' has unexpected vendor '%s' "
"(expected '%s')!\n", fPackageInfo.Name().String(),
fPackageInfo.Vendor().String(), expectedVendor.String());
return B_BAD_DATA;
}
// all packages must have an architecture that's compatible with the one
// used by the repository
BPackageArchitecture expectedArchitecture = fRepositoryInfo->Architecture();
if (fPackageInfo.Architecture() != expectedArchitecture
&& fPackageInfo.Architecture() != B_PACKAGE_ARCHITECTURE_ANY) {
fListener->PrintError(
"package '%s' has non-matching architecture '%s' "
"(expected '%s' or '%s')!\n", fPackageInfo.Name().String(),
BPackageInfo::kArchitectureNames[fPackageInfo.Architecture()],
BPackageInfo::kArchitectureNames[expectedArchitecture],
BPackageInfo::kArchitectureNames[B_PACKAGE_ARCHITECTURE_ANY]
);
return B_BAD_DATA;
}
fPackageNames->insert(fPackageInfo.Name());
RegisterPackageInfo(PackageAttributes(), fPackageInfo);
fPackageCount++;
fListener->OnPackageAdded(fPackageInfo);
return B_OK;
}
status_t
RepositoryWriterImpl::_WriteRepositoryInfo(ssize_t& _repositoryInfoLength)
{
BMessage archive;
status_t result = fRepositoryInfo->Archive(&archive);
if (result != B_OK) {
fListener->PrintError("can't archive repository header!\n");
return result;
}
_repositoryInfoLength = archive.FlattenedSize();
char buffer[_repositoryInfoLength];
if ((result = archive.Flatten(buffer, _repositoryInfoLength)) != B_OK) {
fListener->PrintError("can't flatten repository header!\n");
return result;
}
off_t startOffset = sizeof(hpkg_repo_header);
WriteBuffer(buffer, _repositoryInfoLength, startOffset);
return B_OK;
}
off_t
RepositoryWriterImpl::_WritePackageAttributes(hpkg_repo_header& header)
RepositoryWriterImpl::_WritePackageAttributes(hpkg_repo_header& header,
off_t startOffset)
{
// write the package attributes (zlib writer on top of a file writer)
off_t startOffset = sizeof(header);
FDDataWriter realWriter(FD(), startOffset, fListener);
ZlibDataWriter zlibWriter(&realWriter);
SetDataWriter(&zlibWriter);

View File

@ -5,7 +5,7 @@
#include <Message.h>
#include <String.h>
#include <package/RepositoryHeader.h>
#include <package/RepositoryInfo.h>
using namespace BPackageKit;
@ -20,20 +20,20 @@ main(int argc, const char** argv)
return 1;
}
BRepositoryHeader repoHeader;
repoHeader.SetName(argv[1]);
repoHeader.SetOriginalBaseURL(argv[2]);
repoHeader.SetPriority(atoi(argv[3]));
BRepositoryInfo repoInfo;
repoInfo.SetName(argv[1]);
repoInfo.SetOriginalBaseURL(argv[2]);
repoInfo.SetPriority(atoi(argv[3]));
BMessage repoHeaderArchive;
status_t result = repoHeader.Archive(&repoHeaderArchive);
BMessage repoInfoArchive;
status_t result = repoInfo.Archive(&repoInfoArchive);
if (result != B_OK) {
fprintf(stderr, "couldn't archive repository-header\n");
return 1;
}
BFile output(argv[1], B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
if ((result = repoHeaderArchive.Flatten(&output)) != B_OK) {
if ((result = repoInfoArchive.Flatten(&output)) != B_OK) {
fprintf(stderr, "couldn't flatten repository-header archive\n");
return 1;
}