* 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
+19 -3
View File
@@ -17,20 +17,36 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
class ActivateRepositoryConfigJob;
}
using Private::ActivateRepositoryConfigJob;
class AddRepositoryRequest : public Request { class AddRepositoryRequest : public Request {
typedef Request inherited; typedef Request inherited;
public: public:
AddRepositoryRequest(const Context& context, AddRepositoryRequest(const Context& context,
const BString& repositoryURL, const BString& repositoryBaseURL,
bool asUserRepository); bool asUserRepository);
virtual ~AddRepositoryRequest(); virtual ~AddRepositoryRequest();
virtual status_t CreateJobsToRun(JobQueue& jobQueue); virtual status_t CreateInitialJobs();
const BString& RepositoryName() const;
protected:
// JobStateListener
virtual void JobSucceeded(Job* job);
private: private:
BString fRepositoryURL; BString fRepositoryBaseURL;
bool fAsUserRepository; bool fAsUserRepository;
ActivateRepositoryConfigJob* fActivateJob;
BString fRepositoryName;
}; };
+31
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_
+4 -3
View File
@@ -6,7 +6,7 @@
#define _HAIKU__PACKAGE__CONTEXT_H_ #define _HAIKU__PACKAGE__CONTEXT_H_
#include <package/TempEntryManager.h> #include <package/TempfileManager.h>
namespace Haiku { namespace Haiku {
@@ -15,6 +15,7 @@ namespace Package {
class JobStateListener; class JobStateListener;
using Private::TempfileManager;
struct DecisionProvider { struct DecisionProvider {
@@ -37,7 +38,7 @@ public:
Context(DecisionProvider& decisionProvider); Context(DecisionProvider& decisionProvider);
~Context(); ~Context();
TempEntryManager& GetTempEntryManager() const; TempfileManager& GetTempfileManager() const;
JobStateListener* GetJobStateListener() const; JobStateListener* GetJobStateListener() const;
void SetJobStateListener(JobStateListener* listener); void SetJobStateListener(JobStateListener* listener);
@@ -45,7 +46,7 @@ public:
DecisionProvider& GetDecisionProvider() const; DecisionProvider& GetDecisionProvider() const;
private: private:
mutable TempEntryManager fTempEntryManager; mutable TempfileManager fTempfileManager;
DecisionProvider& fDecisionProvider; DecisionProvider& fDecisionProvider;
JobStateListener* fJobStateListener; JobStateListener* fJobStateListener;
}; };
+5
View File
@@ -18,6 +18,7 @@ namespace Package {
class Context; class Context;
class Job; class Job;
struct JobStateListener { struct JobStateListener {
virtual ~JobStateListener(); virtual ~JobStateListener();
@@ -51,6 +52,7 @@ public:
const BString& Title() const; const BString& Title() const;
JobState State() const; JobState State() const;
status_t Result() const; status_t Result() const;
const BString& ErrorString() const;
status_t AddStateListener(JobStateListener* listener); status_t AddStateListener(JobStateListener* listener);
status_t RemoveStateListener( status_t RemoveStateListener(
@@ -65,6 +67,8 @@ protected:
virtual status_t Execute() = 0; virtual status_t Execute() = 0;
virtual void Cleanup(status_t jobResult); virtual void Cleanup(status_t jobResult);
void SetErrorString(const BString&);
void NotifyStateListeners(); void NotifyStateListeners();
const Context& fContext; const Context& fContext;
@@ -74,6 +78,7 @@ private:
JobState fState; JobState fState;
status_t fResult; status_t fResult;
BString fErrorString;
typedef BObjectList<Job> JobList; typedef BObjectList<Job> JobList;
JobList fDependencies; JobList fDependencies;
@@ -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_
+38 -9
View File
@@ -2,23 +2,52 @@
* Copyright 2011, Haiku, Inc. * Copyright 2011, Haiku, Inc.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _REPOSITORY_H_ #ifndef _HAIKU__PACKAGE__REPOSITORY_CACHE_H_
#define _REPOSITORY_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: public:
BRepository(const char* url); RepositoryCache();
RepositoryCache(const BEntry& entry);
virtual ~RepositoryCache();
public: status_t SetTo(const BEntry& entry);
static BArchivable* Instantiate(BMessage* archive); 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_
+8 -4
View File
@@ -7,6 +7,7 @@
#include <Archivable.h> #include <Archivable.h>
#include <Entry.h>
#include <String.h> #include <String.h>
@@ -34,6 +35,8 @@ public:
status_t StoreAsConfigFile(const BEntry& entry) const; status_t StoreAsConfigFile(const BEntry& entry) const;
status_t SetTo(const BEntry& entry);
status_t SetTo(const BMessage* data);
status_t InitCheck() const; status_t InitCheck() const;
const BString& Name() const; const BString& Name() const;
@@ -41,6 +44,8 @@ public:
uint8 Priority() const; uint8 Priority() const;
bool IsUserSpecific() const; bool IsUserSpecific() const;
const BEntry& Entry() const;
void SetName(const BString& name); void SetName(const BString& name);
void SetURL(const BString& url); void SetURL(const BString& url);
void SetPriority(uint8 priority); void SetPriority(uint8 priority);
@@ -49,21 +54,20 @@ public:
public: public:
static RepositoryConfig* Instantiate(BMessage* data); static RepositoryConfig* Instantiate(BMessage* data);
static const uint8 kDefaultPriority = 50; static const uint8 kDefaultPriority;
static const char* kNameField; static const char* kNameField;
static const char* kURLField; static const char* kURLField;
static const char* kPriorityField; static const char* kPriorityField;
private: private:
status_t _InitFrom(const BEntry& entry);
status_t _InitFrom(const BMessage* data);
status_t fInitStatus; status_t fInitStatus;
BString fName; BString fName;
BString fURL; BString fURL;
uint8 fPriority; uint8 fPriority;
bool fIsUserSpecific; bool fIsUserSpecific;
BEntry fEntry;
}; };
+11 -7
View File
@@ -8,6 +8,8 @@
#include <SupportDefs.h> #include <SupportDefs.h>
#include <package/JobQueue.h>
namespace Haiku { namespace Haiku {
@@ -15,23 +17,25 @@ namespace Package {
class Context; class Context;
class Job; using Private::JobQueue;
class JobQueue;
class Request { class Request : protected JobStateListener {
public: public:
Request(const Context& context); Request(const Context& context);
virtual ~Request(); virtual ~Request();
virtual status_t CreateJobsToRun(JobQueue& jobQueue) = 0; virtual status_t CreateInitialJobs() = 0;
const Context& GetContext() const; Job* PopRunnableJob();
protected: protected:
status_t QueueJob(Job* job, JobQueue& jobQueue) const; status_t QueueJob(Job* job);
private:
const Context& fContext; const Context& fContext;
private:
JobQueue fJobQueue;
}; };
+21
View File
@@ -7,10 +7,14 @@
#include <Entry.h> #include <Entry.h>
#include <FindDirectory.h>
#include <Path.h> #include <Path.h>
#include <SupportDefs.h> #include <SupportDefs.h>
template <class T> class BObjectList;
namespace Haiku { namespace Haiku {
namespace Package { namespace Package {
@@ -25,22 +29,39 @@ struct RepositoryConfigVisitor {
}; };
class RepositoryCache;
class RepositoryConfig;
class Roster { class Roster {
public: public:
Roster(); Roster();
~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, status_t GetCommonRepositoryConfigPath(BPath* path,
bool create = false) const; bool create = false) const;
status_t GetUserRepositoryConfigPath(BPath* path, status_t GetUserRepositoryConfigPath(BPath* path,
bool create = false) const; bool create = false) const;
status_t GetRepositoryNames(BObjectList<BString>& names);
status_t VisitCommonRepositoryConfigs( status_t VisitCommonRepositoryConfigs(
RepositoryConfigVisitor& visitor); RepositoryConfigVisitor& visitor);
status_t VisitUserRepositoryConfigs( status_t VisitUserRepositoryConfigs(
RepositoryConfigVisitor& visitor); RepositoryConfigVisitor& visitor);
status_t GetRepositoryCache(const BString& name,
RepositoryCache* repositoryCache);
status_t GetRepositoryConfig(const BString& name,
RepositoryConfig* repositoryConfig);
private: private:
status_t _GetRepositoryPath(BPath* path, bool create,
directory_which whichDir) const;
status_t _VisitRepositoryConfigs(const BPath& path, status_t _VisitRepositoryConfigs(const BPath& path,
RepositoryConfigVisitor& visitor); RepositoryConfigVisitor& visitor);
@@ -0,0 +1,52 @@
/*
* Copyright 2011, Oliver Tappe <[email protected]>
* 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_
@@ -1,9 +1,9 @@
/* /*
* Copyright 2011, Haiku, Inc. * Copyright 2011, Oliver Tappe <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _HAIKU__PACKAGE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_ #ifndef _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#define _HAIKU__PACKAGE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_ #define _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
#include <Directory.h> #include <Directory.h>
@@ -17,6 +17,8 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
class ActivateRepositoryConfigJob : public Job { class ActivateRepositoryConfigJob : public Job {
typedef Job inherited; typedef Job inherited;
@@ -26,23 +28,31 @@ public:
const Context& context, const Context& context,
const BString& title, const BString& title,
const BEntry& archivedRepoConfigEntry, const BEntry& archivedRepoConfigEntry,
const BString& repositoryBaseURL,
const BDirectory& targetDirectory); const BDirectory& targetDirectory);
virtual ~ActivateRepositoryConfigJob(); virtual ~ActivateRepositoryConfigJob();
const BString& RepositoryName() const;
protected: protected:
virtual status_t Execute(); virtual status_t Execute();
virtual void Cleanup(status_t jobResult); virtual void Cleanup(status_t jobResult);
private: private:
BEntry fArchivedRepoConfigEntry; BEntry fArchivedRepoConfigEntry;
BString fRepositoryBaseURL;
BDirectory fTargetDirectory; BDirectory fTargetDirectory;
BEntry fTargetEntry; BEntry fTargetEntry;
BString fRepositoryName;
}; };
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
#endif // _HAIKU__PACKAGE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_ #endif // _HAIKU__PACKAGE__PRIVATE__ACTIVATE_REPOSITORY_CONFIG_JOB_H_
@@ -0,0 +1,61 @@
/*
* Copyright 2011, Oliver Tappe <[email protected]>
* 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_
+8 -4
View File
@@ -1,9 +1,9 @@
/* /*
* Copyright 2011, Haiku, Inc. * Copyright 2011, Oliver Tappe <[email protected]>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _HAIKU__PACKAGE__FETCH_FILE_JOB_H_ #ifndef _HAIKU__PACKAGE__PRIVATE__FETCH_FILE_JOB_H_
#define _HAIKU__PACKAGE__FETCH_FILE_JOB_H_ #define _HAIKU__PACKAGE__PRIVATE__FETCH_FILE_JOB_H_
#include <Entry.h> #include <Entry.h>
@@ -16,6 +16,8 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
class FetchFileJob : public Job { class FetchFileJob : public Job {
typedef Job inherited; typedef Job inherited;
@@ -37,9 +39,11 @@ private:
}; };
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
#endif // _HAIKU__PACKAGE__FETCH_FILE_JOB_H_ #endif // _HAIKU__PACKAGE__PRIVATE__FETCH_FILE_JOB_H_
@@ -16,6 +16,8 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
class JobQueue : public JobStateListener { class JobQueue : public JobStateListener {
public: public:
@@ -43,6 +45,8 @@ private:
}; };
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
@@ -1,9 +1,9 @@
/* /*
* Copyright 2011, Haiku, Inc. * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _HAIKU__PACKAGE__TEMP_ENTRY_MANAGER_H_ #ifndef _HAIKU__PACKAGE__PRIVATE__TEMPFILE_MANAGER_H_
#define _HAIKU__PACKAGE__TEMP_ENTRY_MANAGER_H_ #define _HAIKU__PACKAGE__PRIVATE__TEMPFILE_MANAGER_H_
#include <Directory.h> #include <Directory.h>
@@ -16,11 +16,13 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
class TempEntryManager {
class TempfileManager {
public: public:
TempEntryManager(); TempfileManager();
~TempEntryManager(); ~TempfileManager();
void SetBaseDirectory(const BDirectory& baseDir); void SetBaseDirectory(const BDirectory& baseDir);
@@ -35,9 +37,11 @@ private:
}; };
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
#endif // _HAIKU__PACKAGE__TEMP_ENTRY_MANAGER_H_ #endif // _HAIKU__PACKAGE__PRIVATE__TEMPFILE_MANAGER_H_
@@ -0,0 +1,57 @@
/*
* Copyright 2011, Oliver Tappe <[email protected]>
* 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_
+2 -1
View File
@@ -1,10 +1,11 @@
SubDir HAIKU_TOP src bin pkgman ; SubDir HAIKU_TOP src bin pkgman ;
UsePrivateHeaders shared support ; UsePrivateHeaders support ;
BinCommand pkgman : BinCommand pkgman :
command_add_repo.cpp command_add_repo.cpp
command_list_repos.cpp command_list_repos.cpp
command_refresh.cpp
MyDecisionProvider.cpp MyDecisionProvider.cpp
MyJobStateListener.cpp MyJobStateListener.cpp
pkgman.cpp pkgman.cpp
+5
View File
@@ -29,6 +29,11 @@ MyJobStateListener::JobSucceeded(Job* job)
void void
MyJobStateListener::JobFailed(Job* job) 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!"); DIE(job->Result(), "failed!");
} }
+22 -6
View File
@@ -13,7 +13,8 @@
#include <package/AddRepositoryRequest.h> #include <package/AddRepositoryRequest.h>
#include <package/Context.h> #include <package/Context.h>
#include <package/JobQueue.h> #include <package/RefreshRepositoryRequest.h>
#include <package/Roster.h>
#include "MyDecisionProvider.h" #include "MyDecisionProvider.h"
#include "MyJobStateListener.h" #include "MyJobStateListener.h"
@@ -87,17 +88,32 @@ command_add_repo(int argc, const char* const* argv)
status_t result; status_t result;
for (int i = 0; i < urlCount; ++i) { for (int i = 0; i < urlCount; ++i) {
AddRepositoryRequest request(context, repoURLs[i], asUserRepository); AddRepositoryRequest addRequest(context, repoURLs[i], asUserRepository);
JobQueue jobQueue; result = addRequest.CreateInitialJobs();
result = request.CreateJobsToRun(jobQueue);
if (result != B_OK) if (result != B_OK)
DIE(result, "unable to create necessary jobs"); DIE(result, "unable to create necessary jobs");
while (Job* job = jobQueue.Pop()) { while (Job* job = addRequest.PopRunnableJob()) {
result = job->Run(); result = job->Run();
delete job; delete job;
if (result == B_CANCELED) 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;
} }
} }
+16 -57
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 int
command_list_repos(int argc, const char* const* argv) 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) if (argc != optind)
print_command_usage_and_exit(true); print_command_usage_and_exit(true);
BObjectList<BString> repositoryNames(20, true);
Roster roster; Roster roster;
RepositoryConfigList repositoryConfigs; status_t result = roster.GetRepositoryNames(repositoryNames);
RepositoryConfigCollector repositoryConfigCollector(repositoryConfigs); if (result != B_OK)
status_t result DIE(result, "can't collect repository names");
= roster.VisitCommonRepositoryConfigs(repositoryConfigCollector);
if (result != B_OK && result != B_ENTRY_NOT_FOUND)
DIE(result, "can't collect common repository configs");
result = roster.VisitUserRepositoryConfigs(repositoryConfigCollector); for (int i = 0; i < repositoryNames.CountItems(); ++i) {
if (result != B_OK && result != B_ENTRY_NOT_FOUND) const BString& repoName = *(repositoryNames.ItemAt(i));
DIE(result, "can't collect user's repository configs"); RepositoryConfig repoConfig;
result = roster.GetRepositoryConfig(repoName, &repoConfig);
int32 count = repositoryConfigs.CountItems(); if (result != B_OK) {
for (int32 i = 0; i < count; ++i) { BPath path;
RepositoryConfig* repoConfig = repositoryConfigs.ItemAt(i); repoConfig.Entry().GetPath(&path);
WARN(result, "skipping repository-config '%s'", path.Path());
continue;
}
printf(" %s %s\n", printf(" %s %s\n",
repoConfig->IsUserSpecific() ? "[User]" : " ", repoConfig.IsUserSpecific() ? "[User]" : " ",
repoConfig->Name().String()); repoConfig.Name().String());
} }
return 0; return 0;
+119
View File
@@ -0,0 +1,119 @@
/*
* Copyright 2011, Oliver Tappe <[email protected]>
* 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;
}
+10 -4
View File
@@ -24,11 +24,14 @@ static const char* kUsage =
" add-repo <repo-base-url>\n" " add-repo <repo-base-url>\n"
" Adds the repository with the given <repo-base-URL>.\n" " Adds the repository with the given <repo-base-URL>.\n"
"\n" "\n"
" drop-repo <repo-name>\n"
" Drops the repository with the given <repo-name>.\n"
"\n"
" list-repos\n" " list-repos\n"
" Lists all repositories.\n" " Lists all repositories.\n"
"\n" "\n"
" drop-repo <repo-name>\n" " refresh [<repo-name> ...]\n"
" Drops the repository with the given <repo-name>.\n" " Refreshes all or just the given repositories.\n"
"\n" "\n"
"Common Options:\n" "Common Options:\n"
" -h, --help - Print this usage info.\n" " -h, --help - Print this usage info.\n"
@@ -50,15 +53,18 @@ main(int argc, const char* const* argv)
print_usage_and_exit(true); print_usage_and_exit(true);
const char* command = argv[1]; 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); return command_add_repo(argc - 1, argv + 1);
// if (strcmp(command, "drop-repo") == 0) // if (strcmp(command, "drop-repo") == 0)
// return command_drop_repo(argc - 1, argv + 1); // 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); 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) // if (strcmp(command, "search") == 0)
// return command_search(argc - 1, argv + 1); // return command_search(argc - 1, argv + 1);
+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_add_repo(int argc, const char* const* argv);
int command_drop_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_list_repos(int argc, const char* const* argv);
int command_refresh(int argc, const char* const* argv);
#endif // PKGMAN_H #endif // PKGMAN_H
@@ -0,0 +1,59 @@
/*
* Copyright 2011, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Oliver Tappe <[email protected]>
*/
#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
@@ -9,8 +9,6 @@
#include <package/ActivateRepositoryConfigJob.h> #include <package/ActivateRepositoryConfigJob.h>
#include <stdlib.h>
#include <File.h> #include <File.h>
#include <package/Context.h> #include <package/Context.h>
@@ -21,13 +19,16 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
ActivateRepositoryConfigJob::ActivateRepositoryConfigJob(const Context& context, ActivateRepositoryConfigJob::ActivateRepositoryConfigJob(const Context& context,
const BString& title, const BEntry& archivedRepoConfigEntry, const BString& title, const BEntry& archivedRepoConfigEntry,
const BDirectory& targetDirectory) const BString& repositoryBaseURL, const BDirectory& targetDirectory)
: :
inherited(context, title), inherited(context, title),
fArchivedRepoConfigEntry(archivedRepoConfigEntry), fArchivedRepoConfigEntry(archivedRepoConfigEntry),
fRepositoryBaseURL(repositoryBaseURL),
fTargetDirectory(targetDirectory) 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) if ((result = repoConfig->StoreAsConfigFile(fTargetEntry)) != B_OK)
return result; return result;
// store name of activated repository as result
fRepositoryName = repoConfig->Name();
return B_OK; return B_OK;
} }
@@ -85,6 +91,15 @@ ActivateRepositoryConfigJob::Cleanup(status_t jobResult)
} }
const BString&
ActivateRepositoryConfigJob::RepositoryName() const
{
return fRepositoryName;
}
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
+34 -14
View File
@@ -23,12 +23,16 @@ namespace Haiku {
namespace Package { namespace Package {
using namespace Private;
AddRepositoryRequest::AddRepositoryRequest(const Context& context, AddRepositoryRequest::AddRepositoryRequest(const Context& context,
const BString& repositoryURL, bool asUserRepository) const BString& repositoryBaseURL, bool asUserRepository)
: :
inherited(context), inherited(context),
fRepositoryURL(repositoryURL), fRepositoryBaseURL(repositoryBaseURL),
fAsUserRepository(asUserRepository) fAsUserRepository(asUserRepository),
fActivateJob(NULL)
{ {
} }
@@ -39,16 +43,16 @@ AddRepositoryRequest::~AddRepositoryRequest()
status_t status_t
AddRepositoryRequest::CreateJobsToRun(JobQueue& jobQueue) AddRepositoryRequest::CreateInitialJobs()
{ {
BEntry tempEntry BEntry tempEntry = fContext.GetTempfileManager().Create("repoheader-");
= GetContext().GetTempEntryManager().Create("repoconfig-"); BString repoHeaderURL = BString(fRepositoryBaseURL) << "/" << "repo.header";
FetchFileJob* fetchJob = new (std::nothrow) FetchFileJob(GetContext(), FetchFileJob* fetchJob = new (std::nothrow) FetchFileJob(fContext,
BString("Fetching repository-config from ") << fRepositoryURL, BString("Fetching repository header from ") << fRepositoryBaseURL,
fRepositoryURL, tempEntry); repoHeaderURL, tempEntry);
if (fetchJob == NULL) if (fetchJob == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
status_t result = QueueJob(fetchJob, jobQueue); status_t result = QueueJob(fetchJob);
if (result != B_OK) { if (result != B_OK) {
delete fetchJob; delete fetchJob;
return result; return result;
@@ -63,21 +67,37 @@ AddRepositoryRequest::CreateJobsToRun(JobQueue& jobQueue)
return result; return result;
BDirectory targetDirectory(targetRepoConfigPath.Path()); BDirectory targetDirectory(targetRepoConfigPath.Path());
ActivateRepositoryConfigJob* activateJob ActivateRepositoryConfigJob* activateJob
= new (std::nothrow) ActivateRepositoryConfigJob(GetContext(), = new (std::nothrow) ActivateRepositoryConfigJob(fContext,
BString("Activating repository-config from ") << fRepositoryURL, BString("Activating repository config from ") << fRepositoryBaseURL,
tempEntry, targetDirectory); tempEntry, fRepositoryBaseURL, targetDirectory);
if (activateJob == NULL) if (activateJob == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
activateJob->AddDependency(fetchJob); activateJob->AddDependency(fetchJob);
if ((result = QueueJob(activateJob, jobQueue)) != B_OK) { if ((result = QueueJob(activateJob)) != B_OK) {
delete activateJob; delete activateJob;
return result; return result;
} }
fActivateJob = activateJob;
return B_OK; return B_OK;
} }
void
AddRepositoryRequest::JobSucceeded(Job* job)
{
if (job == fActivateJob)
fRepositoryName = fActivateJob->RepositoryName();
}
const BString&
AddRepositoryRequest::RepositoryName() const
{
return fRepositoryName;
}
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
+33
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
+136
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
+4 -4
View File
@@ -38,7 +38,7 @@ Context::Context(DecisionProvider& decisionProvider)
BString contextName = BString("pkgkit-context-") << find_thread(NULL); BString contextName = BString("pkgkit-context-") << find_thread(NULL);
BDirectory baseDirectory; BDirectory baseDirectory;
tempDirectory.CreateDirectory(contextName.String(), &baseDirectory); tempDirectory.CreateDirectory(contextName.String(), &baseDirectory);
fTempEntryManager.SetBaseDirectory(baseDirectory); fTempfileManager.SetBaseDirectory(baseDirectory);
} }
@@ -47,10 +47,10 @@ Context::~Context()
} }
TempEntryManager& TempfileManager&
Context::GetTempEntryManager() const Context::GetTempfileManager() const
{ {
return fTempEntryManager; return fTempfileManager;
} }
+4
View File
@@ -19,6 +19,8 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
FetchFileJob::FetchFileJob(const Context& context, const BString& title, FetchFileJob::FetchFileJob(const Context& context, const BString& title,
const BString& fileURL, const BEntry& targetEntry) const BString& fileURL, const BEntry& targetEntry)
@@ -65,6 +67,8 @@ FetchFileJob::Cleanup(status_t jobResult)
} }
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
+10 -3
View File
@@ -1,19 +1,26 @@
SubDir HAIKU_TOP src kits package ; SubDir HAIKU_TOP src kits package ;
UsePrivateHeaders package ; UsePrivateHeaders package shared ;
SharedLibrary libpackage.so SharedLibrary libpackage.so
: :
ActivateRepositoryCacheJob.cpp
ActivateRepositoryConfigJob.cpp ActivateRepositoryConfigJob.cpp
AddRepositoryRequest.cpp AddRepositoryRequest.cpp
Attributes.cpp
ChecksumAccessors.cpp
Context.cpp Context.cpp
FetchFileJob.cpp FetchFileJob.cpp
Job.cpp Job.cpp
JobQueue.cpp JobQueue.cpp
RefreshRepositoryRequest.cpp
RepositoryCache.cpp
RepositoryConfig.cpp RepositoryConfig.cpp
# RepositoryHeader.cpp
Request.cpp Request.cpp
Roster.cpp Roster.cpp
TempEntryManager.cpp TempfileManager.cpp
ValidateChecksumJob.cpp
: :
be $(TARGET_LIBSTDC++) libshared.a be $(TARGET_LIBSTDC++)
; ;
+14
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 status_t
Job::Run() Job::Run()
{ {
+4
View File
@@ -20,6 +20,8 @@ namespace Haiku {
namespace Package { namespace Package {
namespace Private {
struct JobQueue::JobPriorityLess { struct JobQueue::JobPriorityLess {
bool operator()(const Job* left, const Job* right) const; bool operator()(const Job* left, const Job* right) const;
@@ -150,6 +152,8 @@ JobQueue::_UpdateDependantJobsOf(Job* job)
} }
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
@@ -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
+106
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
+95 -76
View File
@@ -15,7 +15,6 @@
#include <Directory.h> #include <Directory.h>
#include <driver_settings.h> #include <driver_settings.h>
#include <Entry.h>
#include <File.h> #include <File.h>
#include <FindDirectory.h> #include <FindDirectory.h>
#include <Path.h> #include <Path.h>
@@ -26,6 +25,7 @@ namespace Haiku {
namespace Package { namespace Package {
const uint8 RepositoryConfig::kDefaultPriority = 50;
const char* RepositoryConfig::kNameField = "name"; const char* RepositoryConfig::kNameField = "name";
const char* RepositoryConfig::kURLField = "url"; const char* RepositoryConfig::kURLField = "url";
const char* RepositoryConfig::kPriorityField = "priority"; const char* RepositoryConfig::kPriorityField = "priority";
@@ -42,7 +42,7 @@ RepositoryConfig::RepositoryConfig()
RepositoryConfig::RepositoryConfig(const BEntry& entry) RepositoryConfig::RepositoryConfig(const BEntry& entry)
{ {
fInitStatus = _InitFrom(entry); SetTo(entry);
} }
@@ -50,7 +50,7 @@ RepositoryConfig::RepositoryConfig(BMessage* data)
: :
inherited(data) inherited(data)
{ {
fInitStatus = _InitFrom(data); SetTo(data);
} }
@@ -109,7 +109,6 @@ RepositoryConfig::StoreAsConfigFile(const BEntry& entry) const
BString configString; BString configString;
configString configString
<< "name=" << fName << "\n"
<< "url=" << fURL << "\n" << "url=" << fURL << "\n"
<< "priority=" << fPriority << "\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& const BString&
RepositoryConfig::Name() const RepositoryConfig::Name() const
{ {
@@ -156,6 +240,13 @@ RepositoryConfig::IsUserSpecific() const
} }
const BEntry&
RepositoryConfig::Entry() const
{
return fEntry;
}
void void
RepositoryConfig::SetName(const BString& name) 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 Package
} // namespace Haiku } // namespace Haiku
+9 -7
View File
@@ -11,7 +11,6 @@
#include <package/Context.h> #include <package/Context.h>
#include <package/Job.h> #include <package/Job.h>
#include <package/JobQueue.h>
namespace Haiku { namespace Haiku {
@@ -21,7 +20,8 @@ namespace Package {
Request::Request(const Context& context) Request::Request(const Context& context)
: :
fContext(context) fContext(context),
fJobQueue()
{ {
} }
@@ -31,21 +31,23 @@ Request::~Request()
} }
const Context& Job*
Request::GetContext() const Request::PopRunnableJob()
{ {
return fContext; return fJobQueue.Pop();
} }
status_t status_t
Request::QueueJob(Job* job, JobQueue& jobQueue) const Request::QueueJob(Job* job)
{ {
job->AddStateListener(this);
JobStateListener* listener = fContext.GetJobStateListener(); JobStateListener* listener = fContext.GetJobStateListener();
if (listener != NULL) if (listener != NULL)
job->AddStateListener(listener); job->AddStateListener(listener);
return jobQueue.AddJob(job); return fJobQueue.AddJob(job);
} }
+138 -40
View File
@@ -14,8 +14,12 @@
#include <Directory.h> #include <Directory.h>
#include <Entry.h> #include <Entry.h>
#include <ObjectList.h>
#include <Path.h> #include <Path.h>
#include <FindDirectory.h> #include <String.h>
#include <package/RepositoryCache.h>
#include <package/RepositoryConfig.h>
namespace Haiku { namespace Haiku {
@@ -36,48 +40,28 @@ Roster::~Roster()
status_t status_t
Roster::GetCommonRepositoryConfigPath(BPath* path, bool create) const Roster::GetCommonRepositoryConfigPath(BPath* path, bool create) const
{ {
if (path == NULL) return _GetRepositoryPath(path, create, B_COMMON_SETTINGS_DIRECTORY);
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;
} }
status_t status_t
Roster::GetUserRepositoryConfigPath(BPath* path, bool create) const Roster::GetUserRepositoryConfigPath(BPath* path, bool create) const
{ {
if (path == NULL) return _GetRepositoryPath(path, create, B_USER_SETTINGS_DIRECTORY);
return B_BAD_VALUE; }
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) { status_t
BEntry entry(path->Path(), true); Roster::GetCommonRepositoryCachePath(BPath* path, bool create) const
if (!entry.Exists()) { {
if (mkdir(path->Path(), 0755) != 0) return _GetRepositoryPath(path, create, B_COMMON_CACHE_DIRECTORY);
return errno; }
}
}
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; BPath commonRepositoryConfigPath;
status_t result status_t result
= GetCommonRepositoryConfigPath(&commonRepositoryConfigPath); = GetCommonRepositoryConfigPath(&commonRepositoryConfigPath);
if (result == B_OK) if (result != B_OK)
result = _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor); return result;
return result; return _VisitRepositoryConfigs(commonRepositoryConfigPath, visitor);
} }
@@ -99,10 +83,122 @@ Roster::VisitUserRepositoryConfigs(RepositoryConfigVisitor& visitor)
{ {
BPath userRepositoryConfigPath; BPath userRepositoryConfigPath;
status_t result = GetUserRepositoryConfigPath(&userRepositoryConfigPath); status_t result = GetUserRepositoryConfigPath(&userRepositoryConfigPath);
if (result == B_OK) if (result != B_OK)
result = _VisitRepositoryConfigs(userRepositoryConfigPath, visitor); 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()); BDirectory directory(path.Path());
status_t result = directory.InitCheck(); status_t result = directory.InitCheck();
if (result == B_ENTRY_NOT_FOUND)
return B_OK;
if (result != B_OK) if (result != B_OK)
return result; return result;
@@ -7,25 +7,27 @@
*/ */
#include <package/TempEntryManager.h> #include <package/TempfileManager.h>
namespace Haiku { namespace Haiku {
namespace Package { namespace Package {
namespace Private {
const BString TempEntryManager::kDefaultName = "tmp-pkgkit-file-";
TempEntryManager::TempEntryManager() const BString TempfileManager::kDefaultName = "tmp-pkgkit-file-";
TempfileManager::TempfileManager()
: :
fNextNumber(1) fNextNumber(1)
{ {
} }
TempEntryManager::~TempEntryManager() TempfileManager::~TempfileManager()
{ {
if (fBaseDirectory.InitCheck() != B_OK) if (fBaseDirectory.InitCheck() != B_OK)
return; return;
@@ -41,14 +43,14 @@ TempEntryManager::~TempEntryManager()
void void
TempEntryManager::SetBaseDirectory(const BDirectory& baseDirectory) TempfileManager::SetBaseDirectory(const BDirectory& baseDirectory)
{ {
fBaseDirectory = baseDirectory; fBaseDirectory = baseDirectory;
} }
BEntry BEntry
TempEntryManager::Create(const BString& baseName) TempfileManager::Create(const BString& baseName)
{ {
BString name = BString(baseName) << atomic_add(&fNextNumber, 1); BString name = BString(baseName) << atomic_add(&fNextNumber, 1);
@@ -56,6 +58,8 @@ TempEntryManager::Create(const BString& baseName)
} }
} // namespace Private
} // namespace Package } // namespace Package
} // namespace Haiku } // namespace Haiku
+86
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