Author: korli Date: 2010-04-01 21:55:54 +0200 (Thu, 01 Apr 2010) New Revision: 36021 Changeset: http://dev.haiku-os.org/changeset/36021/haiku Added: haiku/trunk/src/apps/packageinstaller/PackageInstall.cpp haiku/trunk/src/apps/packageinstaller/PackageInstall.h Log: forgot these files as part of the previous commit Added: haiku/trunk/src/apps/packageinstaller/PackageInstall.cpp =================================================================== --- haiku/trunk/src/apps/packageinstaller/PackageInstall.cpp (rev 0) +++ haiku/trunk/src/apps/packageinstaller/PackageInstall.cpp 2010-04-01 19:55:54 UTC (rev 36021) @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2010, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Author: + * Łukasz 'Sil2100' Zemczak <sil2100@xxxxxxxxxxxxx> + */ + + +#include "PackageInstall.h" + +#include "InstalledPackageInfo.h" +#include "PackageItem.h" +#include "PackageView.h" + +#include <Alert.h> +#include <stdio.h> + + +// Macro reserved for later localization +#define T(x) x + +static int32 install_function(void *data) +{ + // TODO: Inform if already one thread is running + PackageInstall *install = static_cast<PackageInstall *>(data); + if (data == NULL) + return -1; + + install->Install(); + return 0; +} + + +PackageInstall::PackageInstall(PackageView *parent) + : fParent(parent), + fThreadId(-1) +{ +} + + +PackageInstall::~PackageInstall() +{ +} + + +status_t +PackageInstall::Start() +{ + status_t ret = B_OK; + + fIdLocker.Lock(); + if (fThreadId > -1) { + ret = B_BUSY; + } else { + fThreadId = spawn_thread(install_function, "install_package", B_NORMAL_PRIORITY, + static_cast<void *>(this)); + resume_thread(fThreadId); + } + fIdLocker.Unlock(); + + return ret; +} + + +void +PackageInstall::Stop() +{ + fIdLocker.Lock(); + if (fThreadId > -1) { + kill_thread(fThreadId); + fThreadId = -1; + } + fIdLocker.Unlock(); + + fCurrentScriptLocker.Lock(); + if (fCurrentScript != NULL) { + thread_id id = fCurrentScript->GetThreadId(); + if (id > -1) { + fCurrentScript->SetThreadId(-1); + kill_thread(id); + } + fCurrentScript = NULL; + } + fCurrentScriptLocker.Unlock(); +} + + +void +PackageInstall::Install() +{ + // A message sending wrapper around _Install() + uint32 msg = _Install(); + if (fParent && fParent->Looper()) + fParent->Looper()->PostMessage(new BMessage(msg), fParent); +} + + +uint32 +PackageInstall::_Install() +{ + PackageInfo *info = fParent->GetPackageInfo(); + pkg_profile *type = static_cast<pkg_profile *>(info->GetProfile(fParent->GetCurrentType())); + uint32 n = type->items.CountItems(), m = info->GetScriptCount(); + + PackageStatus *progress = fParent->GetStatusWindow(); + progress->Reset(n + m + 5); + + progress->StageStep(1, T("Preparing package")); + + InstalledPackageInfo packageInfo(info->GetName(), info->GetVersion()); + + status_t err = packageInfo.InitCheck(); + if (err == B_OK) { + // The package is already installed, inform the user + BAlert *reinstall = new BAlert("reinstall", + T("The given package seems to be already installed on your system. " + "Would you like to uninstall the existing one and continue the " + "installation?"), T("Continue"), T("Abort")); + + if (reinstall->Go() == 0) { + // Uninstall the package + err = packageInfo.Uninstall(); + if (err != B_OK) { + fprintf(stderr, "Error on uninstall\n"); + return P_MSG_I_ERROR; + } + + err = packageInfo.SetTo(info->GetName(), info->GetVersion(), true); + if (err != B_OK) { + fprintf(stderr, "Error on SetTo\n"); + return P_MSG_I_ERROR; + } + } else { + // Abort the installation + return P_MSG_I_ABORT; + } + } else if (err == B_ENTRY_NOT_FOUND) { + err = packageInfo.SetTo(info->GetName(), info->GetVersion(), true); + if (err != B_OK) { + fprintf(stderr, "Error on SetTo\n"); + return P_MSG_I_ERROR; + } + } else if (progress->Stopped()) { + return P_MSG_I_ABORT; + } else { + fprintf(stderr, "returning on error\n"); + return P_MSG_I_ERROR; + } + + progress->StageStep(1, T("Installing files and folders")); + + // Install files and directories + PackageItem *iter; + ItemState state; + uint32 i; + int32 choice; + BString label; + + packageInfo.SetName(info->GetName()); + // TODO: Here's a small problem, since right now it's not quite sure + // which description is really used as such. The one displayed on + // the installer is mostly package installation description, but + // most people use it for describing the application in more detail + // then in the short description. + // For now, we'll use the short description if possible. + BString description = info->GetShortDescription(); + if (description.Length() <= 0) + description = info->GetDescription(); + packageInfo.SetDescription(description.String()); + packageInfo.SetSpaceNeeded(type->space_needed); + + fItemExistsPolicy = P_EXISTS_NONE; + + const char *installPath = fParent->GetCurrentPath()->Path(); + for (i = 0; i < n; i++) { + state.Reset(fItemExistsPolicy); // Reset the current item state + iter = static_cast<PackageItem *>(type->items.ItemAt(i)); + + err = iter->DoInstall(installPath, &state); + if (err == B_FILE_EXISTS) { + // Writing to path failed because path already exists - ask the user + // what to do and retry the writing process + choice = fParent->ItemExists(*iter, state.destination, fItemExistsPolicy); + if (choice != P_EXISTS_ABORT) { + state.policy = choice; + err = iter->DoInstall(installPath, &state); + } + } + + if (err != B_OK) { + fprintf(stderr, "Error while writing path\n"); + return P_MSG_I_ERROR; + } + + if (progress->Stopped()) + return P_MSG_I_ABORT; + label = ""; + label << (uint32)(i + 1) << " of " << (uint32)n; + progress->StageStep(1, NULL, label.String()); + + packageInfo.AddItem(state.destination.Path()); + } + + progress->StageStep(1, T("Running post-installation scripts"), ""); + + PackageScript *scr; + status_t status; + // Run all scripts + for (i = 0; i < m; i++) { + scr = info->GetScript(i); + + fCurrentScriptLocker.Lock(); + fCurrentScript = scr; + + if (scr->DoInstall() != B_OK) { + fprintf(stderr, "Error while running script\n"); + return P_MSG_I_ERROR; + } + fCurrentScriptLocker.Unlock(); + + wait_for_thread(scr->GetThreadId(), &status); + fCurrentScriptLocker.Lock(); + scr->SetThreadId(-1); + fCurrentScript = NULL; + fCurrentScriptLocker.Unlock(); + + if (progress->Stopped()) + return P_MSG_I_ABORT; + label = ""; + label << (uint32)(i + 1) << " of " << (uint32)m; + progress->StageStep(1, NULL, label.String()); + } + + progress->StageStep(1, T("Finishing installation"), ""); + + err = packageInfo.Save(); + if (err != B_OK) + return P_MSG_I_ERROR; + + progress->StageStep(1, T("Done")); + + // Inform our parent that we finished + return P_MSG_I_FINISHED; +} + Added: haiku/trunk/src/apps/packageinstaller/PackageInstall.h =================================================================== --- haiku/trunk/src/apps/packageinstaller/PackageInstall.h (rev 0) +++ haiku/trunk/src/apps/packageinstaller/PackageInstall.h 2010-04-01 19:55:54 UTC (rev 36021) @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, Haiku, Inc. + * Distributed under the terms of the MIT license. + * + * Author: + * Łukasz 'Sil2100' Zemczak <sil2100@xxxxxxxxxxxxx> + */ +#ifndef PACKAGE_INSTALL_H +#define PACKAGE_INSTALL_H + +#include <Locker.h> + +class PackageView; +class PackageScript; + +enum { + P_MSG_I_FINISHED = 'pifi', + P_MSG_I_ABORT = 'piab', + P_MSG_I_ERROR = 'pier' +}; + +class PackageInstall { + public: + PackageInstall(PackageView *parent); + ~PackageInstall(); + + status_t Start(); + void Stop(); + void Install(); + + private: + uint32 _Install(); + + PackageView *fParent; + thread_id fThreadId; + BLocker fIdLocker; + + PackageScript *fCurrentScript; + BLocker fCurrentScriptLocker; // XXX: will we need this? + int32 fItemExistsPolicy; +}; + +#endif