[haiku-commits] BRANCH HaikuPM-github.package-management - src/kits/package src/bin/pkgman headers/private/package src/servers/package headers/os/package

  • From: HaikuPM-github.package-management <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 20 Apr 2013 21:45:38 +0200 (CEST)

added 10 changesets to branch 'refs/remotes/HaikuPM-github/package-management'
old head: bab6caf3e07bf21d88a5dff857f8ccc7b96e9c0e
new head: eee120f9871cf6f4a1251be97a6a0dc3a4d91a87
overview: https://github.com/haiku/HaikuPM/compare/bab6caf...eee120f

----------------------------------------------------------------------------

e2678ec: pkgman refresh: Include the repository name in error message

2e3f500: package daemon: Fix check in Volume::_PackagesEntryCreated()

a3b1c7b: package daemon: Volume::_WriteActivationFile(): Init _entry

be8f5e0: BPackageInfo: Add CanonicalFileName()
  
  The name of the package file is not part of the package-info.
  CanonicalFileName() constructs the name the file should have (not
  enforced anywhere (yet)).

4ea7f45: BRequest: Change attribute protection from private to protected
  
  Particularly fInitStatus is of interest for derived classes.

e14b247: Add StringChecksumAccessor
  
  A ChecksumAccessor implementation for an already known checksum.

cca3f3b: package daemon: Fix Volume::_WriteActivationFile()
  
  * Wasn't using the toActivate and toDeactivate parameters, but the
    attributes. Thus failed when called from the
    CommitTransactionHandler.
  * Volume::_ChangePackageActivation(): Fix debug output.

69a53ac: Add DownloadFileRequest
  
  Downloads a file and optionally checks its checksum.

6a14307: BDaemonClient: Add support for creating activation transactions
  
  * BActivationTransaction:
    - Remove non-trivial constructor.
    - Remove package list parameters from SetTo().
    - Add AddPackageTo{Dea,A}ctivate().
  * BDaemonClient:
    - Add CreateTransaction(). It creates a transaction directory and
      initializes a BActivationTransaction. Packages to de-/activate have
      to be added afterwards.
    - Add BCommitTransactionResult::FullErrorMessage().

eee120f: pkgman install: Complete basic functionality
  
  Download package files to install from the respective repositories and
  use BDaemonClient to perform the package de-/activation. Still missing
  is the interactive problem solution support.

                                    [ Ingo Weinhold <ingo_weinhold@xxxxxx> ]

----------------------------------------------------------------------------

17 files changed, 491 insertions(+), 64 deletions(-)
headers/build/os/package/DownloadFileRequest.h  |   1 +
headers/os/package/DownloadFileRequest.h        |  41 +++++
headers/os/package/PackageInfo.h                |   2 +
headers/os/package/Request.h                    |   2 +-
headers/private/package/ActivationTransaction.h |  19 +--
headers/private/package/ChecksumAccessors.h     |  11 ++
headers/private/package/DaemonClient.h          |  10 ++
src/bin/pkgman/command_install.cpp              | 161 ++++++++++++++++++--
src/bin/pkgman/command_refresh.cpp              |   6 +-
src/build/libpackage/Jamfile                    |   1 +
src/kits/package/ActivationTransaction.cpp      |  51 +++----
src/kits/package/ChecksumAccessors.cpp          |  31 +++-
src/kits/package/DaemonClient.cpp               | 103 +++++++++++++
src/kits/package/DownloadFileRequest.cpp        |  83 ++++++++++
src/kits/package/Jamfile                        |   1 +
src/kits/package/PackageInfo.cpp                |  11 ++
src/servers/package/Volume.cpp                  |  21 ++-

############################################################################

Commit:      e2678ec0413faa7cdf17c8ae57e4d74a109336cb
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 12:01:32 2013 UTC

pkgman refresh: Include the repository name in error message

----------------------------------------------------------------------------

diff --git a/src/bin/pkgman/command_refresh.cpp 
b/src/bin/pkgman/command_refresh.cpp
index 6023edc..4eddeae 100644
--- a/src/bin/pkgman/command_refresh.cpp
+++ b/src/bin/pkgman/command_refresh.cpp
@@ -101,8 +101,10 @@ RefreshCommand::Execute(int argc, const char* const* argv)
 
                BRefreshRepositoryRequest refreshRequest(context, repoConfig);
                result = refreshRequest.Process();
-               if (result != B_OK)
-                       DIE(result, "request for refreshing repository failed");
+               if (result != B_OK) {
+                       DIE(result, "request for refreshing repository \"%s\" 
failed",
+                               repoName.String());
+               }
        }
 
        return 0;

############################################################################

Commit:      2e3f5000e34297071e630ab70303026715021e31
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 15:15:50 2013 UTC

package daemon: Fix check in Volume::_PackagesEntryCreated()

----------------------------------------------------------------------------

diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp
index 80225c4..0a4ff8d 100644
--- a/src/servers/package/Volume.cpp
+++ b/src/servers/package/Volume.cpp
@@ -1212,10 +1212,16 @@ void
 Volume::_PackagesEntryCreated(const char* name)
 {
 INFORM("Volume::_PackagesEntryCreated(\"%s\")\n", name);
-       // Ignore the event, if we generated it ourselves.
+       // Ignore the event, if the package is already known.
        Package* package = fPackagesByFileName.Lookup(name);
-       if (package->EntryCreatedIgnoreLevel() > 0) {
-               package->DecrementEntryCreatedIgnoreLevel();
+       if (package != NULL) {
+               if (package->EntryCreatedIgnoreLevel() > 0) {
+                       package->DecrementEntryCreatedIgnoreLevel();
+               } else {
+                       WARN("node monitoring created event for already known 
entry "
+                               "\"%s\"\n", name);
+               }
+
                return;
        }
 

############################################################################

Commit:      a3b1c7b96e47e5129c83a5dae6e3b17d1ad06b19
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 15:29:06 2013 UTC

package daemon: Volume::_WriteActivationFile(): Init _entry

----------------------------------------------------------------------------

diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp
index 0a4ff8d..9177c91 100644
--- a/src/servers/package/Volume.cpp
+++ b/src/servers/package/Volume.cpp
@@ -1586,9 +1586,8 @@ Volume::_WriteActivationFile(const RelativePath& 
directoryPath,
                return error;
 
        // write the file
-       BEntry activationFileEntry;
        error = _WriteTextFile(directoryPath, fileName, activationFileContent,
-               activationFileEntry);
+               _entry);
        if (error != B_OK) {
                ERROR("Volume::_WriteActivationFile(): failed to write 
activation "
                        "file \"%s/%s\": %s\n", 
directoryPath.ToString().String(), fileName,

############################################################################

Commit:      be8f5e00f136fdc45f58c4a1c4d802eac9a6e96c
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:10:21 2013 UTC

BPackageInfo: Add CanonicalFileName()

The name of the package file is not part of the package-info.
CanonicalFileName() constructs the name the file should have (not
enforced anywhere (yet)).

----------------------------------------------------------------------------

diff --git a/headers/os/package/PackageInfo.h b/headers/os/package/PackageInfo.h
index 9efaea3..5b0260c 100644
--- a/headers/os/package/PackageInfo.h
+++ b/headers/os/package/PackageInfo.h
@@ -89,6 +89,8 @@ public:
                                                                FreshensList() 
const;
                        const BStringList&      ReplacesList() const;
 
+                       BString                         CanonicalFileName() 
const;
+
                        void                            SetName(const BString& 
name);
                        void                            SetSummary(const 
BString& summary);
                        void                            SetDescription(const 
BString& description);
diff --git a/src/kits/package/PackageInfo.cpp b/src/kits/package/PackageInfo.cpp
index 4d14eee..430bef1 100644
--- a/src/kits/package/PackageInfo.cpp
+++ b/src/kits/package/PackageInfo.cpp
@@ -1590,6 +1590,17 @@ BPackageInfo::ReplacesList() const
 }
 
 
+BString
+BPackageInfo::CanonicalFileName() const
+{
+       if (InitCheck() != B_OK)
+               return BString();
+
+       return BString().SetToFormat("%s-%s-%s.hpkg", fName.String(),
+               fVersion.ToString().String(), 
kArchitectureNames[fArchitecture]);
+}
+
+
 void
 BPackageInfo::SetName(const BString& name)
 {

############################################################################

Commit:      4ea7f45bc5d8ac2936c0c498fd3fc0a45f375f19
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:12:40 2013 UTC

BRequest: Change attribute protection from private to protected

Particularly fInitStatus is of interest for derived classes.

----------------------------------------------------------------------------

diff --git a/headers/os/package/Request.h b/headers/os/package/Request.h
index 5414201..71d1ba8 100644
--- a/headers/os/package/Request.h
+++ b/headers/os/package/Request.h
@@ -39,7 +39,7 @@ protected:
 
                        const BContext&         fContext;
 
-private:
+protected:
                        status_t                        fInitStatus;
                        JobQueue*                       fJobQueue;
 };

############################################################################

Commit:      e14b247176d56b1ddaa4a5efa46ca3c60f33a093
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:16:17 2013 UTC

Add StringChecksumAccessor

A ChecksumAccessor implementation for an already known checksum.

----------------------------------------------------------------------------

diff --git a/headers/private/package/ChecksumAccessors.h 
b/headers/private/package/ChecksumAccessors.h
index 8872cd5..ba95aa5 100644
--- a/headers/private/package/ChecksumAccessors.h
+++ b/headers/private/package/ChecksumAccessors.h
@@ -49,6 +49,17 @@ private:
 };
 
 
+class StringChecksumAccessor : public ChecksumAccessor {
+public:
+                                                               
StringChecksumAccessor(const BString& checksum);
+
+       virtual status_t                        GetChecksum(BString& _checksum) 
const;
+
+private:
+                       BString                         fChecksum;
+};
+
+
 }      // namespace BPrivate
 
 }      // namespace BPackageKit
