package daemon: Rework error and issue propagation to client
* BDaemonClient: Move inner class BCommitTransactionResult to top level
and make it public.
* BCommitTransactionResult:
- Add a whole bunch of specific error code enum values. Such an error
code is now the primary error, as opposed to before where we would
mix status_t and enum value errors. There's a systemError property
of type status_t which may provide additional information, though
(depending on the primary error type).
- Remove the errorMessage property. Due to mapping all errors to the
specific error codes this is no longer necessary. Mixing such a
message with another error description is also not very helpful when
it comes to localization (still not supported, though).
- Add several properties (paths, strings, error codes) that serve as
arguments to the primary error and are used by FullErrorMessage().
- Add issues property, a list of instances of new class
BTransactionIssue. Those describe non-critical issues (e.g. failed
update of a settings file) that occurred in the process of
committing the transaction. Those issues should be presented to the
user by the package management program.
* Exception: Adjust to transport the BCommitTransactionResult
properties.
* CommitTransactionHandler, FsTransactions, Root, Volume: Adjust to
BCommitTransactionResult/Exception changes.
* CommitTransactionHandler: Now requires a BCommitTransactionResult to
which it adds the issues it encounters. The reply BMessage is no
longer needed, though.
* Volume: Refactor common code from the three methods that use
CommitTransactionHandler into new method _CommitTransaction.
This commit is contained in:
@@ -0,0 +1 @@
|
||||
#include <../os/package/CommitTransactionResult.h>
|
||||
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright 2014, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _PACKAGE__COMMIT_TRANSACTION_RESULT_H_
|
||||
#define _PACKAGE__COMMIT_TRANSACTION_RESULT_H_
|
||||
|
||||
|
||||
#include <ObjectList.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class BMessage;
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
enum BTransactionError {
|
||||
B_TRANSACTION_OK = 0,
|
||||
B_TRANSACTION_NO_MEMORY,
|
||||
B_TRANSACTION_INTERNAL_ERROR,
|
||||
B_TRANSACTION_INSTALLATION_LOCATION_BUSY,
|
||||
B_TRANSACTION_CHANGE_COUNT_MISMATCH,
|
||||
B_TRANSACTION_BAD_REQUEST,
|
||||
B_TRANSACTION_NO_SUCH_PACKAGE,
|
||||
B_TRANSACTION_PACKAGE_ALREADY_EXISTS,
|
||||
B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH,
|
||||
B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY,
|
||||
B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY,
|
||||
B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY,
|
||||
B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY,
|
||||
B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE,
|
||||
B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE,
|
||||
B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE,
|
||||
B_TRANSACTION_FAILED_TO_OPEN_FILE,
|
||||
B_TRANSACTION_FAILED_TO_MOVE_FILE,
|
||||
B_TRANSACTION_FAILED_TO_COPY_FILE,
|
||||
B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE,
|
||||
B_TRANSACTION_FAILED_TO_ACCESS_ENTRY,
|
||||
B_TRANSACTION_FAILED_TO_ADD_GROUP,
|
||||
B_TRANSACTION_FAILED_TO_ADD_USER,
|
||||
B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP,
|
||||
B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION,
|
||||
};
|
||||
|
||||
|
||||
class BTransactionIssue {
|
||||
public:
|
||||
enum BType {
|
||||
B_WRITABLE_FILE_TYPE_MISMATCH,
|
||||
B_WRITABLE_FILE_NO_PACKAGE_ATTRIBUTE,
|
||||
B_WRITABLE_FILE_OLD_ORIGINAL_FILE_MISSING,
|
||||
B_WRITABLE_FILE_OLD_ORIGINAL_FILE_TYPE_MISMATCH,
|
||||
B_WRITABLE_FILE_COMPARISON_FAILED,
|
||||
B_WRITABLE_FILE_NOT_EQUAL,
|
||||
B_WRITABLE_SYMLINK_COMPARISON_FAILED,
|
||||
B_WRITABLE_SYMLINK_NOT_EQUAL,
|
||||
B_POST_INSTALL_SCRIPT_NOT_FOUND,
|
||||
B_STARTING_POST_INSTALL_SCRIPT_FAILED,
|
||||
B_POST_INSTALL_SCRIPT_FAILED,
|
||||
};
|
||||
|
||||
public:
|
||||
BTransactionIssue();
|
||||
BTransactionIssue(BType type,
|
||||
const BString& packageName,
|
||||
const BString& path1, const BString& path2,
|
||||
status_t systemError, int exitCode);
|
||||
BTransactionIssue(
|
||||
const BTransactionIssue& other);
|
||||
~BTransactionIssue();
|
||||
|
||||
BType Type() const;
|
||||
const BString& PackageName() const;
|
||||
const BString& Path1() const;
|
||||
const BString& Path2() const;
|
||||
status_t SystemError() const;
|
||||
int ExitCode() const;
|
||||
|
||||
BString ToString() const;
|
||||
|
||||
status_t AddToMessage(BMessage& message) const;
|
||||
status_t ExtractFromMessage(const BMessage& message);
|
||||
|
||||
BTransactionIssue& operator=(const BTransactionIssue& other);
|
||||
|
||||
private:
|
||||
BType fType;
|
||||
BString fPackageName;
|
||||
BString fPath1;
|
||||
BString fPath2;
|
||||
status_t fSystemError;
|
||||
int fExitCode;
|
||||
};
|
||||
|
||||
|
||||
class BCommitTransactionResult {
|
||||
public:
|
||||
BCommitTransactionResult();
|
||||
BCommitTransactionResult(
|
||||
BTransactionError error);
|
||||
BCommitTransactionResult(
|
||||
const BCommitTransactionResult& other);
|
||||
~BCommitTransactionResult();
|
||||
|
||||
void Unset();
|
||||
|
||||
int32 CountIssues() const;
|
||||
const BTransactionIssue* IssueAt(int32 index) const;
|
||||
bool AddIssue(const BTransactionIssue& issue);
|
||||
|
||||
BTransactionError Error() const;
|
||||
void SetError(BTransactionError error);
|
||||
|
||||
status_t SystemError() const;
|
||||
void SetSystemError(status_t error);
|
||||
|
||||
const BString& ErrorPackage() const;
|
||||
// may be empty, even on error
|
||||
void SetErrorPackage(const BString& packageName);
|
||||
|
||||
BString FullErrorMessage() const;
|
||||
|
||||
const BString& Path1() const;
|
||||
void SetPath1(const BString& path);
|
||||
|
||||
const BString& Path2() const;
|
||||
void SetPath2(const BString& path);
|
||||
|
||||
const BString& Path3() const;
|
||||
void SetPath3(const BString& path);
|
||||
|
||||
const BString& String1() const;
|
||||
void SetString1(const BString& string);
|
||||
|
||||
const BString& String2() const;
|
||||
void SetString2(const BString& string);
|
||||
|
||||
const BString& OldStateDirectory() const;
|
||||
void SetOldStateDirectory(const BString& directory);
|
||||
|
||||
status_t AddToMessage(BMessage& message) const;
|
||||
status_t ExtractFromMessage(const BMessage& message);
|
||||
|
||||
BCommitTransactionResult& operator=(
|
||||
const BCommitTransactionResult& other);
|
||||
|
||||
private:
|
||||
typedef BObjectList<BTransactionIssue> IssueList;
|
||||
|
||||
private:
|
||||
BTransactionError fError;
|
||||
status_t fSystemError;
|
||||
BString fErrorPackage;
|
||||
BString fPath1;
|
||||
BString fPath2;
|
||||
BString fString1;
|
||||
BString fString2;
|
||||
BString fOldStateDirectory;
|
||||
IssueList fIssues;
|
||||
};
|
||||
|
||||
|
||||
} // namespace BPackageKit
|
||||
|
||||
|
||||
#endif // _PACKAGE__COMMIT_TRANSACTION_RESULT_H_
|
||||
@@ -22,6 +22,7 @@ class BDirectory;
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
class BCommitTransactionResult;
|
||||
class BInstallationLocationInfo;
|
||||
class BPackageInfoSet;
|
||||
|
||||
@@ -33,9 +34,6 @@ class BActivationTransaction;
|
||||
|
||||
|
||||
class BDaemonClient {
|
||||
public:
|
||||
class BCommitTransactionResult;
|
||||
|
||||
public:
|
||||
BDaemonClient();
|
||||
~BDaemonClient();
|
||||
@@ -65,41 +63,6 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class BDaemonClient::BCommitTransactionResult {
|
||||
public:
|
||||
BCommitTransactionResult();
|
||||
BCommitTransactionResult(int32 error,
|
||||
const BString& errorMessage,
|
||||
const BString& errorPackage,
|
||||
const BString& oldStateDirectory);
|
||||
~BCommitTransactionResult();
|
||||
|
||||
void SetTo(int32 error, const BString& errorMessage,
|
||||
const BString& errorPackage,
|
||||
const BString& oldStateDirectory);
|
||||
|
||||
status_t Error() const;
|
||||
BDaemonError DaemonError() const;
|
||||
// may be B_DAEMON_OK, even if Error() is
|
||||
// != B_OK, then Error() is as specific as
|
||||
// is known
|
||||
const BString& ErrorMessage() const;
|
||||
// may be empty, even on error
|
||||
const BString& ErrorPackage() const;
|
||||
// may be empty, even on error
|
||||
|
||||
BString FullErrorMessage() const;
|
||||
|
||||
const BString& OldStateDirectory() const;
|
||||
|
||||
private:
|
||||
int32 fError;
|
||||
BString fErrorMessage;
|
||||
BString fErrorPackage;
|
||||
BString fOldStateDirectory;
|
||||
};
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
} // namespace BPackageKit
|
||||
|
||||
|
||||
@@ -16,16 +16,6 @@ namespace BPrivate {
|
||||
#define B_PACKAGE_DAEMON_APP_SIGNATURE "application/x-vnd.haiku-package_daemon"
|
||||
|
||||
|
||||
enum BDaemonError {
|
||||
B_DAEMON_OK = 0,
|
||||
B_DAEMON_INSTALLATION_LOCATION_BUSY,
|
||||
B_DAEMON_CHANGE_COUNT_MISMATCH,
|
||||
B_DAEMON_BAD_REQUEST,
|
||||
B_DAEMON_NO_SUCH_PACKAGE,
|
||||
B_DAEMON_PACKAGE_ALREADY_EXISTS
|
||||
};
|
||||
|
||||
|
||||
// message codes for requests to and replies from the daemon
|
||||
enum {
|
||||
B_MESSAGE_GET_INSTALLATION_LOCATION_INFO = 'PKLI',
|
||||
@@ -59,17 +49,40 @@ enum {
|
||||
// transaction directory
|
||||
B_MESSAGE_COMMIT_TRANSACTION_REPLY = 'PKTR'
|
||||
// "error": int32
|
||||
// regular error code or BDaemonError describing how committing
|
||||
// the transaction went
|
||||
// "error message": string
|
||||
// [error case only] gives some additional information what went
|
||||
// wrong; optional
|
||||
// a BTransactionError describing how committing the transaction
|
||||
// went
|
||||
// "system error": int32
|
||||
// a status_t for the operation that failed; B_ERROR, if n/a
|
||||
// "error package": string
|
||||
// [error case only] file name of the package causing the error,
|
||||
// if any in particarly; optional
|
||||
// "path1": string
|
||||
// [error case only] first path specific to the error
|
||||
// "path2": string
|
||||
// [error case only] second path specific to the error
|
||||
// "string1": string
|
||||
// [error case only] first string specific to the error
|
||||
// "string2": string
|
||||
// [error case only] second string specific to the error
|
||||
// "old state": string
|
||||
// name of the directory (subdirectory of the administrative
|
||||
// directory) containing the deactivated packages
|
||||
// [success case only] name of the directory (subdirectory of the
|
||||
// administrative directory) containing the deactivated packages
|
||||
// "issues": message[]
|
||||
// A list of non-critical issues that occurred while performing the
|
||||
// package activation. On success the user should be notified about
|
||||
// these. Each contains:
|
||||
// "type": int32
|
||||
// a BTransactionIssue::BType specifying the kind of issue
|
||||
// "package": string
|
||||
// file name of the package which the issue is related to
|
||||
// "path1": string
|
||||
// first path specific to the issue
|
||||
// "path2": string
|
||||
// second path specific to the issue
|
||||
// "system error": int32
|
||||
// a status_t for the operation that failed; B_OK, if n/a
|
||||
// "exit code": int32
|
||||
// a exit code of the program that failed; 0, if n/a
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -234,8 +234,7 @@ public:
|
||||
virtual status_t PrepareTransaction(Transaction& transaction)
|
||||
= 0;
|
||||
virtual status_t CommitTransaction(Transaction& transaction,
|
||||
BDaemonClient::BCommitTransactionResult&
|
||||
_result) = 0;
|
||||
BCommitTransactionResult& _result) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -250,8 +249,7 @@ public:
|
||||
|
||||
virtual status_t PrepareTransaction(Transaction& transaction);
|
||||
virtual status_t CommitTransaction(Transaction& transaction,
|
||||
BDaemonClient::BCommitTransactionResult&
|
||||
_result);
|
||||
BCommitTransactionResult& _result);
|
||||
|
||||
private:
|
||||
BDaemonClient fDaemonClient;
|
||||
|
||||
@@ -97,6 +97,7 @@ BuildPlatformSharedLibrary libpackage_build.so
|
||||
AddRepositoryRequest.cpp
|
||||
Attributes.cpp
|
||||
ChecksumAccessors.cpp
|
||||
CommitTransactionResult.cpp
|
||||
Context.cpp
|
||||
DownloadFileRequest.cpp
|
||||
DropRepositoryRequest.cpp
|
||||
|
||||
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
* Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Ingo Weinhold <[email protected]>
|
||||
*/
|
||||
|
||||
|
||||
#include <package/CommitTransactionResult.h>
|
||||
|
||||
#include <Message.h>
|
||||
|
||||
//#include <package/DaemonDefs.h>
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
|
||||
|
||||
// #pragma mark - BTransactionIssue
|
||||
|
||||
|
||||
BTransactionIssue::BTransactionIssue()
|
||||
:
|
||||
fType(B_WRITABLE_FILE_TYPE_MISMATCH),
|
||||
fPackageName(),
|
||||
fPath1(),
|
||||
fPath2(),
|
||||
fSystemError(B_OK),
|
||||
fExitCode(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BTransactionIssue::BTransactionIssue(BType type, const BString& packageName,
|
||||
const BString& path1, const BString& path2, status_t systemError,
|
||||
int exitCode)
|
||||
:
|
||||
fType(type),
|
||||
fPackageName(packageName),
|
||||
fPath1(path1),
|
||||
fPath2(path2),
|
||||
fSystemError(systemError),
|
||||
fExitCode(exitCode)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BTransactionIssue::BTransactionIssue(const BTransactionIssue& other)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
BTransactionIssue::~BTransactionIssue()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BTransactionIssue::BType
|
||||
BTransactionIssue::Type() const
|
||||
{
|
||||
return fType;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BTransactionIssue::PackageName() const
|
||||
{
|
||||
return fPackageName;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BTransactionIssue::Path1() const
|
||||
{
|
||||
return fPath1;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BTransactionIssue::Path2() const
|
||||
{
|
||||
return fPath2;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BTransactionIssue::SystemError() const
|
||||
{
|
||||
return fSystemError;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
BTransactionIssue::ExitCode() const
|
||||
{
|
||||
return fExitCode;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BTransactionIssue::ToString() const
|
||||
{
|
||||
const char* messageTemplate = "";
|
||||
switch (fType) {
|
||||
case B_WRITABLE_FILE_TYPE_MISMATCH:
|
||||
messageTemplate = "\"%path1%\" cannot be updated automatically,"
|
||||
" since its type doesn't match the type of \"%path2%\" which it"
|
||||
" is supposed to be updated with."
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_FILE_NO_PACKAGE_ATTRIBUTE:
|
||||
messageTemplate = "\"%path1%\" cannot be updated automatically,"
|
||||
" since it doesn't have a SYS:PACKAGE attribute."
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_MISSING:
|
||||
messageTemplate = "\"%path1%\" cannot be updated automatically,"
|
||||
" since \"%path2%\" which we need to compare it with is"
|
||||
" missing."
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_FILE_OLD_ORIGINAL_FILE_TYPE_MISMATCH:
|
||||
messageTemplate = "\"%path1%\" cannot be updated automatically,"
|
||||
" since its type doesn't match the type of \"%path2%\" which we"
|
||||
" need to compare it with."
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_FILE_COMPARISON_FAILED:
|
||||
messageTemplate = "\"%path1%\" cannot be updated automatically,"
|
||||
" since the comparison with \"%path2%\" failed: %error%."
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_FILE_NOT_EQUAL: // !keep old
|
||||
messageTemplate = "\"%path1%\" cannot be updated automatically,"
|
||||
" since it was changed manually from previous version"
|
||||
" \"%path2\""
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_SYMLINK_COMPARISON_FAILED: // !keep old
|
||||
messageTemplate = "Symbolic link \"%path1%\" cannot be updated"
|
||||
" automatically, since the comparison with \"%path2%\" failed:"
|
||||
" %error%."
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_WRITABLE_SYMLINK_NOT_EQUAL: // !keep old
|
||||
messageTemplate = "Symbolic link \"%path1%\" cannot be updated"
|
||||
" automatically, since it was changed manually from previous"
|
||||
" version \"%path2\""
|
||||
" Please perform the update manually if needed.";
|
||||
break;
|
||||
case B_POST_INSTALL_SCRIPT_NOT_FOUND:
|
||||
messageTemplate = "Failed to find post-installation script "
|
||||
" \"%path1%\": %error%.";
|
||||
break;
|
||||
case B_STARTING_POST_INSTALL_SCRIPT_FAILED:
|
||||
messageTemplate = "Failed to run post-installation script "
|
||||
" \"%path1%\": %error%.";
|
||||
break;
|
||||
case B_POST_INSTALL_SCRIPT_FAILED:
|
||||
messageTemplate = "The post-installation script "
|
||||
" \"%path1%\" failed with exit code %exitCode%.";
|
||||
break;
|
||||
}
|
||||
|
||||
BString message(messageTemplate);
|
||||
message.ReplaceAll("%path1%", fPath1)
|
||||
.ReplaceAll("%path2%", fPath2)
|
||||
.ReplaceAll("%error%", strerror(fSystemError))
|
||||
.ReplaceAll("%exitCode%", BString() << fExitCode);
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BTransactionIssue::AddToMessage(BMessage& message) const
|
||||
{
|
||||
status_t error;
|
||||
if ((error = message.AddInt32("type", (int32)fType)) != B_OK
|
||||
|| (error = message.AddString("package", fPackageName)) != B_OK
|
||||
|| (error = message.AddString("path1", fPath1)) != B_OK
|
||||
|| (error = message.AddString("path2", fPath2)) != B_OK
|
||||
|| (error = message.AddInt32("system error", (int32)fSystemError))
|
||||
!= B_OK
|
||||
|| (error = message.AddInt32("exit code", (int32)fExitCode)) != B_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BTransactionIssue::ExtractFromMessage(const BMessage& message)
|
||||
{
|
||||
status_t error;
|
||||
int32 type;
|
||||
int32 systemError;
|
||||
int32 exitCode;
|
||||
if ((error = message.FindInt32("type", &type)) != B_OK
|
||||
|| (error = message.FindString("package", &fPackageName)) != B_OK
|
||||
|| (error = message.FindString("path1", &fPath1)) != B_OK
|
||||
|| (error = message.FindString("path2", &fPath2)) != B_OK
|
||||
|| (error = message.FindInt32("system error", &systemError)) != B_OK
|
||||
|| (error = message.FindInt32("exit code", &exitCode)) != B_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
fType = (BType)type;
|
||||
fSystemError = (status_t)systemError;
|
||||
fExitCode = (int)exitCode;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BTransactionIssue&
|
||||
BTransactionIssue::operator=(const BTransactionIssue& other)
|
||||
{
|
||||
fType = other.fType;
|
||||
fPackageName = other.fPackageName;
|
||||
fPath1 = other.fPath1;
|
||||
fPath2 = other.fPath2;
|
||||
fSystemError = other.fSystemError;
|
||||
fExitCode = other.fExitCode;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BCommitTransactionResult
|
||||
|
||||
|
||||
BCommitTransactionResult::BCommitTransactionResult()
|
||||
:
|
||||
fError(B_TRANSACTION_INTERNAL_ERROR),
|
||||
fSystemError(B_ERROR),
|
||||
fErrorPackage(),
|
||||
fPath1(),
|
||||
fPath2(),
|
||||
fString1(),
|
||||
fString2(),
|
||||
fOldStateDirectory(),
|
||||
fIssues(10, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCommitTransactionResult::BCommitTransactionResult(BTransactionError error)
|
||||
:
|
||||
fError(error),
|
||||
fSystemError(B_ERROR),
|
||||
fErrorPackage(),
|
||||
fPath1(),
|
||||
fPath2(),
|
||||
fString1(),
|
||||
fString2(),
|
||||
fOldStateDirectory(),
|
||||
fIssues(10, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCommitTransactionResult::BCommitTransactionResult(
|
||||
const BCommitTransactionResult& other)
|
||||
:
|
||||
fError(B_TRANSACTION_INTERNAL_ERROR),
|
||||
fSystemError(B_ERROR),
|
||||
fErrorPackage(),
|
||||
fPath1(),
|
||||
fPath2(),
|
||||
fString1(),
|
||||
fString2(),
|
||||
fOldStateDirectory(),
|
||||
fIssues(10, true)
|
||||
{
|
||||
*this = other;
|
||||
}
|
||||
|
||||
|
||||
BCommitTransactionResult::~BCommitTransactionResult()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::Unset()
|
||||
{
|
||||
fError = B_TRANSACTION_INTERNAL_ERROR;
|
||||
fSystemError = B_ERROR;
|
||||
fErrorPackage.Truncate(0);
|
||||
fPath1.Truncate(0);
|
||||
fPath2.Truncate(0);
|
||||
fString1.Truncate(0);
|
||||
fString2.Truncate(0);
|
||||
fOldStateDirectory.Truncate(0);
|
||||
fIssues.MakeEmpty();
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BCommitTransactionResult::CountIssues() const
|
||||
{
|
||||
return fIssues.CountItems();
|
||||
}
|
||||
|
||||
|
||||
const BTransactionIssue*
|
||||
BCommitTransactionResult::IssueAt(int32 index) const
|
||||
{
|
||||
if (index < 0 || index >= CountIssues())
|
||||
return NULL;
|
||||
return fIssues.ItemAt(index);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BCommitTransactionResult::AddIssue(const BTransactionIssue& issue)
|
||||
{
|
||||
BTransactionIssue* newIssue = new(std::nothrow) BTransactionIssue(issue);
|
||||
if (newIssue == NULL || !fIssues.AddItem(newIssue)) {
|
||||
delete newIssue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
BTransactionError
|
||||
BCommitTransactionResult::Error() const
|
||||
{
|
||||
return fError > 0 ? (BTransactionError)fError : B_TRANSACTION_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetError(BTransactionError error)
|
||||
{
|
||||
fError = error;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCommitTransactionResult::SystemError() const
|
||||
{
|
||||
return fSystemError;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetSystemError(status_t error)
|
||||
{
|
||||
fSystemError = error;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BCommitTransactionResult::ErrorPackage() const
|
||||
{
|
||||
return fErrorPackage;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetErrorPackage(const BString& packageName)
|
||||
{
|
||||
fErrorPackage = packageName;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BCommitTransactionResult::FullErrorMessage() const
|
||||
{
|
||||
if (fError == 0)
|
||||
return "no error";
|
||||
|
||||
const char* messageTemplate = "";
|
||||
switch ((BTransactionError)fError) {
|
||||
case B_TRANSACTION_OK:
|
||||
messageTemplate = "Everything went fine.";
|
||||
break;
|
||||
case B_TRANSACTION_NO_MEMORY:
|
||||
messageTemplate = "Out of memory.";
|
||||
break;
|
||||
case B_TRANSACTION_INTERNAL_ERROR:
|
||||
messageTemplate = "An internal error occurred. Specifics can be"
|
||||
" found in the syslog.";
|
||||
break;
|
||||
case B_TRANSACTION_INSTALLATION_LOCATION_BUSY:
|
||||
messageTemplate = "Another package operation is already in"
|
||||
" progress.";
|
||||
break;
|
||||
case B_TRANSACTION_CHANGE_COUNT_MISMATCH:
|
||||
messageTemplate = "The transaction is out of date.";
|
||||
break;
|
||||
case B_TRANSACTION_BAD_REQUEST:
|
||||
messageTemplate = "The requested transaction is invalid.";
|
||||
break;
|
||||
case B_TRANSACTION_NO_SUCH_PACKAGE:
|
||||
messageTemplate = "No such package \"%package%\".";
|
||||
break;
|
||||
case B_TRANSACTION_PACKAGE_ALREADY_EXISTS:
|
||||
messageTemplate = "The to be activated package \"%package%\" does"
|
||||
" already exist.";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH:
|
||||
if (fPath1.IsEmpty()) {
|
||||
if (fErrorPackage.IsEmpty()) {
|
||||
messageTemplate = "A file path could not be determined:"
|
||||
"%error%";
|
||||
} else {
|
||||
messageTemplate = "While processing package \"%package%\""
|
||||
" a file path could not be determined: %error%";
|
||||
}
|
||||
} else {
|
||||
if (fErrorPackage.IsEmpty()) {
|
||||
messageTemplate = "The file path for \"%path1%\" could not"
|
||||
" be determined: %error%";
|
||||
} else {
|
||||
messageTemplate = "While processing package \"%package%\""
|
||||
" the file path for \"%path1%\" could not be"
|
||||
" determined: %error%";
|
||||
}
|
||||
}
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_OPEN_DIRECTORY:
|
||||
messageTemplate = "Failed to open directory \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_CREATE_DIRECTORY:
|
||||
messageTemplate = "Failed to create directory \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_REMOVE_DIRECTORY:
|
||||
messageTemplate = "Failed to remove directory \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_MOVE_DIRECTORY:
|
||||
messageTemplate = "Failed to move directory \"%path1%\" to"
|
||||
" \"%path2%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_WRITE_ACTIVATION_FILE:
|
||||
messageTemplate = "Failed to write new package activation file"
|
||||
" \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_READ_PACKAGE_FILE:
|
||||
messageTemplate = "Failed to read package file \"%path1%\":"
|
||||
" %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_EXTRACT_PACKAGE_FILE:
|
||||
messageTemplate = "Failed to extract \"%path1%\" from package"
|
||||
" \"%package%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_OPEN_FILE:
|
||||
messageTemplate = "Failed to open file \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_MOVE_FILE:
|
||||
messageTemplate = "Failed to move file \"%path1%\" to \"%path2%\":"
|
||||
" %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_COPY_FILE:
|
||||
messageTemplate = "Failed to copy file \"%path1%\" to \"%path2%\":"
|
||||
" %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_WRITE_FILE_ATTRIBUTE:
|
||||
messageTemplate = "Failed to write attribute \"%string1%\" of file"
|
||||
" \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_ACCESS_ENTRY:
|
||||
messageTemplate = "Failed to access entry \"%path1%\": %error%";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_ADD_GROUP:
|
||||
messageTemplate = "Failed to add user group \"%string1%\" required"
|
||||
" by package \"%package%\".";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_ADD_USER:
|
||||
messageTemplate = "Failed to add user \"%string1%\" required"
|
||||
" by package \"%package%\".";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_ADD_USER_TO_GROUP:
|
||||
messageTemplate = "Failed to add user \"%string1%\" to group"
|
||||
" \"%string2%\" as required by package \"%package%\".";
|
||||
break;
|
||||
case B_TRANSACTION_FAILED_TO_CHANGE_PACKAGE_ACTIVATION:
|
||||
messageTemplate = "Failed to change the package activation in"
|
||||
" packagefs: %error%";
|
||||
break;
|
||||
}
|
||||
|
||||
BString message(messageTemplate);
|
||||
message.ReplaceAll("%package%", fErrorPackage)
|
||||
.ReplaceAll("%path1%", fPath1)
|
||||
.ReplaceAll("%path2%", fPath2)
|
||||
.ReplaceAll("%string1%", fString1)
|
||||
.ReplaceAll("%string2%", fString2)
|
||||
.ReplaceAll("%error%", strerror(fSystemError));
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BCommitTransactionResult::Path1() const
|
||||
{
|
||||
return fPath1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetPath1(const BString& path)
|
||||
{
|
||||
fPath1 = path;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BCommitTransactionResult::Path2() const
|
||||
{
|
||||
return fPath2;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetPath2(const BString& path)
|
||||
{
|
||||
fPath2 = path;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BCommitTransactionResult::String1() const
|
||||
{
|
||||
return fString1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetString1(const BString& string)
|
||||
{
|
||||
fString1 = string;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BCommitTransactionResult::String2() const
|
||||
{
|
||||
return fString2;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetString2(const BString& string)
|
||||
{
|
||||
fString2 = string;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BCommitTransactionResult::OldStateDirectory() const
|
||||
{
|
||||
return fOldStateDirectory;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BCommitTransactionResult::SetOldStateDirectory(const BString& directory)
|
||||
{
|
||||
fOldStateDirectory = directory;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCommitTransactionResult::AddToMessage(BMessage& message) const
|
||||
{
|
||||
status_t error;
|
||||
if ((error = message.AddInt32("error", (int32)fError)) != B_OK
|
||||
|| (error = message.AddInt32("system error", (int32)fSystemError))
|
||||
!= B_OK
|
||||
|| (error = message.AddString("error package", fErrorPackage)) != B_OK
|
||||
|| (error = message.AddString("path1", fPath1)) != B_OK
|
||||
|| (error = message.AddString("path2", fPath2)) != B_OK
|
||||
|| (error = message.AddString("string1", fString1)) != B_OK
|
||||
|| (error = message.AddString("string2", fString2)) != B_OK
|
||||
|| (error = message.AddString("old state", fOldStateDirectory))
|
||||
!= B_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
int32 count = fIssues.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
const BTransactionIssue* issue = fIssues.ItemAt(i);
|
||||
BMessage issueMessage;
|
||||
if ((error = issue->AddToMessage(issueMessage)) != B_OK
|
||||
|| (error = message.AddMessage("issues", &issueMessage)) != B_OK) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCommitTransactionResult::ExtractFromMessage(const BMessage& message)
|
||||
{
|
||||
Unset();
|
||||
|
||||
int32 resultError;
|
||||
int32 systemError;
|
||||
status_t error;
|
||||
if ((error = message.FindInt32("error", &resultError)) != B_OK
|
||||
|| (error = message.FindInt32("system error", &systemError)) != B_OK
|
||||
|| (error = message.FindString("error package", &fErrorPackage)) != B_OK
|
||||
|| (error = message.FindString("path1", &fPath1)) != B_OK
|
||||
|| (error = message.FindString("path2", &fPath2)) != B_OK
|
||||
|| (error = message.FindString("string1", &fString1)) != B_OK
|
||||
|| (error = message.FindString("string2", &fString2)) != B_OK
|
||||
|| (error = message.FindString("old state", &fOldStateDirectory))
|
||||
!= B_OK) {
|
||||
return error;
|
||||
}
|
||||
|
||||
fError = (BTransactionError)resultError;
|
||||
fSystemError = (status_t)systemError;
|
||||
|
||||
BMessage issueMessage;
|
||||
for (int32 i = 0; message.FindMessage("issues", i, &issueMessage) == B_OK;
|
||||
i++) {
|
||||
BTransactionIssue issue;
|
||||
error = issue.ExtractFromMessage(issueMessage);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (!AddIssue(issue))
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
BCommitTransactionResult&
|
||||
BCommitTransactionResult::operator=(const BCommitTransactionResult& other)
|
||||
{
|
||||
Unset();
|
||||
|
||||
fError = other.fError;
|
||||
fSystemError = other.fSystemError;
|
||||
fErrorPackage = other.fErrorPackage;
|
||||
fPath1 = other.fPath1;
|
||||
fPath2 = other.fPath2;
|
||||
fString1 = other.fString1;
|
||||
fString2 = other.fString2;
|
||||
fOldStateDirectory = other.fOldStateDirectory;
|
||||
|
||||
for (int32 i = 0; const BTransactionIssue* issue = other.fIssues.ItemAt(i);
|
||||
i++) {
|
||||
AddIssue(*issue);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
} // namespace BPackageKit
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <package/CommitTransactionResult.h>
|
||||
#include <package/InstallationLocationInfo.h>
|
||||
#include <package/PackageInfo.h>
|
||||
|
||||
@@ -24,9 +25,6 @@ namespace BPackageKit {
|
||||
namespace BPrivate {
|
||||
|
||||
|
||||
// #pragma mark - BCommitTransactionResult
|
||||
|
||||
|
||||
BDaemonClient::BDaemonClient()
|
||||
:
|
||||
fDaemonMessenger()
|
||||
@@ -131,26 +129,7 @@ BDaemonClient::CommitTransaction(const BActivationTransaction& transaction,
|
||||
return B_ERROR;
|
||||
|
||||
// extract the result
|
||||
int32 requestError;
|
||||
error = reply.FindInt32("error", &requestError);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
BString errorMessage;
|
||||
BString errorPackage;
|
||||
BString oldStateDirectory;
|
||||
if (requestError == 0) {
|
||||
error = reply.FindString("old state", &oldStateDirectory);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
} else {
|
||||
reply.FindString("error message", &errorMessage);
|
||||
reply.FindString("error package", &errorPackage);
|
||||
}
|
||||
|
||||
_result.SetTo(requestError, errorMessage, errorPackage, oldStateDirectory);
|
||||
return B_OK;
|
||||
// Even on error. B_OK just indicates that we have initialized _result.
|
||||
return _result.ExtractFromMessage(reply);
|
||||
}
|
||||
|
||||
|
||||
@@ -254,129 +233,5 @@ BDaemonClient::_ExtractPackageInfoSet(const BMessage& message,
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BCommitTransactionResult
|
||||
|
||||
|
||||
BDaemonClient::BCommitTransactionResult::BCommitTransactionResult()
|
||||
:
|
||||
fError(B_NO_INIT),
|
||||
fErrorMessage(),
|
||||
fErrorPackage(),
|
||||
fOldStateDirectory()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BDaemonClient::BCommitTransactionResult::BCommitTransactionResult(int32 error,
|
||||
const BString& errorMessage, const BString& errorPackage,
|
||||
const BString& oldStateDirectory)
|
||||
:
|
||||
fError(error),
|
||||
fErrorMessage(errorMessage),
|
||||
fErrorPackage(errorPackage),
|
||||
fOldStateDirectory(oldStateDirectory)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BDaemonClient::BCommitTransactionResult::~BCommitTransactionResult()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BDaemonClient::BCommitTransactionResult::SetTo(int32 error,
|
||||
const BString& errorMessage, const BString& errorPackage,
|
||||
const BString& oldStateDirectory)
|
||||
{
|
||||
fError = error;
|
||||
fErrorMessage = errorMessage;
|
||||
fErrorPackage = errorPackage;
|
||||
fOldStateDirectory = oldStateDirectory;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BDaemonClient::BCommitTransactionResult::Error() const
|
||||
{
|
||||
return fError <= 0 ? fError : B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
BDaemonError
|
||||
BDaemonClient::BCommitTransactionResult::DaemonError() const
|
||||
{
|
||||
return fError > 0 ? (BDaemonError)fError : B_DAEMON_OK;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BDaemonClient::BCommitTransactionResult::ErrorMessage() const
|
||||
{
|
||||
return fErrorMessage;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BDaemonClient::BCommitTransactionResult::ErrorPackage() const
|
||||
{
|
||||
return fErrorPackage;
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
BDaemonClient::BCommitTransactionResult::FullErrorMessage() const
|
||||
{
|
||||
if (fError == 0)
|
||||
return "no error";
|
||||
|
||||
const char* errorString;
|
||||
if (fError > 0) {
|
||||
switch ((BDaemonError)fError) {
|
||||
case B_DAEMON_INSTALLATION_LOCATION_BUSY:
|
||||
errorString = "another package operation already in progress";
|
||||
break;
|
||||
case B_DAEMON_CHANGE_COUNT_MISMATCH:
|
||||
errorString = "transaction out of date";
|
||||
break;
|
||||
case B_DAEMON_BAD_REQUEST:
|
||||
errorString = "invalid transaction";
|
||||
break;
|
||||
case B_DAEMON_NO_SUCH_PACKAGE:
|
||||
errorString = "no such package";
|
||||
break;
|
||||
case B_DAEMON_PACKAGE_ALREADY_EXISTS:
|
||||
errorString = "package already exists";
|
||||
break;
|
||||
case B_DAEMON_OK:
|
||||
default:
|
||||
errorString = "unknown error";
|
||||
break;
|
||||
}
|
||||
} else
|
||||
errorString = strerror(fError);
|
||||
|
||||
BString result;
|
||||
if (!fErrorMessage.IsEmpty()) {
|
||||
result = fErrorMessage;
|
||||
result << ": ";
|
||||
}
|
||||
|
||||
result << errorString;
|
||||
|
||||
if (!fErrorPackage.IsEmpty())
|
||||
result << ", package: \"" << fErrorPackage << '"';
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
BDaemonClient::BCommitTransactionResult::OldStateDirectory() const
|
||||
{
|
||||
return fOldStateDirectory;
|
||||
}
|
||||
|
||||
|
||||
} // namespace BPrivate
|
||||
} // namespace BPackageKit
|
||||
|
||||
@@ -14,6 +14,7 @@ HPKG_SOURCES =
|
||||
BlockBufferPoolNoLock.cpp
|
||||
BufferDataOutput.cpp
|
||||
BufferPool.cpp
|
||||
CommitTransactionResult.cpp
|
||||
DataReader.cpp
|
||||
DataWriters.cpp
|
||||
ErrorOutput.cpp
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <package/manager/PackageManager.h>
|
||||
|
||||
#include <Directory.h>
|
||||
#include <package/CommitTransactionResult.h>
|
||||
#include <package/DownloadFileRequest.h>
|
||||
#include <package/PackageRoster.h>
|
||||
#include <package/RefreshRepositoryRequest.h>
|
||||
@@ -576,12 +577,12 @@ BPackageManager::_CommitPackageChanges(Transaction& transaction)
|
||||
installationRepository);
|
||||
|
||||
// commit the transaction
|
||||
BDaemonClient::BCommitTransactionResult transactionResult;
|
||||
BCommitTransactionResult transactionResult;
|
||||
status_t error = fInstallationInterface->CommitTransaction(transaction,
|
||||
transactionResult);
|
||||
if (error != B_OK)
|
||||
DIE(error, "failed to commit transaction");
|
||||
if (transactionResult.Error() != B_OK) {
|
||||
if (transactionResult.Error() != B_TRANSACTION_OK) {
|
||||
DIE("failed to commit transaction: %s",
|
||||
transactionResult.FullErrorMessage().String());
|
||||
}
|
||||
@@ -933,7 +934,7 @@ BPackageManager::ClientInstallationInterface::PrepareTransaction(
|
||||
|
||||
status_t
|
||||
BPackageManager::ClientInstallationInterface::CommitTransaction(
|
||||
Transaction& transaction, BDaemonClient::BCommitTransactionResult& _result)
|
||||
Transaction& transaction, BCommitTransactionResult& _result)
|
||||
{
|
||||
return fDaemonClient.CommitTransaction(transaction.ActivationTransaction(),
|
||||
_result);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,10 +22,18 @@
|
||||
typedef std::set<std::string> StringSet;
|
||||
|
||||
|
||||
namespace BPackageKit {
|
||||
class BCommitTransactionResult;
|
||||
}
|
||||
|
||||
using BPackageKit::BCommitTransactionResult;
|
||||
|
||||
|
||||
class CommitTransactionHandler {
|
||||
public:
|
||||
CommitTransactionHandler(Volume* volume,
|
||||
PackageFileManager* packageFileManager);
|
||||
PackageFileManager* packageFileManager,
|
||||
BCommitTransactionResult& result);
|
||||
~CommitTransactionHandler();
|
||||
|
||||
void Init(VolumeState* volumeState,
|
||||
@@ -33,11 +41,9 @@ public:
|
||||
const PackageSet& packagesAlreadyAdded,
|
||||
const PackageSet& packagesAlreadyRemoved);
|
||||
|
||||
void HandleRequest(BMessage* request,
|
||||
BMessage* reply);
|
||||
void HandleRequest(BMessage* request);
|
||||
void HandleRequest(
|
||||
const BActivationTransaction& transaction,
|
||||
BMessage* reply);
|
||||
const BActivationTransaction& transaction);
|
||||
void HandleRequest();
|
||||
// uses packagesAlreadyAdded and
|
||||
// packagesAlreadyRemoved from Init()
|
||||
@@ -47,6 +53,9 @@ public:
|
||||
const BString& OldStateDirectoryName() const
|
||||
{ return fOldStateDirectoryName; }
|
||||
|
||||
Package* CurrentPackage() const
|
||||
{ return fCurrentPackage; }
|
||||
|
||||
VolumeState* DetachVolumeState();
|
||||
bool IsActiveVolumeState() const
|
||||
{ return fVolumeStateIsActive; }
|
||||
@@ -55,13 +64,15 @@ private:
|
||||
typedef BObjectList<Package> PackageList;
|
||||
typedef FSUtils::RelativePath RelativePath;
|
||||
|
||||
struct TransactionIssueBuilder;
|
||||
|
||||
private:
|
||||
void _GetPackagesToDeactivate(
|
||||
const BActivationTransaction& transaction);
|
||||
void _ReadPackagesToActivate(
|
||||
const BActivationTransaction& transaction);
|
||||
void _ApplyChanges(BMessage* reply);
|
||||
void _CreateOldStateDirectory(BMessage* reply);
|
||||
void _ApplyChanges();
|
||||
void _CreateOldStateDirectory();
|
||||
void _RemovePackagesToDeactivate();
|
||||
void _AddPackagesToActivate();
|
||||
|
||||
@@ -102,13 +113,13 @@ private:
|
||||
const char* fileName, uint32 openMode,
|
||||
BFile& _file, BEntry* _entry = NULL);
|
||||
|
||||
status_t _WriteActivationFile(
|
||||
void _WriteActivationFile(
|
||||
const RelativePath& directoryPath,
|
||||
const char* fileName,
|
||||
const PackageSet& toActivate,
|
||||
const PackageSet& toDeactivate,
|
||||
BEntry& _entry);
|
||||
status_t _CreateActivationFileContent(
|
||||
void _CreateActivationFileContent(
|
||||
const PackageSet& toActivate,
|
||||
const PackageSet& toDeactivate,
|
||||
BString& _content);
|
||||
@@ -131,10 +142,13 @@ private:
|
||||
|
||||
bool _IsSystemPackage(Package* package);
|
||||
|
||||
void _AddIssue(
|
||||
const TransactionIssueBuilder& builder);
|
||||
|
||||
static BString _GetPath(const FSUtils::Entry& entry,
|
||||
const BString& fallback);
|
||||
|
||||
static status_t _TagPackageEntriesRecursively(
|
||||
static void _TagPackageEntriesRecursively(
|
||||
BDirectory& directory, const BString& value,
|
||||
bool nonDirectoriesOnly);
|
||||
|
||||
@@ -157,6 +171,8 @@ private:
|
||||
StringSet fAddedGroups;
|
||||
StringSet fAddedUsers;
|
||||
FSTransaction fFSTransaction;
|
||||
BCommitTransactionResult& fResult;
|
||||
Package* fCurrentPackage;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -7,57 +7,77 @@
|
||||
#include "Exception.h"
|
||||
|
||||
|
||||
using namespace BPackageKit::BPrivate;
|
||||
using namespace BPackageKit;
|
||||
|
||||
|
||||
Exception::Exception(int32 error, const char* errorMessage,
|
||||
const char* packageName)
|
||||
Exception::Exception(BTransactionError error)
|
||||
:
|
||||
fError(error),
|
||||
fErrorMessage(errorMessage),
|
||||
fPackageName(packageName)
|
||||
fSystemError(B_ERROR),
|
||||
fPackageName(),
|
||||
fPath1(),
|
||||
fPath2(),
|
||||
fString1(),
|
||||
fString2()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BString
|
||||
Exception::ToString() const
|
||||
Exception&
|
||||
Exception::SetSystemError(status_t error)
|
||||
{
|
||||
const char* error;
|
||||
if (fError >= 0) {
|
||||
switch (fError) {
|
||||
case B_DAEMON_OK:
|
||||
error = "no error";
|
||||
break;
|
||||
case B_DAEMON_CHANGE_COUNT_MISMATCH:
|
||||
error = "transaction out of date";
|
||||
break;
|
||||
case B_DAEMON_BAD_REQUEST:
|
||||
error = "invalid transaction";
|
||||
break;
|
||||
case B_DAEMON_NO_SUCH_PACKAGE:
|
||||
error = "no such package";
|
||||
break;
|
||||
case B_DAEMON_PACKAGE_ALREADY_EXISTS:
|
||||
error = "package already exists";
|
||||
break;
|
||||
default:
|
||||
error = "unknown error";
|
||||
break;
|
||||
}
|
||||
} else
|
||||
error = strerror(fError);
|
||||
|
||||
BString string;
|
||||
if (!fErrorMessage.IsEmpty()) {
|
||||
string = fErrorMessage;
|
||||
string << ": ";
|
||||
}
|
||||
|
||||
string << error;
|
||||
|
||||
if (!fPackageName.IsEmpty())
|
||||
string << ", package: \"" << fPackageName << '"';
|
||||
|
||||
return string;
|
||||
fSystemError = error;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Exception&
|
||||
Exception::SetPackageName(const BString& packageName)
|
||||
{
|
||||
fPackageName = packageName;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Exception&
|
||||
Exception::SetPath1(const BString& path)
|
||||
{
|
||||
fPath1 = path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Exception&
|
||||
Exception::SetPath2(const BString& path)
|
||||
{
|
||||
fPath2 = path;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Exception&
|
||||
Exception::SetString1(const BString& string)
|
||||
{
|
||||
fString1 = string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
Exception&
|
||||
Exception::SetString2(const BString& string)
|
||||
{
|
||||
fString2 = string;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Exception::SetOnResult(BCommitTransactionResult& result)
|
||||
{
|
||||
result.SetError(fError);
|
||||
result.SetSystemError(fSystemError);
|
||||
result.SetErrorPackage(fPackageName);
|
||||
result.SetPath1(fPath1);
|
||||
result.SetPath2(fPath2);
|
||||
result.SetString1(fString1);
|
||||
result.SetString2(fString2);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef EXCEPTION_H
|
||||
@@ -8,30 +8,54 @@
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include <package/DaemonDefs.h>
|
||||
#include <package/CommitTransactionResult.h>
|
||||
|
||||
|
||||
using BPackageKit::BCommitTransactionResult;
|
||||
using BPackageKit::BTransactionError;
|
||||
|
||||
|
||||
class Exception {
|
||||
public:
|
||||
Exception(int32 error,
|
||||
const char* errorMessage = NULL,
|
||||
const char* packageName = NULL);
|
||||
Exception(BTransactionError error);
|
||||
|
||||
int32 Error() const
|
||||
BTransactionError Error() const
|
||||
{ return fError; }
|
||||
|
||||
const BString& ErrorMessage() const
|
||||
{ return fErrorMessage; }
|
||||
status_t SystemError() const
|
||||
{ return fSystemError; }
|
||||
Exception& SetSystemError(status_t error);
|
||||
|
||||
const BString& PackageName() const
|
||||
{ return fPackageName; }
|
||||
Exception& SetPackageName(const BString& packageName);
|
||||
|
||||
BString ToString() const;
|
||||
const BString& Path1() const
|
||||
{ return fPath1; }
|
||||
Exception& SetPath1(const BString& path);
|
||||
|
||||
const BString& Path2() const
|
||||
{ return fPath2; }
|
||||
Exception& SetPath2(const BString& path);
|
||||
|
||||
const BString& String1() const
|
||||
{ return fString1; }
|
||||
Exception& SetString1(const BString& string);
|
||||
|
||||
const BString& String2() const
|
||||
{ return fString2; }
|
||||
Exception& SetString2(const BString& string);
|
||||
|
||||
void SetOnResult(BCommitTransactionResult& result);
|
||||
|
||||
private:
|
||||
int32 fError;
|
||||
BString fErrorMessage;
|
||||
BTransactionError fError;
|
||||
status_t fSystemError;
|
||||
BString fPackageName;
|
||||
BString fPath1;
|
||||
BString fPath2;
|
||||
BString fString1;
|
||||
BString fString2;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "FSTransaction.h"
|
||||
|
||||
#include <Entry.h>
|
||||
#include <package/CommitTransactionResult.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include <CopyEngine.h>
|
||||
@@ -197,9 +198,9 @@ FSTransaction::RemoveOperationAt(int32 index)
|
||||
{
|
||||
int32 count = fOperations.size();
|
||||
if (index < 0 || index >= count) {
|
||||
throw Exception(B_ERROR,
|
||||
BString().SetToFormat("FSTransaction::RemoveOperationAt(): invalid "
|
||||
"operation index %" B_PRId32 "/%" B_PRId32, index, count));
|
||||
ERROR("FSTransaction::RemoveOperationAt(): invalid "
|
||||
"operation index %" B_PRId32 "/%" B_PRId32, index, count);
|
||||
throw Exception(BPackageKit::B_TRANSACTION_INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
fOperations.erase(fOperations.begin() + index);
|
||||
@@ -225,8 +226,14 @@ FSTransaction::_GetPath(const Entry& entry)
|
||||
error = pathBuffer.SetTo(path);
|
||||
}
|
||||
|
||||
if (error != B_OK)
|
||||
throw Exception(error);
|
||||
if (error != B_OK) {
|
||||
if (error == B_NO_MEMORY)
|
||||
throw Exception(BPackageKit::B_TRANSACTION_NO_MEMORY);
|
||||
|
||||
throw Exception(BPackageKit::B_TRANSACTION_FAILED_TO_GET_ENTRY_PATH)
|
||||
.SetPath1(entry.PathOrName())
|
||||
.SetSystemError(error);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
@@ -209,7 +209,7 @@ PackageManager::PrepareTransaction(Transaction& transaction)
|
||||
|
||||
status_t
|
||||
PackageManager::CommitTransaction(Transaction& transaction,
|
||||
BDaemonClient::BCommitTransactionResult& _result)
|
||||
BCommitTransactionResult& _result)
|
||||
{
|
||||
Volume* volume = fRoot->GetVolume(transaction.Repository().Location());
|
||||
if (volume == NULL)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Copyright 2013-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef PACKAGE_MANAGER_H
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <package/manager/PackageManager.h>
|
||||
|
||||
|
||||
using BPackageKit::BCommitTransactionResult;
|
||||
using BPackageKit::BContext;
|
||||
using BPackageKit::BJob;
|
||||
using BPackageKit::BJobStateListener;
|
||||
@@ -51,8 +52,7 @@ private:
|
||||
|
||||
virtual status_t PrepareTransaction(Transaction& transaction);
|
||||
virtual status_t CommitTransaction(Transaction& transaction,
|
||||
BDaemonClient::BCommitTransactionResult&
|
||||
_result);
|
||||
BCommitTransactionResult& _result);
|
||||
|
||||
private:
|
||||
// UserInteractionHandler
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <Alert.h>
|
||||
#include <Directory.h>
|
||||
#include <Entry.h>
|
||||
#include <package/CommitTransactionResult.h>
|
||||
#include <package/PackageDefs.h>
|
||||
#include <Path.h>
|
||||
|
||||
@@ -330,8 +331,9 @@ Root::HandleRequest(BMessage* message)
|
||||
// pending already.
|
||||
if (volume->IsPackageJobPending()) {
|
||||
BMessage reply(B_MESSAGE_COMMIT_TRANSACTION_REPLY);
|
||||
if (reply.AddInt32("error", B_DAEMON_INSTALLATION_LOCATION_BUSY)
|
||||
== B_OK) {
|
||||
BCommitTransactionResult result(
|
||||
B_TRANSACTION_INSTALLATION_LOCATION_BUSY);
|
||||
if (result.AddToMessage(reply) == B_OK) {
|
||||
message->SendReply(&reply, (BHandler*)NULL,
|
||||
kCommunicationTimeout);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
|
||||
#include <package/CommitTransactionResult.h>
|
||||
#include <package/solver/Solver.h>
|
||||
#include <package/solver/SolverPackage.h>
|
||||
#include <package/solver/SolverProblem.h>
|
||||
@@ -519,39 +520,18 @@ Volume::HandleGetLocationInfoRequest(BMessage* message)
|
||||
void
|
||||
Volume::HandleCommitTransactionRequest(BMessage* message)
|
||||
{
|
||||
// Prepare the reply in so far that we can at least set the error code
|
||||
// without risk of failure.
|
||||
BCommitTransactionResult result;
|
||||
PackageSet dummy;
|
||||
_CommitTransaction(message, NULL, dummy, dummy, result);
|
||||
|
||||
BMessage reply(B_MESSAGE_COMMIT_TRANSACTION_REPLY);
|
||||
if (reply.AddInt32("error", B_ERROR) != B_OK)
|
||||
status_t error = result.AddToMessage(reply);
|
||||
if (error != B_OK) {
|
||||
ERROR("Volume::HandleCommitTransactionRequest(): Failed to add "
|
||||
"transaction result to reply: %s\n", strerror(error));
|
||||
return;
|
||||
|
||||
// perform the request
|
||||
CommitTransactionHandler handler(this, fPackageFileManager);
|
||||
int32 error;
|
||||
try {
|
||||
PackageSet dummy;
|
||||
handler.Init(fLatestState, fLatestState == fActiveState, dummy, dummy);
|
||||
handler.HandleRequest(message, &reply);
|
||||
_SetLatestState(handler.DetachVolumeState(),
|
||||
handler.IsActiveVolumeState());
|
||||
error = B_DAEMON_OK;
|
||||
} catch (Exception& exception) {
|
||||
error = exception.Error();
|
||||
|
||||
if (!exception.ErrorMessage().IsEmpty())
|
||||
reply.AddString("error message", exception.ErrorMessage());
|
||||
if (!exception.PackageName().IsEmpty())
|
||||
reply.AddString("error package", exception.PackageName());
|
||||
} catch (std::bad_alloc& exception) {
|
||||
error = B_NO_MEMORY;
|
||||
}
|
||||
|
||||
// revert on error
|
||||
if (error != B_DAEMON_OK)
|
||||
handler.Revert();
|
||||
|
||||
// send the reply
|
||||
reply.ReplaceInt32("error", error);
|
||||
message->SendReply(&reply, (BHandler*)NULL, kCommunicationTimeout);
|
||||
}
|
||||
|
||||
@@ -709,31 +689,16 @@ Volume::ProcessPendingPackageActivationChanges()
|
||||
return;
|
||||
|
||||
// perform the request
|
||||
CommitTransactionHandler handler(this, fPackageFileManager);
|
||||
int32 error;
|
||||
try {
|
||||
handler.Init(fLatestState, fLatestState == fActiveState,
|
||||
fPackagesToBeActivated, fPackagesToBeDeactivated);
|
||||
handler.HandleRequest();
|
||||
_SetLatestState(handler.DetachVolumeState(),
|
||||
handler.IsActiveVolumeState());
|
||||
error = B_DAEMON_OK;
|
||||
} catch (Exception& exception) {
|
||||
error = exception.Error();
|
||||
BCommitTransactionResult result;
|
||||
_CommitTransaction(NULL, NULL, fPackagesToBeActivated,
|
||||
fPackagesToBeDeactivated, result);
|
||||
|
||||
if (result.Error() != B_TRANSACTION_OK) {
|
||||
ERROR("Volume::ProcessPendingPackageActivationChanges(): package "
|
||||
"activation failed: %s\n", exception.ToString().String());
|
||||
// TODO: Notify the user!
|
||||
} catch (std::bad_alloc& exception) {
|
||||
error = B_NO_MEMORY;
|
||||
ERROR("Volume::ProcessPendingPackageActivationChanges(): package "
|
||||
"activation failed: out of memory\n");
|
||||
"activation failed: %s\n", result.FullErrorMessage().String());
|
||||
// TODO: Notify the user!
|
||||
}
|
||||
|
||||
// revert on error
|
||||
if (error != B_DAEMON_OK)
|
||||
handler.Revert();
|
||||
|
||||
// clear the activation/deactivation sets in any event
|
||||
fPackagesToBeActivated.clear();
|
||||
fPackagesToBeDeactivated.clear();
|
||||
@@ -793,33 +758,10 @@ Volume::CreateTransaction(BPackageInstallationLocation location,
|
||||
void
|
||||
Volume::CommitTransaction(const BActivationTransaction& transaction,
|
||||
const PackageSet& packagesAlreadyAdded,
|
||||
const PackageSet& packagesAlreadyRemoved,
|
||||
BDaemonClient::BCommitTransactionResult& _result)
|
||||
const PackageSet& packagesAlreadyRemoved, BCommitTransactionResult& _result)
|
||||
{
|
||||
// perform the request
|
||||
CommitTransactionHandler handler(this, fPackageFileManager);
|
||||
int32 error;
|
||||
try {
|
||||
handler.Init(fLatestState, fLatestState == fActiveState,
|
||||
packagesAlreadyAdded, packagesAlreadyRemoved);
|
||||
handler.HandleRequest(transaction, NULL);
|
||||
_SetLatestState(handler.DetachVolumeState(),
|
||||
handler.IsActiveVolumeState());
|
||||
error = B_DAEMON_OK;
|
||||
_result.SetTo(error, BString(), BString(),
|
||||
handler.OldStateDirectoryName());
|
||||
} catch (Exception& exception) {
|
||||
error = exception.Error();
|
||||
_result.SetTo(error, exception.ErrorMessage(), exception.PackageName(),
|
||||
BString());
|
||||
} catch (std::bad_alloc& exception) {
|
||||
error = B_NO_MEMORY;
|
||||
_result.SetTo(error, BString(), BString(), BString());
|
||||
}
|
||||
|
||||
// revert on error
|
||||
if (error != B_DAEMON_OK)
|
||||
handler.Revert();
|
||||
_CommitTransaction(NULL, &transaction, packagesAlreadyAdded,
|
||||
packagesAlreadyRemoved, _result);
|
||||
}
|
||||
|
||||
|
||||
@@ -1325,3 +1267,47 @@ Volume::_OpenPackagesSubDirectory(const RelativePath& path, bool create,
|
||||
|
||||
return FSUtils::OpenSubDirectory(directory, path, create, _directory);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Volume::_CommitTransaction(BMessage* message,
|
||||
const BActivationTransaction* transaction,
|
||||
const PackageSet& packagesAlreadyAdded,
|
||||
const PackageSet& packagesAlreadyRemoved, BCommitTransactionResult& _result)
|
||||
{
|
||||
_result.Unset();
|
||||
|
||||
// perform the request
|
||||
CommitTransactionHandler handler(this, fPackageFileManager, _result);
|
||||
BTransactionError error = B_TRANSACTION_INTERNAL_ERROR;
|
||||
try {
|
||||
handler.Init(fLatestState, fLatestState == fActiveState,
|
||||
packagesAlreadyAdded, packagesAlreadyRemoved);
|
||||
|
||||
if (message != NULL)
|
||||
handler.HandleRequest(message);
|
||||
else if (transaction != NULL)
|
||||
handler.HandleRequest(*transaction);
|
||||
else
|
||||
handler.HandleRequest();
|
||||
|
||||
_SetLatestState(handler.DetachVolumeState(),
|
||||
handler.IsActiveVolumeState());
|
||||
error = B_TRANSACTION_OK;
|
||||
} catch (Exception& exception) {
|
||||
error = exception.Error();
|
||||
exception.SetOnResult(_result);
|
||||
if (_result.ErrorPackage().IsEmpty()
|
||||
&& handler.CurrentPackage() != NULL) {
|
||||
_result.SetErrorPackage(handler.CurrentPackage()->FileName());
|
||||
}
|
||||
} catch (std::bad_alloc& exception) {
|
||||
error = B_TRANSACTION_NO_MEMORY;
|
||||
}
|
||||
|
||||
_result.SetError(B_TRANSACTION_OK);
|
||||
|
||||
// revert on error
|
||||
if (error != B_TRANSACTION_OK)
|
||||
handler.Revert();
|
||||
}
|
||||
|
||||
@@ -137,8 +137,7 @@ public:
|
||||
const BActivationTransaction& transaction,
|
||||
const PackageSet& packagesAlreadyAdded,
|
||||
const PackageSet& packagesAlreadyRemoved,
|
||||
BDaemonClient::BCommitTransactionResult&
|
||||
_result);
|
||||
BCommitTransactionResult& _result);
|
||||
|
||||
private:
|
||||
struct NodeMonitorEvent;
|
||||
@@ -175,6 +174,12 @@ private:
|
||||
const RelativePath& path, bool create,
|
||||
BDirectory& _directory);
|
||||
|
||||
void _CommitTransaction(BMessage* message,
|
||||
const BActivationTransaction* transaction,
|
||||
const PackageSet& packagesAlreadyAdded,
|
||||
const PackageSet& packagesAlreadyRemoved,
|
||||
BCommitTransactionResult& _result);
|
||||
|
||||
private:
|
||||
BString fPath;
|
||||
PackageFSMountType fMountType;
|
||||
|
||||
Reference in New Issue
Block a user