root/src/servers/package/CommitTransactionHandler.h
/*
 * Copyright 2013-2014, Haiku, Inc. All Rights Reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *              Ingo Weinhold <ingo_weinhold@gmx.de>
 */
#ifndef COMMIT_TRANSACTION_HANDLER_H
#define COMMIT_TRANSACTION_HANDLER_H


#include <set>
#include <string>

#include <Directory.h>

#include "FSTransaction.h"
#include "FSUtils.h"
#include "Volume.h"


typedef std::set<std::string> StringSet;


namespace BPackageKit {
        class BCommitTransactionResult;
}

using BPackageKit::BCommitTransactionResult;


class CommitTransactionHandler {
public:
                                                                CommitTransactionHandler(Volume* volume,
                                                                        PackageFileManager* packageFileManager,
                                                                        BCommitTransactionResult& result);
                                                                ~CommitTransactionHandler();

                        void                            Init(VolumeState* volumeState,
                                                                        bool isActiveVolumeState,
                                                                        const PackageSet& packagesAlreadyAdded,
                                                                        const PackageSet& packagesAlreadyRemoved);

                        void                            HandleRequest(BMessage* request);
                        void                            HandleRequest(
                                                                        const BActivationTransaction& transaction);
                        void                            HandleRequest();
                                                                        // uses packagesAlreadyAdded and
                                                                        // packagesAlreadyRemoved from Init()

                        void                            Revert();

                        const BString&          OldStateDirectoryName() const
                                                                        { return fOldStateDirectoryName; }

                        Package*                        CurrentPackage() const
                                                                        { return fCurrentPackage; }

                        VolumeState*            DetachVolumeState();
                        bool                            IsActiveVolumeState() const
                                                                        { return fVolumeStateIsActive; }

private:
                        typedef BObjectList<Package> PackageList;
                        typedef FSUtils::RelativePath RelativePath;

                        struct TransactionIssueBuilder;

private:
                        void                            _GetPackagesToDeactivate(
                                                                        const BActivationTransaction& transaction);
                        void                            _ReadPackagesToActivate(
                                                                        const BActivationTransaction& transaction);
                        void                            _ApplyChanges();
                        void                            _CreateOldStateDirectory();
                        void                            _RemovePackagesToDeactivate();
                        void                            _AddPackagesToActivate();

                        void                            _PreparePackageToActivate(Package* package);
                        void                            _AddGroup(Package* package,
                                                                        const BString& groupName);
                        void                            _AddUser(Package* package, const BUser& user);
                        void                            _AddGlobalWritableFiles(Package* package);
                        void                            _AddGlobalWritableFile(Package* package,
                                                                        const BGlobalWritableFileInfo& file,
                                                                        const BDirectory& rootDirectory,
                                                                        const BDirectory& extractedFilesDirectory);
                        void                            _AddGlobalWritableFileRecurse(Package* package,
                                                                        const BDirectory& sourceDirectory,
                                                                        FSUtils::Path& relativeSourcePath,
                                                                        const BDirectory& targetDirectory,
                                                                        const char* targetName,
                                                                        BWritableFileUpdateType updateType);

                        void                            _RevertAddPackagesToActivate();
                        void                            _RevertRemovePackagesToDeactivate();
                        void                            _RevertUserGroupChanges();

                        void                            _RunPostInstallScripts();
                        void                            _RunPreUninstallScripts();
                        void                            _RunPostOrPreScript(Package* package,
                                                                        const BString& script,
                                                                        bool postNotPre);

                        void                            _QueuePostInstallScripts();

                        void                            _ExtractPackageContent(Package* package,
                                                                        const BStringList& contentPaths,
                                                                        BDirectory& targetDirectory,
                                                                        BDirectory& _extractedFilesDirectory);

                        status_t                        _OpenPackagesSubDirectory(
                                                                        const RelativePath& path, bool create,
                                                                        BDirectory& _directory);
                        status_t                        _OpenPackagesFile(
                                                                        const RelativePath& subDirectoryPath,
                                                                        const char* fileName, uint32 openMode,
                                                                        BFile& _file, BEntry* _entry = NULL);

                        void                            _WriteActivationFile(
                                                                        const RelativePath& directoryPath,
                                                                        const char* fileName,
                                                                        const PackageSet& toActivate,
                                                                        const PackageSet& toDeactivate,
                                                                        BEntry& _entry);
                        void                            _CreateActivationFileContent(
                                                                        const PackageSet& toActivate,
                                                                        const PackageSet& toDeactivate,
                                                                        BString& _content);
                        status_t                        _WriteTextFile(
                                                                        const RelativePath& directoryPath,
                                                                        const char* fileName,
                                                                        const BString& content, BEntry& _entry);
                        void                            _ChangePackageActivation(
                                                                        const PackageSet& packagesToActivate,
                                                                        const PackageSet& packagesToDeactivate);
                                                                        // throws Exception
                        void                            _ChangePackageActivationIOCtl(
                                                                        const PackageSet& packagesToActivate,
                                                                        const PackageSet& packagesToDeactivate);
                                                                        // throws Exception
                        void                            _PrepareFirstBootPackages();
                        void                            _FillInActivationChangeItem(
                                                                        PackageFSActivationChangeItem* item,
                                                                        PackageFSActivationChangeType type,
                                                                        Package* package, char*& nameBuffer);

                        bool                            _IsSystemPackage(Package* package);

                        void                            _AddIssue(
                                                                        const TransactionIssueBuilder& builder);

        static  BString                         _GetPath(const FSUtils::Entry& entry,
                                                                        const BString& fallback);

        static  void                            _TagPackageEntriesRecursively(
                                                                        BDirectory& directory, const BString& value,
                                                                        bool nonDirectoriesOnly);

        static  status_t                        _AssertEntriesAreEqual(const BEntry& entry,
                                                                        const BDirectory* directory);

private:
                        Volume*                         fVolume;
                        PackageFileManager*     fPackageFileManager;
                        VolumeState*            fVolumeState;
                        bool                            fVolumeStateIsActive;
                        PackageList                     fPackagesToActivate;
                        PackageSet                      fPackagesToDeactivate;
                        PackageSet                      fAddedPackages;
                        PackageSet                      fRemovedPackages;
                        PackageSet                      fPackagesAlreadyAdded;
                        PackageSet                      fPackagesAlreadyRemoved;
                        BDirectory                      fOldStateDirectory;
                        node_ref                        fOldStateDirectoryRef;
                        BString                         fOldStateDirectoryName;
                        node_ref                        fTransactionDirectoryRef;
                        bool                            fFirstBootProcessing;
                        BDirectory                      fWritableFilesDirectory;
                        StringSet                       fAddedGroups;
                        StringSet                       fAddedUsers;
                        FSTransaction           fFSTransaction;
                        BCommitTransactionResult& fResult;
                        Package*                        fCurrentPackage;
};


#endif  // COMMIT_TRANSACTION_HANDLER_H