diff --git a/src/kits/package/ChecksumAccessors.cpp 
b/src/kits/package/ChecksumAccessors.cpp
index 8ec09c9..4eca081 100644
--- a/src/kits/package/ChecksumAccessors.cpp
+++ b/src/kits/package/ChecksumAccessors.cpp
@@ -1,9 +1,10 @@
 /*
- * Copyright 2011, Haiku, Inc. All Rights Reserved.
+ * Copyright 2011-2013, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  *
  * Authors:
  *             Oliver Tappe <zooey@xxxxxxxxxxxxxxx>
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
  */
 
 
@@ -24,11 +25,17 @@ namespace BPrivate {
        (nibble >= 10 ? 'a' + nibble - 10 : '0' + nibble)
 
 
+// #pragma mark - ChecksumAccessor
+
+
 ChecksumAccessor::~ChecksumAccessor()
 {
 }
 
 
+// #pragma mark - ChecksumFileChecksumAccessor
+
+
 ChecksumFileChecksumAccessor::ChecksumFileChecksumAccessor(
        const BEntry& checksumFileEntry)
        :
@@ -62,6 +69,9 @@ ChecksumFileChecksumAccessor::GetChecksum(BString& checksum) 
const
 }
 
 
+// #pragma mark - GeneralFileChecksumAccessor
+
+
 GeneralFileChecksumAccessor::GeneralFileChecksumAccessor(
        const BEntry& fileEntry, bool skipMissingFile)
        :
@@ -127,6 +137,25 @@ GeneralFileChecksumAccessor::GetChecksum(BString& 
checksum) const
 }
 
 
+// #pragma mark - StringChecksumAccessor
+
+
+StringChecksumAccessor::StringChecksumAccessor(const BString& checksum)
+       :
+       fChecksum(checksum)
+{
+}
+
+
+status_t
+StringChecksumAccessor::GetChecksum(BString& _checksum) const
+{
+       _checksum = fChecksum;
+       return B_OK;
+}
+
+
+
 }      // namespace BPrivate
 
 }      // namespace BPackageKit

############################################################################

Commit:      cca3f3b7431cf5e22fa612b171d04933197af3a9
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:18:41 2013 UTC

package daemon: Fix Volume::_WriteActivationFile()

* Wasn't using the toActivate and toDeactivate parameters, but the
  attributes. Thus failed when called from the
  CommitTransactionHandler.
* Volume::_ChangePackageActivation(): Fix debug output.

----------------------------------------------------------------------------

