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.
This commit is contained in:
parent
6a1430716c
commit
eee120f987
@ -11,8 +11,9 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
//#include <sys/stat.h>
|
|
||||||
|
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <package/DownloadFileRequest.h>
|
||||||
#include <package/PackageRoster.h>
|
#include <package/PackageRoster.h>
|
||||||
#include <package/RepositoryConfig.h>
|
#include <package/RepositoryConfig.h>
|
||||||
#include <package/solver/SolverPackageSpecifier.h>
|
#include <package/solver/SolverPackageSpecifier.h>
|
||||||
@ -22,8 +23,12 @@
|
|||||||
#include <package/solver/SolverResult.h>
|
#include <package/solver/SolverResult.h>
|
||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
#include <package/ActivationTransaction.h>
|
||||||
|
#include <package/DaemonClient.h>
|
||||||
|
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
|
#include "DecisionProvider.h"
|
||||||
|
#include "JobStateListener.h"
|
||||||
#include "pkgman.h"
|
#include "pkgman.h"
|
||||||
#include "RepositoryBuilder.h"
|
#include "RepositoryBuilder.h"
|
||||||
|
|
||||||
@ -32,6 +37,7 @@
|
|||||||
|
|
||||||
|
|
||||||
using namespace BPackageKit;
|
using namespace BPackageKit;
|
||||||
|
using namespace BPackageKit::BPrivate;
|
||||||
|
|
||||||
|
|
||||||
static const char* const kShortUsage =
|
static const char* const kShortUsage =
|
||||||
@ -52,6 +58,28 @@ static const char* const kLongUsage =
|
|||||||
DEFINE_COMMAND(InstallCommand, "install", kShortUsage, 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
|
int
|
||||||
InstallCommand::Execute(int argc, const char* const* argv)
|
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")
|
.AddPackages(B_PACKAGE_INSTALLATION_LOCATION_COMMON, "common")
|
||||||
.AddToSolver(solver, !installInHome);
|
.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;
|
BSolverRepository homeRepository;
|
||||||
if (installInHome) {
|
if (installInHome) {
|
||||||
commonRepository.SetPriority(-2);
|
commonRepository.SetPriority(-2);
|
||||||
RepositoryBuilder(homeRepository, "home")
|
RepositoryBuilder(homeRepository, "home")
|
||||||
.AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME, "home")
|
.AddPackages(B_PACKAGE_INSTALLATION_LOCATION_HOME, "home")
|
||||||
.AddToSolver(solver, true);
|
.AddToSolver(solver, true);
|
||||||
|
|
||||||
|
if (!installedRepositories.AddItem(&homeRepository))
|
||||||
|
DIE(B_NO_MEMORY, "failed to add home repository to list");
|
||||||
}
|
}
|
||||||
|
|
||||||
// other repositories
|
// other repositories
|
||||||
BObjectList<BSolverRepository> otherRepositories(10, true);
|
BObjectList<Repository> otherRepositories(10, true);
|
||||||
BPackageRoster roster;
|
BPackageRoster roster;
|
||||||
BStringList repositoryNames;
|
BStringList repositoryNames;
|
||||||
error = roster.GetRepositoryNames(repositoryNames);
|
error = roster.GetRepositoryNames(repositoryNames);
|
||||||
@ -139,20 +176,20 @@ InstallCommand::Execute(int argc, const char* const* argv)
|
|||||||
|
|
||||||
int32 repositoryNameCount = repositoryNames.CountStrings();
|
int32 repositoryNameCount = repositoryNames.CountStrings();
|
||||||
for (int32 i = 0; i < repositoryNameCount; i++) {
|
for (int32 i = 0; i < repositoryNameCount; i++) {
|
||||||
const BString& name = repositoryNames.StringAt(i);
|
Repository* repository = new(std::nothrow) Repository;
|
||||||
BRepositoryConfig config;
|
|
||||||
error = roster.GetRepositoryConfig(name, &config);
|
|
||||||
if (error != B_OK) {
|
|
||||||
WARN(error, "failed to get config for repository \"%s\". Skipping.",
|
|
||||||
name.String());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BSolverRepository* repository = new(std::nothrow) BSolverRepository;
|
|
||||||
if (repository == NULL || !otherRepositories.AddItem(repository))
|
if (repository == NULL || !otherRepositories.AddItem(repository))
|
||||||
DIE(B_NO_MEMORY, "out of memory");
|
DIE(B_NO_MEMORY, "out of memory");
|
||||||
|
|
||||||
RepositoryBuilder(*repository, config)
|
const BString& name = repositoryNames.StringAt(i);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
RepositoryBuilder(*repository, repository->Config())
|
||||||
.AddToSolver(solver, false);
|
.AddToSolver(solver, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,22 +242,124 @@ exit(1);
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
DIE(error, "failed to compute packages to install");
|
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);
|
for (int32 i = 0; const BSolverResultElement* element = result.ElementAt(i);
|
||||||
i++) {
|
i++) {
|
||||||
BSolverPackage* package = element->Package();
|
BSolverPackage* package = element->Package();
|
||||||
|
|
||||||
switch (element->Type()) {
|
switch (element->Type()) {
|
||||||
case BSolverResultElement::B_TYPE_INSTALL:
|
case BSolverResultElement::B_TYPE_INSTALL:
|
||||||
|
if (installedRepositories.HasItem(package->Repository()))
|
||||||
|
continue;
|
||||||
|
|
||||||
printf(" install package %s from repository %s\n",
|
printf(" install package %s from repository %s\n",
|
||||||
package->VersionedName().String(),
|
package->Info().CanonicalFileName().String(),
|
||||||
package->Repository()->Name().String());
|
package->Repository()->Name().String());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BSolverResultElement::B_TYPE_UNINSTALL:
|
case BSolverResultElement::B_TYPE_UNINSTALL:
|
||||||
printf(" uninstall package %s\n",
|
printf(" uninstall package %s\n",
|
||||||
package->VersionedName().String());
|
package->VersionedName().String());
|
||||||
break;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user