* more work on the package kit, repositories can now be added and

refreshed


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40280 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Tappe 2011-01-24 20:48:03 +00:00
parent 77a8a5cce3
commit 35edda8f0b
40 changed files with 1507 additions and 263 deletions

View File

@ -17,20 +17,36 @@ namespace Haiku {
namespace Package {
namespace Private {
class ActivateRepositoryConfigJob;
}
using Private::ActivateRepositoryConfigJob;
class AddRepositoryRequest : public Request {
typedef Request inherited;
public:
AddRepositoryRequest(const Context& context,
const BString& repositoryURL,
const BString& repositoryBaseURL,
bool asUserRepository);
virtual ~AddRepositoryRequest();
virtual status_t CreateJobsToRun(JobQueue& jobQueue);
virtual status_t CreateInitialJobs();
const BString& RepositoryName() const;
protected:
// JobStateListener
virtual void JobSucceeded(Job* job);
private:
BString fRepositoryURL;
BString fRepositoryBaseURL;
bool fAsUserRepository;
ActivateRepositoryConfigJob* fActivateJob;
BString fRepositoryName;
};

View File

@ -0,0 +1,31 @@
/*
* Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__ATTRIBUTES_H_
#define _HAIKU__PACKAGE__ATTRIBUTES_H_
namespace Haiku {
namespace Package {
// attributes used in package and as file attribute, too
extern const char* kNameAttribute;
extern const char* kVendorAttribute;
extern const char* kVersionAttribute;
// attributes kept local to packages
extern const char* kCopyrightAttribute;
extern const char* kLicenseAttribute;
extern const char* kProvidesAttribute;
extern const char* kRequiresAttribute;
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__ATTRIBUTES_H_

View File

@ -6,7 +6,7 @@
#define _HAIKU__PACKAGE__CONTEXT_H_
#include <package/TempEntryManager.h>
#include <package/TempfileManager.h>
namespace Haiku {
@ -15,6 +15,7 @@ namespace Package {
class JobStateListener;
using Private::TempfileManager;
struct DecisionProvider {
@ -37,7 +38,7 @@ public:
Context(DecisionProvider& decisionProvider);
~Context();
TempEntryManager& GetTempEntryManager() const;
TempfileManager& GetTempfileManager() const;
JobStateListener* GetJobStateListener() const;
void SetJobStateListener(JobStateListener* listener);
@ -45,7 +46,7 @@ public:
DecisionProvider& GetDecisionProvider() const;
private:
mutable TempEntryManager fTempEntryManager;
mutable TempfileManager fTempfileManager;
DecisionProvider& fDecisionProvider;
JobStateListener* fJobStateListener;
};

View File

@ -18,6 +18,7 @@ namespace Package {
class Context;
class Job;
struct JobStateListener {
virtual ~JobStateListener();
@ -51,6 +52,7 @@ public:
const BString& Title() const;
JobState State() const;
status_t Result() const;
const BString& ErrorString() const;
status_t AddStateListener(JobStateListener* listener);
status_t RemoveStateListener(
@ -65,6 +67,8 @@ protected:
virtual status_t Execute() = 0;
virtual void Cleanup(status_t jobResult);
void SetErrorString(const BString&);
void NotifyStateListeners();
const Context& fContext;
@ -74,6 +78,7 @@ private:
JobState fState;
status_t fResult;
BString fErrorString;
typedef BObjectList<Job> JobList;
JobList fDependencies;

View File

@ -0,0 +1,56 @@
/*
* Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__REFRESH_REPOSITORY_REQUEST_H_
#define _HAIKU__PACKAGE__REFRESH_REPOSITORY_REQUEST_H_
#include <Entry.h>
#include <String.h>
#include <package/Context.h>
#include <package/RepositoryConfig.h>
#include <package/Request.h>
namespace Haiku {
namespace Package {
namespace Private {
class ValidateChecksumJob;
}
using Private::ValidateChecksumJob;
class RefreshRepositoryRequest : public Request {
typedef Request inherited;
public:
RefreshRepositoryRequest(const Context& context,
const RepositoryConfig& repoConfig);
virtual ~RefreshRepositoryRequest();
virtual status_t CreateInitialJobs();
protected:
// JobStateListener
virtual void JobSucceeded(Job* job);
private:
status_t _FetchRepositoryCache();
BEntry fFetchedChecksumFile;
RepositoryConfig fRepoConfig;
ValidateChecksumJob* fValidateChecksumJob;
};
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__REFRESH_REPOSITORY_REQUEST_H_

View File

@ -2,23 +2,52 @@
* Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef _REPOSITORY_H_
#define _REPOSITORY_H_
#ifndef _HAIKU__PACKAGE__REPOSITORY_CACHE_H_
#define _HAIKU__PACKAGE__REPOSITORY_CACHE_H_
#include <Archivable.h>
#include <Entry.h>
#include <String.h>
class BMessage;
class BEntry;
class BRepository {
namespace Haiku {
namespace Package {
//class RepositoryHeader;
class RepositoryCache {
public:
BRepository(const char* url);
RepositoryCache();
RepositoryCache(const BEntry& entry);
virtual ~RepositoryCache();
public:
static BArchivable* Instantiate(BMessage* archive);
status_t SetTo(const BEntry& entry);
status_t InitCheck() const;
// const RepositoryHeader* Header() const;
const BEntry& Entry() const;
bool IsUserSpecific() const;
void SetIsUserSpecific(bool isUserSpecific);
private:
status_t fInitStatus;
BEntry fEntry;
// RepositoryHeader* fHeader;
bool fIsUserSpecific;
};
#endif // _REPOSITORY_H_
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__REPOSITORY_CACHE_H_

View File

@ -7,6 +7,7 @@
#include <Archivable.h>
#include <Entry.h>
#include <String.h>
@ -34,6 +35,8 @@ public:
status_t StoreAsConfigFile(const BEntry& entry) const;
status_t SetTo(const BEntry& entry);
status_t SetTo(const BMessage* data);
status_t InitCheck() const;
const BString& Name() const;
@ -41,6 +44,8 @@ public:
uint8 Priority() const;
bool IsUserSpecific() const;
const BEntry& Entry() const;
void SetName(const BString& name);
void SetURL(const BString& url);
void SetPriority(uint8 priority);
@ -49,21 +54,20 @@ public:
public:
static RepositoryConfig* Instantiate(BMessage* data);
static const uint8 kDefaultPriority = 50;
static const uint8 kDefaultPriority;
static const char* kNameField;
static const char* kURLField;
static const char* kPriorityField;
private:
status_t _InitFrom(const BEntry& entry);
status_t _InitFrom(const BMessage* data);
status_t fInitStatus;
BString fName;
BString fURL;
uint8 fPriority;
bool fIsUserSpecific;
BEntry fEntry;
};

View File

@ -8,6 +8,8 @@
#include <SupportDefs.h>
#include <package/JobQueue.h>
namespace Haiku {
@ -15,23 +17,25 @@ namespace Package {
class Context;
class Job;
class JobQueue;
using Private::JobQueue;
class Request {
class Request : protected JobStateListener {
public:
Request(const Context& context);
virtual ~Request();
virtual status_t CreateJobsToRun(JobQueue& jobQueue) = 0;
virtual status_t CreateInitialJobs() = 0;
const Context& GetContext() const;
Job* PopRunnableJob();
protected:
status_t QueueJob(Job* job, JobQueue& jobQueue) const;
private:
status_t QueueJob(Job* job);
const Context& fContext;
private:
JobQueue fJobQueue;
};

View File

@ -7,10 +7,14 @@
#include <Entry.h>
#include <FindDirectory.h>
#include <Path.h>
#include <SupportDefs.h>
template <class T> class BObjectList;
namespace Haiku {
namespace Package {
@ -25,22 +29,39 @@ struct RepositoryConfigVisitor {
};
class RepositoryCache;
class RepositoryConfig;
class Roster {
public:
Roster();
~Roster();
status_t GetCommonRepositoryCachePath(BPath* path,
bool create = false) const;
status_t GetUserRepositoryCachePath(BPath* path,
bool create = false) const;
status_t GetCommonRepositoryConfigPath(BPath* path,
bool create = false) const;
status_t GetUserRepositoryConfigPath(BPath* path,
bool create = false) const;
status_t GetRepositoryNames(BObjectList<BString>& names);
status_t VisitCommonRepositoryConfigs(
RepositoryConfigVisitor& visitor);
status_t VisitUserRepositoryConfigs(
RepositoryConfigVisitor& visitor);
status_t GetRepositoryCache(const BString& name,
RepositoryCache* repositoryCache);
status_t GetRepositoryConfig(const BString& name,
RepositoryConfig* repositoryConfig);
private:
status_t _GetRepositoryPath(BPath* path, bool create,
directory_which whichDir) const;
status_t _VisitRepositoryConfigs(const BPath& path,
RepositoryConfigVisitor& visitor);

View File

@ -0,0 +1,52 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CACHE_JOB_H_
#define _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CACHE_JOB_H_
#include <Directory.h>
#include <Entry.h>
#include <String.h>
#include <package/Job.h>
namespace Haiku {
namespace Package {
namespace Private {
class ActivateRepositoryCacheJob : public Job {
typedef Job inherited;
public:
ActivateRepositoryCacheJob(
const Context& context,
const BString& title,
const BEntry& fetchedRepoCacheEntry,
const BString& repositoryName,
const BDirectory& targetDirectory);
virtual ~ActivateRepositoryCacheJob();
protected:
virtual status_t Execute();
private:
BEntry fFetchedRepoCacheEntry;
BString fRepositoryName;
BDirectory fTargetDirectory;
};
} // namespace Private
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CACHE_JOB_H_

View File

@ -1,9 +1,9 @@
/*
* Copyright 2011, Haiku, Inc.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#define _HAIKU__PACKAGE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#ifndef _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#define _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#include <Directory.h>
@ -17,6 +17,8 @@ namespace Haiku {
namespace Package {
namespace Private {
class ActivateRepositoryConfigJob : public Job {
typedef Job inherited;
@ -26,23 +28,31 @@ public:
const Context& context,
const BString& title,
const BEntry& archivedRepoConfigEntry,
const BString& repositoryBaseURL,
const BDirectory& targetDirectory);
virtual ~ActivateRepositoryConfigJob();
const BString& RepositoryName() const;
protected:
virtual status_t Execute();
virtual void Cleanup(status_t jobResult);
private:
BEntry fArchivedRepoConfigEntry;
BString fRepositoryBaseURL;
BDirectory fTargetDirectory;
BEntry fTargetEntry;
BString fRepositoryName;
};
} // namespace Private
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#endif // _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_

View File

@ -0,0 +1,61 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__PRIVATE__CHECKSUM_ACCESSORS_H_
#define _HAIKU__PACKAGE__PRIVATE__CHECKSUM_ACCESSORS_H_
#include <Entry.h>
#include <String.h>
namespace Haiku {
namespace Package {
namespace Private {
class ChecksumAccessor {
public:
virtual ~ChecksumAccessor();
virtual status_t GetChecksum(BString& checksum) const = 0;
};
class ChecksumFileChecksumAccessor : public ChecksumAccessor {
public:
ChecksumFileChecksumAccessor(
const BEntry& checksumFileEntry);
virtual status_t GetChecksum(BString& checksum) const;
private:
BEntry fChecksumFileEntry;
};
class GeneralFileChecksumAccessor : public ChecksumAccessor {
public:
GeneralFileChecksumAccessor(
const BEntry& fileEntry,
bool skipMissingFile = false);
virtual status_t GetChecksum(BString& checksum) const;
private:
BEntry fFileEntry;
bool fSkipMissingFile;
};
} // namespace Private
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__PRIVATE__CHECKSUM_ACCESSORS_H_

View File

@ -1,9 +1,9 @@
/*
* Copyright 2011, Haiku, Inc.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__FETCH_FILE_JOB_H_
#define _HAIKU__PACKAGE__FETCH_FILE_JOB_H_
#ifndef _HAIKU__PACKAGE__PRIVATE__FETCH_FILE_JOB_H_
#define _HAIKU__PACKAGE__PRIVATE__FETCH_FILE_JOB_H_
#include <Entry.h>
@ -16,6 +16,8 @@ namespace Haiku {
namespace Package {
namespace Private {
class FetchFileJob : public Job {
typedef Job inherited;
@ -37,9 +39,11 @@ private:
};
} // namespace Private
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__FETCH_FILE_JOB_H_
#endif // _HAIKU__PACKAGE__PRIVATE__FETCH_FILE_JOB_H_

View File

@ -16,6 +16,8 @@ namespace Haiku {
namespace Package {
namespace Private {
class JobQueue : public JobStateListener {
public:
@ -43,6 +45,8 @@ private:
};
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -1,9 +1,9 @@
/*
* Copyright 2011, Haiku, Inc.
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__TEMP_ENTRY_MANAGER_H_
#define _HAIKU__PACKAGE__TEMP_ENTRY_MANAGER_H_
#ifndef _HAIKU__PACKAGE__PRIVATE__TEMPFILE_MANAGER_H_
#define _HAIKU__PACKAGE__PRIVATE__TEMPFILE_MANAGER_H_
#include <Directory.h>
@ -16,11 +16,13 @@ namespace Haiku {
namespace Package {
namespace Private {
class TempEntryManager {
class TempfileManager {
public:
TempEntryManager();
~TempEntryManager();
TempfileManager();
~TempfileManager();
void SetBaseDirectory(const BDirectory& baseDir);
@ -35,9 +37,11 @@ private:
};
} // namespace Private
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__TEMP_ENTRY_MANAGER_H_
#endif // _HAIKU__PACKAGE__PRIVATE__TEMPFILE_MANAGER_H_

View File

@ -0,0 +1,57 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License.
*/
#ifndef _HAIKU__PACKAGE__PRIVATE__VALIDATE_CHECKSUM_JOB_H_
#define _HAIKU__PACKAGE__PRIVATE__VALIDATE_CHECKSUM_JOB_H_
#include <Directory.h>
#include <Entry.h>
#include <String.h>
#include <package/ChecksumAccessors.h>
#include <package/Job.h>
namespace Haiku {
namespace Package {
namespace Private {
class ValidateChecksumJob : public Job {
typedef Job inherited;
public:
ValidateChecksumJob(
const Context& context,
const BString& title,
ChecksumAccessor* expectedChecksumAccessor,
ChecksumAccessor* realChecksumAccessor,
bool failIfChecksumsDontMatch = true);
virtual ~ValidateChecksumJob();
bool ChecksumsMatch() const;
protected:
virtual status_t Execute();
private:
ChecksumAccessor* fExpectedChecksumAccessor;
ChecksumAccessor* fRealChecksumAccessor;
bool fFailIfChecksumsDontMatch;
bool fChecksumsMatch;
};
} // namespace Private
} // namespace Package
} // namespace Haiku
#endif // _HAIKU__PACKAGE__PRIVATE__VALIDATE_CHECKSUM_JOB_H_

View File

@ -1,10 +1,11 @@
SubDir HAIKU_TOP src bin pkgman ;
UsePrivateHeaders shared support ;
UsePrivateHeaders support ;
BinCommand pkgman :
command_add_repo.cpp
command_list_repos.cpp
command_refresh.cpp
MyDecisionProvider.cpp
MyJobStateListener.cpp
pkgman.cpp

View File

@ -29,6 +29,11 @@ MyJobStateListener::JobSucceeded(Job* job)
void
MyJobStateListener::JobFailed(Job* job)
{
BString error = job->ErrorString();
if (error.Length() > 0) {
error.ReplaceAll("\n", "\n*** ");
fprintf(stderr, "%s", error.String());
}
DIE(job->Result(), "failed!");
}

View File

@ -13,7 +13,8 @@
#include <package/AddRepositoryRequest.h>
#include <package/Context.h>
#include <package/JobQueue.h>
#include <package/RefreshRepositoryRequest.h>
#include <package/Roster.h>
#include "MyDecisionProvider.h"
#include "MyJobStateListener.h"
@ -87,17 +88,32 @@ command_add_repo(int argc, const char* const* argv)
status_t result;
for (int i = 0; i < urlCount; ++i) {
AddRepositoryRequest request(context, repoURLs[i], asUserRepository);
JobQueue jobQueue;
result = request.CreateJobsToRun(jobQueue);
AddRepositoryRequest addRequest(context, repoURLs[i], asUserRepository);
result = addRequest.CreateInitialJobs();
if (result != B_OK)
DIE(result, "unable to create necessary jobs");
while (Job* job = jobQueue.Pop()) {
while (Job* job = addRequest.PopRunnableJob()) {
result = job->Run();
delete job;
if (result == B_CANCELED)
break;
return 1;
}
BString repoName = addRequest.RepositoryName();
Roster roster;
RepositoryConfig repoConfig;
roster.GetRepositoryConfig(repoName, &repoConfig);
RefreshRepositoryRequest refreshRequest(context, repoConfig);
result = refreshRequest.CreateInitialJobs();
if (result != B_OK)
DIE(result, "unable to create necessary jobs");
while (Job* job = refreshRequest.PopRunnableJob()) {
result = job->Run();
delete job;
if (result == B_CANCELED)
return 1;
}
}

View File

@ -43,48 +43,6 @@ print_command_usage_and_exit(bool error)
}
typedef BObjectList<RepositoryConfig> RepositoryConfigList;
struct RepositoryConfigCollector : public RepositoryConfigVisitor {
RepositoryConfigCollector(RepositoryConfigList& _repositoryConfigList);
status_t operator()(const BEntry& entry);
RepositoryConfigList& repositoryConfigList;
};
RepositoryConfigCollector::RepositoryConfigCollector(
RepositoryConfigList& _repositoryConfigList)
:
repositoryConfigList(_repositoryConfigList)
{
}
status_t
RepositoryConfigCollector::operator()(const BEntry& entry)
{
RepositoryConfig* repoConfig = new (std::nothrow) RepositoryConfig(entry);
if (repoConfig == NULL)
DIE(B_NO_MEMORY, "can't create repository-config object");
status_t result = repoConfig->InitCheck();
if (result != B_OK) {
BPath path;
entry.GetPath(&path);
WARN(result, "skipping repository-config '%s'", path.Path());
delete repoConfig;
return B_OK;
// let collector continue
}
return repositoryConfigList.AddItem(repoConfig) ? B_OK : B_NO_MEMORY;
}
int
command_list_repos(int argc, const char* const* argv)
{
@ -121,24 +79,25 @@ command_list_repos(int argc, const char* const* argv)
if (argc != optind)
print_command_usage_and_exit(true);
BObjectList<BString> repositoryNames(20, true);
Roster roster;
RepositoryConfigList repositoryConfigs;
RepositoryConfigCollector repositoryConfigCollector(repositoryConfigs);
status_t result
= roster.VisitCommonRepositoryConfigs(repositoryConfigCollector);
if (result != B_OK && result != B_ENTRY_NOT_FOUND)
DIE(result, "can't collect common repository configs");
status_t result = roster.GetRepositoryNames(repositoryNames);
if (result != B_OK)
DIE(result, "can't collect repository names");
result = roster.VisitUserRepositoryConfigs(repositoryConfigCollector);
if (result != B_OK && result != B_ENTRY_NOT_FOUND)
DIE(result, "can't collect user's repository configs");
int32 count = repositoryConfigs.CountItems();
for (int32 i = 0; i < count; ++i) {
RepositoryConfig* repoConfig = repositoryConfigs.ItemAt(i);
for (int i = 0; i < repositoryNames.CountItems(); ++i) {
const BString& repoName = *(repositoryNames.ItemAt(i));
RepositoryConfig repoConfig;
result = roster.GetRepositoryConfig(repoName, &repoConfig);
if (result != B_OK) {
BPath path;
repoConfig.Entry().GetPath(&path);
WARN(result, "skipping repository-config '%s'", path.Path());
continue;
}
printf(" %s %s\n",
repoConfig->IsUserSpecific() ? "[User]" : " ",
repoConfig->Name().String());
repoConfig.IsUserSpecific() ? "[User]" : " ",
repoConfig.Name().String());
}
return 0;

View File

@ -0,0 +1,119 @@
/*
* Copyright 2011, Oliver Tappe <zooey@hirschkaefere.de>
* Distributed under the terms of the MIT License.
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <Errors.h>
#include <SupportDefs.h>
#include <package/Context.h>
#include <package/RefreshRepositoryRequest.h>
#include <package/Roster.h>
#include "MyDecisionProvider.h"
#include "MyJobStateListener.h"
#include "pkgman.h"
using namespace Haiku::Package;
// TODO: internationalization!
static const char* kCommandUsage =
"Usage: %s refresh [<repo-name> ...]\n"
"Refreshes all or just the given repositories.\n"
"\n"
;
static void
print_command_usage_and_exit(bool error)
{
fprintf(error ? stderr : stdout, kCommandUsage, kProgramName);
exit(error ? 1 : 0);
}
int
command_refresh(int argc, const char* const* argv)
{
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, "hu", sLongOptions, NULL);
if (c == -1)
break;
switch (c) {
case 'h':
print_command_usage_and_exit(false);
break;
default:
print_command_usage_and_exit(true);
break;
}
}
// The remaining arguments are repo names.
const char* const* repoArgs = argv + optind;
int nameCount = argc - optind;
MyDecisionProvider decisionProvider;
Context context(decisionProvider);
MyJobStateListener listener;
context.SetJobStateListener(&listener);
BObjectList<BString> repositoryNames(20, true);
Roster roster;
if (nameCount == 0) {
status_t result = roster.GetRepositoryNames(repositoryNames);
if (result != B_OK)
DIE(result, "can't collect repository names");
} else {
for (int i = 0; i < nameCount; ++i) {
BString* repoName = new (std::nothrow) BString(repoArgs[i]);
if (repoName == NULL)
DIE(B_NO_MEMORY, "can't allocate repository name");
repositoryNames.AddItem(repoName);
}
}
status_t result;
for (int i = 0; i < repositoryNames.CountItems(); ++i) {
const BString& repoName = *(repositoryNames.ItemAt(i));
RepositoryConfig repoConfig;
result = roster.GetRepositoryConfig(repoName, &repoConfig);
if (result != B_OK) {
BPath path;
repoConfig.Entry().GetPath(&path);
WARN(result, "skipping repository-config '%s'", path.Path());
continue;
}
RefreshRepositoryRequest refreshRequest(context, repoConfig);
result = refreshRequest.CreateInitialJobs();
if (result != B_OK)
DIE(result, "unable to create necessary jobs");
while (Job* job = refreshRequest.PopRunnableJob()) {
result = job->Run();
delete job;
if (result != B_OK)
return 1;
}
}
return 0;
}

View File

@ -24,11 +24,14 @@ static const char* kUsage =
" add-repo <repo-base-url>\n"
" Adds the repository with the given <repo-base-URL>.\n"
"\n"
" drop-repo <repo-name>\n"
" Drops the repository with the given <repo-name>.\n"
"\n"
" list-repos\n"
" Lists all repositories.\n"
"\n"
" drop-repo <repo-name>\n"
" Drops the repository with the given <repo-name>.\n"
" refresh [<repo-name> ...]\n"
" Refreshes all or just the given repositories.\n"
"\n"
"Common Options:\n"
" -h, --help - Print this usage info.\n"
@ -50,15 +53,18 @@ main(int argc, const char* const* argv)
print_usage_and_exit(true);
const char* command = argv[1];
if (strcmp(command, "add-repo") == 0)
if (strcmp(command, "add-repo") == 0 || strcmp(command, "ar") == 0)
return command_add_repo(argc - 1, argv + 1);
// if (strcmp(command, "drop-repo") == 0)
// return command_drop_repo(argc - 1, argv + 1);
if (strcmp(command, "list-repos") == 0)
if (strcmp(command, "list-repos") == 0 || strcmp(command, "lr") == 0)
return command_list_repos(argc - 1, argv + 1);
if (strcmp(command, "refresh") == 0)
return command_refresh(argc - 1, argv + 1);
// if (strcmp(command, "search") == 0)
// return command_search(argc - 1, argv + 1);

View File

@ -38,6 +38,7 @@ void print_usage_and_exit(bool error);
int command_add_repo(int argc, const char* const* argv);
int command_drop_repo(int argc, const char* const* argv);
int command_list_repos(int argc, const char* const* argv);
int command_refresh(int argc, const char* const* argv);
#endif // PKGMAN_H

View File

@ -0,0 +1,59 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/ActivateRepositoryCacheJob.h>
#include <File.h>
#include <package/Context.h>
namespace Haiku {
namespace Package {
namespace Private {
ActivateRepositoryCacheJob::ActivateRepositoryCacheJob(const Context& context,
const BString& title, const BEntry& fetchedRepoCacheEntry,
const BString& repositoryName, const BDirectory& targetDirectory)
:
inherited(context, title),
fFetchedRepoCacheEntry(fetchedRepoCacheEntry),
fRepositoryName(repositoryName),
fTargetDirectory(targetDirectory)
{
}
ActivateRepositoryCacheJob::~ActivateRepositoryCacheJob()
{
}
status_t
ActivateRepositoryCacheJob::Execute()
{
status_t result = fFetchedRepoCacheEntry.MoveTo(&fTargetDirectory,
fRepositoryName.String(), true);
if (result != B_OK)
return result;
// TODO: propagate some repository attributes to file attributes
return B_OK;
}
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -9,8 +9,6 @@
#include <package/ActivateRepositoryConfigJob.h>
#include <stdlib.h>
#include <File.h>
#include <package/Context.h>
@ -21,13 +19,16 @@ namespace Haiku {
namespace Package {
namespace Private {
ActivateRepositoryConfigJob::ActivateRepositoryConfigJob(const Context& context,
const BString& title, const BEntry& archivedRepoConfigEntry,
const BDirectory& targetDirectory)
const BString& repositoryBaseURL, const BDirectory& targetDirectory)
:
inherited(context, title),
fArchivedRepoConfigEntry(archivedRepoConfigEntry),
fRepositoryBaseURL(repositoryBaseURL),
fTargetDirectory(targetDirectory)
{
}
@ -69,9 +70,14 @@ ActivateRepositoryConfigJob::Execute()
}
}
// inject the URL that was actually used and write the config file
repoConfig->SetURL(fRepositoryBaseURL);
if ((result = repoConfig->StoreAsConfigFile(fTargetEntry)) != B_OK)
return result;
// store name of activated repository as result
fRepositoryName = repoConfig->Name();
return B_OK;
}
@ -85,6 +91,15 @@ ActivateRepositoryConfigJob::Cleanup(status_t jobResult)
}
const BString&
ActivateRepositoryConfigJob::RepositoryName() const
{
return fRepositoryName;
}
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -23,12 +23,16 @@ namespace Haiku {
namespace Package {
using namespace Private;
AddRepositoryRequest::AddRepositoryRequest(const Context& context,
const BString& repositoryURL, bool asUserRepository)
const BString& repositoryBaseURL, bool asUserRepository)
:
inherited(context),
fRepositoryURL(repositoryURL),
fAsUserRepository(asUserRepository)
fRepositoryBaseURL(repositoryBaseURL),
fAsUserRepository(asUserRepository),
fActivateJob(NULL)
{
}
@ -39,16 +43,16 @@ AddRepositoryRequest::~AddRepositoryRequest()
status_t
AddRepositoryRequest::CreateJobsToRun(JobQueue& jobQueue)
AddRepositoryRequest::CreateInitialJobs()
{
BEntry tempEntry
= GetContext().GetTempEntryManager().Create("repoconfig-");
FetchFileJob* fetchJob = new (std::nothrow) FetchFileJob(GetContext(),
BString("Fetching repository-config from ") << fRepositoryURL,
fRepositoryURL, tempEntry);
BEntry tempEntry = fContext.GetTempfileManager().Create("repoheader-");
BString repoHeaderURL = BString(fRepositoryBaseURL) << "/" << "repo.header";
FetchFileJob* fetchJob = new (std::nothrow) FetchFileJob(fContext,
BString("Fetching repository header from ") << fRepositoryBaseURL,
repoHeaderURL, tempEntry);
if (fetchJob == NULL)
return B_NO_MEMORY;
status_t result = QueueJob(fetchJob, jobQueue);
status_t result = QueueJob(fetchJob);
if (result != B_OK) {
delete fetchJob;
return result;
@ -63,21 +67,37 @@ AddRepositoryRequest::CreateJobsToRun(JobQueue& jobQueue)
return result;
BDirectory targetDirectory(targetRepoConfigPath.Path());
ActivateRepositoryConfigJob* activateJob
= new (std::nothrow) ActivateRepositoryConfigJob(GetContext(),
BString("Activating repository-config from ") << fRepositoryURL,
tempEntry, targetDirectory);
= new (std::nothrow) ActivateRepositoryConfigJob(fContext,
BString("Activating repository config from ") << fRepositoryBaseURL,
tempEntry, fRepositoryBaseURL, targetDirectory);
if (activateJob == NULL)
return B_NO_MEMORY;
activateJob->AddDependency(fetchJob);
if ((result = QueueJob(activateJob, jobQueue)) != B_OK) {
if ((result = QueueJob(activateJob)) != B_OK) {
delete activateJob;
return result;
}
fActivateJob = activateJob;
return B_OK;
}
void
AddRepositoryRequest::JobSucceeded(Job* job)
{
if (job == fActivateJob)
fRepositoryName = fActivateJob->RepositoryName();
}
const BString&
AddRepositoryRequest::RepositoryName() const
{
return fRepositoryName;
}
} // namespace Package
} // namespace Haiku

View File

@ -0,0 +1,33 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/Attributes.h>
namespace Haiku {
namespace Package {
// attributes used in package and as file attribute, too
const char* kNameAttribute = "PKG:name";
const char* kPlatformAttribute = "PKG:platform";
const char* kVendorAttribute = "PKG:vendor";
const char* kVersionAttribute = "PKG:version";
// attributes kept local to packages
const char* kCopyrightAttribute = "PKG:copyright";
const char* kLicenseAttribute = "PKG:license";
const char* kProvidesAttribute = "PKG:provides";
const char* kRequiresAttribute = "PKG:requires";
} // namespace Package
} // namespace Haiku

View File

@ -0,0 +1,136 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <File.h>
#include <AutoDeleter.h>
#include <SHA256.h>
#include <package/ChecksumAccessors.h>
namespace Haiku {
namespace Package {
namespace Private {
#define NIBBLE_AS_HEX(nibble) \
(nibble >= 10 ? 'a' + nibble - 10 : '0' + nibble)
ChecksumAccessor::~ChecksumAccessor()
{
}
ChecksumFileChecksumAccessor::ChecksumFileChecksumAccessor(
const BEntry& checksumFileEntry)
:
fChecksumFileEntry(checksumFileEntry)
{
}
status_t
ChecksumFileChecksumAccessor::GetChecksum(BString& checksum) const
{
BFile checksumFile(&fChecksumFileEntry, B_READ_ONLY);
status_t result = checksumFile.InitCheck();
if (result != B_OK)
return result;
const int kSHA256ChecksumHexDumpSize = 64;
char* buffer = checksum.LockBuffer(kSHA256ChecksumHexDumpSize);
if (buffer == NULL)
return B_NO_MEMORY;
ssize_t bytesRead = checksumFile.Read(buffer, kSHA256ChecksumHexDumpSize);
buffer[kSHA256ChecksumHexDumpSize] = '\0';
checksum.UnlockBuffer(kSHA256ChecksumHexDumpSize);
if (bytesRead < 0)
return bytesRead;
if (bytesRead != kSHA256ChecksumHexDumpSize)
return B_IO_ERROR;
return B_OK;
}
GeneralFileChecksumAccessor::GeneralFileChecksumAccessor(
const BEntry& fileEntry, bool skipMissingFile)
:
fFileEntry(fileEntry),
fSkipMissingFile(skipMissingFile)
{
}
status_t
GeneralFileChecksumAccessor::GetChecksum(BString& checksum) const
{
SHA256 sha;
checksum.Truncate(0);
{
BFile file(&fFileEntry, B_READ_ONLY);
status_t result = file.InitCheck();
if (result != B_OK) {
if (result == B_ENTRY_NOT_FOUND && fSkipMissingFile)
return B_OK;
return result;
}
off_t fileSize;
if ((result = file.GetSize(&fileSize)) != B_OK)
return result;
const int kBlockSize = 64 * 1024;
void* buffer = malloc(kBlockSize);
if (buffer == NULL)
return B_NO_MEMORY;
MemoryDeleter memoryDeleter(buffer);
off_t handledSize = 0;
while (handledSize < fileSize) {
ssize_t bytesRead = file.Read(buffer, kBlockSize);
if (bytesRead < 0)
return bytesRead;
sha.Update(buffer, bytesRead);
handledSize += bytesRead;
}
}
const int kSHA256ChecksumSize = sha.DigestLength();
char* buffer = checksum.LockBuffer(2 * kSHA256ChecksumSize);
if (buffer == NULL)
return B_NO_MEMORY;
const uint8* digest = sha.Digest();
for (int i = 0; i < kSHA256ChecksumSize; ++i) {
uint8 highNibble = (digest[i] & 0xF0) >> 4;
buffer[i * 2] = NIBBLE_AS_HEX(highNibble);
uint8 lowNibble = digest[i] & 0x0F;
buffer[1 + i * 2] = NIBBLE_AS_HEX(lowNibble);
}
buffer[2 * kSHA256ChecksumSize] = '\0';
checksum.UnlockBuffer(2 * kSHA256ChecksumSize);
return B_OK;
}
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -38,7 +38,7 @@ Context::Context(DecisionProvider& decisionProvider)
BString contextName = BString("pkgkit-context-") << find_thread(NULL);
BDirectory baseDirectory;
tempDirectory.CreateDirectory(contextName.String(), &baseDirectory);
fTempEntryManager.SetBaseDirectory(baseDirectory);
fTempfileManager.SetBaseDirectory(baseDirectory);
}
@ -47,10 +47,10 @@ Context::~Context()
}
TempEntryManager&
Context::GetTempEntryManager() const
TempfileManager&
Context::GetTempfileManager() const
{
return fTempEntryManager;
return fTempfileManager;
}

View File

@ -19,6 +19,8 @@ namespace Haiku {
namespace Package {
namespace Private {
FetchFileJob::FetchFileJob(const Context& context, const BString& title,
const BString& fileURL, const BEntry& targetEntry)
@ -65,6 +67,8 @@ FetchFileJob::Cleanup(status_t jobResult)
}
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -1,19 +1,26 @@
SubDir HAIKU_TOP src kits package ;
UsePrivateHeaders package ;
UsePrivateHeaders package shared ;
SharedLibrary libpackage.so
:
ActivateRepositoryCacheJob.cpp
ActivateRepositoryConfigJob.cpp
AddRepositoryRequest.cpp
Attributes.cpp
ChecksumAccessors.cpp
Context.cpp
FetchFileJob.cpp
Job.cpp
JobQueue.cpp
RefreshRepositoryRequest.cpp
RepositoryCache.cpp
RepositoryConfig.cpp
# RepositoryHeader.cpp
Request.cpp
Roster.cpp
TempEntryManager.cpp
TempfileManager.cpp
ValidateChecksumJob.cpp
:
be $(TARGET_LIBSTDC++)
libshared.a be $(TARGET_LIBSTDC++)
;

View File

@ -94,6 +94,20 @@ Job::Result() const
}
const BString&
Job::ErrorString() const
{
return fErrorString;
}
void
Job::SetErrorString(const BString& error)
{
fErrorString = error;
}
status_t
Job::Run()
{

View File

@ -20,6 +20,8 @@ namespace Haiku {
namespace Package {
namespace Private {
struct JobQueue::JobPriorityLess {
bool operator()(const Job* left, const Job* right) const;
@ -150,6 +152,8 @@ JobQueue::_UpdateDependantJobsOf(Job* job)
}
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -0,0 +1,171 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/RefreshRepositoryRequest.h>
#include <Directory.h>
#include <Path.h>
#include <package/ActivateRepositoryCacheJob.h>
#include <package/ChecksumAccessors.h>
#include <package/ValidateChecksumJob.h>
#include <package/FetchFileJob.h>
#include <package/JobQueue.h>
#include <package/RepositoryCache.h>
#include <package/RepositoryConfig.h>
#include <package/Roster.h>
namespace Haiku {
namespace Package {
using namespace Private;
RefreshRepositoryRequest::RefreshRepositoryRequest(const Context& context,
const RepositoryConfig& repoConfig)
:
inherited(context),
fRepoConfig(repoConfig)
{
}
RefreshRepositoryRequest::~RefreshRepositoryRequest()
{
}
status_t
RefreshRepositoryRequest::CreateInitialJobs()
{
Roster roster;
status_t result = fRepoConfig.InitCheck();
if (result != B_OK)
return result;
// fetch the current checksum and compare with our cache's checksum,
// if they differ, fetch the updated cache
fFetchedChecksumFile
= fContext.GetTempfileManager().Create("repochecksum-");
BString repoChecksumURL
= BString(fRepoConfig.URL()) << "/" << "repo.sha256";
FetchFileJob* fetchChecksumJob = new (std::nothrow) FetchFileJob(
fContext,
BString("Fetching repository checksum from ") << fRepoConfig.URL(),
repoChecksumURL, fFetchedChecksumFile);
if (fetchChecksumJob == NULL)
return B_NO_MEMORY;
if ((result = QueueJob(fetchChecksumJob)) != B_OK) {
delete fetchChecksumJob;
return result;
}
RepositoryCache repoCache;
roster.GetRepositoryCache(fRepoConfig.Name(), &repoCache);
ValidateChecksumJob* validateChecksumJob
= new (std::nothrow) ValidateChecksumJob(fContext,
BString("Validating checksum for ") << fRepoConfig.Name(),
new (std::nothrow) ChecksumFileChecksumAccessor(
fFetchedChecksumFile),
new (std::nothrow) GeneralFileChecksumAccessor(repoCache.Entry(),
true),
false);
if (validateChecksumJob == NULL)
return B_NO_MEMORY;
validateChecksumJob->AddDependency(fetchChecksumJob);
if ((result = QueueJob(validateChecksumJob)) != B_OK) {
delete validateChecksumJob;
return result;
}
fValidateChecksumJob = validateChecksumJob;
return B_OK;
}
void
RefreshRepositoryRequest::JobSucceeded(Job* job)
{
if (job == fValidateChecksumJob
&& !fValidateChecksumJob->ChecksumsMatch()) {
// the remote repo cache has a different checksum, we fetch it
fValidateChecksumJob = NULL;
// don't re-trigger fetching if anything goes wrong, fail instead
_FetchRepositoryCache();
}
}
status_t
RefreshRepositoryRequest::_FetchRepositoryCache()
{
// download repository cache and put it in either the common/user cache
// path, depending on where the corresponding repo-config lives
// job fetching the cache
BEntry tempRepoCache = fContext.GetTempfileManager().Create("repocache-");
BString repoCacheURL = BString(fRepoConfig.URL()) << "/" << "repo";
FetchFileJob* fetchCacheJob = new (std::nothrow) FetchFileJob(fContext,
BString("Fetching repository-cache from ") << fRepoConfig.URL(),
repoCacheURL, tempRepoCache);
if (fetchCacheJob == NULL)
return B_NO_MEMORY;
status_t result = QueueJob(fetchCacheJob);
if (result != B_OK) {
delete fetchCacheJob;
return result;
}
// job validating the cache's checksum
ValidateChecksumJob* validateChecksumJob
= new (std::nothrow) ValidateChecksumJob(fContext,
BString("Validating checksum for ") << fRepoConfig.Name(),
new (std::nothrow) ChecksumFileChecksumAccessor(
fFetchedChecksumFile),
new (std::nothrow) GeneralFileChecksumAccessor(tempRepoCache));
if (validateChecksumJob == NULL)
return B_NO_MEMORY;
validateChecksumJob->AddDependency(fetchCacheJob);
if ((result = QueueJob(validateChecksumJob)) != B_OK) {
delete validateChecksumJob;
return result;
}
// job activating the cache
BPath targetRepoCachePath;
Roster roster;
result = fRepoConfig.IsUserSpecific()
? roster.GetUserRepositoryCachePath(&targetRepoCachePath, true)
: roster.GetCommonRepositoryCachePath(&targetRepoCachePath, true);
if (result != B_OK)
return result;
BDirectory targetDirectory(targetRepoCachePath.Path());
ActivateRepositoryCacheJob* activateJob
= new (std::nothrow) ActivateRepositoryCacheJob(fContext,
BString("Activating repository cache for ") << fRepoConfig.Name(),
tempRepoCache, fRepoConfig.Name(), targetDirectory);
if (activateJob == NULL)
return B_NO_MEMORY;
activateJob->AddDependency(validateChecksumJob);
if ((result = QueueJob(activateJob)) != B_OK) {
delete activateJob;
return result;
}
return B_OK;
}
} // namespace Package
} // namespace Haiku

View File

@ -0,0 +1,106 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/RepositoryCache.h>
#include <stdlib.h>
#include <new>
#include <Directory.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
namespace Haiku {
namespace Package {
RepositoryCache::RepositoryCache()
:
fInitStatus(B_NO_INIT),
fIsUserSpecific(false)
{
}
RepositoryCache::RepositoryCache(const BEntry& entry)
{
SetTo(entry);
}
RepositoryCache::~RepositoryCache()
{
}
status_t
RepositoryCache::InitCheck() const
{
return fInitStatus;
}
const BEntry&
RepositoryCache::Entry() const
{
return fEntry;
}
bool
RepositoryCache::IsUserSpecific() const
{
return fIsUserSpecific;
}
void
RepositoryCache::SetIsUserSpecific(bool isUserSpecific)
{
fIsUserSpecific = isUserSpecific;
}
status_t
RepositoryCache::SetTo(const BEntry& entry)
{
fEntry = entry;
fInitStatus = B_NO_INIT;
BFile file(&entry, B_READ_ONLY);
status_t result = file.InitCheck();
if (result != B_OK)
return result;
BMessage headerMsg;
if ((result = headerMsg.Unflatten(&file)) != B_OK)
return result;
// TODO: unarchive header and read packages
BPath userSettingsPath;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &userSettingsPath) == B_OK) {
BDirectory userSettingsDir(userSettingsPath.Path());
fIsUserSpecific = userSettingsDir.Contains(&entry);
} else
fIsUserSpecific = false;
fInitStatus = B_OK;
return B_OK;
}
} // namespace Package
} // namespace Haiku

View File

@ -15,7 +15,6 @@
#include <Directory.h>
#include <driver_settings.h>
#include <Entry.h>
#include <File.h>
#include <FindDirectory.h>
#include <Path.h>
@ -26,6 +25,7 @@ namespace Haiku {
namespace Package {
const uint8 RepositoryConfig::kDefaultPriority = 50;
const char* RepositoryConfig::kNameField = "name";
const char* RepositoryConfig::kURLField = "url";
const char* RepositoryConfig::kPriorityField = "priority";
@ -42,7 +42,7 @@ RepositoryConfig::RepositoryConfig()
RepositoryConfig::RepositoryConfig(const BEntry& entry)
{
fInitStatus = _InitFrom(entry);
SetTo(entry);
}
@ -50,7 +50,7 @@ RepositoryConfig::RepositoryConfig(BMessage* data)
:
inherited(data)
{
fInitStatus = _InitFrom(data);
SetTo(data);
}
@ -109,7 +109,6 @@ RepositoryConfig::StoreAsConfigFile(const BEntry& entry) const
BString configString;
configString
<< "name=" << fName << "\n"
<< "url=" << fURL << "\n"
<< "priority=" << fPriority << "\n";
@ -128,6 +127,91 @@ RepositoryConfig::InitCheck() const
}
status_t
RepositoryConfig::SetTo(const BEntry& entry)
{
fEntry = entry;
fInitStatus = B_NO_INIT;
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)
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* url = get_driver_parameter(settingsHandle, "url", NULL, NULL);
const char* priorityString
= get_driver_parameter(settingsHandle, "priority", NULL, NULL);
unload_driver_settings(settingsHandle);
if (url == NULL || *url == '\0')
return B_BAD_DATA;
char name[B_FILE_NAME_LENGTH];
if ((result = entry.GetName(name)) != B_OK)
return result;
fName = name;
fURL = url;
fPriority = priorityString == NULL
? kDefaultPriority : atoi(priorityString);
BPath userSettingsPath;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &userSettingsPath) == B_OK) {
BDirectory userSettingsDir(userSettingsPath.Path());
fIsUserSpecific = userSettingsDir.Contains(&entry);
} else
fIsUserSpecific = false;
fInitStatus = B_OK;
return B_OK;
}
status_t
RepositoryConfig::SetTo(const BMessage* data)
{
fInitStatus = B_NO_INIT;
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, &fURL)) != B_OK)
return result;
if ((result = data->FindUInt8(kPriorityField, &fPriority)) != B_OK)
return result;
fIsUserSpecific = false;
fInitStatus = B_OK;
return B_OK;
}
const BString&
RepositoryConfig::Name() const
{
@ -156,6 +240,13 @@ RepositoryConfig::IsUserSpecific() const
}
const BEntry&
RepositoryConfig::Entry() const
{
return fEntry;
}
void
RepositoryConfig::SetName(const BString& name)
{
@ -184,78 +275,6 @@ RepositoryConfig::SetIsUserSpecific(bool isUserSpecific)
}
status_t
RepositoryConfig::_InitFrom(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)
return (result >= 0) ? B_ERROR : result;
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* priorityString
= get_driver_parameter(settingsHandle, "priority", NULL, NULL);
unload_driver_settings(settingsHandle);
if (name == NULL || *name == '\0' || url == NULL || *url == '\0')
return B_BAD_DATA;
fName = name;
fURL = url;
fPriority = priorityString == NULL
? kDefaultPriority : atoi(priorityString);
BPath userSettingsPath;
if (find_directory(B_USER_SETTINGS_DIRECTORY, &userSettingsPath) == B_OK) {
BDirectory userSettingsDir(userSettingsPath.Path());
fIsUserSpecific = userSettingsDir.Contains(&entry);
} else
fIsUserSpecific = false;
return B_OK;
}
status_t
RepositoryConfig::_InitFrom(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, &fURL)) != B_OK)
return result;
if ((result = data->FindUInt8(kPriorityField, &fPriority)) != B_OK)
return result;
fIsUserSpecific = false;
return B_OK;
}
} // namespace Package
} // namespace Haiku

View File

@ -11,7 +11,6 @@
#include <package/Context.h>
#include <package/Job.h>
#include <package/JobQueue.h>
namespace Haiku {
@ -21,7 +20,8 @@ namespace Package {
Request::Request(const Context& context)
:
fContext(context)
fContext(context),
fJobQueue()
{
}
@ -31,21 +31,23 @@ Request::~Request()
}
const Context&
Request::GetContext() const
Job*
Request::PopRunnableJob()
{
return fContext;
return fJobQueue.Pop();
}
status_t
Request::QueueJob(Job* job, JobQueue& jobQueue) const
Request::QueueJob(Job* job)
{
job->AddStateListener(this);
JobStateListener* listener = fContext.GetJobStateListener();
if (listener != NULL)
job->AddStateListener(listener);
return jobQueue.AddJob(job);
return fJobQueue.AddJob(job);
}

View File

@ -14,8 +14,12 @@
#include <Directory.h>
#include <Entry.h>
#include <ObjectList.h>
#include <Path.h>
#include <FindDirectory.h>
#include <String.h>
#include <package/RepositoryCache.h>
#include <package/RepositoryConfig.h>
namespace Haiku {
@ -36,48 +40,28 @@ Roster::~Roster()
status_t
Roster::GetCommonRepositoryConfigPath(BPath* path, bool create) const
{
if (path == NULL)
return B_BAD_VALUE;
status_t result = find_directory(B_COMMON_SETTINGS_DIRECTORY, path);
if (result != B_OK)
return result;
if ((result = path->Append("package-repositories")) != B_OK)
return result;
if (create) {
BEntry entry(path->Path(), true);
if (!entry.Exists()) {
if (mkdir(path->Path(), 0755) != 0)
return errno;
}
}
return B_OK;
return _GetRepositoryPath(path, create, B_COMMON_SETTINGS_DIRECTORY);
}
status_t
Roster::GetUserRepositoryConfigPath(BPath* path, bool create) const
{
if (path == NULL)
return B_BAD_VALUE;
return _GetRepositoryPath(path, create, B_USER_SETTINGS_DIRECTORY);
}
status_t result = find_directory(B_USER_SETTINGS_DIRECTORY, path);
if (result != B_OK)
return result;
if ((result = path->Append("package-repositories")) != B_OK)
return result;
if (create) {
BEntry entry(path->Path(), true);
if (!entry.Exists()) {
if (mkdir(path->Path(), 0755) != 0)
return errno;
}
}
status_t
Roster::GetCommonRepositoryCachePath(BPath* path, bool create) const
{
return _GetRepositoryPath(path, create, B_COMMON_CACHE_DIRECTORY);
}
return B_OK;
status_t
Roster::GetUserRepositoryCachePath(BPath* path, bool create) const
{
return _GetRepositoryPath(path, create, B_USER_CACHE_DIRECTORY);
}
@ -87,10 +71,10 @@ Roster::VisitCommonRepositoryConfigs(RepositoryConfigVisitor& visitor)
BPath commonRepositoryConfigPath;
status_t result
= GetCommonRepositoryConfigPath(&commonRepositoryConfigPath);
if (result == B_OK)
result = _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor);
if (result != B_OK)
return result;
return result;
return _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor);
}
@ -99,10 +83,122 @@ Roster::VisitUserRepositoryConfigs(RepositoryConfigVisitor& visitor)
{
BPath userRepositoryConfigPath;
status_t result = GetUserRepositoryConfigPath(&userRepositoryConfigPath);
if (result == B_OK)
result = _VisitRepositoryConfigs(userRepositoryConfigPath, visitor);
if (result != B_OK)
return result;
return result;
return _VisitRepositoryConfigs(userRepositoryConfigPath, visitor);
}
status_t
Roster::GetRepositoryNames(BObjectList<BString>& names)
{
struct RepositoryNameCollector : public RepositoryConfigVisitor {
RepositoryNameCollector(BObjectList<BString>& _names)
: names(_names)
{
}
status_t operator()(const BEntry& entry)
{
char name[B_FILE_NAME_LENGTH];
status_t result = entry.GetName(name);
if (result != B_OK)
return result;
int32 count = names.CountItems();
for (int i = 0; i < count; ++i) {
if (names.ItemAt(i)->Compare(name) == 0)
return B_OK;
}
names.AddItem(new (std::nothrow) BString(name));
return B_OK;
}
BObjectList<BString>& names;
};
RepositoryNameCollector repositoryNameCollector(names);
status_t result = VisitUserRepositoryConfigs(repositoryNameCollector);
if (result != B_OK)
return result;
return VisitCommonRepositoryConfigs(repositoryNameCollector);
}
status_t
Roster::GetRepositoryCache(const BString& name,
RepositoryCache* repositoryCache)
{
if (repositoryCache == NULL)
return B_BAD_VALUE;
// user path has higher precedence than common path
BPath path;
status_t result = GetUserRepositoryCachePath(&path);
if (result != B_OK)
return result;
path.Append(name.String());
BEntry repoCacheEntry(path.Path());
if (repoCacheEntry.Exists())
return repositoryCache->SetTo(repoCacheEntry);
if ((result = GetCommonRepositoryCachePath(&path)) != B_OK)
return result;
path.Append(name.String());
repoCacheEntry.SetTo(path.Path());
return repositoryCache->SetTo(repoCacheEntry);
}
status_t
Roster::GetRepositoryConfig(const BString& name,
RepositoryConfig* repositoryConfig)
{
if (repositoryConfig == NULL)
return B_BAD_VALUE;
// user path has higher precedence than common path
BPath path;
status_t result = GetUserRepositoryConfigPath(&path);
if (result != B_OK)
return result;
path.Append(name.String());
BEntry repoConfigEntry(path.Path());
if (repoConfigEntry.Exists())
return repositoryConfig->SetTo(repoConfigEntry);
if ((result = GetCommonRepositoryConfigPath(&path)) != B_OK)
return result;
path.Append(name.String());
repoConfigEntry.SetTo(path.Path());
return repositoryConfig->SetTo(repoConfigEntry);
}
status_t
Roster::_GetRepositoryPath(BPath* path, bool create,
directory_which whichDir) const
{
if (path == NULL)
return B_BAD_VALUE;
status_t result = find_directory(whichDir, path);
if (result != B_OK)
return result;
if ((result = path->Append("package-repositories")) != B_OK)
return result;
if (create) {
BEntry entry(path->Path(), true);
if (!entry.Exists()) {
if (mkdir(path->Path(), 0755) != 0)
return errno;
}
}
return B_OK;
}
@ -112,6 +208,8 @@ Roster::_VisitRepositoryConfigs(const BPath& path,
{
BDirectory directory(path.Path());
status_t result = directory.InitCheck();
if (result == B_ENTRY_NOT_FOUND)
return B_OK;
if (result != B_OK)
return result;

View File

@ -7,25 +7,27 @@
*/
#include <package/TempEntryManager.h>
#include <package/TempfileManager.h>
namespace Haiku {
namespace Package {
const BString TempEntryManager::kDefaultName = "tmp-pkgkit-file-";
namespace Private {
TempEntryManager::TempEntryManager()
const BString TempfileManager::kDefaultName = "tmp-pkgkit-file-";
TempfileManager::TempfileManager()
:
fNextNumber(1)
{
}
TempEntryManager::~TempEntryManager()
TempfileManager::~TempfileManager()
{
if (fBaseDirectory.InitCheck() != B_OK)
return;
@ -41,14 +43,14 @@ TempEntryManager::~TempEntryManager()
void
TempEntryManager::SetBaseDirectory(const BDirectory& baseDirectory)
TempfileManager::SetBaseDirectory(const BDirectory& baseDirectory)
{
fBaseDirectory = baseDirectory;
}
BEntry
TempEntryManager::Create(const BString& baseName)
TempfileManager::Create(const BString& baseName)
{
BString name = BString(baseName) << atomic_add(&fNextNumber, 1);
@ -56,6 +58,8 @@ TempEntryManager::Create(const BString& baseName)
}
} // namespace Private
} // namespace Package
} // namespace Haiku

View File

@ -0,0 +1,86 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <zooey@hirschkaefer.de>
*/
#include <package/ValidateChecksumJob.h>
#include <File.h>
#include <package/Context.h>
namespace Haiku {
namespace Package {
namespace Private {
ValidateChecksumJob::ValidateChecksumJob(const Context& context,
const BString& title, ChecksumAccessor* expectedChecksumAccessor,
ChecksumAccessor* realChecksumAccessor, bool failIfChecksumsDontMatch)
:
inherited(context, title),
fExpectedChecksumAccessor(expectedChecksumAccessor),
fRealChecksumAccessor(realChecksumAccessor),
fFailIfChecksumsDontMatch(failIfChecksumsDontMatch),
fChecksumsMatch(false)
{
}
ValidateChecksumJob::~ValidateChecksumJob()
{
delete fRealChecksumAccessor;
delete fExpectedChecksumAccessor;
}
status_t
ValidateChecksumJob::Execute()
{
if (fExpectedChecksumAccessor == NULL || fRealChecksumAccessor == NULL)
return B_BAD_VALUE;
BString expectedChecksum;
BString realChecksum;
status_t result = fExpectedChecksumAccessor->GetChecksum(expectedChecksum);
if (result != B_OK)
return result;
result = fRealChecksumAccessor->GetChecksum(realChecksum);
if (result != B_OK)
return result;
fChecksumsMatch = expectedChecksum.ICompare(realChecksum) == 0;
if (fFailIfChecksumsDontMatch && !fChecksumsMatch) {
BString error = BString("Checksum error:\n")
<< "expected '" << expectedChecksum << "'\n"
<< "got '" << realChecksum << "'";
SetErrorString(error);
return B_BAD_DATA;
}
return B_OK;
}
bool
ValidateChecksumJob::ChecksumsMatch() const
{
return fChecksumsMatch;
}
} // namespace Private
} // namespace Package
} // namespace Haiku