status_t
BRefreshRepositoryRequest::_FetchRepositoryCache()
{
	// download repository cache and put it in either the common/user cache
	// path, depending on where the corresponding repo-config lives

	// job fetching the cache
	BEntry tempRepoCache;
	status_t result = fContext.GetNewTempfile("repocache-", &tempRepoCache);
	if (result != B_OK)
		return result;
	BString repoCacheURL = BString(fRepoConfig.BaseURL()) << "/" << "repo";
	FetchFileJob* fetchCacheJob = new (std::nothrow) FetchFileJob(fContext,
		BString("Fetching repository-cache from ") << fRepoConfig.BaseURL(),
		repoCacheURL, tempRepoCache);
	if (fetchCacheJob == NULL)
		return B_NO_MEMORY;
	if ((result = QueueJob(fetchCacheJob)) != B_OK) {
		delete fetchCacheJob;
		return result;
	}

	// job validating the cache's checksum
	ValidateChecksumJob* validateChecksumJob
		= new (std::nothrow) ValidateChecksumJob(fContext,
			BString("Validating checksum for ") << fRepoConfig.Name(),
			new (std::nothrow) ChecksumFileChecksumAccessor(
				fFetchedChecksumFile),
			new (std::nothrow) GeneralFileChecksumAccessor(tempRepoCache));
	if (validateChecksumJob == NULL)
		return B_NO_MEMORY;
	validateChecksumJob->AddDependency(fetchCacheJob);
	if ((result = QueueJob(validateChecksumJob)) != B_OK) {
		delete validateChecksumJob;
		return result;
	}

	// job activating the cache
	BPath targetRepoCachePath;
	BPackageRoster roster;
	result = fRepoConfig.IsUserSpecific()
		? roster.GetUserRepositoryCachePath(&targetRepoCachePath, true)
		: roster.GetCommonRepositoryCachePath(&targetRepoCachePath, true);
	if (result != B_OK)
		return result;
	BDirectory targetDirectory(targetRepoCachePath.Path());
	ActivateRepositoryCacheJob* activateJob
		= new (std::nothrow) ActivateRepositoryCacheJob(fContext,
			BString("Activating repository cache for ") << fRepoConfig.Name(),
			tempRepoCache, fRepoConfig.Name(), targetDirectory);
	if (activateJob == NULL)
		return B_NO_MEMORY;
	activateJob->AddDependency(validateChecksumJob);
	if ((result = QueueJob(activateJob)) != B_OK) {
		delete activateJob;
		return result;
	}

	return B_OK;
}
Beispiel #2
0
status_t
BSolverRepository::SetTo(const BRepositoryConfig& config)
{
	Unset();

	if (config.InitCheck() != B_OK)
		return B_BAD_VALUE;

	fName = config.Name();
	fPriority = config.Priority();

	BPackageRoster roster;
	BRepositoryCache cache;
	status_t error = roster.GetRepositoryCache(config.Name(), &cache);
	if (error != B_OK) {
		Unset();
		return error;
	}

	BRepositoryCache::Iterator it = cache.GetIterator();
	while (const BPackageInfo* packageInfo = it.Next()) {
		error = AddPackage(*packageInfo);
		if (error != B_OK) {
			Unset();
			return error;
		}
	}

	return B_OK;
}
status_t
RemoveRepositoryJob::Execute()
{
	BPackageRoster roster;
	BRepositoryConfig repoConfig;
	status_t result = roster.GetRepositoryConfig(fRepositoryName, &repoConfig);
	if (result != B_OK) {
		if (result == B_ENTRY_NOT_FOUND) {
			BString error = BString("repository '") << fRepositoryName
				<< "' not found!";
			SetErrorString(error);
		}
		return result;
	}

	BString question = BString("Really remove the repository '")
		<< fRepositoryName << "'?";
	bool yes = fContext.DecisionProvider().YesNoDecisionNeeded("", question,
		"yes", "no", "no");
	if (!yes)
		return B_CANCELED;

	BEntry repoConfigEntry = repoConfig.Entry();
	if ((result = repoConfigEntry.Remove()) != B_OK)
		return result;

	BRepositoryCache repoCache;
	if (roster.GetRepositoryCache(fRepositoryName, &repoCache) == B_OK) {
		BEntry repoCacheEntry = repoCache.Entry();
		if ((result = repoCacheEntry.Remove()) != B_OK)
			return result;
	}

	return B_OK;
}
void
BPackageManager::Init(uint32 flags)
{
	if (fSolver != NULL)
		return;

	// create the solver
	status_t error = BSolver::Create(fSolver);
	if (error != B_OK)
		DIE(error, "failed to create solver");

	if (fSystemRepository == NULL || fHomeRepository == NULL
		|| fLocalRepository == NULL) {
		throw std::bad_alloc();
	}

	fSolver->SetDebugLevel(fDebugLevel);

	BRepositoryBuilder(*fLocalRepository).AddToSolver(fSolver, false);

	// add installation location repositories
	if ((flags & B_ADD_INSTALLED_REPOSITORIES) != 0) {
		// We add only the repository of our actual installation location as the
		// "installed" repository. The repositories for the more general
		// installation locations are added as regular repositories, but with
		// better priorities than the actual (remote) repositories. This
		// prevents the solver from showing conflicts when a package in a more
		// specific installation location overrides a package in a more general
		// one. Instead any requirement that is already installed in a more
		// general installation location will turn up as to be installed as
		// well. But we can easily filter those out.
		_AddInstalledRepository(fSystemRepository);

		if (!fSystemRepository->IsInstalled())
			_AddInstalledRepository(fHomeRepository);
	}

	// add other repositories
	if ((flags & B_ADD_REMOTE_REPOSITORIES) != 0) {
		BPackageRoster roster;
		BStringList repositoryNames;
		error = roster.GetRepositoryNames(repositoryNames);
		if (error != B_OK) {
			fUserInteractionHandler->Warn(error,
				"failed to get repository names");
		}

		int32 repositoryNameCount = repositoryNames.CountStrings();
		for (int32 i = 0; i < repositoryNameCount; i++) {
			_AddRemoteRepository(roster, repositoryNames.StringAt(i),
				(flags & B_REFRESH_REPOSITORIES) != 0);
		}
	}
}
Beispiel #5
0
static void add_installed_packages(Repo *repo, Repodata *repoData,
  BPackageInstallationLocation location)
{
  BPackageRoster roster;
  BPackageInfoSet packageInfos;
  if (roster.GetActivePackages(location, packageInfos) == B_OK)
    {
      BRepositoryCache::Iterator it = packageInfos.GetIterator();
      while (const BPackageInfo *packageInfo = it.Next())
        add_package_info_to_repo(repo, repoData, *packageInfo);
    }
}
status_t
BRefreshRepositoryRequest::CreateInitialJobs()
{
	status_t result = InitCheck();
	if (result != B_OK)
		return B_NO_INIT;

	if ((result = fRepoConfig.InitCheck()) != B_OK)
		return result;

	// fetch the current checksum and compare with our cache's checksum,
	// if they differ, fetch the updated cache
	result = fContext.GetNewTempfile("repochecksum-", &fFetchedChecksumFile);
	if (result != B_OK)
		return result;
	BString repoChecksumURL
		= BString(fRepoConfig.BaseURL()) << "/" << "repo.sha256";
	FetchFileJob* fetchChecksumJob = new (std::nothrow) FetchFileJob(
		fContext,
		BString("Fetching repository checksum from ") << fRepoConfig.BaseURL(),
		repoChecksumURL, fFetchedChecksumFile);
	if (fetchChecksumJob == NULL)
		return B_NO_MEMORY;
	if ((result = QueueJob(fetchChecksumJob)) != B_OK) {
		delete fetchChecksumJob;
		return result;
	}

	BRepositoryCache repoCache;
	BPackageRoster roster;
	roster.GetRepositoryCache(fRepoConfig.Name(), &repoCache);

	ValidateChecksumJob* validateChecksumJob
		= new (std::nothrow) ValidateChecksumJob(fContext,
			BString("Validating checksum for ") << fRepoConfig.Name(),
			new (std::nothrow) ChecksumFileChecksumAccessor(
				fFetchedChecksumFile),
			new (std::nothrow) GeneralFileChecksumAccessor(repoCache.Entry(),
				true),
			false);
	if (validateChecksumJob == NULL)
		return B_NO_MEMORY;
	validateChecksumJob->AddDependency(fetchChecksumJob);
	if ((result = QueueJob(validateChecksumJob)) != B_OK) {
		delete validateChecksumJob;
		return result;
	}
	fValidateChecksumJob = validateChecksumJob;

	return B_OK;
}
status_t
BPackageManager::_GetRepositoryCache(BPackageRoster& roster,
	const BRepositoryConfig& config, bool refresh, BRepositoryCache& _cache)
{
	if (!refresh && roster.GetRepositoryCache(config.Name(), &_cache) == B_OK)
		return B_OK;

	status_t error = RefreshRepository(config);
	if (error != B_OK) {
		fUserInteractionHandler->Warn(error,
			"refreshing repository \"%s\" failed", config.Name().String());
	}

	return roster.GetRepositoryCache(config.Name(), &_cache);
}
void
BPackageManager::_AddRemoteRepository(BPackageRoster& roster, const char* name,
	bool refresh)
{
	BRepositoryConfig config;
	status_t error = roster.GetRepositoryConfig(name, &config);
	if (error != B_OK) {
		fUserInteractionHandler->Warn(error,
			"failed to get config for repository \"%s\". Skipping.", name);
		return;
	}

	BRepositoryCache cache;
	error = _GetRepositoryCache(roster, config, refresh, cache);
	if (error != B_OK) {
		fUserInteractionHandler->Warn(error,
			"failed to get cache for repository \"%s\". Skipping.", name);
		return;
	}

	RemoteRepository* repository = new RemoteRepository(config);
	if (!fOtherRepositories.AddItem(repository)) {
		delete repository;
		throw std::bad_alloc();
	}

	BRepositoryBuilder(*repository, cache, config.Name())
		.AddToSolver(fSolver, false);
}
Beispiel #9
0
void
MainWindow::_RefreshRepositories(bool force)
{
	if (fSinglePackageMode)
		return;

	BPackageRoster roster;
	BStringList repositoryNames;

	status_t result = roster.GetRepositoryNames(repositoryNames);
	if (result != B_OK)
		return;

	DecisionProvider decisionProvider;
	JobStateListener listener;
	BContext context(decisionProvider, listener);

	BRepositoryCache cache;
	for (int32 i = 0; i < repositoryNames.CountStrings(); ++i) {
		const BString& repoName = repositoryNames.StringAt(i);
		BRepositoryConfig repoConfig;
		result = roster.GetRepositoryConfig(repoName, &repoConfig);
		if (result != B_OK) {
			// TODO: notify user
			continue;
		}

		if (roster.GetRepositoryCache(repoName, &cache) != B_OK || force) {
			try {
				BRefreshRepositoryRequest refreshRequest(context, repoConfig);

				result = refreshRequest.Process();
			} catch (BFatalErrorException ex) {
				BString message(B_TRANSLATE("An error occurred while "
					"refreshing the repository: %error% (%details%)"));
 				message.ReplaceFirst("%error%", ex.Message());
				message.ReplaceFirst("%details%", ex.Details());
				_NotifyUser("Error", message.String());
			} catch (BException ex) {
				BString message(B_TRANSLATE("An error occurred while "
					"refreshing the repository: %error%"));
				message.ReplaceFirst("%error%", ex.Message());
				_NotifyUser("Error", message.String());
			}
		}
	}
}
Beispiel #10
0
status_t
BSolverRepository::AddPackages(BPackageInstallationLocation location)
{
	BPackageRoster roster;
	BPackageInfoSet packageInfos;
	status_t error = roster.GetActivePackages(location, packageInfos);
	if (error != B_OK)
		return error;

	BRepositoryCache::Iterator it = packageInfos.GetIterator();
	while (const BPackageInfo* packageInfo = it.Next()) {
		error = AddPackage(*packageInfo);
		if (error != B_OK)
			return error;
	}

	return B_OK;
}
Beispiel #11
0
int repo_add_haiku_packages(Repo *repo, const char *repoName, int flags)
{
  BPackageRoster roster;
  BRepositoryCache cache;
  if (roster.GetRepositoryCache(repoName, &cache) != B_OK)
    return 0;

  Repodata *repoData = repo_add_repodata(repo, flags);

  BRepositoryCache::Iterator it = cache.GetIterator();
  while (const BPackageInfo *packageInfo = it.Next())
    add_package_info_to_repo(repo, repoData, *packageInfo);

  if (!(flags & REPO_NO_INTERNALIZE))
    repodata_internalize(repoData);

  return 0;
}
Beispiel #12
0
void
MainWindow::_RefreshPackageList()
{
	BPackageRoster roster;
	BStringList repositoryNames;

	status_t result = roster.GetRepositoryNames(repositoryNames);
	if (result != B_OK)
		return;

	DepotInfoMap depots;
	for (int32 i = 0; i < repositoryNames.CountStrings(); i++) {
		const BString& repoName = repositoryNames.StringAt(i);
		depots[repoName] = DepotInfo(repoName);
	}

	PackageManager manager(B_PACKAGE_INSTALLATION_LOCATION_HOME);
	try {
		manager.Init(PackageManager::B_ADD_INSTALLED_REPOSITORIES
			| PackageManager::B_ADD_REMOTE_REPOSITORIES);
	} catch (BException ex) {
		BString message(B_TRANSLATE("An error occurred while "
			"initializing the package manager: %message%"));
		message.ReplaceFirst("%message%", ex.Message());
		_NotifyUser("Error", message.String());
		return;
	}

	BObjectList<BSolverPackage> packages;
	result = manager.Solver()->FindPackages("",
		BSolver::B_FIND_CASE_INSENSITIVE | BSolver::B_FIND_IN_NAME
			| BSolver::B_FIND_IN_SUMMARY | BSolver::B_FIND_IN_DESCRIPTION
			| BSolver::B_FIND_IN_PROVIDES,
		packages);
	if (result != B_OK) {
		// TODO: notify user
		return;
	}

	if (packages.IsEmpty())
		return;

	PackageInfoMap foundPackages;
		// if a given package is installed locally, we will potentially
		// get back multiple entries, one for each local installation
		// location, and one for each remote repository the package
		// is available in. The above map is used to ensure that in such
		// cases we consolidate the information, rather than displaying
		// duplicates
	PackageInfoMap remotePackages;
		// any package that we find in a remote repository goes in this map.
		// this is later used to discern which packages came from a local
		// installation only, as those must be handled a bit differently
		// upon uninstallation, since we'd no longer be able to pull them
		// down remotely.
	BStringList systemFlaggedPackages;
		// any packages flagged as a system package are added to this list.
		// such packages cannot be uninstalled, nor can any of their deps.
	PackageInfoMap systemInstalledPackages;
		// any packages installed in system are added to this list.
		// This is later used for dependency resolution of the actual
		// system packages in order to compute the list of protected
		// dependencies indicated above.

	BitmapRef defaultIcon(new(std::nothrow) SharedBitmap(
		"application/x-vnd.haiku-package"), true);

	for (int32 i = 0; i < packages.CountItems(); i++) {
		BSolverPackage* package = packages.ItemAt(i);
		const BPackageInfo& repoPackageInfo = package->Info();
		PackageInfoRef modelInfo;
		PackageInfoMap::iterator it = foundPackages.find(
			repoPackageInfo.Name());
		if (it != foundPackages.end())
			modelInfo.SetTo(it->second);
		else {
			// Add new package info
			BString publisherURL;
			if (repoPackageInfo.URLList().CountStrings() > 0)
				publisherURL = repoPackageInfo.URLList().StringAt(0);

			BString publisherName = repoPackageInfo.Vendor();
			const BStringList& rightsList = repoPackageInfo.CopyrightList();
			if (rightsList.CountStrings() > 0)
				publisherName = rightsList.StringAt(0);

			modelInfo.SetTo(new(std::nothrow) PackageInfo(
					repoPackageInfo.Name(),
					repoPackageInfo.Version().ToString(),
					PublisherInfo(BitmapRef(), publisherName,
					"", publisherURL), repoPackageInfo.Summary(),
					repoPackageInfo.Description(),
					repoPackageInfo.Flags()),
				true);

			if (modelInfo.Get() == NULL)
				return;

			foundPackages[repoPackageInfo.Name()] = modelInfo;
		}

		modelInfo->SetIcon(defaultIcon);
		modelInfo->AddListener(this);

		BSolverRepository* repository = package->Repository();
		if (dynamic_cast<BPackageManager::RemoteRepository*>(repository)
				!= NULL) {
			depots[repository->Name()].AddPackage(modelInfo);
			remotePackages[modelInfo->Title()] = modelInfo;
		} else {
			if (repository == static_cast<const BSolverRepository*>(
					manager.SystemRepository())) {
				modelInfo->AddInstallationLocation(
					B_PACKAGE_INSTALLATION_LOCATION_SYSTEM);
				if (!modelInfo->IsSystemPackage()) {
					systemInstalledPackages[repoPackageInfo.FileName()]
						= modelInfo;
				}
			} else if (repository == static_cast<const BSolverRepository*>(
					manager.HomeRepository())) {
				modelInfo->AddInstallationLocation(
					B_PACKAGE_INSTALLATION_LOCATION_HOME);
			}
		}

		if (modelInfo->IsSystemPackage())
			systemFlaggedPackages.Add(repoPackageInfo.FileName());
	}

	BAutolock lock(fModel.Lock());

	fModel.Clear();

	// filter remote packages from the found list
	// any packages remaining will be locally installed packages
	// that weren't acquired from a repository
	for (PackageInfoMap::iterator it = remotePackages.begin();
			it != remotePackages.end(); it++) {
		foundPackages.erase(it->first);
	}

	if (!foundPackages.empty()) {
		BString repoName = B_TRANSLATE("Local");
		depots[repoName] = DepotInfo(repoName);
		DepotInfoMap::iterator depot = depots.find(repoName);
		for (PackageInfoMap::iterator it = foundPackages.begin();
				it != foundPackages.end(); ++it) {
			depot->second.AddPackage(it->second);
		}
	}

	for (DepotInfoMap::iterator it = depots.begin(); it != depots.end(); it++) {
		fModel.AddDepot(it->second);
	}

	// start retrieving package icons and average ratings
	fModel.PopulateAllPackages();

	// compute the OS package dependencies
	try {
		// create the solver
		BSolver* solver;
		status_t error = BSolver::Create(solver);
		if (error != B_OK)
			throw BFatalErrorException(error, "Failed to create solver.");

		ObjectDeleter<BSolver> solverDeleter(solver);
		BPath systemPath;
		error = find_directory(B_SYSTEM_PACKAGES_DIRECTORY, &systemPath);
		if (error != B_OK) {
			throw BFatalErrorException(error,
				"Unable to retrieve system packages directory.");
		}

		// add the "installed" repository with the given packages
		BSolverRepository installedRepository;
		{
			BRepositoryBuilder installedRepositoryBuilder(installedRepository,
				"installed");
			for (int32 i = 0; i < systemFlaggedPackages.CountStrings(); i++) {
				BPath packagePath(systemPath);
				packagePath.Append(systemFlaggedPackages.StringAt(i));
				installedRepositoryBuilder.AddPackage(packagePath.Path());
			}
			installedRepositoryBuilder.AddToSolver(solver, true);
		}

		// add system repository
		BSolverRepository systemRepository;
		{
			BRepositoryBuilder systemRepositoryBuilder(systemRepository,
				"system");
			for (PackageInfoMap::iterator it = systemInstalledPackages.begin();
					it != systemInstalledPackages.end(); it++) {
				BPath packagePath(systemPath);
				packagePath.Append(it->first);
				systemRepositoryBuilder.AddPackage(packagePath.Path());
			}
			systemRepositoryBuilder.AddToSolver(solver, false);
		}

		// solve
		error = solver->VerifyInstallation();
		if (error != B_OK) {
			throw BFatalErrorException(error, "Failed to compute packages to "
				"install.");
		}

		BSolverResult solverResult;
		error = solver->GetResult(solverResult);
		if (error != B_OK) {
			throw BFatalErrorException(error, "Failed to retrieve system "
				"package dependency list.");
		}

		for (int32 i = 0; const BSolverResultElement* element
				= solverResult.ElementAt(i); i++) {
			BSolverPackage* package = element->Package();
			if (element->Type() == BSolverResultElement::B_TYPE_INSTALL) {
				PackageInfoMap::iterator it = systemInstalledPackages.find(
					package->Info().FileName());
				if (it != systemInstalledPackages.end())
					it->second->SetSystemDependency(true);
			}
		}
	} catch (BFatalErrorException ex) {
		printf("Fatal exception occurred while resolving system dependencies: "
			"%s, details: %s\n", strerror(ex.Error()), ex.Details().String());
	} catch (BNothingToDoException) {
		// do nothing
	} catch (BException ex) {
		printf("Exception occurred while resolving system dependencies: %s\n",
			ex.Message().String());
	} catch (...) {
		printf("Unknown exception occurred while resolving system "
			"dependencies.\n");
	}
}
Beispiel #13
0
int
ListReposCommand::Execute(int argc, const char* const* argv)
{
	bool verbose = false;

	while (true) {
		static struct option sLongOptions[] = {
			{ "help", no_argument, 0, 'h' },
			{ "verbose", no_argument, 0, 'v' },
			{ 0, 0, 0, 0 }
		};

		opterr = 0; // don't print errors
		int c = getopt_long(argc, (char**)argv, "hv", sLongOptions, NULL);
		if (c == -1)
			break;

		switch (c) {
			case 'h':
				PrintUsageAndExit(false);
				break;

			case 'v':
				verbose = true;
				break;

			default:
				PrintUsageAndExit(true);
				break;
		}
	}

	// No remaining arguments.
	if (argc != optind)
		PrintUsageAndExit(true);

	BStringList repositoryNames(20);
	BPackageRoster roster;
	status_t result = roster.GetRepositoryNames(repositoryNames);
	if (result != B_OK)
		DIE(result, "can't collect repository names");

	for (int i = 0; i < repositoryNames.CountStrings(); ++i) {
		const BString& repoName = repositoryNames.StringAt(i);
		BRepositoryConfig repoConfig;
		result = roster.GetRepositoryConfig(repoName, &repoConfig);
		if (result != B_OK) {
			BPath path;
			repoConfig.Entry().GetPath(&path);
			WARN(result, "skipping repository-config '%s'", path.Path());
			continue;
		}
		if (verbose && i > 0)
			printf("\n");
		printf(" %s %s\n",
			repoConfig.IsUserSpecific() ? "[User]" : "      ",
			repoConfig.Name().String());
		printf("\t\tbase-url:  %s\n", repoConfig.BaseURL().String());
		printf("\t\tpriority:  %u\n", repoConfig.Priority());

		if (verbose) {
			BRepositoryCache repoCache;
			result = roster.GetRepositoryCache(repoName, &repoCache);
			if (result == B_OK) {
				printf("\t\tvendor:    %s\n",
					repoCache.Info().Vendor().String());
				printf("\t\tsummary:   %s\n",
					repoCache.Info().Summary().String());
				printf("\t\tarch:      %s\n", BPackageInfo::kArchitectureNames[
						repoCache.Info().Architecture()]);
				printf("\t\tpkg-count: %" B_PRIu32 "\n",
					repoCache.CountPackages());
				printf("\t\torig-url:  %s\n",
					repoCache.Info().OriginalBaseURL().String());
				printf("\t\torig-prio: %u\n", repoCache.Info().Priority());
			} else
				printf("\t\t<no repository cache found>\n");
		}
	}

	return 0;
}