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; }
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); } } }
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); }
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()); } } } }
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; }
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; }
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"); } }
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; }