forgot these files as part of the previous commit

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36021 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval 2010-04-01 19:55:54 +00:00
parent 9ff2343b35
commit a527b02780
2 changed files with 289 additions and 0 deletions

View File

@ -0,0 +1,246 @@
/*
* Copyright (c) 2010, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#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;
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2010, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
*/
#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