diff --git a/src/servers/package/Volume.cpp b/src/servers/package/Volume.cpp
index 9177c91..8555628 100644
--- a/src/servers/package/Volume.cpp
+++ b/src/servers/package/Volume.cpp
@@ -1580,8 +1580,8 @@ Volume::_WriteActivationFile(const RelativePath& 
directoryPath,
 {
        // create the content
        BString activationFileContent;
-       status_t error = _CreateActivationFileContent(fPackagesToBeActivated,
-               fPackagesToBeDeactivated, activationFileContent);
+       status_t error = _CreateActivationFileContent(toActivate, toDeactivate,
+               activationFileContent);
        if (error != B_OK)
                return error;
 
@@ -1629,7 +1629,7 @@ void
 Volume::_ChangePackageActivation(const PackageSet& packagesToActivate,
        const PackageSet& packagesToDeactivate)
 {
-INFORM("Volume::ProcessPendingPackageActivationChanges(): activating %zu, 
deactivating %zu packages\n",
+INFORM("Volume::_ChangePackageActivation(): activating %zu, deactivating %zu 
packages\n",
 packagesToActivate.size(), packagesToDeactivate.size());
 
        // write the temporary package activation file

############################################################################

Commit:      69a53ac5b488d6562ebf75b98f143000ba70d623
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:22:34 2013 UTC

Add DownloadFileRequest

Downloads a file and optionally checks its checksum.

----------------------------------------------------------------------------

diff --git a/headers/build/os/package/DownloadFileRequest.h 
b/headers/build/os/package/DownloadFileRequest.h
new file mode 100644
index 0000000..2dd8722
--- /dev/null
+++ b/headers/build/os/package/DownloadFileRequest.h
@@ -0,0 +1 @@
+#include <../os/package/DownloadFileRequest.h>
diff --git a/headers/os/package/DownloadFileRequest.h 
b/headers/os/package/DownloadFileRequest.h
new file mode 100644
index 0000000..cf42d53
--- /dev/null
+++ b/headers/os/package/DownloadFileRequest.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef _PACKAGE__DOWNLOAD_FILE_REQUEST_H_
+#define _PACKAGE__DOWNLOAD_FILE_REQUEST_H_
+
+
+#include <Entry.h>
+#include <String.h>
+
+#include <package/Context.h>
+#include <package/Request.h>
+
+
+namespace BPackageKit {
+
+
+class DownloadFileRequest : public BRequest {
+       typedef BRequest                                inherited;
+
+public:
+                                                               
DownloadFileRequest(const BContext& context,
+                                                                       const 
BString& fileURL,
+                                                                       const 
BEntry& targetEntry,
+                                                                       const 
BString& checksum = BString());
+       virtual                                         ~DownloadFileRequest();
+
+       virtual status_t                        CreateInitialJobs();
+
+private:
+                       BString                         fFileURL;
+                       BEntry                          fTargetEntry;
+                       BString                         fChecksum;
+};
+
+
+}      // namespace BPackageKit
+
+
+#endif // _PACKAGE__DOWNLOAD_FILE_REQUEST_H_
diff --git a/src/build/libpackage/Jamfile b/src/build/libpackage/Jamfile
index 1d99a84..d3f8dfc 100644
--- a/src/build/libpackage/Jamfile
+++ b/src/build/libpackage/Jamfile
@@ -73,6 +73,7 @@ BuildPlatformSharedLibrary libpackage_build.so
        BlockBufferCacheNoLock.cpp
        ChecksumAccessors.cpp
        Context.cpp
+       DownloadFileRequest.cpp
        DropRepositoryRequest.cpp
        FetchFileJob.cpp
        InstallationLocationInfo.cpp
diff --git a/src/kits/package/DownloadFileRequest.cpp 
b/src/kits/package/DownloadFileRequest.cpp
new file mode 100644
index 0000000..81b4064
--- /dev/null
+++ b/src/kits/package/DownloadFileRequest.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2013, Haiku, Inc. All Rights Reserved.
+ * Distributed under the terms of the MIT License.
+ *
+ * Authors:
+ *             Ingo Weinhold <ingo_weinhold@xxxxxx>
+ */
+
+
+#include <package/DownloadFileRequest.h>
+
+#include <package/FetchFileJob.h>
+#include <package/ValidateChecksumJob.h>
+
+
+namespace BPackageKit {
+
+
+using namespace BPrivate;
+
+
+DownloadFileRequest::DownloadFileRequest(const BContext& context,
+       const BString& fileURL, const BEntry& targetEntry, const BString& 
checksum)
+       :
+       inherited(context),
+       fFileURL(fileURL),
+       fTargetEntry(targetEntry),
+       fChecksum(checksum)
+{
+       if (fInitStatus == B_OK) {
+               if (fFileURL.IsEmpty())
+                       fInitStatus = B_BAD_VALUE;
+               else
+                       fInitStatus = targetEntry.InitCheck();
+       }
+}
+
+
+DownloadFileRequest::~DownloadFileRequest()
+{
+}
+
+
+status_t
+DownloadFileRequest::CreateInitialJobs()
+{
+       status_t error = InitCheck();
+       if (error != B_OK)
+               return B_NO_INIT;
+
+       // create the download job
+       FetchFileJob* fetchJob = new (std::nothrow) FetchFileJob(fContext,
+               BString("Downloading ") << fFileURL, fFileURL, fTargetEntry);
+       if (fetchJob == NULL)
+               return B_NO_MEMORY;
+
+       if ((error = QueueJob(fetchJob)) != B_OK) {
+               delete fetchJob;
+               return error;
+       }
+
+       // create the checksum validation job
+       if (fChecksum.IsEmpty())
+               return B_OK;
+
+       ValidateChecksumJob* validateJob = new (std::nothrow) 
ValidateChecksumJob(
+               fContext, BString("Validating checksum for ") << fFileURL,
+               new (std::nothrow) StringChecksumAccessor(fChecksum),
+               new (std::nothrow) GeneralFileChecksumAccessor(fTargetEntry, 
true));
+
+       if (validateJob == NULL)
+               return B_NO_MEMORY;
+
+       if ((error = QueueJob(validateJob)) != B_OK) {
+               delete validateJob;
+               return error;
+       }
+
+       return B_OK;
+}
+
+
+}      // namespace BPackageKit
diff --git a/src/kits/package/Jamfile b/src/kits/package/Jamfile
index 6df66e5..525947e 100644
--- a/src/kits/package/Jamfile
+++ b/src/kits/package/Jamfile
@@ -53,6 +53,7 @@ SharedLibrary libpackage.so
        ChecksumAccessors.cpp
        Context.cpp
        DaemonClient.cpp
+       DownloadFileRequest.cpp
        DropRepositoryRequest.cpp
        FetchFileJob.cpp
        InstallationLocationInfo.cpp

############################################################################

Commit:      6a1430716c8746b3a044bb65fb1849e906ae0453
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:24:28 2013 UTC

BDaemonClient: Add support for creating activation transactions

* BActivationTransaction:
  - Remove non-trivial constructor.
  - Remove package list parameters from SetTo().
  - Add AddPackageTo{Dea,A}ctivate().
* BDaemonClient:
  - Add CreateTransaction(). It creates a transaction directory and
    initializes a BActivationTransaction. Packages to de-/activate have
    to be added afterwards.
  - Add BCommitTransactionResult::FullErrorMessage().

----------------------------------------------------------------------------

diff --git a/headers/private/package/ActivationTransaction.h 
b/headers/private/package/ActivationTransaction.h
index 11b5094..76e311e 100644
--- a/headers/private/package/ActivationTransaction.h
+++ b/headers/private/package/ActivationTransaction.h
@@ -20,20 +20,13 @@ namespace BPrivate {
 class BActivationTransaction {
 public:
                                                                
BActivationTransaction();
-                                                               
BActivationTransaction(
-                                                                       
BPackageInstallationLocation location,
-                                                                       int64 
changeCount,
-                                                                       const 
BString& directoryName,
-                                                                       const 
BStringList& packagesToActivate,
-                                                                       const 
BStringList& packagesToDeactivate);
                                                                
~BActivationTransaction();
 
-                       status_t                        InitCheck() const;
                        status_t                        
SetTo(BPackageInstallationLocation location,
                                                                        int64 
changeCount,
-                                                                       const 
BString& directoryName,
-                                                                       const 
BStringList& packagesToActivate,
-                                                                       const 
BStringList& packagesToDeactivate);
+                                                                       const 
BString& directoryName);
+
+                       status_t                        InitCheck() const;
 
                        BPackageInstallationLocation Location() const;
                        void                            SetLocation(
@@ -47,12 +40,14 @@ public:
                                                                        const 
BString& directoryName);
 
                        const BStringList&      PackagesToActivate() const;
-                       void                            SetPackagesToActivate(
+                       bool                            SetPackagesToActivate(
                                                                        const 
BStringList& packages);
+                       bool                            
AddPackageToActivate(const BString& package);
 
                        const BStringList&      PackagesToDeactivate() const;
-                       void                            SetPackagesToDeactivate(
+                       bool                            SetPackagesToDeactivate(
                                                                        const 
BStringList& packages);
+                       bool                            
AddPackageToDeactivate(const BString& package);
 
 private:
                        BPackageInstallationLocation fLocation;
diff --git a/headers/private/package/DaemonClient.h 
b/headers/private/package/DaemonClient.h
index bcad84a..339f04b 100644
--- a/headers/private/package/DaemonClient.h
+++ b/headers/private/package/DaemonClient.h
@@ -16,6 +16,9 @@
 #include <package/DaemonDefs.h>
 
 
+class BDirectory;
+
+
 namespace BPackageKit {
 
 
@@ -44,6 +47,11 @@ public:
                                                                        const 
BActivationTransaction& transaction,
                                                                        
BCommitTransactionResult& _result);
 
+                       status_t                        CreateTransaction(
+                                                                       
BPackageInstallationLocation location,
+                                                                       
BActivationTransaction& _transaction,
+                                                                       
BDirectory& _transactionDirectory);
+
 private:
                        status_t                        _InitMessenger();
                        status_t                        
_ExtractPackageInfoSet(const BMessage& message,
@@ -81,6 +89,8 @@ public:
                        const BString&          ErrorPackage() const;
                                                                        // may 
be empty, even on error
 
+                       BString                         FullErrorMessage() 
const;
+
                        const BString&          OldStateDirectory() const;
 
 private:
diff --git a/src/kits/package/ActivationTransaction.cpp 
b/src/kits/package/ActivationTransaction.cpp
index 838b071..813ecf3 100644
--- a/src/kits/package/ActivationTransaction.cpp
+++ b/src/kits/package/ActivationTransaction.cpp
@@ -25,20 +25,6 @@ BActivationTransaction::BActivationTransaction()
 }
 
 
-BActivationTransaction::BActivationTransaction(
-       BPackageInstallationLocation location, int64 changeCount,
-       const BString& directoryName, const BStringList& packagesToActivate,
-       const BStringList& packagesToDeactivate)
-       :
-       fLocation(location),
-       fChangeCount(changeCount),
-       fTransactionDirectoryName(directoryName),
-       fPackagesToActivate(packagesToActivate),
-       fPackagesToDeactivate(packagesToDeactivate)
-{
-}
-
-
 BActivationTransaction::~BActivationTransaction()
 {
 }
@@ -57,27 +43,18 @@ BActivationTransaction::InitCheck() const
 
 status_t
 BActivationTransaction::SetTo(BPackageInstallationLocation location,
-       int64 changeCount, const BString& directoryName,
-       const BStringList& packagesToActivate,
-       const BStringList& packagesToDeactivate)
+       int64 changeCount, const BString& directoryName)
 {
        if (location < 0 || location >= 
B_PACKAGE_INSTALLATION_LOCATION_ENUM_COUNT
-               || directoryName.IsEmpty()
-               || (packagesToActivate.IsEmpty() && 
packagesToDeactivate.IsEmpty())) {
+               || directoryName.IsEmpty()) {
                return B_BAD_VALUE;
        }
 
        fLocation = location;
        fChangeCount = changeCount;
        fTransactionDirectoryName = directoryName;
-       fPackagesToActivate = packagesToActivate;
-       fPackagesToDeactivate = packagesToDeactivate;
-
-       if (fPackagesToActivate.CountStrings() != 
packagesToActivate.CountStrings()
-               || fPackagesToDeactivate.CountStrings()
-                       != packagesToDeactivate.CountStrings()) {
-               return B_NO_MEMORY;
-       }
+       fPackagesToActivate.MakeEmpty();
+       fPackagesToDeactivate.MakeEmpty();
 
        return B_OK;
 }
@@ -133,10 +110,18 @@ BActivationTransaction::PackagesToActivate() const
 }
 
 
-void
+bool
 BActivationTransaction::SetPackagesToActivate(const BStringList& packages)
 {
        fPackagesToActivate = packages;
+       return fPackagesToActivate.CountStrings() == packages.CountStrings();
+}
+
+
+bool
+BActivationTransaction::AddPackageToActivate(const BString& package)
+{
+       return fPackagesToActivate.Add(package);
 }
 
 
@@ -147,10 +132,18 @@ BActivationTransaction::PackagesToDeactivate() const
 }
 
 
-void
+bool
 BActivationTransaction::SetPackagesToDeactivate(const BStringList& packages)
 {
        fPackagesToDeactivate = packages;
+       return fPackagesToDeactivate.CountStrings() == packages.CountStrings();
+}
+
+
+bool
+BActivationTransaction::AddPackageToDeactivate(const BString& package)
+{
+       return fPackagesToDeactivate.Add(package);
 }
 
 
diff --git a/src/kits/package/DaemonClient.cpp 
b/src/kits/package/DaemonClient.cpp
index 8d2c1bf..f3446dc 100644
--- a/src/kits/package/DaemonClient.cpp
+++ b/src/kits/package/DaemonClient.cpp
@@ -9,10 +9,15 @@
 
 #include <package/DaemonClient.h>
 
+#include <time.h>
+
+#include <Directory.h>
+#include <Entry.h>
 #include <package/InstallationLocationInfo.h>
 #include <package/PackageInfo.h>
 
 #include <package/ActivationTransaction.h>
+#include <package/PackagesDirectoryDefs.h>
 
 
 namespace BPackageKit {
@@ -104,6 +109,60 @@ BDaemonClient::CommitTransaction(const 
BActivationTransaction& transaction,
 
 
 status_t
+BDaemonClient::CreateTransaction(BPackageInstallationLocation location,
+       BActivationTransaction& _transaction, BDirectory& _transactionDirectory)
+{
+       // get an info for the location
+       BInstallationLocationInfo info;
+       status_t error = GetInstallationLocationInfo(location, info);
+       if (error != B_OK)
+               return error;
+
+       // open admin directory
+       entry_ref entryRef;
+       entryRef.device = info.PackagesDirectoryRef().device;
+       entryRef.directory = info.PackagesDirectoryRef().node;
+       error = entryRef.set_name(PACKAGES_DIRECTORY_ADMIN_DIRECTORY);
+       if (error != B_OK)
+               return error;
+       
+       BDirectory adminDirectory;
+       error = adminDirectory.SetTo(&entryRef);
+       if (error != B_OK)
+               return error;
+
+       // create a transaction directory
+       int uniqueId = 1;
+       BString directoryName;
+       for (;; uniqueId++) {
+               directoryName.SetToFormat("transaction-%d", uniqueId);
+               if (directoryName.IsEmpty())
+                       return B_NO_MEMORY;
+
+               error = adminDirectory.CreateDirectory(directoryName,
+                       &_transactionDirectory);
+               if (error == B_OK)
+                       break;
+               if (error != B_FILE_EXISTS)
+                       return error;
+       }
+
+       // init the transaction
+       error = _transaction.SetTo(location, info.ChangeCount(), directoryName);
+       if (error != B_OK) {
+               BEntry entry;
+               _transactionDirectory.GetEntry(&entry);
+               _transactionDirectory.Unset();
+               if (entry.InitCheck() == B_OK)
+                       entry.Remove();
+               return error;
+       }
+
+       return B_OK;
+}
+
+
+status_t
 BDaemonClient::_InitMessenger()
 {
        if (fDaemonMessenger.IsValid())
@@ -273,6 +332,50 @@ BDaemonClient::BCommitTransactionResult::ErrorPackage() 
const
 }
 
 
+BString
+BDaemonClient::BCommitTransactionResult::FullErrorMessage() const
+{
+       if (fError == 0)
+               return "no error";
+
+       const char* errorString;
+       if (fError > 0) {
+               switch ((BDaemonError)fError) {
+                       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
 {

############################################################################

Commit:      eee120f9871cf6f4a1251be97a6a0dc3a4d91a87
Author:      Ingo Weinhold <ingo_weinhold@xxxxxx>
Date:        Sat Apr 20 19:31:32 2013 UTC

pkgman install: Complete basic functionality

Download package files to install from the respective repositories and
use BDaemonClient to perform the package de-/activation. Still missing
is the interactive problem solution support.

----------------------------------------------------------------------------

diff --git a/src/bin/pkgman/command_install.cpp 
b/src/bin/pkgman/command_install.cpp
index c62a6ff..743f19e 100644
--- a/src/bin/pkgman/command_install.cpp
+++ b/src/bin/pkgman/command_install.cpp
@@ -11,8 +11,9 @@
 #include <getopt.h>
 #include <stdio.h>
 #include <stdlib.h>
-//#include <sys/stat.h>
 
+#include <Directory.h>
+#include <package/DownloadFileRequest.h>
 #include <package/PackageRoster.h>
 #include <package/RepositoryConfig.h>
 #include <package/solver/SolverPackageSpecifier.h>
@@ -22,8 +23,12 @@
 #include <package/solver/SolverResult.h>
 
 #include <AutoDeleter.h>
+#include <package/ActivationTransaction.h>
+#include <package/DaemonClient.h>
 
 #include "Command.h"
+#include "DecisionProvider.h"
+#include "JobStateListener.h"
 #include "pkgman.h"
 #include "RepositoryBuilder.h"
 
@@ -32,6 +37,7 @@
 
 
 using namespace BPackageKit;
+using namespace BPackageKit::BPrivate;
 
 
 static const char* const kShortUsage =
@@ -52,6 +58,28 @@ static const char* const kLongUsage =
 DEFINE_COMMAND(InstallCommand, "install", kShortUsage, kLongUsage)
 
 
+struct Repository : public BSolverRepository {
+       Repository()
+               :
+               BSolverRepository()
+       {
+       }
+
+       status_t Init(BPackageRoster& roster, const char* name)
+       {
+               return roster.GetRepositoryConfig(name, &fConfig);
+       }
+
+       const BRepositoryConfig& Config() const
+       {
+               return fConfig;
+       }
+
+private:
+       BRepositoryConfig       fConfig;
+};
+
+
 int
 InstallCommand::Execute(int argc, const char* const* argv)
 {
@@ -121,16 +149,25 @@ InstallCommand::Execute(int argc, const char* const* argv)
                .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_COMMON, "common")
                .AddToSolver(solver, !installInHome);
 
+       BObjectList<BSolverRepository> installedRepositories(10);
+       if (!installedRepositories.AddItem(&systemRepository)
+               || !installedRepositories.AddItem(&commonRepository)) {
+               DIE(B_NO_MEMORY, "failed to add installed repositories to 
list");
+       }
+
        BSolverRepository homeRepository;
        if (installInHome) {
                commonRepository.SetPriority(-2);
                RepositoryBuilder(homeRepository, "home")
                        .AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME, 
"home")
                        .AddToSolver(solver, true);
+
+               if (!installedRepositories.AddItem(&homeRepository))
+                       DIE(B_NO_MEMORY, "failed to add home repository to 
list");
        }
 
        // other repositories
-       BObjectList<BSolverRepository> otherRepositories(10, true);
+       BObjectList<Repository> otherRepositories(10, true);
        BPackageRoster roster;
        BStringList repositoryNames;
        error = roster.GetRepositoryNames(repositoryNames);
@@ -139,20 +176,20 @@ InstallCommand::Execute(int argc, const char* const* argv)
 
        int32 repositoryNameCount = repositoryNames.CountStrings();
        for (int32 i = 0; i < repositoryNameCount; i++) {
+               Repository* repository = new(std::nothrow) Repository;
+               if (repository == NULL || 
!otherRepositories.AddItem(repository))
+                       DIE(B_NO_MEMORY, "out of memory");
+
                const BString& name = repositoryNames.StringAt(i);
-               BRepositoryConfig config;
-               error = roster.GetRepositoryConfig(name, &config);
+               error = repository->Init(roster, name);
                if (error != B_OK) {
                        WARN(error, "failed to get config for repository 
\"%s\". Skipping.",
                                name.String());
+                       otherRepositories.RemoveItem(repository, true);
                        continue;
                }
 
-               BSolverRepository* repository = new(std::nothrow) 
BSolverRepository;
-               if (repository == NULL || 
!otherRepositories.AddItem(repository))
-                       DIE(B_NO_MEMORY, "out of memory");
-
-               RepositoryBuilder(*repository, config)
+               RepositoryBuilder(*repository, repository->Config())
                        .AddToSolver(solver, false);
        }
 
@@ -205,22 +242,124 @@ exit(1);
        if (error != B_OK)
                DIE(error, "failed to compute packages to install");
 
-       printf("transaction:\n");
+       printf("The following changes will be made:\n");
        for (int32 i = 0; const BSolverResultElement* element = 
result.ElementAt(i);
                        i++) {
                BSolverPackage* package = element->Package();
+
                switch (element->Type()) {
                        case BSolverResultElement::B_TYPE_INSTALL:
+                               if 
(installedRepositories.HasItem(package->Repository()))
+                                       continue;
+
                                printf("  install package %s from repository 
%s\n",
-                                       package->VersionedName().String(),
+                                       
package->Info().CanonicalFileName().String(),
                                        package->Repository()->Name().String());
                                break;
+
                        case BSolverResultElement::B_TYPE_UNINSTALL:
                                printf("  uninstall package %s\n",
                                        package->VersionedName().String());
                                break;
                }
        }
+// TODO: Print file/download sizes. Unfortunately our package infos don't
+// contain the file size. Which is probably correct. The file size (and 
possibly
+// other information) should, however, be provided by the repository cache in
+// some way. Extend BPackageInfo? Create a BPackageFileInfo?
+
+       DecisionProvider decisionProvider;
+       if (!decisionProvider.YesNoDecisionNeeded(BString(), "Continue?", "y", 
"n",
+                       "y")) {
+               return 1;
+       }
+
+       // create an activation transaction
+       BDaemonClient daemonClient;
+       BPackageInstallationLocation location = installInHome
+               ? B_PACKAGE_INSTALLATION_LOCATION_HOME
+               : B_PACKAGE_INSTALLATION_LOCATION_COMMON;
+       BActivationTransaction transaction;
+       BDirectory transactionDirectory;
+       error = daemonClient.CreateTransaction(location, transaction,
+               transactionDirectory);
+       if (error != B_OK)
+               DIE(error, "failed to create transaction");
+
+       // download the new packages and prepare the transaction
+       JobStateListener listener;
+       BContext context(decisionProvider, listener);
+
+       for (int32 i = 0; const BSolverResultElement* element = 
result.ElementAt(i);
+                       i++) {
+               BSolverPackage* package = element->Package();
+
+               switch (element->Type()) {
+                       case BSolverResultElement::B_TYPE_INSTALL:
+                       {
+                               if 
(installedRepositories.HasItem(package->Repository()))
+                                       continue;
+
+                               // get package URL and target entry
+                               Repository* repository
+                                       = 
static_cast<Repository*>(package->Repository());
+                               BString url = repository->Config().BaseURL();
+                               BString 
fileName(package->Info().CanonicalFileName());
+                               if (fileName.IsEmpty())
+                                       DIE(B_NO_MEMORY, "out of memory");
+                               url << '/' << fileName;
+
+                               BEntry entry;
+                               error = entry.SetTo(&transactionDirectory, 
fileName);
+                               if (error != B_OK)
+                                       DIE(error, "failed to create package 
entry");
+
+                               // download the package
+                               DownloadFileRequest downloadRequest(context, 
url, entry,
+                                       package->Info().Checksum());
+                               error = downloadRequest.Process();
+                               if (error != B_OK)
+                                       DIE(error, "failed to download 
package");
+
+                               // add package to transaction
+                               if (!transaction.AddPackageToActivate(
+                                               
package->Info().CanonicalFileName())) {
+                                       DIE(B_NO_MEMORY,
+                                               "failed to add package to 
activate to transaction");
+                               }
+                               break;
+                       }
+
+                       case BSolverResultElement::B_TYPE_UNINSTALL:
+                               // add package to transaction
+                               if (!transaction.AddPackageToDeactivate(
+                                               
package->Info().CanonicalFileName())) {
+                                       DIE(B_NO_MEMORY,
+                                               "failed to add package to 
deactivate to transaction");
+                               }
+                               break;
+               }
+       }
+
+       // commit the transaction
+       BDaemonClient::BCommitTransactionResult transactionResult;
+       error = daemonClient.CommitTransaction(transaction, transactionResult);
+       if (error != B_OK) {
+               fprintf(stderr, "*** failed to commit transaction: %s\n",
+                       transactionResult.FullErrorMessage().String());
+               exit(1);
+       }
+
+       printf("Installation done. Old activation state backed up in \"%s\"\n",
+               transactionResult.OldStateDirectory().String());
+
+       printf("Cleaning up ...\n");
+       BEntry transactionDirectoryEntry;
+       if ((error = transactionDirectory.GetEntry(&transactionDirectoryEntry))
+                       != B_OK
+               || (error = transactionDirectoryEntry.Remove()) != B_OK) {
+               WARN(error, "failed to remove transaction directory");
+       }
 
        return 0;
 }


Other related posts:

  • » [haiku-commits] BRANCH HaikuPM-github.package-management - src/kits/package src/bin/pkgman headers/private/package src/servers/package headers/os/package - HaikuPM-github . package-management