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:
parent
9ff2343b35
commit
a527b02780
246
src/apps/packageinstaller/PackageInstall.cpp
Normal file
246
src/apps/packageinstaller/PackageInstall.cpp
Normal 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;
|
||||
}
|
||||
|
43
src/apps/packageinstaller/PackageInstall.h
Normal file
43
src/apps/packageinstaller/PackageInstall.h
Normal 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
|
Loading…
Reference in New Issue
Block a user